Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendevinst.c
Go to the documentation of this file.
00001 /* 00002 * SetupAPI device installer 00003 * 00004 * Copyright 2000 Andreas Mohr for CodeWeavers 00005 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org) 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "setupapi_private.h" 00023 00024 WINE_DEFAULT_DEBUG_CHANNEL(setupapi); 00025 00026 /* Unicode constants */ 00027 static const WCHAR BackSlash[] = {'\\',0}; 00028 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; 00029 static const WCHAR Class[] = {'C','l','a','s','s',0}; 00030 static const WCHAR DateFormat[] = {'%','u','-','%','u','-','%','u',0}; 00031 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0}; 00032 static const WCHAR DotHW[] = {'.','H','W',0}; 00033 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0}; 00034 static const WCHAR InfDirectory[] = {'i','n','f','\\',0}; 00035 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0}; 00036 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; 00037 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; 00038 00039 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0}; 00040 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0}; 00041 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0}; 00042 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0}; 00043 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0}; 00044 00045 typedef DWORD 00046 (CALLBACK* CLASS_INSTALL_PROC) ( 00047 IN DI_FUNCTION InstallFunction, 00048 IN HDEVINFO DeviceInfoSet, 00049 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL); 00050 typedef BOOL 00051 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) ( 00052 IN HDEVINFO DeviceInfoSet, 00053 IN OUT PSP_DEVINFO_DATA DeviceInfoData); 00054 typedef DWORD 00055 (CALLBACK* COINSTALLER_PROC) ( 00056 IN DI_FUNCTION InstallFunction, 00057 IN HDEVINFO DeviceInfoSet, 00058 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 00059 IN OUT PCOINSTALLER_CONTEXT_DATA Context); 00060 00061 struct CoInstallerElement 00062 { 00063 LIST_ENTRY ListEntry; 00064 00065 HMODULE Module; 00066 COINSTALLER_PROC Function; 00067 BOOL DoPostProcessing; 00068 PVOID PrivateData; 00069 }; 00070 00071 struct GetSectionCallbackInfo 00072 { 00073 PSP_ALTPLATFORM_INFO PlatformInfo; 00074 BYTE ProductType; 00075 WORD SuiteMask; 00076 DWORD PrefixLength; 00077 WCHAR BestSection[LINE_LEN + 1]; 00078 DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5; 00079 }; 00080 00081 00082 00083 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr) 00084 { 00085 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-', 00086 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2', 00087 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%', 00088 '0','2','X','}',0}; 00089 00090 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3, 00091 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], 00092 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); 00093 } 00094 00095 static DWORD 00096 GetErrorCodeFromCrCode(const IN CONFIGRET cr) 00097 { 00098 switch (cr) 00099 { 00100 case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED; 00101 case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER; 00102 case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED; 00103 case CR_FAILURE: return ERROR_GEN_FAILURE; 00104 case CR_INVALID_DATA: return ERROR_INVALID_USER_BUFFER; 00105 case CR_INVALID_DEVICE_ID: return ERROR_INVALID_PARAMETER; 00106 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME; 00107 case CR_INVALID_DEVNODE: return ERROR_INVALID_PARAMETER; 00108 case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS; 00109 case CR_INVALID_POINTER: return ERROR_INVALID_PARAMETER; 00110 case CR_INVALID_PROPERTY: return ERROR_INVALID_PARAMETER; 00111 case CR_NO_SUCH_DEVNODE: return ERROR_FILE_NOT_FOUND; 00112 case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND; 00113 case CR_NO_SUCH_VALUE: return ERROR_FILE_NOT_FOUND; 00114 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY; 00115 case CR_REGISTRY_ERROR: return ERROR_GEN_FAILURE; 00116 case CR_ALREADY_SUCH_DEVINST: return ERROR_DEVINST_ALREADY_EXISTS; 00117 case CR_SUCCESS: return ERROR_SUCCESS; 00118 default: return ERROR_GEN_FAILURE; 00119 } 00120 00121 /* Does not happen */ 00122 } 00123 00124 /* Lower scores are best ones */ 00125 static BOOL 00126 CheckSectionValid( 00127 IN LPCWSTR SectionName, 00128 IN PSP_ALTPLATFORM_INFO PlatformInfo, 00129 IN BYTE ProductType, 00130 IN WORD SuiteMask, 00131 OUT PDWORD ScorePlatform, 00132 OUT PDWORD ScoreMajorVersion, 00133 OUT PDWORD ScoreMinorVersion, 00134 OUT PDWORD ScoreProductType, 00135 OUT PDWORD ScoreSuiteMask) 00136 { 00137 LPWSTR Section = NULL; 00138 //LPCWSTR pExtensionPlatform; 00139 LPCWSTR pExtensionArchitecture; 00140 LPWSTR Fields[6]; 00141 DWORD i; 00142 BOOL ret = FALSE; 00143 00144 //static const WCHAR ExtensionPlatformNone[] = {'.',0}; 00145 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0}; 00146 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0}; 00147 00148 static const WCHAR ExtensionArchitectureNone[] = {0}; 00149 static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0}; 00150 static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0}; 00151 static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0}; 00152 static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0}; 00153 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0}; 00154 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0}; 00155 00156 TRACE("%s %p 0x%x 0x%x\n", 00157 debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask); 00158 00159 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0; 00160 00161 Section = pSetupDuplicateString(SectionName); 00162 if (!Section) 00163 { 00164 TRACE("pSetupDuplicateString() failed\n"); 00165 goto cleanup; 00166 } 00167 00168 /* Set various extensions values */ 00169 switch (PlatformInfo->Platform) 00170 { 00171 case VER_PLATFORM_WIN32_WINDOWS: 00172 //pExtensionPlatform = ExtensionPlatformWindows; 00173 break; 00174 case VER_PLATFORM_WIN32_NT: 00175 //pExtensionPlatform = ExtensionPlatformNT; 00176 break; 00177 default: 00178 ERR("Unknown platform 0x%lx\n", PlatformInfo->Platform); 00179 //pExtensionPlatform = ExtensionPlatformNone; 00180 break; 00181 } 00182 switch (PlatformInfo->ProcessorArchitecture) 00183 { 00184 case PROCESSOR_ARCHITECTURE_ALPHA: 00185 pExtensionArchitecture = ExtensionArchitecturealpha; 00186 break; 00187 case PROCESSOR_ARCHITECTURE_AMD64: 00188 pExtensionArchitecture = ExtensionArchitectureamd64; 00189 break; 00190 case PROCESSOR_ARCHITECTURE_IA64: 00191 pExtensionArchitecture = ExtensionArchitectureia64; 00192 break; 00193 case PROCESSOR_ARCHITECTURE_INTEL: 00194 pExtensionArchitecture = ExtensionArchitecturex86; 00195 break; 00196 case PROCESSOR_ARCHITECTURE_MIPS: 00197 pExtensionArchitecture = ExtensionArchitecturemips; 00198 break; 00199 case PROCESSOR_ARCHITECTURE_PPC: 00200 pExtensionArchitecture = ExtensionArchitectureppc; 00201 break; 00202 default: 00203 ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture); 00204 case PROCESSOR_ARCHITECTURE_UNKNOWN: 00205 pExtensionArchitecture = ExtensionArchitectureNone; 00206 break; 00207 } 00208 00209 /* 00210 * Field[0] Platform 00211 * Field[1] Architecture 00212 * Field[2] Major version 00213 * Field[3] Minor version 00214 * Field[4] Product type 00215 * Field[5] Suite mask 00216 * Remark: lastests fields may be NULL if the information is not provided 00217 */ 00218 Fields[0] = Section; 00219 if (Fields[0] == NULL) 00220 { 00221 TRACE("No extension found\n"); 00222 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX; 00223 ret = TRUE; 00224 goto cleanup; 00225 } 00226 Fields[1] = Fields[0] + 1; 00227 Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL; 00228 for (i = 2; Fields[i - 1] != NULL && i < 6; i++) 00229 { 00230 Fields[i] = wcschr(Fields[i - 1], '.'); 00231 if (Fields[i]) 00232 { 00233 Fields[i]++; 00234 *(Fields[i] - 1) = UNICODE_NULL; 00235 } 00236 } 00237 /* Take care of first 2 fields */ 00238 if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0) 00239 { 00240 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS) 00241 { 00242 TRACE("Mismatch on platform field\n"); 00243 goto cleanup; 00244 } 00245 Fields[1] += wcslen(ExtensionPlatformWindows) - 1; 00246 } 00247 else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0) 00248 { 00249 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT) 00250 { 00251 TRACE("Mismatch on platform field\n"); 00252 goto cleanup; 00253 } 00254 Fields[1] += wcslen(ExtensionPlatformNT) - 1; 00255 } 00256 else 00257 { 00258 /* No platform specified */ 00259 *ScorePlatform |= 0x02; 00260 } 00261 if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0) 00262 { 00263 /* No architecture specified */ 00264 *ScorePlatform |= 0x01; 00265 } 00266 else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0) 00267 { 00268 TRACE("Mismatch on architecture field ('%s' and '%s')\n", 00269 debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture)); 00270 goto cleanup; 00271 } 00272 00273 /* Check if informations are matching */ 00274 if (Fields[2] && *Fields[2]) 00275 { 00276 DWORD MajorVersion, MinorVersion = 0; 00277 MajorVersion = strtoulW(Fields[2], NULL, 0); 00278 if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) && 00279 (errno == ERANGE || errno == EINVAL)) 00280 { 00281 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2])); 00282 goto cleanup; 00283 } 00284 if (Fields[3] && *Fields[3]) 00285 { 00286 MinorVersion = strtoulW(Fields[3], NULL, 0); 00287 if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) && 00288 (errno == ERANGE || errno == EINVAL)) 00289 { 00290 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3])); 00291 goto cleanup; 00292 } 00293 } 00294 if (PlatformInfo->MajorVersion < MajorVersion || 00295 (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion)) 00296 { 00297 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n", 00298 MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion); 00299 goto cleanup; 00300 } 00301 *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion; 00302 if (MajorVersion == PlatformInfo->MajorVersion) 00303 *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion; 00304 else 00305 *ScoreMinorVersion = MinorVersion; 00306 } 00307 else if (Fields[3] && *Fields[3]) 00308 { 00309 TRACE("Minor version found without major version\n"); 00310 goto cleanup; 00311 } 00312 else 00313 { 00314 *ScoreMajorVersion = PlatformInfo->MajorVersion; 00315 *ScoreMinorVersion = PlatformInfo->MinorVersion; 00316 } 00317 00318 if (Fields[4] && *Fields[4]) 00319 { 00320 DWORD CurrentProductType; 00321 CurrentProductType = strtoulW(Fields[4], NULL, 0); 00322 if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) && 00323 (errno == ERANGE || errno == EINVAL)) 00324 { 00325 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4])); 00326 goto cleanup; 00327 } 00328 if (CurrentProductType != ProductType) 00329 { 00330 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n", 00331 CurrentProductType, ProductType); 00332 goto cleanup; 00333 } 00334 } 00335 else 00336 *ScoreProductType = 1; 00337 00338 if (Fields[5] && *Fields[5]) 00339 { 00340 DWORD CurrentSuiteMask; 00341 CurrentSuiteMask = strtoulW(Fields[5], NULL, 0); 00342 if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) && 00343 (errno == ERANGE || errno == EINVAL)) 00344 { 00345 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5])); 00346 goto cleanup; 00347 } 00348 if ((CurrentSuiteMask & ~SuiteMask) != 0) 00349 { 00350 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n", 00351 CurrentSuiteMask, SuiteMask); 00352 goto cleanup; 00353 } 00354 *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask; 00355 } 00356 else 00357 *ScoreSuiteMask = SuiteMask; 00358 00359 ret = TRUE; 00360 00361 cleanup: 00362 MyFree(Section); 00363 return ret; 00364 } 00365 00366 static BOOL 00367 GetSectionCallback( 00368 IN LPCWSTR SectionName, 00369 IN PVOID Context) 00370 { 00371 struct GetSectionCallbackInfo *info = Context; 00372 DWORD Score1, Score2, Score3, Score4, Score5; 00373 BOOL ret; 00374 00375 if (SectionName[info->PrefixLength] != '.') 00376 return TRUE; 00377 00378 ret = CheckSectionValid( 00379 &SectionName[info->PrefixLength], 00380 info->PlatformInfo, 00381 info->ProductType, 00382 info->SuiteMask, 00383 &Score1, &Score2, &Score3, &Score4, &Score5); 00384 if (!ret) 00385 { 00386 TRACE("Section %s not compatible\n", debugstr_w(SectionName)); 00387 return TRUE; 00388 } 00389 if (Score1 > info->BestScore1) goto done; 00390 if (Score1 < info->BestScore1) goto bettersection; 00391 if (Score2 > info->BestScore2) goto done; 00392 if (Score2 < info->BestScore2) goto bettersection; 00393 if (Score3 > info->BestScore3) goto done; 00394 if (Score3 < info->BestScore3) goto bettersection; 00395 if (Score4 > info->BestScore4) goto done; 00396 if (Score4 < info->BestScore4) goto bettersection; 00397 if (Score5 > info->BestScore5) goto done; 00398 if (Score5 < info->BestScore5) goto bettersection; 00399 goto done; 00400 00401 bettersection: 00402 strcpyW(info->BestSection, SectionName); 00403 info->BestScore1 = Score1; 00404 info->BestScore2 = Score2; 00405 info->BestScore3 = Score3; 00406 info->BestScore4 = Score4; 00407 info->BestScore5 = Score5; 00408 00409 done: 00410 return TRUE; 00411 } 00412 00413 /*********************************************************************** 00414 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@) 00415 */ 00416 BOOL WINAPI 00417 SetupDiGetActualSectionToInstallExW( 00418 IN HINF InfHandle, 00419 IN PCWSTR InfSectionName, 00420 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL, 00421 OUT PWSTR InfSectionWithExt OPTIONAL, 00422 IN DWORD InfSectionWithExtSize, 00423 OUT PDWORD RequiredSize OPTIONAL, 00424 OUT PWSTR* Extension OPTIONAL, 00425 IN PVOID Reserved) 00426 { 00427 BOOL ret = FALSE; 00428 00429 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName), 00430 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize, 00431 RequiredSize, Extension, Reserved); 00432 00433 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE) 00434 SetLastError(ERROR_INVALID_HANDLE); 00435 else if (!InfSectionName) 00436 SetLastError(ERROR_INVALID_PARAMETER); 00437 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO)) 00438 SetLastError(ERROR_INVALID_USER_BUFFER); 00439 else if (Reserved != NULL) 00440 SetLastError(ERROR_INVALID_PARAMETER); 00441 else 00442 { 00443 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, }; 00444 static BYTE CurrentProductType = 0; 00445 static WORD CurrentSuiteMask = 0; 00446 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform; 00447 struct GetSectionCallbackInfo CallbackInfo; 00448 DWORD dwFullLength; 00449 BYTE ProductType; 00450 WORD SuiteMask; 00451 00452 /* Fill platform info if needed */ 00453 if (AlternatePlatformInfo) 00454 { 00455 pPlatformInfo = AlternatePlatformInfo; 00456 ProductType = 0; 00457 SuiteMask = 0; 00458 } 00459 else 00460 { 00461 if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO)) 00462 { 00463 /* That's the first time we go here. We need to fill in the structure */ 00464 OSVERSIONINFOEX VersionInfo; 00465 SYSTEM_INFO SystemInfo; 00466 VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 00467 ret = GetVersionExW((OSVERSIONINFO*)&VersionInfo); 00468 if (!ret) 00469 goto done; 00470 GetSystemInfo(&SystemInfo); 00471 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO); 00472 CurrentPlatform.Platform = VersionInfo.dwPlatformId; 00473 CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion; 00474 CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion; 00475 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture; 00476 CurrentPlatform.Reserved = 0; 00477 CurrentProductType = VersionInfo.wProductType; 00478 CurrentSuiteMask = VersionInfo.wSuiteMask; 00479 } 00480 ProductType = CurrentProductType; 00481 SuiteMask = CurrentSuiteMask; 00482 } 00483 00484 CallbackInfo.PlatformInfo = pPlatformInfo; 00485 CallbackInfo.ProductType = ProductType; 00486 CallbackInfo.SuiteMask = SuiteMask; 00487 CallbackInfo.PrefixLength = strlenW(InfSectionName); 00488 CallbackInfo.BestScore1 = ULONG_MAX; 00489 CallbackInfo.BestScore2 = ULONG_MAX; 00490 CallbackInfo.BestScore3 = ULONG_MAX; 00491 CallbackInfo.BestScore4 = ULONG_MAX; 00492 CallbackInfo.BestScore5 = ULONG_MAX; 00493 strcpyW(CallbackInfo.BestSection, InfSectionName); 00494 if (!EnumerateSectionsStartingWith( 00495 InfHandle, 00496 InfSectionName, 00497 GetSectionCallback, 00498 &CallbackInfo)) 00499 { 00500 SetLastError(ERROR_GEN_FAILURE); 00501 goto done; 00502 } 00503 00504 dwFullLength = lstrlenW(CallbackInfo.BestSection); 00505 if (RequiredSize != NULL) 00506 *RequiredSize = dwFullLength + 1; 00507 00508 if (InfSectionWithExtSize > 0) 00509 { 00510 if (InfSectionWithExtSize < dwFullLength + 1) 00511 { 00512 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00513 goto done; 00514 } 00515 strcpyW(InfSectionWithExt, CallbackInfo.BestSection); 00516 if (Extension) 00517 { 00518 DWORD dwLength = lstrlenW(InfSectionName); 00519 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength]; 00520 } 00521 } 00522 00523 ret = TRUE; 00524 } 00525 00526 done: 00527 TRACE("Returning %d\n", ret); 00528 return ret; 00529 } 00530 00531 00532 BOOL 00533 CreateDeviceInfo( 00534 IN struct DeviceInfoSet *list, 00535 IN LPCWSTR InstancePath, 00536 IN LPCGUID pClassGuid, 00537 OUT struct DeviceInfo **pDeviceInfo) 00538 { 00539 DWORD size; 00540 CONFIGRET cr; 00541 struct DeviceInfo *deviceInfo; 00542 00543 *pDeviceInfo = NULL; 00544 00545 size = FIELD_OFFSET(struct DeviceInfo, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR); 00546 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size); 00547 if (!deviceInfo) 00548 { 00549 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00550 return FALSE; 00551 } 00552 ZeroMemory(deviceInfo, size); 00553 00554 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine); 00555 if (cr != CR_SUCCESS) 00556 { 00557 SetLastError(GetErrorCodeFromCrCode(cr)); 00558 return FALSE; 00559 } 00560 00561 deviceInfo->set = list; 00562 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 00563 strcpyW(deviceInfo->Data, InstancePath); 00564 deviceInfo->instanceId = deviceInfo->Data; 00565 deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\'); 00566 deviceInfo->DeviceDescription = NULL; 00567 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID)); 00568 deviceInfo->CreationFlags = 0; 00569 InitializeListHead(&deviceInfo->DriverListHead); 00570 InitializeListHead(&deviceInfo->InterfaceListHead); 00571 00572 *pDeviceInfo = deviceInfo; 00573 return TRUE; 00574 } 00575 00576 00577 static BOOL 00578 DestroyClassInstallParams(struct ClassInstallParams* installParams) 00579 { 00580 HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams); 00581 HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData); 00582 return TRUE; 00583 } 00584 00585 static BOOL 00586 DestroyDeviceInfo(struct DeviceInfo *deviceInfo) 00587 { 00588 PLIST_ENTRY ListEntry; 00589 struct DriverInfoElement *driverInfo; 00590 struct DeviceInterface *deviceInterface; 00591 00592 while (!IsListEmpty(&deviceInfo->DriverListHead)) 00593 { 00594 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead); 00595 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry); 00596 if (!DestroyDriverInfoElement(driverInfo)) 00597 return FALSE; 00598 } 00599 while (!IsListEmpty(&deviceInfo->InterfaceListHead)) 00600 { 00601 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead); 00602 deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry); 00603 if (!DestroyDeviceInterface(deviceInterface)) 00604 return FALSE; 00605 } 00606 DestroyClassInstallParams(&deviceInfo->ClassInstallParams); 00607 return HeapFree(GetProcessHeap(), 0, deviceInfo); 00608 } 00609 00610 static BOOL 00611 DestroyDeviceInfoSet(struct DeviceInfoSet* list) 00612 { 00613 PLIST_ENTRY ListEntry; 00614 struct DeviceInfo *deviceInfo; 00615 00616 while (!IsListEmpty(&list->ListHead)) 00617 { 00618 ListEntry = RemoveHeadList(&list->ListHead); 00619 deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry); 00620 if (!DestroyDeviceInfo(deviceInfo)) 00621 return FALSE; 00622 } 00623 if (list->HKLM != HKEY_LOCAL_MACHINE) 00624 RegCloseKey(list->HKLM); 00625 CM_Disconnect_Machine(list->hMachine); 00626 DestroyClassInstallParams(&list->ClassInstallParams); 00627 return HeapFree(GetProcessHeap(), 0, list); 00628 } 00629 00630 /*********************************************************************** 00631 * SetupDiBuildClassInfoList (SETUPAPI.@) 00632 * 00633 * Returns a list of setup class GUIDs that identify the classes 00634 * that are installed on a local machine. 00635 * 00636 * PARAMS 00637 * Flags [I] control exclusion of classes from the list. 00638 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs. 00639 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList). 00640 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned. 00641 * 00642 * RETURNS 00643 * Success: TRUE. 00644 * Failure: FALSE. 00645 */ 00646 BOOL WINAPI SetupDiBuildClassInfoList( 00647 DWORD Flags, 00648 LPGUID ClassGuidList, 00649 DWORD ClassGuidListSize, 00650 PDWORD RequiredSize) 00651 { 00652 TRACE("\n"); 00653 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList, 00654 ClassGuidListSize, RequiredSize, 00655 NULL, NULL); 00656 } 00657 00658 /*********************************************************************** 00659 * SetupDiBuildClassInfoListExA (SETUPAPI.@) 00660 * 00661 * Returns a list of setup class GUIDs that identify the classes 00662 * that are installed on a local or remote macine. 00663 * 00664 * PARAMS 00665 * Flags [I] control exclusion of classes from the list. 00666 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs. 00667 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList). 00668 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned. 00669 * MachineName [I] name of a remote machine. 00670 * Reserved [I] must be NULL. 00671 * 00672 * RETURNS 00673 * Success: TRUE. 00674 * Failure: FALSE. 00675 */ 00676 BOOL WINAPI SetupDiBuildClassInfoListExA( 00677 DWORD Flags, 00678 LPGUID ClassGuidList, 00679 DWORD ClassGuidListSize, 00680 PDWORD RequiredSize, 00681 LPCSTR MachineName, 00682 PVOID Reserved) 00683 { 00684 LPWSTR MachineNameW = NULL; 00685 BOOL bResult; 00686 00687 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList, 00688 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved); 00689 00690 if (MachineName) 00691 { 00692 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 00693 if (MachineNameW == NULL) return FALSE; 00694 } 00695 00696 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList, 00697 ClassGuidListSize, RequiredSize, 00698 MachineNameW, Reserved); 00699 00700 MyFree(MachineNameW); 00701 00702 return bResult; 00703 } 00704 00705 /*********************************************************************** 00706 * SetupDiBuildClassInfoListExW (SETUPAPI.@) 00707 * 00708 * Returns a list of setup class GUIDs that identify the classes 00709 * that are installed on a local or remote macine. 00710 * 00711 * PARAMS 00712 * Flags [I] control exclusion of classes from the list. 00713 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs. 00714 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList). 00715 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned. 00716 * MachineName [I] name of a remote machine. 00717 * Reserved [I] must be NULL. 00718 * 00719 * RETURNS 00720 * Success: TRUE. 00721 * Failure: FALSE. 00722 */ 00723 BOOL WINAPI SetupDiBuildClassInfoListExW( 00724 DWORD Flags, 00725 LPGUID ClassGuidList, 00726 DWORD ClassGuidListSize, 00727 PDWORD RequiredSize, 00728 LPCWSTR MachineName, 00729 PVOID Reserved) 00730 { 00731 WCHAR szKeyName[40]; 00732 HKEY hClassesKey = INVALID_HANDLE_VALUE; 00733 HKEY hClassKey; 00734 DWORD dwLength; 00735 DWORD dwIndex; 00736 LONG lError; 00737 DWORD dwGuidListIndex = 0; 00738 00739 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList, 00740 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved); 00741 00742 if (!RequiredSize) 00743 { 00744 SetLastError(ERROR_INVALID_PARAMETER); 00745 return FALSE; 00746 } 00747 else if (!ClassGuidList && ClassGuidListSize > 0) 00748 { 00749 SetLastError(ERROR_INVALID_PARAMETER); 00750 return FALSE; 00751 } 00752 00753 hClassesKey = SetupDiOpenClassRegKeyExW(NULL, 00754 KEY_ENUMERATE_SUB_KEYS, 00755 DIOCR_INSTALLER, 00756 MachineName, 00757 Reserved); 00758 if (hClassesKey == INVALID_HANDLE_VALUE) 00759 { 00760 return FALSE; 00761 } 00762 00763 for (dwIndex = 0; ; dwIndex++) 00764 { 00765 dwLength = 40; 00766 lError = RegEnumKeyExW(hClassesKey, 00767 dwIndex, 00768 szKeyName, 00769 &dwLength, 00770 NULL, 00771 NULL, 00772 NULL, 00773 NULL); 00774 TRACE("RegEnumKeyExW() returns %d\n", lError); 00775 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) 00776 { 00777 TRACE("Key name: %s\n", debugstr_w(szKeyName)); 00778 00779 if (RegOpenKeyExW(hClassesKey, 00780 szKeyName, 00781 0, 00782 KEY_QUERY_VALUE, 00783 &hClassKey)) 00784 { 00785 RegCloseKey(hClassesKey); 00786 return FALSE; 00787 } 00788 00789 if (!RegQueryValueExW(hClassKey, 00790 REGSTR_VAL_NOUSECLASS, 00791 NULL, 00792 NULL, 00793 NULL, 00794 NULL)) 00795 { 00796 TRACE("'NoUseClass' value found!\n"); 00797 RegCloseKey(hClassKey); 00798 continue; 00799 } 00800 00801 if ((Flags & DIBCI_NOINSTALLCLASS) && 00802 (!RegQueryValueExW(hClassKey, 00803 REGSTR_VAL_NOINSTALLCLASS, 00804 NULL, 00805 NULL, 00806 NULL, 00807 NULL))) 00808 { 00809 TRACE("'NoInstallClass' value found!\n"); 00810 RegCloseKey(hClassKey); 00811 continue; 00812 } 00813 00814 if ((Flags & DIBCI_NODISPLAYCLASS) && 00815 (!RegQueryValueExW(hClassKey, 00816 REGSTR_VAL_NODISPLAYCLASS, 00817 NULL, 00818 NULL, 00819 NULL, 00820 NULL))) 00821 { 00822 TRACE("'NoDisplayClass' value found!\n"); 00823 RegCloseKey(hClassKey); 00824 continue; 00825 } 00826 00827 RegCloseKey(hClassKey); 00828 00829 TRACE("Guid: %s\n", debugstr_w(szKeyName)); 00830 if (dwGuidListIndex < ClassGuidListSize) 00831 { 00832 if (szKeyName[0] == '{' && szKeyName[37] == '}') 00833 { 00834 szKeyName[37] = 0; 00835 } 00836 TRACE("Guid: %p\n", &szKeyName[1]); 00837 00838 UuidFromStringW(&szKeyName[1], 00839 &ClassGuidList[dwGuidListIndex]); 00840 } 00841 00842 dwGuidListIndex++; 00843 } 00844 00845 if (lError != ERROR_SUCCESS) 00846 break; 00847 } 00848 00849 RegCloseKey(hClassesKey); 00850 00851 if (RequiredSize != NULL) 00852 *RequiredSize = dwGuidListIndex; 00853 00854 if (ClassGuidListSize < dwGuidListIndex) 00855 { 00856 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00857 return FALSE; 00858 } 00859 00860 return TRUE; 00861 } 00862 00863 /*********************************************************************** 00864 * SetupDiClassGuidsFromNameA (SETUPAPI.@) 00865 */ 00866 BOOL WINAPI SetupDiClassGuidsFromNameA( 00867 LPCSTR ClassName, 00868 LPGUID ClassGuidList, 00869 DWORD ClassGuidListSize, 00870 PDWORD RequiredSize) 00871 { 00872 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList, 00873 ClassGuidListSize, RequiredSize, 00874 NULL, NULL); 00875 } 00876 00877 /*********************************************************************** 00878 * SetupDiClassGuidsFromNameW (SETUPAPI.@) 00879 */ 00880 BOOL WINAPI SetupDiClassGuidsFromNameW( 00881 LPCWSTR ClassName, 00882 LPGUID ClassGuidList, 00883 DWORD ClassGuidListSize, 00884 PDWORD RequiredSize) 00885 { 00886 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList, 00887 ClassGuidListSize, RequiredSize, 00888 NULL, NULL); 00889 } 00890 00891 /*********************************************************************** 00892 * SetupDiClassGuidsFromNameExA (SETUPAPI.@) 00893 */ 00894 BOOL WINAPI SetupDiClassGuidsFromNameExA( 00895 LPCSTR ClassName, 00896 LPGUID ClassGuidList, 00897 DWORD ClassGuidListSize, 00898 PDWORD RequiredSize, 00899 LPCSTR MachineName, 00900 PVOID Reserved) 00901 { 00902 LPWSTR ClassNameW = NULL; 00903 LPWSTR MachineNameW = NULL; 00904 BOOL bResult; 00905 00906 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName), ClassGuidList, 00907 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved); 00908 00909 if (!ClassName) 00910 { 00911 SetLastError(ERROR_INVALID_PARAMETER); 00912 return FALSE; 00913 } 00914 00915 ClassNameW = pSetupMultiByteToUnicode(ClassName, CP_ACP); 00916 if (ClassNameW == NULL) 00917 return FALSE; 00918 00919 if (MachineName) 00920 { 00921 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 00922 if (MachineNameW == NULL) 00923 { 00924 MyFree(ClassNameW); 00925 return FALSE; 00926 } 00927 } 00928 00929 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList, 00930 ClassGuidListSize, RequiredSize, 00931 MachineNameW, Reserved); 00932 00933 MyFree(MachineNameW); 00934 MyFree(ClassNameW); 00935 00936 return bResult; 00937 } 00938 00939 /*********************************************************************** 00940 * SetupDiClassGuidsFromNameExW (SETUPAPI.@) 00941 */ 00942 BOOL WINAPI SetupDiClassGuidsFromNameExW( 00943 LPCWSTR ClassName, 00944 LPGUID ClassGuidList, 00945 DWORD ClassGuidListSize, 00946 PDWORD RequiredSize, 00947 LPCWSTR MachineName, 00948 PVOID Reserved) 00949 { 00950 WCHAR szKeyName[40]; 00951 WCHAR szClassName[MAX_CLASS_NAME_LEN]; 00952 HKEY hClassesKey; 00953 HKEY hClassKey; 00954 DWORD dwLength; 00955 DWORD dwIndex; 00956 LONG lError; 00957 DWORD dwGuidListIndex = 0; 00958 00959 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList, 00960 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved); 00961 00962 if (!ClassName || !RequiredSize) 00963 { 00964 SetLastError(ERROR_INVALID_PARAMETER); 00965 return FALSE; 00966 } 00967 if (!ClassGuidList && ClassGuidListSize > 0) 00968 { 00969 SetLastError(ERROR_INVALID_PARAMETER); 00970 return FALSE; 00971 } 00972 *RequiredSize = 0; 00973 00974 hClassesKey = SetupDiOpenClassRegKeyExW(NULL, 00975 KEY_ENUMERATE_SUB_KEYS, 00976 DIOCR_INSTALLER, 00977 MachineName, 00978 Reserved); 00979 if (hClassesKey == INVALID_HANDLE_VALUE) 00980 { 00981 return FALSE; 00982 } 00983 00984 for (dwIndex = 0; ; dwIndex++) 00985 { 00986 dwLength = 40; 00987 lError = RegEnumKeyExW(hClassesKey, 00988 dwIndex, 00989 szKeyName, 00990 &dwLength, 00991 NULL, 00992 NULL, 00993 NULL, 00994 NULL); 00995 TRACE("RegEnumKeyExW() returns %d\n", lError); 00996 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) 00997 { 00998 TRACE("Key name: %p\n", szKeyName); 00999 01000 if (RegOpenKeyExW(hClassesKey, 01001 szKeyName, 01002 0, 01003 KEY_QUERY_VALUE, 01004 &hClassKey)) 01005 { 01006 RegCloseKey(hClassesKey); 01007 return FALSE; 01008 } 01009 01010 dwLength = MAX_CLASS_NAME_LEN * sizeof(WCHAR); 01011 if (!RegQueryValueExW(hClassKey, 01012 Class, 01013 NULL, 01014 NULL, 01015 (LPBYTE)szClassName, 01016 &dwLength)) 01017 { 01018 TRACE("Class name: %p\n", szClassName); 01019 01020 if (strcmpiW(szClassName, ClassName) == 0) 01021 { 01022 TRACE("Found matching class name\n"); 01023 01024 TRACE("Guid: %p\n", szKeyName); 01025 if (dwGuidListIndex < ClassGuidListSize) 01026 { 01027 if (szKeyName[0] == '{' && szKeyName[37] == '}') 01028 { 01029 szKeyName[37] = 0; 01030 } 01031 TRACE("Guid: %p\n", &szKeyName[1]); 01032 01033 UuidFromStringW(&szKeyName[1], 01034 &ClassGuidList[dwGuidListIndex]); 01035 } 01036 01037 dwGuidListIndex++; 01038 } 01039 } 01040 01041 RegCloseKey(hClassKey); 01042 } 01043 01044 if (lError != ERROR_SUCCESS) 01045 break; 01046 } 01047 01048 RegCloseKey(hClassesKey); 01049 01050 if (RequiredSize != NULL) 01051 *RequiredSize = dwGuidListIndex; 01052 01053 if (ClassGuidListSize < dwGuidListIndex) 01054 { 01055 SetLastError(ERROR_INSUFFICIENT_BUFFER); 01056 return FALSE; 01057 } 01058 01059 return TRUE; 01060 } 01061 01062 /*********************************************************************** 01063 * SetupDiClassNameFromGuidA (SETUPAPI.@) 01064 */ 01065 BOOL WINAPI SetupDiClassNameFromGuidA( 01066 const GUID* ClassGuid, 01067 PSTR ClassName, 01068 DWORD ClassNameSize, 01069 PDWORD RequiredSize) 01070 { 01071 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName, 01072 ClassNameSize, RequiredSize, 01073 NULL, NULL); 01074 } 01075 01076 /*********************************************************************** 01077 * SetupDiClassNameFromGuidW (SETUPAPI.@) 01078 */ 01079 BOOL WINAPI SetupDiClassNameFromGuidW( 01080 const GUID* ClassGuid, 01081 PWSTR ClassName, 01082 DWORD ClassNameSize, 01083 PDWORD RequiredSize) 01084 { 01085 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName, 01086 ClassNameSize, RequiredSize, 01087 NULL, NULL); 01088 } 01089 01090 /*********************************************************************** 01091 * SetupDiClassNameFromGuidExA (SETUPAPI.@) 01092 */ 01093 BOOL WINAPI SetupDiClassNameFromGuidExA( 01094 const GUID* ClassGuid, 01095 PSTR ClassName, 01096 DWORD ClassNameSize, 01097 PDWORD RequiredSize, 01098 PCSTR MachineName, 01099 PVOID Reserved) 01100 { 01101 WCHAR ClassNameW[MAX_CLASS_NAME_LEN]; 01102 LPWSTR MachineNameW = NULL; 01103 BOOL ret; 01104 01105 if (MachineName) 01106 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 01107 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN, 01108 RequiredSize, MachineNameW, Reserved); 01109 if (ret) 01110 { 01111 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName, 01112 ClassNameSize, NULL, NULL); 01113 if (len == 0 || len > ClassNameSize) 01114 { 01115 SetLastError(ERROR_INSUFFICIENT_BUFFER); 01116 ret = FALSE; 01117 } 01118 } 01119 MyFree(MachineNameW); 01120 return ret; 01121 } 01122 01123 /*********************************************************************** 01124 * SetupDiClassNameFromGuidExW (SETUPAPI.@) 01125 */ 01126 BOOL WINAPI SetupDiClassNameFromGuidExW( 01127 const GUID* ClassGuid, 01128 PWSTR ClassName, 01129 DWORD ClassNameSize, 01130 PDWORD RequiredSize, 01131 PCWSTR MachineName, 01132 PVOID Reserved) 01133 { 01134 HKEY hKey; 01135 DWORD dwLength; 01136 DWORD dwRegType; 01137 LONG rc; 01138 PWSTR Buffer; 01139 01140 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName, 01141 ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved); 01142 01143 /* Make sure there's a GUID */ 01144 if (ClassGuid == NULL) 01145 { 01146 SetLastError(ERROR_INVALID_CLASS); /* On Vista: ERROR_INVALID_USER_BUFFER */ 01147 return FALSE; 01148 } 01149 01150 /* Make sure there's a real buffer when there's a size */ 01151 if ((ClassNameSize > 0) && (ClassName == NULL)) 01152 { 01153 SetLastError(ERROR_INVALID_PARAMETER); /* On Vista: ERROR_INVALID_USER_BUFFER */ 01154 return FALSE; 01155 } 01156 01157 /* Open the key for the GUID */ 01158 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INSTALLER, MachineName, Reserved); 01159 01160 if (hKey == INVALID_HANDLE_VALUE) 01161 return FALSE; 01162 01163 /* Retrieve the class name data and close the key */ 01164 rc = QueryRegistryValue(hKey, Class, (LPBYTE *) &Buffer, &dwRegType, &dwLength); 01165 RegCloseKey(hKey); 01166 01167 /* Make sure we got the data */ 01168 if (rc != ERROR_SUCCESS) 01169 { 01170 SetLastError(rc); 01171 return FALSE; 01172 } 01173 01174 /* Make sure the data is a string */ 01175 if (dwRegType != REG_SZ) 01176 { 01177 MyFree(Buffer); 01178 SetLastError(ERROR_GEN_FAILURE); 01179 return FALSE; 01180 } 01181 01182 /* Determine the length of the class name */ 01183 dwLength /= sizeof(WCHAR); 01184 01185 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL)) 01186 /* Count the null-terminator */ 01187 dwLength++; 01188 01189 /* Inform the caller about the class name */ 01190 if ((ClassName != NULL) && (dwLength <= ClassNameSize)) 01191 { 01192 memcpy(ClassName, Buffer, (dwLength - 1) * sizeof(WCHAR)); 01193 ClassName[dwLength - 1] = UNICODE_NULL; 01194 } 01195 01196 /* Inform the caller about the required size */ 01197 if (RequiredSize != NULL) 01198 *RequiredSize = dwLength; 01199 01200 /* Clean up the buffer */ 01201 MyFree(Buffer); 01202 01203 /* Make sure the buffer was large enough */ 01204 if ((ClassName == NULL) || (dwLength > ClassNameSize)) 01205 { 01206 SetLastError(ERROR_INSUFFICIENT_BUFFER); 01207 return FALSE; 01208 } 01209 01210 return TRUE; 01211 } 01212 01213 /*********************************************************************** 01214 * SetupDiCreateDeviceInfoList (SETUPAPI.@) 01215 */ 01216 HDEVINFO WINAPI 01217 SetupDiCreateDeviceInfoList(const GUID *ClassGuid, 01218 HWND hwndParent) 01219 { 01220 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL); 01221 } 01222 01223 /*********************************************************************** 01224 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@) 01225 */ 01226 HDEVINFO WINAPI 01227 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid, 01228 HWND hwndParent, 01229 PCSTR MachineName, 01230 PVOID Reserved) 01231 { 01232 LPWSTR MachineNameW = NULL; 01233 HDEVINFO hDevInfo; 01234 01235 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent, 01236 debugstr_a(MachineName), Reserved); 01237 01238 if (MachineName) 01239 { 01240 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 01241 if (MachineNameW == NULL) 01242 return INVALID_HANDLE_VALUE; 01243 } 01244 01245 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, 01246 MachineNameW, Reserved); 01247 01248 MyFree(MachineNameW); 01249 01250 return hDevInfo; 01251 } 01252 01253 /*********************************************************************** 01254 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@) 01255 * 01256 * Create an empty DeviceInfoSet list. 01257 * 01258 * PARAMS 01259 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated 01260 * with this list. 01261 * hwndParent [I] hwnd needed for interface related actions. 01262 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL 01263 * local registry will be used. 01264 * Reserved [I] must be NULL 01265 * 01266 * RETURNS 01267 * Success: empty list. 01268 * Failure: INVALID_HANDLE_VALUE. 01269 */ 01270 HDEVINFO WINAPI 01271 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid, 01272 HWND hwndParent, 01273 PCWSTR MachineName, 01274 PVOID Reserved) 01275 { 01276 struct DeviceInfoSet *list = NULL; 01277 DWORD size = FIELD_OFFSET(struct DeviceInfoSet, szData); 01278 DWORD rc; 01279 CONFIGRET cr; 01280 HDEVINFO ret = INVALID_HANDLE_VALUE; 01281 01282 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent, 01283 debugstr_w(MachineName), Reserved); 01284 01285 if (MachineName != NULL) 01286 { 01287 SIZE_T len = strlenW(MachineName); 01288 if (len >= SP_MAX_MACHINENAME_LENGTH - 4) 01289 { 01290 SetLastError(ERROR_INVALID_MACHINENAME); 01291 goto cleanup; 01292 } 01293 if(len > 0) 01294 size += (len + 3) * sizeof(WCHAR); 01295 else 01296 MachineName = NULL; 01297 } 01298 01299 if (Reserved != NULL) 01300 { 01301 SetLastError(ERROR_INVALID_PARAMETER); 01302 return INVALID_HANDLE_VALUE; 01303 } 01304 01305 list = MyMalloc(size); 01306 if (!list) 01307 { 01308 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01309 return INVALID_HANDLE_VALUE; 01310 } 01311 ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData)); 01312 01313 list->magic = SETUP_DEVICE_INFO_SET_MAGIC; 01314 memcpy(&list->ClassGuid, 01315 ClassGuid ? ClassGuid : &GUID_NULL, 01316 sizeof(list->ClassGuid)); 01317 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 01318 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS; 01319 list->InstallParams.hwndParent = hwndParent; 01320 if (MachineName) 01321 { 01322 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM); 01323 if (rc != ERROR_SUCCESS) 01324 { 01325 SetLastError(ERROR_INVALID_MACHINENAME); 01326 goto cleanup; 01327 } 01328 01329 list->szData[0] = list->szData[1] = '\\'; 01330 strcpyW(list->szData + 2, MachineName); 01331 list->MachineName = list->szData; 01332 } 01333 else 01334 { 01335 list->HKLM = HKEY_LOCAL_MACHINE; 01336 list->MachineName = NULL; 01337 } 01338 cr = CM_Connect_MachineW(list->MachineName, &list->hMachine); 01339 if (cr != CR_SUCCESS) 01340 { 01341 SetLastError(GetErrorCodeFromCrCode(cr)); 01342 goto cleanup; 01343 } 01344 InitializeListHead(&list->DriverListHead); 01345 InitializeListHead(&list->ListHead); 01346 01347 return (HDEVINFO)list; 01348 01349 cleanup: 01350 if (ret == INVALID_HANDLE_VALUE) 01351 { 01352 if (list) 01353 { 01354 if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE) 01355 RegCloseKey(list->HKLM); 01356 MyFree(list); 01357 } 01358 } 01359 return ret; 01360 } 01361 01362 /*********************************************************************** 01363 * SetupDiCreateDevRegKeyA (SETUPAPI.@) 01364 */ 01365 HKEY WINAPI SetupDiCreateDevRegKeyA( 01366 HDEVINFO DeviceInfoSet, 01367 PSP_DEVINFO_DATA DeviceInfoData, 01368 DWORD Scope, 01369 DWORD HwProfile, 01370 DWORD KeyType, 01371 HINF InfHandle, 01372 PCSTR InfSectionName) 01373 { 01374 PWSTR InfSectionNameW = NULL; 01375 HKEY key; 01376 01377 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope, 01378 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName)); 01379 01380 if (InfHandle) 01381 { 01382 if (!InfSectionName) 01383 { 01384 SetLastError(ERROR_INVALID_PARAMETER); 01385 return INVALID_HANDLE_VALUE; 01386 } 01387 else 01388 { 01389 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP); 01390 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE; 01391 } 01392 } 01393 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope, 01394 HwProfile, KeyType, InfHandle, InfSectionNameW); 01395 MyFree(InfSectionNameW); 01396 return key; 01397 } 01398 01399 static HKEY 01400 OpenHardwareProfileKey( 01401 IN HKEY HKLM, 01402 IN DWORD HwProfile, 01403 IN DWORD samDesired); 01404 01405 /*********************************************************************** 01406 * SetupDiCreateDevRegKeyW (SETUPAPI.@) 01407 */ 01408 HKEY WINAPI SetupDiCreateDevRegKeyW( 01409 HDEVINFO DeviceInfoSet, 01410 PSP_DEVINFO_DATA DeviceInfoData, 01411 DWORD Scope, 01412 DWORD HwProfile, 01413 DWORD KeyType, 01414 HINF InfHandle, 01415 PCWSTR InfSectionName) 01416 { 01417 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 01418 HKEY key = INVALID_HANDLE_VALUE; 01419 LPWSTR lpGuidString = NULL; 01420 LPWSTR DriverKey = NULL; /* {GUID}\Index */ 01421 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */ 01422 DWORD Index; /* Index used in the DriverKey name */ 01423 DWORD dwSize; 01424 DWORD Disposition; 01425 DWORD rc; 01426 HKEY hHWProfileKey = INVALID_HANDLE_VALUE; 01427 HKEY hEnumKey = NULL; 01428 HKEY hClassKey = NULL; 01429 HKEY hDeviceKey = INVALID_HANDLE_VALUE; 01430 HKEY hKey = NULL; 01431 HKEY RootKey; 01432 01433 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData, Scope, 01434 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName)); 01435 01436 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 01437 { 01438 SetLastError(ERROR_INVALID_HANDLE); 01439 return INVALID_HANDLE_VALUE; 01440 } 01441 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 01442 { 01443 SetLastError(ERROR_INVALID_HANDLE); 01444 return INVALID_HANDLE_VALUE; 01445 } 01446 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 01447 || !DeviceInfoData->Reserved) 01448 { 01449 SetLastError(ERROR_INVALID_PARAMETER); 01450 return INVALID_HANDLE_VALUE; 01451 } 01452 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 01453 { 01454 SetLastError(ERROR_INVALID_FLAGS); 01455 return INVALID_HANDLE_VALUE; 01456 } 01457 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV) 01458 { 01459 SetLastError(ERROR_INVALID_FLAGS); 01460 return INVALID_HANDLE_VALUE; 01461 } 01462 if (InfHandle && !InfSectionName) 01463 { 01464 SetLastError(ERROR_INVALID_PARAMETER); 01465 return INVALID_HANDLE_VALUE; 01466 } 01467 if (!InfHandle && InfSectionName) 01468 { 01469 SetLastError(ERROR_INVALID_PARAMETER); 01470 return INVALID_HANDLE_VALUE; 01471 } 01472 01473 if (Scope == DICS_FLAG_GLOBAL) 01474 RootKey = set->HKLM; 01475 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */ 01476 { 01477 hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY); 01478 if (hHWProfileKey == INVALID_HANDLE_VALUE) 01479 goto cleanup; 01480 RootKey = hHWProfileKey; 01481 } 01482 01483 if (KeyType == DIREG_DEV) 01484 { 01485 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 01486 01487 rc = RegCreateKeyExW( 01488 RootKey, 01489 REGSTR_PATH_SYSTEMENUM, 01490 0, 01491 NULL, 01492 REG_OPTION_NON_VOLATILE, 01493 KEY_CREATE_SUB_KEY, 01494 NULL, 01495 &hEnumKey, 01496 NULL); 01497 if (rc != ERROR_SUCCESS) 01498 { 01499 SetLastError(rc); 01500 goto cleanup; 01501 } 01502 rc = RegCreateKeyExW( 01503 hEnumKey, 01504 deviceInfo->instanceId, 01505 0, 01506 NULL, 01507 REG_OPTION_NON_VOLATILE, 01508 #if _WIN32_WINNT >= 0x502 01509 KEY_READ | KEY_WRITE, 01510 #else 01511 KEY_ALL_ACCESS, 01512 #endif 01513 NULL, 01514 &hKey, 01515 NULL); 01516 if (rc != ERROR_SUCCESS) 01517 { 01518 SetLastError(rc); 01519 goto cleanup; 01520 } 01521 } 01522 else /* KeyType == DIREG_DRV */ 01523 { 01524 /* Open device key, to read Driver value */ 01525 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE); 01526 if (hDeviceKey == INVALID_HANDLE_VALUE) 01527 goto cleanup; 01528 01529 rc = RegOpenKeyExW(RootKey, REGSTR_PATH_CLASS_NT, 0, KEY_CREATE_SUB_KEY, &hClassKey); 01530 if (rc != ERROR_SUCCESS) 01531 { 01532 SetLastError(rc); 01533 goto cleanup; 01534 } 01535 01536 rc = RegQueryValueExW(hDeviceKey, REGSTR_VAL_DRIVER, NULL, NULL, NULL, &dwSize); 01537 if (rc != ERROR_SUCCESS) 01538 { 01539 /* Create a new driver key */ 01540 01541 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK) 01542 goto cleanup; 01543 01544 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */ 01545 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 01546 if (!DriverKey) 01547 { 01548 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01549 goto cleanup; 01550 } 01551 01552 DriverKey[0] = '{'; 01553 strcpyW(&DriverKey[1], lpGuidString); 01554 pDeviceInstance = &DriverKey[strlenW(DriverKey)]; 01555 *pDeviceInstance++ = '}'; 01556 *pDeviceInstance++ = '\\'; 01557 01558 /* Try all values for Index between 0 and 9999 */ 01559 Index = 0; 01560 while (Index <= 9999) 01561 { 01562 sprintfW(pDeviceInstance, InstanceKeyFormat, Index); 01563 rc = RegCreateKeyExW(hClassKey, 01564 DriverKey, 01565 0, 01566 NULL, 01567 REG_OPTION_NON_VOLATILE, 01568 #if _WIN32_WINNT >= 0x502 01569 KEY_READ | KEY_WRITE, 01570 #else 01571 KEY_ALL_ACCESS, 01572 #endif 01573 NULL, 01574 &hKey, 01575 &Disposition); 01576 if (rc != ERROR_SUCCESS) 01577 { 01578 SetLastError(rc); 01579 goto cleanup; 01580 } 01581 if (Disposition == REG_CREATED_NEW_KEY) 01582 break; 01583 RegCloseKey(hKey); 01584 hKey = NULL; 01585 Index++; 01586 } 01587 01588 if (Index > 9999) 01589 { 01590 /* Unable to create more than 9999 devices within the same class */ 01591 SetLastError(ERROR_GEN_FAILURE); 01592 goto cleanup; 01593 } 01594 01595 /* Write the new Driver value */ 01596 rc = RegSetValueExW(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR)); 01597 if (rc != ERROR_SUCCESS) 01598 { 01599 SetLastError(rc); 01600 goto cleanup; 01601 } 01602 01603 } 01604 else 01605 { 01606 /* Open the existing driver key */ 01607 01608 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwSize); 01609 if (!DriverKey) 01610 { 01611 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01612 goto cleanup; 01613 } 01614 01615 rc = RegQueryValueExW(hDeviceKey, REGSTR_VAL_DRIVER, NULL, NULL, (LPBYTE)DriverKey, &dwSize); 01616 if (rc != ERROR_SUCCESS) 01617 { 01618 SetLastError(rc); 01619 goto cleanup; 01620 } 01621 01622 rc = RegCreateKeyExW(hClassKey, 01623 DriverKey, 01624 0, 01625 NULL, 01626 REG_OPTION_NON_VOLATILE, 01627 #if _WIN32_WINNT >= 0x502 01628 KEY_READ | KEY_WRITE, 01629 #else 01630 KEY_ALL_ACCESS, 01631 #endif 01632 NULL, 01633 &hKey, 01634 &Disposition); 01635 if (rc != ERROR_SUCCESS) 01636 { 01637 SetLastError(rc); 01638 goto cleanup; 01639 } 01640 } 01641 } 01642 01643 /* Do installation of the specified section */ 01644 if (InfHandle) 01645 { 01646 FIXME("Need to install section %s in file %p\n", 01647 debugstr_w(InfSectionName), InfHandle); 01648 } 01649 key = hKey; 01650 01651 cleanup: 01652 if (lpGuidString) 01653 RpcStringFreeW(&lpGuidString); 01654 HeapFree(GetProcessHeap(), 0, DriverKey); 01655 if (hHWProfileKey != INVALID_HANDLE_VALUE) 01656 RegCloseKey(hHWProfileKey); 01657 if (hEnumKey != NULL) 01658 RegCloseKey(hEnumKey); 01659 if (hClassKey != NULL) 01660 RegCloseKey(hClassKey); 01661 if (hDeviceKey != INVALID_HANDLE_VALUE) 01662 RegCloseKey(hDeviceKey); 01663 if (hKey != NULL && hKey != key) 01664 RegCloseKey(hKey); 01665 01666 TRACE("Returning 0x%p\n", key); 01667 return key; 01668 } 01669 01670 /*********************************************************************** 01671 * SetupDiCreateDeviceInfoA (SETUPAPI.@) 01672 */ 01673 BOOL WINAPI SetupDiCreateDeviceInfoA( 01674 HDEVINFO DeviceInfoSet, 01675 PCSTR DeviceName, 01676 CONST GUID *ClassGuid, 01677 PCSTR DeviceDescription, 01678 HWND hwndParent, 01679 DWORD CreationFlags, 01680 PSP_DEVINFO_DATA DeviceInfoData) 01681 { 01682 BOOL ret; 01683 LPWSTR DeviceNameW = NULL; 01684 LPWSTR DeviceDescriptionW = NULL; 01685 01686 TRACE("\n"); 01687 01688 if (DeviceName) 01689 { 01690 DeviceNameW = pSetupMultiByteToUnicode(DeviceName, CP_ACP); 01691 if (DeviceNameW == NULL) return FALSE; 01692 } 01693 if (DeviceDescription) 01694 { 01695 DeviceDescriptionW = pSetupMultiByteToUnicode(DeviceDescription, CP_ACP); 01696 if (DeviceDescriptionW == NULL) 01697 { 01698 MyFree(DeviceNameW); 01699 return FALSE; 01700 } 01701 } 01702 01703 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW, 01704 hwndParent, CreationFlags, DeviceInfoData); 01705 01706 MyFree(DeviceNameW); 01707 MyFree(DeviceDescriptionW); 01708 01709 return ret; 01710 } 01711 01712 /*********************************************************************** 01713 * SetupDiCreateDeviceInfoW (SETUPAPI.@) 01714 */ 01715 BOOL WINAPI SetupDiCreateDeviceInfoW( 01716 HDEVINFO DeviceInfoSet, 01717 PCWSTR DeviceName, 01718 CONST GUID *ClassGuid, 01719 PCWSTR DeviceDescription, 01720 HWND hwndParent, 01721 DWORD CreationFlags, 01722 PSP_DEVINFO_DATA DeviceInfoData) 01723 { 01724 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 01725 struct DeviceInfo *deviceInfo = NULL; 01726 BOOL ret = FALSE; 01727 CONFIGRET cr; 01728 DEVINST RootDevInst; 01729 DEVINST DevInst; 01730 01731 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName), 01732 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription), 01733 hwndParent, CreationFlags, DeviceInfoData); 01734 01735 if (!DeviceName) 01736 { 01737 SetLastError(ERROR_INVALID_DEVINST_NAME); 01738 return FALSE; 01739 } 01740 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 01741 { 01742 SetLastError(ERROR_INVALID_HANDLE); 01743 return FALSE; 01744 } 01745 if (!ClassGuid) 01746 { 01747 SetLastError(ERROR_INVALID_PARAMETER); 01748 return FALSE; 01749 } 01750 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 01751 { 01752 SetLastError(ERROR_INVALID_HANDLE); 01753 return FALSE; 01754 } 01755 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) && 01756 !IsEqualGUID(ClassGuid, &set->ClassGuid)) 01757 { 01758 SetLastError(ERROR_CLASS_MISMATCH); 01759 return FALSE; 01760 } 01761 if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS)) 01762 { 01763 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS)); 01764 SetLastError(ERROR_INVALID_FLAGS); 01765 return FALSE; 01766 } 01767 01768 /* Get the root device instance */ 01769 cr = CM_Locate_DevInst_ExW(&RootDevInst, 01770 NULL, 01771 CM_LOCATE_DEVINST_NORMAL, 01772 set->hMachine); 01773 if (cr != CR_SUCCESS) 01774 { 01775 SetLastError(ERROR_INVALID_DATA); 01776 return FALSE; 01777 } 01778 01779 /* Create the new device instance */ 01780 cr = CM_Create_DevInst_ExW(&DevInst, 01781 (DEVINSTID)DeviceName, 01782 RootDevInst, 01783 0, 01784 set->hMachine); 01785 if (cr != CR_SUCCESS) 01786 { 01787 SetLastError(GetErrorCodeFromCrCode(cr)); 01788 return FALSE; 01789 } 01790 01791 if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo)) 01792 { 01793 InsertTailList(&set->ListHead, &deviceInfo->ListEntry); 01794 01795 if (!DeviceInfoData) 01796 ret = TRUE; 01797 else 01798 { 01799 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 01800 { 01801 SetLastError(ERROR_INVALID_USER_BUFFER); 01802 } 01803 else 01804 { 01805 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID)); 01806 DeviceInfoData->DevInst = deviceInfo->dnDevInst; 01807 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo; 01808 ret = TRUE; 01809 } 01810 } 01811 } 01812 01813 if (ret == FALSE) 01814 { 01815 if (deviceInfo != NULL) 01816 { 01817 /* Remove deviceInfo from List */ 01818 RemoveEntryList(&deviceInfo->ListEntry); 01819 01820 /* Destroy deviceInfo */ 01821 DestroyDeviceInfo(deviceInfo); 01822 } 01823 } 01824 01825 TRACE("Returning %d\n", ret); 01826 return ret; 01827 } 01828 01829 /*********************************************************************** 01830 * SetupDiRegisterDeviceInfo (SETUPAPI.@) 01831 */ 01832 BOOL WINAPI SetupDiRegisterDeviceInfo( 01833 HDEVINFO DeviceInfoSet, 01834 PSP_DEVINFO_DATA DeviceInfoData, 01835 DWORD Flags, 01836 PSP_DETSIG_CMPPROC CompareProc, 01837 PVOID CompareContext, 01838 PSP_DEVINFO_DATA DupDeviceInfoData) 01839 { 01840 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 01841 WCHAR DevInstId[MAX_DEVICE_ID_LEN]; 01842 DEVINST ParentDevInst; 01843 CONFIGRET cr; 01844 DWORD dwError = ERROR_SUCCESS; 01845 01846 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags, 01847 CompareProc, CompareContext, DupDeviceInfoData); 01848 01849 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 01850 { 01851 SetLastError(ERROR_INVALID_HANDLE); 01852 return FALSE; 01853 } 01854 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 01855 { 01856 SetLastError(ERROR_INVALID_HANDLE); 01857 return FALSE; 01858 } 01859 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 01860 || !DeviceInfoData->Reserved) 01861 { 01862 SetLastError(ERROR_INVALID_PARAMETER); 01863 return FALSE; 01864 } 01865 01866 if (Flags & ~SPRDI_FIND_DUPS) 01867 { 01868 TRACE("Unknown flags: 0x%08lx\n", Flags & ~SPRDI_FIND_DUPS); 01869 SetLastError(ERROR_INVALID_FLAGS); 01870 return FALSE; 01871 } 01872 01873 if (Flags & SPRDI_FIND_DUPS) 01874 { 01875 FIXME("Unimplemented codepath!\n"); 01876 } 01877 01878 CM_Get_Device_ID_Ex(DeviceInfoData->DevInst, 01879 DevInstId, 01880 MAX_DEVICE_ID_LEN, 01881 0, 01882 set->hMachine); 01883 01884 CM_Get_Parent_Ex(&ParentDevInst, 01885 DeviceInfoData->DevInst, 01886 0, 01887 set->hMachine); 01888 01889 cr = CM_Create_DevInst_Ex(&DeviceInfoData->DevInst, 01890 DevInstId, 01891 ParentDevInst, 01892 CM_CREATE_DEVINST_NORMAL | CM_CREATE_DEVINST_DO_NOT_INSTALL, 01893 set->hMachine); 01894 if (cr != CR_SUCCESS) 01895 { 01896 dwError = ERROR_NO_SUCH_DEVINST; 01897 } 01898 01899 SetLastError(dwError); 01900 01901 return (dwError == ERROR_SUCCESS); 01902 } 01903 01904 /*********************************************************************** 01905 * SetupDiEnumDeviceInfo (SETUPAPI.@) 01906 */ 01907 BOOL WINAPI SetupDiEnumDeviceInfo( 01908 HDEVINFO devinfo, 01909 DWORD index, 01910 PSP_DEVINFO_DATA info) 01911 { 01912 BOOL ret = FALSE; 01913 01914 TRACE("%p %d %p\n", devinfo, index, info); 01915 01916 if(info==NULL) 01917 { 01918 SetLastError(ERROR_INVALID_PARAMETER); 01919 return FALSE; 01920 } 01921 if (devinfo && devinfo != INVALID_HANDLE_VALUE) 01922 { 01923 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; 01924 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC) 01925 { 01926 if (info->cbSize != sizeof(SP_DEVINFO_DATA)) 01927 SetLastError(ERROR_INVALID_USER_BUFFER); 01928 else 01929 { 01930 PLIST_ENTRY ItemList = list->ListHead.Flink; 01931 while (ItemList != &list->ListHead && index-- > 0) 01932 ItemList = ItemList->Flink; 01933 if (ItemList == &list->ListHead) 01934 SetLastError(ERROR_NO_MORE_ITEMS); 01935 else 01936 { 01937 struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 01938 memcpy(&info->ClassGuid, 01939 &DevInfo->ClassGuid, 01940 sizeof(GUID)); 01941 info->DevInst = DevInfo->dnDevInst; 01942 info->Reserved = (ULONG_PTR)DevInfo; 01943 ret = TRUE; 01944 } 01945 } 01946 } 01947 else 01948 SetLastError(ERROR_INVALID_HANDLE); 01949 } 01950 else 01951 SetLastError(ERROR_INVALID_HANDLE); 01952 return ret; 01953 } 01954 01955 /*********************************************************************** 01956 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@) 01957 */ 01958 BOOL WINAPI SetupDiGetDeviceInstanceIdA( 01959 HDEVINFO DeviceInfoSet, 01960 PSP_DEVINFO_DATA DeviceInfoData, 01961 PSTR DeviceInstanceId, 01962 DWORD DeviceInstanceIdSize, 01963 PDWORD RequiredSize) 01964 { 01965 BOOL ret = FALSE; 01966 DWORD size; 01967 PWSTR instanceId; 01968 01969 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId, 01970 DeviceInstanceIdSize, RequiredSize); 01971 01972 if (!DeviceInstanceId && DeviceInstanceIdSize > 0) 01973 { 01974 SetLastError(ERROR_INVALID_PARAMETER); 01975 return FALSE; 01976 } 01977 01978 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, 01979 DeviceInfoData, 01980 NULL, 01981 0, 01982 &size); 01983 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 01984 return FALSE; 01985 instanceId = MyMalloc(size * sizeof(WCHAR)); 01986 if (instanceId) 01987 { 01988 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, 01989 DeviceInfoData, 01990 instanceId, 01991 size, 01992 &size); 01993 if (ret) 01994 { 01995 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1, 01996 DeviceInstanceId, 01997 DeviceInstanceIdSize, NULL, NULL); 01998 01999 if (!len) 02000 ret = FALSE; 02001 else 02002 { 02003 if (len > DeviceInstanceIdSize) 02004 { 02005 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02006 ret = FALSE; 02007 } 02008 if (RequiredSize) 02009 *RequiredSize = len; 02010 } 02011 } 02012 MyFree(instanceId); 02013 } 02014 else 02015 { 02016 if (RequiredSize) 02017 *RequiredSize = size; 02018 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02019 ret = FALSE; 02020 } 02021 return ret; 02022 } 02023 02024 /*********************************************************************** 02025 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@) 02026 */ 02027 BOOL WINAPI SetupDiGetDeviceInstanceIdW( 02028 HDEVINFO DeviceInfoSet, 02029 PSP_DEVINFO_DATA DeviceInfoData, 02030 PWSTR DeviceInstanceId, 02031 DWORD DeviceInstanceIdSize, 02032 PDWORD RequiredSize) 02033 { 02034 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 02035 struct DeviceInfo *devInfo; 02036 02037 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId, 02038 DeviceInstanceIdSize, RequiredSize); 02039 02040 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 02041 { 02042 SetLastError(ERROR_INVALID_HANDLE); 02043 return FALSE; 02044 } 02045 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02046 { 02047 SetLastError(ERROR_INVALID_HANDLE); 02048 return FALSE; 02049 } 02050 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 02051 || !DeviceInfoData->Reserved) 02052 { 02053 SetLastError(ERROR_INVALID_PARAMETER); 02054 return FALSE; 02055 } 02056 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 02057 if (!DeviceInstanceId && DeviceInstanceIdSize > 0) 02058 { 02059 SetLastError(ERROR_INVALID_PARAMETER); 02060 return FALSE; 02061 } 02062 if (DeviceInstanceId && DeviceInstanceIdSize == 0) 02063 { 02064 SetLastError(ERROR_INVALID_PARAMETER); 02065 return FALSE; 02066 } 02067 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId)); 02068 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1) 02069 { 02070 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02071 if (RequiredSize) 02072 *RequiredSize = lstrlenW(devInfo->instanceId) + 1; 02073 return FALSE; 02074 } 02075 lstrcpyW(DeviceInstanceId, devInfo->instanceId); 02076 if (RequiredSize) 02077 *RequiredSize = lstrlenW(devInfo->instanceId) + 1; 02078 return TRUE; 02079 } 02080 02081 /*********************************************************************** 02082 * SetupDiGetActualSectionToInstallA (SETUPAPI.@) 02083 */ 02084 BOOL WINAPI SetupDiGetActualSectionToInstallA( 02085 HINF InfHandle, 02086 PCSTR InfSectionName, 02087 PSTR InfSectionWithExt, 02088 DWORD InfSectionWithExtSize, 02089 PDWORD RequiredSize, 02090 PSTR *Extension) 02091 { 02092 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName, 02093 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize, 02094 Extension, NULL); 02095 } 02096 02097 /*********************************************************************** 02098 * SetupDiGetActualSectionToInstallW (SETUPAPI.@) 02099 */ 02100 BOOL WINAPI SetupDiGetActualSectionToInstallW( 02101 HINF InfHandle, 02102 PCWSTR InfSectionName, 02103 PWSTR InfSectionWithExt, 02104 DWORD InfSectionWithExtSize, 02105 PDWORD RequiredSize, 02106 PWSTR *Extension) 02107 { 02108 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName, 02109 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize, 02110 Extension, NULL); 02111 } 02112 02113 /*********************************************************************** 02114 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@) 02115 */ 02116 BOOL WINAPI 02117 SetupDiGetActualSectionToInstallExA( 02118 IN HINF InfHandle, 02119 IN PCSTR InfSectionName, 02120 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL, 02121 OUT PSTR InfSectionWithExt OPTIONAL, 02122 IN DWORD InfSectionWithExtSize, 02123 OUT PDWORD RequiredSize OPTIONAL, 02124 OUT PSTR* Extension OPTIONAL, 02125 IN PVOID Reserved) 02126 { 02127 LPWSTR InfSectionNameW = NULL; 02128 LPWSTR InfSectionWithExtW = NULL; 02129 PWSTR ExtensionW; 02130 BOOL bResult = FALSE; 02131 02132 TRACE("\n"); 02133 02134 if (InfSectionName) 02135 { 02136 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP); 02137 if (InfSectionNameW == NULL) 02138 goto cleanup; 02139 } 02140 if (InfSectionWithExt) 02141 { 02142 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR)); 02143 if (InfSectionWithExtW == NULL) 02144 goto cleanup; 02145 } 02146 02147 bResult = SetupDiGetActualSectionToInstallExW( 02148 InfHandle, InfSectionNameW, AlternatePlatformInfo, 02149 InfSectionWithExt ? InfSectionWithExtW : NULL, 02150 InfSectionWithExtSize, 02151 RequiredSize, 02152 Extension ? &ExtensionW : NULL, 02153 Reserved); 02154 02155 if (bResult && InfSectionWithExt) 02156 { 02157 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt, 02158 InfSectionWithExtSize, NULL, NULL) != 0; 02159 } 02160 if (bResult && Extension) 02161 { 02162 if (ExtensionW == NULL) 02163 *Extension = NULL; 02164 else 02165 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW]; 02166 } 02167 02168 cleanup: 02169 MyFree(InfSectionNameW); 02170 MyFree(InfSectionWithExtW); 02171 02172 return bResult; 02173 } 02174 02175 /*********************************************************************** 02176 * SetupDiGetClassDescriptionA (SETUPAPI.@) 02177 */ 02178 BOOL WINAPI SetupDiGetClassDescriptionA( 02179 const GUID* ClassGuid, 02180 PSTR ClassDescription, 02181 DWORD ClassDescriptionSize, 02182 PDWORD RequiredSize) 02183 { 02184 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription, 02185 ClassDescriptionSize, 02186 RequiredSize, NULL, NULL); 02187 } 02188 02189 /*********************************************************************** 02190 * SetupDiGetClassDescriptionW (SETUPAPI.@) 02191 */ 02192 BOOL WINAPI SetupDiGetClassDescriptionW( 02193 const GUID* ClassGuid, 02194 PWSTR ClassDescription, 02195 DWORD ClassDescriptionSize, 02196 PDWORD RequiredSize) 02197 { 02198 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription, 02199 ClassDescriptionSize, 02200 RequiredSize, NULL, NULL); 02201 } 02202 02203 /*********************************************************************** 02204 * SetupDiGetClassDescriptionExA (SETUPAPI.@) 02205 */ 02206 BOOL WINAPI SetupDiGetClassDescriptionExA( 02207 const GUID* ClassGuid, 02208 PSTR ClassDescription, 02209 DWORD ClassDescriptionSize, 02210 PDWORD RequiredSize, 02211 PCSTR MachineName, 02212 PVOID Reserved) 02213 { 02214 PWCHAR ClassDescriptionW = NULL; 02215 LPWSTR MachineNameW = NULL; 02216 BOOL ret = FALSE; 02217 02218 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription, 02219 ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved); 02220 02221 if (ClassDescriptionSize > 0) 02222 { 02223 ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR)); 02224 if (!ClassDescriptionW) 02225 { 02226 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 02227 goto cleanup; 02228 } 02229 } 02230 02231 if (MachineName) 02232 { 02233 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 02234 if (!MachineNameW) 02235 { 02236 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 02237 goto cleanup; 02238 } 02239 } 02240 02241 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW, 02242 ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved); 02243 if (ret) 02244 { 02245 DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription, 02246 ClassDescriptionSize, NULL, NULL); 02247 if (len == 0 || len > ClassDescriptionSize) 02248 { 02249 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02250 ret = FALSE; 02251 } 02252 } 02253 02254 cleanup: 02255 MyFree(ClassDescriptionW); 02256 MyFree(MachineNameW); 02257 return ret; 02258 } 02259 02260 /*********************************************************************** 02261 * SetupDiGetClassDescriptionExW (SETUPAPI.@) 02262 */ 02263 BOOL WINAPI SetupDiGetClassDescriptionExW( 02264 const GUID* ClassGuid, 02265 PWSTR ClassDescription, 02266 DWORD ClassDescriptionSize, 02267 PDWORD RequiredSize, 02268 PCWSTR MachineName, 02269 PVOID Reserved) 02270 { 02271 HKEY hKey; 02272 DWORD dwLength; 02273 DWORD dwRegType; 02274 LONG rc; 02275 PWSTR Buffer; 02276 02277 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription, 02278 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved); 02279 02280 /* Make sure there's a GUID */ 02281 if (!ClassGuid) 02282 { 02283 SetLastError(ERROR_INVALID_PARAMETER); 02284 return FALSE; 02285 } 02286 02287 /* Make sure there's a real buffer when there's a size */ 02288 if (!ClassDescription && ClassDescriptionSize > 0) 02289 { 02290 SetLastError(ERROR_INVALID_PARAMETER); 02291 return FALSE; 02292 } 02293 02294 /* Open the key for the GUID */ 02295 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, 02296 KEY_QUERY_VALUE, 02297 DIOCR_INSTALLER, 02298 MachineName, 02299 Reserved); 02300 if (hKey == INVALID_HANDLE_VALUE) 02301 return FALSE; 02302 02303 /* Retrieve the class description data and close the key */ 02304 rc = QueryRegistryValue(hKey, NULL, (LPBYTE *) &Buffer, &dwRegType, &dwLength); 02305 RegCloseKey(hKey); 02306 02307 /* Make sure we got the data */ 02308 if (rc != ERROR_SUCCESS) 02309 { 02310 SetLastError(rc); 02311 return FALSE; 02312 } 02313 02314 /* Make sure the data is a string */ 02315 if (dwRegType != REG_SZ) 02316 { 02317 MyFree(Buffer); 02318 SetLastError(ERROR_GEN_FAILURE); 02319 return FALSE; 02320 } 02321 02322 /* Determine the length of the class description */ 02323 dwLength /= sizeof(WCHAR); 02324 02325 /* Count the null-terminator if none is present */ 02326 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL)) 02327 dwLength++; 02328 02329 /* Inform the caller about the class description */ 02330 if ((ClassDescription != NULL) && (dwLength <= ClassDescriptionSize)) 02331 { 02332 memcpy(ClassDescription, Buffer, (dwLength - 1) * sizeof(WCHAR)); 02333 ClassDescription[dwLength - 1] = UNICODE_NULL; 02334 } 02335 02336 /* Inform the caller about the required size */ 02337 if (RequiredSize != NULL) 02338 *RequiredSize = dwLength; 02339 02340 /* Clean up the buffer */ 02341 MyFree(Buffer); 02342 02343 /* Make sure the buffer was large enough */ 02344 if ((ClassDescription == NULL) || (dwLength > ClassDescriptionSize)) 02345 { 02346 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02347 return FALSE; 02348 } 02349 02350 return TRUE; 02351 } 02352 02353 /*********************************************************************** 02354 * SetupDiGetClassDevsA (SETUPAPI.@) 02355 */ 02356 HDEVINFO WINAPI SetupDiGetClassDevsA( 02357 CONST GUID *class, 02358 LPCSTR enumstr, 02359 HWND parent, 02360 DWORD flags) 02361 { 02362 return SetupDiGetClassDevsExA(class, enumstr, parent, 02363 flags, NULL, NULL, NULL); 02364 } 02365 02366 /*********************************************************************** 02367 * SetupDiGetClassDevsExA (SETUPAPI.@) 02368 */ 02369 HDEVINFO WINAPI SetupDiGetClassDevsExA( 02370 const GUID *class, 02371 PCSTR enumstr, 02372 HWND parent, 02373 DWORD flags, 02374 HDEVINFO deviceset, 02375 PCSTR machine, 02376 PVOID reserved) 02377 { 02378 HDEVINFO ret; 02379 LPWSTR enumstrW = NULL, machineW = NULL; 02380 02381 if (enumstr) 02382 { 02383 enumstrW = pSetupMultiByteToUnicode(enumstr, CP_ACP); 02384 if (!enumstrW) 02385 { 02386 ret = INVALID_HANDLE_VALUE; 02387 goto end; 02388 } 02389 } 02390 if (machine) 02391 { 02392 machineW = pSetupMultiByteToUnicode(machine, CP_ACP); 02393 if (!machineW) 02394 { 02395 MyFree(enumstrW); 02396 ret = INVALID_HANDLE_VALUE; 02397 goto end; 02398 } 02399 } 02400 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset, 02401 machineW, reserved); 02402 MyFree(enumstrW); 02403 MyFree(machineW); 02404 02405 end: 02406 return ret; 02407 } 02408 02409 /*********************************************************************** 02410 * SetupDiGetClassDevsW (SETUPAPI.@) 02411 */ 02412 HDEVINFO WINAPI SetupDiGetClassDevsW( 02413 CONST GUID *class, 02414 LPCWSTR enumstr, 02415 HWND parent, 02416 DWORD flags) 02417 { 02418 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL, 02419 NULL); 02420 } 02421 02422 /*********************************************************************** 02423 * SetupDiGetClassDevsExW (SETUPAPI.@) 02424 */ 02425 HDEVINFO WINAPI SetupDiGetClassDevsExW( 02426 CONST GUID *class, 02427 PCWSTR enumstr, 02428 HWND parent, 02429 DWORD flags, 02430 HDEVINFO deviceset, 02431 PCWSTR machine, 02432 PVOID reserved) 02433 { 02434 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; 02435 struct DeviceInfoSet *list; 02436 CONST GUID *pClassGuid; 02437 LONG rc; 02438 HDEVINFO set = INVALID_HANDLE_VALUE; 02439 02440 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class), 02441 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine), 02442 reserved); 02443 02444 if (!(flags & DIGCF_ALLCLASSES) && !class) 02445 { 02446 SetLastError(ERROR_INVALID_PARAMETER); 02447 return INVALID_HANDLE_VALUE; 02448 } 02449 02450 /* Create the deviceset if not set */ 02451 if (deviceset) 02452 { 02453 list = (struct DeviceInfoSet *)deviceset; 02454 if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02455 { 02456 SetLastError(ERROR_INVALID_HANDLE); 02457 goto cleanup; 02458 } 02459 hDeviceInfo = deviceset; 02460 } 02461 else 02462 { 02463 hDeviceInfo = SetupDiCreateDeviceInfoListExW( 02464 flags & (DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES) ? NULL : class, 02465 NULL, machine, NULL); 02466 if (hDeviceInfo == INVALID_HANDLE_VALUE) 02467 goto cleanup; 02468 list = (struct DeviceInfoSet *)hDeviceInfo; 02469 } 02470 02471 if (flags & DIGCF_PROFILE) 02472 FIXME(": flag DIGCF_PROFILE ignored\n"); 02473 02474 if (flags & DIGCF_DEVICEINTERFACE) 02475 { 02476 if (!class) 02477 { 02478 SetLastError(ERROR_INVALID_PARAMETER); 02479 goto cleanup; 02480 } 02481 rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT); 02482 } 02483 else 02484 { 02485 /* Determine which class(es) should be included in the deviceset */ 02486 if (flags & DIGCF_ALLCLASSES) 02487 { 02488 /* The caller wants all classes. Check if 02489 * the deviceset limits us to one class */ 02490 if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 02491 pClassGuid = NULL; 02492 else 02493 pClassGuid = &list->ClassGuid; 02494 } 02495 else if (class) 02496 { 02497 /* The caller wants one class. Check if it matches deviceset class */ 02498 if (IsEqualIID(&list->ClassGuid, class) 02499 || IsEqualIID(&list->ClassGuid, &GUID_NULL)) 02500 { 02501 pClassGuid = class; 02502 } 02503 else 02504 { 02505 SetLastError(ERROR_INVALID_PARAMETER); 02506 goto cleanup; 02507 } 02508 } 02509 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL)) 02510 { 02511 /* No class specified. Try to use the one of the deviceset */ 02512 if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 02513 pClassGuid = &list->ClassGuid; 02514 else 02515 { 02516 SetLastError(ERROR_INVALID_PARAMETER); 02517 goto cleanup; 02518 } 02519 } 02520 else 02521 { 02522 SetLastError(ERROR_INVALID_PARAMETER); 02523 goto cleanup; 02524 } 02525 rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr); 02526 } 02527 if (rc != ERROR_SUCCESS) 02528 { 02529 SetLastError(rc); 02530 goto cleanup; 02531 } 02532 set = hDeviceInfo; 02533 02534 cleanup: 02535 if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set) 02536 SetupDiDestroyDeviceInfoList(hDeviceInfo); 02537 return set; 02538 } 02539 02540 /*********************************************************************** 02541 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@) 02542 */ 02543 BOOL WINAPI SetupDiGetDeviceInfoListDetailA( 02544 HDEVINFO DeviceInfoSet, 02545 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData ) 02546 { 02547 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 02548 02549 TRACE("%p %p\n", DeviceInfoSet, DevInfoData); 02550 02551 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 02552 { 02553 SetLastError(ERROR_INVALID_HANDLE); 02554 return FALSE; 02555 } 02556 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02557 { 02558 SetLastError(ERROR_INVALID_HANDLE); 02559 return FALSE; 02560 } 02561 if (!DevInfoData || 02562 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A)) 02563 { 02564 SetLastError(ERROR_INVALID_PARAMETER); 02565 return FALSE; 02566 } 02567 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID)); 02568 DevInfoData->RemoteMachineHandle = set->hMachine; 02569 if (set->MachineName) 02570 { 02571 FIXME("Stub\n"); 02572 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 02573 return FALSE; 02574 } 02575 else 02576 DevInfoData->RemoteMachineName[0] = 0; 02577 02578 return TRUE; 02579 } 02580 02581 /*********************************************************************** 02582 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@) 02583 */ 02584 BOOL WINAPI SetupDiGetDeviceInfoListDetailW( 02585 HDEVINFO DeviceInfoSet, 02586 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData ) 02587 { 02588 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 02589 02590 TRACE("%p %p\n", DeviceInfoSet, DevInfoData); 02591 02592 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 02593 { 02594 SetLastError(ERROR_INVALID_HANDLE); 02595 return FALSE; 02596 } 02597 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02598 { 02599 SetLastError(ERROR_INVALID_HANDLE); 02600 return FALSE; 02601 } 02602 if (!DevInfoData || 02603 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W)) 02604 { 02605 SetLastError(ERROR_INVALID_PARAMETER); 02606 return FALSE; 02607 } 02608 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID)); 02609 DevInfoData->RemoteMachineHandle = set->hMachine; 02610 if (set->MachineName) 02611 strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2); 02612 else 02613 DevInfoData->RemoteMachineName[0] = 0; 02614 02615 return TRUE; 02616 } 02617 02618 /*********************************************************************** 02619 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@) 02620 */ 02621 BOOL WINAPI SetupDiCreateDeviceInterfaceA( 02622 HDEVINFO DeviceInfoSet, 02623 PSP_DEVINFO_DATA DeviceInfoData, 02624 const GUID *InterfaceClassGuid, 02625 PCSTR ReferenceString, 02626 DWORD CreationFlags, 02627 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 02628 { 02629 BOOL ret; 02630 LPWSTR ReferenceStringW = NULL; 02631 02632 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData, 02633 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString), 02634 CreationFlags, DeviceInterfaceData); 02635 02636 if (ReferenceString) 02637 { 02638 ReferenceStringW = pSetupMultiByteToUnicode(ReferenceString, CP_ACP); 02639 if (ReferenceStringW == NULL) return FALSE; 02640 } 02641 02642 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData, 02643 InterfaceClassGuid, ReferenceStringW, CreationFlags, 02644 DeviceInterfaceData); 02645 02646 MyFree(ReferenceStringW); 02647 02648 return ret; 02649 } 02650 02651 /*********************************************************************** 02652 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@) 02653 */ 02654 BOOL WINAPI SetupDiCreateDeviceInterfaceW( 02655 HDEVINFO DeviceInfoSet, 02656 PSP_DEVINFO_DATA DeviceInfoData, 02657 const GUID *InterfaceClassGuid, 02658 PCWSTR ReferenceString, 02659 DWORD CreationFlags, 02660 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 02661 { 02662 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 02663 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData, 02664 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString), 02665 CreationFlags, DeviceInterfaceData); 02666 02667 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 02668 { 02669 SetLastError(ERROR_INVALID_HANDLE); 02670 return FALSE; 02671 } 02672 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02673 { 02674 SetLastError(ERROR_INVALID_HANDLE); 02675 return FALSE; 02676 } 02677 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 02678 || !DeviceInfoData->Reserved) 02679 { 02680 SetLastError(ERROR_INVALID_PARAMETER); 02681 return FALSE; 02682 } 02683 if (!InterfaceClassGuid) 02684 { 02685 SetLastError(ERROR_INVALID_USER_BUFFER); 02686 return FALSE; 02687 } 02688 02689 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData, 02690 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString), 02691 CreationFlags, DeviceInterfaceData); 02692 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 02693 return FALSE; 02694 } 02695 02696 /*********************************************************************** 02697 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@) 02698 */ 02699 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA( 02700 HDEVINFO DeviceInfoSet, 02701 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 02702 DWORD Reserved, 02703 REGSAM samDesired, 02704 HINF InfHandle, 02705 PCSTR InfSectionName) 02706 { 02707 HKEY key; 02708 PWSTR InfSectionNameW = NULL; 02709 02710 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved, 02711 samDesired, InfHandle, InfSectionName); 02712 if (InfHandle) 02713 { 02714 if (!InfSectionName) 02715 { 02716 SetLastError(ERROR_INVALID_PARAMETER); 02717 return INVALID_HANDLE_VALUE; 02718 } 02719 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP); 02720 if (!InfSectionNameW) 02721 return INVALID_HANDLE_VALUE; 02722 } 02723 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet, 02724 DeviceInterfaceData, Reserved, samDesired, InfHandle, 02725 InfSectionNameW); 02726 MyFree(InfSectionNameW); 02727 return key; 02728 } 02729 02730 /*********************************************************************** 02731 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@) 02732 */ 02733 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW( 02734 HDEVINFO DeviceInfoSet, 02735 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 02736 DWORD Reserved, 02737 REGSAM samDesired, 02738 HINF InfHandle, 02739 PCWSTR InfSectionName) 02740 { 02741 HKEY hKey, hDevKey; 02742 LPWSTR SymbolicLink; 02743 DWORD Length, Index; 02744 LONG rc; 02745 WCHAR bracedGuidString[39]; 02746 struct DeviceInterface *DevItf; 02747 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 02748 02749 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved, 02750 samDesired, InfHandle, InfSectionName); 02751 02752 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 02753 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02754 { 02755 SetLastError(ERROR_INVALID_HANDLE); 02756 return INVALID_HANDLE_VALUE; 02757 } 02758 if (!DeviceInterfaceData || 02759 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 02760 !DeviceInterfaceData->Reserved) 02761 { 02762 SetLastError(ERROR_INVALID_PARAMETER); 02763 return INVALID_HANDLE_VALUE; 02764 } 02765 if (InfHandle && !InfSectionName) 02766 { 02767 SetLastError(ERROR_INVALID_PARAMETER); 02768 return INVALID_HANDLE_VALUE; 02769 } 02770 02771 hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL); 02772 if (hKey == INVALID_HANDLE_VALUE) 02773 { 02774 hKey = SetupDiOpenClassRegKeyExW(NULL, samDesired, DIOCR_INTERFACE, NULL, NULL); 02775 if (hKey == INVALID_HANDLE_VALUE) 02776 { 02777 SetLastError(ERROR_INVALID_PARAMETER); 02778 return INVALID_HANDLE_VALUE; 02779 } 02780 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString); 02781 02782 if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS) 02783 { 02784 SetLastError(ERROR_INVALID_PARAMETER); 02785 return INVALID_HANDLE_VALUE; 02786 } 02787 RegCloseKey(hKey); 02788 hKey = hDevKey; 02789 } 02790 02791 DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved; 02792 02793 Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR); 02794 SymbolicLink = HeapAlloc(GetProcessHeap(), 0, Length); 02795 if (!SymbolicLink) 02796 { 02797 RegCloseKey(hKey); 02798 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 02799 return INVALID_HANDLE_VALUE; 02800 } 02801 02802 wcscpy(SymbolicLink, DevItf->SymbolicLink); 02803 02804 Index = 0; 02805 while(SymbolicLink[Index]) 02806 { 02807 if (SymbolicLink[Index] == L'\\') 02808 { 02809 SymbolicLink[Index] = L'#'; 02810 } 02811 Index++; 02812 } 02813 02814 rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL); 02815 02816 RegCloseKey(hKey); 02817 HeapFree(GetProcessHeap(), 0, SymbolicLink); 02818 02819 if (rc == ERROR_SUCCESS) 02820 { 02821 if (InfHandle && InfSectionName) 02822 { 02823 if (!SetupInstallFromInfSection(NULL /*FIXME */, 02824 InfHandle, 02825 InfSectionName, 02826 SPINST_INIFILES | SPINST_REGISTRY | SPINST_INI2REG | SPINST_FILES | SPINST_BITREG | SPINST_REGSVR | SPINST_UNREGSVR | SPINST_PROFILEITEMS | SPINST_COPYINF, 02827 hDevKey, 02828 NULL, 02829 0, 02830 set->SelectedDevice->InstallParams.InstallMsgHandler, 02831 set->SelectedDevice->InstallParams.InstallMsgHandlerContext, 02832 INVALID_HANDLE_VALUE, 02833 NULL)) 02834 { 02835 RegCloseKey(hDevKey); 02836 return INVALID_HANDLE_VALUE; 02837 } 02838 } 02839 } 02840 02841 SetLastError(rc); 02842 return hDevKey; 02843 } 02844 02845 /*********************************************************************** 02846 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@) 02847 */ 02848 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey( 02849 HDEVINFO DeviceInfoSet, 02850 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 02851 DWORD Reserved) 02852 { 02853 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 02854 BOOL ret = FALSE; 02855 02856 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved); 02857 02858 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 02859 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02860 { 02861 SetLastError(ERROR_INVALID_HANDLE); 02862 return FALSE; 02863 } 02864 if (!DeviceInterfaceData || 02865 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 02866 !DeviceInterfaceData->Reserved) 02867 { 02868 SetLastError(ERROR_INVALID_PARAMETER); 02869 return FALSE; 02870 } 02871 02872 FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved); 02873 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 02874 return ret; 02875 } 02876 02877 /*********************************************************************** 02878 * SetupDiEnumDeviceInterfaces (SETUPAPI.@) 02879 * 02880 * PARAMS 02881 * DeviceInfoSet [I] Set of devices from which to enumerate 02882 * interfaces 02883 * DeviceInfoData [I] (Optional) If specified, a specific device 02884 * instance from which to enumerate interfaces. 02885 * If it isn't specified, all interfaces for all 02886 * devices in the set are enumerated. 02887 * InterfaceClassGuid [I] The interface class to enumerate. 02888 * MemberIndex [I] An index of the interface instance to enumerate. 02889 * A caller should start with MemberIndex set to 0, 02890 * and continue until the function fails with 02891 * ERROR_NO_MORE_ITEMS. 02892 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize 02893 * member must be set to 02894 * sizeof(SP_DEVICE_INTERFACE_DATA). 02895 * 02896 * RETURNS 02897 * Success: non-zero value. 02898 * Failure: FALSE. Call GetLastError() for more info. 02899 */ 02900 BOOL WINAPI SetupDiEnumDeviceInterfaces( 02901 HDEVINFO DeviceInfoSet, 02902 PSP_DEVINFO_DATA DeviceInfoData, 02903 CONST GUID * InterfaceClassGuid, 02904 DWORD MemberIndex, 02905 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 02906 { 02907 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 02908 BOOL ret = FALSE; 02909 02910 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData, 02911 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); 02912 02913 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 02914 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 02915 { 02916 SetLastError(ERROR_INVALID_HANDLE); 02917 return FALSE; 02918 } 02919 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) || 02920 !DeviceInfoData->Reserved)) 02921 { 02922 SetLastError(ERROR_INVALID_PARAMETER); 02923 return FALSE; 02924 } 02925 if (!DeviceInterfaceData || 02926 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) 02927 { 02928 SetLastError(ERROR_INVALID_PARAMETER); 02929 return FALSE; 02930 } 02931 if (DeviceInfoData) 02932 { 02933 struct DeviceInfo *devInfo = 02934 (struct DeviceInfo *)DeviceInfoData->Reserved; 02935 BOOL found = FALSE; 02936 PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink; 02937 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found) 02938 { 02939 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); 02940 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid)) 02941 { 02942 InterfaceListEntry = InterfaceListEntry->Flink; 02943 continue; 02944 } 02945 if (MemberIndex-- == 0) 02946 { 02947 /* return this item */ 02948 memcpy(&DeviceInterfaceData->InterfaceClassGuid, 02949 &DevItf->InterfaceClassGuid, 02950 sizeof(GUID)); 02951 DeviceInterfaceData->Flags = DevItf->Flags; 02952 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf; 02953 found = TRUE; 02954 ret = TRUE; 02955 } 02956 InterfaceListEntry = InterfaceListEntry->Flink; 02957 } 02958 if (!found) 02959 SetLastError(ERROR_NO_MORE_ITEMS); 02960 } 02961 else 02962 { 02963 BOOL found = FALSE; 02964 PLIST_ENTRY ItemList = set->ListHead.Flink; 02965 while (ItemList != &set->ListHead && !found) 02966 { 02967 PLIST_ENTRY InterfaceListEntry; 02968 struct DeviceInfo *devInfo = 02969 CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 02970 InterfaceListEntry = devInfo->InterfaceListHead.Flink; 02971 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found) 02972 { 02973 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); 02974 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid)) 02975 { 02976 InterfaceListEntry = InterfaceListEntry->Flink; 02977 continue; 02978 } 02979 if (MemberIndex-- == 0) 02980 { 02981 /* return this item */ 02982 memcpy(&DeviceInterfaceData->InterfaceClassGuid, 02983 &DevItf->InterfaceClassGuid, 02984 sizeof(GUID)); 02985 DeviceInterfaceData->Flags = DevItf->Flags; 02986 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf; 02987 found = TRUE; 02988 ret = TRUE; 02989 } 02990 InterfaceListEntry = InterfaceListEntry->Flink; 02991 } 02992 ItemList = ItemList->Flink; 02993 02994 } 02995 if (!found) 02996 SetLastError(ERROR_NO_MORE_ITEMS); 02997 } 02998 return ret; 02999 } 03000 03001 /*********************************************************************** 03002 * SetupDiDestroyDeviceInfoList (SETUPAPI.@) 03003 * 03004 * Destroy a DeviceInfoList and free all used memory of the list. 03005 * 03006 * PARAMS 03007 * devinfo [I] DeviceInfoList pointer to list to destroy 03008 * 03009 * RETURNS 03010 * Success: non zero value. 03011 * Failure: zero value. 03012 */ 03013 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo) 03014 { 03015 BOOL ret = FALSE; 03016 03017 TRACE("%p\n", devinfo); 03018 if (devinfo && devinfo != INVALID_HANDLE_VALUE) 03019 { 03020 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; 03021 03022 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC) 03023 { 03024 ret = DestroyDeviceInfoSet(list); 03025 } 03026 } 03027 03028 if (ret == FALSE) 03029 SetLastError(ERROR_INVALID_HANDLE); 03030 03031 return ret; 03032 } 03033 03034 /*********************************************************************** 03035 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@) 03036 */ 03037 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA( 03038 HDEVINFO DeviceInfoSet, 03039 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 03040 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData, 03041 DWORD DeviceInterfaceDetailDataSize, 03042 PDWORD RequiredSize, 03043 PSP_DEVINFO_DATA DeviceInfoData) 03044 { 03045 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 03046 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL; 03047 DWORD sizeW = 0, bytesNeeded; 03048 BOOL ret = FALSE; 03049 03050 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet, 03051 DeviceInterfaceData, DeviceInterfaceDetailData, 03052 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); 03053 03054 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 03055 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 03056 { 03057 SetLastError(ERROR_INVALID_HANDLE); 03058 return FALSE; 03059 } 03060 if (!DeviceInterfaceData || 03061 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 03062 !DeviceInterfaceData->Reserved) 03063 { 03064 SetLastError(ERROR_INVALID_PARAMETER); 03065 return FALSE; 03066 } 03067 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))) 03068 { 03069 SetLastError(ERROR_INVALID_USER_BUFFER); 03070 return FALSE; 03071 } 03072 03073 if((DeviceInterfaceDetailDataSize != 0) && 03074 (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(CHAR)))) 03075 { 03076 SetLastError(ERROR_INVALID_USER_BUFFER); 03077 return FALSE; 03078 } 03079 03080 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize) 03081 { 03082 SetLastError(ERROR_INVALID_USER_BUFFER); 03083 return FALSE; 03084 } 03085 03086 03087 if (DeviceInterfaceDetailData != NULL) 03088 { 03089 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) 03090 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR); 03091 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW); 03092 if (!DeviceInterfaceDetailDataW) 03093 { 03094 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03095 } 03096 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); 03097 } 03098 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW)) 03099 { 03100 ret = SetupDiGetDeviceInterfaceDetailW( 03101 DeviceInfoSet, 03102 DeviceInterfaceData, 03103 DeviceInterfaceDetailDataW, 03104 sizeW, 03105 &sizeW, 03106 DeviceInfoData); 03107 bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR) 03108 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath); 03109 if (RequiredSize) 03110 *RequiredSize = bytesNeeded; 03111 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize >= bytesNeeded) 03112 { 03113 if (!WideCharToMultiByte( 03114 CP_ACP, 0, 03115 DeviceInterfaceDetailDataW->DevicePath, -1, 03116 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath), 03117 NULL, NULL)) 03118 { 03119 ret = FALSE; 03120 } 03121 } 03122 } 03123 MyFree(DeviceInterfaceDetailDataW); 03124 03125 return ret; 03126 } 03127 03128 /*********************************************************************** 03129 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@) 03130 */ 03131 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW( 03132 HDEVINFO DeviceInfoSet, 03133 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 03134 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData, 03135 DWORD DeviceInterfaceDetailDataSize, 03136 PDWORD RequiredSize, 03137 PSP_DEVINFO_DATA DeviceInfoData) 03138 { 03139 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 03140 BOOL ret = FALSE; 03141 03142 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet, 03143 DeviceInterfaceData, DeviceInterfaceDetailData, 03144 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); 03145 03146 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || 03147 set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 03148 { 03149 SetLastError(ERROR_INVALID_HANDLE); 03150 return FALSE; 03151 } 03152 if (!DeviceInterfaceData || 03153 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || 03154 !DeviceInterfaceData->Reserved) 03155 { 03156 SetLastError(ERROR_INVALID_PARAMETER); 03157 return FALSE; 03158 } 03159 if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)) 03160 { 03161 SetLastError(ERROR_INVALID_USER_BUFFER); 03162 return FALSE; 03163 } 03164 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize) 03165 { 03166 SetLastError(ERROR_INVALID_USER_BUFFER); 03167 return FALSE; 03168 } 03169 if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 03170 { 03171 SetLastError(ERROR_INVALID_PARAMETER); 03172 return FALSE; 03173 } 03174 if ((DeviceInterfaceDetailData != NULL) 03175 && (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) + sizeof(WCHAR))) 03176 { 03177 SetLastError(ERROR_INVALID_PARAMETER); 03178 return FALSE; 03179 } 03180 else 03181 { 03182 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved; 03183 LPCWSTR devName = deviceInterface->SymbolicLink; 03184 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 03185 (lstrlenW(devName) + 1) * sizeof(WCHAR); 03186 03187 if (sizeRequired > DeviceInterfaceDetailDataSize) 03188 { 03189 SetLastError(ERROR_INSUFFICIENT_BUFFER); 03190 if (RequiredSize) 03191 *RequiredSize = sizeRequired; 03192 } 03193 else 03194 { 03195 strcpyW(DeviceInterfaceDetailData->DevicePath, devName); 03196 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath)); 03197 if (DeviceInfoData) 03198 { 03199 memcpy(&DeviceInfoData->ClassGuid, 03200 &deviceInterface->DeviceInfo->ClassGuid, 03201 sizeof(GUID)); 03202 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst; 03203 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo; 03204 } 03205 ret = TRUE; 03206 } 03207 } 03208 return ret; 03209 } 03210 03211 struct PropertyMapEntry 03212 { 03213 DWORD regType; 03214 LPCSTR nameA; 03215 LPCWSTR nameW; 03216 }; 03217 03218 static struct PropertyMapEntry PropertyMap[] = { 03219 { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC }, 03220 { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID }, 03221 { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS }, 03222 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */ 03223 { REG_SZ, "Service", REGSTR_VAL_SERVICE }, 03224 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */ 03225 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */ 03226 { REG_SZ, "Class", REGSTR_VAL_CLASS }, 03227 { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID }, 03228 { REG_SZ, "Driver", REGSTR_VAL_DRIVER }, 03229 { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS }, 03230 { REG_SZ, "Mfg", REGSTR_VAL_MFG }, 03231 { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME }, 03232 { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION }, 03233 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */ 03234 { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES }, 03235 { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER }, 03236 { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS }, 03237 { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS }, 03238 { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */ 03239 { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */ 03240 { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */ 03241 { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */ 03242 { REG_BINARY, "Security", REGSTR_SECURITY }, 03243 { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */ 03244 { 0, NULL, NULL }, /* SPDRP_DEVTYPE */ 03245 { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */ 03246 { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */ 03247 { 0, NULL, NULL }, /* SPDRP_ADDRESS */ 03248 { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT }, 03249 { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */ 03250 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */ 03251 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */ 03252 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */ 03253 { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */ 03254 }; 03255 03256 /*********************************************************************** 03257 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@) 03258 */ 03259 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA( 03260 HDEVINFO DeviceInfoSet, 03261 PSP_DEVINFO_DATA DeviceInfoData, 03262 DWORD Property, 03263 PDWORD PropertyRegDataType, 03264 PBYTE PropertyBuffer, 03265 DWORD PropertyBufferSize, 03266 PDWORD RequiredSize) 03267 { 03268 BOOL ret; 03269 BOOL bIsStringProperty; 03270 DWORD RegType; 03271 DWORD RequiredSizeA, RequiredSizeW; 03272 DWORD PropertyBufferSizeW = 0; 03273 PBYTE PropertyBufferW = NULL; 03274 03275 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, 03276 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, 03277 RequiredSize); 03278 03279 if (PropertyBufferSize != 0) 03280 { 03281 PropertyBufferSizeW = PropertyBufferSize * 2; 03282 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW); 03283 if (!PropertyBufferW) 03284 { 03285 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03286 return FALSE; 03287 } 03288 } 03289 03290 ret = SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, 03291 DeviceInfoData, 03292 Property, 03293 &RegType, 03294 PropertyBufferW, 03295 PropertyBufferSizeW, 03296 &RequiredSizeW); 03297 03298 if (ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER) 03299 { 03300 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ); 03301 03302 if (bIsStringProperty) 03303 RequiredSizeA = RequiredSizeW / sizeof(WCHAR); 03304 else 03305 RequiredSizeA = RequiredSizeW; 03306 if (RequiredSize) 03307 *RequiredSize = RequiredSizeA; 03308 if (PropertyRegDataType) 03309 *PropertyRegDataType = RegType; 03310 } 03311 03312 if (!ret) 03313 { 03314 HeapFree(GetProcessHeap(), 0, PropertyBufferW); 03315 return ret; 03316 } 03317 03318 if (RequiredSizeA <= PropertyBufferSize) 03319 { 03320 if (bIsStringProperty && PropertyBufferSize > 0) 03321 { 03322 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0) 03323 { 03324 /* Last error is already set by WideCharToMultiByte */ 03325 ret = FALSE; 03326 } 03327 } 03328 else 03329 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA); 03330 } 03331 else 03332 { 03333 SetLastError(ERROR_INSUFFICIENT_BUFFER); 03334 ret = FALSE; 03335 } 03336 03337 HeapFree(GetProcessHeap(), 0, PropertyBufferW); 03338 return ret; 03339 } 03340 03341 /*********************************************************************** 03342 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@) 03343 */ 03344 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW( 03345 HDEVINFO DeviceInfoSet, 03346 PSP_DEVINFO_DATA DeviceInfoData, 03347 DWORD Property, 03348 PDWORD PropertyRegDataType, 03349 PBYTE PropertyBuffer, 03350 DWORD PropertyBufferSize, 03351 PDWORD RequiredSize) 03352 { 03353 BOOL ret = FALSE; 03354 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 03355 struct DeviceInfo *devInfo; 03356 03357 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, 03358 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, 03359 RequiredSize); 03360 03361 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 03362 { 03363 SetLastError(ERROR_INVALID_HANDLE); 03364 return FALSE; 03365 } 03366 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 03367 { 03368 SetLastError(ERROR_INVALID_HANDLE); 03369 return FALSE; 03370 } 03371 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 03372 || !DeviceInfoData->Reserved) 03373 { 03374 SetLastError(ERROR_INVALID_PARAMETER); 03375 return FALSE; 03376 } 03377 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 03378 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0]) 03379 && PropertyMap[Property].nameW) 03380 { 03381 DWORD size = PropertyBufferSize; 03382 HKEY hKey; 03383 LONG l; 03384 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); 03385 if (hKey == INVALID_HANDLE_VALUE) 03386 return FALSE; 03387 l = RegQueryValueExW(hKey, PropertyMap[Property].nameW, 03388 NULL, PropertyRegDataType, PropertyBuffer, &size); 03389 RegCloseKey(hKey); 03390 03391 if (RequiredSize) 03392 *RequiredSize = size; 03393 switch(l) { 03394 case ERROR_SUCCESS: 03395 if (PropertyBuffer != NULL || size == 0) 03396 ret = TRUE; 03397 else 03398 SetLastError(ERROR_INSUFFICIENT_BUFFER); 03399 break; 03400 case ERROR_MORE_DATA: 03401 SetLastError(ERROR_INSUFFICIENT_BUFFER); 03402 break; 03403 default: 03404 SetLastError(l); 03405 } 03406 } 03407 else if (Property == SPDRP_PHYSICAL_DEVICE_OBJECT_NAME) 03408 { 03409 DWORD required = (strlenW(devInfo->Data) + 1) * sizeof(WCHAR); 03410 03411 if (PropertyRegDataType) 03412 *PropertyRegDataType = REG_SZ; 03413 if (RequiredSize) 03414 *RequiredSize = required; 03415 if (PropertyBufferSize >= required) 03416 { 03417 strcpyW((LPWSTR)PropertyBuffer, devInfo->Data); 03418 ret = TRUE; 03419 } 03420 else 03421 SetLastError(ERROR_INSUFFICIENT_BUFFER); 03422 } 03423 else 03424 { 03425 ERR("Property 0x%lx not implemented\n", Property); 03426 SetLastError(ERROR_NOT_SUPPORTED); 03427 } 03428 return ret; 03429 } 03430 03431 /*********************************************************************** 03432 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@) 03433 */ 03434 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA( 03435 HDEVINFO DeviceInfoSet, 03436 PSP_DEVINFO_DATA DeviceInfoData, 03437 DWORD Property, 03438 const BYTE *PropertyBuffer, 03439 DWORD PropertyBufferSize) 03440 { 03441 BOOL ret = FALSE; 03442 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 03443 03444 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property, 03445 PropertyBuffer, PropertyBufferSize); 03446 03447 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 03448 { 03449 SetLastError(ERROR_INVALID_HANDLE); 03450 return FALSE; 03451 } 03452 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 03453 { 03454 SetLastError(ERROR_INVALID_HANDLE); 03455 return FALSE; 03456 } 03457 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 03458 || !DeviceInfoData->Reserved) 03459 { 03460 SetLastError(ERROR_INVALID_PARAMETER); 03461 return FALSE; 03462 } 03463 03464 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, 03465 Property, PropertyBuffer, PropertyBufferSize); 03466 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 03467 return ret; 03468 } 03469 03470 /*********************************************************************** 03471 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@) 03472 */ 03473 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW( 03474 HDEVINFO DeviceInfoSet, 03475 PSP_DEVINFO_DATA DeviceInfoData, 03476 DWORD Property, 03477 const BYTE *PropertyBuffer, 03478 DWORD PropertyBufferSize) 03479 { 03480 BOOL ret = FALSE; 03481 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 03482 03483 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property, 03484 PropertyBuffer, PropertyBufferSize); 03485 03486 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 03487 { 03488 SetLastError(ERROR_INVALID_HANDLE); 03489 return FALSE; 03490 } 03491 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 03492 { 03493 SetLastError(ERROR_INVALID_HANDLE); 03494 return FALSE; 03495 } 03496 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 03497 || !DeviceInfoData->Reserved) 03498 { 03499 SetLastError(ERROR_INVALID_PARAMETER); 03500 return FALSE; 03501 } 03502 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0]) 03503 && PropertyMap[Property].nameW) 03504 { 03505 HKEY hKey; 03506 LONG l; 03507 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE); 03508 if (hKey == INVALID_HANDLE_VALUE) 03509 return FALSE; 03510 /* Write new data */ 03511 l = RegSetValueExW( 03512 hKey, PropertyMap[Property].nameW, 0, 03513 PropertyMap[Property].regType, PropertyBuffer, 03514 PropertyBufferSize); 03515 if (!l) 03516 ret = TRUE; 03517 else 03518 SetLastError(l); 03519 RegCloseKey(hKey); 03520 } 03521 else 03522 { 03523 ERR("Property 0x%lx not implemented\n", Property); 03524 SetLastError(ERROR_NOT_SUPPORTED); 03525 } 03526 03527 TRACE("Returning %d\n", ret); 03528 return ret; 03529 } 03530 03531 /*********************************************************************** 03532 * SetupDiInstallClassA (SETUPAPI.@) 03533 */ 03534 BOOL WINAPI SetupDiInstallClassA( 03535 HWND hwndParent, 03536 PCSTR InfFileName, 03537 DWORD Flags, 03538 HSPFILEQ FileQueue) 03539 { 03540 return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); 03541 } 03542 03543 /*********************************************************************** 03544 * SetupDiInstallClassExA (SETUPAPI.@) 03545 */ 03546 BOOL WINAPI 03547 SetupDiInstallClassExA( 03548 IN HWND hwndParent OPTIONAL, 03549 IN PCSTR InfFileName OPTIONAL, 03550 IN DWORD Flags, 03551 IN HSPFILEQ FileQueue OPTIONAL, 03552 IN CONST GUID *InterfaceClassGuid OPTIONAL, 03553 IN PVOID Reserved1, 03554 IN PVOID Reserved2) 03555 { 03556 PWSTR InfFileNameW = NULL; 03557 BOOL Result; 03558 03559 if (!InfFileName) 03560 { 03561 SetLastError(ERROR_INVALID_PARAMETER); 03562 return FALSE; 03563 } 03564 else 03565 { 03566 InfFileNameW = pSetupMultiByteToUnicode(InfFileName, CP_ACP); 03567 if (InfFileNameW == NULL) 03568 { 03569 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03570 return FALSE; 03571 } 03572 } 03573 03574 Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags, 03575 FileQueue, InterfaceClassGuid, Reserved1, Reserved2); 03576 03577 MyFree(InfFileNameW); 03578 03579 return Result; 03580 } 03581 03582 HKEY SETUP_CreateClassKey(HINF hInf) 03583 { 03584 static const WCHAR slash[] = { '\\',0 }; 03585 WCHAR FullBuffer[MAX_PATH]; 03586 WCHAR Buffer[MAX_PATH]; 03587 DWORD RequiredSize; 03588 HKEY hClassKey; 03589 03590 if (!SetupGetLineTextW(NULL, 03591 hInf, 03592 Version, 03593 ClassGUID, 03594 Buffer, 03595 MAX_PATH, 03596 &RequiredSize)) 03597 { 03598 return INVALID_HANDLE_VALUE; 03599 } 03600 03601 lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT); 03602 lstrcatW(FullBuffer, slash); 03603 lstrcatW(FullBuffer, Buffer); 03604 03605 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 03606 FullBuffer, 03607 0, 03608 KEY_SET_VALUE, 03609 &hClassKey)) 03610 { 03611 if (!SetupGetLineTextW(NULL, 03612 hInf, 03613 Version, 03614 Class, 03615 Buffer, 03616 MAX_PATH, 03617 &RequiredSize)) 03618 { 03619 return INVALID_HANDLE_VALUE; 03620 } 03621 03622 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, 03623 FullBuffer, 03624 0, 03625 NULL, 03626 REG_OPTION_NON_VOLATILE, 03627 KEY_SET_VALUE, 03628 NULL, 03629 &hClassKey, 03630 NULL)) 03631 { 03632 return INVALID_HANDLE_VALUE; 03633 } 03634 } 03635 03636 if (RegSetValueExW(hClassKey, 03637 Class, 03638 0, 03639 REG_SZ, 03640 (LPBYTE)Buffer, 03641 RequiredSize * sizeof(WCHAR))) 03642 { 03643 RegCloseKey(hClassKey); 03644 RegDeleteKeyW(HKEY_LOCAL_MACHINE, 03645 FullBuffer); 03646 return INVALID_HANDLE_VALUE; 03647 } 03648 03649 return hClassKey; 03650 } 03651 03652 /*********************************************************************** 03653 * SetupDiInstallClassW (SETUPAPI.@) 03654 */ 03655 BOOL WINAPI SetupDiInstallClassW( 03656 HWND hwndParent, 03657 PCWSTR InfFileName, 03658 DWORD Flags, 03659 HSPFILEQ FileQueue) 03660 { 03661 return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL); 03662 } 03663 03664 03665 /*********************************************************************** 03666 * SetupDiOpenClassRegKey (SETUPAPI.@) 03667 */ 03668 HKEY WINAPI SetupDiOpenClassRegKey( 03669 const GUID* ClassGuid, 03670 REGSAM samDesired) 03671 { 03672 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, 03673 DIOCR_INSTALLER, NULL, NULL); 03674 } 03675 03676 03677 /*********************************************************************** 03678 * SetupDiOpenClassRegKeyExA (SETUPAPI.@) 03679 */ 03680 HKEY WINAPI SetupDiOpenClassRegKeyExA( 03681 const GUID* ClassGuid, 03682 REGSAM samDesired, 03683 DWORD Flags, 03684 PCSTR MachineName, 03685 PVOID Reserved) 03686 { 03687 PWSTR MachineNameW = NULL; 03688 HKEY hKey; 03689 03690 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired, 03691 Flags, debugstr_a(MachineName), Reserved); 03692 03693 if (MachineName) 03694 { 03695 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP); 03696 if (MachineNameW == NULL) 03697 return INVALID_HANDLE_VALUE; 03698 } 03699 03700 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, 03701 Flags, MachineNameW, Reserved); 03702 03703 MyFree(MachineNameW); 03704 03705 return hKey; 03706 } 03707 03708 03709 /*********************************************************************** 03710 * SetupDiOpenClassRegKeyExW (SETUPAPI.@) 03711 */ 03712 HKEY WINAPI SetupDiOpenClassRegKeyExW( 03713 const GUID* ClassGuid, 03714 REGSAM samDesired, 03715 DWORD Flags, 03716 PCWSTR MachineName, 03717 PVOID Reserved) 03718 { 03719 HKEY HKLM; 03720 HKEY hClassesKey; 03721 HKEY key; 03722 LPCWSTR lpKeyName; 03723 LONG l; 03724 03725 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired, 03726 Flags, debugstr_w(MachineName), Reserved); 03727 03728 if (MachineName != NULL) 03729 { 03730 l = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM); 03731 if (l != ERROR_SUCCESS) 03732 { 03733 SetLastError(l); 03734 return INVALID_HANDLE_VALUE; 03735 } 03736 } 03737 else 03738 HKLM = HKEY_LOCAL_MACHINE; 03739 03740 if (Flags == DIOCR_INSTALLER) 03741 { 03742 lpKeyName = REGSTR_PATH_CLASS_NT; 03743 } 03744 else if (Flags == DIOCR_INTERFACE) 03745 { 03746 lpKeyName = REGSTR_PATH_DEVICE_CLASSES; 03747 } 03748 else 03749 { 03750 ERR("Invalid Flags parameter!\n"); 03751 SetLastError(ERROR_INVALID_FLAGS); 03752 if (MachineName != NULL) RegCloseKey(HKLM); 03753 return INVALID_HANDLE_VALUE; 03754 } 03755 03756 if (!ClassGuid) 03757 { 03758 if ((l = RegOpenKeyExW(HKLM, 03759 lpKeyName, 03760 0, 03761 samDesired, 03762 &hClassesKey))) 03763 { 03764 SetLastError(ERROR_INVALID_CLASS); 03765 hClassesKey = INVALID_HANDLE_VALUE; 03766 } 03767 if (MachineName != NULL) 03768 RegCloseKey(HKLM); 03769 key = hClassesKey; 03770 } 03771 else 03772 { 03773 WCHAR bracedGuidString[39]; 03774 03775 SETUPDI_GuidToString(ClassGuid, bracedGuidString); 03776 03777 if (!(l = RegOpenKeyExW(HKLM, 03778 lpKeyName, 03779 0, 03780 samDesired, 03781 &hClassesKey))) 03782 { 03783 if (MachineName != NULL) 03784 RegCloseKey(HKLM); 03785 03786 if ((l = RegOpenKeyExW(hClassesKey, 03787 bracedGuidString, 03788 0, 03789 samDesired, 03790 &key))) 03791 { 03792 SetLastError(l); 03793 key = INVALID_HANDLE_VALUE; 03794 } 03795 RegCloseKey(hClassesKey); 03796 } 03797 else 03798 { 03799 if (MachineName != NULL) RegCloseKey(HKLM); 03800 SetLastError(l); 03801 key = INVALID_HANDLE_VALUE; 03802 } 03803 } 03804 03805 return key; 03806 } 03807 03808 /*********************************************************************** 03809 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) 03810 */ 03811 BOOL WINAPI SetupDiOpenDeviceInterfaceW( 03812 HDEVINFO DeviceInfoSet, 03813 PCWSTR DevicePath, 03814 DWORD OpenFlags, 03815 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 03816 { 03817 struct DeviceInfoSet * list; 03818 PCWSTR pEnd; 03819 DWORD dwLength, dwError, dwIndex, dwKeyName, dwSubIndex; 03820 CLSID ClassId; 03821 WCHAR Buffer[MAX_PATH + 1]; 03822 WCHAR SymBuffer[MAX_PATH + 1]; 03823 WCHAR InstancePath[MAX_PATH + 1]; 03824 HKEY hKey, hDevKey, hSymKey; 03825 struct DeviceInfo * deviceInfo; 03826 struct DeviceInterface *deviceInterface; 03827 BOOL Ret; 03828 PLIST_ENTRY ItemList; 03829 PLIST_ENTRY InterfaceListEntry; 03830 03831 TRACE("%p %s %08x %p\n", 03832 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData); 03833 03834 03835 if (DeviceInterfaceData && DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) 03836 { 03837 SetLastError(ERROR_INVALID_PARAMETER); 03838 return FALSE; 03839 } 03840 03841 if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 03842 { 03843 SetLastError(ERROR_INVALID_HANDLE); 03844 return FALSE; 03845 } 03846 03847 list = (struct DeviceInfoSet * )DeviceInfoSet; 03848 03849 dwLength = wcslen(DevicePath); 03850 if (dwLength < 39) 03851 { 03852 /* path must be at least a guid length + L'\0' */ 03853 SetLastError(ERROR_BAD_PATHNAME); 03854 return FALSE; 03855 } 03856 03857 if (DevicePath[0] != L'\\' || 03858 DevicePath[1] != L'\\' || 03859 (DevicePath[2] != L'?' && DevicePath[2] != L'.') || 03860 DevicePath[3] != L'\\') 03861 { 03862 /* invalid formatted path */ 03863 SetLastError(ERROR_BAD_PATHNAME); 03864 return FALSE; 03865 } 03866 03867 /* check for reference strings */ 03868 pEnd = wcschr(&DevicePath[4], L'\\'); 03869 if (!pEnd) 03870 { 03871 /* no reference string */ 03872 pEnd = DevicePath + dwLength; 03873 } 03874 03875 /* copy guid */ 03876 wcscpy(Buffer, pEnd - 37); 03877 Buffer[36] = L'\0'; 03878 03879 dwError = UuidFromStringW(Buffer, &ClassId); 03880 if (dwError != NOERROR) 03881 { 03882 /* invalid formatted path */ 03883 SetLastError(ERROR_BAD_PATHNAME); 03884 return FALSE; 03885 } 03886 03887 hKey = SetupDiOpenClassRegKeyExW(&ClassId, KEY_READ, DIOCR_INTERFACE, list->MachineName, NULL); 03888 03889 if (hKey == INVALID_HANDLE_VALUE) 03890 { 03891 /* invalid device class */ 03892 return FALSE; 03893 } 03894 03895 ItemList = list->ListHead.Flink; 03896 while (ItemList != &list->ListHead) 03897 { 03898 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 03899 InterfaceListEntry = deviceInfo->InterfaceListHead.Flink; 03900 while (InterfaceListEntry != &deviceInfo->InterfaceListHead) 03901 { 03902 deviceInterface = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry); 03903 if (!IsEqualIID(&deviceInterface->InterfaceClassGuid, &ClassId)) 03904 { 03905 InterfaceListEntry = InterfaceListEntry->Flink; 03906 continue; 03907 } 03908 03909 if (!wcsicmp(deviceInterface->SymbolicLink, DevicePath)) 03910 { 03911 if (DeviceInterfaceData) 03912 { 03913 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface; 03914 DeviceInterfaceData->Flags = deviceInterface->Flags; 03915 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID)); 03916 } 03917 03918 return TRUE; 03919 } 03920 03921 } 03922 } 03923 03924 03925 dwIndex = 0; 03926 do 03927 { 03928 Buffer[0] = 0; 03929 dwKeyName = sizeof(Buffer) / sizeof(WCHAR); 03930 dwError = RegEnumKeyExW(hKey, dwIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL); 03931 03932 if (dwError != ERROR_SUCCESS) 03933 break; 03934 03935 if (RegOpenKeyExW(hKey, Buffer, 0, KEY_READ, &hDevKey) != ERROR_SUCCESS) 03936 break; 03937 03938 dwSubIndex = 0; 03939 InstancePath[0] = 0; 03940 dwKeyName = sizeof(InstancePath); 03941 03942 dwError = RegQueryValueExW(hDevKey, L"DeviceInstance", NULL, NULL, (LPBYTE)InstancePath, &dwKeyName); 03943 03944 while(TRUE) 03945 { 03946 Buffer[0] = 0; 03947 dwKeyName = sizeof(Buffer) / sizeof(WCHAR); 03948 dwError = RegEnumKeyExW(hDevKey, dwSubIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL); 03949 03950 if (dwError != ERROR_SUCCESS) 03951 break; 03952 03953 dwError = RegOpenKeyExW(hDevKey, Buffer, 0, KEY_READ, &hSymKey); 03954 if (dwError != ERROR_SUCCESS) 03955 break; 03956 03957 /* query for symbolic link */ 03958 dwKeyName = sizeof(SymBuffer); 03959 SymBuffer[0] = L'\0'; 03960 dwError = RegQueryValueExW(hSymKey, L"SymbolicLink", NULL, NULL, (LPBYTE)SymBuffer, &dwKeyName); 03961 03962 if (dwError != ERROR_SUCCESS) 03963 { 03964 RegCloseKey(hSymKey); 03965 break; 03966 } 03967 03968 if (!wcsicmp(SymBuffer, DevicePath)) 03969 { 03970 Ret = CreateDeviceInfo(list, InstancePath, &ClassId, &deviceInfo); 03971 RegCloseKey(hSymKey); 03972 RegCloseKey(hDevKey); 03973 RegCloseKey(hKey); 03974 03975 if (Ret) 03976 { 03977 deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymBuffer) + 1) * sizeof(WCHAR)); 03978 if (deviceInterface) 03979 { 03980 03981 CopyMemory(&deviceInterface->InterfaceClassGuid, &ClassId, sizeof(GUID)); 03982 deviceInterface->DeviceInfo = deviceInfo; 03983 deviceInterface->Flags = SPINT_ACTIVE; //FIXME 03984 03985 wcscpy(deviceInterface->SymbolicLink, SymBuffer); 03986 03987 InsertTailList(&deviceInfo->InterfaceListHead, &deviceInterface->ListEntry); 03988 InsertTailList(&list->ListHead, &deviceInfo->ListEntry); 03989 03990 03991 if (DeviceInterfaceData) 03992 { 03993 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface; 03994 DeviceInterfaceData->Flags = deviceInterface->Flags; 03995 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID)); 03996 } 03997 else 03998 { 03999 Ret = FALSE; 04000 SetLastError(ERROR_INVALID_USER_BUFFER); 04001 } 04002 } 04003 } 04004 else 04005 { 04006 HeapFree(GetProcessHeap(), 0, deviceInfo); 04007 Ret = FALSE; 04008 } 04009 return Ret; 04010 } 04011 RegCloseKey(hSymKey); 04012 dwSubIndex++; 04013 } 04014 04015 RegCloseKey(hDevKey); 04016 dwIndex++; 04017 } while(TRUE); 04018 04019 RegCloseKey(hKey); 04020 return FALSE; 04021 } 04022 04023 /*********************************************************************** 04024 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@) 04025 */ 04026 BOOL WINAPI SetupDiOpenDeviceInterfaceA( 04027 HDEVINFO DeviceInfoSet, 04028 PCSTR DevicePath, 04029 DWORD OpenFlags, 04030 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) 04031 { 04032 LPWSTR DevicePathW = NULL; 04033 BOOL bResult; 04034 04035 TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData); 04036 04037 DevicePathW = pSetupMultiByteToUnicode(DevicePath, CP_ACP); 04038 if (DevicePathW == NULL) 04039 return FALSE; 04040 04041 bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet, 04042 DevicePathW, OpenFlags, DeviceInterfaceData); 04043 04044 MyFree(DevicePathW); 04045 04046 return bResult; 04047 } 04048 04049 /*********************************************************************** 04050 * SetupDiSetClassInstallParamsA (SETUPAPI.@) 04051 */ 04052 BOOL WINAPI SetupDiSetClassInstallParamsA( 04053 HDEVINFO DeviceInfoSet, 04054 PSP_DEVINFO_DATA DeviceInfoData, 04055 PSP_CLASSINSTALL_HEADER ClassInstallParams, 04056 DWORD ClassInstallParamsSize) 04057 { 04058 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData, 04059 ClassInstallParams->InstallFunction, ClassInstallParamsSize); 04060 return FALSE; 04061 } 04062 04063 static BOOL WINAPI 04064 IntSetupDiRegisterDeviceInfo( 04065 IN HDEVINFO DeviceInfoSet, 04066 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 04067 { 04068 return SetupDiRegisterDeviceInfo(DeviceInfoSet, DeviceInfoData, 0, NULL, NULL, NULL); 04069 } 04070 04071 /*********************************************************************** 04072 * SetupDiCallClassInstaller (SETUPAPI.@) 04073 */ 04074 BOOL WINAPI SetupDiCallClassInstaller( 04075 DI_FUNCTION InstallFunction, 04076 HDEVINFO DeviceInfoSet, 04077 PSP_DEVINFO_DATA DeviceInfoData) 04078 { 04079 BOOL ret = FALSE; 04080 04081 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData); 04082 04083 if (!DeviceInfoSet) 04084 SetLastError(ERROR_INVALID_PARAMETER); 04085 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 04086 SetLastError(ERROR_INVALID_HANDLE); 04087 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 04088 SetLastError(ERROR_INVALID_HANDLE); 04089 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE) 04090 SetLastError(ERROR_INVALID_HANDLE); 04091 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 04092 SetLastError(ERROR_INVALID_USER_BUFFER); 04093 else 04094 { 04095 SP_DEVINSTALL_PARAMS_W InstallParams; 04096 #define CLASS_COINSTALLER 0x1 04097 #define DEVICE_COINSTALLER 0x2 04098 #define CLASS_INSTALLER 0x4 04099 UCHAR CanHandle = 0; 04100 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL; 04101 04102 switch (InstallFunction) 04103 { 04104 case DIF_ADDPROPERTYPAGE_ADVANCED: 04105 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04106 break; 04107 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED: 04108 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04109 break; 04110 case DIF_ALLOW_INSTALL: 04111 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04112 break; 04113 case DIF_DETECT: 04114 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04115 break; 04116 case DIF_DESTROYPRIVATEDATA: 04117 CanHandle = CLASS_INSTALLER; 04118 break; 04119 case DIF_INSTALLDEVICE: 04120 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04121 DefaultHandler = SetupDiInstallDevice; 04122 break; 04123 case DIF_INSTALLDEVICEFILES: 04124 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04125 DefaultHandler = SetupDiInstallDriverFiles; 04126 break; 04127 case DIF_INSTALLINTERFACES: 04128 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04129 DefaultHandler = SetupDiInstallDeviceInterfaces; 04130 break; 04131 case DIF_NEWDEVICEWIZARD_FINISHINSTALL: 04132 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04133 break; 04134 case DIF_NEWDEVICEWIZARD_POSTANALYZE: 04135 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04136 break; 04137 case DIF_NEWDEVICEWIZARD_PREANALYZE: 04138 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04139 break; 04140 case DIF_NEWDEVICEWIZARD_PRESELECT: 04141 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04142 break; 04143 case DIF_NEWDEVICEWIZARD_SELECT: 04144 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04145 break; 04146 case DIF_POWERMESSAGEWAKE: 04147 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04148 break; 04149 case DIF_PROPERTYCHANGE: 04150 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04151 DefaultHandler = SetupDiChangeState; 04152 break; 04153 case DIF_REGISTER_COINSTALLERS: 04154 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04155 DefaultHandler = SetupDiRegisterCoDeviceInstallers; 04156 break; 04157 case DIF_REGISTERDEVICE: 04158 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04159 DefaultHandler = IntSetupDiRegisterDeviceInfo; 04160 break; 04161 case DIF_REMOVE: 04162 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04163 DefaultHandler = SetupDiRemoveDevice; 04164 break; 04165 case DIF_SELECTBESTCOMPATDRV: 04166 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04167 DefaultHandler = SetupDiSelectBestCompatDrv; 04168 break; 04169 case DIF_SELECTDEVICE: 04170 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; 04171 DefaultHandler = SetupDiSelectDevice; 04172 break; 04173 case DIF_TROUBLESHOOTER: 04174 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04175 break; 04176 case DIF_UNREMOVE: 04177 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; 04178 DefaultHandler = SetupDiUnremoveDevice; 04179 break; 04180 default: 04181 ERR("Install function %u not supported\n", InstallFunction); 04182 SetLastError(ERROR_NOT_SUPPORTED); 04183 } 04184 04185 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 04186 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams)) 04187 /* Don't process this call, as a parameter is invalid */ 04188 CanHandle = 0; 04189 04190 if (CanHandle != 0) 04191 { 04192 LIST_ENTRY ClassCoInstallersListHead; 04193 LIST_ENTRY DeviceCoInstallersListHead; 04194 HMODULE ClassInstallerLibrary = NULL; 04195 CLASS_INSTALL_PROC ClassInstaller = NULL; 04196 COINSTALLER_CONTEXT_DATA Context; 04197 PLIST_ENTRY ListEntry; 04198 HKEY hKey; 04199 DWORD dwRegType, dwLength; 04200 DWORD rc = NO_ERROR; 04201 04202 InitializeListHead(&ClassCoInstallersListHead); 04203 InitializeListHead(&DeviceCoInstallersListHead); 04204 04205 if (CanHandle & DEVICE_COINSTALLER) 04206 { 04207 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE); 04208 if (hKey != INVALID_HANDLE_VALUE) 04209 { 04210 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength); 04211 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ) 04212 { 04213 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 04214 if (KeyBuffer != NULL) 04215 { 04216 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 04217 if (rc == ERROR_SUCCESS) 04218 { 04219 LPWSTR ptr; 04220 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1) 04221 { 04222 /* Add coinstaller to DeviceCoInstallersListHead list */ 04223 struct CoInstallerElement *coinstaller; 04224 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr)); 04225 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement)); 04226 if (!coinstaller) 04227 continue; 04228 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement)); 04229 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS) 04230 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry); 04231 else 04232 HeapFree(GetProcessHeap(), 0, coinstaller); 04233 } 04234 } 04235 HeapFree(GetProcessHeap(), 0, KeyBuffer); 04236 } 04237 } 04238 RegCloseKey(hKey); 04239 } 04240 } 04241 if (CanHandle & CLASS_COINSTALLER) 04242 { 04243 rc = RegOpenKeyExW( 04244 HKEY_LOCAL_MACHINE, 04245 REGSTR_PATH_CODEVICEINSTALLERS, 04246 0, /* Options */ 04247 KEY_QUERY_VALUE, 04248 &hKey); 04249 if (rc == ERROR_SUCCESS) 04250 { 04251 LPWSTR lpGuidString; 04252 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK) 04253 { 04254 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength); 04255 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ) 04256 { 04257 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 04258 if (KeyBuffer != NULL) 04259 { 04260 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 04261 if (rc == ERROR_SUCCESS) 04262 { 04263 LPWSTR ptr; 04264 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1) 04265 { 04266 /* Add coinstaller to ClassCoInstallersListHead list */ 04267 struct CoInstallerElement *coinstaller; 04268 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr)); 04269 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement)); 04270 if (!coinstaller) 04271 continue; 04272 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement)); 04273 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS) 04274 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry); 04275 else 04276 HeapFree(GetProcessHeap(), 0, coinstaller); 04277 } 04278 } 04279 HeapFree(GetProcessHeap(), 0, KeyBuffer); 04280 } 04281 } 04282 RpcStringFreeW(&lpGuidString); 04283 } 04284 RegCloseKey(hKey); 04285 } 04286 } 04287 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED)) 04288 { 04289 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE); 04290 if (hKey != INVALID_HANDLE_VALUE) 04291 { 04292 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength); 04293 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ) 04294 { 04295 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); 04296 if (KeyBuffer != NULL) 04297 { 04298 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); 04299 if (rc == ERROR_SUCCESS) 04300 { 04301 /* Get ClassInstaller function pointer */ 04302 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer)); 04303 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS) 04304 { 04305 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED; 04306 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 04307 } 04308 } 04309 HeapFree(GetProcessHeap(), 0, KeyBuffer); 04310 } 04311 } 04312 RegCloseKey(hKey); 04313 } 04314 } 04315 04316 /* Call Class co-installers */ 04317 Context.PostProcessing = FALSE; 04318 rc = NO_ERROR; 04319 ListEntry = ClassCoInstallersListHead.Flink; 04320 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead) 04321 { 04322 struct CoInstallerElement *coinstaller; 04323 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 04324 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 04325 coinstaller->PrivateData = Context.PrivateData; 04326 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) 04327 { 04328 coinstaller->DoPostProcessing = TRUE; 04329 rc = NO_ERROR; 04330 } 04331 ListEntry = ListEntry->Flink; 04332 } 04333 04334 /* Call Device co-installers */ 04335 ListEntry = DeviceCoInstallersListHead.Flink; 04336 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead) 04337 { 04338 struct CoInstallerElement *coinstaller; 04339 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 04340 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 04341 coinstaller->PrivateData = Context.PrivateData; 04342 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) 04343 { 04344 coinstaller->DoPostProcessing = TRUE; 04345 rc = NO_ERROR; 04346 } 04347 ListEntry = ListEntry->Flink; 04348 } 04349 04350 /* Call Class installer */ 04351 if (ClassInstaller) 04352 { 04353 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData); 04354 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller); 04355 } 04356 else 04357 rc = ERROR_DI_DO_DEFAULT; 04358 04359 /* Call default handler */ 04360 if (rc == ERROR_DI_DO_DEFAULT) 04361 { 04362 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION)) 04363 { 04364 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData)) 04365 rc = NO_ERROR; 04366 else 04367 rc = GetLastError(); 04368 } 04369 else 04370 rc = NO_ERROR; 04371 } 04372 04373 /* Call Class co-installers that required postprocessing */ 04374 Context.PostProcessing = TRUE; 04375 ListEntry = ClassCoInstallersListHead.Flink; 04376 while (ListEntry != &ClassCoInstallersListHead) 04377 { 04378 struct CoInstallerElement *coinstaller; 04379 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 04380 if (coinstaller->DoPostProcessing) 04381 { 04382 Context.InstallResult = rc; 04383 Context.PrivateData = coinstaller->PrivateData; 04384 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 04385 } 04386 FreeFunctionPointer(coinstaller->Module, coinstaller->Function); 04387 ListEntry = ListEntry->Flink; 04388 } 04389 04390 /* Call Device co-installers that required postprocessing */ 04391 ListEntry = DeviceCoInstallersListHead.Flink; 04392 while (ListEntry != &DeviceCoInstallersListHead) 04393 { 04394 struct CoInstallerElement *coinstaller; 04395 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry); 04396 if (coinstaller->DoPostProcessing) 04397 { 04398 Context.InstallResult = rc; 04399 Context.PrivateData = coinstaller->PrivateData; 04400 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); 04401 } 04402 FreeFunctionPointer(coinstaller->Module, coinstaller->Function); 04403 ListEntry = ListEntry->Flink; 04404 } 04405 04406 /* Free allocated memory */ 04407 while (!IsListEmpty(&ClassCoInstallersListHead)) 04408 { 04409 ListEntry = RemoveHeadList(&ClassCoInstallersListHead); 04410 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry)); 04411 } 04412 while (!IsListEmpty(&DeviceCoInstallersListHead)) 04413 { 04414 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead); 04415 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry)); 04416 } 04417 04418 ret = (rc == NO_ERROR); 04419 } 04420 } 04421 04422 TRACE("Returning %d\n", ret); 04423 return ret; 04424 } 04425 04426 /*********************************************************************** 04427 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@) 04428 */ 04429 BOOL WINAPI SetupDiGetDeviceInstallParamsA( 04430 HDEVINFO DeviceInfoSet, 04431 PSP_DEVINFO_DATA DeviceInfoData, 04432 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) 04433 { 04434 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW; 04435 BOOL ret = FALSE; 04436 04437 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 04438 04439 if (DeviceInstallParams == NULL) 04440 SetLastError(ERROR_INVALID_PARAMETER); 04441 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A)) 04442 SetLastError(ERROR_INVALID_USER_BUFFER); 04443 else 04444 { 04445 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 04446 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW); 04447 04448 if (ret) 04449 { 04450 /* Do W->A conversion */ 04451 memcpy( 04452 DeviceInstallParams, 04453 &deviceInstallParamsW, 04454 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath)); 04455 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1, 04456 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0) 04457 { 04458 DeviceInstallParams->DriverPath[0] = '\0'; 04459 ret = FALSE; 04460 } 04461 } 04462 } 04463 04464 TRACE("Returning %d\n", ret); 04465 return ret; 04466 } 04467 04468 /*********************************************************************** 04469 * SetupDiGetDeviceInfoListClass (SETUPAPI.@) 04470 */ 04471 BOOL WINAPI 04472 SetupDiGetDeviceInfoListClass( 04473 IN HDEVINFO DeviceInfoSet, 04474 OUT LPGUID ClassGuid) 04475 { 04476 struct DeviceInfoSet *list; 04477 BOOL ret = FALSE; 04478 04479 TRACE("%p %p\n", DeviceInfoSet, ClassGuid); 04480 04481 if (!DeviceInfoSet) 04482 SetLastError(ERROR_INVALID_HANDLE); 04483 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 04484 SetLastError(ERROR_INVALID_HANDLE); 04485 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL)) 04486 SetLastError(ERROR_NO_ASSOCIATED_CLASS); 04487 else 04488 { 04489 memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID)); 04490 04491 ret = TRUE; 04492 } 04493 04494 TRACE("Returning %d\n", ret); 04495 return ret; 04496 } 04497 04498 /*********************************************************************** 04499 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@) 04500 */ 04501 BOOL WINAPI 04502 SetupDiGetDeviceInstallParamsW( 04503 IN HDEVINFO DeviceInfoSet, 04504 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 04505 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 04506 { 04507 struct DeviceInfoSet *list; 04508 BOOL ret = FALSE; 04509 04510 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 04511 04512 if (!DeviceInfoSet) 04513 SetLastError(ERROR_INVALID_HANDLE); 04514 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 04515 SetLastError(ERROR_INVALID_HANDLE); 04516 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 04517 SetLastError(ERROR_INVALID_USER_BUFFER); 04518 else if (!DeviceInstallParams) 04519 SetLastError(ERROR_INVALID_PARAMETER); 04520 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W)) 04521 SetLastError(ERROR_INVALID_USER_BUFFER); 04522 else 04523 { 04524 PSP_DEVINSTALL_PARAMS_W Source; 04525 04526 if (DeviceInfoData) 04527 Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams; 04528 else 04529 Source = &list->InstallParams; 04530 04531 ret = TRUE; 04532 04533 _SEH2_TRY 04534 { 04535 memcpy(DeviceInstallParams, Source, Source->cbSize); 04536 } 04537 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 04538 { 04539 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 04540 ret = FALSE; 04541 } 04542 _SEH2_END; 04543 } 04544 04545 TRACE("Returning %d\n", ret); 04546 return ret; 04547 } 04548 04549 static BOOL 04550 CheckDeviceInstallParameters( 04551 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 04552 { 04553 DWORD SupportedFlags = 04554 DI_NOVCP | /* 0x00000008 */ 04555 DI_DIDCOMPAT | /* 0x00000010 */ 04556 DI_DIDCLASS | /* 0x00000020 */ 04557 DI_NEEDRESTART | /* 0x00000080 */ 04558 DI_NEEDREBOOT | /* 0x00000100 */ 04559 DI_RESOURCEPAGE_ADDED | /* 0x00002000 */ 04560 DI_PROPERTIES_CHANGE | /* 0x00004000 */ 04561 DI_ENUMSINGLEINF | /* 0x00010000 */ 04562 DI_DONOTCALLCONFIGMG | /* 0x00020000 */ 04563 DI_CLASSINSTALLPARAMS | /* 0x00100000 */ 04564 DI_NODI_DEFAULTACTION | /* 0x00200000 */ 04565 DI_QUIETINSTALL | /* 0x00800000 */ 04566 DI_NOFILECOPY | /* 0x01000000 */ 04567 DI_DRIVERPAGE_ADDED; /* 0x04000000 */ 04568 DWORD SupportedFlagsEx = 04569 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */ 04570 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */ 04571 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */ 04572 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */ 04573 DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */ 04574 DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */ 04575 BOOL ret = FALSE; 04576 04577 /* FIXME: add support for more flags */ 04578 04579 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used. 04580 * It should be checked before accessing to other values 04581 * of the SP_DEVINSTALL_PARAMS structure */ 04582 04583 if (DeviceInstallParams->Flags & ~SupportedFlags) 04584 { 04585 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags); 04586 SetLastError(ERROR_INVALID_FLAGS); 04587 } 04588 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx) 04589 { 04590 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx); 04591 SetLastError(ERROR_INVALID_FLAGS); 04592 } 04593 else if ((DeviceInstallParams->Flags & DI_NOVCP) 04594 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE)) 04595 SetLastError(ERROR_INVALID_USER_BUFFER); 04596 else 04597 { 04598 /* FIXME: check Reserved field */ 04599 ret = TRUE; 04600 } 04601 04602 return ret; 04603 } 04604 04605 /*********************************************************************** 04606 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@) 04607 */ 04608 BOOL WINAPI 04609 SetupDiSetDeviceInstallParamsW( 04610 IN HDEVINFO DeviceInfoSet, 04611 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, 04612 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) 04613 { 04614 struct DeviceInfoSet *list; 04615 BOOL ret = FALSE; 04616 04617 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 04618 04619 if (!DeviceInfoSet) 04620 SetLastError(ERROR_INVALID_HANDLE); 04621 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 04622 SetLastError(ERROR_INVALID_HANDLE); 04623 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 04624 SetLastError(ERROR_INVALID_USER_BUFFER); 04625 else if (!DeviceInstallParams) 04626 SetLastError(ERROR_INVALID_PARAMETER); 04627 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W)) 04628 SetLastError(ERROR_INVALID_USER_BUFFER); 04629 else if (CheckDeviceInstallParameters(DeviceInstallParams)) 04630 { 04631 PSP_DEVINSTALL_PARAMS_W Destination; 04632 04633 if (DeviceInfoData) 04634 Destination = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams; 04635 else 04636 Destination = &list->InstallParams; 04637 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize); 04638 ret = TRUE; 04639 } 04640 04641 TRACE("Returning %d\n", ret); 04642 return ret; 04643 } 04644 04645 /*********************************************************************** 04646 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@) 04647 */ 04648 BOOL WINAPI 04649 SetupDiSetDeviceInstallParamsA( 04650 HDEVINFO DeviceInfoSet, 04651 PSP_DEVINFO_DATA DeviceInfoData, 04652 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) 04653 { 04654 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW; 04655 int len = 0; 04656 BOOL ret = FALSE; 04657 04658 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); 04659 04660 if (DeviceInstallParams == NULL) 04661 SetLastError(ERROR_INVALID_PARAMETER); 04662 else if (DeviceInstallParams->cbSize < sizeof(SP_DEVINSTALL_PARAMS_A)) 04663 SetLastError(ERROR_INVALID_USER_BUFFER); 04664 else 04665 { 04666 memcpy(&deviceInstallParamsW, DeviceInstallParams, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A, DriverPath)); 04667 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 04668 len = MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, NULL, 0); 04669 if (!len) 04670 { 04671 ERR("DrivePath is NULL\n"); 04672 ret = FALSE; 04673 } 04674 else 04675 { 04676 MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, deviceInstallParamsW.DriverPath, len); 04677 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW); 04678 } 04679 } 04680 04681 TRACE("Returning %d\n", ret); 04682 return ret; 04683 } 04684 04685 static HKEY 04686 OpenHardwareProfileKey( 04687 IN HKEY HKLM, 04688 IN DWORD HwProfile, 04689 IN DWORD samDesired) 04690 { 04691 HKEY hHWProfilesKey = NULL; 04692 HKEY hHWProfileKey = NULL; 04693 HKEY ret = INVALID_HANDLE_VALUE; 04694 LONG rc; 04695 04696 rc = RegOpenKeyExW(HKLM, 04697 REGSTR_PATH_HWPROFILES, 04698 0, 04699 0, 04700 &hHWProfilesKey); 04701 if (rc != ERROR_SUCCESS) 04702 { 04703 SetLastError(rc); 04704 goto cleanup; 04705 } 04706 if (HwProfile == 0) 04707 { 04708 rc = RegOpenKeyExW(hHWProfilesKey, 04709 REGSTR_KEY_CURRENT, 04710 0, 04711 KEY_CREATE_SUB_KEY, 04712 &hHWProfileKey); 04713 } 04714 else 04715 { 04716 WCHAR subKey[5]; 04717 snprintfW(subKey, 4, InstanceKeyFormat, HwProfile); 04718 subKey[4] = '\0'; 04719 rc = RegOpenKeyExW(hHWProfilesKey, 04720 subKey, 04721 0, 04722 KEY_CREATE_SUB_KEY, 04723 &hHWProfileKey); 04724 } 04725 if (rc != ERROR_SUCCESS) 04726 { 04727 SetLastError(rc); 04728 goto cleanup; 04729 } 04730 ret = hHWProfileKey; 04731 04732 cleanup: 04733 if (hHWProfilesKey != NULL) 04734 RegCloseKey(hHWProfilesKey); 04735 if (hHWProfileKey != NULL && hHWProfileKey != ret) 04736 RegCloseKey(hHWProfileKey); 04737 return ret; 04738 } 04739 04740 static BOOL 04741 IsDeviceInfoInDeviceInfoSet( 04742 struct DeviceInfoSet *deviceInfoSet, 04743 struct DeviceInfo *deviceInfo) 04744 { 04745 PLIST_ENTRY ListEntry; 04746 04747 ListEntry = deviceInfoSet->ListHead.Flink; 04748 while (ListEntry != &deviceInfoSet->ListHead) 04749 { 04750 if (deviceInfo == CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry)) 04751 return TRUE; 04752 04753 ListEntry = ListEntry->Flink; 04754 } 04755 04756 return FALSE; 04757 } 04758 04759 /*********************************************************************** 04760 * SetupDiDeleteDeviceInfo (SETUPAPI.@) 04761 */ 04762 BOOL WINAPI 04763 SetupDiDeleteDeviceInfo( 04764 IN HDEVINFO DeviceInfoSet, 04765 IN PSP_DEVINFO_DATA DeviceInfoData) 04766 { 04767 struct DeviceInfoSet *deviceInfoSet; 04768 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData; 04769 BOOL ret = FALSE; 04770 04771 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 04772 04773 if (!DeviceInfoSet) 04774 SetLastError(ERROR_INVALID_HANDLE); 04775 else if ((deviceInfoSet = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 04776 SetLastError(ERROR_INVALID_HANDLE); 04777 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 04778 SetLastError(ERROR_INVALID_USER_BUFFER); 04779 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet, deviceInfo)) 04780 SetLastError(ERROR_INVALID_PARAMETER); 04781 else 04782 { 04783 RemoveEntryList(&deviceInfo->ListEntry); 04784 DestroyDeviceInfo(deviceInfo); 04785 ret = TRUE; 04786 } 04787 04788 return ret; 04789 } 04790 04791 04792 /*********************************************************************** 04793 * SetupDiOpenDeviceInfoA (SETUPAPI.@) 04794 */ 04795 BOOL WINAPI 04796 SetupDiOpenDeviceInfoA( 04797 IN HDEVINFO DeviceInfoSet, 04798 IN PCSTR DeviceInstanceId, 04799 IN HWND hwndParent OPTIONAL, 04800 IN DWORD OpenFlags, 04801 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 04802 { 04803 LPWSTR DeviceInstanceIdW = NULL; 04804 BOOL bResult; 04805 04806 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData); 04807 04808 DeviceInstanceIdW = pSetupMultiByteToUnicode(DeviceInstanceId, CP_ACP); 04809 if (DeviceInstanceIdW == NULL) 04810 return FALSE; 04811 04812 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet, 04813 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData); 04814 04815 MyFree(DeviceInstanceIdW); 04816 04817 return bResult; 04818 } 04819 04820 04821 /*********************************************************************** 04822 * SetupDiOpenDeviceInfoW (SETUPAPI.@) 04823 */ 04824 BOOL WINAPI 04825 SetupDiOpenDeviceInfoW( 04826 IN HDEVINFO DeviceInfoSet, 04827 IN PCWSTR DeviceInstanceId, 04828 IN HWND hwndParent OPTIONAL, 04829 IN DWORD OpenFlags, 04830 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 04831 { 04832 struct DeviceInfoSet *list; 04833 HKEY hEnumKey, hKey = NULL; 04834 DWORD rc, dwSize; 04835 BOOL ret = FALSE; 04836 04837 TRACE("%p %s %p %lx %p\n", 04838 DeviceInfoSet, debugstr_w(DeviceInstanceId), 04839 hwndParent, OpenFlags, DeviceInfoData); 04840 04841 if (OpenFlags & DIOD_CANCEL_REMOVE) 04842 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n"); 04843 04844 if (!DeviceInfoSet) 04845 SetLastError(ERROR_INVALID_HANDLE); 04846 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 04847 SetLastError(ERROR_INVALID_HANDLE); 04848 else if (!DeviceInstanceId) 04849 SetLastError(ERROR_INVALID_PARAMETER); 04850 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS)) 04851 { 04852 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS)); 04853 SetLastError(ERROR_INVALID_FLAGS); 04854 } 04855 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 04856 SetLastError(ERROR_INVALID_USER_BUFFER); 04857 else 04858 { 04859 struct DeviceInfo *deviceInfo = NULL; 04860 /* Search if device already exists in DeviceInfoSet. 04861 * If yes, return the existing element 04862 * If no, create a new element using information in registry 04863 */ 04864 PLIST_ENTRY ItemList = list->ListHead.Flink; 04865 while (ItemList != &list->ListHead) 04866 { 04867 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry); 04868 if (!wcscmp(deviceInfo->instanceId, DeviceInstanceId)) 04869 break; 04870 deviceInfo = NULL; 04871 ItemList = ItemList->Flink; 04872 } 04873 04874 if (deviceInfo) 04875 { 04876 /* good one found */ 04877 ret = TRUE; 04878 } 04879 else 04880 { 04881 GUID ClassGUID; 04882 WCHAR szClassGuid[MAX_GUID_STRING_LEN]; 04883 04884 /* Open supposed registry key */ 04885 rc = RegOpenKeyExW( 04886 list->HKLM, 04887 REGSTR_PATH_SYSTEMENUM, 04888 0, /* Options */ 04889 0, 04890 &hEnumKey); 04891 if (rc != ERROR_SUCCESS) 04892 { 04893 SetLastError(rc); 04894 goto cleanup; 04895 } 04896 rc = RegOpenKeyExW( 04897 hEnumKey, 04898 DeviceInstanceId, 04899 0, /* Options */ 04900 KEY_QUERY_VALUE, 04901 &hKey); 04902 RegCloseKey(hEnumKey); 04903 if (rc != ERROR_SUCCESS) 04904 { 04905 if (rc == ERROR_FILE_NOT_FOUND) 04906 rc = ERROR_NO_SUCH_DEVINST; 04907 SetLastError(rc); 04908 goto cleanup; 04909 } 04910 04911 ClassGUID = GUID_NULL; 04912 dwSize = MAX_GUID_STRING_LEN * sizeof(WCHAR); 04913 04914 if (RegQueryValueExW(hKey, 04915 REGSTR_VAL_CLASSGUID, 04916 NULL, 04917 NULL, 04918 (LPBYTE)szClassGuid, 04919 &dwSize) == ERROR_SUCCESS) 04920 { 04921 szClassGuid[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL; 04922 04923 /* Convert a string to a ClassGuid */ 04924 UuidFromStringW(&szClassGuid[1], &ClassGUID); 04925 } 04926 04927 if (!CreateDeviceInfo(list, DeviceInstanceId, &ClassGUID, &deviceInfo)) 04928 goto cleanup; 04929 04930 InsertTailList(&list->ListHead, &deviceInfo->ListEntry); 04931 04932 ret = TRUE; 04933 } 04934 04935 if (ret && deviceInfo && DeviceInfoData) 04936 { 04937 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID)); 04938 DeviceInfoData->DevInst = deviceInfo->dnDevInst; 04939 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo; 04940 } 04941 } 04942 04943 cleanup: 04944 if (hKey != NULL) 04945 RegCloseKey(hKey); 04946 return ret; 04947 } 04948 04949 04950 /*********************************************************************** 04951 * SetupDiGetSelectedDevice (SETUPAPI.@) 04952 */ 04953 BOOL WINAPI 04954 SetupDiGetSelectedDevice( 04955 IN HDEVINFO DeviceInfoSet, 04956 OUT PSP_DEVINFO_DATA DeviceInfoData) 04957 { 04958 struct DeviceInfoSet *list; 04959 BOOL ret = FALSE; 04960 04961 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 04962 04963 if (!DeviceInfoSet) 04964 SetLastError(ERROR_INVALID_HANDLE); 04965 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 04966 SetLastError(ERROR_INVALID_HANDLE); 04967 else if (list->SelectedDevice == NULL) 04968 SetLastError(ERROR_NO_DEVICE_SELECTED); 04969 else if (!DeviceInfoData) 04970 SetLastError(ERROR_INVALID_PARAMETER); 04971 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 04972 SetLastError(ERROR_INVALID_USER_BUFFER); 04973 else 04974 { 04975 memcpy(&DeviceInfoData->ClassGuid, 04976 &list->SelectedDevice->ClassGuid, 04977 sizeof(GUID)); 04978 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst; 04979 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice; 04980 ret = TRUE; 04981 } 04982 04983 TRACE("Returning %d\n", ret); 04984 return ret; 04985 } 04986 04987 04988 /*********************************************************************** 04989 * SetupDiSetSelectedDevice (SETUPAPI.@) 04990 */ 04991 BOOL WINAPI 04992 SetupDiSetSelectedDevice( 04993 IN HDEVINFO DeviceInfoSet, 04994 IN PSP_DEVINFO_DATA DeviceInfoData) 04995 { 04996 struct DeviceInfoSet *list; 04997 BOOL ret = FALSE; 04998 04999 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 05000 05001 if (!DeviceInfoSet) 05002 SetLastError(ERROR_INVALID_HANDLE); 05003 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 05004 SetLastError(ERROR_INVALID_HANDLE); 05005 else if (!DeviceInfoData) 05006 SetLastError(ERROR_INVALID_PARAMETER); 05007 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 05008 SetLastError(ERROR_INVALID_USER_BUFFER); 05009 else if (DeviceInfoData->Reserved == 0) 05010 SetLastError(ERROR_INVALID_USER_BUFFER); 05011 else 05012 { 05013 list->SelectedDevice = (struct DeviceInfo *)DeviceInfoData->Reserved; 05014 ret = TRUE; 05015 } 05016 05017 TRACE("Returning %d\n", ret); 05018 return ret; 05019 } 05020 05021 05022 /* Return the current hardware profile id, or -1 if error */ 05023 static DWORD 05024 SETUPAPI_GetCurrentHwProfile( 05025 IN HDEVINFO DeviceInfoSet) 05026 { 05027 HKEY hKey = NULL; 05028 DWORD dwRegType, dwLength; 05029 DWORD hwProfile; 05030 LONG rc; 05031 DWORD ret = (DWORD)-1; 05032 05033 rc = RegOpenKeyExW(((struct DeviceInfoSet *)DeviceInfoSet)->HKLM, 05034 REGSTR_PATH_IDCONFIGDB, 05035 0, /* Options */ 05036 KEY_QUERY_VALUE, 05037 &hKey); 05038 if (rc != ERROR_SUCCESS) 05039 { 05040 SetLastError(rc); 05041 goto cleanup; 05042 } 05043 05044 dwLength = sizeof(DWORD); 05045 rc = RegQueryValueExW(hKey, 05046 REGSTR_VAL_CURRENTCONFIG, 05047 NULL, 05048 &dwRegType, 05049 (LPBYTE)&hwProfile, &dwLength); 05050 if (rc != ERROR_SUCCESS) 05051 { 05052 SetLastError(rc); 05053 goto cleanup; 05054 } 05055 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD)) 05056 { 05057 SetLastError(ERROR_GEN_FAILURE); 05058 goto cleanup; 05059 } 05060 05061 ret = hwProfile; 05062 05063 cleanup: 05064 if (hKey != NULL) 05065 RegCloseKey(hKey); 05066 05067 return ret; 05068 } 05069 05070 static BOOL 05071 ResetDevice( 05072 IN HDEVINFO DeviceInfoSet, 05073 IN PSP_DEVINFO_DATA DeviceInfoData) 05074 { 05075 #ifndef __WINESRC__ 05076 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 05077 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 05078 CONFIGRET cr; 05079 05080 cr = CM_Enable_DevNode_Ex(deviceInfo->dnDevInst, 0, set->hMachine); 05081 if (cr != CR_SUCCESS) 05082 { 05083 SetLastError(GetErrorCodeFromCrCode(cr)); 05084 return FALSE; 05085 } 05086 05087 return TRUE; 05088 #else 05089 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData); 05090 return TRUE; 05091 #endif 05092 } 05093 05094 static BOOL StopDevice( 05095 IN HDEVINFO DeviceInfoSet, 05096 IN PSP_DEVINFO_DATA DeviceInfoData) 05097 { 05098 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData); 05099 return TRUE; 05100 } 05101 05102 /*********************************************************************** 05103 * SetupDiChangeState (SETUPAPI.@) 05104 */ 05105 BOOL WINAPI 05106 SetupDiChangeState( 05107 IN HDEVINFO DeviceInfoSet, 05108 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 05109 { 05110 PSP_PROPCHANGE_PARAMS PropChange; 05111 HKEY hKey = INVALID_HANDLE_VALUE; 05112 LPCWSTR RegistryValueName; 05113 DWORD dwConfigFlags, dwLength, dwRegType; 05114 LONG rc; 05115 BOOL ret = FALSE; 05116 05117 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 05118 05119 if (!DeviceInfoData) 05120 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChangeParams; 05121 else 05122 PropChange = ((struct DeviceInfo *)DeviceInfoData->Reserved)->ClassInstallParams.PropChangeParams; 05123 if (!PropChange) 05124 { 05125 SetLastError(ERROR_INVALID_PARAMETER); 05126 goto cleanup; 05127 } 05128 05129 if (PropChange->Scope == DICS_FLAG_GLOBAL) 05130 RegistryValueName = REGSTR_VAL_CONFIGFLAGS; 05131 else 05132 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS; 05133 05134 switch (PropChange->StateChange) 05135 { 05136 case DICS_ENABLE: 05137 case DICS_DISABLE: 05138 { 05139 /* Enable/disable device in registry */ 05140 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE); 05141 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 05142 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL); 05143 if (hKey == INVALID_HANDLE_VALUE) 05144 break; 05145 dwLength = sizeof(DWORD); 05146 rc = RegQueryValueExW( 05147 hKey, 05148 RegistryValueName, 05149 NULL, 05150 &dwRegType, 05151 (LPBYTE)&dwConfigFlags, &dwLength); 05152 if (rc == ERROR_FILE_NOT_FOUND) 05153 dwConfigFlags = 0; 05154 else if (rc != ERROR_SUCCESS) 05155 { 05156 SetLastError(rc); 05157 goto cleanup; 05158 } 05159 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD)) 05160 { 05161 SetLastError(ERROR_GEN_FAILURE); 05162 goto cleanup; 05163 } 05164 if (PropChange->StateChange == DICS_ENABLE) 05165 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED); 05166 else 05167 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED); 05168 rc = RegSetValueExW( 05169 hKey, 05170 RegistryValueName, 05171 0, 05172 REG_DWORD, 05173 (LPBYTE)&dwConfigFlags, sizeof(DWORD)); 05174 if (rc != ERROR_SUCCESS) 05175 { 05176 SetLastError(rc); 05177 goto cleanup; 05178 } 05179 05180 /* Enable/disable device if needed */ 05181 if (PropChange->Scope == DICS_FLAG_GLOBAL 05182 || PropChange->HwProfile == 0 05183 || PropChange->HwProfile == SETUPAPI_GetCurrentHwProfile(DeviceInfoSet)) 05184 { 05185 if (PropChange->StateChange == DICS_ENABLE) 05186 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 05187 else 05188 ret = StopDevice(DeviceInfoSet, DeviceInfoData); 05189 } 05190 else 05191 ret = TRUE; 05192 break; 05193 } 05194 case DICS_PROPCHANGE: 05195 { 05196 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 05197 break; 05198 } 05199 default: 05200 { 05201 ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange); 05202 SetLastError(ERROR_NOT_SUPPORTED); 05203 } 05204 } 05205 05206 cleanup: 05207 if (hKey != INVALID_HANDLE_VALUE) 05208 RegCloseKey(hKey); 05209 05210 TRACE("Returning %d\n", ret); 05211 return ret; 05212 } 05213 05214 /*********************************************************************** 05215 * SetupDiSelectDevice (SETUPAPI.@) 05216 */ 05217 BOOL WINAPI 05218 SetupDiSelectDevice( 05219 IN HDEVINFO DeviceInfoSet, 05220 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) 05221 { 05222 FIXME("%p %p\n", DeviceInfoSet, DeviceInfoData); 05223 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 05224 return FALSE; 05225 } 05226 05227 05228 /*********************************************************************** 05229 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@) 05230 */ 05231 BOOL WINAPI 05232 SetupDiRegisterCoDeviceInstallers( 05233 IN HDEVINFO DeviceInfoSet, 05234 IN PSP_DEVINFO_DATA DeviceInfoData) 05235 { 05236 BOOL ret = FALSE; /* Return value */ 05237 05238 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 05239 05240 if (!DeviceInfoSet) 05241 SetLastError(ERROR_INVALID_PARAMETER); 05242 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 05243 SetLastError(ERROR_INVALID_HANDLE); 05244 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 05245 SetLastError(ERROR_INVALID_HANDLE); 05246 else if (!DeviceInfoData) 05247 SetLastError(ERROR_INVALID_PARAMETER); 05248 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 05249 SetLastError(ERROR_INVALID_USER_BUFFER); 05250 else 05251 { 05252 SP_DEVINSTALL_PARAMS_W InstallParams; 05253 struct DriverInfoElement *SelectedDriver; 05254 BOOL Result; 05255 DWORD DoAction; 05256 WCHAR SectionName[MAX_PATH]; 05257 DWORD SectionNameLength = 0; 05258 HKEY hKey = INVALID_HANDLE_VALUE; 05259 PVOID Context = NULL; 05260 05261 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 05262 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 05263 if (!Result) 05264 goto cleanup; 05265 05266 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; 05267 if (SelectedDriver == NULL) 05268 { 05269 SetLastError(ERROR_NO_DRIVER_SELECTED); 05270 goto cleanup; 05271 } 05272 05273 /* Get .CoInstallers section name */ 05274 Result = SetupDiGetActualSectionToInstallW( 05275 SelectedDriver->InfFileDetails->hInf, 05276 SelectedDriver->Details.SectionName, 05277 SectionName, MAX_PATH, &SectionNameLength, NULL); 05278 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1) 05279 goto cleanup; 05280 lstrcatW(SectionName, DotCoInstallers); 05281 05282 /* Open/Create driver key information */ 05283 #if _WIN32_WINNT >= 0x502 05284 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE); 05285 #else 05286 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS); 05287 #endif 05288 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 05289 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); 05290 if (hKey == INVALID_HANDLE_VALUE) 05291 goto cleanup; 05292 05293 /* Install .CoInstallers section */ 05294 DoAction = SPINST_REGISTRY; 05295 if (!(InstallParams.Flags & DI_NOFILECOPY)) 05296 { 05297 DoAction |= SPINST_FILES; 05298 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 05299 if (!Context) 05300 goto cleanup; 05301 } 05302 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 05303 SelectedDriver->InfFileDetails->hInf, SectionName, 05304 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 05305 SetupDefaultQueueCallbackW, Context, 05306 DeviceInfoSet, DeviceInfoData); 05307 if (!Result) 05308 goto cleanup; 05309 05310 ret = TRUE; 05311 05312 cleanup: 05313 if (Context) 05314 SetupTermDefaultQueueCallback(Context); 05315 if (hKey != INVALID_HANDLE_VALUE) 05316 RegCloseKey(hKey); 05317 } 05318 05319 TRACE("Returning %d\n", ret); 05320 return ret; 05321 } 05322 05323 static BOOL 05324 InfIsFromOEMLocation( 05325 IN PCWSTR FullName, 05326 OUT LPBOOL IsOEMLocation) 05327 { 05328 PWCHAR last; 05329 05330 last = strrchrW(FullName, '\\'); 05331 if (!last) 05332 { 05333 /* No directory specified */ 05334 *IsOEMLocation = FALSE; 05335 } 05336 else 05337 { 05338 LPWSTR Windir; 05339 UINT ret; 05340 05341 Windir = MyMalloc((MAX_PATH + 1 + strlenW(InfDirectory)) * sizeof(WCHAR)); 05342 if (!Windir) 05343 { 05344 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 05345 return FALSE; 05346 } 05347 05348 ret = GetSystemWindowsDirectoryW(Windir, MAX_PATH); 05349 if (ret == 0 || ret > MAX_PATH) 05350 { 05351 MyFree(Windir); 05352 SetLastError(ERROR_GEN_FAILURE); 05353 return FALSE; 05354 } 05355 if (*Windir && Windir[strlenW(Windir) - 1] != '\\') 05356 strcatW(Windir, BackSlash); 05357 strcatW(Windir, InfDirectory); 05358 05359 if (strncmpiW(FullName, Windir, last - FullName) == 0) 05360 { 05361 /* The path is %SYSTEMROOT%\Inf */ 05362 *IsOEMLocation = FALSE; 05363 } 05364 else 05365 { 05366 /* The file is in another place */ 05367 *IsOEMLocation = TRUE; 05368 } 05369 MyFree(Windir); 05370 } 05371 return TRUE; 05372 } 05373 05374 /*********************************************************************** 05375 * SetupDiInstallDevice (SETUPAPI.@) 05376 */ 05377 BOOL WINAPI 05378 SetupDiInstallDevice( 05379 IN HDEVINFO DeviceInfoSet, 05380 IN OUT PSP_DEVINFO_DATA DeviceInfoData) 05381 { 05382 SP_DEVINSTALL_PARAMS_W InstallParams; 05383 struct DriverInfoElement *SelectedDriver; 05384 SYSTEMTIME DriverDate; 05385 WCHAR SectionName[MAX_PATH]; 05386 WCHAR Buffer[32]; 05387 DWORD SectionNameLength = 0; 05388 BOOL Result = FALSE; 05389 ULONG DoAction; 05390 DWORD RequiredSize; 05391 LPWSTR pSectionName = NULL; 05392 WCHAR ClassName[MAX_CLASS_NAME_LEN]; 05393 GUID ClassGuid; 05394 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL; 05395 BOOL RebootRequired = FALSE; 05396 HKEY hKey = INVALID_HANDLE_VALUE; 05397 BOOL NeedtoCopyFile; 05398 LARGE_INTEGER fullVersion; 05399 LONG rc; 05400 PVOID Context = NULL; 05401 BOOL ret = FALSE; /* Return value */ 05402 05403 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); 05404 05405 if (!DeviceInfoSet) 05406 SetLastError(ERROR_INVALID_PARAMETER); 05407 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) 05408 SetLastError(ERROR_INVALID_HANDLE); 05409 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) 05410 SetLastError(ERROR_INVALID_HANDLE); 05411 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) 05412 SetLastError(ERROR_INVALID_USER_BUFFER); 05413 else 05414 Result = TRUE; 05415 05416 if (!Result) 05417 { 05418 /* One parameter is bad */ 05419 goto cleanup; 05420 } 05421 05422 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); 05423 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 05424 if (!Result) 05425 goto cleanup; 05426 05427 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL) 05428 { 05429 /* Set FAILEDINSTALL in ConfigFlags registry value */ 05430 DWORD ConfigFlags, regType; 05431 Result = SetupDiGetDeviceRegistryPropertyW( 05432 DeviceInfoSet, 05433 DeviceInfoData, 05434 SPDRP_CONFIGFLAGS, 05435 ®Type, 05436 (PBYTE)&ConfigFlags, 05437 sizeof(ConfigFlags), 05438 NULL); 05439 if (!Result || regType != REG_DWORD) 05440 { 05441 SetLastError(ERROR_GEN_FAILURE); 05442 goto cleanup; 05443 } 05444 ConfigFlags |= DNF_DISABLED; 05445 Result = SetupDiSetDeviceRegistryPropertyW( 05446 DeviceInfoSet, 05447 DeviceInfoData, 05448 SPDRP_CONFIGFLAGS, 05449 (PBYTE)&ConfigFlags, 05450 sizeof(ConfigFlags)); 05451 if (!Result) 05452 { 05453 SetLastError(ERROR_GEN_FAILURE); 05454 goto cleanup; 05455 } 05456 05457 ret = TRUE; 05458 goto cleanup; 05459 } 05460 05461 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved; 05462 if (SelectedDriver == NULL) 05463 { 05464 SetLastError(ERROR_NO_DRIVER_SELECTED); 05465 goto cleanup; 05466 } 05467 05468 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate); 05469 05470 Result = SetupDiGetActualSectionToInstallW( 05471 SelectedDriver->InfFileDetails->hInf, 05472 SelectedDriver->Details.SectionName, 05473 SectionName, MAX_PATH, &SectionNameLength, NULL); 05474 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices)) 05475 goto cleanup; 05476 pSectionName = &SectionName[strlenW(SectionName)]; 05477 05478 /* Get information from [Version] section */ 05479 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize)) 05480 goto cleanup; 05481 /* Format ClassGuid to a string */ 05482 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK) 05483 goto cleanup; 05484 RequiredSize = lstrlenW(lpGuidString); 05485 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR)); 05486 if (!lpFullGuidString) 05487 { 05488 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 05489 goto cleanup; 05490 } 05491 lpFullGuidString[0] = '{'; 05492 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR)); 05493 lpFullGuidString[RequiredSize + 1] = '}'; 05494 lpFullGuidString[RequiredSize + 2] = '\0'; 05495 05496 /* Copy .inf file to Inf\ directory (if needed) */ 05497 Result = InfIsFromOEMLocation(SelectedDriver->Details.InfFileName, &NeedtoCopyFile); 05498 if (!Result) 05499 goto cleanup; 05500 if (NeedtoCopyFile) 05501 { 05502 WCHAR NewFileName[MAX_PATH]; 05503 struct InfFileDetails *newInfFileDetails; 05504 Result = SetupCopyOEMInfW( 05505 SelectedDriver->Details.InfFileName, 05506 NULL, 05507 SPOST_NONE, 05508 SP_COPY_NOOVERWRITE, 05509 NewFileName, MAX_PATH, 05510 NULL, 05511 NULL); 05512 if (!Result && GetLastError() != ERROR_FILE_EXISTS) 05513 goto cleanup; 05514 /* Create a new struct InfFileDetails, and set it to 05515 * SelectedDriver->InfFileDetails, to release use of 05516 * current InfFile */ 05517 newInfFileDetails = CreateInfFileDetails(NewFileName); 05518 if (!newInfFileDetails) 05519 goto cleanup; 05520 DereferenceInfFile(SelectedDriver->InfFileDetails); 05521 SelectedDriver->InfFileDetails = newInfFileDetails; 05522 strcpyW(SelectedDriver->Details.InfFileName, NewFileName); 05523 } 05524 05525 /* Open/Create driver key information */ 05526 #if _WIN32_WINNT >= 0x502 05527 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE); 05528 #else 05529 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS); 05530 #endif 05531 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) 05532 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); 05533 if (hKey == INVALID_HANDLE_VALUE) 05534 goto cleanup; 05535 05536 /* Install main section */ 05537 DoAction = 0; 05538 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) 05539 DoAction |= SPINST_REGISTRY; 05540 if (!(InstallParams.Flags & DI_NOFILECOPY)) 05541 { 05542 DoAction |= SPINST_FILES; 05543 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent); 05544 if (!Context) 05545 goto cleanup; 05546 } 05547 *pSectionName = '\0'; 05548 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 05549 SelectedDriver->InfFileDetails->hInf, SectionName, 05550 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER, 05551 SetupDefaultQueueCallbackW, Context, 05552 DeviceInfoSet, DeviceInfoData); 05553 if (!Result) 05554 goto cleanup; 05555 InstallParams.Flags |= DI_NOFILECOPY; 05556 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); 05557 05558 /* Write information to driver key */ 05559 *pSectionName = UNICODE_NULL; 05560 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER)); 05561 TRACE("Write information to driver key\n"); 05562 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear); 05563 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description)); 05564 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff); 05565 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName)); 05566 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName)); 05567 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)])); 05568 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId)); 05569 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName)); 05570 sprintfW(Buffer, DateFormat, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear); 05571 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR)); 05572 if (rc == ERROR_SUCCESS) 05573 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME)); 05574 if (rc == ERROR_SUCCESS) 05575 rc = RegSetValueExW(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR)); 05576 if (rc == ERROR_SUCCESS) 05577 { 05578 sprintfW(Buffer, VersionFormat, fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff); 05579 rc = RegSetValueExW(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR)); 05580 } 05581 if (rc == ERROR_SUCCESS) 05582 rc = RegSetValueExW(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->InfFileDetails->FileName, (strlenW(SelectedDriver->InfFileDetails->FileName) + 1) * sizeof(WCHAR)); 05583 if (rc == ERROR_SUCCESS) 05584 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR)); 05585 if (rc == ERROR_SUCCESS) 05586 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTIONEXT, 0, REG_SZ, (const BYTE *)&SectionName[strlenW(SelectedDriver->Details.SectionName)], (strlenW(SectionName) - strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR)); 05587 if (rc == ERROR_SUCCESS) 05588 rc = RegSetValueExW(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR)); 05589 if (rc == ERROR_SUCCESS) 05590 rc = RegSetValueExW(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR)); 05591 if (rc != ERROR_SUCCESS) 05592 { 05593 SetLastError(rc); 05594 goto cleanup; 05595 } 05596 RegCloseKey(hKey); 05597 hKey = INVALID_HANDLE_VALUE; 05598 05599 /* FIXME: Process .LogConfigOverride section */ 05600 05601 /* Install .Services section */ 05602 strcpyW(pSectionName, DotServices); 05603 Result = SetupInstallServicesFromInfSectionExW( 05604 SelectedDriver->InfFileDetails->hInf, 05605 SectionName, 05606 0, 05607 DeviceInfoSet, 05608 DeviceInfoData, 05609 NULL, 05610 NULL); 05611 if (!Result) 05612 goto cleanup; 05613 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED) 05614 RebootRequired = TRUE; 05615 05616 /* Open device registry key */ 05617 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE); 05618 if (hKey == INVALID_HANDLE_VALUE) 05619 goto cleanup; 05620 05621 /* Install .HW section */ 05622 DoAction = 0; 05623 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) 05624 DoAction |= SPINST_REGISTRY; 05625 strcpyW(pSectionName, DotHW); 05626 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent, 05627 SelectedDriver->InfFileDetails->hInf, SectionName, 05628 DoAction, hKey, NULL, 0, 05629 NULL, NULL, 05630 DeviceInfoSet, DeviceInfoData); 05631 if (!Result) 05632 goto cleanup; 05633 05634 /* Write information to enum key */ 05635 TRACE("Write information to enum key\n"); 05636 TRACE("Class : '%s'\n", debugstr_w(ClassName)); 05637 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString)); 05638 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description)); 05639 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName)); 05640 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR)); 05641 if (rc == ERROR_SUCCESS) 05642 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR)); 05643 if (rc == ERROR_SUCCESS) 05644 rc = RegSetValueExW(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR)); 05645 if (rc == ERROR_SUCCESS) 05646 rc = RegSetValueExW(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR)); 05647 if (rc != ERROR_SUCCESS) 05648 { 05649 SetLastError(rc); 05650 goto cleanup; 05651 } 05652 05653 /* Start the device */ 05654 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG))) 05655 ret = ResetDevice(DeviceInfoSet, DeviceInfoData); 05656 else 05657 ret = TRUE; 05658 05659 cleanup: 05660 /* End of installation */ 05661 if (hKey != INVALID_HANDLE_VALUE) 05662 RegCloseKey(hKey); 05663 if (lpGuidString) 05664 RpcStringFreeW(&lpGuidString); 05665 HeapFree(GetProcessHeap(), 0, lpFullGuidString); 05666 if (Context) 05667 SetupTermDefaultQueueCallback(Context); 05668 TRACE("Returning %d\n", ret); 05669 return ret; 05670 } 05671 05672 static HKEY SETUPDI_OpenDevKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired) 05673 { 05674 HKEY enumKey, key = INVALID_HANDLE_VALUE; 05675 LONG l; 05676 05677 l = RegOpenKeyExW(RootKey, REGSTR_PATH_SYSTEMENUM, 0, 0, &enumKey); 05678 if (!l) 05679 { 05680 l = RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key); 05681 RegCloseKey(enumKey); 05682 } 05683 if (l) 05684 SetLastError(l); 05685 return key; 05686 } 05687 05688 static HKEY SETUPDI_OpenDrvKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired) 05689 { 05690 LPWSTR DriverKey = NULL; 05691 DWORD dwLength = 0; 05692 DWORD dwRegType; 05693 DWORD rc; 05694 HKEY hEnumKey = NULL; 05695 HKEY hKey = NULL; 05696 HKEY key = INVALID_HANDLE_VALUE; 05697 05698 hKey = SETUPDI_OpenDevKey(RootKey, devInfo, KEY_QUERY_VALUE); 05699 if (hKey == INVALID_HANDLE_VALUE) 05700 goto cleanup; 05701 /* Read the 'Driver' key */ 05702 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength); 05703 if (rc != ERROR_SUCCESS) 05704 { 05705 SetLastError(rc); 05706 goto cleanup; 05707 } 05708 else if (dwRegType != REG_SZ) 05709 { 05710 SetLastError(ERROR_GEN_FAILURE); 05711 goto cleanup; 05712 } 05713 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength); 05714 if (!DriverKey) 05715 { 05716 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 05717 goto cleanup; 05718 } 05719 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength); 05720 if (rc != ERROR_SUCCESS) 05721 { 05722 SetLastError(rc); 05723 goto cleanup; 05724 } 05725 RegCloseKey(hKey); 05726 hKey = NULL; 05727 /* Need to open the driver key */ 05728 rc = RegOpenKeyExW( 05729 RootKey, 05730 REGSTR_PATH_CLASS_NT, 05731 0, /* Options */ 05732 0, 05733 &hEnumKey); 05734 if (rc != ERROR_SUCCESS) 05735 { 05736 SetLastError(rc); 05737 goto cleanup; 05738 } 05739 rc = RegOpenKeyExW( 05740 hEnumKey, 05741 DriverKey, 05742 0, /* Options */ 05743 samDesired, 05744 &hKey); 05745 if (rc != ERROR_SUCCESS) 05746 { 05747 SetLastError(rc); 05748 goto cleanup; 05749 } 05750 key = hKey; 05751 05752 cleanup: 05753 if (hEnumKey != NULL) 05754 RegCloseKey(hEnumKey); 05755 if (hKey != NULL && hKey != key) 05756 RegCloseKey(hKey); 05757 return key; 05758 } 05759 05760 /*********************************************************************** 05761 * SetupDiOpenDevRegKey (SETUPAPI.@) 05762 */ 05763 HKEY WINAPI SetupDiOpenDevRegKey( 05764 HDEVINFO DeviceInfoSet, 05765 PSP_DEVINFO_DATA DeviceInfoData, 05766 DWORD Scope, 05767 DWORD HwProfile, 05768 DWORD KeyType, 05769 REGSAM samDesired) 05770 { 05771 struct DeviceInfoSet *set = DeviceInfoSet; 05772 struct DeviceInfo *devInfo; 05773 HKEY key = INVALID_HANDLE_VALUE; 05774 HKEY RootKey; 05775 05776 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData, 05777 Scope, HwProfile, KeyType, samDesired); 05778 05779 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 05780 { 05781 SetLastError(ERROR_INVALID_HANDLE); 05782 return INVALID_HANDLE_VALUE; 05783 } 05784 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 05785 { 05786 SetLastError(ERROR_INVALID_HANDLE); 05787 return INVALID_HANDLE_VALUE; 05788 } 05789 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 05790 || !DeviceInfoData->Reserved) 05791 { 05792 SetLastError(ERROR_INVALID_PARAMETER); 05793 return INVALID_HANDLE_VALUE; 05794 } 05795 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 05796 { 05797 SetLastError(ERROR_INVALID_FLAGS); 05798 return INVALID_HANDLE_VALUE; 05799 } 05800 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV) 05801 { 05802 SetLastError(ERROR_INVALID_FLAGS); 05803 return INVALID_HANDLE_VALUE; 05804 } 05805 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 05806 if (devInfo->set != set) 05807 { 05808 SetLastError(ERROR_INVALID_PARAMETER); 05809 return INVALID_HANDLE_VALUE; 05810 } 05811 if (Scope != DICS_FLAG_GLOBAL) 05812 { 05813 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0); 05814 if (RootKey == INVALID_HANDLE_VALUE) 05815 return INVALID_HANDLE_VALUE; 05816 } 05817 else 05818 RootKey = set->HKLM; 05819 switch (KeyType) 05820 { 05821 case DIREG_DEV: 05822 key = SETUPDI_OpenDevKey(RootKey, devInfo, samDesired); 05823 break; 05824 case DIREG_DRV: 05825 key = SETUPDI_OpenDrvKey(RootKey, devInfo, samDesired); 05826 break; 05827 default: 05828 WARN("unknown KeyType %d\n", KeyType); 05829 } 05830 if (RootKey != set->HKLM) 05831 RegCloseKey(RootKey); 05832 return key; 05833 } 05834 05835 static BOOL SETUPDI_DeleteDevKey(HKEY RootKey, struct DeviceInfo *devInfo) 05836 { 05837 FIXME("\n"); 05838 return FALSE; 05839 } 05840 05841 static BOOL SETUPDI_DeleteDrvKey(HKEY RootKey, struct DeviceInfo *devInfo) 05842 { 05843 FIXME("\n"); 05844 return FALSE; 05845 } 05846 05847 /*********************************************************************** 05848 * SetupDiDeleteDevRegKey (SETUPAPI.@) 05849 */ 05850 BOOL WINAPI SetupDiDeleteDevRegKey( 05851 HDEVINFO DeviceInfoSet, 05852 PSP_DEVINFO_DATA DeviceInfoData, 05853 DWORD Scope, 05854 DWORD HwProfile, 05855 DWORD KeyType) 05856 { 05857 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; 05858 struct DeviceInfo *devInfo; 05859 BOOL ret = FALSE; 05860 HKEY RootKey; 05861 05862 TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile, 05863 KeyType); 05864 05865 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE) 05866 { 05867 SetLastError(ERROR_INVALID_HANDLE); 05868 return FALSE; 05869 } 05870 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) 05871 { 05872 SetLastError(ERROR_INVALID_HANDLE); 05873 return FALSE; 05874 } 05875 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) 05876 || !DeviceInfoData->Reserved) 05877 { 05878 SetLastError(ERROR_INVALID_PARAMETER); 05879 return FALSE; 05880 } 05881 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC) 05882 { 05883 SetLastError(ERROR_INVALID_FLAGS); 05884 return FALSE; 05885 } 05886 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH) 05887 { 05888 SetLastError(ERROR_INVALID_FLAGS); 05889 return FALSE; 05890 } 05891 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; 05892 if (devInfo->set != set) 05893 { 05894 SetLastError(ERROR_INVALID_PARAMETER); 05895 return FALSE; 05896 } 05897 if (Scope != DICS_FLAG_GLOBAL) 05898 { 05899 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0); 05900 if (RootKey == INVALID_HANDLE_VALUE) 05901 return FALSE; 05902 } 05903 else 05904 RootKey = set->HKLM; 05905 switch (KeyType) 05906 { 05907 case DIREG_DEV: 05908 ret = SETUPDI_DeleteDevKey(RootKey, devInfo); 05909 break; 05910 case DIREG_DRV: 05911 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo); 05912 break; 05913 case DIREG_BOTH: 05914 ret = SETUPDI_DeleteDevKey(RootKey, devInfo); 05915 if (ret) 05916 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo); 05917 break; 05918 default: 05919 WARN("unknown KeyType %d\n", KeyType); 05920 } 05921 if (RootKey != set->HKLM) 05922 RegCloseKey(RootKey); 05923 return ret; 05924 } Generated on Sat May 26 2012 04:16:55 for ReactOS by
1.7.6.1
|