1 /* 2 * New device installer (newdev.dll) 3 * 4 * Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #include "newdev_private.h" 22 23 #include <wincon.h> 24 #include <cfgmgr32.h> 25 #include <shlobj.h> 26 #include <shlwapi.h> 27 28 HANDLE hThread; 29 30 static VOID 31 CenterWindow( 32 IN HWND hWnd) 33 { 34 HWND hWndParent; 35 RECT rcParent; 36 RECT rcWindow; 37 38 hWndParent = GetParent(hWnd); 39 if (hWndParent == NULL) 40 hWndParent = GetDesktopWindow(); 41 42 GetWindowRect(hWndParent, &rcParent); 43 GetWindowRect(hWnd, &rcWindow); 44 45 /* Check if the child window fits inside the parent window */ 46 if (rcWindow.left < rcParent.left || rcWindow.top < rcParent.top || 47 rcWindow.right > rcParent.right || rcWindow.bottom > rcParent.bottom) 48 { 49 return; 50 } 51 52 SetWindowPos( 53 hWnd, 54 HWND_TOP, 55 ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2, 56 ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2, 57 0, 58 0, 59 SWP_NOSIZE); 60 } 61 62 static BOOL 63 SetFailedInstall( 64 IN HDEVINFO DeviceInfoSet, 65 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL, 66 IN BOOLEAN Set) 67 { 68 DWORD dwType, dwSize, dwFlags = 0; 69 70 dwSize = sizeof(dwFlags); 71 if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet, 72 DevInfoData, 73 SPDRP_CONFIGFLAGS, 74 &dwType, 75 (PBYTE)&dwFlags, 76 dwSize, 77 &dwSize)) 78 { 79 return FALSE; 80 } 81 82 if (Set) 83 dwFlags |= CONFIGFLAG_FAILEDINSTALL; 84 else 85 dwFlags &= ~CONFIGFLAG_FAILEDINSTALL; 86 87 if (!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, 88 DevInfoData, 89 SPDRP_CONFIGFLAGS, 90 (PBYTE)&dwFlags, 91 dwSize)) 92 { 93 94 return FALSE; 95 } 96 97 if (Set) 98 { 99 /* Set the 'Unknown' device class */ 100 PWSTR pszUnknown = L"Unknown"; 101 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet, 102 DevInfoData, 103 SPDRP_CLASS, 104 (PBYTE)pszUnknown, 105 (wcslen(pszUnknown) + 1) * sizeof(WCHAR)); 106 107 PWSTR pszUnknownGuid = L"{4D36E97E-E325-11CE-BFC1-08002BE10318}"; 108 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet, 109 DevInfoData, 110 SPDRP_CLASSGUID, 111 (PBYTE)pszUnknownGuid, 112 (wcslen(pszUnknownGuid) + 1) * sizeof(WCHAR)); 113 114 /* Set device problem code CM_PROB_FAILED_INSTALL */ 115 CM_Set_DevNode_Problem(DevInfoData->DevInst, 116 CM_PROB_FAILED_INSTALL, 117 CM_SET_DEVNODE_PROBLEM_OVERRIDE); 118 } 119 120 return TRUE; 121 } 122 123 static BOOL 124 CanDisableDevice( 125 IN DEVINST DevInst, 126 IN HMACHINE hMachine, 127 OUT BOOL *CanDisable) 128 { 129 CONFIGRET cr; 130 ULONG Status, ProblemNumber; 131 BOOL Ret = FALSE; 132 133 cr = CM_Get_DevNode_Status_Ex(&Status, 134 &ProblemNumber, 135 DevInst, 136 0, 137 hMachine); 138 if (cr == CR_SUCCESS) 139 { 140 *CanDisable = ((Status & DN_DISABLEABLE) != 0); 141 Ret = TRUE; 142 } 143 144 return Ret; 145 } 146 147 static BOOL 148 IsDeviceStarted( 149 IN DEVINST DevInst, 150 IN HMACHINE hMachine, 151 OUT BOOL *IsEnabled) 152 { 153 CONFIGRET cr; 154 ULONG Status, ProblemNumber; 155 BOOL Ret = FALSE; 156 157 cr = CM_Get_DevNode_Status_Ex( 158 &Status, 159 &ProblemNumber, 160 DevInst, 161 0, 162 hMachine); 163 if (cr == CR_SUCCESS) 164 { 165 *IsEnabled = ((Status & DN_STARTED) != 0); 166 Ret = TRUE; 167 } 168 169 return Ret; 170 } 171 172 static BOOL 173 StartDevice( 174 IN HDEVINFO DeviceInfoSet, 175 IN PSP_DEVINFO_DATA DevInfoData OPTIONAL, 176 IN BOOL bEnable, 177 IN DWORD HardwareProfile OPTIONAL, 178 OUT BOOL *bNeedReboot OPTIONAL) 179 { 180 SP_PROPCHANGE_PARAMS pcp; 181 SP_DEVINSTALL_PARAMS dp; 182 DWORD LastErr; 183 BOOL Ret = FALSE; 184 185 pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); 186 pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; 187 pcp.HwProfile = HardwareProfile; 188 189 if (bEnable) 190 { 191 /* try to enable the device on the global profile */ 192 pcp.StateChange = DICS_ENABLE; 193 pcp.Scope = DICS_FLAG_GLOBAL; 194 195 /* ignore errors */ 196 LastErr = GetLastError(); 197 if (SetupDiSetClassInstallParams( 198 DeviceInfoSet, 199 DevInfoData, 200 &pcp.ClassInstallHeader, 201 sizeof(SP_PROPCHANGE_PARAMS))) 202 { 203 SetupDiCallClassInstaller( 204 DIF_PROPERTYCHANGE, 205 DeviceInfoSet, 206 DevInfoData); 207 } 208 SetLastError(LastErr); 209 } 210 211 /* try config-specific */ 212 pcp.StateChange = (bEnable ? DICS_ENABLE : DICS_DISABLE); 213 pcp.Scope = DICS_FLAG_CONFIGSPECIFIC; 214 215 if (SetupDiSetClassInstallParams( 216 DeviceInfoSet, 217 DevInfoData, 218 &pcp.ClassInstallHeader, 219 sizeof(SP_PROPCHANGE_PARAMS)) && 220 SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, 221 DeviceInfoSet, 222 DevInfoData)) 223 { 224 dp.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 225 if (SetupDiGetDeviceInstallParams( 226 DeviceInfoSet, 227 DevInfoData, 228 &dp)) 229 { 230 if (bNeedReboot != NULL) 231 { 232 *bNeedReboot = ((dp.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) != 0); 233 } 234 235 Ret = TRUE; 236 } 237 } 238 return Ret; 239 } 240 241 static DWORD WINAPI 242 FindDriverProc( 243 IN LPVOID lpParam) 244 { 245 PDEVINSTDATA DevInstData; 246 BOOL result = FALSE; 247 248 DevInstData = (PDEVINSTDATA)lpParam; 249 250 result = ScanFoldersForDriver(DevInstData); 251 252 if (result) 253 { 254 PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 1, 0); 255 } 256 else 257 { 258 if (!DevInstData->bUpdate) 259 { 260 /* Update device configuration */ 261 SetFailedInstall(DevInstData->hDevInfo, 262 &DevInstData->devInfoData, 263 TRUE); 264 } 265 PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 0, 0); 266 } 267 return 0; 268 } 269 270 static DWORD WINAPI 271 InstallDriverProc( 272 IN LPVOID lpParam) 273 { 274 PDEVINSTDATA DevInstData; 275 BOOL res; 276 277 DevInstData = (PDEVINSTDATA)lpParam; 278 res = InstallCurrentDriver(DevInstData); 279 PostMessage(DevInstData->hDialog, WM_INSTALL_FINISHED, res ? 0 : 1, 0); 280 return 0; 281 } 282 283 static VOID 284 PopulateCustomPathCombo( 285 IN HWND hwndCombo) 286 { 287 HKEY hKey = NULL; 288 DWORD dwRegType; 289 DWORD dwPathLength = 0; 290 LPWSTR Buffer = NULL; 291 LPCWSTR Path; 292 LONG rc; 293 294 (void)ComboBox_ResetContent(hwndCombo); 295 296 /* RegGetValue would have been better... */ 297 rc = RegOpenKeyEx( 298 HKEY_LOCAL_MACHINE, 299 REGSTR_PATH_SETUP REGSTR_KEY_SETUP, 300 0, 301 KEY_QUERY_VALUE, 302 &hKey); 303 if (rc != ERROR_SUCCESS) 304 { 305 TRACE("RegOpenKeyEx() failed with error 0x%lx\n", rc); 306 goto cleanup; 307 } 308 rc = RegQueryValueExW( 309 hKey, 310 L"Installation Sources", 311 NULL, 312 &dwRegType, 313 NULL, 314 &dwPathLength); 315 if (rc != ERROR_SUCCESS || dwRegType != REG_MULTI_SZ) 316 { 317 TRACE("RegQueryValueEx() failed with error 0x%lx\n", rc); 318 goto cleanup; 319 } 320 321 /* Allocate enough space to add 2 NULL chars at the end of the string */ 322 Buffer = HeapAlloc(GetProcessHeap(), 0, dwPathLength + 2 * sizeof(WCHAR)); 323 if (!Buffer) 324 { 325 TRACE("HeapAlloc() failed\n"); 326 goto cleanup; 327 } 328 rc = RegQueryValueExW( 329 hKey, 330 L"Installation Sources", 331 NULL, 332 NULL, 333 (LPBYTE)Buffer, 334 &dwPathLength); 335 if (rc != ERROR_SUCCESS) 336 { 337 TRACE("RegQueryValueEx() failed with error 0x%lx\n", rc); 338 goto cleanup; 339 } 340 341 Buffer[dwPathLength / sizeof(WCHAR)] = UNICODE_NULL; 342 Buffer[dwPathLength / sizeof(WCHAR) + 1] = UNICODE_NULL; 343 344 /* Populate combo box */ 345 for (Path = Buffer; *Path; Path += wcslen(Path) + 1) 346 { 347 (void)ComboBox_AddString(hwndCombo, Path); 348 if (Path == Buffer) 349 (void)ComboBox_SetCurSel(hwndCombo, 0); 350 } 351 352 cleanup: 353 if (hKey != NULL) 354 RegCloseKey(hKey); 355 HeapFree(GetProcessHeap(), 0, Buffer); 356 } 357 358 static VOID 359 SaveCustomPath( 360 IN HWND hwndCombo) 361 { 362 LPWSTR CustomPath = NULL; 363 DWORD CustomPathLength; 364 LPWSTR Buffer = NULL; 365 LPWSTR pBuffer; /* Pointer into Buffer */ 366 int ItemsCount, Length; 367 int i; 368 DWORD TotalLength = 0; 369 BOOL UseCustomPath = TRUE; 370 HKEY hKey = NULL; 371 LONG rc; 372 373 /* Get custom path */ 374 Length = ComboBox_GetTextLength(hwndCombo) + 1; 375 CustomPath = HeapAlloc(GetProcessHeap(), 0, Length * sizeof(WCHAR)); 376 if (!CustomPath) 377 { 378 TRACE("HeapAlloc() failed\n"); 379 goto cleanup; 380 } 381 CustomPathLength = GetWindowTextW(hwndCombo, CustomPath, Length) + 1; 382 383 /* Calculate length of the buffer */ 384 ItemsCount = ComboBox_GetCount(hwndCombo); 385 if (ItemsCount == CB_ERR) 386 { 387 TRACE("ComboBox_GetCount() failed\n"); 388 goto cleanup; 389 } 390 for (i = 0; i < ItemsCount; i++) 391 { 392 Length = ComboBox_GetLBTextLen(hwndCombo, i); 393 if (Length == CB_ERR) 394 { 395 TRACE("ComboBox_GetLBTextLen() failed\n"); 396 goto cleanup; 397 } 398 TotalLength += Length + 1; 399 } 400 TotalLength++; /* Final NULL char */ 401 402 /* Allocate buffer */ 403 Buffer = HeapAlloc(GetProcessHeap(), 0, (CustomPathLength + TotalLength + 1) * sizeof(WCHAR)); 404 if (!Buffer) 405 { 406 TRACE("HeapAlloc() failed\n"); 407 goto cleanup; 408 } 409 410 /* Fill the buffer */ 411 pBuffer = &Buffer[CustomPathLength]; 412 for (i = 0; i < ItemsCount; i++) 413 { 414 Length = ComboBox_GetLBText(hwndCombo, i, pBuffer); 415 if (Length == CB_ERR) 416 { 417 TRACE("ComboBox_GetLBText() failed\n"); 418 goto cleanup; 419 } 420 else if (UseCustomPath && _wcsicmp(CustomPath, pBuffer) == 0) 421 UseCustomPath = FALSE; 422 pBuffer += 1 + Length; 423 } 424 *pBuffer = '\0'; /* Add final NULL char */ 425 426 if (!UseCustomPath) 427 { 428 /* Nothing to save to registry */ 429 goto cleanup; 430 } 431 432 TotalLength += CustomPathLength; 433 wcscpy(Buffer, CustomPath); 434 435 /* Save the buffer */ 436 /* RegSetKeyValue would have been better... */ 437 rc = RegOpenKeyEx( 438 HKEY_LOCAL_MACHINE, 439 REGSTR_PATH_SETUP REGSTR_KEY_SETUP, 440 0, 441 KEY_SET_VALUE, 442 &hKey); 443 if (rc != ERROR_SUCCESS) 444 { 445 TRACE("RegOpenKeyEx() failed with error 0x%lx\n", rc); 446 goto cleanup; 447 } 448 rc = RegSetValueExW( 449 hKey, 450 L"Installation Sources", 451 0, 452 REG_MULTI_SZ, 453 (const BYTE*)Buffer, 454 TotalLength * sizeof(WCHAR)); 455 if (rc != ERROR_SUCCESS) 456 { 457 TRACE("RegSetValueEx() failed with error 0x%lx\n", rc); 458 goto cleanup; 459 } 460 461 cleanup: 462 if (hKey != NULL) 463 RegCloseKey(hKey); 464 HeapFree(GetProcessHeap(), 0, CustomPath); 465 HeapFree(GetProcessHeap(), 0, Buffer); 466 } 467 468 static INT_PTR CALLBACK 469 WelcomeDlgProc( 470 IN HWND hwndDlg, 471 IN UINT uMsg, 472 IN WPARAM wParam, 473 IN LPARAM lParam) 474 { 475 PDEVINSTDATA DevInstData; 476 UNREFERENCED_PARAMETER(wParam); 477 478 /* Retrieve pointer to the global setup data */ 479 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 480 481 switch (uMsg) 482 { 483 case WM_INITDIALOG: 484 { 485 HWND hwndControl; 486 DWORD dwStyle; 487 488 /* Get pointer to the global setup data */ 489 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam; 490 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)DevInstData); 491 492 hwndControl = GetParent(hwndDlg); 493 494 /* Center the wizard window */ 495 CenterWindow(hwndControl); 496 497 /* Hide the system menu */ 498 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE); 499 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU); 500 501 /* Set title font */ 502 SendDlgItemMessage( 503 hwndDlg, 504 IDC_WELCOMETITLE, 505 WM_SETFONT, 506 (WPARAM)DevInstData->hTitleFont, 507 (LPARAM)TRUE); 508 509 SendDlgItemMessage( 510 hwndDlg, 511 IDC_DEVICE, 512 WM_SETTEXT, 513 0, 514 (LPARAM)DevInstData->buffer); 515 516 SendDlgItemMessage( 517 hwndDlg, 518 IDC_RADIO_AUTO, 519 BM_SETCHECK, 520 (WPARAM)TRUE, 521 (LPARAM)0); 522 523 if (!DevInstData->bUpdate) 524 { 525 SetFailedInstall(DevInstData->hDevInfo, 526 &DevInstData->devInfoData, 527 TRUE); 528 } 529 break; 530 } 531 532 case WM_NOTIFY: 533 { 534 LPNMHDR lpnm = (LPNMHDR)lParam; 535 536 switch (lpnm->code) 537 { 538 case PSN_SETACTIVE: 539 /* Enable the Next button */ 540 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT); 541 break; 542 543 case PSN_WIZNEXT: 544 /* Handle a Next button click, if necessary */ 545 if (SendDlgItemMessage(hwndDlg, IDC_RADIO_AUTO, BM_GETCHECK, (WPARAM)0, (LPARAM)0) == BST_CHECKED) 546 { 547 if (PrepareFoldersToScan(DevInstData, TRUE, FALSE, NULL)) 548 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_SEARCHDRV); 549 else 550 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_INSTALLFAILED); 551 } 552 return TRUE; 553 554 default: 555 break; 556 } 557 break; 558 } 559 560 default: 561 break; 562 } 563 564 return FALSE; 565 } 566 567 static void 568 IncludePath(HWND Dlg, BOOL Enabled) 569 { 570 EnableWindow(GetDlgItem(Dlg, IDC_COMBO_PATH), Enabled); 571 EnableWindow(GetDlgItem(Dlg, IDC_BROWSE), Enabled); 572 } 573 574 static void 575 AutoDriver(HWND Dlg, BOOL Enabled) 576 { 577 EnableWindow(GetDlgItem(Dlg, IDC_CHECK_MEDIA), Enabled); 578 EnableWindow(GetDlgItem(Dlg, IDC_CHECK_PATH), Enabled); 579 IncludePath(Dlg, Enabled & IsDlgButtonChecked(Dlg, IDC_CHECK_PATH)); 580 } 581 582 static INT CALLBACK 583 BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) 584 { 585 BOOL bValid = FALSE; 586 587 switch (uMsg) 588 { 589 case BFFM_INITIALIZED: 590 { 591 PCWSTR pszPath = ((PDEVINSTDATA)lpData)->CustomSearchPath; 592 593 bValid = CheckBestDriver((PDEVINSTDATA)lpData, pszPath); 594 SendMessageW(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)pszPath); 595 SendMessageW(hwnd, BFFM_ENABLEOK, 0, bValid); 596 break; 597 } 598 599 case BFFM_SELCHANGED: 600 { 601 WCHAR szDir[MAX_PATH]; 602 603 if (SHGetPathFromIDListW((LPITEMIDLIST)lParam, szDir)) 604 { 605 bValid = CheckBestDriver((PDEVINSTDATA)lpData, szDir); 606 } 607 PostMessageW(hwnd, BFFM_ENABLEOK, 0, bValid); 608 break; 609 } 610 } 611 return 0; 612 } 613 614 static INT_PTR CALLBACK 615 CHSourceDlgProc( 616 IN HWND hwndDlg, 617 IN UINT uMsg, 618 IN WPARAM wParam, 619 IN LPARAM lParam) 620 { 621 PDEVINSTDATA DevInstData; 622 623 /* Retrieve pointer to the global setup data */ 624 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 625 626 switch (uMsg) 627 { 628 case WM_INITDIALOG: 629 { 630 HWND hwndControl, hwndCombo; 631 DWORD dwStyle; 632 COMBOBOXINFO info = { sizeof(info) }; 633 634 /* Get pointer to the global setup data */ 635 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam; 636 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)DevInstData); 637 638 hwndControl = GetParent(hwndDlg); 639 640 /* Center the wizard window */ 641 CenterWindow(hwndControl); 642 643 /* Hide the system menu */ 644 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE); 645 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU); 646 647 hwndCombo = GetDlgItem(hwndDlg, IDC_COMBO_PATH); 648 PopulateCustomPathCombo(hwndCombo); 649 650 GetComboBoxInfo(hwndCombo, &info); 651 SHAutoComplete(info.hwndItem, SHACF_FILESYS_DIRS); 652 653 SendDlgItemMessage( 654 hwndDlg, 655 IDC_RADIO_SEARCHHERE, 656 BM_SETCHECK, 657 (WPARAM)TRUE, 658 (LPARAM)0); 659 AutoDriver(hwndDlg, TRUE); 660 IncludePath(hwndDlg, FALSE); 661 662 /* Disable manual driver choice for now */ 663 EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_CHOOSE), FALSE); 664 665 break; 666 } 667 668 case WM_COMMAND: 669 { 670 switch (LOWORD(wParam)) 671 { 672 case IDC_RADIO_SEARCHHERE: 673 AutoDriver(hwndDlg, TRUE); 674 return TRUE; 675 676 case IDC_RADIO_CHOOSE: 677 AutoDriver(hwndDlg, FALSE); 678 return TRUE; 679 680 case IDC_CHECK_PATH: 681 IncludePath(hwndDlg, IsDlgButtonChecked(hwndDlg, IDC_CHECK_PATH)); 682 return TRUE; 683 684 case IDC_BROWSE: 685 { 686 BROWSEINFOW bi = { 0 }; 687 LPITEMIDLIST pidl; 688 WCHAR Title[MAX_PATH]; 689 WCHAR CustomSearchPath[MAX_PATH] = { 0 }; 690 INT len, idx = (INT)SendDlgItemMessageW(hwndDlg, IDC_COMBO_PATH, CB_GETCURSEL, 0, 0); 691 LoadStringW(hDllInstance, IDS_BROWSE_FOR_FOLDER_TITLE, Title, _countof(Title)); 692 693 if (idx == CB_ERR) 694 len = GetWindowTextLengthW(GetDlgItem(hwndDlg, IDC_COMBO_PATH)); 695 else 696 len = (INT)SendDlgItemMessageW(hwndDlg, IDC_COMBO_PATH, CB_GETLBTEXTLEN, idx, 0); 697 698 if (len < _countof(CustomSearchPath)) 699 { 700 if (idx == CB_ERR) 701 GetWindowTextW(GetDlgItem(hwndDlg, IDC_COMBO_PATH), CustomSearchPath, _countof(CustomSearchPath)); 702 else 703 SendDlgItemMessageW(hwndDlg, IDC_COMBO_PATH, CB_GETLBTEXT, idx, (LPARAM)CustomSearchPath); 704 } 705 DevInstData->CustomSearchPath = CustomSearchPath; 706 707 bi.hwndOwner = hwndDlg; 708 bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NONEWFOLDERBUTTON; 709 bi.lpszTitle = Title; 710 bi.lpfn = BrowseCallbackProc; 711 bi.lParam = (LPARAM)DevInstData; 712 pidl = SHBrowseForFolderW(&bi); 713 if (pidl) 714 { 715 WCHAR Directory[MAX_PATH]; 716 IMalloc* malloc; 717 718 if (SHGetPathFromIDListW(pidl, Directory)) 719 { 720 /* Set the IDC_COMBO_PATH text */ 721 SetWindowTextW(GetDlgItem(hwndDlg, IDC_COMBO_PATH), Directory); 722 } 723 724 /* Free memory, if possible */ 725 if (SUCCEEDED(SHGetMalloc(&malloc))) 726 { 727 IMalloc_Free(malloc, pidl); 728 IMalloc_Release(malloc); 729 } 730 return TRUE; 731 } 732 break; 733 } 734 } 735 break; 736 } 737 738 case WM_NOTIFY: 739 { 740 LPNMHDR lpnm = (LPNMHDR)lParam; 741 742 switch (lpnm->code) 743 { 744 case PSN_SETACTIVE: 745 /* Enable the Next and Back buttons */ 746 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK); 747 break; 748 749 case PSN_WIZNEXT: 750 /* Handle a Next button click, if necessary */ 751 if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_SEARCHHERE)) 752 { 753 SaveCustomPath(GetDlgItem(hwndDlg, IDC_COMBO_PATH)); 754 HeapFree(GetProcessHeap(), 0, DevInstData->CustomSearchPath); 755 DevInstData->CustomSearchPath = NULL; 756 if (PrepareFoldersToScan( 757 DevInstData, 758 IsDlgButtonChecked(hwndDlg, IDC_CHECK_MEDIA), 759 IsDlgButtonChecked(hwndDlg, IDC_CHECK_PATH), 760 GetDlgItem(hwndDlg, IDC_COMBO_PATH))) 761 { 762 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_SEARCHDRV); 763 } 764 else 765 { 766 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_INSTALLFAILED); 767 } 768 } 769 else 770 { 771 /* FIXME */; 772 } 773 return TRUE; 774 775 default: 776 break; 777 } 778 break; 779 } 780 781 default: 782 break; 783 } 784 785 return FALSE; 786 } 787 788 static INT_PTR CALLBACK 789 SearchDrvDlgProc( 790 IN HWND hwndDlg, 791 IN UINT uMsg, 792 IN WPARAM wParam, 793 IN LPARAM lParam) 794 { 795 PDEVINSTDATA DevInstData; 796 DWORD dwThreadId; 797 798 /* Retrieve pointer to the global setup data */ 799 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 800 801 switch (uMsg) 802 { 803 case WM_INITDIALOG: 804 { 805 HWND hwndControl; 806 DWORD dwStyle; 807 808 /* Get pointer to the global setup data */ 809 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam; 810 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)DevInstData); 811 812 DevInstData->hDialog = hwndDlg; 813 hwndControl = GetParent(hwndDlg); 814 815 /* Center the wizard window */ 816 CenterWindow(hwndControl); 817 818 SendDlgItemMessage( 819 hwndDlg, 820 IDC_DEVICE, 821 WM_SETTEXT, 822 0, 823 (LPARAM)DevInstData->buffer); 824 825 /* Hide the system menu */ 826 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE); 827 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU); 828 break; 829 } 830 831 case WM_SEARCH_FINISHED: 832 { 833 CloseHandle(hThread); 834 hThread = 0; 835 if (wParam == 0) 836 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_NODRIVER); 837 else 838 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_INSTALLDRV); 839 break; 840 } 841 842 case WM_NOTIFY: 843 { 844 LPNMHDR lpnm = (LPNMHDR)lParam; 845 846 switch (lpnm->code) 847 { 848 case PSN_SETACTIVE: 849 PropSheet_SetWizButtons(GetParent(hwndDlg), !PSWIZB_NEXT | !PSWIZB_BACK); 850 /* Yes, we can safely ignore the problem (if any) */ 851 SetupDiDestroyDriverInfoList( 852 DevInstData->hDevInfo, 853 &DevInstData->devInfoData, 854 SPDIT_COMPATDRIVER); 855 hThread = CreateThread(NULL, 0, FindDriverProc, DevInstData, 0, &dwThreadId); 856 break; 857 858 case PSN_KILLACTIVE: 859 if (hThread != 0) 860 { 861 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); 862 return TRUE; 863 } 864 break; 865 866 case PSN_WIZNEXT: 867 /* Handle a Next button click, if necessary */ 868 break; 869 870 default: 871 break; 872 } 873 break; 874 } 875 876 default: 877 break; 878 } 879 880 return FALSE; 881 } 882 883 static INT_PTR CALLBACK 884 InstallDrvDlgProc( 885 IN HWND hwndDlg, 886 IN UINT uMsg, 887 IN WPARAM wParam, 888 IN LPARAM lParam) 889 { 890 PDEVINSTDATA DevInstData; 891 DWORD dwThreadId; 892 893 /* Retrieve pointer to the global setup data */ 894 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 895 896 switch (uMsg) 897 { 898 case WM_INITDIALOG: 899 { 900 HWND hwndControl; 901 DWORD dwStyle; 902 903 /* Get pointer to the global setup data */ 904 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam; 905 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)DevInstData); 906 907 DevInstData->hDialog = hwndDlg; 908 hwndControl = GetParent(hwndDlg); 909 910 /* Center the wizard window */ 911 CenterWindow(hwndControl); 912 913 SendDlgItemMessage( 914 hwndDlg, 915 IDC_DEVICE, 916 WM_SETTEXT, 917 0, 918 (LPARAM)DevInstData->drvInfoData.Description); 919 920 /* Hide the system menu */ 921 dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE); 922 SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU); 923 break; 924 } 925 926 case WM_INSTALL_FINISHED: 927 { 928 CloseHandle(hThread); 929 hThread = 0; 930 if (wParam == 0) 931 { 932 SP_DEVINSTALL_PARAMS installParams; 933 934 SetFailedInstall(DevInstData->hDevInfo, 935 &DevInstData->devInfoData, 936 FALSE); 937 938 /* Should we reboot? */ 939 installParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 940 if (SetupDiGetDeviceInstallParams( 941 DevInstData->hDevInfo, 942 &DevInstData->devInfoData, 943 &installParams)) 944 { 945 if (installParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) 946 { 947 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_NEEDREBOOT); 948 } 949 else 950 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_FINISHPAGE); 951 break; 952 } 953 } 954 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_INSTALLFAILED); 955 break; 956 } 957 958 case WM_NOTIFY: 959 { 960 LPNMHDR lpnm = (LPNMHDR)lParam; 961 962 switch (lpnm->code) 963 { 964 case PSN_SETACTIVE: 965 PropSheet_SetWizButtons(GetParent(hwndDlg), !PSWIZB_NEXT | !PSWIZB_BACK); 966 hThread = CreateThread(NULL, 0, InstallDriverProc, DevInstData, 0, &dwThreadId); 967 break; 968 969 case PSN_KILLACTIVE: 970 if (hThread != 0) 971 { 972 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); 973 return TRUE; 974 } 975 break; 976 977 case PSN_WIZNEXT: 978 /* Handle a Next button click, if necessary */ 979 break; 980 981 default: 982 break; 983 } 984 break; 985 } 986 987 default: 988 break; 989 } 990 991 return FALSE; 992 } 993 994 static INT_PTR CALLBACK 995 NoDriverDlgProc( 996 IN HWND hwndDlg, 997 IN UINT uMsg, 998 IN WPARAM wParam, 999 IN LPARAM lParam) 1000 { 1001 PDEVINSTDATA DevInstData; 1002 HWND hwndControl; 1003 1004 UNREFERENCED_PARAMETER(wParam); 1005 1006 /* Get pointer to the global setup data */ 1007 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1008 1009 switch (uMsg) 1010 { 1011 case WM_INITDIALOG: 1012 { 1013 BOOL DisableableDevice = FALSE; 1014 1015 /* Get pointer to the global setup data */ 1016 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1017 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)DevInstData); 1018 1019 /* Center the wizard window */ 1020 CenterWindow(GetParent(hwndDlg)); 1021 1022 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL); 1023 ShowWindow(hwndControl, SW_HIDE); 1024 EnableWindow(hwndControl, FALSE); 1025 1026 /* Set title font */ 1027 SendDlgItemMessage( 1028 hwndDlg, 1029 IDC_FINISHTITLE, 1030 WM_SETFONT, 1031 (WPARAM)DevInstData->hTitleFont, 1032 (LPARAM)TRUE); 1033 1034 /* disable the "do not show this dialog anymore" checkbox 1035 if the device cannot be disabled */ 1036 CanDisableDevice( 1037 DevInstData->devInfoData.DevInst, 1038 NULL, 1039 &DisableableDevice); 1040 EnableWindow( 1041 GetDlgItem(hwndDlg, IDC_DONOTSHOWDLG), 1042 DisableableDevice); 1043 break; 1044 } 1045 1046 case WM_NOTIFY: 1047 { 1048 LPNMHDR lpnm = (LPNMHDR)lParam; 1049 1050 switch (lpnm->code) 1051 { 1052 case PSN_SETACTIVE: 1053 /* Enable the correct buttons on for the active page */ 1054 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_FINISH); 1055 break; 1056 1057 case PSN_WIZBACK: 1058 /* Handle a Back button click, if necessary */ 1059 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL); 1060 ShowWindow(hwndControl, SW_SHOW); 1061 EnableWindow(hwndControl, TRUE); 1062 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_CHSOURCE); 1063 return TRUE; 1064 1065 case PSN_WIZFINISH: 1066 { 1067 BOOL DisableableDevice = FALSE; 1068 BOOL IsStarted = FALSE; 1069 1070 if (CanDisableDevice(DevInstData->devInfoData.DevInst, 1071 NULL, 1072 &DisableableDevice) && 1073 DisableableDevice && 1074 IsDeviceStarted( 1075 DevInstData->devInfoData.DevInst, 1076 NULL, 1077 &IsStarted) && 1078 !IsStarted && 1079 SendDlgItemMessage( 1080 hwndDlg, 1081 IDC_DONOTSHOWDLG, 1082 BM_GETCHECK, 1083 (WPARAM)0, (LPARAM)0) == BST_CHECKED) 1084 { 1085 /* disable the device */ 1086 StartDevice( 1087 DevInstData->hDevInfo, 1088 &DevInstData->devInfoData, 1089 FALSE, 1090 0, 1091 NULL); 1092 } 1093 else 1094 { 1095 SetFailedInstall(DevInstData->hDevInfo, 1096 &DevInstData->devInfoData, 1097 FALSE); 1098 } 1099 break; 1100 } 1101 1102 default: 1103 break; 1104 } 1105 break; 1106 } 1107 1108 default: 1109 break; 1110 } 1111 1112 return FALSE; 1113 } 1114 1115 static INT_PTR CALLBACK 1116 InstallFailedDlgProc( 1117 IN HWND hwndDlg, 1118 IN UINT uMsg, 1119 IN WPARAM wParam, 1120 IN LPARAM lParam) 1121 { 1122 PDEVINSTDATA DevInstData; 1123 UNREFERENCED_PARAMETER(wParam); 1124 1125 /* Retrieve pointer to the global setup data */ 1126 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1127 1128 switch (uMsg) 1129 { 1130 case WM_INITDIALOG: 1131 { 1132 HWND hwndControl; 1133 1134 /* Get pointer to the global setup data */ 1135 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1136 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)DevInstData); 1137 1138 /* Center the wizard window */ 1139 CenterWindow(GetParent(hwndDlg)); 1140 1141 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL); 1142 ShowWindow(hwndControl, SW_HIDE); 1143 EnableWindow(hwndControl, FALSE); 1144 1145 SendDlgItemMessage( 1146 hwndDlg, 1147 IDC_DEVICE, 1148 WM_SETTEXT, 1149 0, 1150 (LPARAM)DevInstData->drvInfoData.Description); 1151 1152 /* Set title font */ 1153 SendDlgItemMessage( 1154 hwndDlg, 1155 IDC_FINISHTITLE, 1156 WM_SETFONT, 1157 (WPARAM)DevInstData->hTitleFont, 1158 (LPARAM)TRUE); 1159 break; 1160 } 1161 1162 case WM_NOTIFY: 1163 { 1164 LPNMHDR lpnm = (LPNMHDR)lParam; 1165 1166 switch (lpnm->code) 1167 { 1168 case PSN_SETACTIVE: 1169 /* Enable the correct buttons on for the active page */ 1170 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH); 1171 break; 1172 1173 case PSN_WIZBACK: 1174 /* Handle a Back button click, if necessary */ 1175 break; 1176 1177 case PSN_WIZFINISH: 1178 /* Handle a Finish button click, if necessary */ 1179 break; 1180 1181 default: 1182 break; 1183 } 1184 break; 1185 } 1186 1187 default: 1188 break; 1189 } 1190 1191 return FALSE; 1192 } 1193 1194 static INT_PTR CALLBACK 1195 NeedRebootDlgProc( 1196 IN HWND hwndDlg, 1197 IN UINT uMsg, 1198 IN WPARAM wParam, 1199 IN LPARAM lParam) 1200 { 1201 PDEVINSTDATA DevInstData; 1202 UNREFERENCED_PARAMETER(wParam); 1203 1204 /* Retrieve pointer to the global setup data */ 1205 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1206 1207 switch (uMsg) 1208 { 1209 case WM_INITDIALOG: 1210 { 1211 HWND hwndControl; 1212 1213 /* Get pointer to the global setup data */ 1214 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1215 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)DevInstData); 1216 1217 /* Center the wizard window */ 1218 CenterWindow(GetParent(hwndDlg)); 1219 1220 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL); 1221 ShowWindow(hwndControl, SW_HIDE); 1222 EnableWindow(hwndControl, FALSE); 1223 1224 SendDlgItemMessage( 1225 hwndDlg, 1226 IDC_DEVICE, 1227 WM_SETTEXT, 1228 0, 1229 (LPARAM)DevInstData->drvInfoData.Description); 1230 1231 /* Set title font */ 1232 SendDlgItemMessage( 1233 hwndDlg, 1234 IDC_FINISHTITLE, 1235 WM_SETFONT, 1236 (WPARAM)DevInstData->hTitleFont, 1237 (LPARAM)TRUE); 1238 break; 1239 } 1240 1241 case WM_NOTIFY: 1242 { 1243 LPNMHDR lpnm = (LPNMHDR)lParam; 1244 1245 switch (lpnm->code) 1246 { 1247 case PSN_SETACTIVE: 1248 /* Enable the correct buttons on for the active page */ 1249 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH); 1250 break; 1251 1252 case PSN_WIZBACK: 1253 /* Handle a Back button click, if necessary */ 1254 break; 1255 1256 case PSN_WIZFINISH: 1257 /* Handle a Finish button click, if necessary */ 1258 break; 1259 1260 default: 1261 break; 1262 } 1263 break; 1264 } 1265 1266 default: 1267 break; 1268 } 1269 1270 return FALSE; 1271 } 1272 1273 static INT_PTR CALLBACK 1274 FinishDlgProc( 1275 IN HWND hwndDlg, 1276 IN UINT uMsg, 1277 IN WPARAM wParam, 1278 IN LPARAM lParam) 1279 { 1280 PDEVINSTDATA DevInstData; 1281 UNREFERENCED_PARAMETER(wParam); 1282 1283 /* Retrieve pointer to the global setup data */ 1284 DevInstData = (PDEVINSTDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); 1285 1286 switch (uMsg) 1287 { 1288 case WM_INITDIALOG: 1289 { 1290 HWND hwndControl; 1291 1292 /* Get pointer to the global setup data */ 1293 DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam; 1294 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)DevInstData); 1295 1296 /* Center the wizard window */ 1297 CenterWindow(GetParent(hwndDlg)); 1298 1299 hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL); 1300 ShowWindow(hwndControl, SW_HIDE); 1301 EnableWindow(hwndControl, FALSE); 1302 1303 SendDlgItemMessage( 1304 hwndDlg, 1305 IDC_DEVICE, 1306 WM_SETTEXT, 1307 0, 1308 (LPARAM)DevInstData->drvInfoData.Description); 1309 1310 /* Set title font */ 1311 SendDlgItemMessage( 1312 hwndDlg, 1313 IDC_FINISHTITLE, 1314 WM_SETFONT, 1315 (WPARAM)DevInstData->hTitleFont, 1316 (LPARAM)TRUE); 1317 break; 1318 } 1319 1320 case WM_NOTIFY: 1321 { 1322 LPNMHDR lpnm = (LPNMHDR)lParam; 1323 1324 switch (lpnm->code) 1325 { 1326 case PSN_SETACTIVE: 1327 /* Enable the correct buttons on for the active page */ 1328 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH); 1329 break; 1330 1331 case PSN_WIZBACK: 1332 /* Handle a Back button click, if necessary */ 1333 break; 1334 1335 case PSN_WIZFINISH: 1336 /* Handle a Finish button click, if necessary */ 1337 break; 1338 1339 default: 1340 break; 1341 } 1342 break; 1343 } 1344 1345 default: 1346 break; 1347 } 1348 1349 return FALSE; 1350 } 1351 1352 static HFONT 1353 CreateTitleFont(VOID) 1354 { 1355 NONCLIENTMETRICSW ncm; 1356 LOGFONTW LogFont; 1357 HDC hdc; 1358 INT FontSize; 1359 HFONT hFont; 1360 1361 ncm.cbSize = sizeof(NONCLIENTMETRICSW); 1362 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0); 1363 1364 LogFont = ncm.lfMessageFont; 1365 LogFont.lfWeight = FW_BOLD; 1366 wcscpy(LogFont.lfFaceName, L"MS Shell Dlg"); 1367 1368 hdc = GetDC(NULL); 1369 FontSize = 12; 1370 LogFont.lfHeight = 0 - GetDeviceCaps (hdc, LOGPIXELSY) * FontSize / 72; 1371 hFont = CreateFontIndirectW(&LogFont); 1372 ReleaseDC(NULL, hdc); 1373 1374 return hFont; 1375 } 1376 1377 BOOL 1378 DisplayWizard( 1379 IN PDEVINSTDATA DevInstData, 1380 IN HWND hwndParent, 1381 IN UINT startPage) 1382 { 1383 PROPSHEETHEADER psh = {0}; 1384 HPROPSHEETPAGE ahpsp[IDD_MAXIMUMPAGE + 1]; 1385 PROPSHEETPAGE psp = {0}; 1386 HRESULT hr = CoInitialize(NULL); /* for SHAutoComplete */ 1387 1388 /* zero based index */ 1389 startPage -= IDD_FIRSTPAGE; 1390 1391 /* Create the Welcome page */ 1392 ZeroMemory(&psp, sizeof(PROPSHEETPAGE)); 1393 psp.dwSize = sizeof(PROPSHEETPAGE); 1394 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER | PSP_USETITLE; 1395 psp.hInstance = hDllInstance; 1396 psp.lParam = (LPARAM)DevInstData; 1397 psp.pszTitle = MAKEINTRESOURCE(DevInstData->bUpdate ? IDS_UPDATEWIZARDTITLE : IDS_INSTALLWIZARDTITLE); 1398 psp.pfnDlgProc = WelcomeDlgProc; 1399 psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE); 1400 ahpsp[IDD_WELCOMEPAGE-IDD_FIRSTPAGE] = CreatePropertySheetPage(&psp); 1401 1402 /* Create the Select Source page */ 1403 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USETITLE; 1404 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_CHSOURCE_TITLE); 1405 psp.pfnDlgProc = CHSourceDlgProc; 1406 psp.pszTemplate = MAKEINTRESOURCE(IDD_CHSOURCE); 1407 ahpsp[IDD_CHSOURCE-IDD_FIRSTPAGE] = CreatePropertySheetPage(&psp); 1408 1409 /* Create the Search driver page */ 1410 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USETITLE; 1411 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SEARCHDRV_TITLE); 1412 psp.pfnDlgProc = SearchDrvDlgProc; 1413 psp.pszTemplate = MAKEINTRESOURCE(IDD_SEARCHDRV); 1414 ahpsp[IDD_SEARCHDRV-IDD_FIRSTPAGE] = CreatePropertySheetPage(&psp); 1415 1416 /* Create the Install driver page */ 1417 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USETITLE; 1418 psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_INSTALLDRV_TITLE); 1419 psp.pfnDlgProc = InstallDrvDlgProc; 1420 psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLDRV); 1421 ahpsp[IDD_INSTALLDRV-IDD_FIRSTPAGE] = CreatePropertySheetPage(&psp); 1422 1423 /* Create the No driver page */ 1424 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER | PSP_USETITLE; 1425 psp.pfnDlgProc = NoDriverDlgProc; 1426 psp.pszTemplate = MAKEINTRESOURCE(IDD_NODRIVER); 1427 ahpsp[IDD_NODRIVER-IDD_FIRSTPAGE] = CreatePropertySheetPage(&psp); 1428 1429 /* Create the Install failed page */ 1430 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER | PSP_USETITLE; 1431 psp.pfnDlgProc = InstallFailedDlgProc; 1432 psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLFAILED); 1433 ahpsp[IDD_INSTALLFAILED-IDD_FIRSTPAGE] = CreatePropertySheetPage(&psp); 1434 1435 /* Create the Need reboot page */ 1436 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER | PSP_USETITLE; 1437 psp.pfnDlgProc = NeedRebootDlgProc; 1438 psp.pszTemplate = MAKEINTRESOURCE(IDD_NEEDREBOOT); 1439 ahpsp[IDD_NEEDREBOOT-IDD_FIRSTPAGE] = CreatePropertySheetPage(&psp); 1440 1441 /* Create the Finish page */ 1442 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER | PSP_USETITLE; 1443 psp.pfnDlgProc = FinishDlgProc; 1444 psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE); 1445 ahpsp[IDD_FINISHPAGE-IDD_FIRSTPAGE] = CreatePropertySheetPage(&psp); 1446 1447 /* Create the property sheet */ 1448 psh.dwSize = sizeof(PROPSHEETHEADER); 1449 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER; 1450 psh.hInstance = hDllInstance; 1451 psh.hwndParent = hwndParent; 1452 psh.nPages = IDD_MAXIMUMPAGE + 1; 1453 psh.nStartPage = startPage; 1454 psh.phpage = ahpsp; 1455 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK); 1456 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER); 1457 1458 /* Create title font */ 1459 DevInstData->hTitleFont = CreateTitleFont(); 1460 1461 /* Display the wizard */ 1462 PropertySheet(&psh); 1463 1464 DeleteObject(DevInstData->hTitleFont); 1465 1466 if (SUCCEEDED(hr)) 1467 CoUninitialize(); 1468 return TRUE; 1469 } 1470