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.

790 lines
22 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. pcihal.c
  5. Abstract:
  6. Routines for the Pci Hal property page.
  7. Author:
  8. Santosh Jodh 10-July-1998
  9. --*/
  10. #include "setupp.h"
  11. #pragma hdrstop
  12. #include <windowsx.h>
  13. #define MSG_SIZE 2048
  14. #define Allocate(n) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, n)
  15. #define Release(p) HeapFree(GetProcessHeap(), 0, (LPVOID)p)
  16. typedef struct _PciHalPropData PCIHALPROPDATA, *PPCIHALPROPDATA;
  17. struct _PciHalPropData {
  18. HKEY LocalMachine;
  19. BOOLEAN CloseKey;
  20. DWORD Options;
  21. HDEVINFO DeviceInfoSet;
  22. PSP_DEVINFO_DATA DeviceInfoData;
  23. };
  24. const DWORD gPciPropHelpIds[] =
  25. {
  26. IDC_PCIHAL_ICON, (DWORD)-1, // Icon
  27. IDC_PCIHAL_DEVDESC, (DWORD)-1, // Name of PC
  28. IDC_PCIHAL_ENABLE, IDH_IRQ_ENABLE, // Enable IRQ Routing
  29. IDC_PCIHAL_MSSPEC, IDH_IRQ_MSSPEC, // Use $PIR table
  30. IDC_PCIHAL_REALMODE, IDH_IRQ_REALMODE, // Use table from Real-mode BIOS call
  31. IDC_PCIHAL_SETDEFAULTS, IDH_IRQ_SETDEFAULTS, // Set defaults for options
  32. IDC_PCIHAL_RESULTS, IDH_IRQ_RESULTS, // Status information
  33. 0,0
  34. };
  35. //
  36. // Table used to translate status codes into string ids.
  37. //
  38. UINT gStatus[PIR_STATUS_MAX + 1] = { IDS_PCIHAL_ERROR,
  39. IDS_PCIHAL_ENABLED,
  40. IDS_PCIHAL_DISABLED,
  41. IDS_PCIHAL_NOSTATUS
  42. };
  43. UINT gTableStatus[PIR_STATUS_TABLE_MAX] = { IDS_PCIHAL_TABLE_REGISTRY,
  44. IDS_PCIHAL_TABLE_MSSPEC,
  45. IDS_PCIHAL_TABLE_REALMODE,
  46. IDS_PCIHAL_TABLE_NONE,
  47. IDS_PCIHAL_TABLE_ERROR,
  48. IDS_PCIHAL_TABLE_BAD,
  49. IDS_PCIHAL_TABLE_SUCCESS
  50. };
  51. UINT gMiniportStatus[PIR_STATUS_MINIPORT_MAX] = { IDS_PCIHAL_MINIPORT_NORMAL,
  52. IDS_PCIHAL_MINIPORT_COMPATIBLE,
  53. IDS_PCIHAL_MINIPORT_OVERRIDE,
  54. IDS_PCIHAL_MINIPORT_NONE,
  55. IDS_PCIHAL_MINIPORT_ERROR,
  56. IDS_PCIHAL_MINIPORT_NOKEY,
  57. IDS_PCIHAL_MINIPORT_SUCCESS,
  58. IDS_PCIHAL_MINIPORT_INVALID
  59. };
  60. PCIHALPROPDATA gPciHalPropData = {0};
  61. VOID
  62. PciHalSetControls (
  63. IN HWND Dialog,
  64. IN DWORD Options,
  65. IN DWORD Attributes
  66. )
  67. /*++
  68. Routine Description:
  69. This routine sets the controls on the Irq Routing page to the
  70. specified options.
  71. Input Parameters:
  72. Dialog - Window handle for the property sheet page.
  73. Options - Pci Irq Routing options to be displayed.
  74. Return Value:
  75. None.
  76. --*/
  77. {
  78. BOOL enabled = FALSE;
  79. //
  80. // Enable the buttons depending on the options.
  81. //
  82. if (Options & PIR_OPTION_ENABLED)
  83. {
  84. enabled = TRUE;
  85. CheckDlgButton(Dialog, IDC_PCIHAL_ENABLE, 1);
  86. }
  87. CheckDlgButton(Dialog, IDC_PCIHAL_MSSPEC, Options & PIR_OPTION_MSSPEC);
  88. CheckDlgButton(Dialog, IDC_PCIHAL_REALMODE, Options & PIR_OPTION_REALMODE);
  89. //
  90. // Gray the windows not meaningful.
  91. //
  92. EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_ENABLE), !(Attributes & PIR_OPTION_ENABLED));
  93. EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_SETDEFAULTS), !(Attributes & PIR_OPTION_ENABLED));
  94. EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_MSSPEC), enabled && !(Attributes & PIR_OPTION_MSSPEC));
  95. EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_REALMODE), enabled && !(Attributes & PIR_OPTION_REALMODE));
  96. }
  97. LPTSTR
  98. PciHalGetDescription (
  99. IN HDEVINFO DeviceInfoSet,
  100. IN PSP_DEVINFO_DATA DeviceInfoData
  101. )
  102. /*++
  103. Routine Description:
  104. This routine allocates memory and returns the device description
  105. for the specified device.
  106. Input Parameters:
  107. DeviceInfoSet - For the device.
  108. DeviceInfoData - For the device.
  109. Return Value:
  110. Pointer to the description iff successful. Else NULL.
  111. --*/
  112. {
  113. LPTSTR desc;
  114. DWORD size;
  115. desc = NULL;
  116. //
  117. // Get the size of the description for this device.
  118. //
  119. size = 0;
  120. SetupDiGetDeviceRegistryProperty( DeviceInfoSet,
  121. DeviceInfoData,
  122. SPDRP_DEVICEDESC,
  123. NULL,
  124. NULL,
  125. 0,
  126. &size);
  127. if (size != 0)
  128. {
  129. //
  130. // Account for the terminating NULL character.
  131. //
  132. size++;
  133. //
  134. // Allocate memory for the device description.
  135. //
  136. desc = Allocate(size * sizeof(TCHAR));
  137. if (desc != NULL)
  138. {
  139. //
  140. // Get the device description.
  141. //
  142. if (SetupDiGetDeviceRegistryProperty( DeviceInfoSet,
  143. DeviceInfoData,
  144. SPDRP_DEVICEDESC,
  145. NULL,
  146. (PBYTE)desc,
  147. size * sizeof(TCHAR),
  148. &size) == FALSE)
  149. {
  150. Release(desc);
  151. desc = NULL;
  152. }
  153. }
  154. }
  155. return desc;
  156. }
  157. LPTSTR
  158. PciHalGetStatus (
  159. IN DWORD Status,
  160. IN DWORD TableStatus,
  161. IN DWORD MiniportStatus
  162. )
  163. /*++
  164. Routine Description:
  165. This routine converts the different status codes into
  166. a status string and returns the pointer to the string.
  167. The caller should free the memory when done using this
  168. string.
  169. Input Parameters:
  170. Status - Pci Irq Routing status.
  171. TableStatus - Pci Irq Routing Table status. Lower WORD
  172. indicates the source of the table. The upper WORD indicates
  173. the table processing status.
  174. MiniportStatus - Pci Irq Routing Miniport status. Lower
  175. WORD indicates the source of the miniport. The upper WORD
  176. indicates the miniport processing status.
  177. Return Value:
  178. Pointer to the status string iff successful. Else NULL.
  179. --*/
  180. {
  181. LPTSTR status;
  182. TCHAR temp[128];
  183. status = Allocate(MSG_SIZE * sizeof(TCHAR));
  184. if (status)
  185. {
  186. //
  187. // Get the status about Pci Irq Routing.
  188. //
  189. LoadString(MyModuleHandle, gStatus[Status], status, MSG_SIZE);
  190. //
  191. // Get the status about the source of Pci Irq Routing Table.
  192. //
  193. if ((TableStatus & 0xFFFF) < PIR_STATUS_TABLE_MAX)
  194. {
  195. lstrcat(status, L"\r\n\r\n");
  196. LoadString(MyModuleHandle, gTableStatus[TableStatus & 0xFFFF], temp, sizeof(temp)/sizeof(temp[0]));
  197. lstrcat(status, temp);
  198. }
  199. //
  200. // Get the status about the Pci Irq Routing table.
  201. //
  202. TableStatus >>= 16;
  203. if (TableStatus < PIR_STATUS_TABLE_MAX)
  204. {
  205. lstrcat(status, L"\r\n\r\n");
  206. LoadString(MyModuleHandle, gTableStatus[TableStatus], temp, sizeof(temp) / sizeof(TCHAR));
  207. lstrcat(status, temp);
  208. }
  209. //
  210. // Get the status about the source of the miniport.
  211. //
  212. if ((MiniportStatus & 0xFFFF) < PIR_STATUS_MINIPORT_MAX)
  213. {
  214. lstrcat(status, L"\r\n\r\n");
  215. LoadString(MyModuleHandle, gMiniportStatus[MiniportStatus & 0xFFFF], temp, sizeof(temp) / sizeof(TCHAR));
  216. lstrcat(status, temp);
  217. }
  218. //
  219. // Get the status about the miniport status.
  220. //
  221. MiniportStatus >>= 16;
  222. if (MiniportStatus < PIR_STATUS_MINIPORT_MAX)
  223. {
  224. lstrcat(status, L"\r\n\r\n");
  225. LoadString(MyModuleHandle, gMiniportStatus[MiniportStatus], temp, sizeof(temp) / sizeof(TCHAR));
  226. lstrcat(status, temp);
  227. }
  228. }
  229. return status;
  230. }
  231. BOOL
  232. PciHalOnInitDialog (
  233. IN HWND Dialog,
  234. IN WPARAM wParam,
  235. IN LPARAM lParam
  236. )
  237. /*++
  238. Routine Description:
  239. This routine initializes the property sheet page on creation.
  240. Input Paramters:
  241. Dialog - Window handle for the property sheet page.
  242. wParam - wParam of the WM_INITDIALOG message.
  243. lParam - Pointer to the property sheet page.
  244. Return Value:
  245. TRUE.
  246. --*/
  247. {
  248. PPCIHALPROPDATA pciHalPropData;
  249. HKEY hKey;
  250. DWORD size;
  251. DWORD status;
  252. DWORD tableStatus;
  253. DWORD miniportStatus;
  254. DWORD attributes;
  255. HICON hIconOld;
  256. HICON hIconNew;
  257. INT iconIndex;
  258. LPTSTR desc;
  259. SP_DEVINFO_LIST_DETAIL_DATA details;
  260. pciHalPropData = (PPCIHALPROPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
  261. //
  262. // Read the Pci Irq Routing options and status from the registry.
  263. //
  264. pciHalPropData->Options = 0;
  265. status = PIR_STATUS_MAX;
  266. tableStatus = PIR_STATUS_TABLE_MAX | (PIR_STATUS_TABLE_MAX << 16);
  267. miniportStatus = PIR_STATUS_MINIPORT_MAX | (PIR_STATUS_MINIPORT_MAX << 16);
  268. details.cbSize = sizeof(SP_DEVINFO_LIST_DETAIL_DATA);
  269. attributes = PIR_OPTION_ENABLED | PIR_OPTION_MSSPEC | PIR_OPTION_REALMODE;
  270. if (SetupDiGetDeviceInfoListDetail(pciHalPropData->DeviceInfoSet, &details)) {
  271. if (RegConnectRegistry((details.RemoteMachineName[0] == TEXT('\0'))? NULL : details.RemoteMachineName, HKEY_LOCAL_MACHINE, &pciHalPropData->LocalMachine) == ERROR_SUCCESS) {
  272. pciHalPropData->CloseKey = TRUE;
  273. if (RegOpenKeyEx(pciHalPropData->LocalMachine, REGSTR_PATH_PCIIR, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  274. {
  275. size = sizeof(pciHalPropData->Options);
  276. RegQueryValueEx(hKey, REGSTR_VAL_OPTIONS, NULL, NULL, (LPBYTE)&pciHalPropData->Options, &size);
  277. size = sizeof(status);
  278. RegQueryValueEx(hKey, REGSTR_VAL_STAT, NULL, NULL, (LPBYTE)&status, &size);
  279. size = sizeof(tableStatus);
  280. RegQueryValueEx(hKey, REGSTR_VAL_TABLE_STAT, NULL, NULL, (LPBYTE)&tableStatus, &size);
  281. size = sizeof(miniportStatus);
  282. RegQueryValueEx(hKey, REGSTR_VAL_MINIPORT_STAT, NULL, NULL, (LPBYTE)&miniportStatus, &size);
  283. RegCloseKey(hKey);
  284. }
  285. //
  286. // Gray out the controls if the user does not have READ+WRITE access to the REGSTR_PATH_PCIIR.
  287. //
  288. if (RegOpenKeyEx(pciHalPropData->LocalMachine, REGSTR_PATH_PCIIR, 0, KEY_READ | KEY_WRITE, &hKey) == ERROR_SUCCESS) {
  289. RegCloseKey(hKey);
  290. attributes = 0;
  291. if (RegOpenKeyEx(pciHalPropData->LocalMachine, REGSTR_PATH_BIOSINFO L"\\PciIrqRouting", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  292. size = sizeof(attributes);
  293. RegQueryValueEx(hKey, L"Attributes", NULL, NULL, (LPBYTE)&attributes, &size);
  294. RegCloseKey(hKey);
  295. }
  296. }
  297. }
  298. }
  299. //
  300. // Set the class icon.
  301. //
  302. if (SetupDiLoadClassIcon( &pciHalPropData->DeviceInfoData->ClassGuid,
  303. &hIconNew,
  304. &iconIndex) == TRUE)
  305. {
  306. hIconOld = (HICON)SendDlgItemMessage( Dialog,
  307. IDC_PCIHAL_ICON,
  308. STM_SETICON,
  309. (WPARAM)hIconNew,
  310. 0);
  311. if (hIconOld)
  312. {
  313. DestroyIcon(hIconOld);
  314. }
  315. }
  316. //
  317. // Set the device description.
  318. //
  319. desc = PciHalGetDescription(pciHalPropData->DeviceInfoSet, pciHalPropData->DeviceInfoData);
  320. if (desc)
  321. {
  322. SetDlgItemText(Dialog, IDC_PCIHAL_DEVDESC, desc);
  323. Release(desc);
  324. }
  325. //
  326. // Set the initial state of the controls.
  327. //
  328. PciHalSetControls(Dialog, pciHalPropData->Options, attributes);
  329. //
  330. // Display status.
  331. //
  332. desc = PciHalGetStatus(status, tableStatus, miniportStatus);
  333. if (desc)
  334. {
  335. SetDlgItemText(Dialog, IDC_PCIHAL_RESULTS, desc);
  336. Release(desc);
  337. }
  338. //
  339. // Let the system set the focus.
  340. //
  341. return TRUE;
  342. }
  343. BOOL
  344. PciHalOnCommand (
  345. IN HWND Dialog,
  346. IN WPARAM wParam,
  347. IN LPARAM lParam
  348. )
  349. /*++
  350. Routine Description:
  351. This routine handles the message when the user modifies something
  352. on the property sheet page.
  353. Input Parameters:
  354. Dialog - Window handle for the property sheet page.
  355. wParam - wParam of the WM_COMMAND message.
  356. lParam - lParam of the WM_COMMAND message.
  357. Return Value:
  358. TRUE if this function handles the message. Else FALSE.
  359. --*/
  360. {
  361. BOOL status;
  362. BOOL enabled;
  363. status = FALSE;
  364. switch (GET_WM_COMMAND_ID(wParam, lParam))
  365. {
  366. case IDC_PCIHAL_SETDEFAULTS:
  367. //
  368. // Set the controls to the default value.
  369. //
  370. status = TRUE;
  371. PciHalSetControls(Dialog, PIR_OPTION_DEFAULT, 0);
  372. break;
  373. case IDC_PCIHAL_ENABLE:
  374. //
  375. // Gray out the sub-options if Irq Routing is being disabled.
  376. //
  377. status = TRUE;
  378. enabled = IsDlgButtonChecked(Dialog, IDC_PCIHAL_ENABLE);
  379. EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_MSSPEC), enabled);
  380. EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_REALMODE), enabled);
  381. break;
  382. default:
  383. break;
  384. }
  385. return status;
  386. }
  387. BOOL
  388. PciHalOnNotify(
  389. IN HWND Dialog,
  390. IN WPARAM wParam,
  391. IN LPARAM lParam
  392. )
  393. /*++
  394. Routine Description:
  395. This routine handles the WM_NOTIFY message for the Pci Irq Routing
  396. property sheet page.
  397. Input Parameters:
  398. Dialog - Window handle for the property sheet page.
  399. wParam - wParam of the WM_NOTIFY message.
  400. lParam - lParam of the WM_NOTIFY message.
  401. Return Value:
  402. TRUE if this function handles the message. Else FALSE.
  403. --*/
  404. {
  405. BOOL status = FALSE;
  406. HKEY hKey;
  407. DWORD options;
  408. switch (((LPNMHDR)lParam)->code)
  409. {
  410. case PSN_RESET:
  411. //
  412. // User hit cancel.
  413. //
  414. status = TRUE;
  415. if (RegOpenKey(gPciHalPropData.LocalMachine, REGSTR_PATH_PCIIR, &hKey) == ERROR_SUCCESS)
  416. {
  417. RegSetValueEx( hKey,
  418. REGSTR_VAL_OPTIONS,
  419. 0,
  420. REG_DWORD,
  421. (CONST BYTE *)&gPciHalPropData.Options,
  422. sizeof(gPciHalPropData.Options));
  423. RegCloseKey(hKey);
  424. }
  425. break;
  426. case PSN_APPLY:
  427. //
  428. // User hit Apply or Ok.
  429. //
  430. status = TRUE;
  431. //
  432. // Read the different control status and write it to the registry.
  433. //
  434. options = gPciHalPropData.Options;
  435. if (IsDlgButtonChecked(Dialog, IDC_PCIHAL_ENABLE) == BST_CHECKED)
  436. {
  437. options |= PIR_OPTION_ENABLED;
  438. }
  439. else
  440. {
  441. options &= ~PIR_OPTION_ENABLED;
  442. }
  443. if (IsDlgButtonChecked(Dialog, IDC_PCIHAL_MSSPEC))
  444. {
  445. options |= PIR_OPTION_MSSPEC;
  446. }
  447. else
  448. {
  449. options &= ~PIR_OPTION_MSSPEC;
  450. }
  451. if (IsDlgButtonChecked(Dialog, IDC_PCIHAL_REALMODE))
  452. {
  453. options |= PIR_OPTION_REALMODE;
  454. }
  455. else
  456. {
  457. options &= ~PIR_OPTION_REALMODE;
  458. }
  459. if (RegOpenKey(gPciHalPropData.LocalMachine, REGSTR_PATH_PCIIR, &hKey) == ERROR_SUCCESS)
  460. {
  461. RegSetValueEx( hKey,
  462. REGSTR_VAL_OPTIONS,
  463. 0,
  464. REG_DWORD,
  465. (CONST BYTE *)&options,
  466. sizeof(options));
  467. RegCloseKey(hKey);
  468. }
  469. //
  470. // Reboot if any of the options changed.
  471. //
  472. if (options != gPciHalPropData.Options)
  473. {
  474. SP_DEVINSTALL_PARAMS deviceInstallParams;
  475. memset(&deviceInstallParams, 0, sizeof(deviceInstallParams));
  476. deviceInstallParams.cbSize = sizeof(deviceInstallParams);
  477. if (SetupDiGetDeviceInstallParams( gPciHalPropData.DeviceInfoSet,
  478. gPciHalPropData.DeviceInfoData,
  479. &deviceInstallParams))
  480. {
  481. deviceInstallParams.Flags |= DI_NEEDREBOOT;
  482. SetupDiSetDeviceInstallParams( gPciHalPropData.DeviceInfoSet,
  483. gPciHalPropData.DeviceInfoData,
  484. &deviceInstallParams);
  485. }
  486. }
  487. break;
  488. default:
  489. break;
  490. }
  491. return status;
  492. }
  493. INT_PTR
  494. PciHalDialogProc(
  495. IN HWND Dialog,
  496. IN UINT Message,
  497. IN WPARAM wParam,
  498. IN LPARAM lParam
  499. )
  500. /*++
  501. Routine Description:
  502. This is the DlgProc for the Pci Irq Routing property sheet page.
  503. Input Parameters:
  504. Standard DlgProc parameters.
  505. Return Value:
  506. TRUE if it handles the message. Else FALSE.
  507. --*/
  508. {
  509. BOOL status = FALSE;
  510. PCWSTR szHelpFile = L"devmgr.hlp";
  511. switch (Message)
  512. {
  513. case WM_INITDIALOG:
  514. status = PciHalOnInitDialog(Dialog, wParam, lParam);
  515. break;
  516. case WM_COMMAND:
  517. status = PciHalOnCommand(Dialog, wParam, lParam);
  518. break;
  519. case WM_NOTIFY:
  520. status = PciHalOnNotify(Dialog, wParam, lParam);
  521. break;
  522. case WM_HELP:
  523. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, szHelpFile, HELP_WM_HELP, (ULONG_PTR)gPciPropHelpIds);
  524. status = TRUE;
  525. break;
  526. case WM_CONTEXTMENU:
  527. WinHelp((HWND)wParam, szHelpFile, HELP_CONTEXTMENU, (ULONG_PTR)gPciPropHelpIds);
  528. status = TRUE;
  529. break;
  530. case WM_DESTROY:
  531. if (gPciHalPropData.CloseKey) {
  532. RegCloseKey(gPciHalPropData.LocalMachine);
  533. gPciHalPropData.CloseKey = FALSE;
  534. }
  535. default:
  536. break;
  537. }
  538. return status;
  539. }
  540. DWORD
  541. PciHalCoInstaller(
  542. IN DI_FUNCTION InstallFunction,
  543. IN HDEVINFO DeviceInfoSet,
  544. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
  545. IN OUT PCOINSTALLER_CONTEXT_DATA Context
  546. )
  547. {
  548. BOOL status;
  549. HPROPSHEETPAGE pageHandle;
  550. PROPSHEETPAGE page;
  551. SP_DEVINFO_LIST_DETAIL_DATA details;
  552. SP_ADDPROPERTYPAGE_DATA addPropertyPageData;
  553. switch (InstallFunction) {
  554. case DIF_ADDPROPERTYPAGE_ADVANCED:
  555. case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED:
  556. details.cbSize = sizeof(SP_DEVINFO_LIST_DETAIL_DATA);
  557. if (SetupDiGetDeviceInfoListDetail(DeviceInfoSet, &details)) {
  558. if (RegConnectRegistry((details.RemoteMachineName[0] == TEXT('\0'))? NULL : details.RemoteMachineName, HKEY_LOCAL_MACHINE, &gPciHalPropData.LocalMachine) == ERROR_SUCCESS) {
  559. RegCloseKey(gPciHalPropData.LocalMachine);
  560. status = TRUE;
  561. break;
  562. }
  563. }
  564. default:
  565. status = FALSE;
  566. break;
  567. }
  568. if (status) {
  569. ZeroMemory(&addPropertyPageData, sizeof(SP_ADDPROPERTYPAGE_DATA));
  570. addPropertyPageData.ClassInstallHeader.cbSize =
  571. sizeof(SP_CLASSINSTALL_HEADER);
  572. if (SetupDiGetClassInstallParams(DeviceInfoSet, DeviceInfoData,
  573. (PSP_CLASSINSTALL_HEADER)&addPropertyPageData,
  574. sizeof(SP_ADDPROPERTYPAGE_DATA), NULL )) {
  575. if (addPropertyPageData.NumDynamicPages < MAX_INSTALLWIZARD_DYNAPAGES) {
  576. //
  577. // Initialize our globals here.
  578. //
  579. gPciHalPropData.DeviceInfoSet = DeviceInfoSet;
  580. gPciHalPropData.DeviceInfoData = DeviceInfoData;
  581. //
  582. // Initialize our property page here.
  583. //
  584. memset(&page, 0, sizeof(PROPSHEETPAGE));
  585. page.dwSize = sizeof(PROPSHEETPAGE);
  586. page.hInstance = MyModuleHandle;
  587. page.pszTemplate = MAKEINTRESOURCE(IDD_PCIHAL_PROPPAGE);
  588. page.pfnDlgProc = PciHalDialogProc;
  589. page.lParam = (LPARAM)&gPciHalPropData;
  590. pageHandle = CreatePropertySheetPage(&page);
  591. if (pageHandle != NULL)
  592. {
  593. addPropertyPageData.DynamicPages[addPropertyPageData.NumDynamicPages++] = pageHandle;
  594. SetupDiSetClassInstallParams(DeviceInfoSet, DeviceInfoData,
  595. (PSP_CLASSINSTALL_HEADER)&addPropertyPageData,
  596. sizeof(SP_ADDPROPERTYPAGE_DATA));
  597. return NO_ERROR;
  598. }
  599. }
  600. }
  601. }
  602. return NO_ERROR;
  603. }