Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendriver.c
Go to the documentation of this file.
00001 /* 00002 * SetupAPI driver-related functions 00003 * 00004 * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org) 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "setupapi_private.h" 00022 00023 WINE_DEFAULT_DEBUG_CHANNEL(setupapi); 00024 00025 /* Unicode constants */ 00026 static const WCHAR BackSlash[] = {'\\',0}; 00027 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; 00028 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0}; 00029 static const WCHAR InfDirectory[] = {'i','n','f','\\',0}; 00030 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; 00031 00032 static const WCHAR INF_MANUFACTURER[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; 00033 static const WCHAR INF_PROVIDER[] = {'P','r','o','v','i','d','e','r',0}; 00034 static const WCHAR INF_DRIVER_VER[] = {'D','r','i','v','e','r','V','e','r',0}; 00035 00036 00037 /*********************************************************************** 00038 * struct InfFileDetails management 00039 */ 00040 static VOID 00041 ReferenceInfFile(struct InfFileDetails* infFile) 00042 { 00043 InterlockedIncrement(&infFile->References); 00044 } 00045 00046 VOID 00047 DereferenceInfFile(struct InfFileDetails* infFile) 00048 { 00049 if (InterlockedDecrement(&infFile->References) == 0) 00050 { 00051 SetupCloseInfFile(infFile->hInf); 00052 HeapFree(GetProcessHeap(), 0, infFile); 00053 } 00054 } 00055 00056 struct InfFileDetails * 00057 CreateInfFileDetails( 00058 IN LPCWSTR FullInfFileName) 00059 { 00060 struct InfFileDetails *details; 00061 PWCHAR last; 00062 DWORD Needed; 00063 00064 Needed = FIELD_OFFSET(struct InfFileDetails, szData) 00065 + strlenW(FullInfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL); 00066 00067 details = HeapAlloc(GetProcessHeap(), 0, Needed); 00068 if (!details) 00069 { 00070 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00071 return NULL; 00072 } 00073 00074 memset(details, 0, Needed); 00075 strcpyW(details->szData, FullInfFileName); 00076 last = strrchrW(details->szData, '\\'); 00077 if (last) 00078 { 00079 details->DirectoryName = details->szData; 00080 details->FileName = last + 1; 00081 *last = '\0'; 00082 } 00083 else 00084 details->FileName = details->szData; 00085 ReferenceInfFile(details); 00086 details->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL); 00087 if (details->hInf == INVALID_HANDLE_VALUE) 00088 { 00089 HeapFree(GetProcessHeap(), 0, details); 00090 return NULL; 00091 } 00092 return details; 00093 } 00094 00095 BOOL 00096 DestroyDriverInfoElement(struct DriverInfoElement* driverInfo) 00097 { 00098 DereferenceInfFile(driverInfo->InfFileDetails); 00099 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId); 00100 HeapFree(GetProcessHeap(), 0, driverInfo); 00101 return TRUE; 00102 } 00103 00104 /*********************************************************************** 00105 * Helper functions for SetupDiBuildDriverInfoList 00106 */ 00107 static BOOL 00108 AddKnownDriverToList( 00109 IN PLIST_ENTRY DriverListHead, 00110 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */ 00111 IN LPGUID ClassGuid, 00112 IN struct InfFileDetails *InfFileDetails, 00113 IN LPCWSTR InfFile, 00114 IN LPCWSTR SectionName, 00115 IN LPCWSTR DriverDescription, 00116 IN LPCWSTR ProviderName, 00117 IN LPCWSTR ManufacturerName, 00118 IN LPCWSTR MatchingId, 00119 IN FILETIME DriverDate, 00120 IN DWORDLONG DriverVersion, 00121 IN DWORD Rank) 00122 { 00123 struct DriverInfoElement *driverInfo = NULL; 00124 HANDLE hFile = INVALID_HANDLE_VALUE; 00125 BOOL Result = FALSE; 00126 PLIST_ENTRY PreviousEntry; 00127 BOOL ret = FALSE; 00128 00129 driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement)); 00130 if (!driverInfo) 00131 { 00132 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00133 goto cleanup; 00134 } 00135 memset(driverInfo, 0, sizeof(struct DriverInfoElement)); 00136 00137 driverInfo->Params.cbSize = sizeof(SP_DRVINSTALL_PARAMS); 00138 driverInfo->Params.Reserved = (ULONG_PTR)driverInfo; 00139 00140 driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); 00141 driverInfo->Details.Reserved = (ULONG_PTR)driverInfo; 00142 00143 /* Copy InfFileName field */ 00144 lstrcpynW(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1); 00145 driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0'; 00146 00147 /* Fill InfDate field */ 00148 hFile = CreateFileW( 00149 InfFile, 00150 GENERIC_READ, FILE_SHARE_READ, 00151 NULL, OPEN_EXISTING, 0, NULL); 00152 if (hFile == INVALID_HANDLE_VALUE) 00153 goto cleanup; 00154 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate); 00155 if (!Result) 00156 goto cleanup; 00157 00158 /* Fill SectionName field */ 00159 lstrcpynW(driverInfo->Details.SectionName, SectionName, LINE_LEN); 00160 00161 /* Fill DrvDescription field */ 00162 lstrcpynW(driverInfo->Details.DrvDescription, DriverDescription, LINE_LEN); 00163 00164 /* Copy MatchingId information */ 00165 if (MatchingId) 00166 { 00167 driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId) + 1) * sizeof(WCHAR)); 00168 if (!driverInfo->MatchingId) 00169 { 00170 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00171 goto cleanup; 00172 } 00173 RtlCopyMemory(driverInfo->MatchingId, MatchingId, (strlenW(MatchingId) + 1) * sizeof(WCHAR)); 00174 } 00175 else 00176 driverInfo->MatchingId = NULL; 00177 00178 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n", 00179 debugstr_w(driverInfo->Details.DrvDescription), debugstr_w(InfFile), 00180 debugstr_w(SectionName), Rank); 00181 00182 driverInfo->Params.Rank = Rank; 00183 memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME)); 00184 memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID)); 00185 driverInfo->Info.DriverType = DriverType; 00186 driverInfo->Info.Reserved = (ULONG_PTR)driverInfo; 00187 lstrcpynW(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1); 00188 driverInfo->Info.Description[LINE_LEN - 1] = '\0'; 00189 lstrcpynW(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1); 00190 driverInfo->Info.MfgName[LINE_LEN - 1] = '\0'; 00191 if (ProviderName) 00192 { 00193 lstrcpynW(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1); 00194 driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0'; 00195 } 00196 else 00197 driverInfo->Info.ProviderName[0] = '\0'; 00198 driverInfo->Info.DriverDate = DriverDate; 00199 driverInfo->Info.DriverVersion = DriverVersion; 00200 ReferenceInfFile(InfFileDetails); 00201 driverInfo->InfFileDetails = InfFileDetails; 00202 00203 /* Insert current driver in driver list, according to its rank */ 00204 PreviousEntry = DriverListHead->Flink; 00205 while (PreviousEntry != DriverListHead) 00206 { 00207 struct DriverInfoElement *CurrentDriver; 00208 CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry); 00209 if (CurrentDriver->Params.Rank > Rank || 00210 (CurrentDriver->Params.Rank == Rank && CurrentDriver->DriverDate.QuadPart < driverInfo->DriverDate.QuadPart)) 00211 { 00212 /* Insert before the current item */ 00213 InsertHeadList(PreviousEntry->Blink, &driverInfo->ListEntry); 00214 break; 00215 } 00216 PreviousEntry = PreviousEntry->Flink; 00217 } 00218 if (PreviousEntry == DriverListHead) 00219 { 00220 /* Insert at the end of the list */ 00221 InsertTailList(DriverListHead, &driverInfo->ListEntry); 00222 } 00223 00224 ret = TRUE; 00225 00226 cleanup: 00227 if (!ret) 00228 { 00229 if (driverInfo) 00230 HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId); 00231 HeapFree(GetProcessHeap(), 0, driverInfo); 00232 } 00233 if (hFile != INVALID_HANDLE_VALUE) 00234 CloseHandle(hFile); 00235 00236 return ret; 00237 } 00238 00239 static BOOL 00240 AddDriverToList( 00241 IN PLIST_ENTRY DriverListHead, 00242 IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */ 00243 IN LPGUID ClassGuid, 00244 IN INFCONTEXT ContextDevice, 00245 IN struct InfFileDetails *InfFileDetails, 00246 IN LPCWSTR InfFile, 00247 IN LPCWSTR ProviderName, 00248 IN LPCWSTR ManufacturerName, 00249 IN LPCWSTR MatchingId, 00250 IN FILETIME DriverDate, 00251 IN DWORDLONG DriverVersion, 00252 IN DWORD Rank) 00253 { 00254 LPWSTR SectionName = NULL; 00255 LPWSTR DriverDescription = NULL; 00256 BOOL Result; 00257 BOOL ret = FALSE; 00258 00259 /* Read SectionName */ 00260 SectionName = MyMalloc(LINE_LEN); 00261 if (!SectionName) 00262 { 00263 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00264 goto cleanup; 00265 } 00266 ZeroMemory(SectionName, LINE_LEN); 00267 Result = SetupGetStringFieldW( 00268 &ContextDevice, 00269 1, 00270 SectionName, 00271 LINE_LEN, 00272 NULL); 00273 if (!Result) 00274 goto cleanup; 00275 00276 /* Read DriverDescription */ 00277 DriverDescription = MyMalloc(LINE_LEN); 00278 if (!DriverDescription) 00279 { 00280 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00281 goto cleanup; 00282 } 00283 ZeroMemory(DriverDescription, LINE_LEN); 00284 Result = SetupGetStringFieldW( 00285 &ContextDevice, 00286 0, /* Field index */ 00287 DriverDescription, LINE_LEN, 00288 NULL); 00289 00290 ret = AddKnownDriverToList( 00291 DriverListHead, 00292 DriverType, 00293 ClassGuid, 00294 InfFileDetails, 00295 InfFile, 00296 SectionName, 00297 DriverDescription, 00298 ProviderName, 00299 ManufacturerName, 00300 MatchingId, 00301 DriverDate, 00302 DriverVersion, 00303 Rank); 00304 00305 cleanup: 00306 MyFree(SectionName); 00307 MyFree(DriverDescription); 00308 00309 return ret; 00310 } 00311 00312 static BOOL 00313 GetVersionInformationFromInfFile( 00314 IN HINF hInf, 00315 OUT LPGUID ClassGuid, 00316 OUT LPWSTR* pProviderName, 00317 OUT FILETIME* DriverDate, 00318 OUT DWORDLONG* DriverVersion) 00319 { 00320 DWORD RequiredSize; 00321 WCHAR guidW[MAX_GUID_STRING_LEN + 1]; 00322 LPWSTR DriverVer = NULL; 00323 LPWSTR ProviderName = NULL; 00324 LPWSTR pComma; /* Points into DriverVer */ 00325 LPWSTR pVersion = NULL; /* Points into DriverVer */ 00326 SYSTEMTIME SystemTime; 00327 BOOL Result; 00328 BOOL ret = FALSE; /* Final result */ 00329 00330 /* Get class Guid */ 00331 if (!SetupGetLineTextW( 00332 NULL, /* Context */ 00333 hInf, 00334 Version, ClassGUID, 00335 guidW, sizeof(guidW), 00336 NULL /* Required size */)) 00337 { 00338 goto cleanup; 00339 } 00340 guidW[37] = '\0'; /* Replace the } by a NULL character */ 00341 if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK) 00342 { 00343 SetLastError(ERROR_GEN_FAILURE); 00344 goto cleanup; 00345 } 00346 00347 /* Get provider name */ 00348 Result = SetupGetLineTextW( 00349 NULL, /* Context */ 00350 hInf, Version, INF_PROVIDER, 00351 NULL, 0, 00352 &RequiredSize); 00353 if (Result) 00354 { 00355 /* We know the needed buffer size */ 00356 ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 00357 if (!ProviderName) 00358 { 00359 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00360 goto cleanup; 00361 } 00362 Result = SetupGetLineTextW( 00363 NULL, /* Context */ 00364 hInf, Version, INF_PROVIDER, 00365 ProviderName, RequiredSize, 00366 &RequiredSize); 00367 } 00368 if (!Result) 00369 goto cleanup; 00370 *pProviderName = ProviderName; 00371 00372 /* Read the "DriverVer" value */ 00373 Result = SetupGetLineTextW( 00374 NULL, /* Context */ 00375 hInf, Version, INF_DRIVER_VER, 00376 NULL, 0, 00377 &RequiredSize); 00378 if (Result) 00379 { 00380 /* We know know the needed buffer size */ 00381 DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 00382 if (!DriverVer) 00383 { 00384 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00385 goto cleanup; 00386 } 00387 Result = SetupGetLineTextW( 00388 NULL, /* Context */ 00389 hInf, Version, INF_DRIVER_VER, 00390 DriverVer, RequiredSize, 00391 &RequiredSize); 00392 } 00393 else 00394 { 00395 /* windows sets default date of 00/00/0000 when this directive is missing*/ 00396 memset(DriverDate, 0, sizeof(FILETIME)); 00397 *DriverVersion = 0; 00398 return TRUE; 00399 } 00400 00401 /* Get driver date and driver version, by analyzing the "DriverVer" value */ 00402 pComma = strchrW(DriverVer, ','); 00403 if (pComma != NULL) 00404 { 00405 *pComma = UNICODE_NULL; 00406 pVersion = pComma + 1; 00407 } 00408 /* Get driver date version. Invalid date = 00/00/00 */ 00409 memset(DriverDate, 0, sizeof(FILETIME)); 00410 if (strlenW(DriverVer) == 10 00411 && (DriverVer[2] == '-' || DriverVer[2] == '/') 00412 && (DriverVer[5] == '-' || DriverVer[5] == '/')) 00413 { 00414 memset(&SystemTime, 0, sizeof(SYSTEMTIME)); 00415 DriverVer[2] = DriverVer[5] = UNICODE_NULL; 00416 SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0'; 00417 SystemTime.wDay = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0'; 00418 SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0'; 00419 SystemTimeToFileTime(&SystemTime, DriverDate); 00420 } 00421 /* Get driver version. Invalid version = 0.0.0.0 */ 00422 *DriverVersion = 0; 00423 if (pVersion) 00424 { 00425 WORD Major, Minor = 0, Revision = 0, Build = 0; 00426 LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL; 00427 LARGE_INTEGER fullVersion; 00428 00429 pMinor = strchrW(pVersion, '.'); 00430 if (pMinor) 00431 { 00432 *pMinor = 0; 00433 pRevision = strchrW(++pMinor, '.'); 00434 Minor = atoiW(pMinor); 00435 } 00436 if (pRevision) 00437 { 00438 *pRevision = 0; 00439 pBuild = strchrW(++pRevision, '.'); 00440 Revision = atoiW(pRevision); 00441 } 00442 if (pBuild) 00443 { 00444 *pBuild = 0; 00445 pBuild++; 00446 Build = atoiW(pBuild); 00447 } 00448 Major = atoiW(pVersion); 00449 fullVersion.u.HighPart = Major << 16 | Minor; 00450 fullVersion.u.LowPart = Revision << 16 | Build; 00451 memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER)); 00452 } 00453 00454 ret = TRUE; 00455 00456 cleanup: 00457 if (!ret) 00458 { 00459 HeapFree(GetProcessHeap(), 0, ProviderName); 00460 *pProviderName = NULL; 00461 } 00462 HeapFree(GetProcessHeap(), 0, DriverVer); 00463 00464 return ret; 00465 } 00466 00467 static BOOL 00468 GetHardwareAndCompatibleIDsLists( 00469 IN HDEVINFO DeviceInfoSet, 00470 IN OUT PSP_DEVINFO_DATA DeviceInfoData, 00471 OUT LPWSTR *pHardwareIDs OPTIONAL, 00472 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL, 00473 OUT LPWSTR *pCompatibleIDs OPTIONAL, 00474 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL) 00475 { 00476 LPWSTR HardwareIDs = NULL; 00477 LPWSTR CompatibleIDs = NULL; 00478 DWORD RequiredSize; 00479 BOOL Result; 00480 00481 /* Get hardware IDs list */ 00482 Result = FALSE; 00483 RequiredSize = 512; /* Initial buffer size */ 00484 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00485 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 00486 { 00487 MyFree(HardwareIDs); 00488 HardwareIDs = MyMalloc(RequiredSize); 00489 if (!HardwareIDs) 00490 { 00491 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00492 goto done; 00493 } 00494 Result = SetupDiGetDeviceRegistryPropertyW( 00495 DeviceInfoSet, 00496 DeviceInfoData, 00497 SPDRP_HARDWAREID, 00498 NULL, 00499 (PBYTE)HardwareIDs, 00500 RequiredSize, 00501 &RequiredSize); 00502 } 00503 if (!Result) 00504 { 00505 if (GetLastError() == ERROR_FILE_NOT_FOUND) 00506 { 00507 /* No hardware ID for this device */ 00508 MyFree(HardwareIDs); 00509 HardwareIDs = NULL; 00510 RequiredSize = 0; 00511 } 00512 else 00513 goto done; 00514 } 00515 if (pHardwareIDs) 00516 *pHardwareIDs = HardwareIDs; 00517 if (pHardwareIDsRequiredSize) 00518 *pHardwareIDsRequiredSize = RequiredSize; 00519 00520 /* Get compatible IDs list */ 00521 Result = FALSE; 00522 RequiredSize = 512; /* Initial buffer size */ 00523 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00524 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 00525 { 00526 MyFree(CompatibleIDs); 00527 CompatibleIDs = MyMalloc(RequiredSize); 00528 if (!CompatibleIDs) 00529 { 00530 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00531 goto done; 00532 } 00533 Result = SetupDiGetDeviceRegistryPropertyW( 00534 DeviceInfoSet, 00535 DeviceInfoData, 00536 SPDRP_COMPATIBLEIDS, 00537 NULL, 00538 (PBYTE)CompatibleIDs, 00539 RequiredSize, 00540 &RequiredSize); 00541 } 00542 if (!Result) 00543 { 00544 if (GetLastError() == ERROR_FILE_NOT_FOUND) 00545 { 00546 /* No compatible ID for this device */ 00547 MyFree(CompatibleIDs); 00548 CompatibleIDs = NULL; 00549 RequiredSize = 0; 00550 } 00551 else 00552 goto done; 00553 } 00554 if (pCompatibleIDs) 00555 *pCompatibleIDs = CompatibleIDs; 00556 if (pCompatibleIDsRequiredSize) 00557 *pCompatibleIDsRequiredSize = RequiredSize; 00558 00559 Result = TRUE; 00560 00561 done: 00562 if (!Result) 00563 { 00564 MyFree(HardwareIDs); 00565 MyFree(CompatibleIDs); 00566 } 00567 return Result; 00568 } 00569 00570 #if WIN32_WINNT < 0x0600 00571 /* WARNING: 00572 * This code has been copied from advapi32/reg/reg.c, 00573 * so this dll can be tested as is on Windows XP 00574 */ 00575 00576 #define RRF_RT_REG_NONE (1 << 0) 00577 #define RRF_RT_REG_SZ (1 << 1) 00578 #define RRF_RT_REG_EXPAND_SZ (1 << 2) 00579 #define RRF_RT_REG_BINARY (1 << 3) 00580 #define RRF_RT_REG_DWORD (1 << 4) 00581 #define RRF_RT_REG_MULTI_SZ (1 << 5) 00582 #define RRF_RT_REG_QWORD (1 << 6) 00583 #define RRF_RT_DWORD (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD) 00584 #define RRF_RT_QWORD (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD) 00585 #define RRF_NOEXPAND (1 << 28) 00586 #define RRF_ZEROONFAILURE (1 << 29) 00587 00588 static VOID 00589 RegpApplyRestrictions( DWORD dwFlags, DWORD dwType, DWORD cbData, 00590 PLONG ret ) 00591 { 00592 /* Check if the type is restricted by the passed flags */ 00593 if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA) 00594 { 00595 DWORD dwMask = 0; 00596 00597 switch (dwType) 00598 { 00599 case REG_NONE: dwMask = RRF_RT_REG_NONE; break; 00600 case REG_SZ: dwMask = RRF_RT_REG_SZ; break; 00601 case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break; 00602 case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break; 00603 case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break; 00604 case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break; 00605 case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break; 00606 } 00607 00608 if (dwFlags & dwMask) 00609 { 00610 /* Type is not restricted, check for size mismatch */ 00611 if (dwType == REG_BINARY) 00612 { 00613 DWORD cbExpect = 0; 00614 00615 if ((dwFlags & RRF_RT_DWORD) == RRF_RT_DWORD) 00616 cbExpect = 4; 00617 else if ((dwFlags & RRF_RT_QWORD) == RRF_RT_QWORD) 00618 cbExpect = 8; 00619 00620 if (cbExpect && cbData != cbExpect) 00621 *ret = ERROR_DATATYPE_MISMATCH; 00622 } 00623 } 00624 else *ret = ERROR_UNSUPPORTED_TYPE; 00625 } 00626 } 00627 00628 static LONG WINAPI 00629 RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, 00630 DWORD dwFlags, LPDWORD pdwType, PVOID pvData, 00631 LPDWORD pcbData ) 00632 { 00633 DWORD dwType, cbData = pcbData ? *pcbData : 0; 00634 PVOID pvBuf = NULL; 00635 LONG ret; 00636 00637 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n", 00638 hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType, 00639 pvData, pcbData, cbData); 00640 00641 if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND)) 00642 return ERROR_INVALID_PARAMETER; 00643 00644 if (pszSubKey && pszSubKey[0]) 00645 { 00646 ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey); 00647 if (ret != ERROR_SUCCESS) return ret; 00648 } 00649 00650 ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData); 00651 00652 /* If we are going to expand we need to read in the whole the value even 00653 * if the passed buffer was too small as the expanded string might be 00654 * smaller than the unexpanded one and could fit into cbData bytes. */ 00655 if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && 00656 (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))) 00657 { 00658 do { 00659 if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf); 00660 00661 pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData); 00662 if (!pvBuf) 00663 { 00664 ret = ERROR_NOT_ENOUGH_MEMORY; 00665 break; 00666 } 00667 00668 if (ret == ERROR_MORE_DATA) 00669 ret = RegQueryValueExW(hKey, pszValue, NULL, 00670 &dwType, pvBuf, &cbData); 00671 else 00672 { 00673 /* Even if cbData was large enough we have to copy the 00674 * string since ExpandEnvironmentStrings can't handle 00675 * overlapping buffers. */ 00676 CopyMemory(pvBuf, pvData, cbData); 00677 } 00678 00679 /* Both the type or the value itself could have been modified in 00680 * between so we have to keep retrying until the buffer is large 00681 * enough or we no longer have to expand the value. */ 00682 } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA); 00683 00684 if (ret == ERROR_SUCCESS) 00685 { 00686 if (dwType == REG_EXPAND_SZ) 00687 { 00688 cbData = ExpandEnvironmentStringsW(pvBuf, pvData, 00689 pcbData ? (*pcbData)/sizeof(WCHAR) : 0); 00690 dwType = REG_SZ; 00691 if(pcbData && cbData > ((*pcbData)/sizeof(WCHAR))) 00692 ret = ERROR_MORE_DATA; 00693 } 00694 else if (pcbData) 00695 CopyMemory(pvData, pvBuf, *pcbData); 00696 } 00697 00698 if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf); 00699 } 00700 00701 if (pszSubKey && pszSubKey[0]) 00702 RegCloseKey(hKey); 00703 00704 RegpApplyRestrictions(dwFlags, dwType, cbData, &ret); 00705 00706 if (pcbData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE)) 00707 ZeroMemory(pvData, *pcbData); 00708 00709 if (pdwType) *pdwType = dwType; 00710 if (pcbData) *pcbData = cbData; 00711 00712 return ret; 00713 } 00714 #endif /* End of code copied from advapi32/reg/reg.c */ 00715 00716 /*********************************************************************** 00717 * SetupDiBuildDriverInfoList (SETUPAPI.@) 00718 */ 00719 BOOL WINAPI 00720 SetupDiBuildDriverInfoList( 00721 IN HDEVINFO DeviceInfoSet, 00722 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 00723 IN DWORD DriverType) 00724 { 00725 struct DeviceInfoSet *list; 00726 SP_DEVINSTALL_PARAMS_W InstallParams; 00727 PVOID Buffer = NULL; 00728 struct InfFileDetails *currentInfFileDetails = NULL; 00729 LPWSTR ProviderName = NULL; 00730 LPWSTR ManufacturerName = NULL; 00731 WCHAR ManufacturerSection[LINE_LEN + 1]; 00732 LPWSTR HardwareIDs = NULL; 00733 LPWSTR CompatibleIDs = NULL; 00734 LPWSTR FullInfFileName = NULL; 00735 LPWSTR ExcludeFromSelect = NULL; 00736 FILETIME DriverDate; 00737 DWORDLONG DriverVersion = 0; 00738 DWORD RequiredSize; 00739 BOOL ret = FALSE; 00740 00741 TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType); 00742 00743 if (!DeviceInfoSet) 00744 SetLastError(ERROR_INVALID_HANDLE); 00745 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 00746 SetLastError(ERROR_INVALID_HANDLE); 00747 else if (list->HKLM != HKEY_LOCAL_MACHINE) 00748 SetLastError(ERROR_INVALID_HANDLE); 00749 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER) 00750 SetLastError(ERROR_INVALID_PARAMETER); 00751 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData) 00752 SetLastError(ERROR_INVALID_PARAMETER); 00753 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 00754 SetLastError(ERROR_INVALID_USER_BUFFER); 00755 else 00756 { 00757 PLIST_ENTRY pDriverListHead = &list->DriverListHead; 00758 BOOL Result; 00759 00760 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 00761 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 00762 if (!Result) 00763 goto done; 00764 00765 if (DeviceInfoData) 00766 { 00767 struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 00768 if (!(devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)) 00769 pDriverListHead = &devInfo->DriverListHead; 00770 } 00771 00772 if (DriverType == SPDIT_COMPATDRIVER) 00773 { 00774 /* Get hardware and compatible IDs lists */ 00775 Result = GetHardwareAndCompatibleIDsLists( 00776 DeviceInfoSet, 00777 DeviceInfoData, 00778 &HardwareIDs, 00779 NULL, 00780 &CompatibleIDs, 00781 NULL); 00782 if (!Result) 00783 goto done; 00784 if (!HardwareIDs && !CompatibleIDs) 00785 { 00786 SetLastError(ERROR_FILE_NOT_FOUND); 00787 goto done; 00788 } 00789 } 00790 00791 if (InstallParams.FlagsEx & DI_FLAGSEX_INSTALLEDDRIVER) 00792 { 00793 HKEY hDriverKey; 00794 WCHAR InfFileName[MAX_PATH]; 00795 WCHAR InfFileSection[MAX_PATH]; 00796 ULONG RequiredSize; 00797 struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 00798 struct InfFileDetails *infFileDetails = NULL; 00799 FILETIME DriverDate; 00800 LONG rc; 00801 DWORD len; 00802 00803 /* Prepend inf directory name to file name */ 00804 len = sizeof(InfFileName) / sizeof(InfFileName[0]); 00805 RequiredSize = GetSystemWindowsDirectoryW(InfFileName, len); 00806 if (RequiredSize == 0 || RequiredSize >= len) 00807 goto done; 00808 if (*InfFileName && InfFileName[strlenW(InfFileName) - 1] != '\\') 00809 strcatW(InfFileName, BackSlash); 00810 strcatW(InfFileName, InfDirectory); 00811 00812 /* Read some information from registry, before creating the driver structure */ 00813 hDriverKey = SetupDiOpenDevRegKey( 00814 DeviceInfoSet, 00815 DeviceInfoData, 00816 DICS_FLAG_GLOBAL, 00817 0, 00818 DIREG_DRV, 00819 KEY_QUERY_VALUE); 00820 if (hDriverKey == INVALID_HANDLE_VALUE) 00821 goto done; 00822 RequiredSize = (len - strlenW(InfFileName)) * sizeof(WCHAR); 00823 rc = RegGetValueW( 00824 hDriverKey, 00825 NULL, 00826 REGSTR_VAL_INFPATH, 00827 RRF_RT_REG_SZ, 00828 NULL, 00829 &InfFileName[strlenW(InfFileName)], 00830 &RequiredSize); 00831 if (rc != ERROR_SUCCESS) 00832 { 00833 SetLastError(rc); 00834 CloseHandle(hDriverKey); 00835 goto done; 00836 } 00837 RequiredSize = sizeof(InfFileSection); 00838 rc = RegGetValueW( 00839 hDriverKey, 00840 NULL, 00841 REGSTR_VAL_INFSECTION, 00842 RRF_RT_REG_SZ, 00843 NULL, 00844 InfFileSection, 00845 &RequiredSize); 00846 if (rc != ERROR_SUCCESS) 00847 { 00848 SetLastError(rc); 00849 CloseHandle(hDriverKey); 00850 goto done; 00851 } 00852 TRACE("Current driver in %s/%s\n", debugstr_w(InfFileName), debugstr_w(InfFileSection)); 00853 infFileDetails = CreateInfFileDetails(InfFileName); 00854 if (!infFileDetails) 00855 { 00856 CloseHandle(hDriverKey); 00857 goto done; 00858 } 00859 DriverDate.dwLowDateTime = DriverDate.dwHighDateTime = 0; /* FIXME */ 00860 CloseHandle(hDriverKey); 00861 ret = AddKnownDriverToList( 00862 pDriverListHead, 00863 SPDIT_COMPATDRIVER, 00864 &devInfo->ClassGuid, 00865 infFileDetails, 00866 InfFileName, 00867 InfFileSection, /* Yes, we don't care of section extension */ 00868 L"DriverDescription", /* FIXME */ 00869 L"ProviderName", /* FIXME */ 00870 L"ManufacturerName", /* FIXME */ 00871 L"MatchingId", /* FIXME */ 00872 DriverDate, 00873 0, /* FIXME: DriverVersion */ 00874 0); 00875 if (!ret) 00876 DereferenceInfFile(infFileDetails); 00877 Result = FALSE; 00878 } 00879 else if (InstallParams.Flags & DI_ENUMSINGLEINF) 00880 { 00881 /* InstallParams.DriverPath contains the name of a .inf file */ 00882 RequiredSize = strlenW(InstallParams.DriverPath) + 2; 00883 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 00884 if (!Buffer) 00885 { 00886 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00887 goto done; 00888 } 00889 strcpyW(Buffer, InstallParams.DriverPath); 00890 ((LPWSTR)Buffer)[RequiredSize - 1] = 0; 00891 Result = TRUE; 00892 } 00893 else 00894 { 00895 /* Enumerate .inf files */ 00896 Result = FALSE; 00897 RequiredSize = 32768; /* Initial buffer size */ 00898 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00899 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 00900 { 00901 HeapFree(GetProcessHeap(), 0, Buffer); 00902 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 00903 if (!Buffer) 00904 { 00905 Result = FALSE; 00906 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00907 break; 00908 } 00909 Result = SetupGetInfFileListW( 00910 *InstallParams.DriverPath ? InstallParams.DriverPath : NULL, 00911 INF_STYLE_WIN4, 00912 Buffer, RequiredSize, 00913 &RequiredSize); 00914 } 00915 if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND) 00916 { 00917 /* No .inf file in specified directory. So, we should 00918 * success as we created an empty driver info list. 00919 */ 00920 ret = TRUE; 00921 goto done; 00922 } 00923 } 00924 if (Result) 00925 { 00926 LPCWSTR filename; 00927 LPWSTR pFullFilename; 00928 00929 if (InstallParams.Flags & DI_ENUMSINGLEINF) 00930 { 00931 /* Only a filename */ 00932 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); 00933 if (!FullInfFileName) 00934 goto done; 00935 pFullFilename = &FullInfFileName[0]; 00936 } 00937 else if (*InstallParams.DriverPath) 00938 { 00939 /* Directory name specified */ 00940 DWORD len; 00941 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL); 00942 if (len == 0) 00943 goto done; 00944 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + MAX_PATH) * sizeof(WCHAR)); 00945 if (!FullInfFileName) 00946 goto done; 00947 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL); 00948 if (len == 0) 00949 goto done; 00950 if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\') 00951 strcatW(FullInfFileName, BackSlash); 00952 pFullFilename = &FullInfFileName[strlenW(FullInfFileName)]; 00953 } 00954 else 00955 { 00956 /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */ 00957 DWORD len; 00958 len = GetSystemWindowsDirectoryW(NULL, 0); 00959 if (len == 0) 00960 goto done; 00961 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + strlenW(InfDirectory) + MAX_PATH) * sizeof(WCHAR)); 00962 if (!FullInfFileName) 00963 goto done; 00964 len = GetSystemWindowsDirectoryW(FullInfFileName, len); 00965 if (len == 0) 00966 goto done; 00967 if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\') 00968 strcatW(FullInfFileName, BackSlash); 00969 strcatW(FullInfFileName, InfDirectory); 00970 pFullFilename = &FullInfFileName[strlenW(FullInfFileName)]; 00971 } 00972 00973 for (filename = (LPCWSTR)Buffer; *filename; filename += strlenW(filename) + 1) 00974 { 00975 INFCONTEXT ContextManufacturer, ContextDevice; 00976 GUID ClassGuid; 00977 00978 strcpyW(pFullFilename, filename); 00979 TRACE("Opening file %s\n", debugstr_w(FullInfFileName)); 00980 00981 currentInfFileDetails = CreateInfFileDetails(FullInfFileName); 00982 if (!currentInfFileDetails) 00983 continue; 00984 00985 if (!GetVersionInformationFromInfFile( 00986 currentInfFileDetails->hInf, 00987 &ClassGuid, 00988 &ProviderName, 00989 &DriverDate, 00990 &DriverVersion)) 00991 { 00992 DereferenceInfFile(currentInfFileDetails); 00993 currentInfFileDetails = NULL; 00994 continue; 00995 } 00996 00997 if (DriverType == SPDIT_CLASSDRIVER) 00998 { 00999 /* Check if the ClassGuid in this .inf file is corresponding with our needs */ 01000 if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid)) 01001 { 01002 goto next; 01003 } 01004 } 01005 01006 if (InstallParams.FlagsEx & DI_FLAGSEX_ALLOWEXCLUDEDDRVS) 01007 { 01008 /* Read ExcludeFromSelect control flags */ 01009 /* FIXME */ 01010 } 01011 else 01012 FIXME("ExcludeFromSelect list ignored\n"); 01013 01014 /* Get the manufacturers list */ 01015 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, INF_MANUFACTURER, NULL, &ContextManufacturer); 01016 while (Result) 01017 { 01018 Result = SetupGetStringFieldW( 01019 &ContextManufacturer, 01020 0, /* Field index */ 01021 NULL, 0, 01022 &RequiredSize); 01023 if (Result) 01024 { 01025 /* We got the needed size for the buffer */ 01026 ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 01027 if (!ManufacturerName) 01028 { 01029 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01030 goto done; 01031 } 01032 Result = SetupGetStringFieldW( 01033 &ContextManufacturer, 01034 0, /* Field index */ 01035 ManufacturerName, RequiredSize, 01036 &RequiredSize); 01037 } 01038 /* Get manufacturer section name */ 01039 Result = SetupGetStringFieldW( 01040 &ContextManufacturer, 01041 1, /* Field index */ 01042 ManufacturerSection, LINE_LEN, 01043 &RequiredSize); 01044 if (Result) 01045 { 01046 ManufacturerSection[RequiredSize] = 0; /* Final NULL char */ 01047 /* Add (possible) extension to manufacturer section name */ 01048 Result = SetupDiGetActualSectionToInstallW( 01049 currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL); 01050 if (Result) 01051 { 01052 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection)); 01053 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice); 01054 } 01055 } 01056 while (Result) 01057 { 01058 if (DriverType == SPDIT_CLASSDRIVER) 01059 { 01060 /* FIXME: Check ExcludeFromSelect list */ 01061 if (!AddDriverToList( 01062 pDriverListHead, 01063 DriverType, 01064 &ClassGuid, 01065 ContextDevice, 01066 currentInfFileDetails, 01067 FullInfFileName, 01068 ProviderName, 01069 ManufacturerName, 01070 NULL, 01071 DriverDate, DriverVersion, 01072 0)) 01073 { 01074 break; 01075 } 01076 } 01077 else /* DriverType = SPDIT_COMPATDRIVER */ 01078 { 01079 /* 1. Get all fields */ 01080 DWORD FieldCount = SetupGetFieldCount(&ContextDevice); 01081 DWORD DriverRank; 01082 DWORD i; 01083 LPCWSTR currentId; 01084 BOOL DriverAlreadyAdded; 01085 01086 for (i = 2; i <= FieldCount; i++) 01087 { 01088 LPWSTR DeviceId = NULL; 01089 Result = FALSE; 01090 RequiredSize = 128; /* Initial buffer size */ 01091 SetLastError(ERROR_INSUFFICIENT_BUFFER); 01092 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 01093 { 01094 HeapFree(GetProcessHeap(), 0, DeviceId); 01095 DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR)); 01096 if (!DeviceId) 01097 { 01098 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01099 goto done; 01100 } 01101 Result = SetupGetStringFieldW( 01102 &ContextDevice, 01103 i, 01104 DeviceId, RequiredSize, 01105 &RequiredSize); 01106 } 01107 if (!Result) 01108 { 01109 HeapFree(GetProcessHeap(), 0, DeviceId); 01110 goto done; 01111 } 01112 /* FIXME: Check ExcludeFromSelect list */ 01113 DriverAlreadyAdded = FALSE; 01114 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++) 01115 { 01116 if (strcmpiW(DeviceId, currentId) == 0) 01117 { 01118 AddDriverToList( 01119 pDriverListHead, 01120 DriverType, 01121 &ClassGuid, 01122 ContextDevice, 01123 currentInfFileDetails, 01124 FullInfFileName, 01125 ProviderName, 01126 ManufacturerName, 01127 currentId, 01128 DriverDate, DriverVersion, 01129 DriverRank + (i == 2 ? 0 : 0x1000 + i - 3)); 01130 DriverAlreadyAdded = TRUE; 01131 } 01132 } 01133 if (CompatibleIDs) 01134 { 01135 for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++) 01136 { 01137 if (strcmpiW(DeviceId, currentId) == 0) 01138 { 01139 AddDriverToList( 01140 pDriverListHead, 01141 DriverType, 01142 &ClassGuid, 01143 ContextDevice, 01144 currentInfFileDetails, 01145 FullInfFileName, 01146 ProviderName, 01147 ManufacturerName, 01148 currentId, 01149 DriverDate, DriverVersion, 01150 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3)); 01151 DriverAlreadyAdded = TRUE; 01152 } 01153 } 01154 } 01155 HeapFree(GetProcessHeap(), 0, DeviceId); 01156 } 01157 } 01158 Result = SetupFindNextLine(&ContextDevice, &ContextDevice); 01159 } 01160 01161 HeapFree(GetProcessHeap(), 0, ManufacturerName); 01162 ManufacturerName = NULL; 01163 Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer); 01164 } 01165 01166 ret = TRUE; 01167 next: 01168 HeapFree(GetProcessHeap(), 0, ProviderName); 01169 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect); 01170 ProviderName = ExcludeFromSelect = NULL; 01171 01172 DereferenceInfFile(currentInfFileDetails); 01173 currentInfFileDetails = NULL; 01174 } 01175 ret = TRUE; 01176 } 01177 } 01178 01179 done: 01180 if (ret) 01181 { 01182 if (DeviceInfoData) 01183 { 01184 InstallParams.Flags |= DI_DIDCOMPAT; 01185 InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO; 01186 } 01187 else 01188 { 01189 InstallParams.Flags |= DI_DIDCLASS; 01190 InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST; 01191 } 01192 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 01193 } 01194 01195 HeapFree(GetProcessHeap(), 0, ProviderName); 01196 HeapFree(GetProcessHeap(), 0, ManufacturerName); 01197 MyFree(HardwareIDs); 01198 MyFree(CompatibleIDs); 01199 HeapFree(GetProcessHeap(), 0, FullInfFileName); 01200 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect); 01201 if (currentInfFileDetails) 01202 DereferenceInfFile(currentInfFileDetails); 01203 HeapFree(GetProcessHeap(), 0, Buffer); 01204 01205 TRACE("Returning %d\n", ret); 01206 return ret; 01207 } 01208 01209 /*********************************************************************** 01210 * SetupDiDestroyDriverInfoList (SETUPAPI.@) 01211 */ 01212 BOOL WINAPI 01213 SetupDiDestroyDriverInfoList( 01214 IN HDEVINFO DeviceInfoSet, 01215 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 01216 IN DWORD DriverType) 01217 { 01218 struct DeviceInfoSet *list; 01219 BOOL ret = FALSE; 01220 01221 TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType); 01222 01223 if (!DeviceInfoSet) 01224 SetLastError(ERROR_INVALID_HANDLE); 01225 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 01226 SetLastError(ERROR_INVALID_HANDLE); 01227 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER) 01228 SetLastError(ERROR_INVALID_PARAMETER); 01229 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData) 01230 SetLastError(ERROR_INVALID_PARAMETER); 01231 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 01232 SetLastError(ERROR_INVALID_USER_BUFFER); 01233 else 01234 { 01235 PLIST_ENTRY ListEntry; 01236 struct DriverInfoElement *driverInfo; 01237 SP_DEVINSTALL_PARAMS_W InstallParams; 01238 01239 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 01240 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) 01241 goto done; 01242 01243 if (!DeviceInfoData) 01244 /* Fall back to destroying class driver list */ 01245 DriverType = SPDIT_CLASSDRIVER; 01246 01247 if (DriverType == SPDIT_CLASSDRIVER) 01248 { 01249 while (!IsListEmpty(&list->DriverListHead)) 01250 { 01251 ListEntry = RemoveHeadList(&list->DriverListHead); 01252 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); 01253 DestroyDriverInfoElement(driverInfo); 01254 } 01255 InstallParams.Reserved = 0; 01256 InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS); 01257 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST; 01258 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams); 01259 } 01260 else 01261 { 01262 SP_DEVINSTALL_PARAMS_W InstallParamsSet; 01263 struct DeviceInfo *deviceInfo; 01264 01265 InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 01266 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet)) 01267 goto done; 01268 deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 01269 while (!IsListEmpty(&deviceInfo->DriverListHead)) 01270 { 01271 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead); 01272 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); 01273 if ((PVOID)InstallParamsSet.Reserved == driverInfo) 01274 { 01275 InstallParamsSet.Reserved = 0; 01276 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet); 01277 } 01278 DestroyDriverInfoElement(driverInfo); 01279 } 01280 InstallParams.Reserved = 0; 01281 InstallParams.Flags &= ~DI_DIDCOMPAT; 01282 InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO; 01283 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 01284 } 01285 } 01286 01287 done: 01288 TRACE("Returning %d\n", ret); 01289 return ret; 01290 } 01291 01292 /*********************************************************************** 01293 * SetupDiEnumDriverInfoA (SETUPAPI.@) 01294 */ 01295 BOOL WINAPI 01296 SetupDiEnumDriverInfoA( 01297 IN HDEVINFO DeviceInfoSet, 01298 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 01299 IN DWORD DriverType, 01300 IN DWORD MemberIndex, 01301 OUT PSP_DRVINFO_DATA_A DriverInfoData) 01302 { 01303 SP_DRVINFO_DATA_V2_W driverInfoData2W; 01304 BOOL ret = FALSE; 01305 01306 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData, 01307 DriverType, MemberIndex, DriverInfoData); 01308 01309 if (DriverInfoData == NULL) 01310 SetLastError(ERROR_INVALID_PARAMETER); 01311 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A)) 01312 SetLastError(ERROR_INVALID_USER_BUFFER); 01313 else 01314 { 01315 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); 01316 ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData, 01317 DriverType, MemberIndex, &driverInfoData2W); 01318 01319 if (ret) 01320 { 01321 /* Do W->A conversion */ 01322 DriverInfoData->DriverType = driverInfoData2W.DriverType; 01323 DriverInfoData->Reserved = driverInfoData2W.Reserved; 01324 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1, 01325 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0) 01326 { 01327 DriverInfoData->Description[0] = '\0'; 01328 ret = FALSE; 01329 } 01330 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1, 01331 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0) 01332 { 01333 DriverInfoData->MfgName[0] = '\0'; 01334 ret = FALSE; 01335 } 01336 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1, 01337 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0) 01338 { 01339 DriverInfoData->ProviderName[0] = '\0'; 01340 ret = FALSE; 01341 } 01342 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A)) 01343 { 01344 /* Copy more fields */ 01345 DriverInfoData->DriverDate = driverInfoData2W.DriverDate; 01346 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion; 01347 } 01348 } 01349 } 01350 01351 TRACE("Returning %d\n", ret); 01352 return ret; 01353 } 01354 01355 01356 /*********************************************************************** 01357 * SetupDiEnumDriverInfoW (SETUPAPI.@) 01358 */ 01359 BOOL WINAPI 01360 SetupDiEnumDriverInfoW( 01361 IN HDEVINFO DeviceInfoSet, 01362 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 01363 IN DWORD DriverType, 01364 IN DWORD MemberIndex, 01365 OUT PSP_DRVINFO_DATA_W DriverInfoData) 01366 { 01367 PLIST_ENTRY ListHead; 01368 BOOL ret = FALSE; 01369 01370 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData, 01371 DriverType, MemberIndex, DriverInfoData); 01372 01373 if (!DeviceInfoSet || !DriverInfoData) 01374 SetLastError(ERROR_INVALID_PARAMETER); 01375 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 01376 SetLastError(ERROR_INVALID_HANDLE); 01377 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 01378 SetLastError(ERROR_INVALID_HANDLE); 01379 else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER) 01380 SetLastError(ERROR_INVALID_PARAMETER); 01381 else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData) 01382 SetLastError(ERROR_INVALID_PARAMETER); 01383 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W)) 01384 SetLastError(ERROR_INVALID_USER_BUFFER); 01385 else 01386 { 01387 struct DeviceInfo *devInfo = NULL; 01388 PLIST_ENTRY ItemList; 01389 if (DeviceInfoData) 01390 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 01391 if (!devInfo || (devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS)) 01392 { 01393 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead; 01394 } 01395 else 01396 { 01397 ListHead = &devInfo->DriverListHead; 01398 } 01399 01400 ItemList = ListHead->Flink; 01401 while (ItemList != ListHead && MemberIndex-- > 0) 01402 ItemList = ItemList->Flink; 01403 if (ItemList == ListHead) 01404 SetLastError(ERROR_NO_MORE_ITEMS); 01405 else 01406 { 01407 struct DriverInfoElement *DrvInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); 01408 01409 memcpy( 01410 &DriverInfoData->DriverType, 01411 &DrvInfo->Info.DriverType, 01412 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType)); 01413 ret = TRUE; 01414 } 01415 } 01416 01417 TRACE("Returning %d\n", ret); 01418 return ret; 01419 } 01420 01421 /*********************************************************************** 01422 * SetupDiGetSelectedDriverA (SETUPAPI.@) 01423 */ 01424 BOOL WINAPI 01425 SetupDiGetSelectedDriverA( 01426 IN HDEVINFO DeviceInfoSet, 01427 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 01428 OUT PSP_DRVINFO_DATA_A DriverInfoData) 01429 { 01430 SP_DRVINFO_DATA_V2_W driverInfoData2W; 01431 BOOL ret = FALSE; 01432 01433 if (DriverInfoData == NULL) 01434 SetLastError(ERROR_INVALID_PARAMETER); 01435 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A)) 01436 SetLastError(ERROR_INVALID_USER_BUFFER); 01437 else 01438 { 01439 driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); 01440 01441 ret = SetupDiGetSelectedDriverW(DeviceInfoSet, 01442 DeviceInfoData, 01443 &driverInfoData2W); 01444 01445 if (ret) 01446 { 01447 /* Do W->A conversion */ 01448 DriverInfoData->DriverType = driverInfoData2W.DriverType; 01449 DriverInfoData->Reserved = driverInfoData2W.Reserved; 01450 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1, 01451 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0) 01452 { 01453 DriverInfoData->Description[0] = '\0'; 01454 ret = FALSE; 01455 } 01456 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1, 01457 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0) 01458 { 01459 DriverInfoData->MfgName[0] = '\0'; 01460 ret = FALSE; 01461 } 01462 if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1, 01463 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0) 01464 { 01465 DriverInfoData->ProviderName[0] = '\0'; 01466 ret = FALSE; 01467 } 01468 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A)) 01469 { 01470 /* Copy more fields */ 01471 DriverInfoData->DriverDate = driverInfoData2W.DriverDate; 01472 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion; 01473 } 01474 } 01475 } 01476 01477 return ret; 01478 } 01479 01480 /*********************************************************************** 01481 * SetupDiGetSelectedDriverW (SETUPAPI.@) 01482 */ 01483 BOOL WINAPI 01484 SetupDiGetSelectedDriverW( 01485 IN HDEVINFO DeviceInfoSet, 01486 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 01487 OUT PSP_DRVINFO_DATA_W DriverInfoData) 01488 { 01489 BOOL ret = FALSE; 01490 01491 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData); 01492 01493 if (!DeviceInfoSet || !DriverInfoData) 01494 SetLastError(ERROR_INVALID_PARAMETER); 01495 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 01496 SetLastError(ERROR_INVALID_HANDLE); 01497 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 01498 SetLastError(ERROR_INVALID_HANDLE); 01499 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 01500 SetLastError(ERROR_INVALID_USER_BUFFER); 01501 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W)) 01502 SetLastError(ERROR_INVALID_USER_BUFFER); 01503 else 01504 { 01505 SP_DEVINSTALL_PARAMS InstallParams; 01506 01507 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 01508 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) 01509 { 01510 struct DriverInfoElement *driverInfo; 01511 driverInfo = (struct DriverInfoElement *)InstallParams.Reserved; 01512 if (driverInfo == NULL) 01513 SetLastError(ERROR_NO_DRIVER_SELECTED); 01514 else 01515 { 01516 memcpy( 01517 &DriverInfoData->DriverType, 01518 &driverInfo->Info.DriverType, 01519 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType)); 01520 ret = TRUE; 01521 } 01522 } 01523 } 01524 01525 TRACE("Returning %d\n", ret); 01526 return ret; 01527 } 01528 01529 /*********************************************************************** 01530 * SetupDiSetSelectedDriverA (SETUPAPI.@) 01531 */ 01532 BOOL WINAPI 01533 SetupDiSetSelectedDriverA( 01534 IN HDEVINFO DeviceInfoSet, 01535 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 01536 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL) 01537 { 01538 SP_DRVINFO_DATA_V1_W DriverInfoDataW; 01539 PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL; 01540 BOOL ret = FALSE; 01541 01542 if (DriverInfoData != NULL) 01543 { 01544 if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) && 01545 DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A)) 01546 { 01547 SetLastError(ERROR_INVALID_PARAMETER); 01548 return FALSE; 01549 } 01550 01551 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W); 01552 DriverInfoDataW.Reserved = DriverInfoData->Reserved; 01553 01554 if (DriverInfoDataW.Reserved == 0) 01555 { 01556 DriverInfoDataW.DriverType = DriverInfoData->DriverType; 01557 01558 /* convert the strings to unicode */ 01559 if (!MultiByteToWideChar(CP_ACP, 01560 0, 01561 DriverInfoData->Description, 01562 LINE_LEN, 01563 DriverInfoDataW.Description, 01564 LINE_LEN) || 01565 !MultiByteToWideChar(CP_ACP, 01566 0, 01567 DriverInfoData->ProviderName, 01568 LINE_LEN, 01569 DriverInfoDataW.ProviderName, 01570 LINE_LEN)) 01571 { 01572 return FALSE; 01573 } 01574 } 01575 01576 pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW; 01577 } 01578 01579 ret = SetupDiSetSelectedDriverW(DeviceInfoSet, 01580 DeviceInfoData, 01581 pDriverInfoDataW); 01582 01583 if (ret && pDriverInfoDataW != NULL) 01584 { 01585 DriverInfoData->Reserved = DriverInfoDataW.Reserved; 01586 } 01587 01588 return ret; 01589 } 01590 01591 /*********************************************************************** 01592 * SetupDiSetSelectedDriverW (SETUPAPI.@) 01593 */ 01594 BOOL WINAPI 01595 SetupDiSetSelectedDriverW( 01596 IN HDEVINFO DeviceInfoSet, 01597 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 01598 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL) 01599 { 01600 BOOL ret = FALSE; 01601 01602 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData); 01603 01604 if (!DeviceInfoSet) 01605 SetLastError(ERROR_INVALID_PARAMETER); 01606 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 01607 SetLastError(ERROR_INVALID_HANDLE); 01608 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 01609 SetLastError(ERROR_INVALID_HANDLE); 01610 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 01611 SetLastError(ERROR_INVALID_USER_BUFFER); 01612 else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W)) 01613 SetLastError(ERROR_INVALID_USER_BUFFER); 01614 else 01615 { 01616 struct DriverInfoElement **pDriverInfo; 01617 PLIST_ENTRY ListHead, ItemList; 01618 01619 if (DeviceInfoData) 01620 { 01621 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams.Reserved; 01622 ListHead = &((struct DeviceInfo *)DeviceInfoData->Reserved)->DriverListHead; 01623 } 01624 else 01625 { 01626 pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved; 01627 ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead; 01628 } 01629 01630 if (!DriverInfoData) 01631 { 01632 *pDriverInfo = NULL; 01633 ret = TRUE; 01634 } 01635 else 01636 { 01637 /* Search selected driver in list */ 01638 ItemList = ListHead->Flink; 01639 while (ItemList != ListHead) 01640 { 01641 if (DriverInfoData->Reserved != 0) 01642 { 01643 if (DriverInfoData->Reserved == (ULONG_PTR)ItemList) 01644 break; 01645 } 01646 else 01647 { 01648 /* The caller wants to compare only DriverType, Description and ProviderName fields */ 01649 struct DriverInfoElement *driverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); 01650 if (driverInfo->Info.DriverType == DriverInfoData->DriverType 01651 && strcmpW(driverInfo->Info.Description, DriverInfoData->Description) == 0 01652 && strcmpW(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0) 01653 { 01654 break; 01655 } 01656 } 01657 ItemList = ItemList->Flink; 01658 } 01659 if (ItemList == ListHead) 01660 SetLastError(ERROR_INVALID_PARAMETER); 01661 else 01662 { 01663 *pDriverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry); 01664 DriverInfoData->Reserved = (ULONG_PTR)ItemList; 01665 ret = TRUE; 01666 TRACE("Choosing driver whose rank is 0x%lx\n", 01667 (*pDriverInfo)->Params.Rank); 01668 if (DeviceInfoData) 01669 memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID)); 01670 } 01671 } 01672 } 01673 01674 TRACE("Returning %d\n", ret); 01675 return ret; 01676 } 01677 01678 /*********************************************************************** 01679 * SetupDiGetDriverInfoDetailA (SETUPAPI.@) 01680 */ 01681 BOOL WINAPI 01682 SetupDiGetDriverInfoDetailA( 01683 IN HDEVINFO DeviceInfoSet, 01684 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 01685 IN PSP_DRVINFO_DATA_A DriverInfoData, 01686 IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL, 01687 IN DWORD DriverInfoDetailDataSize, 01688 OUT PDWORD RequiredSize OPTIONAL) 01689 { 01690 SP_DRVINFO_DATA_V2_W DriverInfoDataW; 01691 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL; 01692 DWORD BufSize = 0; 01693 DWORD HardwareIDLen = 0; 01694 BOOL ret = FALSE; 01695 01696 /* do some sanity checks, the unicode version might do more thorough checks */ 01697 if (DriverInfoData == NULL || 01698 (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) || 01699 (DriverInfoDetailData != NULL && 01700 (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) || 01701 DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A)))) 01702 { 01703 SetLastError(ERROR_INVALID_PARAMETER); 01704 goto Cleanup; 01705 } 01706 01707 /* make sure we support both versions of the SP_DRVINFO_DATA structure */ 01708 if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A)) 01709 { 01710 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W); 01711 } 01712 else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A)) 01713 { 01714 DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); 01715 } 01716 else 01717 { 01718 SetLastError(ERROR_INVALID_PARAMETER); 01719 goto Cleanup; 01720 } 01721 DriverInfoDataW.DriverType = DriverInfoData->DriverType; 01722 DriverInfoDataW.Reserved = DriverInfoData->Reserved; 01723 01724 /* convert the strings to unicode */ 01725 if (MultiByteToWideChar(CP_ACP, 01726 0, 01727 DriverInfoData->Description, 01728 LINE_LEN, 01729 DriverInfoDataW.Description, 01730 LINE_LEN) && 01731 MultiByteToWideChar(CP_ACP, 01732 0, 01733 DriverInfoData->MfgName, 01734 LINE_LEN, 01735 DriverInfoDataW.MfgName, 01736 LINE_LEN) && 01737 MultiByteToWideChar(CP_ACP, 01738 0, 01739 DriverInfoData->ProviderName, 01740 LINE_LEN, 01741 DriverInfoDataW.ProviderName, 01742 LINE_LEN)) 01743 { 01744 if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W)) 01745 { 01746 DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate; 01747 DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion; 01748 } 01749 01750 if (DriverInfoDetailData != NULL) 01751 { 01752 /* calculate the unicode buffer size from the ansi buffer size */ 01753 HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID); 01754 BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) + 01755 (HardwareIDLen * sizeof(WCHAR)); 01756 01757 DriverInfoDetailDataW = MyMalloc(BufSize); 01758 if (DriverInfoDetailDataW == NULL) 01759 { 01760 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01761 goto Cleanup; 01762 } 01763 01764 /* initialize the buffer */ 01765 ZeroMemory(DriverInfoDetailDataW, 01766 BufSize); 01767 DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); 01768 } 01769 01770 /* call the unicode version */ 01771 ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet, 01772 DeviceInfoData, 01773 &DriverInfoDataW, 01774 DriverInfoDetailDataW, 01775 BufSize, 01776 RequiredSize); 01777 01778 if (ret) 01779 { 01780 if (DriverInfoDetailDataW != NULL) 01781 { 01782 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */ 01783 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A); 01784 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate; 01785 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved; 01786 if (WideCharToMultiByte(CP_ACP, 01787 0, 01788 DriverInfoDetailDataW->SectionName, 01789 LINE_LEN, 01790 DriverInfoDetailData->SectionName, 01791 LINE_LEN, 01792 NULL, 01793 NULL) && 01794 WideCharToMultiByte(CP_ACP, 01795 0, 01796 DriverInfoDetailDataW->InfFileName, 01797 MAX_PATH, 01798 DriverInfoDetailData->InfFileName, 01799 MAX_PATH, 01800 NULL, 01801 NULL) && 01802 WideCharToMultiByte(CP_ACP, 01803 0, 01804 DriverInfoDetailDataW->DrvDescription, 01805 LINE_LEN, 01806 DriverInfoDetailData->DrvDescription, 01807 LINE_LEN, 01808 NULL, 01809 NULL) && 01810 WideCharToMultiByte(CP_ACP, 01811 0, 01812 DriverInfoDetailDataW->HardwareID, 01813 HardwareIDLen, 01814 DriverInfoDetailData->HardwareID, 01815 HardwareIDLen, 01816 NULL, 01817 NULL)) 01818 { 01819 DWORD len, cnt = 0; 01820 DWORD hwidlen = HardwareIDLen; 01821 CHAR *s = DriverInfoDetailData->HardwareID; 01822 01823 /* count the strings in the list */ 01824 while (*s != '\0') 01825 { 01826 len = lstrlenA(s) + 1; 01827 if (hwidlen > len) 01828 { 01829 cnt++; 01830 s += len; 01831 hwidlen -= len; 01832 } 01833 else 01834 { 01835 /* looks like the string list wasn't terminated... */ 01836 SetLastError(ERROR_INVALID_USER_BUFFER); 01837 ret = FALSE; 01838 break; 01839 } 01840 } 01841 01842 /* make sure CompatIDsOffset points to the second string in the 01843 list, if present */ 01844 if (cnt > 1) 01845 { 01846 DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1; 01847 DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) - 01848 DriverInfoDetailData->CompatIDsOffset + 1; 01849 } 01850 else 01851 { 01852 DriverInfoDetailData->CompatIDsOffset = 0; 01853 DriverInfoDetailData->CompatIDsLength = 0; 01854 } 01855 } 01856 else 01857 { 01858 ret = FALSE; 01859 } 01860 } 01861 01862 if (RequiredSize != NULL) 01863 { 01864 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + 01865 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR)); 01866 } 01867 } 01868 } 01869 01870 Cleanup: 01871 if (DriverInfoDetailDataW != NULL) 01872 { 01873 MyFree(DriverInfoDetailDataW); 01874 } 01875 01876 return ret; 01877 } 01878 01879 /*********************************************************************** 01880 * SetupDiGetDriverInfoDetailW (SETUPAPI.@) 01881 */ 01882 BOOL WINAPI 01883 SetupDiGetDriverInfoDetailW( 01884 IN HDEVINFO DeviceInfoSet, 01885 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 01886 IN PSP_DRVINFO_DATA_W DriverInfoData, 01887 IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL, 01888 IN DWORD DriverInfoDetailDataSize, 01889 OUT PDWORD RequiredSize OPTIONAL) 01890 { 01891 BOOL ret = FALSE; 01892 01893 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData, 01894 DriverInfoData, DriverInfoDetailData, 01895 DriverInfoDetailDataSize, RequiredSize); 01896 01897 if (!DeviceInfoSet) 01898 SetLastError(ERROR_INVALID_PARAMETER); 01899 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 01900 SetLastError(ERROR_INVALID_HANDLE); 01901 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 01902 SetLastError(ERROR_INVALID_HANDLE); 01903 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 01904 SetLastError(ERROR_INVALID_USER_BUFFER); 01905 else if (!DriverInfoData) 01906 SetLastError(ERROR_INVALID_PARAMETER); 01907 else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0) 01908 SetLastError(ERROR_INVALID_PARAMETER); 01909 else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W)) 01910 SetLastError(ERROR_INVALID_PARAMETER); 01911 else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W)) 01912 SetLastError(ERROR_INVALID_USER_BUFFER); 01913 else if (DriverInfoData->Reserved == 0) 01914 SetLastError(ERROR_NO_DRIVER_SELECTED); 01915 else 01916 { 01917 struct DriverInfoElement *driverInfoElement; 01918 LPWSTR HardwareIDs = NULL; 01919 LPWSTR CompatibleIDs = NULL; 01920 LPWSTR pBuffer = NULL; 01921 LPCWSTR DeviceID = NULL; 01922 ULONG HardwareIDsSize, CompatibleIDsSize; 01923 ULONG sizeNeeded, sizeLeft, size; 01924 BOOL Result; 01925 01926 driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved; 01927 01928 /* Get hardware and compatible IDs lists */ 01929 Result = GetHardwareAndCompatibleIDsLists( 01930 DeviceInfoSet, 01931 DeviceInfoData, 01932 &HardwareIDs, &HardwareIDsSize, 01933 &CompatibleIDs, &CompatibleIDsSize); 01934 if (!Result) 01935 goto done; 01936 01937 sizeNeeded = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) 01938 + HardwareIDsSize + CompatibleIDsSize; 01939 if (RequiredSize) 01940 *RequiredSize = sizeNeeded; 01941 01942 if (!DriverInfoDetailData) 01943 { 01944 ret = TRUE; 01945 goto done; 01946 } 01947 01948 memcpy( 01949 DriverInfoDetailData, 01950 &driverInfoElement->Details, 01951 driverInfoElement->Details.cbSize); 01952 DriverInfoDetailData->CompatIDsOffset = 0; 01953 DriverInfoDetailData->CompatIDsLength = 0; 01954 01955 sizeLeft = (DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR); 01956 pBuffer = DriverInfoDetailData->HardwareID; 01957 /* Add as many as possible HardwareIDs in the list */ 01958 DeviceID = HardwareIDs; 01959 while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft) 01960 { 01961 TRACE("Adding %s to list\n", debugstr_w(DeviceID)); 01962 wcscpy(pBuffer, DeviceID); 01963 DeviceID += size + 1; 01964 pBuffer += size + 1; 01965 sizeLeft -= size + 1; 01966 DriverInfoDetailData->CompatIDsOffset += size + 1; 01967 } 01968 if (sizeLeft > 0) 01969 { 01970 *pBuffer = UNICODE_NULL; 01971 sizeLeft--; 01972 DriverInfoDetailData->CompatIDsOffset++; 01973 } 01974 /* Add as many as possible CompatibleIDs in the list */ 01975 DeviceID = CompatibleIDs; 01976 while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft) 01977 { 01978 TRACE("Adding %s to list\n", debugstr_w(DeviceID)); 01979 wcscpy(pBuffer, DeviceID); 01980 DeviceID += size + 1; 01981 pBuffer += size + 1; 01982 sizeLeft -= size + 1; 01983 DriverInfoDetailData->CompatIDsLength += size + 1; 01984 } 01985 if (sizeLeft > 0) 01986 { 01987 *pBuffer = UNICODE_NULL; 01988 sizeLeft--; 01989 DriverInfoDetailData->CompatIDsLength++; 01990 } 01991 01992 if (sizeNeeded > DriverInfoDetailDataSize) 01993 SetLastError(ERROR_INSUFFICIENT_BUFFER); 01994 else 01995 ret = TRUE; 01996 01997 done: 01998 MyFree(HardwareIDs); 01999 MyFree(CompatibleIDs); 02000 } 02001 02002 TRACE("Returning %d\n", ret); 02003 return ret; 02004 } 02005 02006 /*********************************************************************** 02007 * SetupDiGetDriverInstallParamsW (SETUPAPI.@) 02008 */ 02009 BOOL WINAPI 02010 SetupDiGetDriverInstallParamsW( 02011 IN HDEVINFO DeviceInfoSet, 02012 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 02013 IN PSP_DRVINFO_DATA_W DriverInfoData, 02014 OUT PSP_DRVINSTALL_PARAMS DriverInstallParams) 02015 { 02016 BOOL ret = FALSE; 02017 02018 TRACE("%p %p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData, DriverInstallParams); 02019 02020 if (!DeviceInfoSet || !DriverInfoData || !DriverInstallParams) 02021 SetLastError(ERROR_INVALID_PARAMETER); 02022 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 02023 SetLastError(ERROR_INVALID_HANDLE); 02024 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02025 SetLastError(ERROR_INVALID_HANDLE); 02026 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 02027 SetLastError(ERROR_INVALID_USER_BUFFER); 02028 else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W)) 02029 SetLastError(ERROR_INVALID_USER_BUFFER); 02030 else if (DriverInstallParams->cbSize != sizeof(SP_DRVINSTALL_PARAMS)) 02031 SetLastError(ERROR_INVALID_USER_BUFFER); 02032 else 02033 { 02034 SP_DEVINSTALL_PARAMS InstallParams; 02035 02036 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 02037 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) 02038 { 02039 struct DriverInfoElement *driverInfo; 02040 driverInfo = (struct DriverInfoElement *)InstallParams.Reserved; 02041 if (driverInfo == NULL) 02042 SetLastError(ERROR_NO_DRIVER_SELECTED); 02043 else 02044 { 02045 memcpy( 02046 DriverInstallParams, 02047 &driverInfo->Params, 02048 DriverInstallParams->cbSize); 02049 ret = TRUE; 02050 } 02051 } 02052 } 02053 02054 TRACE("Returning %d\n", ret); 02055 return ret; 02056 } 02057 02058 /*********************************************************************** 02059 * SetupDiSelectBestCompatDrv (SETUPAPI.@) 02060 */ 02061 BOOL WINAPI 02062 SetupDiSelectBestCompatDrv( 02063 IN HDEVINFO DeviceInfoSet, 02064 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 02065 { 02066 SP_DRVINFO_DATA_W drvInfoData; 02067 BOOL ret; 02068 02069 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 02070 02071 /* Drivers are sorted by rank in the driver list, so 02072 * the first driver in the list is the best one. 02073 */ 02074 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W); 02075 ret = SetupDiEnumDriverInfoW( 02076 DeviceInfoSet, 02077 DeviceInfoData, 02078 SPDIT_COMPATDRIVER, 02079 0, /* Member index */ 02080 &drvInfoData); 02081 02082 if (ret) 02083 { 02084 ret = SetupDiSetSelectedDriverW( 02085 DeviceInfoSet, 02086 DeviceInfoData, 02087 &drvInfoData); 02088 } 02089 02090 TRACE("Returning %d\n", ret); 02091 return ret; 02092 } 02093 02094 /*********************************************************************** 02095 * SetupDiInstallDriverFiles (SETUPAPI.@) 02096 */ 02097 BOOL WINAPI 02098 SetupDiInstallDriverFiles( 02099 IN HDEVINFO DeviceInfoSet, 02100 IN PSP_DEVINFO_DATA DeviceInfoData) 02101 { 02102 BOOL ret = FALSE; 02103 02104 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 02105 02106 if (!DeviceInfoSet) 02107 SetLastError(ERROR_INVALID_PARAMETER); 02108 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 02109 SetLastError(ERROR_INVALID_HANDLE); 02110 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02111 SetLastError(ERROR_INVALID_HANDLE); 02112 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 02113 SetLastError(ERROR_INVALID_USER_BUFFER); 02114 else if (DeviceInfoData && ((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0) 02115 SetLastError(ERROR_NO_DRIVER_SELECTED); 02116 else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0) 02117 SetLastError(ERROR_NO_DRIVER_SELECTED); 02118 else 02119 { 02120 SP_DEVINSTALL_PARAMS_W InstallParams; 02121 struct DriverInfoElement *SelectedDriver; 02122 WCHAR SectionName[MAX_PATH]; 02123 DWORD SectionNameLength = 0; 02124 PVOID InstallMsgHandler; 02125 PVOID InstallMsgHandlerContext; 02126 PVOID Context = NULL; 02127 02128 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 02129 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 02130 if (!ret) 02131 goto done; 02132 02133 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; 02134 if (!SelectedDriver) 02135 { 02136 SetLastError(ERROR_NO_DRIVER_SELECTED); 02137 goto done; 02138 } 02139 02140 ret = SetupDiGetActualSectionToInstallW( 02141 SelectedDriver->InfFileDetails->hInf, 02142 SelectedDriver->Details.SectionName, 02143 SectionName, MAX_PATH - strlenW(DotCoInstallers), &SectionNameLength, NULL); 02144 if (!ret) 02145 goto done; 02146 02147 if (InstallParams.InstallMsgHandler) 02148 { 02149 InstallMsgHandler = InstallParams.InstallMsgHandler; 02150 InstallMsgHandlerContext = InstallParams.InstallMsgHandlerContext; 02151 } 02152 else 02153 { 02154 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 02155 if (!Context) 02156 goto cleanup; 02157 InstallMsgHandler = SetupDefaultQueueCallbackW; 02158 InstallMsgHandlerContext = Context; 02159 } 02160 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent, 02161 SelectedDriver->InfFileDetails->hInf, SectionName, 02162 SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 02163 InstallMsgHandler, InstallMsgHandlerContext, 02164 DeviceInfoSet, DeviceInfoData); 02165 if (!ret) 02166 goto done; 02167 02168 /* Install files from .CoInstallers section */ 02169 lstrcatW(SectionName, DotCoInstallers); 02170 ret = SetupInstallFromInfSectionW(InstallParams.hwndParent, 02171 SelectedDriver->InfFileDetails->hInf, SectionName, 02172 SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 02173 InstallMsgHandler, InstallMsgHandlerContext, 02174 DeviceInfoSet, DeviceInfoData); 02175 if (!ret) 02176 goto done; 02177 02178 /* Set the DI_NOFILECOPY flag to prevent another 02179 * installation during SetupDiInstallDevice */ 02180 InstallParams.Flags |= DI_NOFILECOPY; 02181 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 02182 02183 cleanup: 02184 if (Context) 02185 SetupTermDefaultQueueCallback(Context); 02186 } 02187 02188 done: 02189 TRACE("Returning %d\n", ret); 02190 return ret; 02191 } Generated on Sun May 27 2012 04:18:51 for ReactOS by
1.7.6.1
|