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.

528 lines
16 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998-2001
  4. *
  5. * TITLE: STIEVENT.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 4-6-2001
  12. *
  13. * DESCRIPTION:
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include <wiaregst.h>
  19. #include "simcrack.h"
  20. #include "resource.h"
  21. #include "stievent.h"
  22. #include "evntparm.h"
  23. #include "shmemsec.h"
  24. //
  25. // This dialog displays the sti application list and lets the user choose one.
  26. //
  27. class CStiEventHandlerDialog
  28. {
  29. public:
  30. struct CData
  31. {
  32. //
  33. // This will contain the event information, including the application list,
  34. // which is really what we are interested in.
  35. //
  36. CStiEventData *pStiEventData;
  37. //
  38. // The OUT member is intended to contain the selected handler, which will
  39. // be copied from the list contained in the CStiEventData class
  40. //
  41. CStiEventData::CStiEventHandler EventHandler;
  42. //
  43. // We will set the window handle in this shared memory section,
  44. // so we can activate ourselves.
  45. //
  46. CSharedMemorySection<HWND> *pStiEventHandlerSharedMemory;
  47. };
  48. private:
  49. //
  50. // Not implemented
  51. //
  52. CStiEventHandlerDialog();
  53. CStiEventHandlerDialog( const CStiEventHandlerDialog & );
  54. CStiEventHandlerDialog &operator=( const CStiEventHandlerDialog & );
  55. private:
  56. HWND m_hWnd;
  57. CData *m_pData;
  58. private:
  59. //
  60. // Sole constructor
  61. //
  62. explicit CStiEventHandlerDialog( HWND hWnd )
  63. : m_hWnd(hWnd),
  64. m_pData(NULL)
  65. {
  66. }
  67. //
  68. // Destructor
  69. //
  70. ~CStiEventHandlerDialog()
  71. {
  72. m_hWnd = NULL;
  73. m_pData = NULL;
  74. }
  75. //
  76. // WM_INITDIALOG handler.
  77. //
  78. LRESULT OnInitDialog( WPARAM, LPARAM lParam )
  79. {
  80. //
  81. // Get the dialog's data
  82. //
  83. m_pData = reinterpret_cast<CData*>(lParam);
  84. //
  85. // Make sure we have valid data
  86. //
  87. if (!m_pData || !m_pData->pStiEventData)
  88. {
  89. EndDialog( m_hWnd, -1 );
  90. SetLastError( ERROR_INVALID_PARAMETER );
  91. return 0;
  92. }
  93. //
  94. // Make sure we were supplied with a memory section
  95. //
  96. if (m_pData->pStiEventHandlerSharedMemory)
  97. {
  98. //
  99. // Get a pointer to the shared memory
  100. //
  101. HWND *phWnd = m_pData->pStiEventHandlerSharedMemory->Lock();
  102. if (phWnd)
  103. {
  104. //
  105. // Store our window handle
  106. //
  107. *phWnd = m_hWnd;
  108. //
  109. // Release the mutex
  110. //
  111. m_pData->pStiEventHandlerSharedMemory->Release();
  112. }
  113. }
  114. //
  115. // Add the handlers to the list
  116. //
  117. for (int i=0;i<m_pData->pStiEventData->EventHandlers().Size();++i)
  118. {
  119. //
  120. // Get the program name and make sure it is valid
  121. //
  122. CSimpleString strAppName = CSimpleStringConvert::NaturalString(m_pData->pStiEventData->EventHandlers()[i].ApplicationName());
  123. if (strAppName.Length())
  124. {
  125. //
  126. // Add the string and save the item id
  127. //
  128. LRESULT nIndex = SendDlgItemMessage( m_hWnd, IDC_STI_APPS_LIST, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(strAppName.String()) );
  129. if (LB_ERR != nIndex)
  130. {
  131. //
  132. // Set the item data to the index in our handler array
  133. //
  134. SendDlgItemMessage( m_hWnd, IDC_STI_APPS_LIST, LB_SETITEMDATA, nIndex, i );
  135. }
  136. }
  137. }
  138. //
  139. // Select the first item
  140. //
  141. SendDlgItemMessage( m_hWnd, IDC_STI_APPS_LIST, LB_SETCURSEL, 0, 0 );
  142. //
  143. // Enable the OK button if we have a valid selected item
  144. //
  145. EnableWindow( GetDlgItem( m_hWnd, IDOK ), GetHandlerIndexOfCurrentSelection() != -1 );
  146. return 0;
  147. }
  148. void OnCancel( WPARAM, LPARAM )
  149. {
  150. //
  151. // Just close the dialog on cancel
  152. //
  153. EndDialog( m_hWnd, IDCANCEL );
  154. }
  155. int GetHandlerIndexOfCurrentSelection()
  156. {
  157. //
  158. // Assume failure
  159. //
  160. int nResult = -1;
  161. //
  162. // Make sure we have valid pointers still
  163. //
  164. if (m_pData && m_pData->pStiEventData)
  165. {
  166. //
  167. // Get the current selection index and make sure it is valid
  168. //
  169. LRESULT nCurIndex = SendDlgItemMessage( m_hWnd, IDC_STI_APPS_LIST, LB_GETCURSEL, 0, 0 );
  170. if (LB_ERR != nCurIndex)
  171. {
  172. //
  173. // Get the index into our event handler array from the item data for the current item
  174. //
  175. LRESULT nEventItemIndex = SendDlgItemMessage( m_hWnd, IDC_STI_APPS_LIST, LB_GETITEMDATA, nCurIndex, 0 );
  176. //
  177. // Make sure the index is valid
  178. //
  179. if (nEventItemIndex >= 0 && nEventItemIndex < m_pData->pStiEventData->EventHandlers().Size())
  180. {
  181. nResult = static_cast<int>(nEventItemIndex);
  182. }
  183. }
  184. }
  185. return nResult;
  186. }
  187. void OnOK( WPARAM, LPARAM )
  188. {
  189. //
  190. // Make sure we have valid parameters
  191. //
  192. int nEventItemIndex = GetHandlerIndexOfCurrentSelection();
  193. if (-1 != nEventItemIndex)
  194. {
  195. //
  196. // Copy the event handler to our OUT parameter
  197. //
  198. m_pData->EventHandler = m_pData->pStiEventData->EventHandlers()[nEventItemIndex];
  199. //
  200. // Close the dialog
  201. //
  202. EndDialog( m_hWnd, IDOK );
  203. }
  204. }
  205. void OnAppsListDblClk( WPARAM, LPARAM )
  206. {
  207. //
  208. // Simulate the user pressing the OK button
  209. //
  210. SendMessage( m_hWnd, WM_COMMAND, MAKEWPARAM(IDOK,0), 0 );
  211. }
  212. void OnAppsListSelChange( WPARAM, LPARAM )
  213. {
  214. //
  215. // Enable the OK button if we have a valid selected item
  216. //
  217. EnableWindow( GetDlgItem( m_hWnd, IDOK ), GetHandlerIndexOfCurrentSelection() != -1 );
  218. }
  219. LRESULT OnCommand( WPARAM wParam, LPARAM lParam )
  220. {
  221. SC_BEGIN_COMMAND_HANDLERS()
  222. {
  223. SC_HANDLE_COMMAND(IDCANCEL,OnCancel);
  224. SC_HANDLE_COMMAND(IDOK,OnOK);
  225. SC_HANDLE_COMMAND_NOTIFY(LBN_DBLCLK,IDC_STI_APPS_LIST,OnAppsListDblClk);
  226. SC_HANDLE_COMMAND_NOTIFY(LBN_SELCHANGE,IDC_STI_APPS_LIST,OnAppsListSelChange);
  227. }
  228. SC_END_COMMAND_HANDLERS();
  229. }
  230. public:
  231. static INT_PTR __stdcall DlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  232. {
  233. SC_BEGIN_DIALOG_MESSAGE_HANDLERS(CStiEventHandlerDialog)
  234. {
  235. SC_HANDLE_DIALOG_MESSAGE( WM_INITDIALOG, OnInitDialog );
  236. SC_HANDLE_DIALOG_MESSAGE( WM_COMMAND, OnCommand );
  237. }
  238. SC_END_DIALOG_MESSAGE_HANDLERS();
  239. }
  240. };
  241. HRESULT StiEventHandler( CStiEventData &StiEventData )
  242. {
  243. HRESULT hr = S_OK;
  244. #if defined(DBG)
  245. //
  246. // Dump the parameters
  247. //
  248. WIA_PUSH_FUNCTION((TEXT("StiEventHandler")));
  249. WIA_PRINTGUID((StiEventData.Event(),TEXT(" Event")));
  250. WIA_TRACE((TEXT(" EventDescription: %ws"), StiEventData.EventDescription().String()));
  251. WIA_TRACE((TEXT(" DeviceDescription: %ws"), StiEventData.DeviceDescription().String()));
  252. WIA_TRACE((TEXT(" DeviceId: %ws"), StiEventData.DeviceId().String()));
  253. WIA_TRACE((TEXT(" EventType: %08X"), StiEventData.EventType()));
  254. WIA_TRACE((TEXT(" Reserved: %08X"), StiEventData.Reserved()));
  255. for (int i=0;i<StiEventData.EventHandlers().Size();++i)
  256. {
  257. WIA_TRACE((TEXT(" Handler %d: [%ws] CommandLine: [%ws]"), i, StiEventData.EventHandlers()[i].ApplicationName().String(), StiEventData.EventHandlers()[i].CommandLine().String()));
  258. }
  259. #endif // defined(DBG)
  260. //
  261. // Make sure we have some handlers
  262. //
  263. if (0 == StiEventData.EventHandlers().Size())
  264. {
  265. return E_INVALIDARG;
  266. }
  267. //
  268. // Create the mutex name
  269. //
  270. CSimpleStringWide strMutexName = StiEventData.DeviceId();
  271. //
  272. // Append the event ID
  273. //
  274. LPOLESTR pwszEventGuid = NULL;
  275. if (SUCCEEDED(StringFromIID( StiEventData.Event(), &pwszEventGuid )) && pwszEventGuid)
  276. {
  277. strMutexName += CSimpleStringWide(pwszEventGuid);
  278. CoTaskMemFree( pwszEventGuid );
  279. }
  280. WIA_TRACE((TEXT("strMutexName: %ws"), strMutexName.String() ));
  281. //
  282. // Create the shared memory section for excluding multiple instances
  283. //
  284. CSharedMemorySection<HWND> StiEventHandlerSharedMemory;
  285. //
  286. // If we were able to open the memory section
  287. //
  288. if (CSharedMemorySection<HWND>::SmsOpened == StiEventHandlerSharedMemory.Open( CSimpleStringConvert::NaturalString(CSimpleStringWide(strMutexName)), true ))
  289. {
  290. HWND *phWnd = StiEventHandlerSharedMemory.Lock();
  291. if (phWnd)
  292. {
  293. //
  294. // Make sure we have a valid window handle
  295. //
  296. if (*phWnd && IsWindow(*phWnd))
  297. {
  298. //
  299. // If it is a valid window, bring it to the foreground.
  300. //
  301. SetForegroundWindow(*phWnd);
  302. }
  303. //
  304. // Release the mutex
  305. //
  306. StiEventHandlerSharedMemory.Release();
  307. }
  308. }
  309. else
  310. {
  311. //
  312. // We will execute this handler below, after we decide which one to use
  313. //
  314. CStiEventData::CStiEventHandler EventHandler;
  315. //
  316. // If there is only one handler, save that handler
  317. //
  318. if (1 == StiEventData.EventHandlers().Size())
  319. {
  320. EventHandler = StiEventData.EventHandlers()[0];
  321. }
  322. //
  323. // Otherwise, if there is more than one handler, display the handler prompt dialog
  324. //
  325. else
  326. {
  327. //
  328. // Prepare the dialog data
  329. //
  330. CStiEventHandlerDialog::CData DialogData;
  331. DialogData.pStiEventData = &StiEventData;
  332. DialogData.pStiEventHandlerSharedMemory = &StiEventHandlerSharedMemory;
  333. //
  334. // Display the dialog
  335. //
  336. INT_PTR nDialogResult = DialogBoxParam( g_hInstance, MAKEINTRESOURCE(IDD_CHOOSE_STI_APPLICATION), NULL, CStiEventHandlerDialog::DlgProc, reinterpret_cast<LPARAM>(&DialogData) );
  337. //
  338. // If the user selected a program and hit OK, save the handler
  339. //
  340. if (IDOK == nDialogResult)
  341. {
  342. EventHandler = DialogData.EventHandler;
  343. }
  344. //
  345. // If the user cancelled, just return S_FALSE immediately (premature return)
  346. //
  347. else if (IDCANCEL == nDialogResult)
  348. {
  349. return S_FALSE;
  350. }
  351. //
  352. // If there was an internal error, save the correct error
  353. //
  354. else if (-1 == nDialogResult)
  355. {
  356. hr = HRESULT_FROM_WIN32(GetLastError());
  357. }
  358. //
  359. // For all other return values, save a generic error
  360. //
  361. else
  362. {
  363. hr = E_FAIL;
  364. }
  365. }
  366. if (SUCCEEDED(hr))
  367. {
  368. //
  369. // Make sure we have a valid handler
  370. //
  371. if (EventHandler.IsValid())
  372. {
  373. //
  374. // Prepare the process information
  375. //
  376. STARTUPINFO StartupInfo = {0};
  377. StartupInfo.cb = sizeof(StartupInfo);
  378. //
  379. // Convert the command line to a TCHAR string
  380. //
  381. CSimpleString CommandLine = CSimpleStringConvert::NaturalString(EventHandler.CommandLine());
  382. //
  383. // Make sure we actually have a command line
  384. //
  385. if (CommandLine.Length())
  386. {
  387. //
  388. // Execute the program
  389. //
  390. PROCESS_INFORMATION ProcessInformation = {0};
  391. if (CreateProcess( NULL, const_cast<LPTSTR>(CommandLine.String()), NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation ))
  392. {
  393. //
  394. // If the program succeeded, close the handles to prevent leaks
  395. //
  396. CloseHandle( ProcessInformation.hProcess );
  397. CloseHandle( ProcessInformation.hThread );
  398. }
  399. else
  400. {
  401. //
  402. // Save the error from CreateProcess
  403. //
  404. hr = HRESULT_FROM_WIN32(GetLastError());
  405. }
  406. }
  407. else
  408. {
  409. //
  410. // Assume out of memory error if we couldn't create the string
  411. //
  412. hr = E_OUTOFMEMORY;
  413. }
  414. }
  415. else
  416. {
  417. //
  418. // Who knows what went wrong?
  419. //
  420. hr = E_FAIL;
  421. }
  422. }
  423. //
  424. // If we've failed, display an error message
  425. //
  426. if (FAILED(hr))
  427. {
  428. //
  429. // We will display this string, after we've constructed it
  430. //
  431. CSimpleString strMessage;
  432. //
  433. // Get the error text
  434. //
  435. CSimpleString strError = WiaUiUtil::GetErrorTextFromHResult(hr);
  436. //
  437. // Get the application name
  438. //
  439. CSimpleString strApplication = CSimpleStringConvert::NaturalString(EventHandler.ApplicationName());
  440. //
  441. // If we don't have an application name, use some default
  442. //
  443. if (!strApplication.Length())
  444. {
  445. strApplication.LoadString( IDS_STI_EVENT_ERROR_APP_NAME, g_hInstance );
  446. }
  447. //
  448. // If we have a specific error message, use it.
  449. //
  450. if (strError.Length())
  451. {
  452. strMessage.Format( IDS_STI_EVENT_ERROR_WITH_EXPLANATION, g_hInstance, strApplication.String(), strError.String() );
  453. }
  454. //
  455. // Otherwise, use a generic error message.
  456. //
  457. else
  458. {
  459. strMessage.Format( IDS_STI_EVENT_ERROR_NO_EXPLANATION, g_hInstance, strApplication.String() );
  460. }
  461. //
  462. // Display the error message.
  463. //
  464. MessageBox( NULL, strMessage, CSimpleString( IDS_STI_EVENT_ERROR_TITLE, g_hInstance ), MB_ICONHAND );
  465. }
  466. }
  467. //
  468. // We're done here
  469. //
  470. return hr;
  471. }