[KS]
[reactos.git] / reactos / dll / win32 / setupapi / devinst.c
1 /*
2 * SetupAPI device installer
3 *
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "setupapi_private.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
25
26 /* Unicode constants */
27 static const WCHAR BackSlash[] = {'\\',0};
28 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class[] = {'C','l','a','s','s',0};
30 static const WCHAR DateFormat[] = {'%','u','-','%','u','-','%','u',0};
31 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
32 static const WCHAR DotHW[] = {'.','H','W',0};
33 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
34 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
35 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0};
36 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
37 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
38
39 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0};
40 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
41 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
42 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0};
43 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};
44
45 typedef DWORD
46 (CALLBACK* CLASS_INSTALL_PROC) (
47 IN DI_FUNCTION InstallFunction,
48 IN HDEVINFO DeviceInfoSet,
49 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
50 typedef BOOL
51 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
52 IN HDEVINFO DeviceInfoSet,
53 IN OUT PSP_DEVINFO_DATA DeviceInfoData);
54 typedef DWORD
55 (CALLBACK* COINSTALLER_PROC) (
56 IN DI_FUNCTION InstallFunction,
57 IN HDEVINFO DeviceInfoSet,
58 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
59 IN OUT PCOINSTALLER_CONTEXT_DATA Context);
60
61 struct CoInstallerElement
62 {
63 LIST_ENTRY ListEntry;
64
65 HMODULE Module;
66 COINSTALLER_PROC Function;
67 BOOL DoPostProcessing;
68 PVOID PrivateData;
69 };
70
71 struct GetSectionCallbackInfo
72 {
73 PSP_ALTPLATFORM_INFO PlatformInfo;
74 BYTE ProductType;
75 WORD SuiteMask;
76 DWORD PrefixLength;
77 WCHAR BestSection[LINE_LEN + 1];
78 DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5;
79 };
80
81
82
83 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
84 {
85 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
86 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
87 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
88 '0','2','X','}',0};
89
90 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
91 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
92 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
93 }
94
95 static DWORD
96 GetErrorCodeFromCrCode(const IN CONFIGRET cr)
97 {
98 switch (cr)
99 {
100 case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED;
101 case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER;
102 case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED;
103 case CR_FAILURE: return ERROR_GEN_FAILURE;
104 case CR_INVALID_DATA: return ERROR_INVALID_USER_BUFFER;
105 case CR_INVALID_DEVICE_ID: return ERROR_INVALID_PARAMETER;
106 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
107 case CR_INVALID_DEVNODE: return ERROR_INVALID_PARAMETER;
108 case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS;
109 case CR_INVALID_POINTER: return ERROR_INVALID_PARAMETER;
110 case CR_INVALID_PROPERTY: return ERROR_INVALID_PARAMETER;
111 case CR_NO_SUCH_DEVNODE: return ERROR_FILE_NOT_FOUND;
112 case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND;
113 case CR_NO_SUCH_VALUE: return ERROR_FILE_NOT_FOUND;
114 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
115 case CR_REGISTRY_ERROR: return ERROR_GEN_FAILURE;
116 case CR_SUCCESS: return ERROR_SUCCESS;
117 default: return ERROR_GEN_FAILURE;
118 }
119
120 /* Does not happen */
121 }
122
123 /* Lower scores are best ones */
124 static BOOL
125 CheckSectionValid(
126 IN LPCWSTR SectionName,
127 IN PSP_ALTPLATFORM_INFO PlatformInfo,
128 IN BYTE ProductType,
129 IN WORD SuiteMask,
130 OUT PDWORD ScorePlatform,
131 OUT PDWORD ScoreMajorVersion,
132 OUT PDWORD ScoreMinorVersion,
133 OUT PDWORD ScoreProductType,
134 OUT PDWORD ScoreSuiteMask)
135 {
136 LPWSTR Section = NULL;
137 LPCWSTR pExtensionPlatform, pExtensionArchitecture;
138 LPWSTR Fields[6];
139 DWORD i;
140 BOOL ret = FALSE;
141
142 static const WCHAR ExtensionPlatformNone[] = {'.',0};
143 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
144 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
145
146 static const WCHAR ExtensionArchitectureNone[] = {0};
147 static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0};
148 static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0};
149 static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0};
150 static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0};
151 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
152 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
153
154 TRACE("%s %p 0x%x 0x%x\n",
155 debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask);
156
157 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0;
158
159 Section = DuplicateString(SectionName);
160 if (!Section)
161 {
162 TRACE("DuplicateString() failed\n");
163 goto cleanup;
164 }
165
166 /* Set various extensions values */
167 switch (PlatformInfo->Platform)
168 {
169 case VER_PLATFORM_WIN32_WINDOWS:
170 pExtensionPlatform = ExtensionPlatformWindows;
171 break;
172 case VER_PLATFORM_WIN32_NT:
173 pExtensionPlatform = ExtensionPlatformNT;
174 break;
175 default:
176 ERR("Unknown platform 0x%lx\n", PlatformInfo->Platform);
177 pExtensionPlatform = ExtensionPlatformNone;
178 break;
179 }
180 switch (PlatformInfo->ProcessorArchitecture)
181 {
182 case PROCESSOR_ARCHITECTURE_ALPHA:
183 pExtensionArchitecture = ExtensionArchitecturealpha;
184 break;
185 case PROCESSOR_ARCHITECTURE_AMD64:
186 pExtensionArchitecture = ExtensionArchitectureamd64;
187 break;
188 case PROCESSOR_ARCHITECTURE_IA64:
189 pExtensionArchitecture = ExtensionArchitectureia64;
190 break;
191 case PROCESSOR_ARCHITECTURE_INTEL:
192 pExtensionArchitecture = ExtensionArchitecturex86;
193 break;
194 case PROCESSOR_ARCHITECTURE_MIPS:
195 pExtensionArchitecture = ExtensionArchitecturemips;
196 break;
197 case PROCESSOR_ARCHITECTURE_PPC:
198 pExtensionArchitecture = ExtensionArchitectureppc;
199 break;
200 default:
201 ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture);
202 case PROCESSOR_ARCHITECTURE_UNKNOWN:
203 pExtensionArchitecture = ExtensionArchitectureNone;
204 break;
205 }
206
207 /*
208 * Field[0] Platform
209 * Field[1] Architecture
210 * Field[2] Major version
211 * Field[3] Minor version
212 * Field[4] Product type
213 * Field[5] Suite mask
214 * Remark: lastests fields may be NULL if the information is not provided
215 */
216 Fields[0] = Section;
217 if (Fields[0] == NULL)
218 {
219 TRACE("No extension found\n");
220 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX;
221 ret = TRUE;
222 goto cleanup;
223 }
224 Fields[1] = Fields[0] + 1;
225 Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL;
226 for (i = 2; Fields[i - 1] != NULL && i < 6; i++)
227 {
228 Fields[i] = wcschr(Fields[i - 1], '.');
229 if (Fields[i])
230 {
231 Fields[i]++;
232 *(Fields[i] - 1) = UNICODE_NULL;
233 }
234 }
235 /* Take care of first 2 fields */
236 if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0)
237 {
238 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS)
239 {
240 TRACE("Mismatch on platform field\n");
241 goto cleanup;
242 }
243 Fields[1] += wcslen(ExtensionPlatformWindows) - 1;
244 }
245 else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0)
246 {
247 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT)
248 {
249 TRACE("Mismatch on platform field\n");
250 goto cleanup;
251 }
252 Fields[1] += wcslen(ExtensionPlatformNT) - 1;
253 }
254 else
255 {
256 /* No platform specified */
257 *ScorePlatform |= 0x02;
258 }
259 if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0)
260 {
261 /* No architecture specified */
262 *ScorePlatform |= 0x01;
263 }
264 else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0)
265 {
266 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
267 debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture));
268 goto cleanup;
269 }
270
271 /* Check if informations are matching */
272 if (Fields[2] && *Fields[2])
273 {
274 DWORD MajorVersion, MinorVersion = 0;
275 MajorVersion = strtoulW(Fields[2], NULL, 0);
276 if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) &&
277 (errno == ERANGE || errno == EINVAL))
278 {
279 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2]));
280 goto cleanup;
281 }
282 if (Fields[3] && *Fields[3])
283 {
284 MinorVersion = strtoulW(Fields[3], NULL, 0);
285 if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) &&
286 (errno == ERANGE || errno == EINVAL))
287 {
288 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3]));
289 goto cleanup;
290 }
291 }
292 if (PlatformInfo->MajorVersion < MajorVersion ||
293 (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion))
294 {
295 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
296 MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion);
297 goto cleanup;
298 }
299 *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion;
300 if (MajorVersion == PlatformInfo->MajorVersion)
301 *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion;
302 else
303 *ScoreMinorVersion = MinorVersion;
304 }
305 else if (Fields[3] && *Fields[3])
306 {
307 TRACE("Minor version found without major version\n");
308 goto cleanup;
309 }
310 else
311 {
312 *ScoreMajorVersion = PlatformInfo->MajorVersion;
313 *ScoreMinorVersion = PlatformInfo->MinorVersion;
314 }
315
316 if (Fields[4] && *Fields[4])
317 {
318 DWORD CurrentProductType;
319 CurrentProductType = strtoulW(Fields[4], NULL, 0);
320 if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) &&
321 (errno == ERANGE || errno == EINVAL))
322 {
323 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4]));
324 goto cleanup;
325 }
326 if (CurrentProductType != ProductType)
327 {
328 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
329 CurrentProductType, ProductType);
330 goto cleanup;
331 }
332 }
333 else
334 *ScoreProductType = 1;
335
336 if (Fields[5] && *Fields[5])
337 {
338 DWORD CurrentSuiteMask;
339 CurrentSuiteMask = strtoulW(Fields[5], NULL, 0);
340 if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) &&
341 (errno == ERANGE || errno == EINVAL))
342 {
343 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5]));
344 goto cleanup;
345 }
346 if ((CurrentSuiteMask & ~SuiteMask) != 0)
347 {
348 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
349 CurrentSuiteMask, SuiteMask);
350 goto cleanup;
351 }
352 *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask;
353 }
354 else
355 *ScoreSuiteMask = SuiteMask;
356
357 ret = TRUE;
358
359 cleanup:
360 MyFree(Section);
361 return ret;
362 }
363
364 static BOOL
365 GetSectionCallback(
366 IN LPCWSTR SectionName,
367 IN PVOID Context)
368 {
369 struct GetSectionCallbackInfo *info = Context;
370 DWORD Score1, Score2, Score3, Score4, Score5;
371 BOOL ret;
372
373 if (SectionName[info->PrefixLength] != '.')
374 return TRUE;
375
376 ret = CheckSectionValid(
377 &SectionName[info->PrefixLength],
378 info->PlatformInfo,
379 info->ProductType,
380 info->SuiteMask,
381 &Score1, &Score2, &Score3, &Score4, &Score5);
382 if (!ret)
383 {
384 TRACE("Section %s not compatible\n", debugstr_w(SectionName));
385 return TRUE;
386 }
387 if (Score1 > info->BestScore1) goto done;
388 if (Score1 < info->BestScore1) goto bettersection;
389 if (Score2 > info->BestScore2) goto done;
390 if (Score2 < info->BestScore2) goto bettersection;
391 if (Score3 > info->BestScore3) goto done;
392 if (Score3 < info->BestScore3) goto bettersection;
393 if (Score4 > info->BestScore4) goto done;
394 if (Score4 < info->BestScore4) goto bettersection;
395 if (Score5 > info->BestScore5) goto done;
396 if (Score5 < info->BestScore5) goto bettersection;
397 goto done;
398
399 bettersection:
400 strcpyW(info->BestSection, SectionName);
401 info->BestScore1 = Score1;
402 info->BestScore2 = Score2;
403 info->BestScore3 = Score3;
404 info->BestScore4 = Score4;
405 info->BestScore5 = Score5;
406
407 done:
408 return TRUE;
409 }
410
411 /***********************************************************************
412 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
413 */
414 BOOL WINAPI
415 SetupDiGetActualSectionToInstallExW(
416 IN HINF InfHandle,
417 IN PCWSTR InfSectionName,
418 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
419 OUT PWSTR InfSectionWithExt OPTIONAL,
420 IN DWORD InfSectionWithExtSize,
421 OUT PDWORD RequiredSize OPTIONAL,
422 OUT PWSTR* Extension OPTIONAL,
423 IN PVOID Reserved)
424 {
425 BOOL ret = FALSE;
426
427 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
428 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
429 RequiredSize, Extension, Reserved);
430
431 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
432 SetLastError(ERROR_INVALID_HANDLE);
433 else if (!InfSectionName)
434 SetLastError(ERROR_INVALID_PARAMETER);
435 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
436 SetLastError(ERROR_INVALID_USER_BUFFER);
437 else if (Reserved != NULL)
438 SetLastError(ERROR_INVALID_PARAMETER);
439 else
440 {
441 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
442 static BYTE CurrentProductType = 0;
443 static WORD CurrentSuiteMask = 0;
444 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
445 struct GetSectionCallbackInfo CallbackInfo;
446 DWORD dwFullLength;
447 BYTE ProductType;
448 WORD SuiteMask;
449
450 /* Fill platform info if needed */
451 if (AlternatePlatformInfo)
452 {
453 pPlatformInfo = AlternatePlatformInfo;
454 ProductType = 0;
455 SuiteMask = 0;
456 }
457 else
458 {
459 if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
460 {
461 /* That's the first time we go here. We need to fill in the structure */
462 OSVERSIONINFOEX VersionInfo;
463 SYSTEM_INFO SystemInfo;
464 VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
465 ret = GetVersionExW((OSVERSIONINFO*)&VersionInfo);
466 if (!ret)
467 goto done;
468 GetSystemInfo(&SystemInfo);
469 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
470 CurrentPlatform.Platform = VersionInfo.dwPlatformId;
471 CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion;
472 CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion;
473 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
474 CurrentPlatform.Reserved = 0;
475 CurrentProductType = VersionInfo.wProductType;
476 CurrentSuiteMask = VersionInfo.wSuiteMask;
477 }
478 ProductType = CurrentProductType;
479 SuiteMask = CurrentSuiteMask;
480 }
481
482 CallbackInfo.PlatformInfo = pPlatformInfo;
483 CallbackInfo.ProductType = ProductType;
484 CallbackInfo.SuiteMask = SuiteMask;
485 CallbackInfo.PrefixLength = strlenW(InfSectionName);
486 CallbackInfo.BestScore1 = ULONG_MAX;
487 CallbackInfo.BestScore2 = ULONG_MAX;
488 CallbackInfo.BestScore3 = ULONG_MAX;
489 CallbackInfo.BestScore4 = ULONG_MAX;
490 CallbackInfo.BestScore5 = ULONG_MAX;
491 strcpyW(CallbackInfo.BestSection, InfSectionName);
492 if (!EnumerateSectionsStartingWith(
493 InfHandle,
494 InfSectionName,
495 GetSectionCallback,
496 &CallbackInfo))
497 {
498 SetLastError(ERROR_GEN_FAILURE);
499 goto done;
500 }
501
502 dwFullLength = lstrlenW(CallbackInfo.BestSection);
503 if (RequiredSize != NULL)
504 *RequiredSize = dwFullLength + 1;
505
506 if (InfSectionWithExtSize > 0)
507 {
508 if (InfSectionWithExtSize < dwFullLength + 1)
509 {
510 SetLastError(ERROR_INSUFFICIENT_BUFFER);
511 goto done;
512 }
513 strcpyW(InfSectionWithExt, CallbackInfo.BestSection);
514 if (Extension)
515 {
516 DWORD dwLength = lstrlenW(InfSectionName);
517 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
518 }
519 }
520
521 ret = TRUE;
522 }
523
524 done:
525 TRACE("Returning %d\n", ret);
526 return ret;
527 }
528
529
530 BOOL
531 CreateDeviceInfo(
532 IN struct DeviceInfoSet *list,
533 IN LPCWSTR InstancePath,
534 IN LPCGUID pClassGuid,
535 OUT struct DeviceInfo **pDeviceInfo)
536 {
537 DWORD size;
538 CONFIGRET cr;
539 struct DeviceInfo *deviceInfo;
540
541 *pDeviceInfo = NULL;
542
543 size = FIELD_OFFSET(struct DeviceInfo, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR);
544 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
545 if (!deviceInfo)
546 {
547 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
548 return FALSE;
549 }
550 ZeroMemory(deviceInfo, size);
551
552 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
553 if (cr != CR_SUCCESS)
554 {
555 SetLastError(GetErrorCodeFromCrCode(cr));
556 return FALSE;
557 }
558
559 deviceInfo->set = list;
560 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
561 strcpyW(deviceInfo->Data, InstancePath);
562 deviceInfo->instanceId = deviceInfo->Data;
563 deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
564 deviceInfo->DeviceDescription = NULL;
565 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
566 deviceInfo->CreationFlags = 0;
567 InitializeListHead(&deviceInfo->DriverListHead);
568 InitializeListHead(&deviceInfo->InterfaceListHead);
569
570 *pDeviceInfo = deviceInfo;
571 return TRUE;
572 }
573
574
575 static BOOL
576 DestroyClassInstallParams(struct ClassInstallParams* installParams)
577 {
578 HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams);
579 HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData);
580 return TRUE;
581 }
582
583 static BOOL
584 DestroyDeviceInfo(struct DeviceInfo *deviceInfo)
585 {
586 PLIST_ENTRY ListEntry;
587 struct DriverInfoElement *driverInfo;
588 struct DeviceInterface *deviceInterface;
589
590 while (!IsListEmpty(&deviceInfo->DriverListHead))
591 {
592 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
593 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
594 if (!DestroyDriverInfoElement(driverInfo))
595 return FALSE;
596 }
597 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
598 {
599 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
600 deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
601 if (!DestroyDeviceInterface(deviceInterface))
602 return FALSE;
603 }
604 DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
605 return HeapFree(GetProcessHeap(), 0, deviceInfo);
606 }
607
608 static BOOL
609 DestroyDeviceInfoSet(struct DeviceInfoSet* list)
610 {
611 PLIST_ENTRY ListEntry;
612 struct DeviceInfo *deviceInfo;
613
614 while (!IsListEmpty(&list->ListHead))
615 {
616 ListEntry = RemoveHeadList(&list->ListHead);
617 deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry);
618 if (!DestroyDeviceInfo(deviceInfo))
619 return FALSE;
620 }
621 if (list->HKLM != HKEY_LOCAL_MACHINE)
622 RegCloseKey(list->HKLM);
623 CM_Disconnect_Machine(list->hMachine);
624 DestroyClassInstallParams(&list->ClassInstallParams);
625 return HeapFree(GetProcessHeap(), 0, list);
626 }
627
628 /***********************************************************************
629 * SetupDiBuildClassInfoList (SETUPAPI.@)
630 *
631 * Returns a list of setup class GUIDs that identify the classes
632 * that are installed on a local machine.
633 *
634 * PARAMS
635 * Flags [I] control exclusion of classes from the list.
636 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
637 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
638 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
639 *
640 * RETURNS
641 * Success: TRUE.
642 * Failure: FALSE.
643 */
644 BOOL WINAPI SetupDiBuildClassInfoList(
645 DWORD Flags,
646 LPGUID ClassGuidList,
647 DWORD ClassGuidListSize,
648 PDWORD RequiredSize)
649 {
650 TRACE("\n");
651 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
652 ClassGuidListSize, RequiredSize,
653 NULL, NULL);
654 }
655
656 /***********************************************************************
657 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
658 *
659 * Returns a list of setup class GUIDs that identify the classes
660 * that are installed on a local or remote macine.
661 *
662 * PARAMS
663 * Flags [I] control exclusion of classes from the list.
664 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
665 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
666 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
667 * MachineName [I] name of a remote machine.
668 * Reserved [I] must be NULL.
669 *
670 * RETURNS
671 * Success: TRUE.
672 * Failure: FALSE.
673 */
674 BOOL WINAPI SetupDiBuildClassInfoListExA(
675 DWORD Flags,
676 LPGUID ClassGuidList,
677 DWORD ClassGuidListSize,
678 PDWORD RequiredSize,
679 LPCSTR MachineName,
680 PVOID Reserved)
681 {
682 LPWSTR MachineNameW = NULL;
683 BOOL bResult;
684
685 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
686 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
687
688 if (MachineName)
689 {
690 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
691 if (MachineNameW == NULL) return FALSE;
692 }
693
694 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
695 ClassGuidListSize, RequiredSize,
696 MachineNameW, Reserved);
697
698 MyFree(MachineNameW);
699
700 return bResult;
701 }
702
703 /***********************************************************************
704 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
705 *
706 * Returns a list of setup class GUIDs that identify the classes
707 * that are installed on a local or remote macine.
708 *
709 * PARAMS
710 * Flags [I] control exclusion of classes from the list.
711 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
712 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
713 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
714 * MachineName [I] name of a remote machine.
715 * Reserved [I] must be NULL.
716 *
717 * RETURNS
718 * Success: TRUE.
719 * Failure: FALSE.
720 */
721 BOOL WINAPI SetupDiBuildClassInfoListExW(
722 DWORD Flags,
723 LPGUID ClassGuidList,
724 DWORD ClassGuidListSize,
725 PDWORD RequiredSize,
726 LPCWSTR MachineName,
727 PVOID Reserved)
728 {
729 WCHAR szKeyName[40];
730 HKEY hClassesKey = INVALID_HANDLE_VALUE;
731 HKEY hClassKey;
732 DWORD dwLength;
733 DWORD dwIndex;
734 LONG lError;
735 DWORD dwGuidListIndex = 0;
736
737 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
738 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
739
740 if (!RequiredSize)
741 {
742 SetLastError(ERROR_INVALID_PARAMETER);
743 return FALSE;
744 }
745 else if (!ClassGuidList && ClassGuidListSize > 0)
746 {
747 SetLastError(ERROR_INVALID_PARAMETER);
748 return FALSE;
749 }
750
751 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
752 KEY_ENUMERATE_SUB_KEYS,
753 DIOCR_INSTALLER,
754 MachineName,
755 Reserved);
756 if (hClassesKey == INVALID_HANDLE_VALUE)
757 {
758 return FALSE;
759 }
760
761 for (dwIndex = 0; ; dwIndex++)
762 {
763 dwLength = 40;
764 lError = RegEnumKeyExW(hClassesKey,
765 dwIndex,
766 szKeyName,
767 &dwLength,
768 NULL,
769 NULL,
770 NULL,
771 NULL);
772 TRACE("RegEnumKeyExW() returns %d\n", lError);
773 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
774 {
775 TRACE("Key name: %s\n", debugstr_w(szKeyName));
776
777 if (RegOpenKeyExW(hClassesKey,
778 szKeyName,
779 0,
780 KEY_QUERY_VALUE,
781 &hClassKey))
782 {
783 RegCloseKey(hClassesKey);
784 return FALSE;
785 }
786
787 if (!RegQueryValueExW(hClassKey,
788 REGSTR_VAL_NOUSECLASS,
789 NULL,
790 NULL,
791 NULL,
792 NULL))
793 {
794 TRACE("'NoUseClass' value found!\n");
795 RegCloseKey(hClassKey);
796 continue;
797 }
798
799 if ((Flags & DIBCI_NOINSTALLCLASS) &&
800 (!RegQueryValueExW(hClassKey,
801 REGSTR_VAL_NOINSTALLCLASS,
802 NULL,
803 NULL,
804 NULL,
805 NULL)))
806 {
807 TRACE("'NoInstallClass' value found!\n");
808 RegCloseKey(hClassKey);
809 continue;
810 }
811
812 if ((Flags & DIBCI_NODISPLAYCLASS) &&
813 (!RegQueryValueExW(hClassKey,
814 REGSTR_VAL_NODISPLAYCLASS,
815 NULL,
816 NULL,
817 NULL,
818 NULL)))
819 {
820 TRACE("'NoDisplayClass' value found!\n");
821 RegCloseKey(hClassKey);
822 continue;
823 }
824
825 RegCloseKey(hClassKey);
826
827 TRACE("Guid: %s\n", debugstr_w(szKeyName));
828 if (dwGuidListIndex < ClassGuidListSize)
829 {
830 if (szKeyName[0] == '{' && szKeyName[37] == '}')
831 {
832 szKeyName[37] = 0;
833 }
834 TRACE("Guid: %p\n", &szKeyName[1]);
835
836 UuidFromStringW(&szKeyName[1],
837 &ClassGuidList[dwGuidListIndex]);
838 }
839
840 dwGuidListIndex++;
841 }
842
843 if (lError != ERROR_SUCCESS)
844 break;
845 }
846
847 RegCloseKey(hClassesKey);
848
849 if (RequiredSize != NULL)
850 *RequiredSize = dwGuidListIndex;
851
852 if (ClassGuidListSize < dwGuidListIndex)
853 {
854 SetLastError(ERROR_INSUFFICIENT_BUFFER);
855 return FALSE;
856 }
857
858 return TRUE;
859 }
860
861 /***********************************************************************
862 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
863 */
864 BOOL WINAPI SetupDiClassGuidsFromNameA(
865 LPCSTR ClassName,
866 LPGUID ClassGuidList,
867 DWORD ClassGuidListSize,
868 PDWORD RequiredSize)
869 {
870 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
871 ClassGuidListSize, RequiredSize,
872 NULL, NULL);
873 }
874
875 /***********************************************************************
876 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
877 */
878 BOOL WINAPI SetupDiClassGuidsFromNameW(
879 LPCWSTR ClassName,
880 LPGUID ClassGuidList,
881 DWORD ClassGuidListSize,
882 PDWORD RequiredSize)
883 {
884 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
885 ClassGuidListSize, RequiredSize,
886 NULL, NULL);
887 }
888
889 /***********************************************************************
890 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
891 */
892 BOOL WINAPI SetupDiClassGuidsFromNameExA(
893 LPCSTR ClassName,
894 LPGUID ClassGuidList,
895 DWORD ClassGuidListSize,
896 PDWORD RequiredSize,
897 LPCSTR MachineName,
898 PVOID Reserved)
899 {
900 LPWSTR ClassNameW = NULL;
901 LPWSTR MachineNameW = NULL;
902 BOOL bResult;
903
904 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName), ClassGuidList,
905 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
906
907 if (!ClassName)
908 {
909 SetLastError(ERROR_INVALID_PARAMETER);
910 return FALSE;
911 }
912
913 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
914 if (ClassNameW == NULL)
915 return FALSE;
916
917 if (MachineName)
918 {
919 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
920 if (MachineNameW == NULL)
921 {
922 MyFree(ClassNameW);
923 return FALSE;
924 }
925 }
926
927 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
928 ClassGuidListSize, RequiredSize,
929 MachineNameW, Reserved);
930
931 MyFree(MachineNameW);
932 MyFree(ClassNameW);
933
934 return bResult;
935 }
936
937 /***********************************************************************
938 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
939 */
940 BOOL WINAPI SetupDiClassGuidsFromNameExW(
941 LPCWSTR ClassName,
942 LPGUID ClassGuidList,
943 DWORD ClassGuidListSize,
944 PDWORD RequiredSize,
945 LPCWSTR MachineName,
946 PVOID Reserved)
947 {
948 WCHAR szKeyName[40];
949 WCHAR szClassName[MAX_CLASS_NAME_LEN];
950 HKEY hClassesKey;
951 HKEY hClassKey;
952 DWORD dwLength;
953 DWORD dwIndex;
954 LONG lError;
955 DWORD dwGuidListIndex = 0;
956
957 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
958 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
959
960 if (!ClassName || !RequiredSize)
961 {
962 SetLastError(ERROR_INVALID_PARAMETER);
963 return FALSE;
964 }
965 if (!ClassGuidList && ClassGuidListSize > 0)
966 {
967 SetLastError(ERROR_INVALID_PARAMETER);
968 return FALSE;
969 }
970 *RequiredSize = 0;
971
972 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
973 KEY_ENUMERATE_SUB_KEYS,
974 DIOCR_INSTALLER,
975 MachineName,
976 Reserved);
977 if (hClassesKey == INVALID_HANDLE_VALUE)
978 {
979 return FALSE;
980 }
981
982 for (dwIndex = 0; ; dwIndex++)
983 {
984 dwLength = 40;
985 lError = RegEnumKeyExW(hClassesKey,
986 dwIndex,
987 szKeyName,
988 &dwLength,
989 NULL,
990 NULL,
991 NULL,
992 NULL);
993 TRACE("RegEnumKeyExW() returns %d\n", lError);
994 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
995 {
996 TRACE("Key name: %p\n", szKeyName);
997
998 if (RegOpenKeyExW(hClassesKey,
999 szKeyName,
1000 0,
1001 KEY_QUERY_VALUE,
1002 &hClassKey))
1003 {
1004 RegCloseKey(hClassesKey);
1005 return FALSE;
1006 }
1007
1008 dwLength = MAX_CLASS_NAME_LEN * sizeof(WCHAR);
1009 if (!RegQueryValueExW(hClassKey,
1010 Class,
1011 NULL,
1012 NULL,
1013 (LPBYTE)szClassName,
1014 &dwLength))
1015 {
1016 TRACE("Class name: %p\n", szClassName);
1017
1018 if (strcmpiW(szClassName, ClassName) == 0)
1019 {
1020 TRACE("Found matching class name\n");
1021
1022 TRACE("Guid: %p\n", szKeyName);
1023 if (dwGuidListIndex < ClassGuidListSize)
1024 {
1025 if (szKeyName[0] == '{' && szKeyName[37] == '}')
1026 {
1027 szKeyName[37] = 0;
1028 }
1029 TRACE("Guid: %p\n", &szKeyName[1]);
1030
1031 UuidFromStringW(&szKeyName[1],
1032 &ClassGuidList[dwGuidListIndex]);
1033 }
1034
1035 dwGuidListIndex++;
1036 }
1037 }
1038
1039 RegCloseKey(hClassKey);
1040 }
1041
1042 if (lError != ERROR_SUCCESS)
1043 break;
1044 }
1045
1046 RegCloseKey(hClassesKey);
1047
1048 if (RequiredSize != NULL)
1049 *RequiredSize = dwGuidListIndex;
1050
1051 if (ClassGuidListSize < dwGuidListIndex)
1052 {
1053 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1054 return FALSE;
1055 }
1056
1057 return TRUE;
1058 }
1059
1060 /***********************************************************************
1061 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1062 */
1063 BOOL WINAPI SetupDiClassNameFromGuidA(
1064 const GUID* ClassGuid,
1065 PSTR ClassName,
1066 DWORD ClassNameSize,
1067 PDWORD RequiredSize)
1068 {
1069 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
1070 ClassNameSize, RequiredSize,
1071 NULL, NULL);
1072 }
1073
1074 /***********************************************************************
1075 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1076 */
1077 BOOL WINAPI SetupDiClassNameFromGuidW(
1078 const GUID* ClassGuid,
1079 PWSTR ClassName,
1080 DWORD ClassNameSize,
1081 PDWORD RequiredSize)
1082 {
1083 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
1084 ClassNameSize, RequiredSize,
1085 NULL, NULL);
1086 }
1087
1088 /***********************************************************************
1089 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1090 */
1091 BOOL WINAPI SetupDiClassNameFromGuidExA(
1092 const GUID* ClassGuid,
1093 PSTR ClassName,
1094 DWORD ClassNameSize,
1095 PDWORD RequiredSize,
1096 PCSTR MachineName,
1097 PVOID Reserved)
1098 {
1099 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
1100 LPWSTR MachineNameW = NULL;
1101 BOOL ret;
1102
1103 if (MachineName)
1104 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1105 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
1106 RequiredSize, MachineNameW, Reserved);
1107 if (ret)
1108 {
1109 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
1110 ClassNameSize, NULL, NULL);
1111 if (len == 0 || len > ClassNameSize)
1112 {
1113 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1114 ret = FALSE;
1115 }
1116 }
1117 MyFree(MachineNameW);
1118 return ret;
1119 }
1120
1121 /***********************************************************************
1122 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1123 */
1124 BOOL WINAPI SetupDiClassNameFromGuidExW(
1125 const GUID* ClassGuid,
1126 PWSTR ClassName,
1127 DWORD ClassNameSize,
1128 PDWORD RequiredSize,
1129 PCWSTR MachineName,
1130 PVOID Reserved)
1131 {
1132 HKEY hKey;
1133 DWORD dwLength;
1134 DWORD dwRegType;
1135 LONG rc;
1136 PWSTR Buffer;
1137
1138 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
1139 ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
1140
1141 /* Make sure there's a GUID */
1142 if (ClassGuid == NULL)
1143 {
1144 SetLastError(ERROR_INVALID_CLASS); /* On Vista: ERROR_INVALID_USER_BUFFER */
1145 return FALSE;
1146 }
1147
1148 /* Make sure there's a real buffer when there's a size */
1149 if ((ClassNameSize > 0) && (ClassName == NULL))
1150 {
1151 SetLastError(ERROR_INVALID_PARAMETER); /* On Vista: ERROR_INVALID_USER_BUFFER */
1152 return FALSE;
1153 }
1154
1155 /* Open the key for the GUID */
1156 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INSTALLER, MachineName, Reserved);
1157
1158 if (hKey == INVALID_HANDLE_VALUE)
1159 return FALSE;
1160
1161 /* Retrieve the class name data and close the key */
1162 rc = QueryRegistryValue(hKey, Class, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
1163 RegCloseKey(hKey);
1164
1165 /* Make sure we got the data */
1166 if (rc != ERROR_SUCCESS)
1167 {
1168 SetLastError(rc);
1169 return FALSE;
1170 }
1171
1172 /* Make sure the data is a string */
1173 if (dwRegType != REG_SZ)
1174 {
1175 MyFree(Buffer);
1176 SetLastError(ERROR_GEN_FAILURE);
1177 return FALSE;
1178 }
1179
1180 /* Determine the length of the class name */
1181 dwLength /= sizeof(WCHAR);
1182
1183 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
1184 /* Count the null-terminator */
1185 dwLength++;
1186
1187 /* Inform the caller about the class name */
1188 if ((ClassName != NULL) && (dwLength <= ClassNameSize))
1189 {
1190 memcpy(ClassName, Buffer, (dwLength - 1) * sizeof(WCHAR));
1191 ClassName[dwLength - 1] = UNICODE_NULL;
1192 }
1193
1194 /* Inform the caller about the required size */
1195 if (RequiredSize != NULL)
1196 *RequiredSize = dwLength;
1197
1198 /* Clean up the buffer */
1199 MyFree(Buffer);
1200
1201 /* Make sure the buffer was large enough */
1202 if ((ClassName == NULL) || (dwLength > ClassNameSize))
1203 {
1204 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1205 return FALSE;
1206 }
1207
1208 return TRUE;
1209 }
1210
1211 /***********************************************************************
1212 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1213 */
1214 HDEVINFO WINAPI
1215 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1216 HWND hwndParent)
1217 {
1218 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1219 }
1220
1221 /***********************************************************************
1222 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1223 */
1224 HDEVINFO WINAPI
1225 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1226 HWND hwndParent,
1227 PCSTR MachineName,
1228 PVOID Reserved)
1229 {
1230 LPWSTR MachineNameW = NULL;
1231 HDEVINFO hDevInfo;
1232
1233 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1234 debugstr_a(MachineName), Reserved);
1235
1236 if (MachineName)
1237 {
1238 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1239 if (MachineNameW == NULL)
1240 return INVALID_HANDLE_VALUE;
1241 }
1242
1243 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1244 MachineNameW, Reserved);
1245
1246 MyFree(MachineNameW);
1247
1248 return hDevInfo;
1249 }
1250
1251 /***********************************************************************
1252 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1253 *
1254 * Create an empty DeviceInfoSet list.
1255 *
1256 * PARAMS
1257 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1258 * with this list.
1259 * hwndParent [I] hwnd needed for interface related actions.
1260 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1261 * local registry will be used.
1262 * Reserved [I] must be NULL
1263 *
1264 * RETURNS
1265 * Success: empty list.
1266 * Failure: INVALID_HANDLE_VALUE.
1267 */
1268 HDEVINFO WINAPI
1269 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1270 HWND hwndParent,
1271 PCWSTR MachineName,
1272 PVOID Reserved)
1273 {
1274 struct DeviceInfoSet *list = NULL;
1275 DWORD size = FIELD_OFFSET(struct DeviceInfoSet, szData);
1276 DWORD rc;
1277 CONFIGRET cr;
1278 HDEVINFO ret = INVALID_HANDLE_VALUE;
1279
1280 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1281 debugstr_w(MachineName), Reserved);
1282
1283 if (MachineName != NULL)
1284 {
1285 SIZE_T len = strlenW(MachineName);
1286 if (len >= SP_MAX_MACHINENAME_LENGTH - 4)
1287 {
1288 SetLastError(ERROR_INVALID_MACHINENAME);
1289 goto cleanup;
1290 }
1291 size += (len + 3) * sizeof(WCHAR);
1292 }
1293
1294 if (Reserved != NULL)
1295 {
1296 SetLastError(ERROR_INVALID_PARAMETER);
1297 return INVALID_HANDLE_VALUE;
1298 }
1299
1300 list = MyMalloc(size);
1301 if (!list)
1302 {
1303 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1304 return INVALID_HANDLE_VALUE;
1305 }
1306 ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData));
1307
1308 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1309 memcpy(&list->ClassGuid,
1310 ClassGuid ? ClassGuid : &GUID_NULL,
1311 sizeof(list->ClassGuid));
1312 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1313 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
1314 list->InstallParams.hwndParent = hwndParent;
1315 if (MachineName)
1316 {
1317 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
1318 if (rc != ERROR_SUCCESS)
1319 {
1320 SetLastError(ERROR_INVALID_MACHINENAME);
1321 goto cleanup;
1322 }
1323
1324 list->szData[0] = list->szData[1] = '\\';
1325 strcpyW(list->szData + 2, MachineName);
1326 list->MachineName = list->szData;
1327 }
1328 else
1329 {
1330 list->HKLM = HKEY_LOCAL_MACHINE;
1331 list->MachineName = NULL;
1332 }
1333 cr = CM_Connect_MachineW(list->MachineName, &list->hMachine);
1334 if (cr != CR_SUCCESS)
1335 {
1336 SetLastError(GetErrorCodeFromCrCode(cr));
1337 goto cleanup;
1338 }
1339 InitializeListHead(&list->DriverListHead);
1340 InitializeListHead(&list->ListHead);
1341
1342 return (HDEVINFO)list;
1343
1344 cleanup:
1345 if (ret == INVALID_HANDLE_VALUE)
1346 {
1347 if (list)
1348 {
1349 if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
1350 RegCloseKey(list->HKLM);
1351 MyFree(list);
1352 }
1353 }
1354 return ret;
1355 }
1356
1357 /***********************************************************************
1358 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1359 */
1360 HKEY WINAPI SetupDiCreateDevRegKeyA(
1361 HDEVINFO DeviceInfoSet,
1362 PSP_DEVINFO_DATA DeviceInfoData,
1363 DWORD Scope,
1364 DWORD HwProfile,
1365 DWORD KeyType,
1366 HINF InfHandle,
1367 PCSTR InfSectionName)
1368 {
1369 PWSTR InfSectionNameW = NULL;
1370 HKEY key;
1371
1372 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1373 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1374
1375 if (InfHandle)
1376 {
1377 if (!InfSectionName)
1378 {
1379 SetLastError(ERROR_INVALID_PARAMETER);
1380 return INVALID_HANDLE_VALUE;
1381 }
1382 else
1383 {
1384 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
1385 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1386 }
1387 }
1388 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
1389 HwProfile, KeyType, InfHandle, InfSectionNameW);
1390 MyFree(InfSectionNameW);
1391 return key;
1392 }
1393
1394 static HKEY
1395 OpenHardwareProfileKey(
1396 IN HKEY HKLM,
1397 IN DWORD HwProfile,
1398 IN DWORD samDesired);
1399
1400 /***********************************************************************
1401 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1402 */
1403 HKEY WINAPI SetupDiCreateDevRegKeyW(
1404 HDEVINFO DeviceInfoSet,
1405 PSP_DEVINFO_DATA DeviceInfoData,
1406 DWORD Scope,
1407 DWORD HwProfile,
1408 DWORD KeyType,
1409 HINF InfHandle,
1410 PCWSTR InfSectionName)
1411 {
1412 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1413 HKEY key = INVALID_HANDLE_VALUE;
1414 LPWSTR lpGuidString = NULL;
1415 LPWSTR DriverKey = NULL; /* {GUID}\Index */
1416 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
1417 DWORD Index; /* Index used in the DriverKey name */
1418 DWORD rc;
1419 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
1420 HKEY hEnumKey = NULL;
1421 HKEY hClassKey = NULL;
1422 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
1423 HKEY hKey = NULL;
1424 HKEY RootKey;
1425
1426 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1427 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1428
1429 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1430 {
1431 SetLastError(ERROR_INVALID_HANDLE);
1432 return INVALID_HANDLE_VALUE;
1433 }
1434 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1435 {
1436 SetLastError(ERROR_INVALID_HANDLE);
1437 return INVALID_HANDLE_VALUE;
1438 }
1439 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1440 || !DeviceInfoData->Reserved)
1441 {
1442 SetLastError(ERROR_INVALID_PARAMETER);
1443 return INVALID_HANDLE_VALUE;
1444 }
1445 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1446 {
1447 SetLastError(ERROR_INVALID_FLAGS);
1448 return INVALID_HANDLE_VALUE;
1449 }
1450 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1451 {
1452 SetLastError(ERROR_INVALID_FLAGS);
1453 return INVALID_HANDLE_VALUE;
1454 }
1455 if (InfHandle && !InfSectionName)
1456 {
1457 SetLastError(ERROR_INVALID_PARAMETER);
1458 return INVALID_HANDLE_VALUE;
1459 }
1460 if (!InfHandle && InfSectionName)
1461 {
1462 SetLastError(ERROR_INVALID_PARAMETER);
1463 return INVALID_HANDLE_VALUE;
1464 }
1465
1466 if (Scope == DICS_FLAG_GLOBAL)
1467 RootKey = set->HKLM;
1468 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1469 {
1470 hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
1471 if (hHWProfileKey == INVALID_HANDLE_VALUE)
1472 goto cleanup;
1473 RootKey = hHWProfileKey;
1474 }
1475
1476 if (KeyType == DIREG_DEV)
1477 {
1478 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1479
1480 rc = RegCreateKeyExW(
1481 RootKey,
1482 REGSTR_PATH_SYSTEMENUM,
1483 0,
1484 NULL,
1485 REG_OPTION_NON_VOLATILE,
1486 KEY_CREATE_SUB_KEY,
1487 NULL,
1488 &hEnumKey,
1489 NULL);
1490 if (rc != ERROR_SUCCESS)
1491 {
1492 SetLastError(rc);
1493 goto cleanup;
1494 }
1495 rc = RegCreateKeyExW(
1496 hEnumKey,
1497 deviceInfo->instanceId,
1498 0,
1499 NULL,
1500 REG_OPTION_NON_VOLATILE,
1501 #if _WIN32_WINNT >= 0x502
1502 KEY_READ | KEY_WRITE,
1503 #else
1504 KEY_ALL_ACCESS,
1505 #endif
1506 NULL,
1507 &hKey,
1508 NULL);
1509 if (rc != ERROR_SUCCESS)
1510 {
1511 SetLastError(rc);
1512 goto cleanup;
1513 }
1514 }
1515 else /* KeyType == DIREG_DRV */
1516 {
1517 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
1518 goto cleanup;
1519 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1520 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1521 if (!DriverKey)
1522 {
1523 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1524 goto cleanup;
1525 }
1526 DriverKey[0] = '{';
1527 strcpyW(&DriverKey[1], lpGuidString);
1528 pDeviceInstance = &DriverKey[strlenW(DriverKey)];
1529 *pDeviceInstance++ = '}';
1530 *pDeviceInstance++ = '\\';
1531 rc = RegOpenKeyExW(RootKey,
1532 REGSTR_PATH_CLASS_NT,
1533 0,
1534 KEY_CREATE_SUB_KEY,
1535 &hClassKey);
1536 if (rc != ERROR_SUCCESS)
1537 {
1538 SetLastError(rc);
1539 goto cleanup;
1540 }
1541
1542 /* Try all values for Index between 0 and 9999 */
1543 Index = 0;
1544 while (Index <= 9999)
1545 {
1546 DWORD Disposition;
1547 sprintfW(pDeviceInstance, InstanceKeyFormat, Index);
1548 rc = RegCreateKeyExW(hClassKey,
1549 DriverKey,
1550 0,
1551 NULL,
1552 REG_OPTION_NON_VOLATILE,
1553 #if _WIN32_WINNT >= 0x502
1554 KEY_READ | KEY_WRITE,
1555 #else
1556 KEY_ALL_ACCESS,
1557 #endif
1558 NULL,
1559 &hKey,
1560 &Disposition);
1561 if (rc != ERROR_SUCCESS)
1562 {
1563 SetLastError(rc);
1564 goto cleanup;
1565 }
1566 if (Disposition == REG_CREATED_NEW_KEY)
1567 break;
1568 RegCloseKey(hKey);
1569 hKey = NULL;
1570 Index++;
1571 }
1572 if (Index > 9999)
1573 {
1574 /* Unable to create more than 9999 devices within the same class */
1575 SetLastError(ERROR_GEN_FAILURE);
1576 goto cleanup;
1577 }
1578
1579 /* Open device key, to write Driver value */
1580 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
1581 if (hDeviceKey == INVALID_HANDLE_VALUE)
1582 goto cleanup;
1583 rc = RegSetValueExW(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR));
1584 if (rc != ERROR_SUCCESS)
1585 {
1586 SetLastError(rc);
1587 goto cleanup;
1588 }
1589 }
1590
1591 /* Do installation of the specified section */
1592 if (InfHandle)
1593 {
1594 FIXME("Need to install section %s in file %p\n",
1595 debugstr_w(InfSectionName), InfHandle);
1596 }
1597 key = hKey;
1598
1599 cleanup:
1600 if (lpGuidString)
1601 RpcStringFreeW(&lpGuidString);
1602 HeapFree(GetProcessHeap(), 0, DriverKey);
1603 if (hHWProfileKey != INVALID_HANDLE_VALUE)
1604 RegCloseKey(hHWProfileKey);
1605 if (hEnumKey != NULL)
1606 RegCloseKey(hEnumKey);
1607 if (hClassKey != NULL)
1608 RegCloseKey(hClassKey);
1609 if (hDeviceKey != INVALID_HANDLE_VALUE)
1610 RegCloseKey(hDeviceKey);
1611 if (hKey != NULL && hKey != key)
1612 RegCloseKey(hKey);
1613
1614 TRACE("Returning 0x%p\n", key);
1615 return key;
1616 }
1617
1618 /***********************************************************************
1619 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1620 */
1621 BOOL WINAPI SetupDiCreateDeviceInfoA(
1622 HDEVINFO DeviceInfoSet,
1623 PCSTR DeviceName,
1624 CONST GUID *ClassGuid,
1625 PCSTR DeviceDescription,
1626 HWND hwndParent,
1627 DWORD CreationFlags,
1628 PSP_DEVINFO_DATA DeviceInfoData)
1629 {
1630 BOOL ret;
1631 LPWSTR DeviceNameW = NULL;
1632 LPWSTR DeviceDescriptionW = NULL;
1633
1634 TRACE("\n");
1635
1636 if (DeviceName)
1637 {
1638 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1639 if (DeviceNameW == NULL) return FALSE;
1640 }
1641 if (DeviceDescription)
1642 {
1643 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1644 if (DeviceDescriptionW == NULL)
1645 {
1646 MyFree(DeviceNameW);
1647 return FALSE;
1648 }
1649 }
1650
1651 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1652 hwndParent, CreationFlags, DeviceInfoData);
1653
1654 MyFree(DeviceNameW);
1655 MyFree(DeviceDescriptionW);
1656
1657 return ret;
1658 }
1659
1660 /***********************************************************************
1661 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1662 */
1663 BOOL WINAPI SetupDiCreateDeviceInfoW(
1664 HDEVINFO DeviceInfoSet,
1665 PCWSTR DeviceName,
1666 CONST GUID *ClassGuid,
1667 PCWSTR DeviceDescription,
1668 HWND hwndParent,
1669 DWORD CreationFlags,
1670 PSP_DEVINFO_DATA DeviceInfoData)
1671 {
1672 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1673 BOOL ret = FALSE;
1674 SP_DEVINFO_DATA DevInfo;
1675
1676 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1677 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1678 hwndParent, CreationFlags, DeviceInfoData);
1679
1680 if (!DeviceName)
1681 {
1682 SetLastError(ERROR_INVALID_DEVINST_NAME);
1683 return FALSE;
1684 }
1685 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1686 {
1687 SetLastError(ERROR_INVALID_HANDLE);
1688 return FALSE;
1689 }
1690 if (!ClassGuid)
1691 {
1692 SetLastError(ERROR_INVALID_PARAMETER);
1693 return FALSE;
1694 }
1695 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1696 {
1697 SetLastError(ERROR_INVALID_HANDLE);
1698 return FALSE;
1699 }
1700 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1701 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1702 {
1703 SetLastError(ERROR_CLASS_MISMATCH);
1704 return FALSE;
1705 }
1706 if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
1707 {
1708 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
1709 SetLastError(ERROR_INVALID_FLAGS);
1710 return FALSE;
1711 }
1712
1713 if (CreationFlags & DICD_GENERATE_ID)
1714 {
1715 /* Generate a new unique ID for this device */
1716 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1717 FIXME("not implemented\n");
1718 }
1719 else
1720 {
1721 /* Device name is fully qualified. Try to open it */
1722 BOOL rc;
1723
1724 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
1725 rc = SetupDiOpenDeviceInfoW(
1726 DeviceInfoSet,
1727 DeviceName,
1728 NULL, /* hwndParent */
1729 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
1730 &DevInfo);
1731
1732 if (rc)
1733 {
1734 /* SetupDiOpenDeviceInfoW has already added
1735 * the device info to the device info set
1736 */
1737 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1738 }
1739 else if (GetLastError() == ERROR_NO_SUCH_DEVINST)
1740 {
1741 struct DeviceInfo *deviceInfo;
1742
1743 if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo))
1744 {
1745 InsertTailList(&set->ListHead, &deviceInfo->ListEntry);
1746
1747 if (!DeviceInfoData)
1748 ret = TRUE;
1749 else
1750 {
1751 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
1752 {
1753 SetLastError(ERROR_INVALID_USER_BUFFER);
1754 }
1755 else
1756 {
1757 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
1758 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
1759 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
1760 ret = TRUE;
1761 }
1762 }
1763 }
1764 }
1765 }
1766
1767 TRACE("Returning %d\n", ret);
1768 return ret;
1769 }
1770
1771 /***********************************************************************
1772 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1773 */
1774 BOOL WINAPI SetupDiRegisterDeviceInfo(
1775 HDEVINFO DeviceInfoSet,
1776 PSP_DEVINFO_DATA DeviceInfoData,
1777 DWORD Flags,
1778 PSP_DETSIG_CMPPROC CompareProc,
1779 PVOID CompareContext,
1780 PSP_DEVINFO_DATA DupDeviceInfoData)
1781 {
1782 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1783
1784 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1785 CompareProc, CompareContext, DupDeviceInfoData);
1786
1787 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1788 {
1789 SetLastError(ERROR_INVALID_HANDLE);
1790 return FALSE;
1791 }
1792 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1793 {
1794 SetLastError(ERROR_INVALID_HANDLE);
1795 return FALSE;
1796 }
1797 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1798 || !DeviceInfoData->Reserved)
1799 {
1800 SetLastError(ERROR_INVALID_PARAMETER);
1801 return FALSE;
1802 }
1803 FIXME("Stub %p %p 0x%lx %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1804 CompareProc, CompareContext, DupDeviceInfoData);
1805 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1806 return FALSE;
1807 }
1808
1809 /***********************************************************************
1810 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1811 */
1812 BOOL WINAPI SetupDiEnumDeviceInfo(
1813 HDEVINFO devinfo,
1814 DWORD index,
1815 PSP_DEVINFO_DATA info)
1816 {
1817 BOOL ret = FALSE;
1818
1819 TRACE("%p %d %p\n", devinfo, index, info);
1820
1821 if(info==NULL)
1822 {
1823 SetLastError(ERROR_INVALID_PARAMETER);
1824 return FALSE;
1825 }
1826 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1827 {
1828 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1829 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1830 {
1831 if (info->cbSize != sizeof(SP_DEVINFO_DATA))
1832 SetLastError(ERROR_INVALID_USER_BUFFER);
1833 else
1834 {
1835 PLIST_ENTRY ItemList = list->ListHead.Flink;
1836 while (ItemList != &list->ListHead && index-- > 0)
1837 ItemList = ItemList->Flink;
1838 if (ItemList == &list->ListHead)
1839 SetLastError(ERROR_NO_MORE_ITEMS);
1840 else
1841 {
1842 struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
1843 memcpy(&info->ClassGuid,
1844 &DevInfo->ClassGuid,
1845 sizeof(GUID));
1846 info->DevInst = DevInfo->dnDevInst;
1847 info->Reserved = (ULONG_PTR)DevInfo;
1848 ret = TRUE;
1849 }
1850 }
1851 }
1852 else
1853 SetLastError(ERROR_INVALID_HANDLE);
1854 }
1855 else
1856 SetLastError(ERROR_INVALID_HANDLE);
1857 return ret;
1858 }
1859
1860 /***********************************************************************
1861 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1862 */
1863 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1864 HDEVINFO DeviceInfoSet,
1865 PSP_DEVINFO_DATA DeviceInfoData,
1866 PSTR DeviceInstanceId,
1867 DWORD DeviceInstanceIdSize,
1868 PDWORD RequiredSize)
1869 {
1870 BOOL ret = FALSE;
1871 DWORD size;
1872 PWSTR instanceId;
1873
1874 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1875 DeviceInstanceIdSize, RequiredSize);
1876
1877 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1878 {
1879 SetLastError(ERROR_INVALID_PARAMETER);
1880 return FALSE;
1881 }
1882
1883 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1884 DeviceInfoData,
1885 NULL,
1886 0,
1887 &size);
1888 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1889 return FALSE;
1890 instanceId = MyMalloc(size * sizeof(WCHAR));
1891 if (instanceId)
1892 {
1893 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1894 DeviceInfoData,
1895 instanceId,
1896 size,
1897 &size);
1898 if (ret)
1899 {
1900 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1901 DeviceInstanceId,
1902 DeviceInstanceIdSize, NULL, NULL);
1903
1904 if (!len)
1905 ret = FALSE;
1906 else
1907 {
1908 if (len > DeviceInstanceIdSize)
1909 {
1910 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1911 ret = FALSE;
1912 }
1913 if (RequiredSize)
1914 *RequiredSize = len;
1915 }
1916 }
1917 MyFree(instanceId);
1918 }
1919 else
1920 {
1921 if (RequiredSize)
1922 *RequiredSize = size;
1923 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1924 ret = FALSE;
1925 }
1926 return ret;
1927 }
1928
1929 /***********************************************************************
1930 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1931 */
1932 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1933 HDEVINFO DeviceInfoSet,
1934 PSP_DEVINFO_DATA DeviceInfoData,
1935 PWSTR DeviceInstanceId,
1936 DWORD DeviceInstanceIdSize,
1937 PDWORD RequiredSize)
1938 {
1939 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1940 struct DeviceInfo *devInfo;
1941
1942 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1943 DeviceInstanceIdSize, RequiredSize);
1944
1945 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1946 {
1947 SetLastError(ERROR_INVALID_HANDLE);
1948 return FALSE;
1949 }
1950 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1951 {
1952 SetLastError(ERROR_INVALID_HANDLE);
1953 return FALSE;
1954 }
1955 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1956 || !DeviceInfoData->Reserved)
1957 {
1958 SetLastError(ERROR_INVALID_PARAMETER);
1959 return FALSE;
1960 }
1961 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1962 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1963 {
1964 SetLastError(ERROR_INVALID_PARAMETER);
1965 return FALSE;
1966 }
1967 if (DeviceInstanceId && DeviceInstanceIdSize == 0)
1968 {
1969 SetLastError(ERROR_INVALID_PARAMETER);
1970 return FALSE;
1971 }
1972 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1973 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1974 {
1975 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1976 if (RequiredSize)
1977 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1978 return FALSE;
1979 }
1980 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1981 if (RequiredSize)
1982 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1983 return TRUE;
1984 }
1985
1986 /***********************************************************************
1987 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1988 */
1989 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1990 HINF InfHandle,
1991 PCSTR InfSectionName,
1992 PSTR InfSectionWithExt,
1993 DWORD InfSectionWithExtSize,
1994 PDWORD RequiredSize,
1995 PSTR *Extension)
1996 {
1997 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
1998 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
1999 Extension, NULL);
2000 }
2001
2002 /***********************************************************************
2003 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2004 */
2005 BOOL WINAPI SetupDiGetActualSectionToInstallW(
2006 HINF InfHandle,
2007 PCWSTR InfSectionName,
2008 PWSTR InfSectionWithExt,
2009 DWORD InfSectionWithExtSize,
2010 PDWORD RequiredSize,
2011 PWSTR *Extension)
2012 {
2013 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
2014 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
2015 Extension, NULL);
2016 }
2017
2018 /***********************************************************************
2019 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2020 */
2021 BOOL WINAPI
2022 SetupDiGetActualSectionToInstallExA(
2023 IN HINF InfHandle,
2024 IN PCSTR InfSectionName,
2025 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
2026 OUT PSTR InfSectionWithExt OPTIONAL,
2027 IN DWORD InfSectionWithExtSize,
2028 OUT PDWORD RequiredSize OPTIONAL,
2029 OUT PSTR* Extension OPTIONAL,
2030 IN PVOID Reserved)
2031 {
2032 LPWSTR InfSectionNameW = NULL;
2033 LPWSTR InfSectionWithExtW = NULL;
2034 PWSTR ExtensionW;
2035 BOOL bResult = FALSE;
2036
2037 TRACE("\n");
2038
2039 if (InfSectionName)
2040 {
2041 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2042 if (InfSectionNameW == NULL)
2043 goto cleanup;
2044 }
2045 if (InfSectionWithExt)
2046 {
2047 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
2048 if (InfSectionWithExtW == NULL)
2049 goto cleanup;
2050 }
2051
2052 bResult = SetupDiGetActualSectionToInstallExW(
2053 InfHandle, InfSectionNameW, AlternatePlatformInfo,
2054 InfSectionWithExt ? InfSectionWithExtW : NULL,
2055 InfSectionWithExtSize,
2056 RequiredSize,
2057 Extension ? &ExtensionW : NULL,
2058 Reserved);
2059
2060 if (bResult && InfSectionWithExt)
2061 {
2062 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
2063 InfSectionWithExtSize, NULL, NULL) != 0;
2064 }
2065 if (bResult && Extension)
2066 {
2067 if (ExtensionW == NULL)
2068 *Extension = NULL;
2069 else
2070 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
2071 }
2072
2073 cleanup:
2074 MyFree(InfSectionNameW);
2075 MyFree(InfSectionWithExtW);
2076
2077 return bResult;
2078 }
2079
2080 /***********************************************************************
2081 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2082 */
2083 BOOL WINAPI SetupDiGetClassDescriptionA(
2084 const GUID* ClassGuid,
2085 PSTR ClassDescription,
2086 DWORD ClassDescriptionSize,
2087 PDWORD RequiredSize)
2088 {
2089 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
2090 ClassDescriptionSize,
2091 RequiredSize, NULL, NULL);
2092 }
2093
2094 /***********************************************************************
2095 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2096 */
2097 BOOL WINAPI SetupDiGetClassDescriptionW(
2098 const GUID* ClassGuid,
2099 PWSTR ClassDescription,
2100 DWORD ClassDescriptionSize,
2101 PDWORD RequiredSize)
2102 {
2103 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
2104 ClassDescriptionSize,
2105 RequiredSize, NULL, NULL);
2106 }
2107
2108 /***********************************************************************
2109 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2110 */
2111 BOOL WINAPI SetupDiGetClassDescriptionExA(
2112 const GUID* ClassGuid,
2113 PSTR ClassDescription,
2114 DWORD ClassDescriptionSize,
2115 PDWORD RequiredSize,
2116 PCSTR MachineName,
2117 PVOID Reserved)
2118 {
2119 PWCHAR ClassDescriptionW = NULL;
2120 LPWSTR MachineNameW = NULL;
2121 BOOL ret = FALSE;
2122
2123 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2124 ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved);
2125
2126 if (ClassDescriptionSize > 0)
2127 {
2128 ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR));
2129 if (!ClassDescriptionW)
2130 {
2131 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2132 goto cleanup;
2133 }
2134 }
2135
2136 if (MachineName)
2137 {
2138 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2139 if (!MachineNameW)
2140 {
2141 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2142 goto cleanup;
2143 }
2144 }
2145
2146 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW,
2147 ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved);
2148 if (ret)
2149 {
2150 DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
2151 ClassDescriptionSize, NULL, NULL);
2152 if (len == 0 || len > ClassDescriptionSize)
2153 {
2154 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2155 ret = FALSE;
2156 }
2157 }
2158
2159 cleanup:
2160 MyFree(ClassDescriptionW);
2161 MyFree(MachineNameW);
2162 return ret;
2163 }
2164
2165 /***********************************************************************
2166 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2167 */
2168 BOOL WINAPI SetupDiGetClassDescriptionExW(
2169 const GUID* ClassGuid,
2170 PWSTR ClassDescription,
2171 DWORD ClassDescriptionSize,
2172 PDWORD RequiredSize,
2173 PCWSTR MachineName,
2174 PVOID Reserved)
2175 {
2176 HKEY hKey;
2177 DWORD dwLength;
2178 DWORD dwRegType;
2179 LONG rc;
2180 PWSTR Buffer;
2181
2182 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2183 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
2184
2185 /* Make sure there's a GUID */
2186 if (!ClassGuid)
2187 {
2188 SetLastError(ERROR_INVALID_PARAMETER);
2189 return FALSE;
2190 }
2191
2192 /* Make sure there's a real buffer when there's a size */
2193 if (!ClassDescription && ClassDescriptionSize > 0)
2194 {
2195 SetLastError(ERROR_INVALID_PARAMETER);
2196 return FALSE;
2197 }
2198
2199 /* Open the key for the GUID */
2200 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
2201 KEY_QUERY_VALUE,
2202 DIOCR_INSTALLER,
2203 MachineName,
2204 Reserved);
2205 if (hKey == INVALID_HANDLE_VALUE)
2206 return FALSE;
2207
2208 /* Retrieve the class description data and close the key */
2209 rc = QueryRegistryValue(hKey, NULL, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
2210 RegCloseKey(hKey);
2211
2212 /* Make sure we got the data */
2213 if (rc != ERROR_SUCCESS)
2214 {
2215 SetLastError(rc);
2216 return FALSE;
2217 }
2218
2219 /* Make sure the data is a string */
2220 if (dwRegType != REG_SZ)
2221 {
2222 MyFree(Buffer);
2223 SetLastError(ERROR_GEN_FAILURE);
2224 return FALSE;
2225 }
2226
2227 /* Determine the length of the class description */
2228 dwLength /= sizeof(WCHAR);
2229
2230 /* Count the null-terminator if none is present */
2231 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
2232 dwLength++;
2233
2234 /* Inform the caller about the class description */
2235 if ((ClassDescription != NULL) && (dwLength <= ClassDescriptionSize))
2236 {
2237 memcpy(ClassDescription, Buffer, (dwLength - 1) * sizeof(WCHAR));
2238 ClassDescription[dwLength - 1] = UNICODE_NULL;
2239 }
2240
2241 /* Inform the caller about the required size */
2242 if (RequiredSize != NULL)
2243 *RequiredSize = dwLength;
2244
2245 /* Clean up the buffer */
2246 MyFree(Buffer);
2247
2248 /* Make sure the buffer was large enough */
2249 if ((ClassDescription == NULL) || (dwLength > ClassDescriptionSize))
2250 {
2251 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2252 return FALSE;
2253 }
2254
2255 return TRUE;
2256 }
2257
2258 /***********************************************************************
2259 * SetupDiGetClassDevsA (SETUPAPI.@)
2260 */
2261 HDEVINFO WINAPI SetupDiGetClassDevsA(
2262 CONST GUID *class,
2263 LPCSTR enumstr,
2264 HWND parent,
2265 DWORD flags)
2266 {
2267 return SetupDiGetClassDevsExA(class, enumstr, parent,
2268 flags, NULL, NULL, NULL);
2269 }
2270
2271 /***********************************************************************
2272 * SetupDiGetClassDevsExA (SETUPAPI.@)
2273 */
2274 HDEVINFO WINAPI SetupDiGetClassDevsExA(
2275 const GUID *class,
2276 PCSTR enumstr,
2277 HWND parent,
2278 DWORD flags,
2279 HDEVINFO deviceset,
2280 PCSTR machine,
2281 PVOID reserved)
2282 {
2283 HDEVINFO ret;
2284 LPWSTR enumstrW = NULL, machineW = NULL;
2285
2286 if (enumstr)
2287 {
2288 enumstrW = MultiByteToUnicode(enumstr, CP_ACP);
2289 if (!enumstrW)
2290 {
2291 ret = INVALID_HANDLE_VALUE;
2292 goto end;
2293 }
2294 }
2295 if (machine)
2296 {
2297 machineW = MultiByteToUnicode(machine, CP_ACP);
2298 if (!machineW)
2299 {
2300 MyFree(enumstrW);
2301 ret = INVALID_HANDLE_VALUE;
2302 goto end;
2303 }
2304 }
2305 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
2306 machineW, reserved);
2307 MyFree(enumstrW);
2308 MyFree(machineW);
2309
2310 end:
2311 return ret;
2312 }
2313
2314 /***********************************************************************
2315 * SetupDiGetClassDevsW (SETUPAPI.@)
2316 */
2317 HDEVINFO WINAPI SetupDiGetClassDevsW(
2318 CONST GUID *class,
2319 LPCWSTR enumstr,
2320 HWND parent,
2321 DWORD flags)
2322 {
2323 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2324 NULL);
2325 }
2326
2327 /***********************************************************************
2328 * SetupDiGetClassDevsExW (SETUPAPI.@)
2329 */
2330 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2331 CONST GUID *class,
2332 PCWSTR enumstr,
2333 HWND parent,
2334 DWORD flags,
2335 HDEVINFO deviceset,
2336 PCWSTR machine,
2337 PVOID reserved)
2338 {
2339 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2340 struct DeviceInfoSet *list;
2341 CONST GUID *pClassGuid;
2342 LONG rc;
2343 HDEVINFO set = INVALID_HANDLE_VALUE;
2344
2345 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2346 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2347 reserved);
2348
2349 if (!(flags & DIGCF_ALLCLASSES) && !class)
2350 {
2351 SetLastError(ERROR_INVALID_PARAMETER);
2352 return INVALID_HANDLE_VALUE;
2353 }
2354
2355 /* Create the deviceset if not set */
2356 if (deviceset)
2357 {
2358 list = (struct DeviceInfoSet *)deviceset;
2359 if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2360 {
2361 SetLastError(ERROR_INVALID_HANDLE);
2362 goto cleanup;
2363 }
2364 hDeviceInfo = deviceset;
2365 }
2366 else
2367 {
2368 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
2369 flags & (DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES) ? NULL : class,
2370 NULL, machine, NULL);
2371 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2372 goto cleanup;
2373 list = (struct DeviceInfoSet *)hDeviceInfo;
2374 }
2375
2376 if (flags & DIGCF_PROFILE)
2377 FIXME(": flag DIGCF_PROFILE ignored\n");
2378
2379 if (flags & DIGCF_DEVICEINTERFACE)
2380 {
2381 if (!class)
2382 {
2383 SetLastError(ERROR_INVALID_PARAMETER);
2384 goto cleanup;
2385 }
2386 rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT);
2387 }
2388 else
2389 {
2390 /* Determine which class(es) should be included in the deviceset */
2391 if (flags & DIGCF_ALLCLASSES)
2392 {
2393 /* The caller wants all classes. Check if
2394 * the deviceset limits us to one class */
2395 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2396 pClassGuid = NULL;
2397 else
2398 pClassGuid = &list->ClassGuid;
2399 }
2400 else if (class)
2401 {
2402 /* The caller wants one class. Check if it matches deviceset class */
2403 if (IsEqualIID(&list->ClassGuid, class)
2404 || IsEqualIID(&list->ClassGuid, &GUID_NULL))
2405 {
2406 pClassGuid = class;
2407 }
2408 else
2409 {
2410 SetLastError(ERROR_INVALID_PARAMETER);
2411 goto cleanup;
2412 }
2413 }
2414 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL))
2415 {
2416 /* No class specified. Try to use the one of the deviceset */
2417 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2418 pClassGuid = &list->ClassGuid;
2419 else
2420 {
2421 SetLastError(ERROR_INVALID_PARAMETER);
2422 goto cleanup;
2423 }
2424 }
2425 else
2426 {
2427 SetLastError(ERROR_INVALID_PARAMETER);
2428 goto cleanup;
2429 }
2430 rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr);
2431 }
2432 if (rc != ERROR_SUCCESS)
2433 {
2434 SetLastError(rc);
2435 goto cleanup;
2436 }
2437 set = hDeviceInfo;
2438
2439 cleanup:
2440 if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set)
2441 SetupDiDestroyDeviceInfoList(hDeviceInfo);
2442 return set;
2443 }
2444
2445 /***********************************************************************
2446 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2447 */
2448 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2449 HDEVINFO DeviceInfoSet,
2450 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2451 {
2452 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2453
2454 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2455
2456 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2457 {
2458 SetLastError(ERROR_INVALID_HANDLE);
2459 return FALSE;
2460 }
2461 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2462 {
2463 SetLastError(ERROR_INVALID_HANDLE);
2464 return FALSE;
2465 }
2466 if (!DevInfoData ||
2467 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2468 {
2469 SetLastError(ERROR_INVALID_PARAMETER);
2470 return FALSE;
2471 }
2472 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2473 DevInfoData->RemoteMachineHandle = set->hMachine;
2474 if (set->MachineName)
2475 {
2476 FIXME("Stub\n");
2477 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2478 return FALSE;
2479 }
2480 else
2481 DevInfoData->RemoteMachineName[0] = 0;
2482
2483 return TRUE;
2484 }
2485
2486 /***********************************************************************
2487 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2488 */
2489 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2490 HDEVINFO DeviceInfoSet,
2491 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2492 {
2493 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2494
2495 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2496
2497 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2498 {
2499 SetLastError(ERROR_INVALID_HANDLE);
2500 return FALSE;
2501 }
2502 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2503 {
2504 SetLastError(ERROR_INVALID_HANDLE);
2505 return FALSE;
2506 }
2507 if (!DevInfoData ||
2508 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2509 {
2510 SetLastError(ERROR_INVALID_PARAMETER);
2511 return FALSE;
2512 }
2513 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2514 DevInfoData->RemoteMachineHandle = set->hMachine;
2515 if (set->MachineName)
2516 strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2);
2517 else
2518 DevInfoData->RemoteMachineName[0] = 0;
2519
2520 return TRUE;
2521 }
2522
2523 /***********************************************************************
2524 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2525 */
2526 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2527 HDEVINFO DeviceInfoSet,
2528 PSP_DEVINFO_DATA DeviceInfoData,
2529 const GUID *InterfaceClassGuid,
2530 PCSTR ReferenceString,
2531 DWORD CreationFlags,
2532 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2533 {
2534 BOOL ret;
2535 LPWSTR ReferenceStringW = NULL;
2536
2537 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2538 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2539 CreationFlags, DeviceInterfaceData);
2540
2541 if (ReferenceString)
2542 {
2543 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2544 if (ReferenceStringW == NULL) return FALSE;
2545 }
2546
2547 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2548 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2549 DeviceInterfaceData);
2550
2551 MyFree(ReferenceStringW);
2552
2553 return ret;
2554 }
2555
2556 /***********************************************************************
2557 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2558 */
2559 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2560 HDEVINFO DeviceInfoSet,
2561 PSP_DEVINFO_DATA DeviceInfoData,
2562 const GUID *InterfaceClassGuid,
2563 PCWSTR ReferenceString,
2564 DWORD CreationFlags,
2565 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2566 {
2567 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2568 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2569 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2570 CreationFlags, DeviceInterfaceData);
2571
2572 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2573 {
2574 SetLastError(ERROR_INVALID_HANDLE);
2575 return FALSE;
2576 }
2577 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2578 {
2579 SetLastError(ERROR_INVALID_HANDLE);
2580 return FALSE;
2581 }
2582 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2583 || !DeviceInfoData->Reserved)
2584 {
2585 SetLastError(ERROR_INVALID_PARAMETER);
2586 return FALSE;
2587 }
2588 if (!InterfaceClassGuid)
2589 {
2590 SetLastError(ERROR_INVALID_USER_BUFFER);
2591 return FALSE;
2592 }
2593
2594 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2595 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2596 CreationFlags, DeviceInterfaceData);
2597 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2598 return FALSE;
2599 }
2600
2601 /***********************************************************************
2602 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2603 */
2604 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2605 HDEVINFO DeviceInfoSet,
2606 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2607 DWORD Reserved,
2608 REGSAM samDesired,
2609 HINF InfHandle,
2610 PCSTR InfSectionName)
2611 {
2612 HKEY key;
2613 PWSTR InfSectionNameW = NULL;
2614
2615 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2616 samDesired, InfHandle, InfSectionName);
2617 if (InfHandle)
2618 {
2619 if (!InfSectionName)
2620 {
2621 SetLastError(ERROR_INVALID_PARAMETER);
2622 return INVALID_HANDLE_VALUE;
2623 }
2624 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2625 if (!InfSectionNameW)
2626 return INVALID_HANDLE_VALUE;
2627 }
2628 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2629 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2630 InfSectionNameW);
2631 MyFree(InfSectionNameW);
2632 return key;
2633 }
2634
2635 /***********************************************************************
2636 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2637 */
2638 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2639 HDEVINFO DeviceInfoSet,
2640 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2641 DWORD Reserved,
2642 REGSAM samDesired,
2643 HINF InfHandle,
2644 PCWSTR InfSectionName)
2645 {
2646 HKEY hKey, hDevKey;
2647 LPWSTR SymbolicLink;
2648 DWORD Length, Index;
2649 LONG rc;
2650 WCHAR bracedGuidString[39];
2651 struct DeviceInterface *DevItf;
2652 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2653
2654 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2655 samDesired, InfHandle, InfSectionName);
2656
2657 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2658 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2659 {
2660 SetLastError(ERROR_INVALID_HANDLE);
2661 return INVALID_HANDLE_VALUE;
2662 }
2663 if (!DeviceInterfaceData ||
2664 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2665 !DeviceInterfaceData->Reserved)
2666 {
2667 SetLastError(ERROR_INVALID_PARAMETER);
2668 return INVALID_HANDLE_VALUE;
2669 }
2670 if (InfHandle && !InfSectionName)
2671 {
2672 SetLastError(ERROR_INVALID_PARAMETER);
2673 return INVALID_HANDLE_VALUE;
2674 }
2675
2676 hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL);
2677 if (hKey == INVALID_HANDLE_VALUE)
2678 {
2679 hKey = SetupDiOpenClassRegKeyExW(NULL, samDesired, DIOCR_INTERFACE, NULL, NULL);
2680 if (hKey == INVALID_HANDLE_VALUE)
2681 {
2682 SetLastError(ERROR_INVALID_PARAMETER);
2683 return INVALID_HANDLE_VALUE;
2684 }
2685 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString);
2686
2687 if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS)
2688 {
2689 SetLastError(ERROR_INVALID_PARAMETER);
2690 return INVALID_HANDLE_VALUE;
2691 }
2692 RegCloseKey(hKey);
2693 hKey = hDevKey;
2694 }
2695
2696 DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2697
2698 Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR);
2699 SymbolicLink = HeapAlloc(GetProcessHeap(), 0, Length);
2700 if (!SymbolicLink)
2701 {
2702 RegCloseKey(hKey);
2703 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2704 return INVALID_HANDLE_VALUE;
2705 }
2706
2707 wcscpy(SymbolicLink, DevItf->SymbolicLink);
2708
2709 Index = 0;
2710 while(SymbolicLink[Index])
2711 {
2712 if (SymbolicLink[Index] == L'\\')
2713 {
2714 SymbolicLink[Index] = L'#';
2715 }
2716 Index++;
2717 }
2718
2719 rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL);
2720
2721 RegCloseKey(hKey);
2722 HeapFree(GetProcessHeap(), 0, SymbolicLink);
2723
2724 if (rc == ERROR_SUCCESS)
2725 {
2726 if (InfHandle && InfSectionName)
2727 {
2728 if (!SetupInstallFromInfSection(NULL /*FIXME */,
2729 InfHandle,
2730 InfSectionName,
2731 SPINST_INIFILES | SPINST_REGISTRY | SPINST_INI2REG | SPINST_FILES | SPINST_BITREG | SPINST_REGSVR | SPINST_UNREGSVR | SPINST_PROFILEITEMS | SPINST_COPYINF,
2732 hDevKey,
2733 NULL,
2734 0,
2735 set->SelectedDevice->InstallParams.InstallMsgHandler,
2736 set->SelectedDevice->InstallParams.InstallMsgHandlerContext,
2737 INVALID_HANDLE_VALUE,
2738 NULL))
2739 {
2740 RegCloseKey(hDevKey);
2741 return INVALID_HANDLE_VALUE;
2742 }
2743 }
2744 }
2745
2746 SetLastError(rc);
2747 return hDevKey;
2748 }
2749
2750 /***********************************************************************
2751 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2752 */
2753 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2754 HDEVINFO DeviceInfoSet,
2755 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2756 DWORD Reserved)
2757 {
2758 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2759 BOOL ret = FALSE;
2760
2761 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2762
2763 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2764 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2765 {
2766 SetLastError(ERROR_INVALID_HANDLE);
2767 return FALSE;
2768 }
2769 if (!DeviceInterfaceData ||
2770 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2771 !DeviceInterfaceData->Reserved)
2772 {
2773 SetLastError(ERROR_INVALID_PARAMETER);
2774 return FALSE;
2775 }
2776
2777 FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2778 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2779 return ret;
2780 }
2781
2782 /***********************************************************************
2783 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2784 *
2785 * PARAMS
2786 * DeviceInfoSet [I] Set of devices from which to enumerate
2787 * interfaces
2788 * DeviceInfoData [I] (Optional) If specified, a specific device
2789 * instance from which to enumerate interfaces.
2790 * If it isn't specified, all interfaces for all
2791 * devices in the set are enumerated.
2792 * InterfaceClassGuid [I] The interface class to enumerate.
2793 * MemberIndex [I] An index of the interface instance to enumerate.
2794 * A caller should start with MemberIndex set to 0,
2795 * and continue until the function fails with
2796 * ERROR_NO_MORE_ITEMS.
2797 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2798 * member must be set to
2799 * sizeof(SP_DEVICE_INTERFACE_DATA).
2800 *
2801 * RETURNS
2802 * Success: non-zero value.
2803 * Failure: FALSE. Call GetLastError() for more info.
2804 */
2805 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2806 HDEVINFO DeviceInfoSet,
2807 PSP_DEVINFO_DATA DeviceInfoData,
2808 CONST GUID * InterfaceClassGuid,
2809 DWORD MemberIndex,
2810 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2811 {
2812 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2813 BOOL ret = FALSE;
2814
2815 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2816 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2817
2818 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2819 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2820 {
2821 SetLastError(ERROR_INVALID_HANDLE);
2822 return FALSE;
2823 }
2824 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2825 !DeviceInfoData->Reserved))
2826 {
2827 SetLastError(ERROR_INVALID_PARAMETER);
2828 return FALSE;
2829 }
2830 if (!DeviceInterfaceData ||
2831 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2832 {
2833 SetLastError(ERROR_INVALID_PARAMETER);
2834 return FALSE;
2835 }
2836 if (DeviceInfoData)
2837 {
2838 struct DeviceInfo *devInfo =
2839 (struct DeviceInfo *)DeviceInfoData->Reserved;
2840 BOOL found = FALSE;
2841 PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2842 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2843 {
2844 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2845 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2846 {
2847 InterfaceListEntry = InterfaceListEntry->Flink;
2848 continue;
2849 }
2850 if (MemberIndex-- == 0)
2851 {
2852 /* return this item */
2853 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2854 &DevItf->InterfaceClassGuid,
2855 sizeof(GUID));
2856 DeviceInterfaceData->Flags = DevItf->Flags;
2857 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2858 found = TRUE;
2859 ret = TRUE;
2860 }
2861 InterfaceListEntry = InterfaceListEntry->Flink;
2862 }
2863 if (!found)
2864 SetLastError(ERROR_NO_MORE_ITEMS);
2865 }
2866 else
2867 {
2868 BOOL found = FALSE;
2869 PLIST_ENTRY ItemList = set->ListHead.Flink;
2870 while (ItemList != &set->ListHead && !found)
2871 {
2872 PLIST_ENTRY InterfaceListEntry;
2873 struct DeviceInfo *devInfo =
2874 CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
2875 InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2876 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2877 {
2878 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2879 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2880 {
2881 InterfaceListEntry = InterfaceListEntry->Flink;
2882 continue;
2883 }
2884 if (MemberIndex-- == 0)
2885 {
2886 /* return this item */
2887 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2888 &DevItf->InterfaceClassGuid,
2889 sizeof(GUID));
2890 DeviceInterfaceData->Flags = DevItf->Flags;
2891 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2892 found = TRUE;
2893 ret = TRUE;
2894 }
2895 InterfaceListEntry = InterfaceListEntry->Flink;
2896 }
2897 ItemList = ItemList->Flink;
2898
2899 }
2900 if (!found)
2901 SetLastError(ERROR_NO_MORE_ITEMS);
2902 }
2903 return ret;
2904 }
2905
2906 /***********************************************************************
2907 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2908 *
2909 * Destroy a DeviceInfoList and free all used memory of the list.
2910 *
2911 * PARAMS
2912 * devinfo [I] DeviceInfoList pointer to list to destroy
2913 *
2914 * RETURNS
2915 * Success: non zero value.
2916 * Failure: zero value.
2917 */
2918 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2919 {
2920 BOOL ret = FALSE;
2921
2922 TRACE("%p\n", devinfo);
2923 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
2924 {
2925 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2926
2927 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2928 {
2929 ret = DestroyDeviceInfoSet(list);
2930 }
2931 }
2932
2933 if (ret == FALSE)
2934 SetLastError(ERROR_INVALID_HANDLE);
2935
2936 return ret;
2937 }
2938
2939 /***********************************************************************
2940 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2941 */
2942 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2943 HDEVINFO DeviceInfoSet,
2944 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2945 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2946 DWORD DeviceInterfaceDetailDataSize,
2947 PDWORD RequiredSize,
2948 PSP_DEVINFO_DATA DeviceInfoData)
2949 {
2950 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2951 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2952 DWORD sizeW = 0, bytesNeeded;
2953 BOOL ret = FALSE;
2954
2955 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2956 DeviceInterfaceData, DeviceInterfaceDetailData,
2957 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2958
2959 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2960 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2961 {
2962 SetLastError(ERROR_INVALID_HANDLE);
2963 return FALSE;
2964 }
2965 if (!DeviceInterfaceData ||
2966 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2967 !DeviceInterfaceData->Reserved)
2968 {
2969 SetLastError(ERROR_INVALID_PARAMETER);
2970 return FALSE;
2971 }
2972 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2973 FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1 ||
2974 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2975 {
2976 SetLastError(ERROR_INVALID_USER_BUFFER);
2977 return FALSE;
2978 }
2979 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2980 {
2981 SetLastError(ERROR_INVALID_USER_BUFFER);
2982 return FALSE;
2983 }
2984
2985
2986 if (DeviceInterfaceDetailData != NULL)
2987 {
2988 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2989 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2990 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW);
2991 if (!DeviceInterfaceDetailDataW)
2992 {
2993 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2994 }
2995 }
2996 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2997 {
2998 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2999 ret = SetupDiGetDeviceInterfaceDetailW(
3000 DeviceInfoSet,
3001 DeviceInterfaceData,
3002 DeviceInterfaceDetailDataW,
3003 sizeW,
3004 &sizeW,
3005 DeviceInfoData);
3006 bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
3007 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
3008 if (RequiredSize)
3009 *RequiredSize = bytesNeeded;
3010 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= bytesNeeded)
3011 {
3012 if (!WideCharToMultiByte(
3013 CP_ACP, 0,
3014 DeviceInterfaceDetailDataW->DevicePath, -1,
3015 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
3016 NULL, NULL))
3017 {
3018 ret = FALSE;
3019 }
3020 }
3021 }
3022 MyFree(DeviceInterfaceDetailDataW);
3023
3024 return ret;
3025 }
3026
3027 /***********************************************************************
3028 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3029 */
3030 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
3031 HDEVINFO DeviceInfoSet,
3032 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
3033 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
3034 DWORD DeviceInterfaceDetailDataSize,
3035 PDWORD RequiredSize,
3036 PSP_DEVINFO_DATA DeviceInfoData)
3037 {
3038 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3039 BOOL ret = FALSE;
3040
3041 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
3042 DeviceInterfaceData, DeviceInterfaceDetailData,
3043 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
3044
3045 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
3046 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3047 {
3048 SetLastError(ERROR_INVALID_HANDLE);
3049 return FALSE;
3050 }
3051 if (!DeviceInterfaceData ||
3052 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
3053 !DeviceInterfaceData->Reserved)
3054 {
3055 SetLastError(ERROR_INVALID_PARAMETER);
3056 return FALSE;
3057 }
3058 if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
3059 {
3060 SetLastError(ERROR_INVALID_USER_BUFFER);
3061 return FALSE;
3062 }
3063 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
3064 {
3065 SetLastError(ERROR_INVALID_USER_BUFFER);
3066 return FALSE;
3067 }
3068 if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3069 {
3070 SetLastError(ERROR_INVALID_PARAMETER);
3071 return FALSE;
3072 }
3073 if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
3074 {
3075 SetLastError(ERROR_INVALID_PARAMETER);
3076 return FALSE;
3077 }
3078 else
3079 {
3080 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
3081 LPCWSTR devName = deviceInterface->SymbolicLink;
3082 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
3083 (lstrlenW(devName) + 1) * sizeof(WCHAR);
3084
3085 if (sizeRequired > DeviceInterfaceDetailDataSize)
3086 {
3087 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3088 if (RequiredSize)
3089 *RequiredSize = sizeRequired;
3090 }
3091 else
3092 {
3093 strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
3094 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
3095 if (DeviceInfoData)
3096 {
3097 memcpy(&DeviceInfoData->ClassGuid,
3098 &deviceInterface->DeviceInfo->ClassGuid,
3099 sizeof(GUID));
3100 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
3101 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
3102 }
3103 ret = TRUE;
3104 }
3105 }
3106 return ret;
3107 }
3108
3109 struct PropertyMapEntry
3110 {
3111 DWORD regType;
3112 LPCSTR nameA;
3113 LPCWSTR nameW;
3114 };
3115
3116 static struct PropertyMapEntry PropertyMap[] = {
3117 { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC },
3118 { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID },
3119 { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS },
3120 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
3121 { REG_SZ, "Service", REGSTR_VAL_SERVICE },
3122 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
3123 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
3124 { REG_SZ, "Class", REGSTR_VAL_CLASS },
3125 { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID },
3126 { REG_SZ, "Driver", REGSTR_VAL_DRIVER },
3127 { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS },
3128 { REG_SZ, "Mfg", REGSTR_VAL_MFG },
3129 { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME },
3130 { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION },
3131 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3132 { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES },
3133 { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER },
3134 { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS },
3135 { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS },
3136 { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */
3137 { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */
3138 { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */
3139 { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */
3140 { REG_BINARY, "Security", REGSTR_SECURITY },
3141 { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */
3142 { 0, NULL, NULL }, /* SPDRP_DEVTYPE */
3143 { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */
3144 { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */
3145 { 0, NULL, NULL }, /* SPDRP_ADDRESS */
3146 { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT },
3147 { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */
3148 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */
3149 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3150 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3151 { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */
3152 };
3153
3154 /***********************************************************************
3155 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3156 */
3157 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
3158 HDEVINFO DeviceInfoSet,
3159 PSP_DEVINFO_DATA DeviceInfoData,
3160 DWORD Property,
3161 PDWORD PropertyRegDataType,
3162 PBYTE PropertyBuffer,
3163 DWORD PropertyBufferSize,
3164 PDWORD RequiredSize)
3165 {
3166 BOOL ret;
3167 BOOL bIsStringProperty;
3168 DWORD RegType;
3169 DWORD RequiredSizeA, RequiredSizeW;
3170 DWORD PropertyBufferSizeW = 0;
3171 PBYTE PropertyBufferW = NULL;
3172
3173 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3174 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3175 RequiredSize);
3176
3177 if (PropertyBufferSize != 0)
3178 {
3179 PropertyBufferSizeW = PropertyBufferSize * 2;
3180 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
3181 if (!PropertyBufferW)
3182 {
3183 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3184 return FALSE;
3185 }
3186 }
3187
3188 ret = SetupDiGetDeviceRegistryPropertyW(
3189 DeviceInfoSet,
3190 DeviceInfoData,
3191 Property,
3192 &RegType,
3193 PropertyBufferW,
3194 PropertyBufferSizeW,
3195 &RequiredSizeW);
3196
3197 if (ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3198 {
3199 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
3200
3201 if (bIsStringProperty)
3202 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
3203 else
3204 RequiredSizeA = RequiredSizeW;
3205 if (RequiredSize)
3206 *RequiredSize = RequiredSizeA;
3207 if (PropertyRegDataType)
3208 *PropertyRegDataType = RegType;
3209 }
3210
3211 if (!ret)
3212 {
3213 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3214 return ret;
3215 }
3216
3217 if (RequiredSizeA <= PropertyBufferSize)
3218 {
3219 if (bIsStringProperty && PropertyBufferSize > 0)
3220 {
3221 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
3222 {
3223 /* Last error is already set by WideCharToMultiByte */
3224 ret = FALSE;
3225 }
3226 }
3227 else
3228 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
3229 }
3230 else
3231 {
3232 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3233 ret = FALSE;
3234 }
3235
3236 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3237 return ret;
3238 }
3239
3240 /***********************************************************************
3241 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3242 */
3243 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
3244 HDEVINFO DeviceInfoSet,
3245 PSP_DEVINFO_DATA DeviceInfoData,
3246 DWORD Property,
3247 PDWORD PropertyRegDataType,
3248 PBYTE PropertyBuffer,
3249 DWORD PropertyBufferSize,
3250 PDWORD RequiredSize)
3251 {
3252 BOOL ret = FALSE;
3253 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3254 struct DeviceInfo *devInfo;
3255
3256 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3257 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3258 RequiredSize);
3259
3260 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3261 {
3262 SetLastError(ERROR_INVALID_HANDLE);
3263 return FALSE;
3264 }
3265 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3266 {
3267 SetLastError(ERROR_INVALID_HANDLE);
3268 return FALSE;
3269 }
3270 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3271 || !DeviceInfoData->Reserved)
3272 {
3273 SetLastError(ERROR_INVALID_PARAMETER);
3274 return FALSE;
3275 }
3276 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3277 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3278 && PropertyMap[Property].nameW)
3279 {
3280 DWORD size = PropertyBufferSize;
3281 HKEY hKey;
3282 LONG l;
3283 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
3284 if (hKey == INVALID_HANDLE_VALUE)
3285 return FALSE;
3286 l = RegQueryValueExW(hKey, PropertyMap[Property].nameW,
3287 NULL, PropertyRegDataType, PropertyBuffer, &size);
3288 RegCloseKey(hKey);
3289
3290 if (RequiredSize)
3291 *RequiredSize = size;
3292 switch(l) {
3293 case ERROR_SUCCESS:
3294 if (PropertyBuffer != NULL || size == 0)
3295 ret = TRUE;
3296 else
3297 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3298 break;
3299 case ERROR_MORE_DATA:
3300 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3301 break;
3302 default:
3303 SetLastError(l);
3304 }
3305 }
3306 else if (Property == SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)
3307 {
3308 DWORD required = (strlenW(devInfo->Data) + 1) * sizeof(WCHAR);
3309
3310 if (PropertyRegDataType)
3311 *PropertyRegDataType = REG_SZ;
3312 if (RequiredSize)
3313 *RequiredSize = required;
3314 if (PropertyBufferSize >= required)
3315 {
3316 strcpyW((LPWSTR)PropertyBuffer, devInfo->Data);
3317 ret = TRUE;
3318 }
3319 else
3320 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3321 }
3322 else
3323 {
3324 ERR("Property 0x%lx not implemented\n", Property);
3325 SetLastError(ERROR_NOT_SUPPORTED);
3326 }
3327 return ret;
3328 }
3329
3330 /***********************************************************************
3331 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3332 */
3333 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
3334 HDEVINFO DeviceInfoSet,
3335 PSP_DEVINFO_DATA DeviceInfoData,
3336 DWORD Property,
3337 const BYTE *PropertyBuffer,
3338 DWORD PropertyBufferSize)
3339 {
3340 BOOL ret = FALSE;
3341 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3342
3343 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3344 PropertyBuffer, PropertyBufferSize);
3345
3346 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3347 {
3348 SetLastError(ERROR_INVALID_HANDLE);
3349 return FALSE;
3350 }
3351 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3352 {
3353 SetLastError(ERROR_INVALID_HANDLE);
3354 return FALSE;
3355 }
3356 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3357 || !DeviceInfoData->Reserved)
3358 {
3359 SetLastError(ERROR_INVALID_PARAMETER);
3360 return FALSE;
3361 }
3362
3363 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
3364 Property, PropertyBuffer, PropertyBufferSize);
3365 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3366 return ret;
3367 }
3368
3369 /***********************************************************************
3370 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3371 */
3372 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
3373 HDEVINFO DeviceInfoSet,
3374 PSP_DEVINFO_DATA DeviceInfoData,
3375 DWORD Property,
3376 const BYTE *PropertyBuffer,
3377 DWORD PropertyBufferSize)
3378 {
3379 BOOL ret = FALSE;
3380 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3381
3382 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3383 PropertyBuffer, PropertyBufferSize);
3384
3385 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3386 {
3387 SetLastError(ERROR_INVALID_HANDLE);
3388 return FALSE;
3389 }
3390 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3391 {
3392 SetLastError(ERROR_INVALID_HANDLE);
3393 return FALSE;
3394 }
3395 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3396 || !DeviceInfoData->Reserved)
3397 {
3398 SetLastError(ERROR_INVALID_PARAMETER);
3399 return FALSE;
3400 }
3401 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3402 && PropertyMap[Property].nameW)
3403 {
3404 HKEY hKey;
3405 LONG l;
3406 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
3407 if (hKey == INVALID_HANDLE_VALUE)
3408 return FALSE;
3409 /* Write new data */
3410 l = RegSetValueExW(
3411 hKey, PropertyMap[Property].nameW, 0,
3412 PropertyMap[Property].regType, PropertyBuffer,
3413 PropertyBufferSize);
3414 if (!l)
3415 ret = TRUE;
3416 else
3417 SetLastError(l);
3418 RegCloseKey(hKey);
3419 }
3420 else
3421 {
3422 ERR("Property 0x%lx not implemented\n", Property);
3423 SetLastError(ERROR_NOT_SUPPORTED);
3424 }
3425
3426 TRACE("Returning %d\n", ret);
3427 return ret;
3428 }
3429
3430 /***********************************************************************
3431 * SetupDiInstallClassA (SETUPAPI.@)
3432 */
3433 BOOL WINAPI SetupDiInstallClassA(
3434 HWND hwndParent,
3435 PCSTR InfFileName,
3436 DWORD Flags,
3437 HSPFILEQ FileQueue)
3438 {
3439 return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3440 }
3441
3442 /***********************************************************************
3443 * SetupDiInstallClassExA (SETUPAPI.@)
3444 */
3445 BOOL WINAPI
3446 SetupDiInstallClassExA(
3447 IN HWND hwndParent OPTIONAL,
3448 IN PCSTR InfFileName OPTIONAL,
3449 IN DWORD Flags,
3450 IN HSPFILEQ FileQueue OPTIONAL,
3451 IN CONST GUID *InterfaceClassGuid OPTIONAL,
3452 IN PVOID Reserved1,
3453 IN PVOID Reserved2)
3454 {
3455 PWSTR InfFileNameW = NULL;
3456 BOOL Result;
3457
3458 if (!InfFileName)
3459 {
3460 SetLastError(ERROR_INVALID_PARAMETER);
3461 return FALSE;
3462 }
3463 else
3464 {
3465 InfFileNameW = MultiByteToUnicode(InfFileName, CP_ACP);
3466 if (InfFileNameW == NULL)
3467 {
3468 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3469 return FALSE;
3470 }
3471 }
3472
3473 Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
3474 FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
3475
3476 MyFree(InfFileNameW);
3477
3478 return Result;
3479 }
3480
3481 HKEY SETUP_CreateClassKey(HINF hInf)
3482 {
3483 static const WCHAR slash[] = { '\\',0 };
3484 WCHAR FullBuffer[MAX_PATH];
3485 WCHAR Buffer[MAX_PATH];
3486 DWORD RequiredSize;
3487 HKEY hClassKey;
3488
3489 if (!SetupGetLineTextW(NULL,
3490 hInf,
3491 Version,
3492 ClassGUID,
3493 Buffer,
3494 MAX_PATH,
3495 &RequiredSize))
3496 {
3497 return INVALID_HANDLE_VALUE;
3498 }
3499
3500 lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
3501 lstrcatW(FullBuffer, slash);
3502 lstrcatW(FullBuffer, Buffer);
3503
3504 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3505 FullBuffer,
3506 0,
3507 KEY_SET_VALUE,
3508 &hClassKey))
3509 {
3510 if (!SetupGetLineTextW(NULL,
3511 hInf,
3512 Version,
3513 Class,
3514 Buffer,
3515 MAX_PATH,
3516 &RequiredSize))
3517 {
3518 return INVALID_HANDLE_VALUE;
3519 }
3520
3521 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3522 FullBuffer,
3523 0,
3524 NULL,
3525 REG_OPTION_NON_VOLATILE,
3526 KEY_SET_VALUE,
3527 NULL,
3528 &hClassKey,
3529 NULL))
3530 {
3531 return INVALID_HANDLE_VALUE;
3532 }
3533
3534 }
3535
3536 if (RegSetValueExW(hClassKey,
3537 Class,
3538 0,
3539 REG_SZ,
3540 (LPBYTE)Buffer,
3541 RequiredSize * sizeof(WCHAR)))
3542 {
3543 RegCloseKey(hClassKey);
3544 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
3545 FullBuffer);
3546 return INVALID_HANDLE_VALUE;
3547 }
3548
3549 return hClassKey;
3550 }
3551
3552 /***********************************************************************
3553 * SetupDiInstallClassW (SETUPAPI.@)
3554 */
3555 BOOL WINAPI SetupDiInstallClassW(
3556 HWND hwndParent,
3557 PCWSTR InfFileName,
3558 DWORD Flags,
3559 HSPFILEQ FileQueue)
3560 {
3561 return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3562 }
3563
3564
3565 /***********************************************************************
3566 * SetupDiOpenClassRegKey (SETUPAPI.@)
3567 */
3568 HKEY WINAPI SetupDiOpenClassRegKey(
3569 const GUID* ClassGuid,
3570 REGSAM samDesired)
3571 {
3572 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3573 DIOCR_INSTALLER, NULL, NULL);
3574 }
3575
3576
3577 /***********************************************************************
3578 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3579 */
3580 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3581 const GUID* ClassGuid,
3582 REGSAM samDesired,
3583 DWORD Flags,
3584 PCSTR MachineName,
3585 PVOID Reserved)
3586 {
3587 PWSTR MachineNameW = NULL;
3588 HKEY hKey;
3589
3590 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3591 Flags, debugstr_a(MachineName), Reserved);
3592
3593 if (MachineName)
3594 {
3595 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3596 if (MachineNameW == NULL)
3597 return INVALID_HANDLE_VALUE;
3598 }
3599
3600 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3601 Flags, MachineNameW, Reserved);
3602
3603 MyFree(MachineNameW);
3604
3605 return hKey;
3606 }
3607
3608
3609 /***********************************************************************
3610 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3611 */
3612 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3613 const GUID* ClassGuid,
3614 REGSAM samDesired,
3615 DWORD Flags,
3616 PCWSTR MachineName,
3617 PVOID Reserved)
3618 {
3619 HKEY HKLM;
3620 HKEY hClassesKey;
3621 HKEY key;
3622 LPCWSTR lpKeyName;
3623 LONG l;
3624
3625 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3626 Flags, debugstr_w(MachineName), Reserved);
3627
3628 if (MachineName != NULL)
3629 {
3630 l = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
3631 if (l != ERROR_SUCCESS)
3632 {
3633 SetLastError(l);
3634 return INVALID_HANDLE_VALUE;
3635 }
3636 }
3637 else
3638 HKLM = HKEY_LOCAL_MACHINE;
3639
3640 if (Flags == DIOCR_INSTALLER)
3641 {
3642 lpKeyName = REGSTR_PATH_CLASS_NT;
3643 }
3644 else if (Flags == DIOCR_INTERFACE)
3645 {
3646 lpKeyName = REGSTR_PATH_DEVICE_CLASSES;
3647 }
3648 else
3649 {
3650 ERR("Invalid Flags parameter!\n");
3651 SetLastError(ERROR_INVALID_FLAGS);
3652 if (MachineName != NULL) RegCloseKey(HKLM);
3653 return INVALID_HANDLE_VALUE;
3654 }
3655
3656 if (!ClassGuid)
3657 {
3658 if ((l = RegOpenKeyExW(HKLM,
3659 lpKeyName,
3660 0,
3661 samDesired,
3662 &hClassesKey)))
3663 {
3664 SetLastError(ERROR_INVALID_CLASS);
3665 hClassesKey = INVALID_HANDLE_VALUE;
3666 }
3667 if (MachineName != NULL)
3668 RegCloseKey(HKLM);
3669 key = hClassesKey;
3670 }
3671 else
3672 {
3673 WCHAR bracedGuidString[39];
3674
3675 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3676
3677 if (!(l = RegOpenKeyExW(HKLM,
3678 lpKeyName,
3679 0,
3680 samDesired,
3681 &hClassesKey)))
3682 {
3683 if (MachineName != NULL)
3684 RegCloseKey(HKLM);
3685
3686 if ((l = RegOpenKeyExW(hClassesKey,
3687 bracedGuidString,
3688 0,
3689 samDesired,
3690 &key)))
3691 {
3692 SetLastError(l);
3693 key = INVALID_HANDLE_VALUE;
3694 }
3695 RegCloseKey(hClassesKey);
3696 }
3697 else
3698 {
3699 if (MachineName != NULL) RegCloseKey(HKLM);
3700 SetLastError(l);
3701 key = INVALID_HANDLE_VALUE;
3702 }
3703 }
3704
3705 return key;
3706 }
3707
3708 /***********************************************************************
3709 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3710 */
3711 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3712 HDEVINFO DeviceInfoSet,
3713 PCWSTR DevicePath,
3714 DWORD OpenFlags,
3715 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3716 {
3717 struct DeviceInfoSet * list;
3718 PCWSTR pEnd;
3719 DWORD dwLength, dwError, dwIndex, dwKeyName, dwSubIndex;
3720 CLSID ClassId;
3721 WCHAR Buffer[MAX_PATH + 1];
3722 WCHAR SymBuffer[MAX_PATH + 1];
3723 WCHAR InstancePath[MAX_PATH + 1];
3724 HKEY hKey, hDevKey, hSymKey;
3725 struct DeviceInfo * deviceInfo;
3726 struct DeviceInterface *deviceInterface;
3727 BOOL Ret;
3728 PLIST_ENTRY ItemList;
3729 PLIST_ENTRY InterfaceListEntry;
3730
3731 TRACE("%p %s %08x %p\n",
3732 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3733
3734
3735 if (DeviceInterfaceData && DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
3736 {
3737 SetLastError(ERROR_INVALID_PARAMETER);
3738 return FALSE;
3739 }
3740
3741 if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3742 {
3743 SetLastError(ERROR_INVALID_HANDLE);
3744 return FALSE;
3745 }
3746
3747 list = (struct DeviceInfoSet * )DeviceInfoSet;
3748
3749 dwLength = wcslen(DevicePath);
3750 if (dwLength < 39)
3751 {
3752 /* path must be at least a guid length + L'\0' */
3753 SetLastError(ERROR_BAD_PATHNAME);
3754 return FALSE;
3755 }
3756
3757 if (DevicePath[0] != L'\\' ||
3758 DevicePath[1] != L'\\' ||
3759 (DevicePath[2] != L'?' && DevicePath[2] != L'.') ||
3760 DevicePath[3] != L'\\')
3761 {
3762 /* invalid formatted path */
3763 SetLastError(ERROR_BAD_PATHNAME);
3764 return FALSE;
3765 }
3766
3767 /* check for reference strings */
3768 pEnd = wcschr(&DevicePath[4], L'\\');
3769 if (!pEnd)
3770 {
3771 /* no reference string */
3772 pEnd = DevicePath + dwLength;
3773 }
3774
3775 /* copy guid */
3776 wcscpy(Buffer, pEnd - 37);
3777 Buffer[36] = L'\0';
3778
3779 dwError = UuidFromStringW(Buffer, &ClassId);
3780 if (dwError != NOERROR)
3781 {
3782 /* invalid formatted path */
3783 SetLastError(ERROR_BAD_PATHNAME);
3784 return FALSE;
3785 }
3786
3787 hKey = SetupDiOpenClassRegKeyExW(&ClassId, KEY_READ, DIOCR_INTERFACE, list->MachineName, NULL);
3788
3789 if (hKey == INVALID_HANDLE_VALUE)
3790 {
3791 /* invalid device class */
3792 return FALSE;
3793 }
3794
3795 ItemList = list->ListHead.Flink;
3796 while (ItemList != &list->ListHead)
3797 {
3798 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
3799 InterfaceListEntry = deviceInfo->InterfaceListHead.Flink;
3800 while (InterfaceListEntry != &deviceInfo->InterfaceListHead)
3801 {
3802 deviceInterface = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
3803 if (!IsEqualIID(&deviceInterface->InterfaceClassGuid, &ClassId))
3804 {
3805 InterfaceListEntry = InterfaceListEntry->Flink;
3806 continue;
3807 }
3808
3809 if (!wcsicmp(deviceInterface->SymbolicLink, DevicePath))
3810 {
3811 if (DeviceInterfaceData)
3812 {
3813 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface;
3814 DeviceInterfaceData->Flags = deviceInterface->Flags;
3815 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID));
3816 }
3817
3818 return TRUE;
3819 }
3820
3821 }
3822 }
3823
3824
3825 dwIndex = 0;
3826 do
3827 {
3828 Buffer[0] = 0;
3829 dwKeyName = sizeof(Buffer) / sizeof(WCHAR);
3830 dwError = RegEnumKeyExW(hKey, dwIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL);
3831
3832 if (dwError != ERROR_SUCCESS)
3833 break;
3834
3835 if (RegOpenKeyExW(hKey, Buffer, 0, KEY_READ, &hDevKey) != ERROR_SUCCESS)
3836 break;
3837
3838 dwSubIndex = 0;
3839 InstancePath[0] = 0;
3840 dwKeyName = sizeof(InstancePath);
3841
3842 dwError = RegQueryValueExW(hDevKey, L"DeviceInstance", NULL, NULL, (LPBYTE)InstancePath, &dwKeyName);
3843
3844 while(TRUE)
3845 {
3846 Buffer[0] = 0;
3847 dwKeyName = sizeof(Buffer) / sizeof(WCHAR);
3848 dwError = RegEnumKeyExW(hDevKey, dwSubIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL);
3849
3850 if (dwError != ERROR_SUCCESS)
3851 break;
3852
3853 dwError = RegOpenKeyExW(hDevKey, Buffer, 0, KEY_READ, &hSymKey);
3854 if (dwError != ERROR_SUCCESS)
3855 break;
3856
3857 /* query for symbolic link */
3858 dwKeyName = sizeof(SymBuffer);
3859 SymBuffer[0] = L'\0';
3860 dwError = RegQueryValueExW(hSymKey, L"SymbolicLink", NULL, NULL, (LPBYTE)SymBuffer, &dwKeyName);
3861
3862 if (dwError != ERROR_SUCCESS)
3863 {
3864 RegCloseKey(hSymKey);
3865 break;
3866 }
3867
3868 if (!wcsicmp(SymBuffer, DevicePath))
3869 {
3870 Ret = CreateDeviceInfo(list, InstancePath, &ClassId, &deviceInfo);
3871 RegCloseKey(hSymKey);
3872 RegCloseKey(hDevKey);
3873 RegCloseKey(hKey);
3874
3875 if (Ret)
3876 {
3877 deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymBuffer) + 1) * sizeof(WCHAR));
3878 if (deviceInterface)
3879 {
3880
3881 CopyMemory(&deviceInterface->InterfaceClassGuid, &ClassId, sizeof(GUID));
3882 deviceInterface->DeviceInfo = deviceInfo;
3883 deviceInterface->Flags = SPINT_ACTIVE; //FIXME
3884
3885 wcscpy(deviceInterface->SymbolicLink, SymBuffer);
3886
3887 InsertTailList(&deviceInfo->InterfaceListHead, &deviceInterface->ListEntry);
3888 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
3889
3890
3891 if (DeviceInterfaceData)
3892 {
3893 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface;
3894 DeviceInterfaceData->Flags = deviceInterface->Flags;
3895 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID));
3896 }
3897 else
3898 {
3899 Ret = FALSE;
3900 SetLastError(ERROR_INVALID_USER_BUFFER);
3901 }
3902 }
3903 }
3904 else
3905 {
3906 HeapFree(GetProcessHeap(), 0, deviceInfo);
3907 Ret = FALSE;
3908 }
3909 return Ret;
3910 }
3911 RegCloseKey(hSymKey);
3912 dwSubIndex++;
3913 }
3914
3915 RegCloseKey(hDevKey);
3916 dwIndex++;
3917 }while(TRUE);
3918
3919 RegCloseKey(hKey);
3920 return FALSE;
3921 }
3922
3923 /***********************************************************************
3924 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3925 */
3926 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3927 HDEVINFO DeviceInfoSet,
3928 PCSTR DevicePath,
3929 DWORD OpenFlags,
3930 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3931 {
3932 LPWSTR DevicePathW = NULL;
3933 BOOL bResult;
3934
3935 TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3936
3937 DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP);
3938 if (DevicePathW == NULL)
3939 return FALSE;
3940
3941 bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet,
3942 DevicePathW, OpenFlags, DeviceInterfaceData);
3943
3944 MyFree(DevicePathW);
3945
3946 return bResult;
3947 }
3948
3949 /***********************************************************************
3950 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3951 */
3952 BOOL WINAPI SetupDiSetClassInstallParamsA(
3953 HDEVINFO DeviceInfoSet,
3954 PSP_DEVINFO_DATA DeviceInfoData,
3955 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3956 DWORD ClassInstallParamsSize)
3957 {
3958 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3959 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3960 return FALSE;
3961 }
3962
3963 static BOOL WINAPI
3964 IntSetupDiRegisterDeviceInfo(
3965 IN HDEVINFO DeviceInfoSet,
3966 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
3967 {
3968 return SetupDiRegisterDeviceInfo(DeviceInfoSet, DeviceInfoData, 0, NULL, NULL, NULL);
3969 }
3970
3971 /***********************************************************************
3972 * SetupDiCallClassInstaller (SETUPAPI.@)
3973 */
3974 BOOL WINAPI SetupDiCallClassInstaller(
3975 DI_FUNCTION InstallFunction,
3976 HDEVINFO DeviceInfoSet,
3977 PSP_DEVINFO_DATA DeviceInfoData)
3978 {
3979 BOOL ret = FALSE;
3980
3981 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3982
3983 if (!DeviceInfoSet)
3984 SetLastError(ERROR_INVALID_PARAMETER);
3985 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
3986 SetLastError(ERROR_INVALID_HANDLE);
3987 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3988 SetLastError(ERROR_INVALID_HANDLE);
3989 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
3990 SetLastError(ERROR_INVALID_HANDLE);
3991 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3992 SetLastError(ERROR_INVALID_USER_BUFFER);
3993 else
3994 {
3995 SP_DEVINSTALL_PARAMS_W InstallParams;
3996 #define CLASS_COINSTALLER 0x1
3997 #define DEVICE_COINSTALLER 0x2
3998 #define CLASS_INSTALLER 0x4
3999 UCHAR CanHandle = 0;
4000 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
4001
4002 switch (InstallFunction)
4003 {
4004 case DIF_ADDPROPERTYPAGE_ADVANCED:
4005 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4006 break;
4007 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED:
4008 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4009 break;
4010 case DIF_ALLOW_INSTALL:
4011 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4012 break;
4013 case DIF_DETECT:
4014 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4015 break;
4016 case DIF_DESTROYPRIVATEDATA:
4017 CanHandle = CLASS_INSTALLER;
4018 break;
4019 case DIF_INSTALLDEVICE:
4020 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4021 DefaultHandler = SetupDiInstallDevice;
4022 break;
4023 case DIF_INSTALLDEVICEFILES:
4024 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4025 DefaultHandler = SetupDiInstallDriverFiles;
4026 break;
4027 case DIF_INSTALLINTERFACES:
4028 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4029 DefaultHandler = SetupDiInstallDeviceInterfaces;
4030 break;
4031 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
4032 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4033 break;
4034 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
4035 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4036 break;
4037 case DIF_NEWDEVICEWIZARD_PREANALYZE:
4038 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4039 break;
4040 case DIF_NEWDEVICEWIZARD_PRESELECT:
4041 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4042 break;
4043 case DIF_NEWDEVICEWIZARD_SELECT:
4044 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4045 break;
4046 case DIF_POWERMESSAGEWAKE:
4047 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4048 break;
4049 case DIF_PROPERTYCHANGE:
4050 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4051 DefaultHandler = SetupDiChangeState;
4052 break;
4053 case DIF_REGISTER_COINSTALLERS:
4054 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4055 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
4056 break;
4057 case DIF_REGISTERDEVICE:
4058 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4059 DefaultHandler = IntSetupDiRegisterDeviceInfo;
4060 break;
4061 case DIF_REMOVE:
4062 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4063 DefaultHandler = SetupDiRemoveDevice;
4064 break;
4065 case DIF_SELECTBESTCOMPATDRV:
4066 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4067 DefaultHandler = SetupDiSelectBestCompatDrv;
4068 break;
4069 case DIF_SELECTDEVICE:
4070 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4071 DefaultHandler = SetupDiSelectDevice;
4072 break;
4073 case DIF_TROUBLESHOOTER:
4074 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4075 break;
4076 case DIF_UNREMOVE:
4077 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4078 DefaultHandler = SetupDiUnremoveDevice;
4079 break;
4080 default:
4081 ERR("Install function %u not supported\n", InstallFunction);
4082 SetLastError(ERROR_NOT_SUPPORTED);
4083 }
4084
4085 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4086 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
4087 /* Don't process this call, as a parameter is invalid */
4088 CanHandle = 0;
4089
4090 if (CanHandle != 0)
4091 {
4092 LIST_ENTRY ClassCoInstallersListHead;
4093 LIST_ENTRY DeviceCoInstallersListHead;
4094 HMODULE ClassInstallerLibrary = NULL;
4095 CLASS_INSTALL_PROC ClassInstaller = NULL;
4096 COINSTALLER_CONTEXT_DATA Context;
4097 PLIST_ENTRY ListEntry;
4098 HKEY hKey;
4099 DWORD dwRegType, dwLength;
4100 DWORD rc = NO_ERROR;
4101
4102 InitializeListHead(&ClassCoInstallersListHead);
4103 InitializeListHead(&DeviceCoInstallersListHead);
4104
4105 if (CanHandle & DEVICE_COINSTALLER)
4106 {
4107 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
4108 if (hKey != INVALID_HANDLE_VALUE)
4109 {
4110 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength);
4111 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
4112 {
4113 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4114 if (KeyBuffer != NULL)
4115 {
4116 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4117 if (rc == ERROR_SUCCESS)
4118 {
4119 LPWSTR ptr;
4120 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
4121 {
4122 /* Add coinstaller to DeviceCoInstallersListHead list */
4123 struct CoInstallerElement *coinstaller;
4124 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
4125 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
4126 if (!coinstaller)
4127 continue;
4128 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
4129 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4130 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
4131 else
4132 HeapFree(GetProcessHeap(), 0, coinstaller);
4133 }
4134 }
4135 HeapFree(GetProcessHeap(), 0, KeyBuffer);
4136 }
4137 }
4138 RegCloseKey(hKey);
4139 }
4140 }
4141 if (CanHandle & CLASS_COINSTALLER)
4142 {
4143 rc = RegOpenKeyExW(
4144 HKEY_LOCAL_MACHINE,
4145 REGSTR_PATH_CODEVICEINSTALLERS,
4146 0, /* Options */
4147 KEY_QUERY_VALUE,
4148 &hKey);
4149 if (rc == ERROR_SUCCESS)
4150 {
4151 LPWSTR lpGuidString;
4152 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
4153 {
4154 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
4155 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
4156 {
4157 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4158 if (KeyBuffer != NULL)
4159 {
4160 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4161 if (rc == ERROR_SUCCESS)
4162 {
4163 LPWSTR ptr;
4164 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
4165 {
4166 /* Add coinstaller to ClassCoInstallersListHead list */
4167 struct CoInstallerElement *coinstaller;
4168 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
4169 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
4170 if (!coinstaller)
4171 continue;
4172 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
4173 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4174 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
4175 else
4176 HeapFree(GetProcessHeap(), 0, coinstaller);
4177 }
4178 }
4179 HeapFree(GetProcessHeap(), 0, KeyBuffer);
4180 }
4181 }
4182 RpcStringFreeW(&lpGuidString);
4183 }
4184 RegCloseKey(hKey);
4185 }
4186 }
4187 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
4188 {
4189 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
4190 if (hKey != INVALID_HANDLE_VALUE)
4191 {
4192 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
4193 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
4194 {
4195 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4196 if (KeyBuffer != NULL)
4197 {
4198 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4199 if (rc == ERROR_SUCCESS)
4200 {
4201 /* Get ClassInstaller function pointer */
4202 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
4203 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
4204 {
4205 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
4206 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4207 }
4208 }
4209 HeapFree(GetProcessHeap(), 0, KeyBuffer);
4210 }
4211 }
4212 RegCloseKey(hKey);
4213 }
4214 }
4215
4216 /* Call Class co-installers */
4217 Context.PostProcessing = FALSE;
4218 rc = NO_ERROR;
4219 ListEntry = ClassCoInstallersListHead.Flink;
4220 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
4221 {
4222 struct CoInstallerElement *coinstaller;
4223 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4224 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4225 coinstaller->PrivateData = Context.PrivateData;
4226 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
4227 {
4228 coinstaller->DoPostProcessing = TRUE;
4229 rc = NO_ERROR;
4230 }
4231 ListEntry = ListEntry->Flink;
4232 }
4233
4234 /* Call Device co-installers */
4235 ListEntry = DeviceCoInstallersListHead.Flink;
4236 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
4237 {
4238 struct CoInstallerElement *coinstaller;
4239 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4240 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4241 coinstaller->PrivateData = Context.PrivateData;
4242 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
4243 {
4244 coinstaller->DoPostProcessing = TRUE;
4245 rc = NO_ERROR;
4246 }
4247 ListEntry = ListEntry->Flink;
4248 }
4249
4250 /* Call Class installer */
4251 if (ClassInstaller)
4252 {
4253 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
4254 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
4255 }
4256 else
4257 rc = ERROR_DI_DO_DEFAULT;
4258
4259 /* Call default handler */
4260 if (rc == ERROR_DI_DO_DEFAULT)
4261 {
4262 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
4263 {
4264 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
4265 rc = NO_ERROR;
4266 else
4267 rc = GetLastError();
4268 }
4269 else
4270 rc = NO_ERROR;
4271 }
4272
4273 /* Call Class co-installers that required postprocessing */
4274 Context.PostProcessing = TRUE;
4275 ListEntry = ClassCoInstallersListHead.Flink;
4276 while (ListEntry != &ClassCoInstallersListHead)
4277 {
4278 struct CoInstallerElement *coinstaller;
4279 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4280 if (coinstaller->DoPostProcessing)
4281 {
4282 Context.InstallResult = rc;
4283 Context.PrivateData = coinstaller->PrivateData;
4284 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4285 }
4286 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4287 ListEntry = ListEntry->Flink;
4288 }
4289
4290 /* Call Device co-installers that required postprocessing */
4291 ListEntry = DeviceCoInstallersListHead.Flink;
4292 while (ListEntry != &DeviceCoInstallersListHead)
4293 {
4294 struct CoInstallerElement *coinstaller;
4295 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4296 if (coinstaller->DoPostProcessing)
4297 {
4298 Context.InstallResult = rc;
4299 Context.PrivateData = coinstaller->PrivateData;
4300 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4301 }
4302 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4303 ListEntry = ListEntry->Flink;
4304 }
4305
4306 /* Free allocated memory */
4307 while (!IsListEmpty(&ClassCoInstallersListHead))
4308 {
4309 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
4310 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
4311 }
4312 while (!IsListEmpty(&DeviceCoInstallersListHead))
4313 {
4314 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
4315 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
4316 }
4317
4318 ret = (rc == NO_ERROR);
4319 }
4320 }
4321
4322 TRACE("Returning %d\n", ret);
4323 return ret;
4324 }
4325
4326 /***********************************************************************
4327 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4328 */
4329 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
4330 HDEVINFO DeviceInfoSet,
4331 PSP_DEVINFO_DATA DeviceInfoData,
4332 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
4333 {
4334 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
4335 BOOL ret = FALSE;
4336
4337 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4338
4339 if (DeviceInstallParams == NULL)
4340 SetLastError(ERROR_INVALID_PARAMETER);
4341 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
4342 SetLastError(ERROR_INVALID_USER_BUFFER);
4343 else
4344 {
4345 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4346 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
4347
4348 if (ret)
4349 {
4350 /* Do W->A conversion */
4351 memcpy(
4352 DeviceInstallParams,
4353 &deviceInstallParamsW,
4354 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
4355 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
4356 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
4357 {
4358 DeviceInstallParams->DriverPath[0] = '\0';
4359 ret = FALSE;
4360 }
4361 }
4362 }
4363
4364 TRACE("Returning %d\n", ret);
4365 return ret;
4366 }
4367
4368 /***********************************************************************
4369 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4370 */
4371 BOOL WINAPI
4372 SetupDiGetDeviceInfoListClass(
4373 IN HDEVINFO DeviceInfoSet,
4374 OUT LPGUID ClassGuid)
4375 {
4376 struct DeviceInfoSet *list;
4377 BOOL ret = FALSE;
4378
4379 TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
4380
4381 if (!DeviceInfoSet)
4382 SetLastError(ERROR_INVALID_HANDLE);
4383 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4384 SetLastError(ERROR_INVALID_HANDLE);
4385 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
4386 SetLastError(ERROR_NO_ASSOCIATED_CLASS);
4387 else
4388 {
4389 memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
4390
4391 ret = TRUE;
4392 }
4393
4394 TRACE("Returning %d\n", ret);
4395 return ret;
4396 }
4397
4398 /***********************************************************************
4399 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4400 */
4401 BOOL WINAPI
4402 SetupDiGetDeviceInstallParamsW(
4403 IN HDEVINFO DeviceInfoSet,
4404 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4405 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4406 {
4407 struct DeviceInfoSet *list;
4408 BOOL ret = FALSE;
4409
4410 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4411
4412 if (!DeviceInfoSet)
4413 SetLastError(ERROR_INVALID_HANDLE);
4414 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4415 SetLastError(ERROR_INVALID_HANDLE);
4416 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4417 SetLastError(ERROR_INVALID_USER_BUFFER);
4418 else if (!DeviceInstallParams)
4419 SetLastError(ERROR_INVALID_PARAMETER);
4420 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4421 SetLastError(ERROR_INVALID_USER_BUFFER);
4422 else
4423 {
4424 PSP_DEVINSTALL_PARAMS_W Source;
4425
4426 if (DeviceInfoData)
4427 Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
4428 else
4429 Source = &list->InstallParams;
4430
4431 ret = TRUE;
4432
4433 _SEH2_TRY
4434 {
4435 memcpy(DeviceInstallParams, Source, Source->cbSize);
4436 }
4437 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4438 {
4439 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4440 ret = FALSE;
4441 }
4442 _SEH2_END;
4443 }
4444
4445 TRACE("Returning %d\n", ret);
4446 return ret;
4447 }
4448
4449 static BOOL
4450 CheckDeviceInstallParameters(
4451 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4452 {
4453 DWORD SupportedFlags =
4454 DI_NOVCP | /* 0x00000008 */
4455 DI_DIDCOMPAT | /* 0x00000010 */
4456 DI_DIDCLASS | /* 0x00000020 */
4457 DI_NEEDRESTART | /* 0x00000080 */
4458 DI_NEEDREBOOT | /* 0x00000100 */
4459 DI_RESOURCEPAGE_ADDED | /* 0x00002000 */
4460 DI_PROPERTIES_CHANGE | /* 0x00004000 */
4461 DI_ENUMSINGLEINF | /* 0x00010000 */
4462 DI_DONOTCALLCONFIGMG | /* 0x00020000 */
4463 DI_CLASSINSTALLPARAMS | /* 0x00100000 */
4464 DI_NODI_DEFAULTACTION | /* 0x00200000 */
4465 DI_QUIETINSTALL | /* 0x00800000 */
4466 DI_NOFILECOPY | /* 0x01000000 */
4467 DI_DRIVERPAGE_ADDED; /* 0x04000000 */
4468 DWORD SupportedFlagsEx =
4469 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */
4470 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */
4471 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */
4472 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */
4473 DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */
4474 DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */
4475 BOOL ret = FALSE;
4476
4477 /* FIXME: add support for more flags */
4478
4479 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4480 * It should be checked before accessing to other values
4481 * of the SP_DEVINSTALL_PARAMS structure */
4482
4483 if (DeviceInstallParams->Flags & ~SupportedFlags)
4484 {
4485 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags);
4486 SetLastError(ERROR_INVALID_FLAGS);
4487 }
4488 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx)
4489 {
4490 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx);
4491 SetLastError(ERROR_INVALID_FLAGS);
4492 }
4493 else if ((DeviceInstallParams->Flags & DI_NOVCP)
4494 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE))
4495 SetLastError(ERROR_INVALID_USER_BUFFER);
4496 else
4497 {
4498 /* FIXME: check Reserved field */
4499 ret = TRUE;
4500 }
4501
4502 return ret;
4503 }
4504
4505 /***********************************************************************
4506 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4507 */
4508 BOOL WINAPI
4509 SetupDiSetDeviceInstallParamsW(
4510 IN HDEVINFO DeviceInfoSet,
4511 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4512 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4513 {
4514 struct DeviceInfoSet *list;
4515 BOOL ret = FALSE;
4516
4517 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4518
4519 if (!DeviceInfoSet)
4520 SetLastError(ERROR_INVALID_HANDLE);
4521 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4522 SetLastError(ERROR_INVALID_HANDLE);
4523 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4524 SetLastError(ERROR_INVALID_USER_BUFFER);
4525 else if (!DeviceInstallParams)
4526 SetLastError(ERROR_INVALID_PARAMETER);
4527 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4528 SetLastError(ERROR_INVALID_USER_BUFFER);
4529 else if (CheckDeviceInstallParameters(DeviceInstallParams))
4530 {
4531 PSP_DEVINSTALL_PARAMS_W Destination;
4532
4533 if (DeviceInfoData)
4534 Destination = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
4535 else
4536 Destination = &list->InstallParams;
4537 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
4538 ret = TRUE;
4539 }
4540
4541 TRACE("Returning %d\n", ret);
4542 return ret;
4543 }
4544
4545 BOOL WINAPI SetupDiSetDeviceInstallParamsA(
4546 HDEVINFO DeviceInfoSet,
4547 PSP_DEVINFO_DATA DeviceInfoData,
4548 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
4549 {
4550 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
4551 int len = 0;
4552 BOOL ret = FALSE;
4553
4554 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4555
4556 if (DeviceInstallParams == NULL)
4557 SetLastError(ERROR_INVALID_PARAMETER);
4558 else if (DeviceInstallParams->cbSize < sizeof(SP_DEVINSTALL_PARAMS_A))
4559 SetLastError(ERROR_INVALID_USER_BUFFER);
4560 else
4561 {
4562 memcpy(&deviceInstallParamsW, DeviceInstallParams, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A, DriverPath));
4563 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4564 len = MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, NULL, 0);
4565 if (!len)
4566 {
4567 ERR("DrivePath is NULL\n");
4568 ret = FALSE;
4569 }
4570 else
4571 {
4572 MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, deviceInstallParamsW.DriverPath, len);
4573 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
4574 }
4575 }
4576
4577 TRACE("Returning %d\n", ret);
4578 return ret;
4579 }
4580
4581 static HKEY
4582 OpenHardwareProfileKey(
4583 IN HKEY HKLM,
4584 IN DWORD HwProfile,
4585 IN DWORD samDesired)
4586 {
4587 HKEY hHWProfilesKey = NULL;
4588 HKEY hHWProfileKey = NULL;
4589 HKEY ret = INVALID_HANDLE_VALUE;
4590 LONG rc;
4591
4592 rc = RegOpenKeyExW(HKLM,
4593 REGSTR_PATH_HWPROFILES,
4594 0,
4595 0,
4596 &hHWProfilesKey);
4597 if (rc != ERROR_SUCCESS)
4598 {
4599 SetLastError(rc);
4600 goto cleanup;
4601 }
4602 if (HwProfile == 0)
4603 {
4604 rc = RegOpenKeyExW(
4605 hHWProfilesKey,
4606 REGSTR_KEY_CURRENT,
4607 0,
4608 KEY_CREATE_SUB_KEY,
4609 &hHWProfileKey);
4610 }
4611 else
4612 {
4613 WCHAR subKey[5];
4614 snprintfW(subKey, 4, InstanceKeyFormat, HwProfile);
4615 subKey[4] = '\0';
4616 rc = RegOpenKeyExW(
4617 hHWProfilesKey,
4618 subKey,
4619 0,
4620 KEY_CREATE_SUB_KEY,
4621 &hHWProfileKey);
4622 }
4623 if (rc != ERROR_SUCCESS)
4624 {
4625 SetLastError(rc);
4626 goto cleanup;
4627 }
4628 ret = hHWProfileKey;
4629
4630 cleanup:
4631 if (hHWProfilesKey != NULL)
4632 RegCloseKey(hHWProfilesKey);
4633 if (hHWProfileKey != NULL && hHWProfileKey != ret)
4634 RegCloseKey(hHWProfileKey);
4635 return ret;
4636 }
4637
4638 /***********************************************************************
4639 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4640 */
4641 BOOL WINAPI
4642 SetupDiDeleteDeviceInfo(
4643 IN HDEVINFO DeviceInfoSet,
4644 IN PSP_DEVINFO_DATA DeviceInfoData)
4645 {
4646 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4647
4648 FIXME("not implemented\n");
4649 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4650 return FALSE;
4651 }
4652
4653
4654 /***********************************************************************
4655 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4656 */
4657 BOOL WINAPI
4658 SetupDiOpenDeviceInfoA(
4659 IN HDEVINFO DeviceInfoSet,
4660 IN PCSTR DeviceInstanceId,
4661 IN HWND hwndParent OPTIONAL,
4662 IN DWORD OpenFlags,
4663 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4664 {
4665 LPWSTR DeviceInstanceIdW = NULL;
4666 BOOL bResult;
4667
4668 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
4669
4670 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
4671 if (DeviceInstanceIdW == NULL)
4672 return FALSE;
4673
4674 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
4675 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
4676
4677 MyFree(DeviceInstanceIdW);
4678
4679 return bResult;
4680 }
4681
4682
4683 /***********************************************************************
4684 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4685 */
4686 BOOL WINAPI
4687 SetupDiOpenDeviceInfoW(
4688 IN HDEVINFO DeviceInfoSet,
4689 IN PCWSTR DeviceInstanceId,
4690 IN HWND hwndParent OPTIONAL,
4691 IN DWORD OpenFlags,
4692 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4693 {
4694 struct DeviceInfoSet *list;
4695 HKEY hEnumKey, hKey = NULL;
4696 DWORD rc, dwSize;
4697 BOOL ret = FALSE;
4698
4699 TRACE("%p %s %p %lx %p\n",
4700 DeviceInfoSet, debugstr_w(DeviceInstanceId),
4701 hwndParent, OpenFlags, DeviceInfoData);
4702
4703 if (OpenFlags & DIOD_CANCEL_REMOVE)
4704 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4705
4706 if (!DeviceInfoSet)
4707 SetLastError(ERROR_INVALID_HANDLE);
4708 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4709 SetLastError(ERROR_INVALID_HANDLE);
4710 else if (!DeviceInstanceId)
4711 SetLastError(ERROR_INVALID_PARAMETER);
4712 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
4713 {
4714 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
4715 SetLastError(ERROR_INVALID_FLAGS);
4716 }
4717 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4718 SetLastError(ERROR_INVALID_USER_BUFFER);
4719 else
4720 {
4721 struct DeviceInfo *deviceInfo = NULL;
4722 /* Search if device already exists in DeviceInfoSet.
4723 * If yes, return the existing element
4724 * If no, create a new element using information in registry
4725 */
4726 PLIST_ENTRY ItemList = list->ListHead.Flink;
4727 while (ItemList != &list->ListHead)
4728 {
4729 // TODO
4730 //if (good one)
4731 // break;
4732 FIXME("not implemented\n");
4733 ItemList = ItemList->Flink;
4734 }
4735
4736 if (deviceInfo)
4737 {
4738 /* good one found */
4739 ret = TRUE;
4740 }
4741 else
4742 {
4743 GUID ClassGUID;
4744 WCHAR szClassGuid[MAX_GUID_STRING_LEN];
4745
4746 /* Open supposed registry key */
4747 rc = RegOpenKeyExW(
4748 list->HKLM,
4749 REGSTR_PATH_SYSTEMENUM,
4750 0, /* Options */
4751 0,
4752 &hEnumKey);
4753 if (rc != ERROR_SUCCESS)
4754 {
4755 SetLastError(rc);
4756 goto cleanup;
4757 }
4758 rc = RegOpenKeyExW(
4759 hEnumKey,
4760 DeviceInstanceId,
4761 0, /* Options */
4762 KEY_QUERY_VALUE,
4763 &hKey);
4764 RegCloseKey(hEnumKey);
4765 if (rc != ERROR_SUCCESS)
4766 {
4767 if (rc == ERROR_FILE_NOT_FOUND)
4768 rc = ERROR_NO_SUCH_DEVINST;
4769 SetLastError(rc);
4770 goto cleanup;
4771 }
4772
4773 ClassGUID = GUID_NULL;
4774 dwSize = MAX_GUID_STRING_LEN * sizeof(WCHAR);
4775
4776 if (RegQueryValueExW(hKey,
4777 REGSTR_VAL_CLASSGUID,
4778 NULL,
4779 NULL,
4780 (LPBYTE)szClassGuid,
4781 &dwSize) == ERROR_SUCCESS)
4782 {
4783 szClassGuid[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL;
4784
4785 /* Convert a string to a ClassGuid */
4786 UuidFromStringW(&szClassGuid[1], &ClassGUID);
4787 }
4788
4789 if (!CreateDeviceInfo(list, DeviceInstanceId, &ClassGUID, &deviceInfo))
4790 goto cleanup;
4791
4792 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
4793
4794 ret = TRUE;
4795 }
4796
4797 if (ret && deviceInfo && DeviceInfoData)
4798 {
4799 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
4800 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
4801 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
4802 }
4803 }
4804
4805 cleanup:
4806 if (hKey != NULL)
4807 RegCloseKey(hKey);
4808 return ret;
4809 }
4810
4811
4812 /***********************************************************************
4813 * SetupDiGetSelectedDevice (SETUPAPI.@)
4814 */
4815 BOOL WINAPI
4816 SetupDiGetSelectedDevice(
4817 IN HDEVINFO DeviceInfoSet,
4818 OUT PSP_DEVINFO_DATA DeviceInfoData)
4819 {
4820 struct DeviceInfoSet *list;
4821 BOOL ret = FALSE;
4822
4823 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4824
4825 if (!DeviceInfoSet)
4826 SetLastError(ERROR_INVALID_HANDLE);
4827 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4828 SetLastError(ERROR_INVALID_HANDLE);
4829 else if (list->SelectedDevice == NULL)
4830 SetLastError(ERROR_NO_DEVICE_SELECTED);
4831 else if (!DeviceInfoData)
4832 SetLastError(ERROR_INVALID_PARAMETER);
4833 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4834 SetLastError(ERROR_INVALID_USER_BUFFER);
4835 else
4836 {
4837 memcpy(&DeviceInfoData->ClassGuid,
4838 &list->SelectedDevice->ClassGuid,
4839 sizeof(GUID));
4840 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst;
4841 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice;
4842 ret = TRUE;
4843 }
4844
4845 TRACE("Returning %d\n", ret);
4846 return ret;
4847 }
4848
4849
4850 /***********************************************************************
4851 * SetupDiSetSelectedDevice (SETUPAPI.@)
4852 */
4853 BOOL WINAPI
4854 SetupDiSetSelectedDevice(
4855 IN HDEVINFO DeviceInfoSet,
4856 IN PSP_DEVINFO_DATA DeviceInfoData)
4857 {
4858 struct DeviceInfoSet *list;
4859 BOOL ret = FALSE;
4860
4861 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4862
4863 if (!DeviceInfoSet)
4864 SetLastError(ERROR_INVALID_HANDLE);
4865 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4866 SetLastError(ERROR_INVALID_HANDLE);
4867 else if (!DeviceInfoData)
4868 SetLastError(ERROR_INVALID_PARAMETER);
4869 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4870 SetLastError(ERROR_INVALID_USER_BUFFER);
4871 else if (DeviceInfoData->Reserved == 0)
4872 SetLastError(ERROR_INVALID_USER_BUFFER);
4873 else
4874 {
4875 list->SelectedDevice = (struct DeviceInfo *)DeviceInfoData->Reserved;
4876 ret = TRUE;
4877 }
4878
4879 TRACE("Returning %d\n", ret);
4880 return ret;
4881 }
4882
4883
4884 /* Return the current hardware profile id, or -1 if error */
4885 static DWORD
4886 SETUPAPI_GetCurrentHwProfile(
4887 IN HDEVINFO DeviceInfoSet)
4888 {
4889 HKEY hKey = NULL;
4890 DWORD dwRegType, dwLength;
4891 DWORD hwProfile;
4892 LONG rc;
4893 DWORD ret = (DWORD)-1;
4894
4895 rc = RegOpenKeyExW(
4896 ((struct DeviceInfoSet *)DeviceInfoSet)->HKLM,
4897 REGSTR_PATH_IDCONFIGDB,
4898 0, /* Options */
4899 KEY_QUERY_VALUE,
4900 &hKey);
4901 if (rc != ERROR_SUCCESS)
4902 {
4903 SetLastError(rc);
4904 goto cleanup;
4905 }
4906
4907 dwLength = sizeof(DWORD);
4908 rc = RegQueryValueExW(
4909 hKey,
4910 REGSTR_VAL_CURRENTCONFIG,
4911 NULL,
4912 &dwRegType,
4913 (LPBYTE)&hwProfile, &dwLength);
4914 if (rc != ERROR_SUCCESS)
4915 {
4916 SetLastError(rc);
4917 goto cleanup;
4918 }
4919 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
4920 {
4921 SetLastError(ERROR_GEN_FAILURE);
4922 goto cleanup;
4923 }
4924
4925 ret = hwProfile;
4926
4927 cleanup:
4928 if (hKey != NULL)
4929 RegCloseKey(hKey);
4930
4931 return ret;
4932 }
4933
4934 static BOOL
4935 ResetDevice(
4936 IN HDEVINFO DeviceInfoSet,
4937 IN PSP_DEVINFO_DATA DeviceInfoData)
4938 {
4939 #ifndef __WINESRC__
4940 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
4941 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
4942 CONFIGRET cr;
4943
4944 cr = CM_Enable_DevNode_Ex(deviceInfo->dnDevInst, 0, set->hMachine);
4945 if (cr != CR_SUCCESS)
4946 {
4947 SetLastError(GetErrorCodeFromCrCode(cr));
4948 return FALSE;
4949 }
4950
4951 return TRUE;
4952 #else
4953 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
4954 return TRUE;
4955 #endif
4956 }
4957
4958 static BOOL StopDevice(
4959 IN HDEVINFO DeviceInfoSet,
4960 IN PSP_DEVINFO_DATA DeviceInfoData)
4961 {
4962 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
4963 return TRUE;
4964 }
4965
4966 /***********************************************************************
4967 * SetupDiChangeState (SETUPAPI.@)
4968 */
4969 BOOL WINAPI
4970 SetupDiChangeState(
4971 IN HDEVINFO DeviceInfoSet,
4972 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
4973 {
4974 PSP_PROPCHANGE_PARAMS PropChange;
4975 HKEY hKey = INVALID_HANDLE_VALUE;
4976 LPCWSTR RegistryValueName;
4977 DWORD dwConfigFlags, dwLength, dwRegType;
4978 LONG rc;
4979 BOOL ret = FALSE;
4980
4981 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4982
4983 if (!DeviceInfoData)
4984 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChangeParams;
4985 else
4986 PropChange = ((struct DeviceInfo *)DeviceInfoData->Reserved)->ClassInstallParams.PropChangeParams;
4987 if (!PropChange)
4988 {
4989 SetLastError(ERROR_INVALID_PARAMETER);
4990 goto cleanup;
4991 }
4992
4993 if (PropChange->Scope == DICS_FLAG_GLOBAL)
4994 RegistryValueName = REGSTR_VAL_CONFIGFLAGS;
4995 else
4996 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS;
4997
4998 switch (PropChange->StateChange)
4999 {
5000 case DICS_ENABLE:
5001 case DICS_DISABLE:
5002 {
5003 /* Enable/disable device in registry */
5004 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
5005 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5006 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
5007 if (hKey == INVALID_HANDLE_VALUE)
5008 break;
5009 dwLength = sizeof(DWORD);
5010 rc = RegQueryValueExW(
5011 hKey,
5012 RegistryValueName,
5013 NULL,
5014 &dwRegType,
5015 (LPBYTE)&dwConfigFlags, &dwLength);
5016 if (rc == ERROR_FILE_NOT_FOUND)
5017 dwConfigFlags = 0;
5018 else if (rc != ERROR_SUCCESS)
5019 {
5020 SetLastError(rc);
5021 goto cleanup;
5022 }
5023 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
5024 {
5025 SetLastError(ERROR_GEN_FAILURE);
5026 goto cleanup;
5027 }
5028 if (PropChange->StateChange == DICS_ENABLE)
5029 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
5030 else
5031 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
5032 rc = RegSetValueExW(
5033 hKey,
5034 RegistryValueName,
5035 0,
5036 REG_DWORD,
5037 (LPBYTE)&dwConfigFlags, sizeof(DWORD));
5038 if (rc != ERROR_SUCCESS)
5039 {
5040 SetLastError(rc);
5041 goto cleanup;
5042 }
5043
5044 /* Enable/disable device if needed */
5045 if (PropChange->Scope == DICS_FLAG_GLOBAL
5046 || PropChange->HwProfile == 0
5047 || PropChange->HwProfile == SETUPAPI_GetCurrentHwProfile(DeviceInfoSet))
5048 {
5049 if (PropChange->StateChange == DICS_ENABLE)
5050 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
5051 else
5052 ret = StopDevice(DeviceInfoSet, DeviceInfoData);
5053 }
5054 else
5055 ret = TRUE;
5056 break;
5057 }
5058 case DICS_PROPCHANGE:
5059 {
5060 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
5061 break;
5062 }
5063 default:
5064 {
5065 ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange);
5066 SetLastError(ERROR_NOT_SUPPORTED);
5067 }
5068 }
5069
5070 cleanup:
5071 if (hKey != INVALID_HANDLE_VALUE)
5072 RegCloseKey(hKey);
5073
5074 TRACE("Returning %d\n", ret);
5075 return ret;
5076 }
5077
5078 /***********************************************************************
5079 * SetupDiSelectDevice (SETUPAPI.@)
5080 */
5081 BOOL WINAPI
5082 SetupDiSelectDevice(
5083 IN HDEVINFO DeviceInfoSet,
5084 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5085 {
5086 FIXME("%p %p\n", DeviceInfoSet, DeviceInfoData);
5087 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5088 return FALSE;
5089 }
5090
5091
5092 /***********************************************************************
5093 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5094 */
5095 BOOL WINAPI
5096 SetupDiRegisterCoDeviceInstallers(
5097 IN HDEVINFO DeviceInfoSet,
5098 IN PSP_DEVINFO_DATA DeviceInfoData)
5099 {
5100 BOOL ret = FALSE; /* Return value */
5101
5102 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5103
5104 if (!DeviceInfoSet)
5105 SetLastError(ERROR_INVALID_PARAMETER);
5106 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5107 SetLastError(ERROR_INVALID_HANDLE);
5108 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5109 SetLastError(ERROR_INVALID_HANDLE);
5110 else if (!DeviceInfoData)
5111 SetLastError(ERROR_INVALID_PARAMETER);
5112 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5113 SetLastError(ERROR_INVALID_USER_BUFFER);
5114 else
5115 {
5116 SP_DEVINSTALL_PARAMS_W InstallParams;
5117 struct DriverInfoElement *SelectedDriver;
5118 BOOL Result;
5119 DWORD DoAction;
5120 WCHAR SectionName[MAX_PATH];
5121 DWORD SectionNameLength = 0;
5122 HKEY hKey = INVALID_HANDLE_VALUE;
5123 PVOID Context = NULL;
5124
5125 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5126 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5127 if (!Result)
5128 goto cleanup;
5129
5130 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5131 if (SelectedDriver == NULL)
5132 {
5133 SetLastError(ERROR_NO_DRIVER_SELECTED);
5134 goto cleanup;
5135 }
5136
5137 /* Get .CoInstallers section name */
5138 Result = SetupDiGetActualSectionToInstallW(
5139 SelectedDriver->InfFileDetails->hInf,
5140 SelectedDriver->Details.SectionName,
5141 SectionName, MAX_PATH, &SectionNameLength, NULL);
5142 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1)
5143 goto cleanup;
5144 lstrcatW(SectionName, DotCoInstallers);
5145
5146 /* Open/Create driver key information */
5147 #if _WIN32_WINNT >= 0x502
5148 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
5149 #else
5150 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
5151 #endif
5152 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5153 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
5154 if (hKey == INVALID_HANDLE_VALUE)
5155 goto cleanup;
5156
5157 /* Install .CoInstallers section */
5158 DoAction = SPINST_REGISTRY;
5159 if (!(InstallParams.Flags & DI_NOFILECOPY))
5160 {
5161 DoAction |= SPINST_FILES;
5162 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5163 if (!Context)
5164 goto cleanup;
5165 }
5166 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5167 SelectedDriver->InfFileDetails->hInf, SectionName,
5168 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
5169 SetupDefaultQueueCallbackW, Context,
5170 DeviceInfoSet, DeviceInfoData);
5171 if (!Result)
5172 goto cleanup;
5173
5174 ret = TRUE;
5175
5176 cleanup:
5177 if (Context)
5178 SetupTermDefaultQueueCallback(Context);
5179 if (hKey != INVALID_HANDLE_VALUE)
5180 RegCloseKey(hKey);
5181 }
5182
5183 TRACE("Returning %d\n", ret);
5184 return ret;
5185 }
5186
5187 static BOOL
5188 InfIsFromOEMLocation(
5189 IN PCWSTR FullName,
5190 OUT LPBOOL IsOEMLocation)
5191 {
5192 PWCHAR last;
5193
5194 last = strrchrW(FullName, '\\');
5195 if (!last)
5196 {
5197 /* No directory specified */
5198 *IsOEMLocation = FALSE;
5199 }
5200 else
5201 {
5202 LPWSTR Windir;
5203 UINT ret;
5204
5205 Windir = MyMalloc((MAX_PATH + 1 + strlenW(InfDirectory)) * sizeof(WCHAR));
5206 if (!Windir)
5207 {
5208 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5209 return FALSE;
5210 }
5211
5212 ret = GetSystemWindowsDirectoryW(Windir, MAX_PATH);
5213 if (ret == 0 || ret > MAX_PATH)
5214 {
5215 MyFree(Windir);
5216 SetLastError(ERROR_GEN_FAILURE);
5217 return FALSE;
5218 }
5219 if (*Windir && Windir[strlenW(Windir) - 1] != '\\')
5220 strcatW(Windir, BackSlash);
5221 strcatW(Windir, InfDirectory);
5222
5223 if (strncmpiW(FullName, Windir, last - FullName) == 0)
5224 {
5225 /* The path is %SYSTEMROOT%\Inf */
5226 *IsOEMLocation = FALSE;
5227 }
5228 else
5229 {
5230 /* The file is in another place */
5231 *IsOEMLocation = TRUE;
5232 }
5233 MyFree(Windir);
5234 }
5235 return TRUE;
5236 }
5237
5238 /***********************************************************************
5239 * SetupDiInstallDevice (SETUPAPI.@)
5240 */
5241 BOOL WINAPI
5242 SetupDiInstallDevice(
5243 IN HDEVINFO DeviceInfoSet,
5244 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
5245 {
5246 SP_DEVINSTALL_PARAMS_W InstallParams;
5247 struct DriverInfoElement *SelectedDriver;
5248 SYSTEMTIME DriverDate;
5249 WCHAR SectionName[MAX_PATH];
5250 WCHAR Buffer[32];
5251 DWORD SectionNameLength = 0;
5252 BOOL Result = FALSE;
5253 ULONG DoAction;
5254 DWORD RequiredSize;
5255 LPWSTR pSectionName = NULL;
5256 WCHAR ClassName[MAX_CLASS_NAME_LEN];
5257 GUID ClassGuid;
5258 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
5259 BOOL RebootRequired = FALSE;
5260 HKEY hKey = INVALID_HANDLE_VALUE;
5261 BOOL NeedtoCopyFile;
5262 LARGE_INTEGER fullVersion;
5263 LONG rc;
5264 PVOID Context = NULL;
5265 BOOL ret = FALSE; /* Return value */
5266
5267 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5268
5269 if (!DeviceInfoSet)
5270 SetLastError(ERROR_INVALID_PARAMETER);
5271 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5272 SetLastError(ERROR_INVALID_HANDLE);
5273 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5274 SetLastError(ERROR_INVALID_HANDLE);
5275 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5276 SetLastError(ERROR_INVALID_USER_BUFFER);
5277 else
5278 Result = TRUE;
5279
5280 if (!Result)
5281 {
5282 /* One parameter is bad */
5283 goto cleanup;
5284 }
5285
5286 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5287 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5288 if (!Result)
5289 goto cleanup;
5290
5291 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
5292 {
5293 /* Set FAILEDINSTALL in ConfigFlags registry value */
5294 DWORD ConfigFlags, regType;
5295 Result = SetupDiGetDeviceRegistryPropertyW(
5296 DeviceInfoSet,
5297 DeviceInfoData,
5298 SPDRP_CONFIGFLAGS,
5299 &regType,
5300 (PBYTE)&ConfigFlags,
5301 sizeof(ConfigFlags),
5302 NULL);
5303 if (!Result || regType != REG_DWORD)
5304 {
5305 SetLastError(ERROR_GEN_FAILURE);
5306 goto cleanup;
5307 }
5308 ConfigFlags |= DNF_DISABLED;
5309 Result = SetupDiSetDeviceRegistryPropertyW(
5310 DeviceInfoSet,
5311 DeviceInfoData,
5312 SPDRP_CONFIGFLAGS,
5313 (PBYTE)&ConfigFlags,
5314 sizeof(ConfigFlags));
5315 if (!Result)
5316 {
5317 SetLastError(ERROR_GEN_FAILURE);
5318 goto cleanup;
5319 }
5320
5321 ret = TRUE;
5322 goto cleanup;
5323 }
5324
5325 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5326 if (SelectedDriver == NULL)
5327 {
5328 SetLastError(ERROR_NO_DRIVER_SELECTED);
5329 goto cleanup;
5330 }
5331
5332 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
5333
5334 Result = SetupDiGetActualSectionToInstallW(
5335 SelectedDriver->InfFileDetails->hInf,
5336 SelectedDriver->Details.SectionName,
5337 SectionName, MAX_PATH, &SectionNameLength, NULL);
5338 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices))
5339 goto cleanup;
5340 pSectionName = &SectionName[strlenW(SectionName)];
5341
5342 /* Get information from [Version] section */
5343 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
5344 goto cleanup;
5345 /* Format ClassGuid to a string */
5346 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
5347 goto cleanup;
5348 RequiredSize = lstrlenW(lpGuidString);
5349 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
5350 if (!lpFullGuidString)
5351 {
5352 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5353 goto cleanup;
5354 }
5355 lpFullGuidString[0] = '{';
5356 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
5357 lpFullGuidString[RequiredSize + 1] = '}';
5358 lpFullGuidString[RequiredSize + 2] = '\0';
5359
5360 /* Copy .inf file to Inf\ directory (if needed) */
5361 Result = InfIsFromOEMLocation(SelectedDriver->Details.InfFileName, &NeedtoCopyFile);
5362 if (!Result)
5363 goto cleanup;
5364 if (NeedtoCopyFile)
5365 {
5366 WCHAR NewFileName[MAX_PATH];
5367 struct InfFileDetails *newInfFileDetails;
5368 Result = SetupCopyOEMInfW(
5369 SelectedDriver->Details.InfFileName,
5370 NULL,
5371 SPOST_NONE,
5372 SP_COPY_NOOVERWRITE,
5373 NewFileName, MAX_PATH,
5374 NULL,
5375 NULL);
5376 if (!Result)
5377 goto cleanup;
5378 /* Create a new struct InfFileDetails, and set it to
5379 * SelectedDriver->InfFileDetails, to release use of
5380 * current InfFile */
5381 newInfFileDetails = CreateInfFileDetails(NewFileName);
5382 if (!newInfFileDetails)
5383 goto cleanup;
5384 DereferenceInfFile(SelectedDriver->InfFileDetails);
5385 SelectedDriver->InfFileDetails = newInfFileDetails;
5386 strcpyW(SelectedDriver->Details.InfFileName, NewFileName);
5387 }
5388
5389 /* Open/Create driver key information */
5390 #if _WIN32_WINNT >= 0x502
5391 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
5392 #else
5393 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
5394 #endif
5395 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5396 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
5397 if (hKey == INVALID_HANDLE_VALUE)
5398 goto cleanup;
5399
5400 /* Install main section */
5401 DoAction = 0;
5402 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
5403 DoAction |= SPINST_REGISTRY;
5404 if (!(InstallParams.Flags & DI_NOFILECOPY))
5405 {
5406 DoAction |= SPINST_FILES;
5407 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5408 if (!Context)
5409 goto cleanup;
5410 }
5411 *pSectionName = '\0';
5412 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5413 SelectedDriver->InfFileDetails->hInf, SectionName,
5414 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
5415 SetupDefaultQueueCallbackW, Context,
5416 DeviceInfoSet, DeviceInfoData);
5417 if (!Result)
5418 goto cleanup;
5419 InstallParams.Flags |= DI_NOFILECOPY;
5420 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5421
5422 /* Write information to driver key */
5423 *pSectionName = UNICODE_NULL;
5424 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
5425 TRACE("Write information to driver key\n");
5426 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5427 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
5428 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
5429 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName));
5430 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName));
5431 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)]));
5432 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId));
5433 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName));
5434 sprintfW(Buffer, DateFormat, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5435 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
5436 if (rc == ERROR_SUCCESS)
5437 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
5438 if (rc == ERROR_SUCCESS)
5439 rc = RegSetValueExW(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
5440 if (rc == ERROR_SUCCESS)
5441 {
5442 sprintfW(Buffer, VersionFormat, fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
5443 rc = RegSetValueExW(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
5444 }
5445 if (rc == ERROR_SUCCESS)
5446 rc = RegSetValueExW(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->InfFileDetails->FileName, (strlenW(SelectedDriver->InfFileDetails->FileName) + 1) * sizeof(WCHAR));
5447 if (rc == ERROR_SUCCESS)
5448 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
5449 if (rc == ERROR_SUCCESS)
5450 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));
5451 if (rc == ERROR_SUCCESS)
5452 rc = RegSetValueExW(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
5453 if (rc == ERROR_SUCCESS)
5454 rc = RegSetValueExW(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
5455 if (rc != ERROR_SUCCESS)
5456 {
5457 SetLastError(rc);
5458 goto cleanup;
5459 }
5460 RegCloseKey(hKey);
5461 hKey = INVALID_HANDLE_VALUE;
5462
5463 /* FIXME: Process .LogConfigOverride section */
5464
5465 /* Install .Services section */
5466 strcpyW(pSectionName, DotServices);
5467 Result = SetupInstallServicesFromInfSectionExW(
5468 SelectedDriver->InfFileDetails->hInf,
5469 SectionName,
5470 0,
5471 DeviceInfoSet,
5472 DeviceInfoData,
5473 NULL,
5474 NULL);
5475 if (!Result)
5476 goto cleanup;
5477 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
5478 RebootRequired = TRUE;
5479
5480 /* Open device registry key */
5481 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
5482 if (hKey == INVALID_HANDLE_VALUE)
5483 goto cleanup;
5484
5485 /* Install .HW section */
5486 DoAction = 0;
5487 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
5488 DoAction |= SPINST_REGISTRY;
5489 strcpyW(pSectionName, DotHW);
5490 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5491 SelectedDriver->InfFileDetails->hInf, SectionName,
5492 DoAction, hKey, NULL, 0,
5493 NULL, NULL,
5494 DeviceInfoSet, DeviceInfoData);
5495 if (!Result)
5496 goto cleanup;
5497
5498 /* Write information to enum key */
5499 TRACE("Write information to enum key\n");
5500 TRACE("Class : '%s'\n", debugstr_w(ClassName));
5501 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString));
5502 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
5503 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName));
5504 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR));
5505 if (rc == ERROR_SUCCESS)
5506 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR));
5507 if (rc == ERROR_SUCCESS)
5508 rc = RegSetValueExW(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
5509 if (rc == ERROR_SUCCESS)
5510 rc = RegSetValueExW(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
5511 if (rc != ERROR_SUCCESS)
5512 {
5513 SetLastError(rc);
5514 goto cleanup;
5515 }
5516
5517 /* Start the device */
5518 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
5519 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
5520 else
5521 ret = TRUE;
5522
5523 cleanup:
5524 /* End of installation */
5525 if (hKey != INVALID_HANDLE_VALUE)
5526 RegCloseKey(hKey);
5527 if (lpGuidString)
5528 RpcStringFreeW(&lpGuidString);
5529 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
5530 if (Context)
5531 SetupTermDefaultQueueCallback(Context);
5532 TRACE("Returning %d\n", ret);
5533 return ret;
5534 }
5535
5536 static HKEY SETUPDI_OpenDevKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired)
5537 {
5538 HKEY enumKey, key = INVALID_HANDLE_VALUE;
5539 LONG l;
5540
5541 l = RegOpenKeyExW(RootKey, REGSTR_PATH_SYSTEMENUM, 0, 0, &enumKey);
5542 if (!l)
5543 {
5544 l = RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key);
5545 RegCloseKey(enumKey);
5546 }
5547 if (l)
5548 SetLastError(l);
5549 return key;
5550 }
5551
5552 static HKEY SETUPDI_OpenDrvKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired)
5553 {
5554 LPWSTR DriverKey = NULL;
5555 DWORD dwLength = 0;
5556 DWORD dwRegType;
5557 DWORD rc;
5558 HKEY hEnumKey = NULL;
5559 HKEY hKey = NULL;
5560 HKEY key = INVALID_HANDLE_VALUE;
5561
5562 hKey = SETUPDI_OpenDevKey(RootKey, devInfo, KEY_QUERY_VALUE);
5563 if (hKey == INVALID_HANDLE_VALUE)
5564 goto cleanup;
5565 /* Read the 'Driver' key */
5566 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength);
5567 if (rc != ERROR_SUCCESS)
5568 {
5569 SetLastError(rc);
5570 goto cleanup;
5571 }
5572 else if (dwRegType != REG_SZ)
5573 {
5574 SetLastError(ERROR_GEN_FAILURE);
5575 goto cleanup;
5576 }
5577 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
5578 if (!DriverKey)
5579 {
5580 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5581 goto cleanup;
5582 }
5583 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
5584 if (rc != ERROR_SUCCESS)
5585 {
5586 SetLastError(rc);
5587 goto cleanup;
5588 }
5589 RegCloseKey(hKey);
5590 hKey = NULL;
5591 /* Need to open the driver key */
5592 rc = RegOpenKeyExW(
5593 RootKey,
5594 REGSTR_PATH_CLASS_NT,
5595 0, /* Options */
5596 0,
5597 &hEnumKey);
5598 if (rc != ERROR_SUCCESS)
5599 {
5600 SetLastError(rc);
5601 goto cleanup;
5602 }
5603 rc = RegOpenKeyExW(
5604 hEnumKey,
5605 DriverKey,
5606 0, /* Options */
5607 samDesired,
5608 &hKey);
5609 if (rc != ERROR_SUCCESS)
5610 {
5611 SetLastError(rc);
5612 goto cleanup;
5613 }
5614 key = hKey;
5615
5616 cleanup:
5617 if (hEnumKey != NULL)
5618 RegCloseKey(hEnumKey);
5619 if (hKey != NULL && hKey != key)
5620 RegCloseKey(hKey);
5621 return key;
5622 }
5623
5624 /***********************************************************************
5625 * SetupDiOpenDevRegKey (SETUPAPI.@)
5626 */
5627 HKEY WINAPI SetupDiOpenDevRegKey(
5628 HDEVINFO DeviceInfoSet,
5629 PSP_DEVINFO_DATA DeviceInfoData,
5630 DWORD Scope,
5631 DWORD HwProfile,
5632 DWORD KeyType,
5633 REGSAM samDesired)
5634 {
5635 struct DeviceInfoSet *set = DeviceInfoSet;
5636 struct DeviceInfo *devInfo;
5637 HKEY key = INVALID_HANDLE_VALUE;
5638 HKEY RootKey;
5639
5640 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
5641 Scope, HwProfile, KeyType, samDesired);
5642
5643 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
5644 {
5645 SetLastError(ERROR_INVALID_HANDLE);
5646 return INVALID_HANDLE_VALUE;
5647 }
5648 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5649 {
5650 SetLastError(ERROR_INVALID_HANDLE);
5651 return INVALID_HANDLE_VALUE;
5652 }
5653 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
5654 || !DeviceInfoData->Reserved)
5655 {
5656 SetLastError(ERROR_INVALID_PARAMETER);
5657 return INVALID_HANDLE_VALUE;
5658 }
5659 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
5660 {
5661 SetLastError(ERROR_INVALID_FLAGS);
5662 return INVALID_HANDLE_VALUE;
5663 }
5664 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
5665 {
5666 SetLastError(ERROR_INVALID_FLAGS);
5667 return INVALID_HANDLE_VALUE;
5668 }
5669 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
5670 if (devInfo->set != set)
5671 {
5672 SetLastError(ERROR_INVALID_PARAMETER);
5673 return INVALID_HANDLE_VALUE;
5674 }
5675 if (Scope != DICS_FLAG_GLOBAL)
5676 {
5677 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0);
5678 if (RootKey == INVALID_HANDLE_VALUE)
5679 return INVALID_HANDLE_VALUE;
5680 }
5681 else
5682 RootKey = set->HKLM;
5683 switch (KeyType)
5684 {
5685 case DIREG_DEV:
5686 key = SETUPDI_OpenDevKey(RootKey, devInfo, samDesired);
5687 break;
5688 case DIREG_DRV:
5689 key = SETUPDI_OpenDrvKey(RootKey, devInfo, samDesired);
5690 break;
5691 default:
5692 WARN("unknown KeyType %d\n", KeyType);
5693 }
5694 if (RootKey != set->HKLM)
5695 RegCloseKey(RootKey);
5696 return key;
5697 }
5698
5699 static BOOL SETUPDI_DeleteDevKey(HKEY RootKey, struct DeviceInfo *devInfo)
5700 {
5701 FIXME("\n");
5702 return FALSE;
5703 }
5704
5705 static BOOL SETUPDI_DeleteDrvKey(HKEY RootKey, struct DeviceInfo *devInfo)
5706 {
5707 FIXME("\n");
5708 return FALSE;
5709 }
5710
5711 /***********************************************************************
5712 * SetupDiDeleteDevRegKey (SETUPAPI.@)
5713 */
5714 BOOL WINAPI SetupDiDeleteDevRegKey(
5715 HDEVINFO DeviceInfoSet,
5716 PSP_DEVINFO_DATA DeviceInfoData,
5717 DWORD Scope,
5718 DWORD HwProfile,
5719 DWORD KeyType)
5720 {
5721 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
5722 struct DeviceInfo *devInfo;
5723 BOOL ret = FALSE;
5724 HKEY RootKey;
5725
5726 TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile,
5727 KeyType);
5728
5729 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
5730 {
5731 SetLastError(ERROR_INVALID_HANDLE);
5732 return FALSE;
5733 }
5734 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5735 {
5736 SetLastError(ERROR_INVALID_HANDLE);
5737 return FALSE;
5738 }
5739 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
5740 || !DeviceInfoData->Reserved)
5741 {
5742 SetLastError(ERROR_INVALID_PARAMETER);
5743 return FALSE;
5744 }
5745 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
5746 {
5747 SetLastError(ERROR_INVALID_FLAGS);
5748 return FALSE;
5749 }
5750 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH)
5751 {
5752 SetLastError(ERROR_INVALID_FLAGS);
5753 return FALSE;
5754 }
5755 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
5756 if (devInfo->set != set)
5757 {
5758 SetLastError(ERROR_INVALID_PARAMETER);
5759 return FALSE;
5760 }
5761 if (Scope != DICS_FLAG_GLOBAL)
5762 {
5763 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0);
5764 if (RootKey == INVALID_HANDLE_VALUE)
5765 return FALSE;
5766 }
5767 else
5768 RootKey = set->HKLM;
5769 switch (KeyType)
5770 {
5771 case DIREG_DEV:
5772 ret = SETUPDI_DeleteDevKey(RootKey, devInfo);
5773 break;
5774 case DIREG_DRV:
5775 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo);
5776 break;
5777 case DIREG_BOTH:
5778 ret = SETUPDI_DeleteDevKey(RootKey, devInfo);
5779 if (ret)
5780 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo);
5781 break;
5782 default:
5783 WARN("unknown KeyType %d\n", KeyType);
5784 }
5785 if (RootKey != set->HKLM)
5786 RegCloseKey(RootKey);
5787 return ret;
5788 }