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.

610 lines
19 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1993-1995
  4. * TITLE: USBPOPUP.CPP
  5. * VERSION: 1.0
  6. * AUTHOR: jsenior
  7. * DATE: 10/28/1998
  8. *
  9. ********************************************************************************
  10. *
  11. * CHANGE LOG:
  12. *
  13. * DATE REV DESCRIPTION
  14. * ---------- ------- ----------------------------------------------------------
  15. * 10/28/1998 jsenior Original implementation.
  16. *
  17. *******************************************************************************/
  18. #include "UsbPopup.h"
  19. #include "PropPage.h"
  20. #include "debug.h"
  21. #include "usbutil.h"
  22. UINT CALLBACK
  23. UsbPopup::StaticDialogCallback(HWND Hwnd,
  24. UINT Msg,
  25. LPPROPSHEETPAGE Page)
  26. {
  27. UsbPopup *that;
  28. switch (Msg) {
  29. case PSPCB_CREATE:
  30. return TRUE; // return TRUE to continue with creation of page
  31. case PSPCB_RELEASE:
  32. that = (UsbPopup*) Page->lParam;
  33. DeleteChunk(that);
  34. delete that;
  35. return 0; // return value ignored
  36. default:
  37. break;
  38. }
  39. return TRUE;
  40. }
  41. USBINT_PTR APIENTRY UsbPopup::StaticDialogProc(IN HWND hDlg,
  42. IN UINT uMessage,
  43. IN WPARAM wParam,
  44. IN LPARAM lParam)
  45. {
  46. UsbPopup *that;
  47. that = (UsbPopup *) UsbGetWindowLongPtr(hDlg, USBDWLP_USER);
  48. if (!that && uMessage != WM_INITDIALOG)
  49. return FALSE; //DefDlgProc(hDlg, uMessage, wParam, lParam);
  50. switch (uMessage) {
  51. case WM_COMMAND:
  52. return that->OnCommand(HIWORD(wParam),
  53. LOWORD(wParam),
  54. (HWND) lParam);
  55. case WM_TIMER:
  56. return that->OnTimer();
  57. case WM_INITDIALOG:
  58. that = (UsbPopup *) lParam;
  59. UsbSetWindowLongPtr(hDlg, USBDWLP_USER, (USBLONG_PTR) that);
  60. that->hWnd = hDlg;
  61. return that->OnInitDialog(hDlg);
  62. case WM_NOTIFY:
  63. return that->OnNotify(hDlg, (int) wParam, (LPNMHDR) lParam);
  64. case WM_DEVICECHANGE:
  65. return that->OnDeviceChange(hDlg, wParam, (PDEV_BROADCAST_HDR)lParam);
  66. default:
  67. break;
  68. }
  69. return that->ActualDialogProc(hDlg, uMessage, wParam, lParam);
  70. }
  71. BOOL
  72. UsbPopup::OnCommand(INT wNotifyCode,
  73. INT wID,
  74. HWND hCtl)
  75. {
  76. switch (wID) {
  77. case IDOK:
  78. EndDialog(hWnd, wID);
  79. return TRUE;
  80. }
  81. return FALSE;
  82. }
  83. BOOL UsbPopup::OnNotify(HWND hDlg, int nID, LPNMHDR pnmh)
  84. {
  85. switch (nID) {
  86. case IDC_LIST_CONTROLLERS:
  87. if (pnmh->code == NM_DBLCLK) {
  88. //
  89. // Display properties on this specific device on double click
  90. //
  91. UsbPropertyPage::DisplayPPSelectedListItem(hDlg, hListDevices);
  92. }
  93. return TRUE;
  94. case IDC_TREE_HUBS:
  95. if (pnmh->code == NM_DBLCLK) {
  96. //
  97. // Display properties on this specific device on double click
  98. //
  99. UsbPropertyPage::DisplayPPSelectedTreeItem(hDlg, hTreeDevices);
  100. }
  101. return TRUE;
  102. }
  103. return 0;
  104. }
  105. BOOL
  106. UsbPopup::CustomDialog(
  107. DWORD DialogBoxId,
  108. DWORD IconId,
  109. DWORD FormatStringId,
  110. DWORD TitleStringId)
  111. {
  112. HRESULT hr;
  113. //
  114. // Make sure the device hasn't gone away.
  115. //
  116. if (UsbItem::UsbItemType::Empty == deviceItem.itemType) {
  117. return FALSE;
  118. }
  119. TCHAR buf[MAX_PATH];
  120. TCHAR formatString[MAX_PATH];
  121. LoadString(gHInst,
  122. FormatStringId,
  123. formatString,
  124. MAX_PATH);
  125. UsbSprintf(buf, formatString, deviceItem.configInfo->deviceDesc.c_str());
  126. LoadString(gHInst, TitleStringId, formatString, MAX_PATH);
  127. pun->SetBalloonRetry(-1, -1, 0);
  128. pun->SetIconInfo(LoadIcon(gHInst, MAKEINTRESOURCE(IDI_USB)), formatString);
  129. pun->SetBalloonInfo(formatString, buf, IconId);
  130. //
  131. // Query me every 2 seconds.
  132. //
  133. hr = pun->Show(this, 2000);
  134. pun->Release();
  135. if (S_OK == hr) {
  136. if (-1 == DialogBoxParam(gHInst,
  137. MAKEINTRESOURCE(DialogBoxId),
  138. NULL,
  139. StaticDialogProc,
  140. (LPARAM) this)) {
  141. return FALSE;
  142. }
  143. }
  144. return TRUE;
  145. }
  146. STDMETHODIMP_(ULONG) UsbPopup::AddRef()
  147. {
  148. return InterlockedIncrement(&RefCount);
  149. }
  150. STDMETHODIMP_(ULONG) UsbPopup::Release()
  151. {
  152. assert( 0 != RefCount );
  153. ULONG cRef = InterlockedDecrement(&RefCount);
  154. if ( 0 == cRef )
  155. {
  156. //
  157. // TODO: gpease 27-FEB-2002
  158. // Figure out why someone commented out this delete. What's the use of having
  159. // the RefCount if it is meaningless?
  160. //
  161. // delete this;
  162. }
  163. return cRef;
  164. }
  165. HRESULT UsbPopup::QueryInterface(REFIID iid, void **ppv)
  166. {
  167. if ((iid == IID_IUnknown) || (iid == IID_IQueryContinue)) {
  168. *ppv = (void *)(IQueryContinue *)this;
  169. }
  170. else {
  171. *ppv = NULL; // null the out param
  172. return E_NOINTERFACE;
  173. }
  174. AddRef();
  175. return S_OK;
  176. }
  177. HRESULT
  178. UsbPopup::QueryContinue()
  179. {
  180. USB_NODE_CONNECTION_INFORMATION connectionInfo;
  181. ULONG nBytes;
  182. HANDLE hHubDevice;
  183. String hubName = HubAcquireInfo->Buffer;
  184. //
  185. // Try to open the hub device
  186. //
  187. hHubDevice = GetHandleForDevice(hubName);
  188. if (hHubDevice == INVALID_HANDLE_VALUE) {
  189. return S_FALSE;
  190. }
  191. //
  192. // Find out if we still have an underpowered device attached .
  193. //
  194. nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION);
  195. ZeroMemory(&connectionInfo, nBytes);
  196. connectionInfo.ConnectionIndex = ConnectionNotification->ConnectionNumber;
  197. if ( !DeviceIoControl(hHubDevice,
  198. IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
  199. &connectionInfo,
  200. nBytes,
  201. &connectionInfo,
  202. nBytes,
  203. &nBytes,
  204. NULL)) {
  205. return S_FALSE;
  206. }
  207. CloseHandle(hHubDevice);
  208. switch (ConnectionNotification->NotificationType) {
  209. case InsufficentBandwidth:
  210. return connectionInfo.ConnectionStatus == DeviceNotEnoughBandwidth ? S_OK : S_FALSE;
  211. case EnumerationFailure:
  212. return connectionInfo.ConnectionStatus == DeviceFailedEnumeration ? S_OK : S_FALSE;
  213. case InsufficentPower:
  214. return connectionInfo.ConnectionStatus == DeviceNotEnoughPower ? S_OK : S_FALSE;
  215. case OverCurrent:
  216. return connectionInfo.ConnectionStatus == DeviceCausedOvercurrent ? S_OK : S_FALSE;
  217. case ModernDeviceInLegacyHub:
  218. return connectionInfo.ConnectionStatus == DeviceConnected ? S_OK : S_FALSE;
  219. case HubNestedTooDeeply:
  220. return connectionInfo.ConnectionStatus == DeviceHubNestedTooDeeply ? S_OK : S_FALSE;
  221. }
  222. return S_FALSE;
  223. }
  224. void
  225. UsbPopup::Make(PUSB_CONNECTION_NOTIFICATION vUsbConnectionNotification,
  226. LPTSTR strInstanceName)
  227. {
  228. ULONG result;
  229. HRESULT hr;
  230. String hubName;
  231. InstanceName = strInstanceName;
  232. ConnectionNotification = vUsbConnectionNotification;
  233. result = WmiOpenBlock((LPGUID) &GUID_USB_WMI_STD_DATA,
  234. 0,
  235. &WmiHandle);
  236. if (result != ERROR_SUCCESS) {
  237. goto UsbPopupMakeError;
  238. }
  239. hWnd = GetDesktopWindow();
  240. InitCommonControls();
  241. //
  242. // Get the hub name and from that, get the name of the device to display in
  243. // the dialog and display it.
  244. // We'll use the port number which the device is attached to. This is:
  245. // ConnectionNotification->ConnectionNumber;
  246. HubAcquireInfo = GetHubName(WmiHandle,
  247. strInstanceName,
  248. ConnectionNotification);
  249. if (!HubAcquireInfo) {
  250. goto UsbPopupMakeError;
  251. }
  252. hubName = HubAcquireInfo->Buffer;
  253. //
  254. // Make sure that the condition still exists.
  255. //
  256. if (S_FALSE == QueryContinue()) {
  257. USBTRACE((_T("Erorr does not exist anymore. Exitting.\n")));
  258. goto UsbPopupMakeError;
  259. }
  260. if (!deviceItem.GetDeviceInfo(hubName,
  261. ConnectionNotification->ConnectionNumber)) {
  262. goto UsbPopupMakeError;
  263. }
  264. if (!IsPopupStillValid()) {
  265. //
  266. // We already saw the error for this device. Usbhub is being
  267. // repetitive.
  268. //
  269. goto UsbPopupMakeError;
  270. }
  271. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
  272. if (FAILED(hr)) {
  273. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
  274. }
  275. if (FAILED(hr)) {
  276. goto UsbPopupMakeError;
  277. }
  278. hr = CoCreateInstance(CLSID_UserNotification, NULL, CLSCTX_ALL,
  279. IID_PPV_ARG(IUserNotification, &pun));
  280. if (!FAILED(hr)) {
  281. CustomDialogWrap();
  282. }
  283. CoUninitialize();
  284. UsbPopupMakeError:
  285. USBTRACE((_T("UsbPopupMakeError\n")));
  286. if (WmiHandle != INVALID_HANDLE_VALUE) {
  287. WmiCloseBlock(WmiHandle);
  288. }
  289. }
  290. BOOL
  291. UsbPopup::OnInitDialog(HWND HWnd)
  292. {
  293. hWnd = HWnd;
  294. HANDLE hExclamation;
  295. HICON hIcon;
  296. if (RegisterForDeviceReattach) {
  297. //
  298. // Try to open the hub device
  299. //
  300. String hubName = HubAcquireInfo->Buffer;
  301. HANDLE hHubDevice = GetHandleForDevice(hubName);
  302. if (hHubDevice != INVALID_HANDLE_VALUE) {
  303. //
  304. // Register for notification for when the device is re-attached. We want
  305. // to do this before we see the device get detached because we are polling
  306. // and may miss the re-attach if we register when the device is removed.
  307. //
  308. // Allocate configuration information structure and get config mgr info
  309. //
  310. ConfigInfo = new UsbConfigInfo();
  311. AddChunk(ConfigInfo);
  312. if (ConfigInfo) {
  313. String driverKeyName = GetDriverKeyName(hHubDevice,
  314. ConnectionNotification->ConnectionNumber);
  315. if (!driverKeyName.empty()) {
  316. GetConfigMgrInfo(driverKeyName, ConfigInfo); // ISSUE: leak, jsenior, 4/19/00
  317. } else {
  318. USBWARN((_T("Couldn't get driver key name. Error: (%x)."), GetLastError()));
  319. }
  320. CHAR guidBuf[MAX_PATH];
  321. DEV_BROADCAST_DEVICEINTERFACE devInterface;
  322. DWORD len = MAX_PATH;
  323. if (CM_Get_DevNode_Registry_PropertyA(ConfigInfo->devInst,
  324. CM_DRP_CLASSGUID,
  325. NULL,
  326. guidBuf,
  327. &len,
  328. 0) == CR_SUCCESS) {
  329. ZeroMemory(&devInterface, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
  330. if (StrToGUID(guidBuf, &devInterface.dbcc_classguid)) {
  331. devInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  332. devInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  333. hNotifyArrival =
  334. RegisterDeviceNotification( HWnd,
  335. &devInterface,
  336. DEVICE_NOTIFY_WINDOW_HANDLE);
  337. if (!hNotifyArrival){
  338. USBWARN((_T("RegisterDeviceNotification failure (%x)."), GetLastError()));
  339. }
  340. } else {
  341. USBWARN((_T("GUID conversion didn't work.")));
  342. }
  343. USBWARN((_T("GUID data: %x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x"),
  344. devInterface.dbcc_classguid.Data1,
  345. devInterface.dbcc_classguid.Data2,
  346. devInterface.dbcc_classguid.Data3,
  347. devInterface.dbcc_classguid.Data4[0],
  348. devInterface.dbcc_classguid.Data4[1],
  349. devInterface.dbcc_classguid.Data4[2],
  350. devInterface.dbcc_classguid.Data4[3],
  351. devInterface.dbcc_classguid.Data4[4],
  352. devInterface.dbcc_classguid.Data4[5],
  353. devInterface.dbcc_classguid.Data4[6],
  354. devInterface.dbcc_classguid.Data4[7]));
  355. } else {
  356. //
  357. // If this fails, we need to default to the old functionality!
  358. // ISSUE: jsenior
  359. //
  360. }
  361. }
  362. CloseHandle(hHubDevice);
  363. }
  364. }
  365. //
  366. // Set the Icon to an exclamation mark
  367. //
  368. if (NULL == (hIcon = LoadIcon(NULL, (LPTSTR) IDI_EXCLAMATION)) ||
  369. NULL == (hExclamation = GetDlgItem(hWnd, IDC_ICON_POWER))) {
  370. return FALSE;
  371. }
  372. SendMessage((HWND) hExclamation, STM_SETICON, (WPARAM) hIcon, NULL);
  373. //
  374. // Get a persistent handle to the tree view control
  375. //
  376. if (NULL == (hTreeDevices = GetDlgItem(HWnd, IDC_TREE_HUBS))) {
  377. return FALSE;
  378. }
  379. TreeView_SetImageList(hTreeDevices, ImageList.ImageList(), TVSIL_NORMAL);
  380. return Refresh();
  381. }
  382. PUSB_ACQUIRE_INFO
  383. UsbPopup::GetHubName(WMIHANDLE WmiHandle,
  384. UsbString InstanceName,
  385. PUSB_CONNECTION_NOTIFICATION ConnectionNotification)
  386. {
  387. ULONG res, size;
  388. PUSB_ACQUIRE_INFO usbAcquireInfo;
  389. //
  390. // zero all the vars, get the controllers name
  391. //
  392. size = ConnectionNotification->HubNameLength * sizeof(WCHAR)
  393. + sizeof(USB_ACQUIRE_INFO);
  394. usbAcquireInfo = (PUSB_ACQUIRE_INFO) LocalAlloc(LMEM_ZEROINIT, size);
  395. if (!usbAcquireInfo) {
  396. USBERROR((_T("Acquire info allocation failed.")));
  397. return NULL;
  398. }
  399. usbAcquireInfo->NotificationType = AcquireHubName;
  400. usbAcquireInfo->TotalSize = size;
  401. res = WmiExecuteMethod(WmiHandle,
  402. InstanceName.c_str(),
  403. AcquireHubName,
  404. size,
  405. usbAcquireInfo,
  406. &size,
  407. usbAcquireInfo
  408. );
  409. if (res != ERROR_SUCCESS) {
  410. usbAcquireInfo = (PUSB_ACQUIRE_INFO) LocalFree(usbAcquireInfo);
  411. }
  412. return usbAcquireInfo;
  413. }
  414. BOOLEAN
  415. UsbPopup::GetBusNotification(WMIHANDLE WmiHandle,
  416. PUSB_BUS_NOTIFICATION UsbBusNotification)
  417. {
  418. ULONG res, size;
  419. memset(UsbBusNotification, 0, sizeof(USB_BUS_NOTIFICATION));
  420. UsbBusNotification->NotificationType = AcquireBusInfo;
  421. size = sizeof(USB_BUS_NOTIFICATION);
  422. res = WmiExecuteMethod(WmiHandle,
  423. InstanceName.c_str(),
  424. AcquireBusInfo,
  425. size,
  426. UsbBusNotification,
  427. &size,
  428. UsbBusNotification
  429. );
  430. if (res != ERROR_SUCCESS) {
  431. return FALSE;
  432. }
  433. return TRUE;
  434. }
  435. PUSB_ACQUIRE_INFO
  436. UsbPopup::GetControllerName(WMIHANDLE WmiHandle,
  437. UsbString InstanceName)
  438. {
  439. ULONG res, size;
  440. USB_BUS_NOTIFICATION usbBusNotification;
  441. PUSB_ACQUIRE_INFO usbAcquireInfo;
  442. memset(&usbBusNotification, 0, sizeof(USB_BUS_NOTIFICATION));
  443. usbBusNotification.NotificationType = AcquireBusInfo;
  444. size = sizeof(USB_BUS_NOTIFICATION);
  445. res = WmiExecuteMethod(WmiHandle,
  446. InstanceName.c_str(),
  447. AcquireBusInfo,
  448. size,
  449. &usbBusNotification,
  450. &size,
  451. &usbBusNotification
  452. );
  453. if (res != ERROR_SUCCESS) {
  454. return NULL;
  455. }
  456. //
  457. // zero all the vars, get the controllers name
  458. //
  459. size = usbBusNotification.ControllerNameLength * sizeof(WCHAR)
  460. + sizeof(USB_ACQUIRE_INFO);
  461. usbAcquireInfo = (PUSB_ACQUIRE_INFO) LocalAlloc(LMEM_ZEROINIT, size);
  462. usbAcquireInfo->NotificationType = AcquireControllerName;
  463. usbAcquireInfo->TotalSize = size;
  464. res = WmiExecuteMethod(WmiHandle,
  465. InstanceName.c_str(),
  466. AcquireControllerName,
  467. size,
  468. usbAcquireInfo,
  469. &size,
  470. usbAcquireInfo
  471. );
  472. if (res != ERROR_SUCCESS) {
  473. usbAcquireInfo = (PUSB_ACQUIRE_INFO) LocalFree(usbAcquireInfo);
  474. }
  475. return usbAcquireInfo;
  476. }
  477. BOOL
  478. UsbPopup::OnDeviceChange(HWND hDlg,
  479. WPARAM wParam,
  480. PDEV_BROADCAST_HDR devHdr)
  481. {
  482. PDEV_BROADCAST_DEVICEINTERFACE devInterface =
  483. (PDEV_BROADCAST_DEVICEINTERFACE) devHdr;
  484. USBTRACE((_T("Device change notification, type %x."), wParam));
  485. switch (wParam) {
  486. case DBT_DEVICEARRIVAL:
  487. USBTRACE((_T("Device arrival.")));
  488. if (devHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
  489. USBTRACE((_T("Device: %s"),devInterface->dbcc_name));
  490. // New device arrival.
  491. // Compare the device description of this puppy to that of the one
  492. // that we have.
  493. //
  494. if (devInterface->dbcc_name == ConfigInfo->deviceDesc &&
  495. deviceState == DeviceDetachedError) {
  496. USBTRACE((_T("Device name match on arrival!")));
  497. //
  498. // The device has been reattached!
  499. //
  500. deviceState = DeviceReattached;
  501. Refresh();
  502. }
  503. }
  504. break;
  505. case DBT_DEVICEREMOVECOMPLETE:
  506. USBTRACE((_T("Device removal.")));
  507. if (devHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
  508. USBTRACE((_T("Device: %s"),devInterface->dbcc_name));
  509. // New device arrival.
  510. // Compare the device description of this puppy to that of the one
  511. // that we have.
  512. //
  513. if (devInterface->dbcc_name == ConfigInfo->deviceDesc &&
  514. deviceState == DeviceAttachedError) {
  515. USBTRACE((_T("Device name match on remove!")));
  516. //
  517. // The device has been reattached!
  518. //
  519. deviceState = DeviceDetachedError;
  520. Refresh();
  521. }
  522. }
  523. break;
  524. }
  525. return TRUE;
  526. }