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.

510 lines
16 KiB

  1. #include "dfpnp.h"
  2. #include <stdio.h>
  3. #include <winuser.h>
  4. #include <tchar.h>
  5. #include <initguid.h>
  6. #include <ioevent.h>
  7. #include <winioctl.h>
  8. #include "cfgmgr32.h"
  9. #include "setupapi.h"
  10. #include "dbt.h"
  11. #include "dfstpdi.h"
  12. #include "drvfull.h"
  13. #include "dfhlprs.h"
  14. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  15. static HDEVNOTIFY g_hdevnotify = NULL;
  16. static DWORD g_cchIndent = 0;
  17. static DWORD g_dwFlags[MAX_FLAGS] = {0};
  18. static DWORD g_dwEvent = 0;
  19. static GUID g_guidVolume =
  20. {0x53f5630d, 0xb6bf, 0x11d0,
  21. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  22. static GUID g_guidUSB =
  23. {0x36fc9e60, 0xc465, 0x11cf,
  24. {0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
  25. static GUID g_guidIntfClass =
  26. {0x53f5630d, 0xb6bf, 0x11d0,
  27. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  28. static GUID g_guid1 =
  29. {0x7373654aL, 0x812a, 0x11d0, {0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f}};
  30. static GUID g_guid2 =
  31. {0xd16a55e8L, 0x1059, 0x11d2, {0x8f, 0xfd, 0x00, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}};
  32. static GUID g_guid3 =
  33. {0xe3c5b178L, 0x105d, 0x11d2, {0x8f, 0xfd, 0x00, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}};
  34. static GUID g_guid4 =
  35. {0xb5804878L, 0x1a96, 0x11d2, {0x8f, 0xfd, 0x00, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}};
  36. static GUID g_guid5 =
  37. {0x50708874L, 0xc9af, 0x11d1, {0x8f, 0xef, 0x00, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}};
  38. static GUID g_guid6 =
  39. {0xae2eed10L, 0x0ba8, 0x11d2, {0x8f, 0xfb, 0x00, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}};
  40. static GUID g_guid7 =
  41. {0x9a8c3d68L, 0xd0cb, 0x11d1, {0x8f, 0xef, 0x00, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}};
  42. static GUID g_guid8 =
  43. {0x2de97f83, 0x4c06, 0x11d2, {0xa5, 0x32, 0x0, 0x60, 0x97, 0x13, 0x5, 0x5a}};
  44. static GUID g_guid9 =
  45. {0x2de97f84, 0x4c06, 0x11d2, {0xa5, 0x32, 0x0, 0x60, 0x97, 0x13, 0x5, 0x5a}};
  46. static GUID g_guid10 =
  47. {0x53f5630d, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  48. static GUID g_guid11 =
  49. {0xd07433c0, 0xa98e, 0x11d2, {0x91, 0x7a, 0x00, 0xa0, 0xc9, 0x06, 0x8f, 0xf3}};
  50. static GUID g_guid12 =
  51. {0xd07433c1, 0xa98e, 0x11d2, {0x91, 0x7a, 0x00, 0xa0, 0xc9, 0x06, 0x8f, 0xf3}};
  52. static GUID g_guid13 =
  53. {0xd0744792, 0xa98e, 0x11d2, {0x91, 0x7a, 0x00, 0xa0, 0xc9, 0x06, 0x8f, 0xf3}};
  54. _sGUID_DESCR _rgintfguidGD2[] =
  55. {
  56. GUID_DESCR(&g_guid1, TEXT("GUID_IO_VOLUME_CHANGE")),
  57. GUID_DESCR(&g_guid2, TEXT("GUID_IO_VOLUME_DISMOUNT")),
  58. GUID_DESCR(&g_guid3, TEXT("GUID_IO_VOLUME_DISMOUNT_FAILED")),
  59. GUID_DESCR(&g_guid4, TEXT("GUID_IO_VOLUME_MOUNT")),
  60. GUID_DESCR(&g_guid5, TEXT("GUID_IO_VOLUME_LOCK")),
  61. GUID_DESCR(&g_guid6, TEXT("GUID_IO_VOLUME_LOCK_FAILED")),
  62. GUID_DESCR(&g_guid7, TEXT("GUID_IO_VOLUME_UNLOCK")),
  63. GUID_DESCR(&g_guid8, TEXT("GUID_IO_VOLUME_NAME_CHANGE")),
  64. GUID_DESCR(&g_guid9, TEXT("GUID_IO_VOLUME_PHYSICAL_CONFIGURATION_CHANGE")),
  65. GUID_DESCR(&g_guid10, TEXT("GUID_IO_VOLUME_DEVICE_INTERFACE")),
  66. GUID_DESCR(&g_guid11, TEXT("GUID_IO_MEDIA_ARRIVAL")),
  67. GUID_DESCR(&g_guid12, TEXT("GUID_IO_MEDIA_REMOVAL")),
  68. GUID_DESCR(&g_guid13, TEXT("GUID_DEVICE_EVENT_RBC")),
  69. };
  70. LRESULT _FakeWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  71. HRESULT _Cleanup(DWORD dwFlags[])
  72. {
  73. if (g_hdevnotify)
  74. {
  75. UnregisterDeviceNotification(g_hdevnotify);
  76. }
  77. if (_IsFlagSet(PNP_WATCHSETUPDI, dwFlags))
  78. {
  79. _CleanupSetupDI();
  80. }
  81. return S_OK;
  82. }
  83. HRESULT _InitNotif(DWORD dwFlags[], HWND hwnd, LPTSTR pszArg, DWORD cchIndent)
  84. {
  85. HRESULT hres = S_OK;
  86. if (_IsFlagSet(PNP_WATCHSETUPDI, dwFlags))
  87. {
  88. DEV_BROADCAST_DEVICEINTERFACE dbdNotifFilter = {0};
  89. // Now register to begin receiving notifications for the comings
  90. // and goings of device interfaces which are members of the
  91. // interface class whose GUID was passed in as the lParam to this
  92. // dialog procedure.
  93. dbdNotifFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  94. dbdNotifFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  95. CopyMemory(&(dbdNotifFilter.dbcc_classguid), &g_guidIntfClass,
  96. sizeof(g_guidIntfClass));
  97. g_hdevnotify = RegisterDeviceNotification(hwnd, &dbdNotifFilter,
  98. DEVICE_NOTIFY_WINDOW_HANDLE);
  99. if (g_hdevnotify)
  100. {
  101. if (_IsFlagSet(PNP_WATCHSETUPDI, dwFlags))
  102. {
  103. hres = _InitNotifSetupDI(dwFlags, cchIndent);
  104. if (FAILED(hres))
  105. {
  106. _Cleanup(dwFlags);
  107. }
  108. }
  109. else
  110. {
  111. hres = E_NOTIMPL;
  112. }
  113. }
  114. else
  115. {
  116. _PrintIndent(cchIndent);
  117. _tprintf(TEXT("RegisterDeviceNotification failed\n"));
  118. _PrintGetLastError(cchIndent);
  119. hres = E_FAIL;
  120. }
  121. }
  122. else
  123. {
  124. if (_IsFlagSet(PNP_HANDLE, dwFlags))
  125. {
  126. HANDLE hVol = CreateFile(
  127. pszArg,
  128. GENERIC_READ | GENERIC_WRITE,
  129. FILE_SHARE_READ | FILE_SHARE_WRITE,
  130. NULL,
  131. OPEN_EXISTING,
  132. 0,
  133. NULL);
  134. if (INVALID_HANDLE_VALUE != hVol)
  135. {
  136. DEV_BROADCAST_HANDLE dbhNotifFilter = {0};
  137. dbhNotifFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
  138. dbhNotifFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
  139. dbhNotifFilter.dbch_handle = hVol;
  140. g_hdevnotify = RegisterDeviceNotification(hwnd, &dbhNotifFilter,
  141. DEVICE_NOTIFY_WINDOW_HANDLE);
  142. if (g_hdevnotify)
  143. {
  144. _PrintIndent(cchIndent);
  145. _tprintf(TEXT("RegisterDeviceNotification SUCCEEDED: %s -> 0x%08X\n"),
  146. pszArg, g_hdevnotify);
  147. }
  148. else
  149. {
  150. _PrintIndent(cchIndent);
  151. _tprintf(TEXT("RegisterDeviceNotification failed\n"));
  152. _PrintGetLastError(cchIndent);
  153. hres = E_FAIL;
  154. }
  155. CloseHandle(hVol);
  156. }
  157. else
  158. {
  159. _PrintIndent(cchIndent);
  160. _tprintf(TEXT("Cannot open volume\n"));
  161. _PrintGetLastError(cchIndent);
  162. hres = E_FAIL;
  163. }
  164. }
  165. else
  166. {
  167. if (_IsFlagSet(PNP_EJECTBUTTON, dwFlags))
  168. {
  169. HANDLE hVol = CreateFile(
  170. pszArg,
  171. GENERIC_READ | GENERIC_WRITE,
  172. FILE_SHARE_READ | FILE_SHARE_WRITE,
  173. NULL,
  174. OPEN_EXISTING,
  175. 0,
  176. NULL);
  177. if (INVALID_HANDLE_VALUE != hVol)
  178. {
  179. DWORD dwDummy;
  180. PREVENT_MEDIA_REMOVAL pmr = {0};
  181. pmr.PreventMediaRemoval = TRUE;
  182. BOOL f = DeviceIoControl(hVol,
  183. IOCTL_STORAGE_MEDIA_REMOVAL, // dwIoControlCode operation to perform
  184. &pmr, // lpInBuffer; must be NULL
  185. sizeof(pmr), // nInBufferSize; must be zero
  186. NULL, // pointer to output buffer
  187. 0, // size of output buffer
  188. &dwDummy, // receives number of bytes returned
  189. NULL);
  190. if (f)
  191. {
  192. // Register for notification
  193. DEV_BROADCAST_HANDLE dbhNotifFilter = {0};
  194. dbhNotifFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
  195. dbhNotifFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
  196. dbhNotifFilter.dbch_handle = hVol;
  197. g_hdevnotify = RegisterDeviceNotification(hwnd, &dbhNotifFilter,
  198. DEVICE_NOTIFY_WINDOW_HANDLE);
  199. if (g_hdevnotify)
  200. {
  201. _PrintIndent(cchIndent);
  202. _tprintf(TEXT("RegisterDeviceNotification SUCCEEDED: %s -> 0x%08X\n"),
  203. pszArg, g_hdevnotify);
  204. }
  205. else
  206. {
  207. _PrintIndent(cchIndent);
  208. _tprintf(TEXT("RegisterDeviceNotification failed\n"));
  209. _PrintGetLastError(cchIndent);
  210. hres = E_FAIL;
  211. }
  212. }
  213. else
  214. {
  215. _PrintIndent(cchIndent);
  216. _tprintf(TEXT("Could not lock the volume, GLE = 0x%08X\n"), GetLastError());
  217. }
  218. CloseHandle(hVol);
  219. }
  220. else
  221. {
  222. _PrintIndent(cchIndent);
  223. _tprintf(TEXT("Cannot open volume\n"));
  224. _PrintGetLastError(cchIndent);
  225. hres = E_FAIL;
  226. }
  227. }
  228. }
  229. }
  230. ///////////////////////////////////////////////////////////////////////////
  231. //
  232. return hres;
  233. }
  234. _sFLAG_DESCR _dbtdevtypeFD[] =
  235. {
  236. FLAG_DESCR(DBT_DEVTYP_OEM),
  237. FLAG_DESCR(DBT_DEVTYP_DEVNODE),
  238. FLAG_DESCR(DBT_DEVTYP_VOLUME),
  239. FLAG_DESCR(DBT_DEVTYP_PORT),
  240. FLAG_DESCR(DBT_DEVTYP_NET),
  241. FLAG_DESCR(DBT_DEVTYP_DEVICEINTERFACE),
  242. FLAG_DESCR(DBT_DEVTYP_HANDLE),
  243. };
  244. _sFLAG_DESCR _dbteventFD[] =
  245. {
  246. FLAG_DESCR(DBT_APPYBEGIN),
  247. FLAG_DESCR(DBT_APPYEND),
  248. FLAG_DESCR(DBT_DEVNODES_CHANGED),
  249. FLAG_DESCR(DBT_QUERYCHANGECONFIG),
  250. FLAG_DESCR(DBT_CONFIGCHANGED),
  251. FLAG_DESCR(DBT_CONFIGCHANGECANCELED),
  252. FLAG_DESCR(DBT_MONITORCHANGE),
  253. FLAG_DESCR(DBT_SHELLLOGGEDON),
  254. FLAG_DESCR(DBT_CONFIGMGAPI32),
  255. FLAG_DESCR(DBT_VXDINITCOMPLETE),
  256. FLAG_DESCR(DBT_VOLLOCKQUERYLOCK),
  257. FLAG_DESCR(DBT_VOLLOCKLOCKTAKEN),
  258. FLAG_DESCR(DBT_VOLLOCKLOCKFAILED),
  259. FLAG_DESCR(DBT_VOLLOCKQUERYUNLOCK),
  260. FLAG_DESCR(DBT_VOLLOCKLOCKRELEASED),
  261. FLAG_DESCR(DBT_VOLLOCKUNLOCKFAILED),
  262. FLAG_DESCR(DBT_NO_DISK_SPACE),
  263. FLAG_DESCR(DBT_LOW_DISK_SPACE),
  264. FLAG_DESCR(DBT_CONFIGMGPRIVATE),
  265. FLAG_DESCR(DBT_DEVICEARRIVAL),
  266. FLAG_DESCR(DBT_DEVICEQUERYREMOVE),
  267. FLAG_DESCR(DBT_DEVICEQUERYREMOVEFAILED),
  268. FLAG_DESCR(DBT_DEVICEREMOVEPENDING),
  269. FLAG_DESCR(DBT_DEVICEREMOVECOMPLETE),
  270. FLAG_DESCR(DBT_DEVICETYPESPECIFIC),
  271. FLAG_DESCR(DBT_CUSTOMEVENT),
  272. FLAG_DESCR(DBT_DEVTYP_OEM),
  273. FLAG_DESCR(DBT_DEVTYP_DEVNODE),
  274. FLAG_DESCR(DBT_DEVTYP_VOLUME),
  275. FLAG_DESCR(DBT_DEVTYP_PORT),
  276. FLAG_DESCR(DBT_DEVTYP_NET),
  277. FLAG_DESCR(DBT_DEVTYP_DEVICEINTERFACE),
  278. FLAG_DESCR(DBT_DEVTYP_HANDLE),
  279. FLAG_DESCR(DBT_VPOWERDAPI),
  280. FLAG_DESCR(DBT_USERDEFINED),
  281. };
  282. HRESULT _HandleNotif(DWORD dwFlags[], DWORD cchIndent, WPARAM wParam, LPARAM lParam)
  283. {
  284. HRESULT hres = E_NOTIMPL;
  285. if (_IsFlagSet(PNP_WATCHSETUPDI, dwFlags))
  286. {
  287. hres = _HandleNotifSetupDI(dwFlags, cchIndent, wParam, lParam);
  288. }
  289. return hres;
  290. }
  291. _sGUID_DESCR _rgintfguidGD[] =
  292. {
  293. GUID_DESCR(&g_guidVolume, TEXT("Volume Device")),
  294. };
  295. LRESULT _FakeWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  296. {
  297. LRESULT lRes;
  298. BOOL fProcessed = FALSE;
  299. switch (uMsg)
  300. {
  301. case WM_DEVICECHANGE:
  302. fProcessed = TRUE;
  303. _PrintIndent(g_cchIndent + 2);
  304. _tprintf(TEXT("Received WM_DEVICECHANGE:\n"));
  305. _PrintIndent(g_cchIndent + 4);
  306. _tprintf(TEXT("wParam: "));
  307. _PrintFlag((DWORD) wParam, _dbteventFD, ARRAYSIZE(_dbteventFD), 0, TRUE,
  308. TRUE, FALSE, FALSE);
  309. _PrintCR();
  310. _PrintIndent(g_cchIndent + 4);
  311. _tprintf(TEXT("lParam: "));
  312. if (lParam)
  313. {
  314. _PrintFlag((((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype),
  315. _dbtdevtypeFD, ARRAYSIZE(_dbtdevtypeFD), 0, TRUE, TRUE,
  316. FALSE, FALSE);
  317. _PrintCR();
  318. _PrintIndent(g_cchIndent + 6);
  319. _tprintf(TEXT("dbch_size: %u"),
  320. (((DEV_BROADCAST_HDR*)lParam)->dbch_size));
  321. _PrintCR();
  322. if (DBT_DEVTYP_DEVICEINTERFACE ==
  323. ((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype)
  324. {
  325. _PrintIndent(g_cchIndent + 6);
  326. _tprintf(TEXT("Interface: "));
  327. _PrintGUIDEx(&(((DEV_BROADCAST_DEVICEINTERFACE*)lParam)->dbcc_classguid),
  328. _rgintfguidGD, ARRAYSIZE(_rgintfguidGD), TRUE, 0);
  329. }
  330. else
  331. {
  332. if (DBT_DEVTYP_HANDLE == ((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype)
  333. {
  334. _PrintIndent(g_cchIndent + 6);
  335. _tprintf(TEXT("dbch_hdevnotify: 0x%08X\n"),
  336. ((DEV_BROADCAST_HANDLE*)lParam)->dbch_hdevnotify);
  337. _PrintIndent(g_cchIndent + 6);
  338. _tprintf(TEXT("Handle notif: "));
  339. _PrintGUIDEx(&(((DEV_BROADCAST_HANDLE*)lParam)->dbch_eventguid),
  340. _rgintfguidGD2, ARRAYSIZE(_rgintfguidGD2), TRUE, 0);
  341. }
  342. }
  343. _HandleNotif(g_dwFlags, g_cchIndent + 4, wParam, lParam);
  344. }
  345. else
  346. {
  347. _tprintf(TEXT("NULL\n"));
  348. }
  349. lRes = TRUE;
  350. ++g_dwEvent;
  351. _PrintCR();
  352. _PrintIndent(g_cchIndent);
  353. _tprintf(TEXT("== (%d) Waiting for events ======================================\n"), g_dwEvent);
  354. break;
  355. case WM_DESTROY:
  356. _Cleanup(g_dwFlags);
  357. fProcessed = FALSE;
  358. break;
  359. default:
  360. fProcessed = FALSE;
  361. break;
  362. }
  363. if (!fProcessed)
  364. {
  365. lRes = DefWindowProc(hWnd, uMsg, wParam, lParam);
  366. }
  367. return lRes;
  368. }
  369. HRESULT _ProcessPNP(DWORD dwFlags[], LPTSTR pszArg, DWORD cchIndent)
  370. {
  371. HRESULT hres = E_FAIL;
  372. WNDCLASSEX wndclass;
  373. HINSTANCE hinst = GetModuleHandle(NULL);
  374. g_cchIndent = cchIndent;
  375. for (DWORD dw = 0; dw < MAX_FLAGS; ++dw)
  376. {
  377. g_dwFlags[dw] = dwFlags[dw];
  378. }
  379. if (hinst)
  380. {
  381. wndclass.cbSize = sizeof(wndclass);
  382. wndclass.style = NULL;
  383. wndclass.lpfnWndProc = _FakeWndProc;
  384. wndclass.cbClsExtra = 0;
  385. wndclass.cbWndExtra = 0;
  386. wndclass.hInstance = hinst;
  387. wndclass.hIcon = NULL;
  388. wndclass.hCursor = NULL;
  389. wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  390. wndclass.lpszMenuName = NULL;
  391. wndclass.lpszClassName = TEXT("FakeWnd");
  392. wndclass.hIconSm = NULL;
  393. if (RegisterClassEx(&wndclass))
  394. {
  395. HWND hwnd = CreateWindow(TEXT("FakeWnd"), TEXT("FakeWnd"),
  396. WS_POPUPWINDOW, 0, 0, 100, 200, NULL, NULL, hinst, NULL);
  397. if (hwnd)
  398. {
  399. hres = _InitNotif(dwFlags, hwnd, pszArg, cchIndent);
  400. if (SUCCEEDED(hres))
  401. {
  402. MSG msg;
  403. _PrintCR();
  404. _PrintIndent(cchIndent);
  405. _tprintf(TEXT("== (%d) Waiting for events ======================================\n"), g_dwEvent);
  406. while (GetMessage(&msg, NULL, 0, 0))
  407. {
  408. DispatchMessage(&msg) ;
  409. }
  410. }
  411. }
  412. }
  413. }
  414. return hres;
  415. }
  416. ///////////////////////////////////////////////////////////////////////////////
  417. //
  418. /*Volume {53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
  419. Mounted device {53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
  420. in \NT\public\sdk\inc\mountmgr.h:
  421. //
  422. // Devices that wish to be mounted should report this GUID in
  423. // IoRegisterDeviceInterface.
  424. //
  425. DEFINE_GUID(MOUNTDEV_MOUNTED_DEVICE_GUID, 0x53f5630d, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
  426. */