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