Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennewdev.c
Go to the documentation of this file.
00001 /* 00002 * New device installer (newdev.dll) 00003 * 00004 * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org) 00005 * 2005 Christoph von Wittich (Christoph@ActiveVB.de) 00006 * 2009 Colin Finck (colin@reactos.org) 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 #include "newdev_private.h" 00024 00025 WINE_DEFAULT_DEBUG_CHANNEL(newdev); 00026 00027 /* Global variables */ 00028 HINSTANCE hDllInstance; 00029 00030 static BOOL 00031 SearchDriver( 00032 IN PDEVINSTDATA DevInstData, 00033 IN LPCWSTR Directory OPTIONAL, 00034 IN LPCWSTR InfFile OPTIONAL); 00035 00036 /* 00037 * @implemented 00038 */ 00039 BOOL WINAPI 00040 UpdateDriverForPlugAndPlayDevicesW( 00041 IN HWND hwndParent, 00042 IN LPCWSTR HardwareId, 00043 IN LPCWSTR FullInfPath, 00044 IN DWORD InstallFlags, 00045 OUT PBOOL bRebootRequired OPTIONAL) 00046 { 00047 DEVINSTDATA DevInstData; 00048 DWORD i; 00049 LPWSTR Buffer = NULL; 00050 DWORD BufferSize; 00051 LPCWSTR CurrentHardwareId; /* Pointer into Buffer */ 00052 BOOL FoundHardwareId, FoundAtLeastOneDevice = FALSE; 00053 BOOL ret = FALSE; 00054 00055 DevInstData.hDevInfo = INVALID_HANDLE_VALUE; 00056 00057 TRACE("UpdateDriverForPlugAndPlayDevicesW(%p %s %s 0x%x %p)\n", 00058 hwndParent, debugstr_w(HardwareId), debugstr_w(FullInfPath), InstallFlags, bRebootRequired); 00059 00060 /* FIXME: InstallFlags bRebootRequired ignored! */ 00061 00062 /* Check flags */ 00063 if (InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE)) 00064 { 00065 TRACE("Unknown flags: 0x%08lx\n", InstallFlags & ~(INSTALLFLAG_FORCE | INSTALLFLAG_READONLY | INSTALLFLAG_NONINTERACTIVE)); 00066 SetLastError(ERROR_INVALID_FLAGS); 00067 goto cleanup; 00068 } 00069 00070 /* Enumerate all devices of the system */ 00071 DevInstData.hDevInfo = SetupDiGetClassDevsW(NULL, NULL, hwndParent, DIGCF_ALLCLASSES | DIGCF_PRESENT); 00072 if (DevInstData.hDevInfo == INVALID_HANDLE_VALUE) 00073 goto cleanup; 00074 DevInstData.devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 00075 for (i = 0; ; i++) 00076 { 00077 if (!SetupDiEnumDeviceInfo(DevInstData.hDevInfo, i, &DevInstData.devInfoData)) 00078 { 00079 if (GetLastError() != ERROR_NO_MORE_ITEMS) 00080 { 00081 TRACE("SetupDiEnumDeviceInfo() failed with error 0x%x\n", GetLastError()); 00082 goto cleanup; 00083 } 00084 /* This error was expected */ 00085 break; 00086 } 00087 00088 /* Get Hardware ID */ 00089 HeapFree(GetProcessHeap(), 0, Buffer); 00090 Buffer = NULL; 00091 BufferSize = 0; 00092 while (!SetupDiGetDeviceRegistryPropertyW( 00093 DevInstData.hDevInfo, 00094 &DevInstData.devInfoData, 00095 SPDRP_HARDWAREID, 00096 NULL, 00097 (PBYTE)Buffer, 00098 BufferSize, 00099 &BufferSize)) 00100 { 00101 if (GetLastError() == ERROR_FILE_NOT_FOUND) 00102 { 00103 Buffer = NULL; 00104 break; 00105 } 00106 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 00107 { 00108 TRACE("SetupDiGetDeviceRegistryPropertyW() failed with error 0x%x\n", GetLastError()); 00109 goto cleanup; 00110 } 00111 /* This error was expected */ 00112 HeapFree(GetProcessHeap(), 0, Buffer); 00113 Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize); 00114 if (!Buffer) 00115 { 00116 TRACE("HeapAlloc() failed\n", GetLastError()); 00117 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00118 goto cleanup; 00119 } 00120 } 00121 if (Buffer == NULL) 00122 continue; 00123 00124 /* Check if we match the given hardware ID */ 00125 FoundHardwareId = FALSE; 00126 for (CurrentHardwareId = Buffer; *CurrentHardwareId != UNICODE_NULL; CurrentHardwareId += wcslen(CurrentHardwareId) + 1) 00127 { 00128 if (wcscmp(CurrentHardwareId, HardwareId) == 0) 00129 { 00130 FoundHardwareId = TRUE; 00131 break; 00132 } 00133 } 00134 if (!FoundHardwareId) 00135 continue; 00136 00137 /* We need to try to update the driver of this device */ 00138 00139 /* Get Instance ID */ 00140 HeapFree(GetProcessHeap(), 0, Buffer); 00141 Buffer = NULL; 00142 if (SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, NULL, 0, &BufferSize)) 00143 { 00144 /* Error, as the output buffer should be too small */ 00145 SetLastError(ERROR_GEN_FAILURE); 00146 goto cleanup; 00147 } 00148 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 00149 { 00150 TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError()); 00151 goto cleanup; 00152 } 00153 else if ((Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize * sizeof(WCHAR))) == NULL) 00154 { 00155 TRACE("HeapAlloc() failed\n", GetLastError()); 00156 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00157 goto cleanup; 00158 } 00159 else if (!SetupDiGetDeviceInstanceIdW(DevInstData.hDevInfo, &DevInstData.devInfoData, Buffer, BufferSize, NULL)) 00160 { 00161 TRACE("SetupDiGetDeviceInstanceIdW() failed with error 0x%x\n", GetLastError()); 00162 goto cleanup; 00163 } 00164 TRACE("Trying to update the driver of %s\n", debugstr_w(Buffer)); 00165 00166 /* Search driver in the specified .inf file */ 00167 if (!SearchDriver(&DevInstData, NULL, FullInfPath)) 00168 { 00169 TRACE("SearchDriver() failed with error 0x%x\n", GetLastError()); 00170 continue; 00171 } 00172 00173 /* FIXME: HACK! We shouldn't check of ERROR_PRIVILEGE_NOT_HELD */ 00174 //if (!InstallCurrentDriver(&DevInstData)) 00175 if (!InstallCurrentDriver(&DevInstData) && GetLastError() != ERROR_PRIVILEGE_NOT_HELD) 00176 { 00177 TRACE("InstallCurrentDriver() failed with error 0x%x\n", GetLastError()); 00178 continue; 00179 } 00180 00181 FoundAtLeastOneDevice = TRUE; 00182 } 00183 00184 if (FoundAtLeastOneDevice) 00185 { 00186 SetLastError(NO_ERROR); 00187 ret = TRUE; 00188 } 00189 else 00190 { 00191 TRACE("No device found with HardwareID %s\n", debugstr_w(HardwareId)); 00192 SetLastError(ERROR_NO_SUCH_DEVINST); 00193 } 00194 00195 cleanup: 00196 if (DevInstData.hDevInfo != INVALID_HANDLE_VALUE) 00197 SetupDiDestroyDeviceInfoList(DevInstData.hDevInfo); 00198 HeapFree(GetProcessHeap(), 0, Buffer); 00199 return ret; 00200 } 00201 00202 /* 00203 * @implemented 00204 */ 00205 BOOL WINAPI 00206 UpdateDriverForPlugAndPlayDevicesA( 00207 IN HWND hwndParent, 00208 IN LPCSTR HardwareId, 00209 IN LPCSTR FullInfPath, 00210 IN DWORD InstallFlags, 00211 OUT PBOOL bRebootRequired OPTIONAL) 00212 { 00213 BOOL Result; 00214 LPWSTR HardwareIdW = NULL; 00215 LPWSTR FullInfPathW = NULL; 00216 00217 int len = MultiByteToWideChar(CP_ACP, 0, HardwareId, -1, NULL, 0); 00218 HardwareIdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00219 if (!HardwareIdW) 00220 { 00221 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00222 return FALSE; 00223 } 00224 MultiByteToWideChar(CP_ACP, 0, HardwareId, -1, HardwareIdW, len); 00225 00226 len = MultiByteToWideChar(CP_ACP, 0, FullInfPath, -1, NULL, 0); 00227 FullInfPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00228 if (!FullInfPathW) 00229 { 00230 HeapFree(GetProcessHeap(), 0, HardwareIdW); 00231 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00232 return FALSE; 00233 } 00234 MultiByteToWideChar(CP_ACP, 0, FullInfPath, -1, FullInfPathW, len); 00235 00236 Result = UpdateDriverForPlugAndPlayDevicesW( 00237 hwndParent, 00238 HardwareIdW, 00239 FullInfPathW, 00240 InstallFlags, 00241 bRebootRequired); 00242 00243 HeapFree(GetProcessHeap(), 0, HardwareIdW); 00244 HeapFree(GetProcessHeap(), 0, FullInfPathW); 00245 00246 return Result; 00247 } 00248 00249 /* Directory and InfFile MUST NOT be specified simultaneously */ 00250 static BOOL 00251 SearchDriver( 00252 IN PDEVINSTDATA DevInstData, 00253 IN LPCWSTR Directory OPTIONAL, 00254 IN LPCWSTR InfFile OPTIONAL) 00255 { 00256 SP_DEVINSTALL_PARAMS_W DevInstallParams = {0,}; 00257 BOOL ret; 00258 00259 DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 00260 if (!SetupDiGetDeviceInstallParamsW(DevInstData->hDevInfo, &DevInstData->devInfoData, &DevInstallParams)) 00261 { 00262 TRACE("SetupDiGetDeviceInstallParams() failed with error 0x%x\n", GetLastError()); 00263 return FALSE; 00264 } 00265 DevInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS; 00266 00267 if (InfFile) 00268 { 00269 DevInstallParams.Flags |= DI_ENUMSINGLEINF; 00270 wcsncpy(DevInstallParams.DriverPath, InfFile, MAX_PATH); 00271 } 00272 else if (Directory) 00273 { 00274 DevInstallParams.Flags &= ~DI_ENUMSINGLEINF; 00275 wcsncpy(DevInstallParams.DriverPath, Directory, MAX_PATH); 00276 } 00277 else 00278 { 00279 DevInstallParams.Flags &= ~DI_ENUMSINGLEINF; 00280 *DevInstallParams.DriverPath = '\0'; 00281 } 00282 00283 ret = SetupDiSetDeviceInstallParamsW( 00284 DevInstData->hDevInfo, 00285 &DevInstData->devInfoData, 00286 &DevInstallParams); 00287 if (!ret) 00288 { 00289 TRACE("SetupDiSetDeviceInstallParams() failed with error 0x%x\n", GetLastError()); 00290 return FALSE; 00291 } 00292 00293 ret = SetupDiBuildDriverInfoList( 00294 DevInstData->hDevInfo, 00295 &DevInstData->devInfoData, 00296 SPDIT_COMPATDRIVER); 00297 if (!ret) 00298 { 00299 TRACE("SetupDiBuildDriverInfoList() failed with error 0x%x\n", GetLastError()); 00300 return FALSE; 00301 } 00302 00303 DevInstData->drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); 00304 ret = SetupDiEnumDriverInfoW( 00305 DevInstData->hDevInfo, 00306 &DevInstData->devInfoData, 00307 SPDIT_COMPATDRIVER, 00308 0, 00309 &DevInstData->drvInfoData); 00310 if (!ret) 00311 { 00312 if (GetLastError() == ERROR_NO_MORE_ITEMS) 00313 return FALSE; 00314 TRACE("SetupDiEnumDriverInfo() failed with error 0x%x\n", GetLastError()); 00315 return FALSE; 00316 } 00317 00318 return TRUE; 00319 } 00320 00321 static BOOL 00322 IsDots(IN LPCWSTR str) 00323 { 00324 if(wcscmp(str, L".") && wcscmp(str, L"..")) return FALSE; 00325 return TRUE; 00326 } 00327 00328 static LPCWSTR 00329 GetFileExt(IN LPWSTR FileName) 00330 { 00331 LPCWSTR Dot; 00332 00333 Dot = wcsrchr(FileName, '.'); 00334 if (!Dot) 00335 return L""; 00336 00337 return Dot; 00338 } 00339 00340 static BOOL 00341 SearchDriverRecursive( 00342 IN PDEVINSTDATA DevInstData, 00343 IN LPCWSTR Path) 00344 { 00345 WIN32_FIND_DATAW wfd; 00346 WCHAR DirPath[MAX_PATH]; 00347 WCHAR FileName[MAX_PATH]; 00348 WCHAR FullPath[MAX_PATH]; 00349 WCHAR LastDirPath[MAX_PATH] = L""; 00350 WCHAR PathWithPattern[MAX_PATH]; 00351 BOOL ok = TRUE; 00352 BOOL retval = FALSE; 00353 HANDLE hFindFile = INVALID_HANDLE_VALUE; 00354 00355 wcscpy(DirPath, Path); 00356 00357 if (DirPath[wcslen(DirPath) - 1] != '\\') 00358 wcscat(DirPath, L"\\"); 00359 00360 wcscpy(PathWithPattern, DirPath); 00361 wcscat(PathWithPattern, L"\\*"); 00362 00363 for (hFindFile = FindFirstFileW(PathWithPattern, &wfd); 00364 ok && hFindFile != INVALID_HANDLE_VALUE; 00365 ok = FindNextFileW(hFindFile, &wfd)) 00366 { 00367 00368 wcscpy(FileName, wfd.cFileName); 00369 if (IsDots(FileName)) 00370 continue; 00371 00372 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 00373 { 00374 /* Recursive search */ 00375 wcscpy(FullPath, DirPath); 00376 wcscat(FullPath, FileName); 00377 if (SearchDriverRecursive(DevInstData, FullPath)) 00378 { 00379 retval = TRUE; 00380 /* We continue the search for a better driver */ 00381 } 00382 } 00383 else 00384 { 00385 LPCWSTR pszExtension = GetFileExt(FileName); 00386 00387 if ((_wcsicmp(pszExtension, L".inf") == 0) && (wcscmp(LastDirPath, DirPath) != 0)) 00388 { 00389 wcscpy(LastDirPath, DirPath); 00390 00391 if (wcslen(DirPath) > MAX_PATH) 00392 /* Path is too long to be searched */ 00393 continue; 00394 00395 if (SearchDriver(DevInstData, DirPath, NULL)) 00396 { 00397 retval = TRUE; 00398 /* We continue the search for a better driver */ 00399 } 00400 00401 } 00402 } 00403 } 00404 00405 if (hFindFile != INVALID_HANDLE_VALUE) 00406 FindClose(hFindFile); 00407 return retval; 00408 } 00409 00410 BOOL 00411 ScanFoldersForDriver( 00412 IN PDEVINSTDATA DevInstData) 00413 { 00414 BOOL result; 00415 00416 /* Search in default location */ 00417 result = SearchDriver(DevInstData, NULL, NULL); 00418 00419 if (DevInstData->CustomSearchPath) 00420 { 00421 /* Search only in specified paths */ 00422 /* We need to check all specified directories to be 00423 * sure to find the best driver for the device. 00424 */ 00425 LPCWSTR Path; 00426 for (Path = DevInstData->CustomSearchPath; *Path != '\0'; Path += wcslen(Path) + 1) 00427 { 00428 TRACE("Search driver in %s\n", debugstr_w(Path)); 00429 if (wcslen(Path) == 2 && Path[1] == ':') 00430 { 00431 if (SearchDriverRecursive(DevInstData, Path)) 00432 result = TRUE; 00433 } 00434 else 00435 { 00436 if (SearchDriver(DevInstData, Path, NULL)) 00437 result = TRUE; 00438 } 00439 } 00440 } 00441 00442 return result; 00443 } 00444 00445 BOOL 00446 PrepareFoldersToScan( 00447 IN PDEVINSTDATA DevInstData, 00448 IN BOOL IncludeRemovableDevices, 00449 IN BOOL IncludeCustomPath, 00450 IN HWND hwndCombo OPTIONAL) 00451 { 00452 WCHAR drive[] = {'?',':',0}; 00453 DWORD dwDrives = 0; 00454 DWORD i; 00455 UINT nType; 00456 DWORD CustomTextLength = 0; 00457 DWORD LengthNeeded = 0; 00458 LPWSTR Buffer; 00459 00460 /* Calculate length needed to store the search paths */ 00461 if (IncludeRemovableDevices) 00462 { 00463 dwDrives = GetLogicalDrives(); 00464 for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1) 00465 { 00466 if (dwDrives & i) 00467 { 00468 nType = GetDriveTypeW(drive); 00469 if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM) 00470 { 00471 LengthNeeded += 3; 00472 } 00473 } 00474 } 00475 } 00476 if (IncludeCustomPath) 00477 { 00478 CustomTextLength = 1 + ComboBox_GetTextLength(hwndCombo); 00479 LengthNeeded += CustomTextLength; 00480 } 00481 00482 /* Allocate space for search paths */ 00483 HeapFree(GetProcessHeap(), 0, DevInstData->CustomSearchPath); 00484 DevInstData->CustomSearchPath = Buffer = HeapAlloc( 00485 GetProcessHeap(), 00486 0, 00487 (LengthNeeded + 1) * sizeof(WCHAR)); 00488 if (!Buffer) 00489 { 00490 TRACE("HeapAlloc() failed\n"); 00491 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00492 return FALSE; 00493 } 00494 00495 /* Fill search paths */ 00496 if (IncludeRemovableDevices) 00497 { 00498 for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1) 00499 { 00500 if (dwDrives & i) 00501 { 00502 nType = GetDriveTypeW(drive); 00503 if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM) 00504 { 00505 Buffer += 1 + swprintf(Buffer, drive); 00506 } 00507 } 00508 } 00509 } 00510 if (IncludeCustomPath) 00511 { 00512 Buffer += 1 + GetWindowTextW(hwndCombo, Buffer, CustomTextLength); 00513 } 00514 *Buffer = '\0'; 00515 00516 return TRUE; 00517 } 00518 00519 BOOL 00520 InstallCurrentDriver( 00521 IN PDEVINSTDATA DevInstData) 00522 { 00523 BOOL ret; 00524 00525 TRACE("Installing driver %s: %s\n", 00526 debugstr_w(DevInstData->drvInfoData.MfgName), 00527 debugstr_w(DevInstData->drvInfoData.Description)); 00528 00529 ret = SetupDiCallClassInstaller( 00530 DIF_SELECTBESTCOMPATDRV, 00531 DevInstData->hDevInfo, 00532 &DevInstData->devInfoData); 00533 if (!ret) 00534 { 00535 TRACE("SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV) failed with error 0x%x\n", GetLastError()); 00536 return FALSE; 00537 } 00538 00539 ret = SetupDiCallClassInstaller( 00540 DIF_ALLOW_INSTALL, 00541 DevInstData->hDevInfo, 00542 &DevInstData->devInfoData); 00543 if (!ret) 00544 { 00545 TRACE("SetupDiCallClassInstaller(DIF_ALLOW_INSTALL) failed with error 0x%x\n", GetLastError()); 00546 return FALSE; 00547 } 00548 00549 ret = SetupDiCallClassInstaller( 00550 DIF_NEWDEVICEWIZARD_PREANALYZE, 00551 DevInstData->hDevInfo, 00552 &DevInstData->devInfoData); 00553 if (!ret) 00554 { 00555 TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_PREANALYZE) failed with error 0x%x\n", GetLastError()); 00556 return FALSE; 00557 } 00558 00559 ret = SetupDiCallClassInstaller( 00560 DIF_NEWDEVICEWIZARD_POSTANALYZE, 00561 DevInstData->hDevInfo, 00562 &DevInstData->devInfoData); 00563 if (!ret) 00564 { 00565 TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_POSTANALYZE) failed with error 0x%x\n", GetLastError()); 00566 return FALSE; 00567 } 00568 00569 ret = SetupDiCallClassInstaller( 00570 DIF_INSTALLDEVICEFILES, 00571 DevInstData->hDevInfo, 00572 &DevInstData->devInfoData); 00573 if (!ret) 00574 { 00575 TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES) failed with error 0x%x\n", GetLastError()); 00576 return FALSE; 00577 } 00578 00579 ret = SetupDiCallClassInstaller( 00580 DIF_REGISTER_COINSTALLERS, 00581 DevInstData->hDevInfo, 00582 &DevInstData->devInfoData); 00583 if (!ret) 00584 { 00585 TRACE("SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS) failed with error 0x%x\n", GetLastError()); 00586 return FALSE; 00587 } 00588 00589 ret = SetupDiCallClassInstaller( 00590 DIF_INSTALLINTERFACES, 00591 DevInstData->hDevInfo, 00592 &DevInstData->devInfoData); 00593 if (!ret) 00594 { 00595 TRACE("SetupDiCallClassInstaller(DIF_INSTALLINTERFACES) failed with error 0x%x\n", GetLastError()); 00596 return FALSE; 00597 } 00598 00599 ret = SetupDiCallClassInstaller( 00600 DIF_INSTALLDEVICE, 00601 DevInstData->hDevInfo, 00602 &DevInstData->devInfoData); 00603 if (!ret) 00604 { 00605 TRACE("SetupDiCallClassInstaller(DIF_INSTALLDEVICE) failed with error 0x%x\n", GetLastError()); 00606 return FALSE; 00607 } 00608 00609 ret = SetupDiCallClassInstaller( 00610 DIF_NEWDEVICEWIZARD_FINISHINSTALL, 00611 DevInstData->hDevInfo, 00612 &DevInstData->devInfoData); 00613 if (!ret) 00614 { 00615 TRACE("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_FINISHINSTALL) failed with error 0x%x\n", GetLastError()); 00616 return FALSE; 00617 } 00618 00619 ret = SetupDiCallClassInstaller( 00620 DIF_DESTROYPRIVATEDATA, 00621 DevInstData->hDevInfo, 00622 &DevInstData->devInfoData); 00623 if (!ret) 00624 { 00625 TRACE("SetupDiCallClassInstaller(DIF_DESTROYPRIVATEDATA) failed with error 0x%x\n", GetLastError()); 00626 return FALSE; 00627 } 00628 00629 return TRUE; 00630 } 00631 00632 /* 00633 * @implemented 00634 */ 00635 BOOL WINAPI 00636 DevInstallW( 00637 IN HWND hWndParent, 00638 IN HINSTANCE hInstance, 00639 IN LPCWSTR InstanceId, 00640 IN INT Show) 00641 { 00642 PDEVINSTDATA DevInstData = NULL; 00643 BOOL ret; 00644 DWORD config_flags; 00645 BOOL retval = FALSE; 00646 00647 TRACE("(%p, %p, %s, %d)\n", hWndParent, hInstance, debugstr_w(InstanceId), Show); 00648 00649 if (!IsUserAdmin()) 00650 { 00651 /* XP kills the process... */ 00652 ExitProcess(ERROR_ACCESS_DENIED); 00653 } 00654 00655 DevInstData = HeapAlloc(GetProcessHeap(), 0, sizeof(DEVINSTDATA)); 00656 if (!DevInstData) 00657 { 00658 TRACE("HeapAlloc() failed\n"); 00659 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00660 goto cleanup; 00661 } 00662 00663 /* Clear devinst data */ 00664 ZeroMemory(DevInstData, sizeof(DEVINSTDATA)); 00665 DevInstData->devInfoData.cbSize = 0; /* Tell if the devInfoData is valid */ 00666 00667 /* Fill devinst data */ 00668 DevInstData->hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); 00669 if (DevInstData->hDevInfo == INVALID_HANDLE_VALUE) 00670 { 00671 TRACE("SetupDiCreateDeviceInfoListExW() failed with error 0x%x\n", GetLastError()); 00672 goto cleanup; 00673 } 00674 00675 DevInstData->devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 00676 ret = SetupDiOpenDeviceInfoW( 00677 DevInstData->hDevInfo, 00678 InstanceId, 00679 NULL, 00680 0, /* Open flags */ 00681 &DevInstData->devInfoData); 00682 if (!ret) 00683 { 00684 TRACE("SetupDiOpenDeviceInfoW() failed with error 0x%x (InstanceId %s)\n", 00685 GetLastError(), debugstr_w(InstanceId)); 00686 DevInstData->devInfoData.cbSize = 0; 00687 goto cleanup; 00688 } 00689 00690 SetLastError(ERROR_GEN_FAILURE); 00691 ret = SetupDiGetDeviceRegistryProperty( 00692 DevInstData->hDevInfo, 00693 &DevInstData->devInfoData, 00694 SPDRP_DEVICEDESC, 00695 &DevInstData->regDataType, 00696 NULL, 0, 00697 &DevInstData->requiredSize); 00698 00699 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER && DevInstData->regDataType == REG_SZ) 00700 { 00701 DevInstData->buffer = HeapAlloc(GetProcessHeap(), 0, DevInstData->requiredSize); 00702 if (!DevInstData->buffer) 00703 { 00704 TRACE("HeapAlloc() failed\n"); 00705 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00706 } 00707 else 00708 { 00709 ret = SetupDiGetDeviceRegistryPropertyW( 00710 DevInstData->hDevInfo, 00711 &DevInstData->devInfoData, 00712 SPDRP_DEVICEDESC, 00713 &DevInstData->regDataType, 00714 DevInstData->buffer, DevInstData->requiredSize, 00715 &DevInstData->requiredSize); 00716 } 00717 } 00718 if (!ret) 00719 { 00720 TRACE("SetupDiGetDeviceRegistryProperty() failed with error 0x%x (InstanceId %s)\n", 00721 GetLastError(), debugstr_w(InstanceId)); 00722 goto cleanup; 00723 } 00724 00725 if (SetupDiGetDeviceRegistryPropertyW( 00726 DevInstData->hDevInfo, 00727 &DevInstData->devInfoData, 00728 SPDRP_CONFIGFLAGS, 00729 NULL, 00730 (BYTE *)&config_flags, 00731 sizeof(config_flags), 00732 NULL)) 00733 { 00734 if (config_flags & CONFIGFLAG_FAILEDINSTALL) 00735 { 00736 /* The device is disabled */ 00737 TRACE("Device is disabled\n"); 00738 retval = TRUE; 00739 goto cleanup; 00740 } 00741 } 00742 00743 TRACE("Installing %s (%s)\n", debugstr_w((PCWSTR)DevInstData->buffer), debugstr_w(InstanceId)); 00744 00745 /* Search driver in default location and removable devices */ 00746 if (!PrepareFoldersToScan(DevInstData, FALSE, FALSE, NULL)) 00747 { 00748 TRACE("PrepareFoldersToScan() failed with error 0x%lx\n", GetLastError()); 00749 goto cleanup; 00750 } 00751 if (ScanFoldersForDriver(DevInstData)) 00752 { 00753 /* Driver found ; install it */ 00754 retval = InstallCurrentDriver(DevInstData); 00755 TRACE("InstallCurrentDriver() returned %d\n", retval); 00756 if (retval && Show != SW_HIDE) 00757 { 00758 /* Should we display the 'Need to reboot' page? */ 00759 SP_DEVINSTALL_PARAMS installParams; 00760 installParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 00761 if (SetupDiGetDeviceInstallParams( 00762 DevInstData->hDevInfo, 00763 &DevInstData->devInfoData, 00764 &installParams)) 00765 { 00766 if (installParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) 00767 { 00768 TRACE("Displaying 'Reboot' wizard page\n"); 00769 retval = DisplayWizard(DevInstData, hWndParent, IDD_NEEDREBOOT); 00770 } 00771 } 00772 } 00773 goto cleanup; 00774 } 00775 else if (Show == SW_HIDE) 00776 { 00777 /* We can't show the wizard. Fail the install */ 00778 TRACE("No wizard\n"); 00779 goto cleanup; 00780 } 00781 00782 /* Prepare the wizard, and display it */ 00783 TRACE("Need to show install wizard\n"); 00784 retval = DisplayWizard(DevInstData, hWndParent, IDD_WELCOMEPAGE); 00785 00786 cleanup: 00787 if (DevInstData) 00788 { 00789 if (DevInstData->devInfoData.cbSize != 0) 00790 { 00791 if (!SetupDiDestroyDriverInfoList(DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER)) 00792 TRACE("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError()); 00793 } 00794 if (DevInstData->hDevInfo != INVALID_HANDLE_VALUE) 00795 { 00796 if (!SetupDiDestroyDeviceInfoList(DevInstData->hDevInfo)) 00797 TRACE("SetupDiDestroyDeviceInfoList() failed with error 0x%lx\n", GetLastError()); 00798 } 00799 HeapFree(GetProcessHeap(), 0, DevInstData->buffer); 00800 HeapFree(GetProcessHeap(), 0, DevInstData); 00801 } 00802 00803 return retval; 00804 } 00805 00806 /* 00807 * @implemented 00808 */ 00809 BOOL WINAPI 00810 ClientSideInstallW( 00811 IN HWND hWndOwner, 00812 IN DWORD dwUnknownFlags, 00813 IN LPWSTR lpNamedPipeName) 00814 { 00815 BOOL ReturnValue = FALSE; 00816 BOOL ShowWizard; 00817 DWORD BytesRead; 00818 DWORD Value; 00819 HANDLE hPipe = INVALID_HANDLE_VALUE; 00820 PWSTR DeviceInstance = NULL; 00821 PWSTR InstallEventName = NULL; 00822 00823 /* Open the pipe */ 00824 hPipe = CreateFileW(lpNamedPipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00825 00826 if(hPipe == INVALID_HANDLE_VALUE) 00827 { 00828 ERR("CreateFileW failed with error %u\n", GetLastError()); 00829 goto cleanup; 00830 } 00831 00832 /* Read the data. Some is just included for compatibility with Windows right now and not yet used by ReactOS. 00833 See umpnpmgr for more details. */ 00834 if(!ReadFile(hPipe, &Value, sizeof(Value), &BytesRead, NULL)) 00835 { 00836 ERR("ReadFile failed with error %u\n", GetLastError()); 00837 goto cleanup; 00838 } 00839 00840 InstallEventName = (PWSTR)HeapAlloc(GetProcessHeap(), 0, Value); 00841 00842 if(!ReadFile(hPipe, InstallEventName, Value, &BytesRead, NULL)) 00843 { 00844 ERR("ReadFile failed with error %u\n", GetLastError()); 00845 goto cleanup; 00846 } 00847 00848 /* I couldn't figure out what the following value means under Windows XP. 00849 Therefore I used it in umpnpmgr to pass the ShowWizard variable. */ 00850 if(!ReadFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesRead, NULL)) 00851 { 00852 ERR("ReadFile failed with error %u\n", GetLastError()); 00853 goto cleanup; 00854 } 00855 00856 /* Next one is again size in bytes of the following string */ 00857 if(!ReadFile(hPipe, &Value, sizeof(Value), &BytesRead, NULL)) 00858 { 00859 ERR("ReadFile failed with error %u\n", GetLastError()); 00860 goto cleanup; 00861 } 00862 00863 DeviceInstance = (PWSTR)HeapAlloc(GetProcessHeap(), 0, Value); 00864 00865 if(!ReadFile(hPipe, DeviceInstance, Value, &BytesRead, NULL)) 00866 { 00867 ERR("ReadFile failed with error %u\n", GetLastError()); 00868 goto cleanup; 00869 } 00870 00871 ReturnValue = DevInstallW(NULL, NULL, DeviceInstance, ShowWizard ? SW_SHOWNOACTIVATE : SW_HIDE); 00872 00873 cleanup: 00874 if(hPipe != INVALID_HANDLE_VALUE) 00875 CloseHandle(hPipe); 00876 00877 if(InstallEventName) 00878 HeapFree(GetProcessHeap(), 0, InstallEventName); 00879 00880 if(DeviceInstance) 00881 HeapFree(GetProcessHeap(), 0, DeviceInstance); 00882 00883 return ReturnValue; 00884 } 00885 00886 BOOL WINAPI 00887 DllMain( 00888 IN HINSTANCE hInstance, 00889 IN DWORD dwReason, 00890 IN LPVOID lpReserved) 00891 { 00892 if (dwReason == DLL_PROCESS_ATTACH) 00893 { 00894 INITCOMMONCONTROLSEX InitControls; 00895 00896 DisableThreadLibraryCalls(hInstance); 00897 00898 InitControls.dwSize = sizeof(INITCOMMONCONTROLSEX); 00899 InitControls.dwICC = ICC_PROGRESS_CLASS; 00900 InitCommonControlsEx(&InitControls); 00901 hDllInstance = hInstance; 00902 } 00903 00904 return TRUE; 00905 } Generated on Fri May 25 2012 04:23:38 for ReactOS by
1.7.6.1
|