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.

879 lines
24 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 2000
  6. //
  7. // File: init.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "hotplug.h"
  11. #define HOTPLUG_CLASS_NAME TEXT("HotPlugClass")
  12. #if BUBBLES
  13. #define SURPRISE_UNDOCK_TIMER TEXT("Local\\HotPlug_SurpriseUndockTimer_{25126bc2-1ab0-4494-8b6d-e4034cb9c24a}")
  14. #define SURPRISE_UNDOCK_EVENT TEXT("Local\\HotPlug_SurpriseUndockEvent_{25126bc2-1ab0-4494-8b6d-e4034cb9c24a}")
  15. #endif
  16. void
  17. HotPlugDeviceTree(
  18. HWND hwndParent,
  19. PTCHAR MachineName,
  20. BOOLEAN HotPlugTree
  21. )
  22. {
  23. CONFIGRET ConfigRet;
  24. DEVICETREE DeviceTree;
  25. memset(&DeviceTree, 0, sizeof(DeviceTree));
  26. if (MachineName) {
  27. lstrcpy(DeviceTree.MachineName, MachineName);
  28. ConfigRet = CM_Connect_Machine(MachineName, &DeviceTree.hMachine);
  29. if (ConfigRet != CR_SUCCESS) {
  30. return;
  31. }
  32. }
  33. DeviceTree.HotPlugTree = HotPlugTree;
  34. InitializeListHead(&DeviceTree.ChildSiblingList);
  35. DeviceTree.HideUI = FALSE;
  36. DialogBoxParam(hHotPlug,
  37. MAKEINTRESOURCE(DLG_DEVTREE),
  38. hwndParent,
  39. (DLGPROC)DevTreeDlgProc,
  40. (LPARAM)&DeviceTree
  41. );
  42. if (DeviceTree.hMachine) {
  43. CM_Disconnect_Machine(DeviceTree.hMachine);
  44. }
  45. return;
  46. }
  47. BOOL
  48. HotPlugEjectDevice(
  49. HWND hwndParent,
  50. PTCHAR DeviceInstanceId
  51. )
  52. /*++
  53. Routine Description:
  54. Exported Entry point from hotplug.dll to eject a specific Device Instance.
  55. Arguments:
  56. hwndParent - Window handle of the top-level window to use for any UI related
  57. to installing the device.
  58. DeviceInstanceId - Supplies the ID of the device instance. This is the registry
  59. path (relative to the Enum branch) of the device instance key.
  60. Return Value:
  61. BOOL TRUE for success (does not mean device was ejected or not),
  62. FALSE unexpected error. GetLastError returns the winerror code.
  63. --*/
  64. {
  65. DEVNODE DevNode;
  66. CONFIGRET ConfigRet;
  67. if ((ConfigRet = CM_Locate_DevNode(&DevNode,
  68. DeviceInstanceId,
  69. 0)) == CR_SUCCESS) {
  70. ConfigRet = CM_Request_Device_Eject_Ex(DevNode,
  71. NULL,
  72. NULL,
  73. 0,
  74. 0,
  75. NULL);
  76. }
  77. SetLastError(ConfigRet);
  78. return (ConfigRet == CR_SUCCESS);
  79. }
  80. #if UNDOCK_WARNING
  81. DWORD
  82. WINAPI
  83. HotPlugSurpriseWarnW(
  84. HWND hwnd,
  85. HINSTANCE hInst,
  86. LPWSTR szCmd,
  87. int nShow
  88. )
  89. {
  90. HANDLE hPipeRead;
  91. HANDLE hEvent;
  92. SURPRISE_WARN_COLLECTION surpriseWarnCollection;
  93. MSG Msg;
  94. WNDCLASS wndClass;
  95. HWND hSurpriseWarnWnd;
  96. HANDLE hHotplugIconEvent;
  97. HANDLE hSurpriseUndockEventTimer = NULL;
  98. HANDLE hSurpriseUndockEvent = NULL;
  99. LARGE_INTEGER liDelayTime;
  100. DWORD result, handleCount;
  101. HANDLE handleArray[2];
  102. //
  103. // Open the specified name pipe and event.
  104. //
  105. if (!OpenPipeAndEventHandles(szCmd,
  106. &hPipeRead,
  107. &hEvent)) {
  108. return 1;
  109. }
  110. ASSERT((hEvent != NULL) && (hEvent != INVALID_HANDLE_VALUE));
  111. ASSERT((hPipeRead != NULL) && (hPipeRead != INVALID_HANDLE_VALUE));
  112. DeviceCollectionBuildFromPipe(
  113. hPipeRead,
  114. CT_SURPRISE_REMOVAL_WARNING,
  115. (PDEVICE_COLLECTION) &surpriseWarnCollection
  116. );
  117. surpriseWarnCollection.SuppressSurprise = FALSE;
  118. #if BUBBLES
  119. //
  120. // This is how long the bubble should watch for a surprise undock (in secs)
  121. //
  122. surpriseWarnCollection.MaxWaitForDock = BUBBLE_SUPPRESSION_TIME;
  123. #endif
  124. //
  125. // We are finished reading from the pipe, so close the handle and tell
  126. // umpnpmgr that it can continue.
  127. //
  128. CloseHandle(hPipeRead);
  129. SetEvent(hEvent);
  130. CloseHandle(hEvent);
  131. //
  132. // If we have any devices then bring up the surprise removal dialog
  133. //
  134. if (surpriseWarnCollection.NumDevices) {
  135. #if BUBBLES
  136. //
  137. // A surprise removal event occured. Make sure our waitable timer is
  138. // up.
  139. //
  140. OpenGetSurpriseUndockObjects(
  141. &hSurpriseUndockEventTimer,
  142. &hSurpriseUndockEvent
  143. );
  144. #endif // BUBBLES
  145. if (surpriseWarnCollection.DockInList) {
  146. #if BUBBLES
  147. //
  148. // Tell anyone out there waiting to put up their bubble to bail
  149. //
  150. if (hSurpriseUndockEvent) {
  151. PulseEvent(hSurpriseUndockEvent);
  152. }
  153. if (hSurpriseUndockEventTimer) {
  154. //
  155. // We suppress bubbles for some period of time after a surprise
  156. // undock event.
  157. //
  158. liDelayTime.QuadPart = -10000000 * BUBBLE_SUPPRESSION_TIME;
  159. SetWaitableTimer(
  160. hSurpriseUndockEventTimer,
  161. &liDelayTime,
  162. 0,
  163. NULL,
  164. NULL,
  165. FALSE
  166. );
  167. }
  168. #endif // BUBBLES
  169. DialogBoxParam(hHotPlug,
  170. MAKEINTRESOURCE(DLG_SURPRISEUNDOCK),
  171. NULL,
  172. SurpriseWarnDlgProc,
  173. (LPARAM)&surpriseWarnCollection
  174. );
  175. } else {
  176. #if BUBBLES
  177. if (!GetClassInfo(hHotPlug, HOTPLUG_CLASS_NAME, &wndClass)) {
  178. memset(&wndClass, 0, sizeof(wndClass));
  179. wndClass.lpfnWndProc = SurpriseWarnBalloonProc;
  180. wndClass.hInstance = hHotPlug;
  181. wndClass.lpszClassName = HOTPLUG_CLASS_NAME;
  182. if (!RegisterClass(&wndClass)) {
  183. goto clean0;
  184. }
  185. }
  186. //
  187. // In order to prevent multiple hotplug icons on the tray and multiple surprise
  188. // removals stepping on each other, we will create a named event that will be
  189. // used to serialize the surprise removal UI.
  190. //
  191. // Note that if we can't create the event for some reason then we will just
  192. // display the UI. This might cause multiple hotplug icons, but it is
  193. // better than not displaying any UI at all.
  194. //
  195. hHotplugIconEvent = CreateEvent(NULL,
  196. FALSE,
  197. TRUE,
  198. TEXT("Local\\HotPlug_TaskBarIcon_Event")
  199. );
  200. if (hHotplugIconEvent) {
  201. handleArray[0] = hHotplugIconEvent;
  202. handleArray[1] = hSurpriseUndockEvent;
  203. handleCount = hSurpriseUndockEvent ? 2 : 1;
  204. //
  205. // Wait for our chance to put up a hotplug icon. Note that we
  206. // will throw our message away if an undock happened recently.
  207. // hSurpriseUndockEvent tells us we should throw away this
  208. // UI attempt.
  209. //
  210. result = WaitForMultipleObjects(
  211. handleCount,
  212. handleArray,
  213. FALSE,
  214. INFINITE
  215. );
  216. if (result == (WAIT_OBJECT_0 + 1)) {
  217. //
  218. // A surprise undock occured, throw it back.
  219. //
  220. goto clean0;
  221. } else if (hSurpriseUndockEventTimer) {
  222. result = WaitForSingleObject(hSurpriseUndockEventTimer, 0);
  223. if (result == WAIT_TIMEOUT) {
  224. //
  225. // We missed the kill event but an undock occured
  226. // recently. Throw this one back.
  227. //
  228. SetEvent(hHotplugIconEvent);
  229. CloseHandle(hHotplugIconEvent);
  230. goto clean0;
  231. }
  232. }
  233. }
  234. //
  235. // First disable the hotplug service so that the icon will go away from
  236. // the taskbar. We do this just in case there are any other hotplug devices
  237. // in the machine.
  238. //
  239. SysTray_EnableService(STSERVICE_HOTPLUG, FALSE);
  240. hSurpriseWarnWnd = CreateWindowEx(WS_EX_TOOLWINDOW,
  241. HOTPLUG_CLASS_NAME,
  242. TEXT(""),
  243. WS_DLGFRAME | WS_BORDER | WS_DISABLED,
  244. CW_USEDEFAULT,
  245. CW_USEDEFAULT,
  246. 0,
  247. 0,
  248. NULL,
  249. NULL,
  250. hHotPlug,
  251. (LPVOID)&surpriseWarnCollection
  252. );
  253. if (hSurpriseWarnWnd != NULL) {
  254. while (IsWindow(hSurpriseWarnWnd)) {
  255. if (GetMessage(&Msg, NULL, 0, 0)) {
  256. TranslateMessage(&Msg);
  257. DispatchMessage(&Msg);
  258. }
  259. }
  260. }
  261. //
  262. // Set the Event so the next surprise removal process can go to work
  263. // and then close the event handle.
  264. //
  265. if (hHotplugIconEvent) {
  266. SetEvent(hHotplugIconEvent);
  267. CloseHandle(hHotplugIconEvent);
  268. }
  269. //
  270. // Re-enable the hotplug service so that the icon can show back up in
  271. // the taskbar if we have any hotplug devices.
  272. //
  273. SysTray_EnableService(STSERVICE_HOTPLUG, TRUE);
  274. #endif // BUBBLES
  275. }
  276. }
  277. #if BUBBLES
  278. clean0:
  279. if (hSurpriseUndockEventTimer) {
  280. CloseHandle(hSurpriseUndockEventTimer);
  281. }
  282. if (hSurpriseUndockEvent) {
  283. CloseHandle(hSurpriseUndockEvent);
  284. }
  285. if (surpriseWarnCollection.SuppressSurprise) {
  286. DeviceCollectionSuppressSurprise(
  287. (PDEVICE_COLLECTION) &surpriseWarnCollection
  288. );
  289. }
  290. #endif
  291. DeviceCollectionDestroy(
  292. (PDEVICE_COLLECTION) &surpriseWarnCollection
  293. );
  294. return 1;
  295. }
  296. #endif // UNDOCK_WARNING
  297. DWORD
  298. WINAPI
  299. HotPlugRemovalVetoedW(
  300. HWND hwnd,
  301. HINSTANCE hInst,
  302. LPWSTR szCmd,
  303. int nShow
  304. )
  305. {
  306. return HandleVetoedOperation(szCmd, VETOED_REMOVAL);
  307. }
  308. DWORD
  309. WINAPI
  310. HotPlugEjectVetoedW(
  311. HWND hwnd,
  312. HINSTANCE hInst,
  313. LPWSTR szCmd,
  314. int nShow
  315. )
  316. {
  317. return HandleVetoedOperation(szCmd, VETOED_EJECT);
  318. }
  319. DWORD
  320. WINAPI
  321. HotPlugStandbyVetoedW(
  322. HWND hwnd,
  323. HINSTANCE hInst,
  324. LPWSTR szCmd,
  325. int nShow
  326. )
  327. {
  328. return HandleVetoedOperation(szCmd, VETOED_STANDBY);
  329. }
  330. DWORD
  331. WINAPI
  332. HotPlugHibernateVetoedW(
  333. HWND hwnd,
  334. HINSTANCE hInst,
  335. LPWSTR szCmd,
  336. int nShow
  337. )
  338. {
  339. return HandleVetoedOperation(szCmd, VETOED_HIBERNATE);
  340. }
  341. DWORD
  342. WINAPI
  343. HotPlugWarmEjectVetoedW(
  344. HWND hwnd,
  345. HINSTANCE hInst,
  346. LPWSTR szCmd,
  347. int nShow
  348. )
  349. {
  350. return HandleVetoedOperation(szCmd, VETOED_WARM_EJECT);
  351. }
  352. DWORD
  353. WINAPI
  354. HandleVetoedOperation(
  355. LPWSTR szCmd,
  356. VETOED_OPERATION VetoedOperation
  357. )
  358. {
  359. HANDLE hPipeRead;
  360. HANDLE hEvent;
  361. PNP_VETO_TYPE vetoType;
  362. DWORD bytesRead;
  363. VETO_DEVICE_COLLECTION removalVetoCollection;
  364. //
  365. // Open the specified name pipe and event.
  366. //
  367. if (!OpenPipeAndEventHandles(szCmd,
  368. &hPipeRead,
  369. &hEvent)) {
  370. return 1;
  371. }
  372. ASSERT((hEvent != NULL) && (hEvent != INVALID_HANDLE_VALUE));
  373. ASSERT((hPipeRead != NULL) && (hPipeRead != INVALID_HANDLE_VALUE));
  374. //
  375. // The first DWORD is the VetoType
  376. //
  377. if (!ReadFile(hPipeRead,
  378. (LPVOID)&vetoType,
  379. sizeof(PNP_VETO_TYPE),
  380. &bytesRead,
  381. NULL)) {
  382. CloseHandle(hPipeRead);
  383. SetEvent(hEvent);
  384. CloseHandle(hEvent);
  385. return 1;
  386. }
  387. //
  388. // Now drain all the removal strings. Note that some of them will be
  389. // device instance paths (definitely the first)
  390. //
  391. DeviceCollectionBuildFromPipe(
  392. hPipeRead,
  393. CT_VETOED_REMOVAL_NOTIFICATION,
  394. (PDEVICE_COLLECTION) &removalVetoCollection
  395. );
  396. //
  397. // We are finished reading from the pipe, so close the handle and tell
  398. // umpnpmgr that it can continue.
  399. //
  400. CloseHandle(hPipeRead);
  401. SetEvent(hEvent);
  402. CloseHandle(hEvent);
  403. //
  404. // There should always be one device as that is the device who's removal
  405. // was vetoed.
  406. //
  407. ASSERT(removalVetoCollection.dc.NumDevices);
  408. //
  409. // Invent the VetoedOperation "VETOED_UNDOCK" from an eject containing
  410. // another dock.
  411. //
  412. if (removalVetoCollection.dc.DockInList) {
  413. if (VetoedOperation == VETOED_EJECT) {
  414. VetoedOperation = VETOED_UNDOCK;
  415. } else if (VetoedOperation == VETOED_WARM_EJECT) {
  416. VetoedOperation = VETOED_WARM_UNDOCK;
  417. }
  418. }
  419. removalVetoCollection.VetoType = vetoType;
  420. removalVetoCollection.VetoedOperation = VetoedOperation;
  421. VetoedRemovalUI(&removalVetoCollection);
  422. DeviceCollectionDestroy(
  423. (PDEVICE_COLLECTION) &removalVetoCollection
  424. );
  425. return 1;
  426. }
  427. DWORD
  428. WINAPI
  429. HotPlugSafeRemovalNotificationW(
  430. HWND hwnd,
  431. HINSTANCE hInst,
  432. LPWSTR szCmd,
  433. int nShow
  434. )
  435. {
  436. HANDLE hPipeRead, hEvent;
  437. DEVICE_COLLECTION safeRemovalCollection;
  438. MSG Msg;
  439. WNDCLASS wndClass;
  440. HWND hSafeRemovalWnd;
  441. HANDLE hHotplugIconEvent;
  442. //
  443. // Open the specified name pipe and event.
  444. //
  445. if (!OpenPipeAndEventHandles(szCmd,
  446. &hPipeRead,
  447. &hEvent)) {
  448. return 1;
  449. }
  450. ASSERT((hEvent != NULL) && (hEvent != INVALID_HANDLE_VALUE));
  451. ASSERT((hPipeRead != NULL) && (hPipeRead != INVALID_HANDLE_VALUE));
  452. //
  453. // Read out the device ID list from the Pipe
  454. //
  455. DeviceCollectionBuildFromPipe(
  456. hPipeRead,
  457. CT_SAFE_REMOVAL_NOTIFICATION,
  458. &safeRemovalCollection
  459. );
  460. //
  461. // On success or error, we are finished reading from the pipe, so close the
  462. // handle and tell umpnpmgr it can continue.
  463. //
  464. CloseHandle(hPipeRead);
  465. SetEvent(hEvent);
  466. CloseHandle(hEvent);
  467. //
  468. // If we have any devices then bring up the safe removal dialog
  469. //
  470. if (safeRemovalCollection.NumDevices) {
  471. if (!GetClassInfo(hHotPlug, HOTPLUG_CLASS_NAME, &wndClass)) {
  472. memset(&wndClass, 0, sizeof(wndClass));
  473. wndClass.lpfnWndProc = (safeRemovalCollection.DockInList)
  474. ? DockSafeRemovalBalloonProc
  475. : SafeRemovalBalloonProc;
  476. wndClass.hInstance = hHotPlug;
  477. wndClass.lpszClassName = HOTPLUG_CLASS_NAME;
  478. if (!RegisterClass(&wndClass)) {
  479. goto clean0;
  480. }
  481. }
  482. //
  483. // In order to prevent multiple similar icons on the tray, we will
  484. // create a named event that will be used to serialize the UI.
  485. //
  486. // Note that if we can't create the event for some reason then we will just
  487. // display the UI. This might cause multiple icons, but it is better
  488. // than not displaying any UI at all.
  489. //
  490. hHotplugIconEvent = CreateEvent(NULL,
  491. FALSE,
  492. TRUE,
  493. safeRemovalCollection.DockInList
  494. ? TEXT("Local\\Dock_TaskBarIcon_Event")
  495. : TEXT("Local\\HotPlug_TaskBarIcon_Event")
  496. );
  497. if (hHotplugIconEvent) {
  498. WaitForSingleObject(hHotplugIconEvent, INFINITE);
  499. }
  500. if (!safeRemovalCollection.DockInList) {
  501. //
  502. // First disable the hotplug service so that the icon will go away from
  503. // the taskbar. We do this just in case there are any other hotplug devices
  504. // in the machine since we don't want multiple hotplug icons
  505. // showing up in the taskbar.
  506. //
  507. // NOTE: We don't need to do this for the safe to undock case since
  508. // the docking icon is different.
  509. //
  510. SysTray_EnableService(STSERVICE_HOTPLUG, FALSE);
  511. }
  512. hSafeRemovalWnd = CreateWindowEx(WS_EX_TOOLWINDOW,
  513. HOTPLUG_CLASS_NAME,
  514. TEXT(""),
  515. WS_DLGFRAME | WS_BORDER | WS_DISABLED,
  516. CW_USEDEFAULT,
  517. CW_USEDEFAULT,
  518. 0,
  519. 0,
  520. NULL,
  521. NULL,
  522. hHotPlug,
  523. (LPVOID)&safeRemovalCollection
  524. );
  525. if (hSafeRemovalWnd != NULL) {
  526. while (IsWindow(hSafeRemovalWnd)) {
  527. if (GetMessage(&Msg, NULL, 0, 0)) {
  528. TranslateMessage(&Msg);
  529. DispatchMessage(&Msg);
  530. }
  531. }
  532. }
  533. //
  534. // Set the Event so the next surprise removal process can go to work
  535. // and then close the event handle.
  536. //
  537. if (hHotplugIconEvent) {
  538. SetEvent(hHotplugIconEvent);
  539. CloseHandle(hHotplugIconEvent);
  540. }
  541. if (!safeRemovalCollection.DockInList) {
  542. //
  543. // Re-enable the hotplug service so that the icon can show back up in
  544. // the taskbar if we have any hotplug devices.
  545. //
  546. SysTray_EnableService(STSERVICE_HOTPLUG, TRUE);
  547. }
  548. }
  549. clean0:
  550. DeviceCollectionDestroy(&safeRemovalCollection);
  551. return 1;
  552. }
  553. DWORD
  554. WINAPI
  555. HotPlugDriverBlockedW(
  556. HWND hwnd,
  557. HINSTANCE hInst,
  558. LPWSTR szCmd,
  559. int nShow
  560. )
  561. {
  562. HANDLE hPipeRead, hEvent;
  563. DEVICE_COLLECTION blockedDriverCollection;
  564. HANDLE hHotplugIconEvent = NULL;
  565. //
  566. // Open the specified name pipe and event.
  567. //
  568. if (!OpenPipeAndEventHandles(szCmd,
  569. &hPipeRead,
  570. &hEvent)) {
  571. return 1;
  572. }
  573. ASSERT((hEvent != NULL) && (hEvent != INVALID_HANDLE_VALUE));
  574. ASSERT((hPipeRead != NULL) && (hPipeRead != INVALID_HANDLE_VALUE));
  575. //
  576. // Read out the list of blocked driver GUIDs from the Pipe. Note that for
  577. // the CT_BLOCKED_DRIVER_NOTIFICATION collection type, we use only the
  578. // DeviceInstanceId field of each collection entry (which is OK because
  579. // MAX_GUID_STRING_LEN << MAX_DEVICE_ID_LEN). All other fields are skipped.
  580. //
  581. DeviceCollectionBuildFromPipe(
  582. hPipeRead,
  583. CT_BLOCKED_DRIVER_NOTIFICATION,
  584. &blockedDriverCollection
  585. );
  586. //
  587. // On success or error, we are finished reading from the pipe, so close the
  588. // handle and tell umpnpmgr it can continue.
  589. //
  590. CloseHandle(hPipeRead);
  591. SetEvent(hEvent);
  592. CloseHandle(hEvent);
  593. //
  594. // In order to prevent multipe driver blocked icons and ballons showing up
  595. // on the taskbar together and stepping on each other, we will create a
  596. // named event that will be used to serialize the hotplug icons and balloon
  597. // UI.
  598. //
  599. // Note that if we can't create the event for some reason then we will just
  600. // display the UI. This might cause multiple driver blocked icons, but it
  601. // is better than not displaying any UI at all.
  602. //
  603. // Also note that we can coexist with normal hotplug icon. As such we have
  604. // a different event name and a different icon.
  605. //
  606. hHotplugIconEvent = CreateEvent(NULL,
  607. FALSE,
  608. TRUE,
  609. TEXT("Local\\HotPlug_DriverBlockedIcon_Event")
  610. );
  611. if (hHotplugIconEvent) {
  612. WaitForSingleObject(hHotplugIconEvent, INFINITE);
  613. }
  614. //
  615. // Show the balloon.
  616. //
  617. DisplayDriverBlockBalloon(&blockedDriverCollection);
  618. //
  619. // Set the Event so the next blocked driver process can go to work and then
  620. // close the event handle.
  621. //
  622. if (hHotplugIconEvent) {
  623. SetEvent(hHotplugIconEvent);
  624. CloseHandle(hHotplugIconEvent);
  625. }
  626. //
  627. // Destroy the collection.
  628. //
  629. DeviceCollectionDestroy(&blockedDriverCollection);
  630. return 1;
  631. }
  632. LONG
  633. CPlApplet(
  634. HWND hWnd,
  635. WORD uMsg,
  636. DWORD_PTR lParam1,
  637. LRESULT lParam2
  638. )
  639. {
  640. LPNEWCPLINFO lpCPlInfo;
  641. LPCPLINFO lpOldCPlInfo;
  642. switch (uMsg) {
  643. case CPL_INIT:
  644. return TRUE;
  645. case CPL_GETCOUNT:
  646. return 1;
  647. case CPL_INQUIRE:
  648. lpOldCPlInfo = (LPCPLINFO)(LPARAM)lParam2;
  649. lpOldCPlInfo->lData = 0L;
  650. lpOldCPlInfo->idIcon = IDI_HOTPLUGICON;
  651. lpOldCPlInfo->idName = IDS_HOTPLUGNAME;
  652. lpOldCPlInfo->idInfo = IDS_HOTPLUGINFO;
  653. return TRUE;
  654. case CPL_NEWINQUIRE:
  655. lpCPlInfo = (LPNEWCPLINFO)(LPARAM)lParam2;
  656. lpCPlInfo->hIcon = LoadIcon(hHotPlug, MAKEINTRESOURCE(IDI_HOTPLUGICON));
  657. LoadString(hHotPlug, IDS_HOTPLUGNAME, lpCPlInfo->szName, sizeof(lpCPlInfo->szName));
  658. LoadString(hHotPlug, IDS_HOTPLUGINFO, lpCPlInfo->szInfo, sizeof(lpCPlInfo->szInfo));
  659. lpCPlInfo->dwHelpContext = IDH_HOTPLUGAPPLET;
  660. lpCPlInfo->dwSize = sizeof(NEWCPLINFO);
  661. lpCPlInfo->lData = 0;
  662. lpCPlInfo->szHelpFile[0] = '\0';
  663. return TRUE;
  664. case CPL_DBLCLK:
  665. HotPlugDeviceTree(hWnd, NULL, TRUE);
  666. break;
  667. case CPL_STARTWPARMS:
  668. //
  669. // what does this mean ?
  670. //
  671. break;
  672. case CPL_EXIT:
  673. // Free up any allocations of resources made.
  674. break;
  675. default:
  676. break;
  677. }
  678. return 0L;
  679. }
  680. #if BUBBLES
  681. VOID
  682. OpenGetSurpriseUndockObjects(
  683. OUT HANDLE *SurpriseUndockTimer,
  684. OUT HANDLE *SurpriseUndockEvent
  685. )
  686. {
  687. LARGE_INTEGER liDelayTime;
  688. HANDLE hSurpriseUndockEventTimer;
  689. HANDLE hSurpriseUndockEvent;
  690. hSurpriseUndockEventTimer = CreateWaitableTimer(
  691. NULL,
  692. TRUE,
  693. SURPRISE_UNDOCK_TIMER
  694. );
  695. if ((hSurpriseUndockEventTimer != NULL) &&
  696. (GetLastError() == ERROR_SUCCESS)) {
  697. //
  698. // We created it (if not the status would be ERROR_ALREADY_EXISTS).
  699. // Ensure it starts life signalled.
  700. //
  701. liDelayTime.QuadPart = 0;
  702. SetWaitableTimer(
  703. hSurpriseUndockEventTimer,
  704. &liDelayTime,
  705. 0,
  706. NULL,
  707. NULL,
  708. FALSE
  709. );
  710. }
  711. hSurpriseUndockEvent = CreateEvent(
  712. NULL,
  713. TRUE,
  714. FALSE,
  715. SURPRISE_UNDOCK_EVENT
  716. );
  717. *SurpriseUndockTimer = hSurpriseUndockEventTimer;
  718. *SurpriseUndockEvent = hSurpriseUndockEvent;
  719. }
  720. #endif // BUBBLES