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.

643 lines
21 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999
  6. //
  7. // File: eventprompt.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <precomp.h>
  11. #pragma hdrstop
  12. #include "eventprompt.h"
  13. #include "resource.h"
  14. #include "wiacsh.h"
  15. #include "psutil.h"
  16. //
  17. #define COL_NAME 0
  18. #define COL_DESCRIPTION 1
  19. const UINT c_auTileColumns[] = {COL_NAME, COL_DESCRIPTION};
  20. const UINT c_auTileSubItems[] = {COL_DESCRIPTION};
  21. static const DWORD HelpIds [] =
  22. {
  23. IDC_EVENTNAME, IDH_WIA_EVENT_OCCURRED,
  24. IDC_HANDLERLIST, IDH_WIA_PROGRAM_LIST,
  25. IDC_NOPROMPT, IDH_WIA_ALWAYS_USE,
  26. IDOK, IDH_OK,
  27. IDCANCEL, IDH_CANCEL,
  28. 0,0
  29. };
  30. INT_PTR CALLBACK
  31. CEventPromptDlg::DlgProc (HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
  32. {
  33. CEventPromptDlg *pThis;
  34. pThis = reinterpret_cast<CEventPromptDlg*>(GetWindowLongPtr(hwnd,DWLP_USER));
  35. switch (msg)
  36. {
  37. case WM_INITDIALOG:
  38. SetWindowLongPtr (hwnd, DWLP_USER, lp);
  39. pThis = reinterpret_cast<CEventPromptDlg*>(lp);
  40. pThis->m_hwnd = hwnd;
  41. pThis->OnInit ();
  42. //
  43. // Initially disable the OK button, unless there is something selected
  44. //
  45. EnableWindow(GetDlgItem(hwnd,IDOK),(0!=ListView_GetSelectedCount(GetDlgItem(hwnd,IDC_HANDLERLIST))));
  46. return TRUE;
  47. case WM_COMMAND:
  48. if (pThis)
  49. {
  50. return pThis->OnCommand(HIWORD(wp), LOWORD(wp));
  51. }
  52. break;
  53. case WM_DESTROY:
  54. {
  55. //
  56. // Delete the listview's image list
  57. //
  58. HIMAGELIST hImageList = ListView_SetImageList(GetDlgItem(hwnd,IDC_HANDLERLIST), NULL, LVSIL_NORMAL);
  59. if (hImageList)
  60. {
  61. ImageList_Destroy(hImageList);
  62. }
  63. if (pThis)
  64. {
  65. pThis->m_PromptData->Close();
  66. }
  67. SetWindowLongPtr(hwnd, DWLP_USER, NULL);
  68. }
  69. return TRUE;
  70. case WM_HELP:
  71. WiaHelp::HandleWmHelp( wp, lp, HelpIds );
  72. return TRUE;
  73. case WM_CONTEXTMENU:
  74. WiaHelp::HandleWmContextMenu( wp, lp, HelpIds );
  75. return TRUE;
  76. case WM_NOTIFY:
  77. {
  78. //
  79. // Get the notification struct
  80. //
  81. NMHDR *pNmHdr = reinterpret_cast<NMHDR*>(lp);
  82. if (pNmHdr)
  83. {
  84. //
  85. // Is this the handler listview?
  86. //
  87. if (IDC_HANDLERLIST == pNmHdr->idFrom)
  88. {
  89. //
  90. // Get the listview notification stuff
  91. //
  92. NMLISTVIEW *pNmListView = reinterpret_cast<NMLISTVIEW*>(lp);
  93. //
  94. // If this is an item changed notification message
  95. //
  96. if (LVN_ITEMCHANGED == pNmHdr->code)
  97. {
  98. //
  99. // If the state changed
  100. //
  101. if (pNmListView->uChanged & LVIF_STATE)
  102. {
  103. //
  104. // Enable the OK button iff there is a selected item
  105. //
  106. EnableWindow(GetDlgItem(hwnd,IDOK),(0!=ListView_GetSelectedCount(GetDlgItem(hwnd,IDC_HANDLERLIST))));
  107. return TRUE;
  108. }
  109. }
  110. //
  111. // Double click?
  112. //
  113. else if (NM_DBLCLK == pNmHdr->code)
  114. {
  115. //
  116. // Check to make sure something is selected
  117. //
  118. if (ListView_GetSelectedCount(GetDlgItem(hwnd,IDC_HANDLERLIST)))
  119. {
  120. //
  121. // Simulate an OK message
  122. //
  123. SendMessage( hwnd, WM_COMMAND, MAKEWPARAM(IDOK,BN_CLICKED), 0 );
  124. return TRUE;
  125. }
  126. }
  127. //
  128. // Deleting an item
  129. //
  130. else if (LVN_DELETEITEM == pNmHdr->code)
  131. {
  132. //
  133. // Get the event data
  134. //
  135. WIA_EVENT_HANDLER *peh = reinterpret_cast<WIA_EVENT_HANDLER*>(pNmListView->lParam);
  136. if (peh)
  137. {
  138. //
  139. // Free the bstrings
  140. //
  141. if (peh->bstrDescription)
  142. {
  143. SysFreeString (peh->bstrDescription);
  144. }
  145. if (peh->bstrIcon)
  146. {
  147. SysFreeString (peh->bstrIcon);
  148. }
  149. if (peh->bstrName)
  150. {
  151. SysFreeString (peh->bstrName);
  152. }
  153. //
  154. // Free the structure
  155. //
  156. delete peh;
  157. }
  158. return TRUE;
  159. }
  160. }
  161. }
  162. }
  163. break;
  164. default:
  165. break;
  166. }
  167. return FALSE;
  168. }
  169. void
  170. CEventPromptDlg::OnInit ()
  171. {
  172. WIA_PUSHFUNCTION(TEXT("CEventPromptDlg::OnInit"));
  173. // update the shared memory section indicating we exist
  174. // use a unique name for the shared memory
  175. LPWSTR wszGuid;
  176. StringFromCLSID (m_pEventParameters->EventGUID, &wszGuid);
  177. CSimpleStringWide strSection(wszGuid);
  178. strSection.Concat (m_pEventParameters->strDeviceID);
  179. CoTaskMemFree (wszGuid);
  180. m_PromptData = new CSharedMemorySection<HWND>(CSimpleStringConvert::NaturalString(strSection), true);
  181. if (m_PromptData)
  182. {
  183. HWND *pData = m_PromptData->Lock();
  184. if (pData)
  185. {
  186. *pData = m_hwnd;
  187. m_PromptData->Release();
  188. }
  189. }
  190. // fill in the list of handlers
  191. m_pList = new CHandlerList (GetDlgItem(m_hwnd, IDC_HANDLERLIST));
  192. if (m_pList)
  193. {
  194. m_pList->FillList (m_pEventParameters->strDeviceID,
  195. m_pEventParameters->EventGUID);
  196. }
  197. // Set the dialog's caption to be the name of the device
  198. SetWindowText (m_hwnd, CSimpleStringConvert::NaturalString(m_pEventParameters->strDeviceDescription));
  199. // Set the event description text
  200. SetDlgItemText (m_hwnd, IDC_EVENTNAME, CSimpleStringConvert::NaturalString(m_pEventParameters->strEventDescription));
  201. //
  202. // Disable the "always make this the handler" checkbox for low privilege users
  203. SC_HANDLE hSCM = ::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  204. if (!hSCM)
  205. {
  206. EnableWindow(GetDlgItem(m_hwnd, IDC_NOPROMPT), FALSE);
  207. }
  208. else
  209. {
  210. CloseServiceHandle(hSCM);
  211. }
  212. }
  213. INT_PTR
  214. CEventPromptDlg::OnCommand (WORD wCode, WORD widItem)
  215. {
  216. INT_PTR iRet = TRUE;
  217. // we only care about IDOK or IDCANCEL
  218. switch (widItem)
  219. {
  220. case IDOK:
  221. iRet = OnOK ();
  222. if (!iRet)
  223. {
  224. break;;
  225. }
  226. // fall through
  227. case IDCANCEL:
  228. EndDialog (m_hwnd, 1);
  229. break;
  230. }
  231. return iRet;
  232. }
  233. // When the user presses OK, invoke the selected application and make it
  234. // the default if requested
  235. INT_PTR
  236. CEventPromptDlg::OnOK ()
  237. {
  238. WIA_PUSHFUNCTION(TEXT("CEventPromptDlg::OnOK"));
  239. WIA_EVENT_HANDLER *pSelHandler = NULL;
  240. if (m_pList)
  241. {
  242. pSelHandler = m_pList->GetSelectedHandler ();
  243. }
  244. if (pSelHandler)
  245. {
  246. if (IsDlgButtonChecked (m_hwnd, IDC_NOPROMPT))
  247. {
  248. // Set this handler as the default
  249. SetDefaultHandler (pSelHandler);
  250. }
  251. if (!InvokeHandler(pSelHandler))
  252. {
  253. WIA_ERROR((TEXT("InvokeHandler failed")));
  254. return FALSE;
  255. }
  256. }
  257. return TRUE;
  258. }
  259. void
  260. CEventPromptDlg::SetDefaultHandler (WIA_EVENT_HANDLER *pHandler)
  261. {
  262. WIA_PUSHFUNCTION(TEXT("CEventPromptDlg::SetDefaultHandler"));
  263. CComPtr<IWiaDevMgr> pDevMgr;
  264. if (SUCCEEDED(CoCreateInstance (CLSID_WiaDevMgr,
  265. NULL,
  266. CLSCTX_LOCAL_SERVER,
  267. IID_IWiaDevMgr,
  268. reinterpret_cast<LPVOID*>(&pDevMgr))))
  269. {
  270. pDevMgr->RegisterEventCallbackCLSID (WIA_SET_DEFAULT_HANDLER,
  271. CComBSTR(m_pEventParameters->strDeviceID),
  272. &m_pEventParameters->EventGUID,
  273. &pHandler->guid,
  274. pHandler->bstrName,
  275. pHandler->bstrDescription,
  276. pHandler->bstrIcon);
  277. }
  278. }
  279. bool
  280. CEventPromptDlg::InvokeHandler(WIA_EVENT_HANDLER *pHandler)
  281. {
  282. WIA_PUSHFUNCTION(TEXT("CEventPromptDlg::InvokeHandler"));
  283. CComPtr<IWiaEventCallback> pCallback;
  284. if (pHandler->bstrCommandline) {
  285. PROCESS_INFORMATION pi;
  286. STARTUPINFO si;
  287. TCHAR szCommand[MAX_PATH*2];
  288. ZeroMemory (&si, sizeof(si));
  289. ZeroMemory (&pi, sizeof(pi));
  290. si.cb = sizeof(si);
  291. si.wShowWindow = SW_SHOW;
  292. #ifdef UNICODE
  293. wcscpy (szCommand, pHandler->bstrCommandline);
  294. #else
  295. WideCharToMultiByte (CP_ACP, 0,
  296. pHandler->bstrCommandline, -1,
  297. szCommand, ARRAYSIZE(szCommand),
  298. NULL, NULL);
  299. #endif
  300. // Trace(TEXT("Command line for STI app is %s"), szCommand);
  301. if (CreateProcess (NULL,
  302. szCommand,
  303. NULL,
  304. NULL,
  305. FALSE,
  306. 0,
  307. NULL,
  308. NULL,
  309. &si,
  310. &pi))
  311. {
  312. CloseHandle (pi.hProcess);
  313. CloseHandle (pi.hThread);
  314. return true;
  315. }
  316. else
  317. {
  318. WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("Execution of pHandler->bstrCommandline [%ws] FAILED"),pHandler->bstrCommandline));
  319. }
  320. }
  321. else
  322. {
  323. HRESULT hr = CoCreateInstance(pHandler->guid,
  324. NULL,
  325. CLSCTX_LOCAL_SERVER,
  326. IID_IWiaEventCallback,
  327. reinterpret_cast<LPVOID*>(&pCallback));
  328. if (SUCCEEDED(hr))
  329. {
  330. hr = pCallback->ImageEventCallback (&m_pEventParameters->EventGUID,
  331. CComBSTR(m_pEventParameters->strEventDescription),
  332. CComBSTR(m_pEventParameters->strDeviceID),
  333. CComBSTR(m_pEventParameters->strDeviceDescription),
  334. m_pEventParameters->dwDeviceType,
  335. CComBSTR(m_pEventParameters->strFullItemName),
  336. &m_pEventParameters->ulEventType,
  337. m_pEventParameters->ulReserved);
  338. }
  339. if (FAILED(hr))
  340. {
  341. // inform the user something went wrong
  342. UIErrors::ReportMessage(m_hwnd,g_hInstance,
  343. NULL,
  344. MAKEINTRESOURCE(IDS_HANDLERERR_CAPTION),
  345. MAKEINTRESOURCE(IDS_HANDLERERR),
  346. MB_OK);
  347. }
  348. else
  349. {
  350. return true;
  351. }
  352. }
  353. return false;
  354. }
  355. // Parse the bstrIconPath to get the image name and resource id
  356. // Note that -1 is not a valid id for ExtractIconEx
  357. int
  358. AddIconToImageList (HIMAGELIST himl, BSTR strIconPath)
  359. {
  360. int iRet = 0;
  361. TCHAR szPath[MAX_PATH];
  362. LONG nIcon;
  363. INT nComma=0;
  364. HICON hIcon = NULL;
  365. HRESULT hr;
  366. if (!strIconPath)
  367. {
  368. return 0;
  369. }
  370. while (strIconPath[nComma] && strIconPath[nComma] != L',')
  371. {
  372. nComma++;
  373. }
  374. if (strIconPath[nComma])
  375. {
  376. ZeroMemory (szPath, sizeof(szPath));
  377. nIcon = wcstol (strIconPath+nComma+1, NULL, 10);
  378. #ifdef UNICODE
  379. wcsncpy (szPath, strIconPath, nComma);
  380. *(szPath+nComma)=L'\0';
  381. #else
  382. WideCharToMultiByte (CP_ACP,
  383. 0,
  384. strIconPath, nComma,
  385. szPath, MAX_PATH,
  386. NULL,NULL);
  387. #endif
  388. ExtractIconEx (szPath, nIcon, &hIcon, NULL, 1);
  389. if (hIcon)
  390. {
  391. iRet = ImageList_AddIcon (himl, hIcon);
  392. DestroyIcon (hIcon);
  393. }
  394. }
  395. return iRet;
  396. }
  397. static int CALLBACK HandlerListCompareFunction( LPARAM lParam1, LPARAM lParam2, LPARAM )
  398. {
  399. int nResult = 0;
  400. LVITEM *pItem1 = reinterpret_cast<LVITEM*>(lParam1);
  401. LVITEM *pItem2 = reinterpret_cast<LVITEM*>(lParam2);
  402. if (pItem1 && pItem2 && pItem1->pszText && pItem2->pszText)
  403. {
  404. int nCompareResult = CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE, pItem1->pszText, -1, pItem2->pszText, -1 );
  405. switch (nCompareResult)
  406. {
  407. case CSTR_LESS_THAN:
  408. nResult = -1;
  409. break;
  410. case CSTR_GREATER_THAN:
  411. nResult = 1;
  412. break;
  413. }
  414. }
  415. return nResult;
  416. }
  417. // Enumerate the installed handlers for the event and add them to the listview
  418. // return the number of handlers we added
  419. UINT
  420. CHandlerList::FillList (const CSimpleStringWide &strDeviceId, GUID &guidEvent)
  421. {
  422. WIA_PUSHFUNCTION(TEXT("CHandlerList::FillList"));
  423. CComPtr<IWiaDevMgr> pDevMgr;
  424. CComPtr<IWiaItem> pItem;
  425. UINT uRet = 0;
  426. //
  427. // Remove all existing items
  428. //
  429. ListView_DeleteAllItems(m_hwnd);
  430. if (SUCCEEDED(CoCreateInstance( CLSID_WiaDevMgr,
  431. NULL,
  432. CLSCTX_LOCAL_SERVER,
  433. IID_IWiaDevMgr,
  434. reinterpret_cast<LPVOID*>(&pDevMgr))))
  435. {
  436. if (SUCCEEDED(pDevMgr->CreateDevice(CComBSTR(strDeviceId.String()),
  437. &pItem)))
  438. {
  439. RECT rc = {0};
  440. LVTILEVIEWINFO lvtvi = {0};
  441. // set up the listview style
  442. ListView_SetView(m_hwnd, LV_VIEW_TILE);
  443. for (int i = 0; i < ARRAYSIZE(c_auTileColumns); ++i)
  444. {
  445. LVCOLUMN lvcolumn = {0};
  446. lvcolumn.mask = LVCF_SUBITEM;
  447. lvcolumn.iSubItem = c_auTileColumns[i];
  448. ListView_InsertColumn(m_hwnd, i, &lvcolumn);
  449. }
  450. GetClientRect(m_hwnd, &rc);
  451. lvtvi.cbSize = sizeof(lvtvi);
  452. lvtvi.dwMask = LVTVIM_TILESIZE | LVTVIM_COLUMNS;
  453. lvtvi.dwFlags = LVTVIF_FIXEDWIDTH;
  454. // Leave room for the scroll bar when setting tile sizes or listview gets screwed up.
  455. lvtvi.sizeTile.cx = ((rc.right - rc.left) - GetSystemMetrics(SM_CXVSCROLL));
  456. lvtvi.cLines = ARRAYSIZE(c_auTileSubItems);
  457. ListView_SetTileViewInfo(m_hwnd, &lvtvi);
  458. CComPtr<IEnumWIA_DEV_CAPS> pEnum;
  459. if (SUCCEEDED(pItem->EnumRegisterEventInfo(0,
  460. &guidEvent,
  461. &pEnum)) )
  462. {
  463. WIA_EVENT_HANDLER *pHandler;
  464. ULONG ul;
  465. LVITEM lvi = {0};
  466. HICON hicon;
  467. HRESULT hr = NOERROR;
  468. CSimpleString strText;
  469. // Create a new imagelist
  470. HIMAGELIST hImageList = ImageList_Create (GetSystemMetrics(SM_CXICON),
  471. GetSystemMetrics(SM_CYICON),
  472. PrintScanUtil::CalculateImageListColorDepth() | ILC_MASK,
  473. 2,
  474. 2);
  475. // Add the "default" icon
  476. hicon =reinterpret_cast<HICON>(LoadImage (g_hInstance,
  477. MAKEINTRESOURCE(IDI_SCANCAM),
  478. IMAGE_ICON,
  479. GetSystemMetrics(SM_CXICON),
  480. GetSystemMetrics(SM_CYICON),
  481. LR_SHARED | LR_DEFAULTCOLOR));
  482. ImageList_AddIcon (hImageList, hicon);
  483. SendMessage (m_hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL,
  484. reinterpret_cast<LPARAM>(hImageList));
  485. // enum the items and add them to the listview
  486. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  487. while (S_OK == hr)
  488. {
  489. pHandler = new WIA_EVENT_HANDLER;
  490. if (!pHandler)
  491. {
  492. break;
  493. }
  494. hr = pEnum->Next (1, pHandler, &ul);
  495. if (IsEqualCLSID(pHandler->guid, CLSID_EventPrompter) ||
  496. IsEqualCLSID(pHandler->guid, WIA_EVENT_HANDLER_NO_ACTION) ||
  497. IsEqualCLSID(pHandler->guid, WIA_EVENT_HANDLER_PROMPT) ||
  498. !lstrcmpiW(pHandler->bstrName, L"Internal"))
  499. {
  500. delete pHandler;
  501. continue;
  502. }
  503. if (S_OK == hr)
  504. {
  505. // get the string
  506. strText = CSimpleStringConvert::NaturalString (CSimpleStringWide(pHandler->bstrName));
  507. lvi.pszText = const_cast<LPTSTR>(strText.String());
  508. lvi.lParam = reinterpret_cast<LPARAM>(pHandler);
  509. // get the icon
  510. lvi.iImage = AddIconToImageList (hImageList, pHandler->bstrIcon);
  511. // get the index
  512. lvi.iItem = ListView_GetItemCount(m_hwnd);
  513. // add the item
  514. int nIndex = ListView_InsertItem(m_hwnd, &lvi);
  515. if (-1 != nIndex)
  516. {
  517. // add the description subitem
  518. strText = CSimpleStringConvert::NaturalString (CSimpleStringWide(pHandler->bstrDescription));
  519. LVTILEINFO lvti = {0};
  520. lvti.cbSize = sizeof(LVTILEINFO);
  521. lvti.iItem = nIndex;
  522. lvti.cColumns = 1;
  523. lvti.puColumns = (UINT*)c_auTileSubItems;
  524. ListView_SetTileInfo(m_hwnd, &lvti);
  525. ListView_SetItemText(m_hwnd, nIndex, 1, (LPTSTR)strText.String());
  526. uRet++;
  527. }
  528. }
  529. else
  530. {
  531. if (pHandler)
  532. {
  533. delete pHandler;
  534. }
  535. }
  536. }
  537. // Sort the list
  538. ListView_SortItems( m_hwnd, HandlerListCompareFunction, 0 );
  539. // set the default to the first item
  540. lvi.iItem = 0;
  541. lvi.mask = LVIF_STATE;
  542. lvi.stateMask = LVIS_FOCUSED|LVIS_SELECTED;
  543. lvi.state = LVIS_FOCUSED|LVIS_SELECTED;
  544. ListView_SetItem(m_hwnd, &lvi);
  545. ListView_EnsureVisible(m_hwnd, lvi.iItem, FALSE);
  546. }
  547. }
  548. }
  549. return uRet;
  550. }
  551. WIA_EVENT_HANDLER *
  552. CHandlerList::GetSelectedHandler ()
  553. {
  554. WIA_PUSHFUNCTION(TEXT("CHandlerList::GetSelectedHandler"));
  555. WIA_EVENT_HANDLER *pRet = NULL;
  556. int nIndex = ListView_GetNextItem( m_hwnd, -1, LVNI_SELECTED );
  557. if (-1 != nIndex)
  558. {
  559. LVITEM lvi = {0};
  560. lvi.mask = LVIF_PARAM;
  561. lvi.iItem = nIndex;
  562. if (ListView_GetItem(m_hwnd, &lvi))
  563. {
  564. pRet = reinterpret_cast<WIA_EVENT_HANDLER*>(lvi.lParam);
  565. }
  566. }
  567. return pRet;
  568. }