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.

638 lines
19 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation
  6. //
  7. // File: getdev.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "hdwwiz.h"
  11. #include <htmlhelp.h>
  12. HMODULE hDevMgr=NULL;
  13. PDEVICEPROBLEMTEXT pDeviceProblemText = NULL;
  14. PTCHAR
  15. DeviceProblemText(
  16. DEVNODE DevNode,
  17. ULONG Status,
  18. ULONG ProblemNumber
  19. )
  20. {
  21. UINT LenChars, ReqLenChars;
  22. PTCHAR Buffer=NULL;
  23. PTCHAR p=NULL;
  24. TCHAR TempBuffer[MAX_PATH];
  25. if (hDevMgr) {
  26. if (!pDeviceProblemText) {
  27. pDeviceProblemText = (PDEVICEPROBLEMTEXT)GetProcAddress(hDevMgr, "DeviceProblemTextW");
  28. }
  29. }
  30. if (pDeviceProblemText) {
  31. LenChars = (pDeviceProblemText)(NULL,
  32. DevNode,
  33. ProblemNumber,
  34. Buffer,
  35. 0
  36. );
  37. if (!LenChars) {
  38. goto DPTExitCleanup;
  39. }
  40. LenChars++; // one extra for terminating NULL
  41. Buffer = LocalAlloc(LPTR, LenChars*sizeof(TCHAR));
  42. if (!Buffer) {
  43. goto DPTExitCleanup;
  44. }
  45. ReqLenChars = (pDeviceProblemText)(NULL,
  46. DevNode,
  47. ProblemNumber,
  48. Buffer,
  49. LenChars
  50. );
  51. if (!ReqLenChars || ReqLenChars >= LenChars) {
  52. LocalFree(Buffer);
  53. Buffer = NULL;
  54. }
  55. if (Buffer && (Status != 0)) {
  56. if (Status & DN_WILL_BE_REMOVED) {
  57. if (LoadString(hHdwWiz,
  58. IDS_WILL_BE_REMOVED,
  59. TempBuffer,
  60. SIZECHARS(TempBuffer)
  61. )) {
  62. LenChars += lstrlen(TempBuffer) + 1;
  63. p = LocalAlloc(LPTR, LenChars*sizeof(TCHAR));
  64. if (p) {
  65. StringCchCopy(p, LenChars, Buffer);
  66. StringCchCat(p, LenChars, TempBuffer);
  67. LocalFree(Buffer);
  68. Buffer = p;
  69. }
  70. }
  71. }
  72. if (Status & DN_NEED_RESTART) {
  73. if (LoadString(hHdwWiz,
  74. IDS_NEED_RESTART,
  75. TempBuffer,
  76. SIZECHARS(TempBuffer)
  77. )) {
  78. LenChars += lstrlen(TempBuffer) + 1;
  79. p = LocalAlloc(LPTR, LenChars*sizeof(TCHAR));
  80. if (p) {
  81. StringCchCopy(p, LenChars, Buffer);
  82. StringCchCat(p, LenChars, TempBuffer);
  83. LocalFree(Buffer);
  84. Buffer = p;
  85. }
  86. }
  87. }
  88. }
  89. }
  90. DPTExitCleanup:
  91. return Buffer;
  92. }
  93. int CALLBACK
  94. DeviceListCompare(
  95. LPARAM lParam1,
  96. LPARAM lParam2,
  97. LPARAM lParamSort
  98. )
  99. {
  100. TCHAR ClassName1[MAX_CLASS_NAME_LEN];
  101. TCHAR ClassName2[MAX_CLASS_NAME_LEN];
  102. TCHAR Buffer[MAX_PATH];
  103. GUID ClassGuid1, ClassGuid2;
  104. BOOL bSpecialClass1 = FALSE, bSpecialClass2 = FALSE;
  105. ULONG ulLength;
  106. ULONG Status, Problem1, Problem2;
  107. UNREFERENCED_PARAMETER(lParamSort);
  108. //
  109. // Return
  110. // -1 if the first item should precede the second
  111. // +1 if the first item should follow the second
  112. // 0 if they are the same
  113. //
  114. //
  115. // First check if lParam1 or lParam2 are 0. A 0 lParam means that this
  116. // is the special 'Add a new hardware device' that goes at the bottom
  117. // of the list.
  118. //
  119. if (lParam1 == 0) {
  120. return 1;
  121. }
  122. if (lParam2 == 0) {
  123. return -1;
  124. }
  125. if (CM_Get_DevNode_Status(&Status, &Problem1, (DEVINST)lParam1, 0) != CR_SUCCESS) {
  126. Problem1 = 0;
  127. }
  128. if (CM_Get_DevNode_Status(&Status, &Problem2, (DEVINST)lParam2, 0) != CR_SUCCESS) {
  129. Problem2 = 0;
  130. }
  131. //
  132. // Devices with problems always go at the top of the list. If both devices
  133. // have problems then we sort by class name.
  134. //
  135. if (Problem1 && !Problem2) {
  136. return -1;
  137. } else if (!Problem1 && Problem2) {
  138. return 1;
  139. }
  140. //
  141. // The next check is to put the special device classes above non-special
  142. // device classes.
  143. //
  144. ulLength = sizeof(Buffer);
  145. if ((CM_Get_DevNode_Registry_Property((DEVINST)lParam1,
  146. CM_DRP_CLASSGUID,
  147. NULL,
  148. Buffer,
  149. &ulLength,
  150. 0) == CR_SUCCESS) &&
  151. (ulLength != 0)) {
  152. pSetupGuidFromString(Buffer, &ClassGuid1);
  153. if (IsEqualGUID(&ClassGuid1, &GUID_DEVCLASS_DISPLAY) ||
  154. IsEqualGUID(&ClassGuid1, &GUID_DEVCLASS_MEDIA)) {
  155. //
  156. // Device 1 is one of the special classes that go at the top of the list.
  157. //
  158. bSpecialClass1 = TRUE;
  159. }
  160. }
  161. ulLength = sizeof(Buffer);
  162. if ((CM_Get_DevNode_Registry_Property((DEVINST)lParam2,
  163. CM_DRP_CLASSGUID,
  164. NULL,
  165. Buffer,
  166. &ulLength,
  167. 0) == CR_SUCCESS) &&
  168. (ulLength != 0)) {
  169. pSetupGuidFromString(Buffer, &ClassGuid2);
  170. if (IsEqualGUID(&ClassGuid2, &GUID_DEVCLASS_DISPLAY) ||
  171. IsEqualGUID(&ClassGuid2, &GUID_DEVCLASS_MEDIA)) {
  172. //
  173. // Device 2 is one of the special classes that go at the top of the list.
  174. //
  175. bSpecialClass2 = TRUE;
  176. }
  177. }
  178. if (bSpecialClass1 && !bSpecialClass2) {
  179. return -1;
  180. } else if (!bSpecialClass1 && bSpecialClass2) {
  181. return 1;
  182. }
  183. //
  184. // The final check is to sort the items by classes
  185. //
  186. ulLength = sizeof(ClassName1);
  187. if ((CM_Get_DevNode_Registry_Property((DEVINST)lParam1,
  188. CM_DRP_CLASS,
  189. NULL,
  190. ClassName1,
  191. &ulLength,
  192. 0) != CR_SUCCESS) ||
  193. (ulLength == 0)) {
  194. //
  195. // If we could not get a class name then set it to all Z's so it will
  196. // get put at the bottom of the list.
  197. //
  198. StringCchCopy(ClassName1, SIZECHARS(ClassName1), TEXT("ZZZZZZZZZZ"));;
  199. }
  200. ulLength = sizeof(ClassName2);
  201. if ((CM_Get_DevNode_Registry_Property((DEVINST)lParam2,
  202. CM_DRP_CLASS,
  203. NULL,
  204. ClassName2,
  205. &ulLength,
  206. 0) != CR_SUCCESS) ||
  207. (ulLength == 0)) {
  208. //
  209. // If we could not get a class name then set it to all Z's so it will
  210. // get put at the bottom of the list.
  211. //
  212. StringCchCopy(ClassName2, SIZECHARS(ClassName2), TEXT("ZZZZZZZZZZ"));;
  213. }
  214. return lstrcmpi(ClassName1, ClassName2);
  215. }
  216. void
  217. InsertNoneOfTheseDevices(
  218. HWND hwndList
  219. )
  220. {
  221. LV_ITEM lviItem;
  222. TCHAR String[MAX_PATH];
  223. LoadString(hHdwWiz, IDS_HDW_NONEDEVICES, String, SIZECHARS(String));
  224. lviItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  225. lviItem.iSubItem = 0;
  226. lviItem.lParam = (LPARAM)0;
  227. lviItem.iItem = 0;
  228. lviItem.iImage = g_BlankIconIndex;
  229. lviItem.pszText = String;
  230. ListView_InsertItem(hwndList, &lviItem);
  231. }
  232. BOOL
  233. ProblemDeviceListFilter(
  234. PHARDWAREWIZ HardwareWiz,
  235. PSP_DEVINFO_DATA DeviceInfoData
  236. )
  237. /*++
  238. Routine Description:
  239. This function is a callback for the BuildDeviceListView API. It will get called
  240. for every device and can filter which devices end up getting displayed. If it
  241. returns FALSE then the given device won't be displayed. If it returns TRUE then
  242. the device will be displayed.
  243. Currently we will filter out all system devices from the problem devices list since
  244. they cluter up the list view and it would be very rare that a user would come to
  245. Add Hardware to add a system device.
  246. --*/
  247. {
  248. UNREFERENCED_PARAMETER(HardwareWiz);
  249. //
  250. // If this is a system class device then filter it out of the list by
  251. // returning FALSE.
  252. //
  253. if (IsEqualGUID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_SYSTEM)) {
  254. return FALSE;
  255. }
  256. return TRUE;
  257. }
  258. INT_PTR CALLBACK
  259. HdwProbListDlgProc(
  260. HWND hDlg,
  261. UINT message,
  262. WPARAM wParam,
  263. LPARAM lParam
  264. )
  265. /*++
  266. Routine Description:
  267. Arguments:
  268. standard stuff.
  269. Return Value:
  270. INT_PTR
  271. --*/
  272. {
  273. PHARDWAREWIZ HardwareWiz;
  274. if (message == WM_INITDIALOG) {
  275. LV_COLUMN lvcCol;
  276. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  277. HardwareWiz = (PHARDWAREWIZ) lppsp->lParam;
  278. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
  279. HardwareWiz->hwndProbList = GetDlgItem(hDlg, IDC_HDWPROBLIST);
  280. //
  281. // Insert columns for listview.
  282. // 0 == device name
  283. //
  284. lvcCol.mask = LVCF_WIDTH | LVCF_SUBITEM;
  285. lvcCol.iSubItem = 0;
  286. ListView_InsertColumn(HardwareWiz->hwndProbList, 0, &lvcCol);
  287. SendMessage(HardwareWiz->hwndProbList,
  288. LVM_SETEXTENDEDLISTVIEWSTYLE,
  289. LVS_EX_FULLROWSELECT,
  290. LVS_EX_FULLROWSELECT
  291. );
  292. ListView_SetExtendedListViewStyle(HardwareWiz->hwndProbList, LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);
  293. return TRUE;
  294. }
  295. //
  296. // retrieve private data from window long (stored there during WM_INITDIALOG)
  297. //
  298. HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  299. switch (message) {
  300. case WM_DESTROY:
  301. break;
  302. case WM_COMMAND:
  303. break;
  304. case WM_NOTIFY: {
  305. NMHDR FAR *pnmhdr = (NMHDR FAR *)lParam;
  306. switch (pnmhdr->code) {
  307. case PSN_SETACTIVE: {
  308. DWORD DevicesDetected;
  309. HWND hwndProbList;
  310. HWND hwndParentDlg;
  311. LVITEM lvItem;
  312. hwndParentDlg = GetParent(hDlg);
  313. HardwareWiz->PrevPage = IDD_ADDDEVICE_PROBLIST;
  314. //
  315. // initialize the list view, we do this on each setactive
  316. // since a new class may have been installed or the problem
  317. // device list may change as we go back and forth between pages.
  318. //
  319. hwndProbList = HardwareWiz->hwndProbList;
  320. SendMessage(hwndProbList, WM_SETREDRAW, FALSE, 0L);
  321. ListView_DeleteAllItems(hwndProbList);
  322. if (HardwareWiz->ClassImageList.cbSize) {
  323. ListView_SetImageList(hwndProbList,
  324. HardwareWiz->ClassImageList.ImageList,
  325. LVSIL_SMALL
  326. );
  327. }
  328. //
  329. // Next put all of the devices into the list
  330. //
  331. DevicesDetected = 0;
  332. BuildDeviceListView(HardwareWiz,
  333. HardwareWiz->hwndProbList,
  334. FALSE,
  335. HardwareWiz->ProblemDevInst,
  336. &DevicesDetected,
  337. ProblemDeviceListFilter
  338. );
  339. InsertNoneOfTheseDevices(HardwareWiz->hwndProbList);
  340. //
  341. // Sort the list
  342. //
  343. ListView_SortItems(HardwareWiz->hwndProbList,
  344. (PFNLVCOMPARE)DeviceListCompare,
  345. NULL
  346. );
  347. lvItem.mask = LVIF_PARAM;
  348. lvItem.iSubItem = 0;
  349. lvItem.iItem = ListView_GetNextItem(HardwareWiz->hwndProbList, -1, LVNI_SELECTED);
  350. //
  351. // select the first item in the list if nothing else was selected
  352. //
  353. if (lvItem.iItem == -1) {
  354. ListView_SetItemState(hwndProbList,
  355. 0,
  356. LVIS_FOCUSED,
  357. LVIS_FOCUSED
  358. );
  359. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
  360. } else {
  361. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
  362. }
  363. ListView_EnsureVisible(hwndProbList, lvItem.iItem, FALSE);
  364. ListView_SetColumnWidth(hwndProbList, 0, LVSCW_AUTOSIZE_USEHEADER);
  365. SendMessage(hwndProbList, WM_SETREDRAW, TRUE, 0L);
  366. }
  367. break;
  368. case PSN_WIZNEXT: {
  369. LVITEM lvItem;
  370. lvItem.mask = LVIF_PARAM;
  371. lvItem.iSubItem = 0;
  372. lvItem.iItem = ListView_GetNextItem(HardwareWiz->hwndProbList, -1, LVNI_SELECTED);
  373. if (lvItem.iItem != -1) {
  374. ListView_GetItem(HardwareWiz->hwndProbList, &lvItem);
  375. HardwareWiz->ProblemDevInst = (DEVNODE)lvItem.lParam;
  376. } else {
  377. HardwareWiz->ProblemDevInst = 0;
  378. }
  379. //
  380. // If the HardwareWiz->ProblemDevInst is 0 then the user selected none of the items
  381. // so we will move on to detection
  382. //
  383. if (HardwareWiz->ProblemDevInst == 0) {
  384. SetDlgMsgResult(hDlg, WM_NOTIFY, IDD_ADDDEVICE_ASKDETECT);
  385. } else {
  386. SetDlgMsgResult(hDlg, WM_NOTIFY, IDD_ADDDEVICE_PROBLIST_FINISH);
  387. }
  388. }
  389. break;
  390. case PSN_WIZFINISH:
  391. break;
  392. case PSN_WIZBACK:
  393. SetDlgMsgResult(hDlg, WM_NOTIFY, IDD_ADDDEVICE_CONNECTED);
  394. break;
  395. case NM_DBLCLK:
  396. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  397. break;
  398. case LVN_ITEMCHANGED:
  399. if (ListView_GetSelectedCount(HardwareWiz->hwndProbList) == 0) {
  400. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
  401. } else {
  402. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
  403. }
  404. }
  405. }
  406. break;
  407. case WM_SYSCOLORCHANGE:
  408. HdwWizPropagateMessage(hDlg, message, wParam, lParam);
  409. break;
  410. default:
  411. return FALSE;
  412. }
  413. return TRUE;
  414. }
  415. INT_PTR CALLBACK
  416. HdwProbListFinishDlgProc(
  417. HWND hDlg,
  418. UINT wMsg,
  419. WPARAM wParam,
  420. LPARAM lParam
  421. )
  422. /*++
  423. Routine Description:
  424. Arguments:
  425. Return Value:
  426. INT_PTR
  427. --*/
  428. {
  429. PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  430. UNREFERENCED_PARAMETER(wParam);
  431. if (wMsg == WM_INITDIALOG) {
  432. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  433. HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
  434. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
  435. SetWindowFont(GetDlgItem(hDlg, IDC_HDWNAME), HardwareWiz->hfontTextBigBold, TRUE);
  436. return TRUE;
  437. }
  438. switch (wMsg) {
  439. case WM_DESTROY:
  440. break;
  441. case WM_COMMAND:
  442. break;
  443. case WM_NOTIFY: {
  444. NMHDR FAR *pnmhdr = (NMHDR FAR *)lParam;
  445. switch (pnmhdr->code) {
  446. case PSN_SETACTIVE:
  447. {
  448. PTCHAR FriendlyName;
  449. PTCHAR ProblemText;
  450. ULONG Status, Problem;
  451. FriendlyName = BuildFriendlyName(HardwareWiz->ProblemDevInst);
  452. if (FriendlyName) {
  453. SetDlgItemText(hDlg, IDC_HDW_DESCRIPTION, FriendlyName);
  454. LocalFree(FriendlyName);
  455. }
  456. Status = Problem = 0;
  457. CM_Get_DevNode_Status(&Status,
  458. &Problem,
  459. HardwareWiz->ProblemDevInst,
  460. 0
  461. );
  462. ProblemText = DeviceProblemText(HardwareWiz->ProblemDevInst,
  463. Status,
  464. Problem
  465. );
  466. if (ProblemText) {
  467. SetDlgItemText(hDlg, IDC_PROBLEM_DESC, ProblemText);
  468. LocalFree(ProblemText);
  469. }
  470. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
  471. }
  472. break;
  473. case PSN_WIZFINISH:
  474. HardwareWiz->RunTroubleShooter = TRUE;
  475. break;
  476. case PSN_WIZBACK:
  477. SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_PROBLIST);
  478. break;
  479. }
  480. }
  481. break;
  482. default:
  483. return FALSE;
  484. }
  485. return TRUE;
  486. }