1 /* 2 * New device installer (newdev.dll) 3 * 4 * Copyright 2005-2006 Herv� Poussineau (hpoussin@reactos.org) 5 * 2005 Christoph von Wittich (Christoph@ActiveVB.de) 6 * 2009 Colin Finck (colin@reactos.org) 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23 #include "newdev_private.h" 24 25 #include <stdio.h> 26 #include <winnls.h> 27 28 /* Global variables */ 29 HINSTANCE hDllInstance; 30 31 static BOOL 32 SearchDriver( 33 IN PDEVINSTDATA DevInstData, 34 IN LPCWSTR Directory OPTIONAL, 35 IN LPCWSTR InfFile OPTIONAL); 36 37 /* 38 * @implemented 39 */ 40 BOOL WINAPI 41 UpdateDriverForPlugAndPlayDevicesW( 42 IN HWND hwndParent, 43 IN LPCWSTR HardwareId, 44 IN LPCWSTR FullInfPath, 45 IN DWORD InstallFlags, 46 OUT PBOOL bRebootRequired OPTIONAL) 47 { 48 DEVINSTDATA DevInstData; 49 DWORD i; 50 LPWSTR Buffer = NULL; 51 DWORD BufferSize; 52 LPCWSTR CurrentHardwareId; /* Pointer into Buffer */ 53 BOOL FoundHardwareId, FoundAtLeastOneDevice = FALSE; 54 BOOL ret = FALSE; 55 56 DevInstData.hDevInfo = INVALID_HANDLE_VALUE; 57 58 TRACE("UpdateDriverForPlugAndPlayDevicesW(%p %s %s 0x%x %p)\n", 59 hwndParent, debugstr_w(HardwareId), debugstr_w(FullInfPath), InstallFlags, bRebootRequired); 60 61 /* FIXME: InstallFlags bRebootRequired ignored! */ 62 63 /* Check flags */ 64 if (InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE)) 65 { 66 TRACE("Unknown flags: 0x%08lx\n", InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE)); 67 SetLastError(ERROR_INVALID_FLAGS); 68 goto cleanup; 69 } 70 71 /* Enumerate all devices of the system */ 72 DevInstData.hDevInfo = SetupDiGetClassDevsW(NULL, NULL, hwndParent, DIGCF_ALLCLASSES | DIGCF_PRESENT); 73 if (DevInstData.hDevInfo == INVALID_HANDLE_VALUE) 74 goto cleanup; 75 DevInstData.devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 76 for (i = 0; ; i++) 77 { 78 if (!SetupDiEnumDeviceInfo(DevInstData.hDevInfo, i, &DevInstData.devInfoData)) 79 { 80 if (GetLastError() != ERROR_NO_MORE_ITEMS) 81 { 82 TRACE("SetupDiEnumDeviceInfo() failed with error 0x%x\n", GetLastError()); 83 goto cleanup; 84 } 85 /* This error was expected */ 86 break; 87 } 88 89 /* Get Hardware ID */ 90 HeapFree(GetProcessHeap(), 0, Buffer); 91 Buffer = NULL; 92 BufferSize = 0; 93 while (!SetupDiGetDeviceRegistryPropertyW( 94 DevInstData.hDevInfo, 95 &DevInstData.devInfoData, 96 SPDRP_HARDWAREID, 97 NULL, 98 (PBYTE)Buffer, 99 BufferSize, 100 &BufferSize)) 101 { 102 if (GetLastError() == ERROR_FILE_NOT_FOUND) 103 { 104 Buffer = NULL; 105 break; 106 } 107 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 108 { 109 TRACE("SetupDiGetDeviceRegistryPropertyW() failed with error 0x%x\n", GetLastError()); 110 goto cleanup; 111 } 112 /* This error was expected */ 113 HeapFree(GetProcessHeap(), 0, Buffer); 114 Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize); 115 if (!Buffer) 116 { 117 TRACE("HeapAlloc() failed\n", GetLastError()); 118 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 119 goto cleanup; 120 } 121 } 122 if (Buffer == NULL) 123 continue; 124 125 /* Check if we match the given hardware ID */ 126 FoundHardwareId = FALSE; 127 for (CurrentHardwareId = Buffer; *CurrentHardwareId != UNICODE_NULL; CurrentHardwareId += wcslen(CurrentHardwareId) + 1) 128 { 129 if (wcscmp(CurrentHardwareId, HardwareId) == 0) 130 { 131 FoundHardwareId = TRUE; 132 break; 133 } 134 } 135 if (!FoundHardwareId) 136 continue; 137 138 /* We need to try to update the driver of this device */ 139 140 /* Get Instance ID */ 141 HeapFree(GetProcessHeap(), 0, Buffer); 142 Buffer = NULL; 143 if (SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, NULL, 0, &BufferSize)) 144 { 145 /* Error, as the output buffer should be too small */ 146 SetLastError(ERROR_GEN_FAILURE); 147 goto cleanup; 148 } 149 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 150 { 151 TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError()); 152 goto cleanup; 153 } 154 else if ((Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize * sizeof(WCHAR))) == NULL) 155 { 156 TRACE("HeapAlloc() failed\n", GetLastError()); 157 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 158 goto cleanup; 159 } 160 else if (!SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, Buffer, BufferSize, NULL)) 161 { 162 TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError()); 163 goto cleanup; 164 } 165 TRACE("Trying to update the driver of %s\n", debugstr_w(Buffer)); 166 167 /* Search driver in the specified .inf file */ 168 if (!SearchDriver(&DevInstData, NULL, FullInfPath)) 169 { 170 TRACE("SearchDriver() failed with error 0x%x\n", GetLastError()); 171 continue; 172 } 173 174 /* FIXME: HACK! We shouldn't check of ERROR_PRIVILEGE_NOT_HELD */ 175 //if (!InstallCurrentDriver(&DevInstData)) 176 if (!InstallCurrentDriver(&DevInstData) && GetLastError() != ERROR_PRIVILEGE_NOT_HELD) 177 { 178 TRACE("InstallCurrentDriver() failed with error 0x%x\n", GetLastError()); 179 continue; 180 } 181 182 FoundAtLeastOneDevice = TRUE; 183 } 184 185 if (FoundAtLeastOneDevice) 186 { 187 SetLastError(NO_ERROR); 188 ret = TRUE; 189 } 190 else 191 { 192 TRACE("No device found with HardwareID %s\n", debugstr_w(HardwareId)); 193 SetLastError(ERROR_NO_SUCH_DEVINST); 194 } 195 196 cleanup: 197 if (DevInstData.hDevInfo != INVALID_HANDLE_VALUE) 198 SetupDiDestroyDeviceInfoList(DevInstData.hDevInfo); 199 HeapFree(GetProcessHeap(), 0, Buffer); 200 return ret; 201 } 202 203 /* 204 * @implemented 205 */ 206 BOOL WINAPI 207 UpdateDriverForPlugAndPlayDevicesA( 208 IN HWND hwndParent, 209 IN LPCSTR HardwareId, 210 IN LPCSTR FullInfPath, 211 IN DWORD InstallFlags, 212 OUT PBOOL bRebootRequired OPTIONAL) 213 { 214 BOOL Result; 215 LPWSTR HardwareIdW = NULL; 216 LPWSTR FullInfPathW = NULL; 217 218 int len = MultiByteToWideChar(CP_ACP, 0, HardwareId, -1, NULL, 0); 219 HardwareIdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 220 if (!HardwareIdW) 221 { 222 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 223 return FALSE; 224 } 225 MultiByteToWideChar(CP_ACP, 0, HardwareId, -1, HardwareIdW, len); 226 227 len = MultiByteToWideChar(CP_ACP, 0, FullInfPath, -1, NULL, 0); 228 FullInfPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 229 if (!FullInfPathW) 230 { 231 HeapFree(GetProcessHeap(), 0, HardwareIdW); 232 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 233 return FALSE; 234 } 235 MultiByteToWideChar(CP_ACP, 0, FullInfPath, -1, FullInfPathW, len); 236 237 Result = UpdateDriverForPlugAndPlayDevicesW( 238 hwndParent, 239 HardwareIdW, 240 FullInfPathW, 241 InstallFlags, 242 bRebootRequired); 243 244 HeapFree(GetProcessHeap(), 0, HardwareIdW); 245 HeapFree(GetProcessHeap(), 0, FullInfPathW); 246 247 return Result; 248 } 249 250 /* Directory and InfFile MUST NOT be specified simultaneously */ 251 static BOOL 252 SearchDriver( 253 IN PDEVINSTDATA DevInstData, 254 IN LPCWSTR Directory OPTIONAL, 255 IN LPCWSTR InfFile OPTIONAL) 256 { 257 SP_DEVINSTALL_PARAMS_W DevInstallParams = {0,}; 258 BOOL ret; 259 260 DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 261 if (!SetupDiGetDeviceInstallParamsW(DevInstData->hDevInfo, &DevInstData->devInfoData, &DevInstallParams)) 262 { 263 TRACE("SetupDiGetDeviceInstallParams() failed with error 0x%x\n", GetLastError()); 264 return FALSE; 265 } 266 DevInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS; 267 268 if (InfFile) 269 { 270 DevInstallParams.Flags |= DI_ENUMSINGLEINF; 271 wcsncpy(DevInstallParams.DriverPath, InfFile, MAX_PATH); 272 } 273 else if (Directory) 274 { 275 DevInstallParams.Flags &= ~DI_ENUMSINGLEINF; 276 wcsncpy(DevInstallParams.DriverPath, Directory, MAX_PATH); 277 } 278 else 279 { 280 DevInstallParams.Flags &= ~DI_ENUMSINGLEINF; 281 *DevInstallParams.DriverPath = '\0'; 282 } 283 284 ret = SetupDiSetDeviceInstallParamsW( 285 DevInstData->hDevInfo, 286 &DevInstData->devInfoData, 287 &DevInstallParams); 288 if (!ret) 289 { 290 TRACE("SetupDiSetDeviceInstallParams() failed with error 0x%x\n", GetLastError()); 291 return FALSE; 292 } 293 294 ret = SetupDiBuildDriverInfoList( 295 DevInstData->hDevInfo, 296 &DevInstData->devInfoData, 297 SPDIT_COMPATDRIVER); 298 if (!ret) 299 { 300 TRACE("SetupDiBuildDriverInfoList() failed with error 0x%x\n", GetLastError()); 301 return FALSE; 302 } 303 304 DevInstData->drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); 305 ret = SetupDiEnumDriverInfoW( 306 DevInstData->hDevInfo, 307 &DevInstData->devInfoData, 308 SPDIT_COMPATDRIVER, 309 0, 310 &DevInstData->drvInfoData); 311 if (!ret) 312 { 313 if (GetLastError() == ERROR_NO_MORE_ITEMS) 314 return FALSE; 315 TRACE("SetupDiEnumDriverInfo() failed with error 0x%x\n", GetLastError()); 316 return FALSE; 317 } 318 319 return TRUE; 320 } 321 322 static BOOL 323 IsDots(IN LPCWSTR str) 324 { 325 if(wcscmp(str, L".") && wcscmp(str, L"..")) return FALSE; 326 return TRUE; 327 } 328 329 static LPCWSTR 330 GetFileExt(IN LPWSTR FileName) 331 { 332 LPCWSTR Dot; 333 334 Dot = wcsrchr(FileName, '.'); 335 if (!Dot) 336 return L""; 337 338 return Dot; 339 } 340 341 static BOOL 342 SearchDriverRecursive( 343 IN PDEVINSTDATA DevInstData, 344 IN LPCWSTR Path) 345 { 346 WIN32_FIND_DATAW wfd; 347 WCHAR DirPath[MAX_PATH]; 348 WCHAR FileName[MAX_PATH]; 349 WCHAR FullPath[MAX_PATH]; 350 WCHAR LastDirPath[MAX_PATH] = L""; 351 WCHAR PathWithPattern[MAX_PATH]; 352 BOOL ok = TRUE; 353 BOOL retval = FALSE; 354 HANDLE hFindFile = INVALID_HANDLE_VALUE; 355 356 wcscpy(DirPath, Path); 357 358 if (DirPath[wcslen(DirPath) - 1] != '\\') 359 wcscat(DirPath, L"\\"); 360 361 wcscpy(PathWithPattern, DirPath); 362 wcscat(PathWithPattern, L"\\*"); 363 364 for (hFindFile = FindFirstFileW(PathWithPattern, &wfd); 365 ok && hFindFile != INVALID_HANDLE_VALUE; 366 ok = FindNextFileW(hFindFile, &wfd)) 367 { 368 369 wcscpy(FileName, wfd.cFileName); 370 if (IsDots(FileName)) 371 continue; 372 373 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 374 { 375 /* Recursive search */ 376 wcscpy(FullPath, DirPath); 377 wcscat(FullPath, FileName); 378 if (SearchDriverRecursive(DevInstData, FullPath)) 379 { 380 retval = TRUE; 381 /* We continue the search for a better driver */ 382 } 383 } 384 else 385 { 386 LPCWSTR pszExtension = GetFileExt(FileName); 387 388 if ((_wcsicmp(pszExtension, L".inf") == 0) && (wcscmp(LastDirPath, DirPath) != 0)) 389 { 390 wcscpy(LastDirPath, DirPath); 391 392 if (wcslen(DirPath) > MAX_PATH) 393 /* Path is too long to be searched */ 394 continue; 395 396 if (SearchDriver(DevInstData, DirPath, NULL)) 397 { 398 retval = TRUE; 399 /* We continue the search for a better driver */ 400 } 401 402 } 403 } 404 } 405 406 if (hFindFile != INVALID_HANDLE_VALUE) 407 FindClose(hFindFile); 408 return retval; 409 } 410 411 BOOL 412 ScanFoldersForDriver( 413 IN PDEVINSTDATA DevInstData) 414 { 415 BOOL result; 416 417 /* Search in default location */ 418 result = SearchDriver(DevInstData, NULL, NULL); 419 420 if (DevInstData->CustomSearchPath) 421 { 422 /* Search only in specified paths */ 423 /* We need to check all specified directories to be 424 * sure to find the best driver for the device. 425 */ 426 LPCWSTR Path; 427 for (Path = DevInstData->CustomSearchPath; *Path != '\0'; Path += wcslen(Path) + 1) 428 { 429 TRACE("Search driver in %s\n", debugstr_w(Path)); 430 if (wcslen(Path) == 2 && Path[1] == ':') 431 { 432 if (SearchDriverRecursive(DevInstData, Path)) 433 result = TRUE; 434 } 435 else 436 { 437 if (SearchDriver(DevInstData, Path, NULL)) 438 result = TRUE; 439 } 440 } 441 } 442 443 return result; 444 } 445 446 BOOL 447 PrepareFoldersToScan( 448 IN PDEVINSTDATA DevInstData, 449 IN BOOL IncludeRemovableDevices, 450 IN BOOL IncludeCustomPath, 451 IN HWND hwndCombo OPTIONAL) 452 { 453 WCHAR drive[] = {'?',':',0}; 454 DWORD dwDrives = 0; 455 DWORD i; 456 UINT nType; 457 DWORD CustomTextLength = 0; 458 DWORD LengthNeeded = 0; 459 LPWSTR Buffer; 460 461 /* Calculate length needed to store the search paths */ 462 if (IncludeRemovableDevices) 463 { 464 dwDrives = GetLogicalDrives(); 465 for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1) 466 { 467 if (dwDrives & i) 468 { 469 nType = GetDriveTypeW(drive); 470 if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM) 471 { 472 LengthNeeded += 3; 473 } 474 } 475 } 476 } 477 if (IncludeCustomPath) 478 { 479 CustomTextLength = 1 + ComboBox_GetTextLength(hwndCombo); 480 LengthNeeded += CustomTextLength; 481 } 482 483 /* Allocate space for search paths */ 484 HeapFree(GetProcessHeap(), 0, DevInstData->CustomSearchPath); 485 DevInstData->CustomSearchPath = Buffer = HeapAlloc( 486 GetProcessHeap(), 487 0, 488 (LengthNeeded + 1) * sizeof(WCHAR)); 489 if (!Buffer) 490 { 491 TRACE("HeapAlloc() failed\n"); 492 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 493 return FALSE; 494 } 495 496 /* Fill search paths */ 497 if (IncludeRemovableDevices) 498 { 499 for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1) 500 { 501 if (dwDrives & i) 502 { 503 nType = GetDriveTypeW(drive); 504 if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM) 505 { 506 Buffer += 1 + swprintf(Buffer, drive); 507 } 508 } 509 } 510 } 511 if (IncludeCustomPath) 512 { 513 Buffer += 1 + GetWindowTextW(hwndCombo, Buffer, CustomTextLength); 514 } 515 *Buffer = '\0'; 516 517 return TRUE; 518 } 519 520 BOOL 521 InstallCurrentDriver( 522 IN PDEVINSTDATA DevInstData) 523 { 524 BOOL ret; 525 526 TRACE("Installing driver %s: %s\n", 527 debugstr_w(DevInstData->drvInfoData.MfgName), 528 debugstr_w(DevInstData->drvInfoData.Description)); 529 530 ret = SetupDiCallClassInstaller( 531 DIF_SELECTBESTCOMPATDRV, 532 DevInstData->hDevInfo, 533 &DevInstData->devInfoData); 534 if (!ret) 535 { 536 TRACE("SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV) failed with error 0x%x\n", GetLastError()); 537 return FALSE; 538 } 539 540 ret = SetupDiCallClassInstaller( 541 DIF_ALLOW_INSTALL, 542 DevInstData->hDevInfo, 543 &DevInstData->devInfoData); 544 if (!ret) 545 { 546 TRACE("SetupDiCallClassInstaller(DIF_ALLOW_INSTALL) failed with error 0x%x\n", GetLastError()); 547 return FALSE; 548 } 549 550 ret = SetupDiCallClassInstaller( 551 DIF_NEWDEVICEWIZARD_PREANALYZE, 552 DevInstData->hDevInfo, 553 &DevInstData->devInfoData); 554 if (!ret) 555 { 556 TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_PREANALYZE) failed with error 0x%x\n", GetLastError()); 557 return FALSE; 558 } 559 560 ret = SetupDiCallClassInstaller( 561 DIF_NEWDEVICEWIZARD_POSTANALYZE, 562 DevInstData->hDevInfo, 563 &DevInstData->devInfoData); 564 if (!ret) 565 { 566 TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_POSTANALYZE) failed with error 0x%x\n", GetLastError()); 567 return FALSE; 568 } 569 570 ret = SetupDiCallClassInstaller( 571 DIF_INSTALLDEVICEFILES, 572 DevInstData->hDevInfo, 573 &DevInstData->devInfoData); 574 if (!ret) 575 { 576 TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES) failed with error 0x%x\n", GetLastError()); 577 return FALSE; 578 } 579 580 ret = SetupDiCallClassInstaller( 581 DIF_REGISTER_COINSTALLERS, 582 DevInstData->hDevInfo, 583 &DevInstData->devInfoData); 584 if (!ret) 585 { 586 TRACE("SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS) failed with error 0x%x\n", GetLastError()); 587 return FALSE; 588 } 589 590 ret = SetupDiCallClassInstaller( 591 DIF_INSTALLINTERFACES, 592 DevInstData->hDevInfo, 593 &DevInstData->devInfoData); 594 if (!ret) 595 { 596 TRACE("SetupDiCallClassInstaller(DIF_INSTALLINTERFACES) failed with error 0x%x\n", GetLastError()); 597 return FALSE; 598 } 599 600 ret = SetupDiCallClassInstaller( 601 DIF_INSTALLDEVICE, 602 DevInstData->hDevInfo, 603 &DevInstData->devInfoData); 604 if (!ret) 605 { 606 TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICE) failed with error 0x%x\n", GetLastError()); 607 return FALSE; 608 } 609 610 ret = SetupDiCallClassInstaller( 611 DIF_NEWDEVICEWIZARD_FINISHINSTALL, 612 DevInstData->hDevInfo, 613 &DevInstData->devInfoData); 614 if (!ret) 615 { 616 TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_FINISHINSTALL) failed with error 0x%x\n", GetLastError()); 617 return FALSE; 618 } 619 620 ret = SetupDiCallClassInstaller( 621 DIF_DESTROYPRIVATEDATA, 622 DevInstData->hDevInfo, 623 &DevInstData->devInfoData); 624 if (!ret) 625 { 626 TRACE("SetupDiCallClassInstaller(DIF_DESTROYPRIVATEDATA) failed with error 0x%x\n", GetLastError()); 627 return FALSE; 628 } 629 630 return TRUE; 631 } 632 633 /* 634 * @implemented 635 */ 636 BOOL WINAPI 637 DevInstallW( 638 IN HWND hWndParent, 639 IN HINSTANCE hInstance, 640 IN LPCWSTR InstanceId, 641 IN INT Show) 642 { 643 PDEVINSTDATA DevInstData = NULL; 644 BOOL ret; 645 DWORD config_flags; 646 BOOL retval = FALSE; 647 648 TRACE("(%p, %p, %s, %d)\n", hWndParent, hInstance, debugstr_w(InstanceId), Show); 649 650 if (!IsUserAdmin()) 651 { 652 /* XP kills the process... */ 653 ExitProcess(ERROR_ACCESS_DENIED); 654 } 655 656 DevInstData = HeapAlloc(GetProcessHeap(), 0, sizeof(DEVINSTDATA)); 657 if (!DevInstData) 658 { 659 TRACE("HeapAlloc() failed\n"); 660 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 661 goto cleanup; 662 } 663 664 /* Clear devinst data */ 665 ZeroMemory(DevInstData, sizeof(DEVINSTDATA)); 666 DevInstData->devInfoData.cbSize = 0; /* Tell if the devInfoData is valid */ 667 668 /* Fill devinst data */ 669 DevInstData->hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); 670 if (DevInstData->hDevInfo == INVALID_HANDLE_VALUE) 671 { 672 TRACE("SetupDiCreateDeviceInfoListExW() failed with error 0x%x\n", GetLastError()); 673 goto cleanup; 674 } 675 676 DevInstData->devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 677 ret = SetupDiOpenDeviceInfoW( 678 DevInstData->hDevInfo, 679 InstanceId, 680 NULL, 681 0, /* Open flags */ 682 &DevInstData->devInfoData); 683 if (!ret) 684 { 685 TRACE("SetupDiOpenDeviceInfoW() failed with error 0x%x (InstanceId %s)\n", 686 GetLastError(), debugstr_w(InstanceId)); 687 DevInstData->devInfoData.cbSize = 0; 688 goto cleanup; 689 } 690 691 SetLastError(ERROR_GEN_FAILURE); 692 ret = SetupDiGetDeviceRegistryProperty( 693 DevInstData->hDevInfo, 694 &DevInstData->devInfoData, 695 SPDRP_DEVICEDESC, 696 &DevInstData->regDataType, 697 NULL, 0, 698 &DevInstData->requiredSize); 699 700 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER && DevInstData->regDataType == REG_SZ) 701 { 702 DevInstData->buffer = HeapAlloc(GetProcessHeap(), 0, DevInstData->requiredSize); 703 if (!DevInstData->buffer) 704 { 705 TRACE("HeapAlloc() failed\n"); 706 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 707 } 708 else 709 { 710 ret = SetupDiGetDeviceRegistryPropertyW( 711 DevInstData->hDevInfo, 712 &DevInstData->devInfoData, 713 SPDRP_DEVICEDESC, 714 &DevInstData->regDataType, 715 DevInstData->buffer, DevInstData->requiredSize, 716 &DevInstData->requiredSize); 717 } 718 } 719 if (!ret) 720 { 721 TRACE("SetupDiGetDeviceRegistryProperty() failed with error 0x%x (InstanceId %s)\n", 722 GetLastError(), debugstr_w(InstanceId)); 723 goto cleanup; 724 } 725 726 if (SetupDiGetDeviceRegistryPropertyW( 727 DevInstData->hDevInfo, 728 &DevInstData->devInfoData, 729 SPDRP_CONFIGFLAGS, 730 NULL, 731 (BYTE *)&config_flags, 732 sizeof(config_flags), 733 NULL)) 734 { 735 if (config_flags & CONFIGFLAG_FAILEDINSTALL) 736 { 737 /* The device is disabled */ 738 TRACE("Device is disabled\n"); 739 retval = TRUE; 740 goto cleanup; 741 } 742 } 743 744 TRACE("Installing %s (%s)\n", debugstr_w((PCWSTR)DevInstData->buffer), debugstr_w(InstanceId)); 745 746 /* Search driver in default location and removable devices */ 747 if (!PrepareFoldersToScan(DevInstData, FALSE, FALSE, NULL)) 748 { 749 TRACE("PrepareFoldersToScan() failed with error 0x%lx\n", GetLastError()); 750 goto cleanup; 751 } 752 if (ScanFoldersForDriver(DevInstData)) 753 { 754 /* Driver found ; install it */ 755 retval = InstallCurrentDriver(DevInstData); 756 TRACE("InstallCurrentDriver() returned %d\n", retval); 757 if (retval && Show != SW_HIDE) 758 { 759 /* Should we display the 'Need to reboot' page? */ 760 SP_DEVINSTALL_PARAMS installParams; 761 installParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 762 if (SetupDiGetDeviceInstallParams( 763 DevInstData->hDevInfo, 764 &DevInstData->devInfoData, 765 &installParams)) 766 { 767 if (installParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) 768 { 769 TRACE("Displaying 'Reboot' wizard page\n"); 770 retval = DisplayWizard(DevInstData, hWndParent, IDD_NEEDREBOOT); 771 } 772 } 773 } 774 goto cleanup; 775 } 776 else if (Show == SW_HIDE) 777 { 778 /* We can't show the wizard. Fail the install */ 779 TRACE("No wizard\n"); 780 goto cleanup; 781 } 782 783 /* Prepare the wizard, and display it */ 784 TRACE("Need to show install wizard\n"); 785 retval = DisplayWizard(DevInstData, hWndParent, IDD_WELCOMEPAGE); 786 787 cleanup: 788 if (DevInstData) 789 { 790 if (DevInstData->devInfoData.cbSize != 0) 791 { 792 if (!SetupDiDestroyDriverInfoList(DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER)) 793 TRACE("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError()); 794 } 795 if (DevInstData->hDevInfo != INVALID_HANDLE_VALUE) 796 { 797 if (!SetupDiDestroyDeviceInfoList(DevInstData->hDevInfo)) 798 TRACE("SetupDiDestroyDeviceInfoList() failed with error 0x%lx\n", GetLastError()); 799 } 800 HeapFree(GetProcessHeap(), 0, DevInstData->buffer); 801 HeapFree(GetProcessHeap(), 0, DevInstData); 802 } 803 804 return retval; 805 } 806 807 808 BOOL 809 WINAPI 810 InstallDevInstEx( 811 IN HWND hWndParent, 812 IN LPCWSTR InstanceId, 813 IN BOOL bUpdate, 814 OUT LPDWORD lpReboot, 815 IN DWORD Unknown) 816 { 817 PDEVINSTDATA DevInstData = NULL; 818 BOOL ret; 819 BOOL retval = FALSE; 820 821 TRACE("InstllDevInstEx(%p, %s, %d, %p, %lx)\n", 822 hWndParent, debugstr_w(InstanceId), bUpdate, lpReboot, Unknown); 823 824 DevInstData = HeapAlloc(GetProcessHeap(), 0, sizeof(DEVINSTDATA)); 825 if (!DevInstData) 826 { 827 TRACE("HeapAlloc() failed\n"); 828 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 829 goto cleanup; 830 } 831 832 /* Clear devinst data */ 833 ZeroMemory(DevInstData, sizeof(DEVINSTDATA)); 834 DevInstData->devInfoData.cbSize = 0; /* Tell if the devInfoData is valid */ 835 DevInstData->bUpdate = bUpdate; 836 837 /* Fill devinst data */ 838 DevInstData->hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); 839 if (DevInstData->hDevInfo == INVALID_HANDLE_VALUE) 840 { 841 TRACE("SetupDiCreateDeviceInfoListExW() failed with error 0x%x\n", GetLastError()); 842 goto cleanup; 843 } 844 845 DevInstData->devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 846 ret = SetupDiOpenDeviceInfoW( 847 DevInstData->hDevInfo, 848 InstanceId, 849 NULL, 850 0, /* Open flags */ 851 &DevInstData->devInfoData); 852 if (!ret) 853 { 854 TRACE("SetupDiOpenDeviceInfoW() failed with error 0x%x (InstanceId %s)\n", 855 GetLastError(), debugstr_w(InstanceId)); 856 DevInstData->devInfoData.cbSize = 0; 857 goto cleanup; 858 } 859 860 SetLastError(ERROR_GEN_FAILURE); 861 ret = SetupDiGetDeviceRegistryProperty( 862 DevInstData->hDevInfo, 863 &DevInstData->devInfoData, 864 SPDRP_DEVICEDESC, 865 &DevInstData->regDataType, 866 NULL, 0, 867 &DevInstData->requiredSize); 868 869 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER && DevInstData->regDataType == REG_SZ) 870 { 871 DevInstData->buffer = HeapAlloc(GetProcessHeap(), 0, DevInstData->requiredSize); 872 if (!DevInstData->buffer) 873 { 874 TRACE("HeapAlloc() failed\n"); 875 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 876 } 877 else 878 { 879 ret = SetupDiGetDeviceRegistryPropertyW( 880 DevInstData->hDevInfo, 881 &DevInstData->devInfoData, 882 SPDRP_DEVICEDESC, 883 &DevInstData->regDataType, 884 DevInstData->buffer, DevInstData->requiredSize, 885 &DevInstData->requiredSize); 886 } 887 } 888 889 if (!ret) 890 { 891 TRACE("SetupDiGetDeviceRegistryProperty() failed with error 0x%x (InstanceId %s)\n", 892 GetLastError(), debugstr_w(InstanceId)); 893 goto cleanup; 894 } 895 896 /* Prepare the wizard, and display it */ 897 TRACE("Need to show install wizard\n"); 898 retval = DisplayWizard(DevInstData, hWndParent, IDD_WELCOMEPAGE); 899 900 cleanup: 901 if (DevInstData) 902 { 903 if (DevInstData->devInfoData.cbSize != 0) 904 { 905 if (!SetupDiDestroyDriverInfoList(DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER)) 906 TRACE("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError()); 907 } 908 if (DevInstData->hDevInfo != INVALID_HANDLE_VALUE) 909 { 910 if (!SetupDiDestroyDeviceInfoList(DevInstData->hDevInfo)) 911 TRACE("SetupDiDestroyDeviceInfoList() failed with error 0x%lx\n", GetLastError()); 912 } 913 HeapFree(GetProcessHeap(), 0, DevInstData->buffer); 914 HeapFree(GetProcessHeap(), 0, DevInstData); 915 } 916 917 return retval; 918 } 919 920 921 /* 922 * @implemented 923 */ 924 BOOL 925 WINAPI 926 InstallDevInst( 927 IN HWND hWndParent, 928 IN LPCWSTR InstanceId, 929 IN BOOL bUpdate, 930 OUT LPDWORD lpReboot) 931 { 932 return InstallDevInstEx(hWndParent, InstanceId, bUpdate, lpReboot, 0); 933 } 934 935 936 /* 937 * @implemented 938 */ 939 BOOL WINAPI 940 ClientSideInstallW( 941 IN HWND hWndOwner, 942 IN HINSTANCE hInstance, 943 IN LPWSTR lpNamedPipeName, 944 IN INT Show) 945 { 946 BOOL ReturnValue = FALSE; 947 BOOL ShowWizard; 948 DWORD BytesRead; 949 DWORD Value; 950 HANDLE hPipe = INVALID_HANDLE_VALUE; 951 PWSTR DeviceInstance = NULL; 952 PWSTR InstallEventName = NULL; 953 HANDLE hInstallEvent; 954 955 /* Open the pipe */ 956 hPipe = CreateFileW(lpNamedPipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 957 958 if(hPipe == INVALID_HANDLE_VALUE) 959 { 960 ERR("CreateFileW failed with error %u\n", GetLastError()); 961 goto cleanup; 962 } 963 964 /* Read the data. Some is just included for compatibility with Windows right now and not yet used by ReactOS. 965 See umpnpmgr for more details. */ 966 if(!ReadFile(hPipe, &Value, sizeof(Value), &BytesRead, NULL)) 967 { 968 ERR("ReadFile failed with error %u\n", GetLastError()); 969 goto cleanup; 970 } 971 972 InstallEventName = (PWSTR)HeapAlloc(GetProcessHeap(), 0, Value); 973 974 if(!ReadFile(hPipe, InstallEventName, Value, &BytesRead, NULL)) 975 { 976 ERR("ReadFile failed with error %u\n", GetLastError()); 977 goto cleanup; 978 } 979 980 /* I couldn't figure out what the following value means under Windows XP. 981 Therefore I used it in umpnpmgr to pass the ShowWizard variable. */ 982 if(!ReadFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesRead, NULL)) 983 { 984 ERR("ReadFile failed with error %u\n", GetLastError()); 985 goto cleanup; 986 } 987 988 /* Next one is again size in bytes of the following string */ 989 if(!ReadFile(hPipe, &Value, sizeof(Value), &BytesRead, NULL)) 990 { 991 ERR("ReadFile failed with error %u\n", GetLastError()); 992 goto cleanup; 993 } 994 995 DeviceInstance = (PWSTR)HeapAlloc(GetProcessHeap(), 0, Value); 996 997 if(!ReadFile(hPipe, DeviceInstance, Value, &BytesRead, NULL)) 998 { 999 ERR("ReadFile failed with error %u\n", GetLastError()); 1000 goto cleanup; 1001 } 1002 1003 ReturnValue = DevInstallW(NULL, NULL, DeviceInstance, ShowWizard ? SW_SHOWNOACTIVATE : SW_HIDE); 1004 if(!ReturnValue) 1005 { 1006 ERR("DevInstallW failed with error %lu\n", GetLastError()); 1007 goto cleanup; 1008 } 1009 1010 hInstallEvent = CreateEventW(NULL, TRUE, FALSE, InstallEventName); 1011 if(!hInstallEvent) 1012 { 1013 TRACE("CreateEventW('%ls') failed with error %lu\n", InstallEventName, GetLastError()); 1014 goto cleanup; 1015 } 1016 1017 SetEvent(hInstallEvent); 1018 CloseHandle(hInstallEvent); 1019 1020 cleanup: 1021 if(hPipe != INVALID_HANDLE_VALUE) 1022 CloseHandle(hPipe); 1023 1024 if(InstallEventName) 1025 HeapFree(GetProcessHeap(), 0, InstallEventName); 1026 1027 if(DeviceInstance) 1028 HeapFree(GetProcessHeap(), 0, DeviceInstance); 1029 1030 return ReturnValue; 1031 } 1032 1033 BOOL WINAPI 1034 DllMain( 1035 IN HINSTANCE hInstance, 1036 IN DWORD dwReason, 1037 IN LPVOID lpReserved) 1038 { 1039 if (dwReason == DLL_PROCESS_ATTACH) 1040 { 1041 INITCOMMONCONTROLSEX InitControls; 1042 1043 DisableThreadLibraryCalls(hInstance); 1044 1045 InitControls.dwSize = sizeof(INITCOMMONCONTROLSEX); 1046 InitControls.dwICC = ICC_PROGRESS_CLASS; 1047 InitCommonControlsEx(&InitControls); 1048 hDllInstance = hInstance; 1049 } 1050 1051 return TRUE; 1052 } 1053