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