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