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

  1. /*++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1981 - 1999
  4. Module Name:
  5. controller.cpp
  6. Abstract:
  7. Author:
  8. Rahul Thombre (RahulTh) 4/30/1998
  9. Revision History:
  10. 4/30/1998 RahulTh
  11. Created this module.
  12. --*/
  13. // Controller.cpp : implementation file
  14. //
  15. #include "precomp.hxx"
  16. #include <wtsapi32.h>
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. #define DEFAULT_TIMEOUT 30000 //30 seconds.
  23. #define TIMER_ID 7 //randomly chosen id for the timer
  24. ///////////////////
  25. // Module wide structure.
  26. //
  27. FLASHWINFO fwinfo = {
  28. sizeof (FLASHWINFO),
  29. NULL, // Window handle initialized later.
  30. FLASHW_ALL,
  31. 3,
  32. 0
  33. };
  34. /////////////////////////////////////////////////////////////////////////////
  35. //type for loading CPlApplet function declaration: declared in irprops.cpl
  36. typedef LONG (*LPROCCPLAPPLET) (HWND , UINT , LPARAM, LPARAM);
  37. inline CIrRecvProgress *
  38. ValidateRecvCookie( COOKIE cookie)
  39. {
  40. CIrRecvProgress * window = (CIrRecvProgress *) cookie;
  41. __try
  42. {
  43. if (RECV_MAGIC_ID != window->m_dwMagicID)
  44. {
  45. window = 0;
  46. }
  47. }
  48. __except (EXCEPTION_EXECUTE_HANDLER)
  49. {
  50. window = 0;
  51. }
  52. return window;
  53. }
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CController dialog
  56. //bNoForeground specifies whether the dialog should give focus back to the
  57. //app. which had the focus before irftp started. If set to true, the focus
  58. //is given back. This is necessary because an irftp is usually started with
  59. //the /h option by the irmon service and it is a bad user experience if the
  60. //an app. which the user is running suddenly loses focus to a window which
  61. //is not even visible.
  62. CController::CController(BOOL bNoForeground, CController* pParent /*=NULL*/) : m_pParent(pParent), m_lAppIsDisplayed(-1),m_SessionEnded(0)
  63. #if 0
  64. , m_pDlgRecvProgress(NULL)
  65. #endif
  66. {
  67. m_fHaveTimer = FALSE;
  68. m_lTimeout = DEFAULT_TIMEOUT;
  69. HWND hwnd = NULL;
  70. InterlockedIncrement (&g_lUIComponentCount);
  71. if (appController)
  72. {
  73. appController->PostMessage (WM_APP_KILL_TIMER);
  74. }
  75. else
  76. {
  77. InitTimeout(); //initializes the timeout period
  78. //the app kills itself if there are no devices in range and no UI has
  79. // been put up for a period specified by the timeout period
  80. //note: we only need to initialize the timeout period for the main
  81. //app window. The other windows will never even have a timer.
  82. WTSRegisterSessionNotification(m_hWnd,NOTIFY_FOR_THIS_SESSION);
  83. }
  84. //hack. the call to create steals the focus from the current
  85. //foreground window. This is bad if we are not going to put up any
  86. //UI. Therefore, in this case, we get the foreground window just before the
  87. //call to create and give it back its focus immediately after the call.
  88. //the whole operation takes only about 35 milliseconds, so the loss of
  89. //focus in the other app. is almost imperceptible.
  90. hwnd = ::GetForegroundWindow ();
  91. Create(IDD);
  92. if (bNoForeground && hwnd)
  93. ::SetForegroundWindow (hwnd);
  94. //{{AFX_DATA_INIT(CController)
  95. // NOTE: the ClassWizard will add member initialization here
  96. //}}AFX_DATA_INIT
  97. }
  98. void CController::InitTimeout (void)
  99. {
  100. m_fHaveTimer = FALSE; //we have not obtained a timer yet.
  101. m_lTimeout = DEFAULT_TIMEOUT; //set it to the default
  102. //then see if a different value has been set in the registry
  103. HKEY hftKey = NULL;
  104. DWORD iSize = sizeof(DWORD);
  105. DWORD data = 0;
  106. RegOpenKeyEx (HKEY_CURRENT_USER,
  107. TEXT("Control Panel\\Infrared\\File Transfer"),
  108. 0, KEY_READ, &hftKey);
  109. if (!hftKey)
  110. return; //we did not find a value in the registry, so use defaults
  111. if (hftKey && ERROR_SUCCESS ==
  112. RegQueryValueEx (hftKey, TEXT("AppTimeout"), NULL, NULL,
  113. (LPBYTE)&data, &iSize))
  114. {
  115. m_lTimeout = (LONG)data;
  116. if (m_lTimeout < 10000)
  117. m_lTimeout = 10000;
  118. }
  119. if (hftKey)
  120. RegCloseKey(hftKey);
  121. }
  122. void CController::DoDataExchange(CDataExchange* pDX)
  123. {
  124. CDialog::DoDataExchange(pDX);
  125. //{{AFX_DATA_MAP(CController)
  126. // NOTE: the ClassWizard will add DDX and DDV calls here
  127. //}}AFX_DATA_MAP
  128. }
  129. BEGIN_MESSAGE_MAP(CController, CDialog)
  130. //{{AFX_MSG_MAP(CController)
  131. ON_WM_CLOSE()
  132. ON_WM_ENDSESSION()
  133. ON_MESSAGE(WM_WTSSESSION_CHANGE, OnSessionChange)
  134. ON_MESSAGE(WM_APP_TRIGGER_UI, OnTriggerUI)
  135. ON_MESSAGE(WM_APP_DISPLAY_UI, OnDisplayUI)
  136. ON_MESSAGE(WM_APP_TRIGGER_SETTINGS, OnTriggerSettings)
  137. ON_MESSAGE(WM_APP_DISPLAY_SETTINGS, OnDisplaySettings)
  138. ON_MESSAGE(WM_APP_RECV_IN_PROGRESS, OnRecvInProgress)
  139. ON_MESSAGE(WM_APP_GET_PERMISSION, OnGetPermission)
  140. ON_MESSAGE(WM_APP_RECV_FINISHED, OnRecvFinished)
  141. ON_MESSAGE(WM_APP_START_TIMER, OnStartTimer)
  142. ON_MESSAGE(WM_APP_KILL_TIMER, OnKillTimer)
  143. ON_WM_COPYDATA()
  144. ON_WM_TIMER()
  145. //}}AFX_MSG_MAP
  146. END_MESSAGE_MAP()
  147. /////////////////////////////////////////////////////////////////////////////
  148. // CController message handlers
  149. void CController::PostNcDestroy()
  150. {
  151. #if 0
  152. OutputDebugStringA("PostNcDestroy");
  153. #endif
  154. if (this != appController)
  155. {
  156. BOOL fNoUIComponents = (0 == InterlockedDecrement (&g_lUIComponentCount));
  157. if (fNoUIComponents && !g_deviceList.GetDeviceCount())
  158. {
  159. //there are no UI components displayed and there are no devices in
  160. //range. Start the timer. If the timer expires, the app. will quit.
  161. appController->PostMessage (WM_APP_START_TIMER);
  162. }
  163. if (m_SessionEnded) {
  164. appController->PostMessage (WM_CLOSE);
  165. }
  166. }
  167. delete this;
  168. }
  169. void CController::OnEndSession(BOOL Ending)
  170. {
  171. // OutputDebugStringA("OnEndSession\n");
  172. RemoveLinks();
  173. }
  174. void CController::OnClose()
  175. {
  176. //if the WM_CLOSE message was posted from the RPC thread's ShutdownUi
  177. //routine, then it might be a good idea to wait for a couple of seconds
  178. //before killing the app. so that the RPC stack can unwind. 3 seconds seems
  179. //like a reasonable amount of time. - 6/22/1998 : rahulth & jroberts
  180. #if 0
  181. OutputDebugStringA("OnClose\n");
  182. #endif
  183. RemoveLinks();
  184. Sleep (3000);
  185. if (AppUI.m_pParentWnd)
  186. AppUI.m_pParentWnd->PostMessage(WM_QUIT);
  187. CWnd::OnClose();
  188. }
  189. void CController::OnCancel()
  190. {
  191. DestroyWindow(); //For modeless boxes
  192. }
  193. void CController::OnDisplayUI(WPARAM wParam, LPARAM lParam)
  194. {
  195. ASSERT (m_pParent);
  196. AppUI.m_ofn.hInstance = g_hInstance;
  197. AppUI.DoModal();
  198. AppUI.m_pParentWnd = NULL;
  199. InterlockedDecrement(&m_lAppIsDisplayed);
  200. InterlockedDecrement(&(m_pParent->m_lAppIsDisplayed));
  201. DestroyWindow();
  202. }
  203. void CController::OnTriggerUI (WPARAM wParam, LPARAM lParam)
  204. {
  205. CWnd * pWnd = NULL;
  206. BOOL fAppIsDisplayed = (0 != InterlockedIncrement(&m_lAppIsDisplayed));
  207. if (fAppIsDisplayed)
  208. {
  209. InterlockedDecrement(&m_lAppIsDisplayed); //decrement the count before leaving.
  210. pWnd = AppUI.m_pParentWnd;
  211. if (NULL != pWnd)
  212. {
  213. //this will usually be true except in the case where the displayed
  214. //window is just getting destroyed at the same time. In that case,
  215. //we must go ahead and create it again.
  216. pWnd->SetActiveWindow();
  217. return;
  218. }
  219. }
  220. //the app is not displayed
  221. CController* dlgSubController = new CController(FALSE, this);
  222. if (dlgSubController != NULL) {
  223. InterlockedIncrement(&(dlgSubController->m_lAppIsDisplayed));
  224. dlgSubController->ShowWindow (SW_HIDE);
  225. dlgSubController->PostMessage(WM_APP_DISPLAY_UI);
  226. }
  227. }
  228. void CController::OnTriggerSettings(WPARAM wParam, LPARAM lParam)
  229. {
  230. CController* dlgSettingsController = new CController(FALSE, this);
  231. if (dlgSettingsController != NULL) {
  232. dlgSettingsController->ShowWindow(SW_HIDE);
  233. dlgSettingsController->PostMessage(WM_APP_DISPLAY_SETTINGS);
  234. }
  235. }
  236. void CController::OnDisplaySettings(WPARAM wParam, LPARAM lParam)
  237. {
  238. LPROCCPLAPPLET pProcApplet = NULL;
  239. CString szApplet;
  240. CError error (this);
  241. PROCESS_INFORMATION ProcessInformation;
  242. STARTUPINFO StartupInfo;
  243. BOOL bResult;
  244. UINT DirPathLength;
  245. TCHAR Path[MAX_PATH*2];
  246. TCHAR CommandLine[]=TEXT("rundll32.exe shell32.dll,Control_RunDLL irprops.cpl ");
  247. ZeroMemory(&StartupInfo,sizeof(StartupInfo));
  248. StartupInfo.cb=sizeof(StartupInfo);
  249. DirPathLength=GetSystemDirectory(
  250. Path,
  251. sizeof(Path)/sizeof(TCHAR)
  252. );
  253. if (DirPathLength != 0) {
  254. StringCbCat(Path,sizeof(Path),TEXT("\\rundll32.exe"));
  255. bResult=CreateProcess(
  256. Path,
  257. CommandLine,
  258. NULL,
  259. NULL,
  260. FALSE,
  261. NORMAL_PRIORITY_CLASS,
  262. NULL,
  263. NULL,
  264. &StartupInfo,
  265. &ProcessInformation
  266. );
  267. if (bResult) {
  268. CloseHandle(ProcessInformation.hProcess);
  269. CloseHandle(ProcessInformation.hThread);
  270. } else {
  271. error.ShowMessage (IDS_APPLET_ERROR);
  272. }
  273. } else {
  274. error.ShowMessage (IDS_APPLET_ERROR);
  275. }
  276. DestroyWindow();
  277. }
  278. void CController::OnRecvInProgress (WPARAM wParam, LPARAM lParam)
  279. {
  280. DWORD dwShowRecv;
  281. struct MSG_RECEIVE_IN_PROGRESS * msg = (struct MSG_RECEIVE_IN_PROGRESS *) wParam;
  282. dwShowRecv = GetIRRegVal (TEXT("ShowRecvStatus"), 1);
  283. if (!dwShowRecv) {
  284. msg->status = 0;
  285. return;
  286. }
  287. if (wcslen(msg->MachineName) > IRDA_DEVICE_NAME_LENGTH) {
  288. msg->status = ERROR_INVALID_PARAMETER;
  289. return;
  290. }
  291. CIrRecvProgress * pDlgRecvProgress = new CIrRecvProgress(msg->MachineName,
  292. msg->bSuppressRecvConf);
  293. if (!pDlgRecvProgress) {
  294. msg->status = ERROR_NOT_ENOUGH_MEMORY;
  295. return;
  296. }
  297. SetForegroundWindow();
  298. pDlgRecvProgress->SetActiveWindow();
  299. pDlgRecvProgress->SetWindowPos(&appController->wndTop, -1, -1, -1, -1, SWP_NOSIZE | SWP_NOMOVE);
  300. fwinfo.hwnd = pDlgRecvProgress->m_hWnd;
  301. FlashWindowEx (&fwinfo);
  302. *(msg->pCookie) = (COOKIE) pDlgRecvProgress;
  303. msg->status = 0;
  304. }
  305. void CController::OnGetPermission( WPARAM wParam, LPARAM lParam )
  306. {
  307. DWORD dwShowRecv;
  308. struct MSG_GET_PERMISSION * msg = (MSG_GET_PERMISSION *) wParam;
  309. dwShowRecv = GetIRRegVal (TEXT("ShowRecvStatus"), 1);
  310. if (!dwShowRecv) {
  311. msg->status = 0;
  312. return;
  313. }
  314. SetForegroundWindow();
  315. CIrRecvProgress * pDlgRecvProgress = ValidateRecvCookie(msg->Cookie);
  316. if (!pDlgRecvProgress) {
  317. msg->status = ERROR_INVALID_PARAMETER;
  318. return;
  319. }
  320. msg->status = pDlgRecvProgress->GetPermission( msg->Name, msg->fDirectory );
  321. }
  322. void CController::OnRecvFinished (WPARAM wParam, LPARAM lParam)
  323. {
  324. DWORD dwShowRecv;
  325. struct MSG_RECEIVE_FINISHED * msg = (struct MSG_RECEIVE_FINISHED *) wParam;
  326. dwShowRecv = GetIRRegVal (TEXT("ShowRecvStatus"), 1);
  327. if (!dwShowRecv) {
  328. msg->status = 0;
  329. return;
  330. }
  331. CIrRecvProgress * pDlgRecvProgress = ValidateRecvCookie(msg->Cookie);
  332. if (!pDlgRecvProgress) {
  333. msg->status = ERROR_INVALID_PARAMETER;
  334. return;
  335. }
  336. //
  337. // Preset the error code to ERROR_SUCCESS -- no error popup
  338. //
  339. DWORD Win32Error = ERROR_SUCCESS;
  340. //
  341. // first, filter out unwarranted errors. These error codes
  342. // are treated as ERROR_SUCCESS.
  343. // We have three so far:
  344. // ERROR_SCEP_UNSPECIFIED_DISCONNECT,
  345. // ERROR_SCEP_USER_DISCONNECT and
  346. // ERROR_SCEP_PROVIDER_DISCONNECT.
  347. //
  348. // ERROR_SCEP_UNSPECIFIED_DISCONNECT is the error code
  349. // we encounter most of the time because users usually do
  350. // (1) move the device within IR range
  351. // (2) do image transfer
  352. // (3) move the device out of IR range.
  353. //
  354. if (ERROR_SCEP_UNSPECIFIED_DISCONNECT != (DWORD)msg->ReceiveStatus &&
  355. ERROR_SCEP_USER_DISCONNECT != (DWORD)msg->ReceiveStatus &&
  356. ERROR_SCEP_PROVIDER_DISCONNECT != (DWORD)msg->ReceiveStatus)
  357. {
  358. Win32Error = (DWORD)msg->ReceiveStatus;
  359. }
  360. pDlgRecvProgress->DestroyAndCleanup(Win32Error);
  361. pDlgRecvProgress = NULL;
  362. msg->status = 0;
  363. }
  364. BOOL CController::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
  365. {
  366. CSendProgress* dlgProgress;
  367. int iCharCount=(int) pCopyDataStruct->cbData;
  368. TCHAR* lpszFileNames = new TCHAR [iCharCount];
  369. if (lpszFileNames == NULL) {
  370. return FALSE;
  371. }
  372. memcpy ((LPVOID)lpszFileNames, pCopyDataStruct->lpData, pCopyDataStruct->cbData);
  373. dlgProgress = new CSendProgress(lpszFileNames, iCharCount);
  374. if (dlgProgress != NULL) {
  375. dlgProgress->ShowWindow(SW_SHOW);
  376. dlgProgress->SetFocus();
  377. dlgProgress->SetWindowPos (&wndTop, -1, -1, -1, -1, SWP_NOMOVE | SWP_NOSIZE);
  378. fwinfo.hwnd = dlgProgress->m_hWnd;
  379. ::FlashWindowEx (&fwinfo);
  380. return TRUE;
  381. } else {
  382. delete lpszFileNames;
  383. return FALSE;
  384. }
  385. }
  386. void CController::OnStartTimer (WPARAM wParam, LPARAM lParam)
  387. {
  388. //update the state of the help window
  389. if (g_hwndHelp && ! ::IsWindow (g_hwndHelp))
  390. g_hwndHelp = NULL;
  391. if (!m_fHaveTimer)
  392. {
  393. m_fHaveTimer = SetTimer (TIMER_ID,
  394. m_lTimeout,
  395. NULL //want WM_TIMER messages
  396. )?TRUE:FALSE;
  397. }
  398. }
  399. void CController::OnKillTimer (WPARAM wParam, LPARAM lParam)
  400. {
  401. //update the state of the help window
  402. if (g_hwndHelp && ! ::IsWindow (g_hwndHelp))
  403. g_hwndHelp = NULL;
  404. if (m_fHaveTimer)
  405. {
  406. KillTimer(TIMER_ID);
  407. m_fHaveTimer = FALSE;
  408. }
  409. }
  410. void CController::OnTimer (UINT nTimerID)
  411. {
  412. //there is only one timer, so we don't have to check for it.
  413. //the timer has expired, so kill self
  414. //however, first make sure that the help window (if it was put up)
  415. //is gone.
  416. if (g_hwndHelp && ::IsWindow (g_hwndHelp))
  417. {
  418. //the help window is around. restart the timer.
  419. //this is the only way we can kill ourselves when the window
  420. //is finally destroyed.
  421. m_fHaveTimer = FALSE;
  422. this->OnStartTimer (NULL, NULL);
  423. }
  424. else
  425. {
  426. g_hwndHelp = NULL;
  427. this->PostMessage(WM_CLOSE);
  428. }
  429. }
  430. void CController::OnSessionChange(WPARAM wParam, LPARAM lParam)
  431. {
  432. OutputDebugStringA("irftp: controller session changed\n");
  433. return;
  434. }