Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

563 lines
15 KiB

/*++
Microsoft Windows
Copyright (C) Microsoft Corporation, 1981 - 1999
Module Name:
controller.cpp
Abstract:
Author:
Rahul Thombre (RahulTh) 4/30/1998
Revision History:
4/30/1998 RahulTh
Created this module.
--*/
// Controller.cpp : implementation file
//
#include "precomp.hxx"
#include <wtsapi32.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define DEFAULT_TIMEOUT 30000 //30 seconds.
#define TIMER_ID 7 //randomly chosen id for the timer
///////////////////
// Module wide structure.
//
FLASHWINFO fwinfo = {
sizeof (FLASHWINFO),
NULL, // Window handle initialized later.
FLASHW_ALL,
3,
0
};
/////////////////////////////////////////////////////////////////////////////
//type for loading CPlApplet function declaration: declared in irprops.cpl
typedef LONG (*LPROCCPLAPPLET) (HWND , UINT , LPARAM, LPARAM);
inline CIrRecvProgress *
ValidateRecvCookie( COOKIE cookie)
{
CIrRecvProgress * window = (CIrRecvProgress *) cookie;
__try
{
if (RECV_MAGIC_ID != window->m_dwMagicID)
{
window = 0;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
window = 0;
}
return window;
}
/////////////////////////////////////////////////////////////////////////////
// CController dialog
//bNoForeground specifies whether the dialog should give focus back to the
//app. which had the focus before irftp started. If set to true, the focus
//is given back. This is necessary because an irftp is usually started with
//the /h option by the irmon service and it is a bad user experience if the
//an app. which the user is running suddenly loses focus to a window which
//is not even visible.
CController::CController(BOOL bNoForeground, CController* pParent /*=NULL*/) : m_pParent(pParent), m_lAppIsDisplayed(-1),m_SessionEnded(0)
#if 0
, m_pDlgRecvProgress(NULL)
#endif
{
m_fHaveTimer = FALSE;
m_lTimeout = DEFAULT_TIMEOUT;
HWND hwnd = NULL;
InterlockedIncrement (&g_lUIComponentCount);
if (appController)
{
appController->PostMessage (WM_APP_KILL_TIMER);
}
else
{
InitTimeout(); //initializes the timeout period
//the app kills itself if there are no devices in range and no UI has
// been put up for a period specified by the timeout period
//note: we only need to initialize the timeout period for the main
//app window. The other windows will never even have a timer.
WTSRegisterSessionNotification(m_hWnd,NOTIFY_FOR_THIS_SESSION);
}
//hack. the call to create steals the focus from the current
//foreground window. This is bad if we are not going to put up any
//UI. Therefore, in this case, we get the foreground window just before the
//call to create and give it back its focus immediately after the call.
//the whole operation takes only about 35 milliseconds, so the loss of
//focus in the other app. is almost imperceptible.
hwnd = ::GetForegroundWindow ();
Create(IDD);
if (bNoForeground && hwnd)
::SetForegroundWindow (hwnd);
//{{AFX_DATA_INIT(CController)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CController::InitTimeout (void)
{
m_fHaveTimer = FALSE; //we have not obtained a timer yet.
m_lTimeout = DEFAULT_TIMEOUT; //set it to the default
//then see if a different value has been set in the registry
HKEY hftKey = NULL;
DWORD iSize = sizeof(DWORD);
DWORD data = 0;
RegOpenKeyEx (HKEY_CURRENT_USER,
TEXT("Control Panel\\Infrared\\File Transfer"),
0, KEY_READ, &hftKey);
if (!hftKey)
return; //we did not find a value in the registry, so use defaults
if (hftKey && ERROR_SUCCESS ==
RegQueryValueEx (hftKey, TEXT("AppTimeout"), NULL, NULL,
(LPBYTE)&data, &iSize))
{
m_lTimeout = (LONG)data;
if (m_lTimeout < 10000)
m_lTimeout = 10000;
}
if (hftKey)
RegCloseKey(hftKey);
}
void CController::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CController)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CController, CDialog)
//{{AFX_MSG_MAP(CController)
ON_WM_CLOSE()
ON_WM_ENDSESSION()
ON_MESSAGE(WM_WTSSESSION_CHANGE, OnSessionChange)
ON_MESSAGE(WM_APP_TRIGGER_UI, OnTriggerUI)
ON_MESSAGE(WM_APP_DISPLAY_UI, OnDisplayUI)
ON_MESSAGE(WM_APP_TRIGGER_SETTINGS, OnTriggerSettings)
ON_MESSAGE(WM_APP_DISPLAY_SETTINGS, OnDisplaySettings)
ON_MESSAGE(WM_APP_RECV_IN_PROGRESS, OnRecvInProgress)
ON_MESSAGE(WM_APP_GET_PERMISSION, OnGetPermission)
ON_MESSAGE(WM_APP_RECV_FINISHED, OnRecvFinished)
ON_MESSAGE(WM_APP_START_TIMER, OnStartTimer)
ON_MESSAGE(WM_APP_KILL_TIMER, OnKillTimer)
ON_WM_COPYDATA()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CController message handlers
void CController::PostNcDestroy()
{
#if 0
OutputDebugStringA("PostNcDestroy");
#endif
if (this != appController)
{
BOOL fNoUIComponents = (0 == InterlockedDecrement (&g_lUIComponentCount));
if (fNoUIComponents && !g_deviceList.GetDeviceCount())
{
//there are no UI components displayed and there are no devices in
//range. Start the timer. If the timer expires, the app. will quit.
appController->PostMessage (WM_APP_START_TIMER);
}
if (m_SessionEnded) {
appController->PostMessage (WM_CLOSE);
}
}
delete this;
}
void CController::OnEndSession(BOOL Ending)
{
// OutputDebugStringA("OnEndSession\n");
RemoveLinks();
}
void CController::OnClose()
{
//if the WM_CLOSE message was posted from the RPC thread's ShutdownUi
//routine, then it might be a good idea to wait for a couple of seconds
//before killing the app. so that the RPC stack can unwind. 3 seconds seems
//like a reasonable amount of time. - 6/22/1998 : rahulth & jroberts
#if 0
OutputDebugStringA("OnClose\n");
#endif
RemoveLinks();
Sleep (3000);
if (AppUI.m_pParentWnd)
AppUI.m_pParentWnd->PostMessage(WM_QUIT);
CWnd::OnClose();
}
void CController::OnCancel()
{
DestroyWindow(); //For modeless boxes
}
void CController::OnDisplayUI(WPARAM wParam, LPARAM lParam)
{
ASSERT (m_pParent);
AppUI.m_ofn.hInstance = g_hInstance;
AppUI.DoModal();
AppUI.m_pParentWnd = NULL;
InterlockedDecrement(&m_lAppIsDisplayed);
InterlockedDecrement(&(m_pParent->m_lAppIsDisplayed));
DestroyWindow();
}
void CController::OnTriggerUI (WPARAM wParam, LPARAM lParam)
{
CWnd * pWnd = NULL;
BOOL fAppIsDisplayed = (0 != InterlockedIncrement(&m_lAppIsDisplayed));
if (fAppIsDisplayed)
{
InterlockedDecrement(&m_lAppIsDisplayed); //decrement the count before leaving.
pWnd = AppUI.m_pParentWnd;
if (NULL != pWnd)
{
//this will usually be true except in the case where the displayed
//window is just getting destroyed at the same time. In that case,
//we must go ahead and create it again.
pWnd->SetActiveWindow();
return;
}
}
//the app is not displayed
CController* dlgSubController = new CController(FALSE, this);
if (dlgSubController != NULL) {
InterlockedIncrement(&(dlgSubController->m_lAppIsDisplayed));
dlgSubController->ShowWindow (SW_HIDE);
dlgSubController->PostMessage(WM_APP_DISPLAY_UI);
}
}
void CController::OnTriggerSettings(WPARAM wParam, LPARAM lParam)
{
CController* dlgSettingsController = new CController(FALSE, this);
if (dlgSettingsController != NULL) {
dlgSettingsController->ShowWindow(SW_HIDE);
dlgSettingsController->PostMessage(WM_APP_DISPLAY_SETTINGS);
}
}
void CController::OnDisplaySettings(WPARAM wParam, LPARAM lParam)
{
LPROCCPLAPPLET pProcApplet = NULL;
CString szApplet;
CError error (this);
PROCESS_INFORMATION ProcessInformation;
STARTUPINFO StartupInfo;
BOOL bResult;
UINT DirPathLength;
TCHAR Path[MAX_PATH*2];
TCHAR CommandLine[]=TEXT("rundll32.exe shell32.dll,Control_RunDLL irprops.cpl ");
ZeroMemory(&StartupInfo,sizeof(StartupInfo));
StartupInfo.cb=sizeof(StartupInfo);
DirPathLength=GetSystemDirectory(
Path,
sizeof(Path)/sizeof(TCHAR)
);
if (DirPathLength != 0) {
StringCbCat(Path,sizeof(Path),TEXT("\\rundll32.exe"));
bResult=CreateProcess(
Path,
CommandLine,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&StartupInfo,
&ProcessInformation
);
if (bResult) {
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
} else {
error.ShowMessage (IDS_APPLET_ERROR);
}
} else {
error.ShowMessage (IDS_APPLET_ERROR);
}
DestroyWindow();
}
void CController::OnRecvInProgress (WPARAM wParam, LPARAM lParam)
{
DWORD dwShowRecv;
struct MSG_RECEIVE_IN_PROGRESS * msg = (struct MSG_RECEIVE_IN_PROGRESS *) wParam;
dwShowRecv = GetIRRegVal (TEXT("ShowRecvStatus"), 1);
if (!dwShowRecv) {
msg->status = 0;
return;
}
if (wcslen(msg->MachineName) > IRDA_DEVICE_NAME_LENGTH) {
msg->status = ERROR_INVALID_PARAMETER;
return;
}
CIrRecvProgress * pDlgRecvProgress = new CIrRecvProgress(msg->MachineName,
msg->bSuppressRecvConf);
if (!pDlgRecvProgress) {
msg->status = ERROR_NOT_ENOUGH_MEMORY;
return;
}
SetForegroundWindow();
pDlgRecvProgress->SetActiveWindow();
pDlgRecvProgress->SetWindowPos(&appController->wndTop, -1, -1, -1, -1, SWP_NOSIZE | SWP_NOMOVE);
fwinfo.hwnd = pDlgRecvProgress->m_hWnd;
FlashWindowEx (&fwinfo);
*(msg->pCookie) = (COOKIE) pDlgRecvProgress;
msg->status = 0;
}
void CController::OnGetPermission( WPARAM wParam, LPARAM lParam )
{
DWORD dwShowRecv;
struct MSG_GET_PERMISSION * msg = (MSG_GET_PERMISSION *) wParam;
dwShowRecv = GetIRRegVal (TEXT("ShowRecvStatus"), 1);
if (!dwShowRecv) {
msg->status = 0;
return;
}
SetForegroundWindow();
CIrRecvProgress * pDlgRecvProgress = ValidateRecvCookie(msg->Cookie);
if (!pDlgRecvProgress) {
msg->status = ERROR_INVALID_PARAMETER;
return;
}
msg->status = pDlgRecvProgress->GetPermission( msg->Name, msg->fDirectory );
}
void CController::OnRecvFinished (WPARAM wParam, LPARAM lParam)
{
DWORD dwShowRecv;
struct MSG_RECEIVE_FINISHED * msg = (struct MSG_RECEIVE_FINISHED *) wParam;
dwShowRecv = GetIRRegVal (TEXT("ShowRecvStatus"), 1);
if (!dwShowRecv) {
msg->status = 0;
return;
}
CIrRecvProgress * pDlgRecvProgress = ValidateRecvCookie(msg->Cookie);
if (!pDlgRecvProgress) {
msg->status = ERROR_INVALID_PARAMETER;
return;
}
//
// Preset the error code to ERROR_SUCCESS -- no error popup
//
DWORD Win32Error = ERROR_SUCCESS;
//
// first, filter out unwarranted errors. These error codes
// are treated as ERROR_SUCCESS.
// We have three so far:
// ERROR_SCEP_UNSPECIFIED_DISCONNECT,
// ERROR_SCEP_USER_DISCONNECT and
// ERROR_SCEP_PROVIDER_DISCONNECT.
//
// ERROR_SCEP_UNSPECIFIED_DISCONNECT is the error code
// we encounter most of the time because users usually do
// (1) move the device within IR range
// (2) do image transfer
// (3) move the device out of IR range.
//
if (ERROR_SCEP_UNSPECIFIED_DISCONNECT != (DWORD)msg->ReceiveStatus &&
ERROR_SCEP_USER_DISCONNECT != (DWORD)msg->ReceiveStatus &&
ERROR_SCEP_PROVIDER_DISCONNECT != (DWORD)msg->ReceiveStatus)
{
Win32Error = (DWORD)msg->ReceiveStatus;
}
pDlgRecvProgress->DestroyAndCleanup(Win32Error);
pDlgRecvProgress = NULL;
msg->status = 0;
}
BOOL CController::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
CSendProgress* dlgProgress;
int iCharCount=(int) pCopyDataStruct->cbData;
TCHAR* lpszFileNames = new TCHAR [iCharCount];
if (lpszFileNames == NULL) {
return FALSE;
}
memcpy ((LPVOID)lpszFileNames, pCopyDataStruct->lpData, pCopyDataStruct->cbData);
dlgProgress = new CSendProgress(lpszFileNames, iCharCount);
if (dlgProgress != NULL) {
dlgProgress->ShowWindow(SW_SHOW);
dlgProgress->SetFocus();
dlgProgress->SetWindowPos (&wndTop, -1, -1, -1, -1, SWP_NOMOVE | SWP_NOSIZE);
fwinfo.hwnd = dlgProgress->m_hWnd;
::FlashWindowEx (&fwinfo);
return TRUE;
} else {
delete lpszFileNames;
return FALSE;
}
}
void CController::OnStartTimer (WPARAM wParam, LPARAM lParam)
{
//update the state of the help window
if (g_hwndHelp && ! ::IsWindow (g_hwndHelp))
g_hwndHelp = NULL;
if (!m_fHaveTimer)
{
m_fHaveTimer = SetTimer (TIMER_ID,
m_lTimeout,
NULL //want WM_TIMER messages
)?TRUE:FALSE;
}
}
void CController::OnKillTimer (WPARAM wParam, LPARAM lParam)
{
//update the state of the help window
if (g_hwndHelp && ! ::IsWindow (g_hwndHelp))
g_hwndHelp = NULL;
if (m_fHaveTimer)
{
KillTimer(TIMER_ID);
m_fHaveTimer = FALSE;
}
}
void CController::OnTimer (UINT nTimerID)
{
//there is only one timer, so we don't have to check for it.
//the timer has expired, so kill self
//however, first make sure that the help window (if it was put up)
//is gone.
if (g_hwndHelp && ::IsWindow (g_hwndHelp))
{
//the help window is around. restart the timer.
//this is the only way we can kill ourselves when the window
//is finally destroyed.
m_fHaveTimer = FALSE;
this->OnStartTimer (NULL, NULL);
}
else
{
g_hwndHelp = NULL;
this->PostMessage(WM_CLOSE);
}
}
void CController::OnSessionChange(WPARAM wParam, LPARAM lParam)
{
OutputDebugStringA("irftp: controller session changed\n");
return;
}