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.

610 lines
16 KiB

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <commctrl.h>
  4. #include "resource.h"
  5. #include "shpriv.h"
  6. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  7. HINSTANCE g_hinst = 0;
  8. // {4456E541-7CAB-45ee-AB09-3FF379FA9AA4}
  9. static const CLSID CLSID_App = { 0x4456e541, 0x7cab, 0x45ee, { 0xab, 0x9, 0x3f, 0xf3, 0x79, 0xfa, 0x9a, 0xa4}};
  10. #define INVALID_DWORD ((DWORD)-1)
  11. class CAppDialog : public IClassFactory, public IHWEventHandler, public IQueryCancelAutoPlay
  12. {
  13. public:
  14. CAppDialog();
  15. HRESULT DoModal(HWND hwnd);
  16. // IUnknown
  17. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj);
  18. STDMETHODIMP_(ULONG) AddRef(void);
  19. STDMETHODIMP_(ULONG) Release(void);
  20. // IClassFactory
  21. STDMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv);
  22. STDMETHODIMP LockServer(BOOL fLock);
  23. // IHWEventHandler
  24. STDMETHODIMP Initialize(LPCWSTR pszParams);
  25. STDMETHODIMP HandleEvent(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID,
  26. LPCWSTR pszEventType);
  27. STDMETHODIMP HandleEventWithContent(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID,
  28. LPCWSTR pszEventType, LPCWSTR pszContentTypeHandler, IDataObject* pdataobject);
  29. // IQueryCancelAutoPlay
  30. STDMETHODIMP AllowAutoPlay(LPCWSTR pszPath, DWORD dwContentType, LPCWSTR pszLabel, DWORD dwSerialNumber);
  31. private:
  32. ~CAppDialog();
  33. static INT_PTR CALLBACK s_DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  34. INT_PTR CALLBACK DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
  35. void _OnInitDlg();
  36. void _OnDestroyDlg();
  37. LRESULT _OnQueryCancelAutoplay(WPARAM wParam, LPARAM lParam);
  38. void _OnQueryCancelAutoplayWindowsMessageChanged();
  39. void _OnQueryCancelAutoplayIntfChanged();
  40. void _OnAutoplayChanged();
  41. void _PrintMsg(LPCWSTR pszMsg);
  42. LONG _cRef;
  43. DWORD _dwRegisterClass;
  44. DWORD _dwRegisterROT;
  45. DWORD _dwRegisterROT2;
  46. HWND _hdlg;
  47. };
  48. CAppDialog::CAppDialog() : _cRef(1), _dwRegisterClass(INVALID_DWORD), _dwRegisterROT(INVALID_DWORD), _dwRegisterROT2(INVALID_DWORD), _hdlg(NULL)//, _hdlgLV(NULL)
  49. {
  50. InitCommonControls();
  51. }
  52. CAppDialog::~CAppDialog()
  53. {
  54. }
  55. HRESULT CAppDialog::QueryInterface(REFIID riid, void **ppv)
  56. {
  57. HRESULT hr;
  58. if (riid == IID_IUnknown)
  59. {
  60. *ppv = static_cast<IClassFactory *>(this);
  61. AddRef();
  62. hr = S_OK;
  63. }
  64. else if (riid == IID_IClassFactory)
  65. {
  66. *ppv = static_cast<IClassFactory *>(this);
  67. AddRef();
  68. hr = S_OK;
  69. }
  70. else if (riid == IID_IHWEventHandler)
  71. {
  72. *ppv = static_cast<IHWEventHandler *>(this);
  73. AddRef();
  74. hr = S_OK;
  75. }
  76. else if (riid == IID_IQueryCancelAutoPlay)
  77. {
  78. *ppv = static_cast<IQueryCancelAutoPlay *>(this);
  79. AddRef();
  80. hr = S_OK;
  81. }
  82. else
  83. {
  84. *ppv = NULL;
  85. hr = E_NOINTERFACE;
  86. }
  87. return hr;
  88. }
  89. STDMETHODIMP_(ULONG) CAppDialog::AddRef(void)
  90. {
  91. return InterlockedIncrement(&_cRef);
  92. }
  93. STDMETHODIMP_(ULONG) CAppDialog::Release()
  94. {
  95. if (InterlockedDecrement(&_cRef))
  96. return _cRef;
  97. delete this;
  98. return 0;
  99. }
  100. STDMETHODIMP CAppDialog::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
  101. {
  102. if (punkOuter)
  103. {
  104. *ppv = NULL;
  105. return CLASS_E_NOAGGREGATION;
  106. }
  107. return QueryInterface(riid, ppv);
  108. }
  109. STDMETHODIMP CAppDialog::LockServer(BOOL /*fLock*/)
  110. {
  111. return S_OK;
  112. }
  113. STDMETHODIMP CAppDialog::Initialize(LPCWSTR /*pszParams*/)
  114. {
  115. return S_OK;
  116. }
  117. STDMETHODIMP CAppDialog::HandleEvent(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID,
  118. LPCWSTR pszEventType)
  119. {
  120. WCHAR szText[4096];
  121. wsprintf(szText, TEXT("%s, %s, %s"), pszDeviceID, pszAltDeviceID, pszEventType);
  122. _PrintMsg(szText);
  123. return S_OK;
  124. }
  125. STDMETHODIMP CAppDialog::HandleEventWithContent(LPCWSTR /*pszDeviceID*/, LPCWSTR /*pszAltDeviceID*/,
  126. LPCWSTR /*pszEventType*/, LPCWSTR /*pszContentTypeHandler*/, IDataObject* /*pdataobject*/)
  127. {
  128. return S_OK;
  129. }
  130. void CAppDialog::_PrintMsg(LPCWSTR pszMsg)
  131. {
  132. SendMessage(GetDlgItem(_hdlg, IDC_EDIT1), EM_SETSEL, (WPARAM)-2, (WPARAM)-2);
  133. SendMessage(GetDlgItem(_hdlg, IDC_EDIT1), EM_REPLACESEL, 0, (LPARAM)pszMsg);
  134. SendMessage(GetDlgItem(_hdlg, IDC_EDIT1), EM_SETSEL, (WPARAM)-2, (WPARAM)-2);
  135. SendMessage(GetDlgItem(_hdlg, IDC_EDIT1), EM_REPLACESEL, 0, (LPARAM)TEXT("\r\n"));
  136. }
  137. DWORD _BuildFilterFlag(HWND hwndDlg, int iResourceBase)
  138. {
  139. DWORD dwRet = 0;
  140. for (int i = 0; i < 5; ++i)
  141. {
  142. if (BST_CHECKED == Button_GetCheck(GetDlgItem(hwndDlg, iResourceBase + (1 << (i + 1)))))
  143. {
  144. dwRet |= (1 << (i + 1));
  145. }
  146. }
  147. return dwRet;
  148. }
  149. STDMETHODIMP CAppDialog::AllowAutoPlay(LPCWSTR pszPath, DWORD dwContentType,
  150. LPCWSTR /*pszLabel*/, DWORD /*dwSerialNumber*/)
  151. {
  152. HRESULT hr = S_OK;
  153. WCHAR szText[4096];
  154. wsprintf(szText, TEXT("IQueryCancelAutoPlay::AllowAutoPlay called for drive '%s' and ContentType (0x%08X)"),
  155. pszPath, dwContentType);
  156. _PrintMsg(szText);
  157. // Are we registered?
  158. if (INVALID_DWORD != _dwRegisterROT2)
  159. {
  160. // Yes
  161. WCHAR szDrive[MAX_PATH];
  162. if (GetDlgItemText(_hdlg, IDC_IQCA_EDIT, szDrive, ARRAYSIZE(szDrive)))
  163. {
  164. // Same drive?
  165. if (!lstrcmpi(szDrive, pszPath))
  166. {
  167. // Yes
  168. DWORD dwFilter = _BuildFilterFlag(_hdlg, 3000);
  169. if (dwFilter & dwContentType)
  170. {
  171. wsprintf(szText, TEXT(" Filter (0x%08X) matches ContentType -> Cancel AutoRun! (S_FALSE)"),
  172. dwFilter);
  173. hr = S_FALSE;
  174. }
  175. else
  176. {
  177. wsprintf(szText, TEXT(" Filter (0x%08X) does *NOT* match ContentType -> No cancel (S_OK)"));
  178. }
  179. _PrintMsg(szText);
  180. }
  181. }
  182. }
  183. return hr;
  184. }
  185. HRESULT CAppDialog::DoModal(HWND hwnd)
  186. {
  187. DialogBoxParam(g_hinst, MAKEINTRESOURCE(IDD_DIALOG1), hwnd, s_DlgProc, (LPARAM)this);
  188. return S_OK;
  189. }
  190. typedef HRESULT (*CREATEHARDWAREEVENTMONIKER)(REFCLSID clsid, LPCTSTR pszEventHandler, IMoniker **ppmoniker);
  191. void CAppDialog::_OnInitDlg()
  192. {
  193. SetDlgItemText(_hdlg, IDC_AUTOPLAY_CLSID_EDIT, TEXT("{4456E541-7CAB-45ee-AB09-3FF379FA9AA4}"));
  194. }
  195. void CAppDialog::_OnDestroyDlg()
  196. {
  197. if (INVALID_DWORD != _dwRegisterClass)
  198. {
  199. CoRevokeClassObject(_dwRegisterClass);
  200. _dwRegisterClass = INVALID_DWORD;
  201. }
  202. if (INVALID_DWORD != _dwRegisterROT)
  203. {
  204. IRunningObjectTable *prot;
  205. if (SUCCEEDED(GetRunningObjectTable(0, &prot)))
  206. {
  207. prot->Revoke(_dwRegisterROT);
  208. _dwRegisterROT = INVALID_DWORD;
  209. prot->Release();
  210. }
  211. }
  212. if (INVALID_DWORD != _dwRegisterROT2)
  213. {
  214. IRunningObjectTable *prot;
  215. if (SUCCEEDED(GetRunningObjectTable(0, &prot)))
  216. {
  217. prot->Revoke(_dwRegisterROT2);
  218. _dwRegisterROT2 = INVALID_DWORD;
  219. prot->Release();
  220. }
  221. }
  222. }
  223. INT_PTR CALLBACK CAppDialog::s_DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  224. {
  225. CAppDialog *pcd = (CAppDialog*) GetWindowLongPtr(hdlg, DWLP_USER);
  226. if (uMsg == WM_INITDIALOG)
  227. {
  228. pcd = (CAppDialog *) lParam;
  229. pcd->_hdlg = hdlg;
  230. SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR) pcd);
  231. }
  232. return pcd ? pcd->DlgProc(uMsg, wParam, lParam) : FALSE;
  233. }
  234. LRESULT CAppDialog::_OnQueryCancelAutoplay(WPARAM wParam, LPARAM lParam)
  235. {
  236. LRESULT lRet = 0;
  237. WCHAR szText[4096];
  238. wsprintf(szText, TEXT("QueryCancelAutoPlay Windows Message Received for drive '0x%08X' and ContentType (0x%08X)"),
  239. wParam, lParam);
  240. _PrintMsg(szText);
  241. if (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_QCA_CHECKBOX)))
  242. {
  243. WCHAR szDrive[MAX_PATH];
  244. if (GetDlgItemText(_hdlg, IDC_QCA_EDIT, szDrive, ARRAYSIZE(szDrive)))
  245. {
  246. int iDrive = -1;
  247. if ((TEXT('a') <= szDrive[0]) && (TEXT('z') >= szDrive[0]))
  248. {
  249. iDrive = szDrive[0] - TEXT('a');
  250. }
  251. else
  252. {
  253. if ((TEXT('A') <= szDrive[0]) && (TEXT('Z') >= szDrive[0]))
  254. {
  255. iDrive = szDrive[0] - TEXT('A');
  256. }
  257. }
  258. if (-1 != iDrive)
  259. {
  260. if (wParam == (WPARAM)iDrive)
  261. {
  262. DWORD dwFilter = _BuildFilterFlag(_hdlg, IDC_QCA_CHECKBOX);
  263. lRet = (lParam & dwFilter);
  264. if (lRet)
  265. {
  266. wsprintf(szText, TEXT(" Filter (0x%08X) matches ContentType -> Cancel AutoRun! (ret = 0x%08X)"),
  267. dwFilter, lRet);
  268. }
  269. else
  270. {
  271. wsprintf(szText, TEXT(" Filter (0x%08X) does *NOT* match ContentType -> No cancel (ret = 0x%08X)"),
  272. dwFilter, lRet);
  273. }
  274. }
  275. _PrintMsg(szText);
  276. }
  277. }
  278. }
  279. return lRet;
  280. }
  281. typedef HRESULT (*SHCREATEQUERYCANCELAUTOPLAYMONIKER)(IMoniker** ppmoniker);
  282. void CAppDialog::_OnQueryCancelAutoplayIntfChanged()
  283. {
  284. BOOL fEnable = (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_IQCA_CHECKBOX)));
  285. EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_EDIT ), fEnable);
  286. EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_AUTORUNINF_CHECKBOX), fEnable);
  287. EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_AUDIOCD_CHECKBOX ), fEnable);
  288. EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_DVDMOVIE_CHECKBOX ), fEnable);
  289. EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_BLANKCD_CHECKBOX ), fEnable);
  290. EnableWindow(GetDlgItem(_hdlg, IDC_IQCA_BLANKDVD_CHECKBOX ), fEnable);
  291. // Are we registered?
  292. if (INVALID_DWORD == _dwRegisterROT2)
  293. {
  294. // Nope
  295. // Do we need to register?
  296. if (fEnable)
  297. {
  298. // Yes
  299. HINSTANCE hinstShell32 = LoadLibrary(TEXT("shell32.dll"));
  300. if (hinstShell32)
  301. {
  302. SHCREATEQUERYCANCELAUTOPLAYMONIKER fct = (SHCREATEQUERYCANCELAUTOPLAYMONIKER)GetProcAddress(
  303. hinstShell32, "SHCreateQueryCancelAutoPlayMoniker");
  304. if (fct)
  305. {
  306. IMoniker* pmoniker;
  307. HRESULT hr = fct(&pmoniker);
  308. if (SUCCEEDED(hr))
  309. {
  310. IRunningObjectTable *prot;
  311. if (SUCCEEDED(GetRunningObjectTable(0, &prot)))
  312. {
  313. prot->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE,
  314. static_cast<IClassFactory *>(this), pmoniker, &_dwRegisterROT2);
  315. _PrintMsg(TEXT("Registered for IQueryCancelAutoplay!"));
  316. prot->Release();
  317. }
  318. pmoniker->Release();
  319. }
  320. }
  321. FreeLibrary(hinstShell32);
  322. }
  323. }
  324. }
  325. else
  326. {
  327. // Yes
  328. // Do we need to unregister?
  329. if (!fEnable)
  330. {
  331. // Yes
  332. IRunningObjectTable *prot;
  333. if (SUCCEEDED(GetRunningObjectTable(0, &prot)))
  334. {
  335. prot->Revoke(_dwRegisterROT2);
  336. _PrintMsg(TEXT("Unregistered for IQueryCancelAutoplay!"));
  337. _dwRegisterROT2 = INVALID_DWORD;
  338. prot->Release();
  339. }
  340. }
  341. }
  342. }
  343. void CAppDialog::_OnQueryCancelAutoplayWindowsMessageChanged()
  344. {
  345. BOOL fEnable = (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_QCA_CHECKBOX)));
  346. EnableWindow(GetDlgItem(_hdlg, IDC_QCA_EDIT ), fEnable);
  347. EnableWindow(GetDlgItem(_hdlg, IDC_QCA_AUTORUNINF_CHECKBOX), fEnable);
  348. EnableWindow(GetDlgItem(_hdlg, IDC_QCA_AUDIOCD_CHECKBOX ), fEnable);
  349. EnableWindow(GetDlgItem(_hdlg, IDC_QCA_DVDMOVIE_CHECKBOX ), fEnable);
  350. EnableWindow(GetDlgItem(_hdlg, IDC_QCA_BLANKCD_CHECKBOX ), fEnable);
  351. EnableWindow(GetDlgItem(_hdlg, IDC_QCA_BLANKDVD_CHECKBOX ), fEnable);
  352. }
  353. void CAppDialog::_OnAutoplayChanged()
  354. {
  355. BOOL fEnable = (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_AUTOPLAY_CHECKBOX)));
  356. BOOL fRegister = (BST_CHECKED == Button_GetCheck(GetDlgItem(_hdlg, IDC_AUTOPLAY_ONOFF_CHECKBOX)));
  357. EnableWindow(GetDlgItem(_hdlg, IDC_AUTOPLAY_EVENTHANDLER_EDIT), fEnable);
  358. EnableWindow(GetDlgItem(_hdlg, IDC_AUTOPLAY_CLSID_EDIT), fEnable);
  359. EnableWindow(GetDlgItem(_hdlg, IDC_AUTOPLAY_ONOFF_CHECKBOX), fEnable);
  360. // Are we registered?
  361. if (INVALID_DWORD == _dwRegisterROT)
  362. {
  363. // Nope
  364. // Do we need to register?
  365. if (fEnable && fRegister)
  366. {
  367. // Yes
  368. HINSTANCE hinstShSvcs = LoadLibrary(TEXT("shsvcs.dll"));
  369. if (hinstShSvcs)
  370. {
  371. CREATEHARDWAREEVENTMONIKER fct = (CREATEHARDWAREEVENTMONIKER)GetProcAddress(
  372. hinstShSvcs, "CreateHardwareEventMoniker");
  373. if (fct)
  374. {
  375. WCHAR szEventHandler[64];
  376. WCHAR szCLSID[39];
  377. IMoniker* pmoniker;
  378. if (GetDlgItemText(_hdlg, IDC_AUTOPLAY_EVENTHANDLER_EDIT, szEventHandler,
  379. ARRAYSIZE(szEventHandler)))
  380. {
  381. if (GetDlgItemText(_hdlg, IDC_AUTOPLAY_CLSID_EDIT, szCLSID,
  382. ARRAYSIZE(szCLSID)))
  383. {
  384. CLSID clsid;
  385. HRESULT hr = CLSIDFromString(szCLSID, &clsid);
  386. if (SUCCEEDED(hr))
  387. {
  388. hr = fct(clsid, szEventHandler, &pmoniker);
  389. if (SUCCEEDED(hr))
  390. {
  391. IRunningObjectTable *prot;
  392. if (SUCCEEDED(GetRunningObjectTable(0, &prot)))
  393. {
  394. if (SUCCEEDED(prot->Register(ROTFLAGS_ALLOWANYCLIENT | ROTFLAGS_REGISTRATIONKEEPSALIVE,
  395. static_cast<IClassFactory *>(this), pmoniker, &_dwRegisterROT)))
  396. {
  397. _PrintMsg(TEXT("Registered to Cancel Autoplay!"));
  398. }
  399. prot->Release();
  400. }
  401. pmoniker->Release();
  402. }
  403. /* CoRegisterClassObject(CLSID_App, static_cast<IClassFactory *>(this),
  404. CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &_dwRegisterClass);*/
  405. }
  406. }
  407. }
  408. }
  409. FreeLibrary(hinstShSvcs);
  410. }
  411. }
  412. }
  413. else
  414. {
  415. // Yes
  416. // Do we need to unregister?
  417. if (!(fEnable && fRegister))
  418. {
  419. // Yes
  420. IRunningObjectTable *prot;
  421. if (SUCCEEDED(GetRunningObjectTable(0, &prot)))
  422. {
  423. prot->Revoke(_dwRegisterROT);
  424. _PrintMsg(TEXT("Unregistered to Cancel Autoplay!"));
  425. _dwRegisterROT = INVALID_DWORD;
  426. prot->Release();
  427. }
  428. }
  429. }
  430. }
  431. INT_PTR CAppDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  432. {
  433. static UINT uQCA = 0;
  434. if (!uQCA)
  435. {
  436. uQCA = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  437. }
  438. if (uMsg == uQCA)
  439. {
  440. INT_PTR iRet= _OnQueryCancelAutoplay(wParam, lParam);
  441. SetWindowLongPtr(_hdlg, DWLP_MSGRESULT, iRet);
  442. return TRUE;
  443. }
  444. else
  445. {
  446. switch (uMsg)
  447. {
  448. case WM_INITDIALOG:
  449. _OnInitDlg();
  450. break;
  451. case WM_COMMAND:
  452. switch (LOWORD(wParam))
  453. {
  454. case IDCANCEL:
  455. return EndDialog(_hdlg, TRUE);
  456. case IDC_QCA_CHECKBOX:
  457. _OnQueryCancelAutoplayWindowsMessageChanged();
  458. return FALSE;
  459. case IDC_IQCA_CHECKBOX:
  460. _OnQueryCancelAutoplayIntfChanged();
  461. return FALSE;
  462. case IDC_AUTOPLAY_CHECKBOX:
  463. _OnAutoplayChanged();
  464. return FALSE;
  465. case IDC_AUTOPLAY_ONOFF_CHECKBOX:
  466. _OnAutoplayChanged();
  467. return FALSE;
  468. }
  469. break;
  470. case WM_DESTROY:
  471. _OnDestroyDlg();
  472. break;
  473. default:
  474. return FALSE;
  475. }
  476. }
  477. return TRUE;
  478. }
  479. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nCmdShow*/)
  480. {
  481. g_hinst = hInstance;
  482. HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
  483. if (SUCCEEDED(hr))
  484. {
  485. CAppDialog *pdlg = new CAppDialog();
  486. if (pdlg)
  487. {
  488. pdlg->DoModal(NULL);
  489. pdlg->Release();
  490. }
  491. CoUninitialize();
  492. }
  493. return 0;
  494. }