Source code of Windows XP (NT5)
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.

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