[SETUPAPI] Fix broken control definition.
[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 DateFormat[] = {'%','u','-','%','u','-','%','u',0};
27 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
28 static const WCHAR DotHW[] = {'.','H','W',0};
29 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
30 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
31 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0};
32 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
33 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
34
35 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0};
36 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
37 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
38 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0};
39 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};
40
41 typedef DWORD
42 (CALLBACK* CLASS_INSTALL_PROC) (
43 IN DI_FUNCTION InstallFunction,
44 IN HDEVINFO DeviceInfoSet,
45 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
46 typedef BOOL
47 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
48 IN HDEVINFO DeviceInfoSet,
49 IN OUT PSP_DEVINFO_DATA DeviceInfoData);
50 typedef DWORD
51 (CALLBACK* COINSTALLER_PROC) (
52 IN DI_FUNCTION InstallFunction,
53 IN HDEVINFO DeviceInfoSet,
54 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
55 IN OUT PCOINSTALLER_CONTEXT_DATA Context);
56
57 struct CoInstallerElement
58 {
59 LIST_ENTRY ListEntry;
60
61 HMODULE Module;
62 COINSTALLER_PROC Function;
63 BOOL DoPostProcessing;
64 PVOID PrivateData;
65 };
66
67 struct GetSectionCallbackInfo
68 {
69 PSP_ALTPLATFORM_INFO PlatformInfo;
70 BYTE ProductType;
71 WORD SuiteMask;
72 DWORD PrefixLength;
73 WCHAR BestSection[LINE_LEN + 1];
74 DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5;
75 };
76
77
78
79 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
80 {
81 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
82 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
83 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
84 '0','2','X','}',0};
85
86 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
87 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
88 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
89 }
90
91 static DWORD
92 GetErrorCodeFromCrCode(const IN CONFIGRET cr)
93 {
94 switch (cr)
95 {
96 case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED;
97 case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER;
98 case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED;
99 case CR_FAILURE: return ERROR_GEN_FAILURE;
100 case CR_INVALID_DATA: return ERROR_INVALID_USER_BUFFER;
101 case CR_INVALID_DEVICE_ID: return ERROR_INVALID_PARAMETER;
102 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
103 case CR_INVALID_DEVNODE: return ERROR_INVALID_PARAMETER;
104 case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS;
105 case CR_INVALID_POINTER: return ERROR_INVALID_PARAMETER;
106 case CR_INVALID_PROPERTY: return ERROR_INVALID_PARAMETER;
107 case CR_NO_SUCH_DEVNODE: return ERROR_FILE_NOT_FOUND;
108 case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND;
109 case CR_NO_SUCH_VALUE: return ERROR_FILE_NOT_FOUND;
110 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
111 case CR_REGISTRY_ERROR: return ERROR_GEN_FAILURE;
112 case CR_ALREADY_SUCH_DEVINST: return ERROR_DEVINST_ALREADY_EXISTS;
113 case CR_SUCCESS: return ERROR_SUCCESS;
114 default: return ERROR_GEN_FAILURE;
115 }
116
117 /* Does not happen */
118 }
119
120 /* Lower scores are best ones */
121 static BOOL
122 CheckSectionValid(
123 IN LPCWSTR SectionName,
124 IN PSP_ALTPLATFORM_INFO PlatformInfo,
125 IN BYTE ProductType,
126 IN WORD SuiteMask,
127 OUT PDWORD ScorePlatform,
128 OUT PDWORD ScoreMajorVersion,
129 OUT PDWORD ScoreMinorVersion,
130 OUT PDWORD ScoreProductType,
131 OUT PDWORD ScoreSuiteMask)
132 {
133 LPWSTR Section = NULL;
134 //LPCWSTR pExtensionPlatform;
135 LPCWSTR pExtensionArchitecture;
136 LPWSTR Fields[6];
137 DWORD i;
138 BOOL ret = FALSE;
139
140 //static const WCHAR ExtensionPlatformNone[] = {'.',0};
141 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
142 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
143
144 static const WCHAR ExtensionArchitectureNone[] = {0};
145 static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0};
146 static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0};
147 static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0};
148 static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0};
149 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
150 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
151
152 TRACE("%s %p 0x%x 0x%x\n",
153 debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask);
154
155 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0;
156
157 Section = pSetupDuplicateString(SectionName);
158 if (!Section)
159 {
160 TRACE("pSetupDuplicateString() failed\n");
161 goto cleanup;
162 }
163
164 /* Set various extensions values */
165 switch (PlatformInfo->Platform)
166 {
167 case VER_PLATFORM_WIN32_WINDOWS:
168 //pExtensionPlatform = ExtensionPlatformWindows;
169 break;
170 case VER_PLATFORM_WIN32_NT:
171 //pExtensionPlatform = ExtensionPlatformNT;
172 break;
173 default:
174 ERR("Unknown platform 0x%lx\n", PlatformInfo->Platform);
175 //pExtensionPlatform = ExtensionPlatformNone;
176 break;
177 }
178 switch (PlatformInfo->ProcessorArchitecture)
179 {
180 case PROCESSOR_ARCHITECTURE_ALPHA:
181 pExtensionArchitecture = ExtensionArchitecturealpha;
182 break;
183 case PROCESSOR_ARCHITECTURE_AMD64:
184 pExtensionArchitecture = ExtensionArchitectureamd64;
185 break;
186 case PROCESSOR_ARCHITECTURE_IA64:
187 pExtensionArchitecture = ExtensionArchitectureia64;
188 break;
189 case PROCESSOR_ARCHITECTURE_INTEL:
190 pExtensionArchitecture = ExtensionArchitecturex86;
191 break;
192 case PROCESSOR_ARCHITECTURE_MIPS:
193 pExtensionArchitecture = ExtensionArchitecturemips;
194 break;
195 case PROCESSOR_ARCHITECTURE_PPC:
196 pExtensionArchitecture = ExtensionArchitectureppc;
197 break;
198 default:
199 ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture);
200 case PROCESSOR_ARCHITECTURE_UNKNOWN:
201 pExtensionArchitecture = ExtensionArchitectureNone;
202 break;
203 }
204
205 /*
206 * Field[0] Platform
207 * Field[1] Architecture
208 * Field[2] Major version
209 * Field[3] Minor version
210 * Field[4] Product type
211 * Field[5] Suite mask
212 * Remark: these fields may be NULL if the information is not provided
213 */
214 Fields[0] = Section;
215 if (Fields[0] == NULL)
216 {
217 TRACE("No extension found\n");
218 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX;
219 ret = TRUE;
220 goto cleanup;
221 }
222 Fields[1] = Fields[0] + 1;
223 Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL;
224 for (i = 2; Fields[i - 1] != NULL && i < 6; i++)
225 {
226 Fields[i] = wcschr(Fields[i - 1], '.');
227 if (Fields[i])
228 {
229 Fields[i]++;
230 *(Fields[i] - 1) = UNICODE_NULL;
231 }
232 }
233 /* Take care of first 2 fields */
234 if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0)
235 {
236 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS)
237 {
238 TRACE("Mismatch on platform field\n");
239 goto cleanup;
240 }
241 Fields[1] += wcslen(ExtensionPlatformWindows) - 1;
242 }
243 else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0)
244 {
245 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT)
246 {
247 TRACE("Mismatch on platform field\n");
248 goto cleanup;
249 }
250 Fields[1] += wcslen(ExtensionPlatformNT) - 1;
251 }
252 else
253 {
254 /* No platform specified */
255 *ScorePlatform |= 0x02;
256 }
257 if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0)
258 {
259 /* No architecture specified */
260 *ScorePlatform |= 0x01;
261 }
262 else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0)
263 {
264 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
265 debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture));
266 goto cleanup;
267 }
268
269 /* Check if informations are matching */
270 if (Fields[2] && *Fields[2])
271 {
272 DWORD MajorVersion, MinorVersion = 0;
273 MajorVersion = strtoulW(Fields[2], NULL, 0);
274 if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) &&
275 (errno == ERANGE || errno == EINVAL))
276 {
277 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2]));
278 goto cleanup;
279 }
280 if (Fields[3] && *Fields[3])
281 {
282 MinorVersion = strtoulW(Fields[3], NULL, 0);
283 if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) &&
284 (errno == ERANGE || errno == EINVAL))
285 {
286 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3]));
287 goto cleanup;
288 }
289 }
290 if (PlatformInfo->MajorVersion < MajorVersion ||
291 (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion))
292 {
293 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
294 MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion);
295 goto cleanup;
296 }
297 *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion;
298 if (MajorVersion == PlatformInfo->MajorVersion)
299 *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion;
300 else
301 *ScoreMinorVersion = MinorVersion;
302 }
303 else if (Fields[3] && *Fields[3])
304 {
305 TRACE("Minor version found without major version\n");
306 goto cleanup;
307 }
308 else
309 {
310 *ScoreMajorVersion = PlatformInfo->MajorVersion;
311 *ScoreMinorVersion = PlatformInfo->MinorVersion;
312 }
313
314 if (Fields[4] && *Fields[4])
315 {
316 DWORD CurrentProductType;
317 CurrentProductType = strtoulW(Fields[4], NULL, 0);
318 if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) &&
319 (errno == ERANGE || errno == EINVAL))
320 {
321 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4]));
322 goto cleanup;
323 }
324 if (CurrentProductType != ProductType)
325 {
326 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
327 CurrentProductType, ProductType);
328 goto cleanup;
329 }
330 }
331 else
332 *ScoreProductType = 1;
333
334 if (Fields[5] && *Fields[5])
335 {
336 DWORD CurrentSuiteMask;
337 CurrentSuiteMask = strtoulW(Fields[5], NULL, 0);
338 if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) &&
339 (errno == ERANGE || errno == EINVAL))
340 {
341 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5]));
342 goto cleanup;
343 }
344 if ((CurrentSuiteMask & ~SuiteMask) != 0)
345 {
346 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
347 CurrentSuiteMask, SuiteMask);
348 goto cleanup;
349 }
350 *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask;
351 }
352 else
353 *ScoreSuiteMask = SuiteMask;
354
355 ret = TRUE;
356
357 cleanup:
358 MyFree(Section);
359 return ret;
360 }
361
362 static BOOL
363 GetSectionCallback(
364 IN LPCWSTR SectionName,
365 IN PVOID Context)
366 {
367 struct GetSectionCallbackInfo *info = Context;
368 DWORD Score1, Score2, Score3, Score4, Score5;
369 BOOL ret;
370
371 if (SectionName[info->PrefixLength] != '.')
372 return TRUE;
373
374 ret = CheckSectionValid(
375 &SectionName[info->PrefixLength],
376 info->PlatformInfo,
377 info->ProductType,
378 info->SuiteMask,
379 &Score1, &Score2, &Score3, &Score4, &Score5);
380 if (!ret)
381 {
382 TRACE("Section %s not compatible\n", debugstr_w(SectionName));
383 return TRUE;
384 }
385 if (Score1 > info->BestScore1) goto done;
386 if (Score1 < info->BestScore1) goto bettersection;
387 if (Score2 > info->BestScore2) goto done;
388 if (Score2 < info->BestScore2) goto bettersection;
389 if (Score3 > info->BestScore3) goto done;
390 if (Score3 < info->BestScore3) goto bettersection;
391 if (Score4 > info->BestScore4) goto done;
392 if (Score4 < info->BestScore4) goto bettersection;
393 if (Score5 > info->BestScore5) goto done;
394 if (Score5 < info->BestScore5) goto bettersection;
395 goto done;
396
397 bettersection:
398 strcpyW(info->BestSection, SectionName);
399 info->BestScore1 = Score1;
400 info->BestScore2 = Score2;
401 info->BestScore3 = Score3;
402 info->BestScore4 = Score4;
403 info->BestScore5 = Score5;
404
405 done:
406 return TRUE;
407 }
408
409 /***********************************************************************
410 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
411 */
412 BOOL WINAPI
413 SetupDiGetActualSectionToInstallExW(
414 IN HINF InfHandle,
415 IN PCWSTR InfSectionName,
416 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
417 OUT PWSTR InfSectionWithExt OPTIONAL,
418 IN DWORD InfSectionWithExtSize,
419 OUT PDWORD RequiredSize OPTIONAL,
420 OUT PWSTR* Extension OPTIONAL,
421 IN PVOID Reserved)
422 {
423 BOOL ret = FALSE;
424
425 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
426 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
427 RequiredSize, Extension, Reserved);
428
429 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
430 SetLastError(ERROR_INVALID_HANDLE);
431 else if (!InfSectionName)
432 SetLastError(ERROR_INVALID_PARAMETER);
433 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
434 SetLastError(ERROR_INVALID_USER_BUFFER);
435 else if (Reserved != NULL)
436 SetLastError(ERROR_INVALID_PARAMETER);
437 else
438 {
439 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
440 static BYTE CurrentProductType = 0;
441 static WORD CurrentSuiteMask = 0;
442 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
443 struct GetSectionCallbackInfo CallbackInfo;
444 DWORD dwFullLength;
445 BYTE ProductType;
446 WORD SuiteMask;
447
448 /* Fill platform info if needed */
449 if (AlternatePlatformInfo)
450 {
451 pPlatformInfo = AlternatePlatformInfo;
452 ProductType = 0;
453 SuiteMask = 0;
454 }
455 else
456 {
457 if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
458 {
459 /* That's the first time we go here. We need to fill in the structure */
460 SYSTEM_INFO SystemInfo;
461 GetSystemInfo(&SystemInfo);
462 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
463 CurrentPlatform.Platform = OsVersionInfo.dwPlatformId;
464 CurrentPlatform.MajorVersion = OsVersionInfo.dwMajorVersion;
465 CurrentPlatform.MinorVersion = OsVersionInfo.dwMinorVersion;
466 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
467 CurrentPlatform.Reserved = 0;
468 CurrentProductType = OsVersionInfo.wProductType;
469 CurrentSuiteMask = OsVersionInfo.wSuiteMask;
470 }
471 ProductType = CurrentProductType;
472 SuiteMask = CurrentSuiteMask;
473 }
474
475 CallbackInfo.PlatformInfo = pPlatformInfo;
476 CallbackInfo.ProductType = ProductType;
477 CallbackInfo.SuiteMask = SuiteMask;
478 CallbackInfo.PrefixLength = strlenW(InfSectionName);
479 CallbackInfo.BestScore1 = ULONG_MAX;
480 CallbackInfo.BestScore2 = ULONG_MAX;
481 CallbackInfo.BestScore3 = ULONG_MAX;
482 CallbackInfo.BestScore4 = ULONG_MAX;
483 CallbackInfo.BestScore5 = ULONG_MAX;
484 strcpyW(CallbackInfo.BestSection, InfSectionName);
485 TRACE("EnumerateSectionsStartingWith(InfSectionName = %S)\n", InfSectionName);
486 if (!EnumerateSectionsStartingWith(
487 InfHandle,
488 InfSectionName,
489 GetSectionCallback,
490 &CallbackInfo))
491 {
492 SetLastError(ERROR_GEN_FAILURE);
493 goto done;
494 }
495 TRACE("CallbackInfo.BestSection = %S\n", CallbackInfo.BestSection);
496
497 dwFullLength = lstrlenW(CallbackInfo.BestSection);
498 if (RequiredSize != NULL)
499 *RequiredSize = dwFullLength + 1;
500
501 if (InfSectionWithExtSize > 0)
502 {
503 if (InfSectionWithExtSize < dwFullLength + 1)
504 {
505 SetLastError(ERROR_INSUFFICIENT_BUFFER);
506 goto done;
507 }
508 strcpyW(InfSectionWithExt, CallbackInfo.BestSection);
509 if (Extension)
510 {
511 DWORD dwLength = lstrlenW(InfSectionName);
512 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
513 }
514 }
515
516 ret = TRUE;
517 }
518
519 done:
520 TRACE("Returning %d\n", ret);
521 return ret;
522 }
523
524
525 BOOL
526 CreateDeviceInfo(
527 IN struct DeviceInfoSet *list,
528 IN LPCWSTR InstancePath,
529 IN LPCGUID pClassGuid,
530 OUT struct DeviceInfo **pDeviceInfo)
531 {
532 DWORD size;
533 CONFIGRET cr;
534 struct DeviceInfo *deviceInfo;
535
536 *pDeviceInfo = NULL;
537
538 size = FIELD_OFFSET(struct DeviceInfo, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR);
539 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
540 if (!deviceInfo)
541 {
542 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
543 return FALSE;
544 }
545 ZeroMemory(deviceInfo, size);
546
547 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
548 if (cr != CR_SUCCESS)
549 {
550 SetLastError(GetErrorCodeFromCrCode(cr));
551 return FALSE;
552 }
553
554 deviceInfo->set = list;
555 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
556 strcpyW(deviceInfo->Data, InstancePath);
557 deviceInfo->instanceId = deviceInfo->Data;
558 deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
559 deviceInfo->DeviceDescription = NULL;
560 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
561 deviceInfo->CreationFlags = 0;
562 InitializeListHead(&deviceInfo->DriverListHead);
563 InitializeListHead(&deviceInfo->InterfaceListHead);
564
565 *pDeviceInfo = deviceInfo;
566 return TRUE;
567 }
568
569
570 static BOOL
571 DestroyClassInstallParams(struct ClassInstallParams* installParams)
572 {
573 HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams);
574 HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData);
575 return TRUE;
576 }
577
578 static BOOL
579 DestroyDeviceInfo(struct DeviceInfo *deviceInfo)
580 {
581 PLIST_ENTRY ListEntry;
582 struct DriverInfoElement *driverInfo;
583 struct DeviceInterface *deviceInterface;
584
585 while (!IsListEmpty(&deviceInfo->DriverListHead))
586 {
587 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
588 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
589 if (!DestroyDriverInfoElement(driverInfo))
590 return FALSE;
591 }
592 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
593 {
594 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
595 deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
596 if (!DestroyDeviceInterface(deviceInterface))
597 return FALSE;
598 }
599 DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
600 if (deviceInfo->hmodDevicePropPageProvider)
601 FreeLibrary(deviceInfo->hmodDevicePropPageProvider);
602 return HeapFree(GetProcessHeap(), 0, deviceInfo);
603 }
604
605 static BOOL
606 DestroyDeviceInfoSet(struct DeviceInfoSet* list)
607 {
608 PLIST_ENTRY ListEntry;
609 struct DeviceInfo *deviceInfo;
610
611 while (!IsListEmpty(&list->ListHead))
612 {
613 ListEntry = RemoveHeadList(&list->ListHead);
614 deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry);
615 if (!DestroyDeviceInfo(deviceInfo))
616 return FALSE;
617 }
618 if (list->HKLM != HKEY_LOCAL_MACHINE)
619 RegCloseKey(list->HKLM);
620 CM_Disconnect_Machine(list->hMachine);
621 DestroyClassInstallParams(&list->ClassInstallParams);
622 if (list->hmodClassPropPageProvider)
623 FreeLibrary(list->hmodClassPropPageProvider);
624 return HeapFree(GetProcessHeap(), 0, list);
625 }
626
627 /***********************************************************************
628 * SetupDiBuildClassInfoList (SETUPAPI.@)
629 *
630 * Returns a list of setup class GUIDs that identify the classes
631 * that are installed on a local machine.
632 *
633 * PARAMS
634 * Flags [I] control exclusion of classes from the list.
635 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
636 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
637 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
638 *
639 * RETURNS
640 * Success: TRUE.
641 * Failure: FALSE.
642 */
643 BOOL WINAPI SetupDiBuildClassInfoList(
644 DWORD Flags,
645 LPGUID ClassGuidList,
646 DWORD ClassGuidListSize,
647 PDWORD RequiredSize)
648 {
649 TRACE("\n");
650 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
651 ClassGuidListSize, RequiredSize,
652 NULL, NULL);
653 }
654
655 /***********************************************************************
656 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
657 *
658 * Returns a list of setup class GUIDs that identify the classes
659 * that are installed on a local or remote machine.
660 *
661 * PARAMS
662 * Flags [I] control exclusion of classes from the list.
663 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
664 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
665 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
666 * MachineName [I] name of a remote machine.
667 * Reserved [I] must be NULL.
668 *
669 * RETURNS
670 * Success: TRUE.
671 * Failure: FALSE.
672 */
673 BOOL WINAPI SetupDiBuildClassInfoListExA(
674 DWORD Flags,
675 LPGUID ClassGuidList,
676 DWORD ClassGuidListSize,
677 PDWORD RequiredSize,
678 LPCSTR MachineName,
679 PVOID Reserved)
680 {
681 LPWSTR MachineNameW = NULL;
682 BOOL bResult;
683
684 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
685 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
686
687 if (MachineName)
688 {
689 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
690 if (MachineNameW == NULL) return FALSE;
691 }
692
693 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
694 ClassGuidListSize, RequiredSize,
695 MachineNameW, Reserved);
696
697 MyFree(MachineNameW);
698
699 return bResult;
700 }
701
702 /***********************************************************************
703 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
704 *
705 * Returns a list of setup class GUIDs that identify the classes
706 * that are installed on a local or remote machine.
707 *
708 * PARAMS
709 * Flags [I] control exclusion of classes from the list.
710 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
711 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
712 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
713 * MachineName [I] name of a remote machine.
714 * Reserved [I] must be NULL.
715 *
716 * RETURNS
717 * Success: TRUE.
718 * Failure: FALSE.
719 */
720 BOOL WINAPI SetupDiBuildClassInfoListExW(
721 DWORD Flags,
722 LPGUID ClassGuidList,
723 DWORD ClassGuidListSize,
724 PDWORD RequiredSize,
725 LPCWSTR MachineName,
726 PVOID Reserved)
727 {
728 WCHAR szKeyName[40];
729 HKEY hClassesKey = INVALID_HANDLE_VALUE;
730 HKEY hClassKey;
731 DWORD dwLength;
732 DWORD dwIndex;
733 LONG lError;
734 DWORD dwGuidListIndex = 0;
735
736 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
737 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
738
739 if (!RequiredSize)
740 {
741 SetLastError(ERROR_INVALID_PARAMETER);
742 return FALSE;
743 }
744 else if (!ClassGuidList && ClassGuidListSize > 0)
745 {
746 SetLastError(ERROR_INVALID_PARAMETER);
747 return FALSE;
748 }
749
750 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
751 KEY_ENUMERATE_SUB_KEYS,
752 DIOCR_INSTALLER,
753 MachineName,
754 Reserved);
755 if (hClassesKey == INVALID_HANDLE_VALUE)
756 {
757 return FALSE;
758 }
759
760 for (dwIndex = 0; ; dwIndex++)
761 {
762 dwLength = 40;
763 lError = RegEnumKeyExW(hClassesKey,
764 dwIndex,
765 szKeyName,
766 &dwLength,
767 NULL,
768 NULL,
769 NULL,
770 NULL);
771 TRACE("RegEnumKeyExW() returns %d\n", lError);
772 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
773 {
774 TRACE("Key name: %s\n", debugstr_w(szKeyName));
775
776 if (RegOpenKeyExW(hClassesKey,
777 szKeyName,
778 0,
779 KEY_QUERY_VALUE,
780 &hClassKey))
781 {
782 RegCloseKey(hClassesKey);
783 return FALSE;
784 }
785
786 if (!RegQueryValueExW(hClassKey,
787 REGSTR_VAL_NOUSECLASS,
788 NULL,
789 NULL,
790 NULL,
791 NULL))
792 {
793 TRACE("'NoUseClass' value found!\n");
794 RegCloseKey(hClassKey);
795 continue;
796 }
797
798 if ((Flags & DIBCI_NOINSTALLCLASS) &&
799 (!RegQueryValueExW(hClassKey,
800 REGSTR_VAL_NOINSTALLCLASS,
801 NULL,
802 NULL,
803 NULL,
804 NULL)))
805 {
806 TRACE("'NoInstallClass' value found!\n");
807 RegCloseKey(hClassKey);
808 continue;
809 }
810
811 if ((Flags & DIBCI_NODISPLAYCLASS) &&
812 (!RegQueryValueExW(hClassKey,
813 REGSTR_VAL_NODISPLAYCLASS,
814 NULL,
815 NULL,
816 NULL,
817 NULL)))
818 {
819 TRACE("'NoDisplayClass' value found!\n");
820 RegCloseKey(hClassKey);
821 continue;
822 }
823
824 RegCloseKey(hClassKey);
825
826 TRACE("Guid: %s\n", debugstr_w(szKeyName));
827 if (dwGuidListIndex < ClassGuidListSize)
828 {
829 if (szKeyName[0] == '{' && szKeyName[37] == '}')
830 {
831 szKeyName[37] = 0;
832 }
833 TRACE("Guid: %p\n", &szKeyName[1]);
834
835 UuidFromStringW(&szKeyName[1],
836 &ClassGuidList[dwGuidListIndex]);
837 }
838
839 dwGuidListIndex++;
840 }
841
842 if (lError != ERROR_SUCCESS)
843 break;
844 }
845
846 RegCloseKey(hClassesKey);
847
848 if (RequiredSize != NULL)
849 *RequiredSize = dwGuidListIndex;
850
851 if (ClassGuidListSize < dwGuidListIndex)
852 {
853 SetLastError(ERROR_INSUFFICIENT_BUFFER);
854 return FALSE;
855 }
856
857 return TRUE;
858 }
859
860 /***********************************************************************
861 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
862 */
863 BOOL WINAPI SetupDiClassGuidsFromNameA(
864 LPCSTR ClassName,
865 LPGUID ClassGuidList,
866 DWORD ClassGuidListSize,
867 PDWORD RequiredSize)
868 {
869 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
870 ClassGuidListSize, RequiredSize,
871 NULL, NULL);
872 }
873
874 /***********************************************************************
875 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
876 */
877 BOOL WINAPI SetupDiClassGuidsFromNameW(
878 LPCWSTR ClassName,
879 LPGUID ClassGuidList,
880 DWORD ClassGuidListSize,
881 PDWORD RequiredSize)
882 {
883 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
884 ClassGuidListSize, RequiredSize,
885 NULL, NULL);
886 }
887
888 /***********************************************************************
889 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
890 */
891 BOOL WINAPI SetupDiClassGuidsFromNameExA(
892 LPCSTR ClassName,
893 LPGUID ClassGuidList,
894 DWORD ClassGuidListSize,
895 PDWORD RequiredSize,
896 LPCSTR MachineName,
897 PVOID Reserved)
898 {
899 LPWSTR ClassNameW = NULL;
900 LPWSTR MachineNameW = NULL;
901 BOOL bResult;
902
903 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName), ClassGuidList,
904 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
905
906 if (!ClassName)
907 {
908 SetLastError(ERROR_INVALID_PARAMETER);
909 return FALSE;
910 }
911
912 ClassNameW = pSetupMultiByteToUnicode(ClassName, CP_ACP);
913 if (ClassNameW == NULL)
914 return FALSE;
915
916 if (MachineName)
917 {
918 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
919 if (MachineNameW == NULL)
920 {
921 MyFree(ClassNameW);
922 return FALSE;
923 }
924 }
925
926 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
927 ClassGuidListSize, RequiredSize,
928 MachineNameW, Reserved);
929
930 MyFree(MachineNameW);
931 MyFree(ClassNameW);
932
933 return bResult;
934 }
935
936 /***********************************************************************
937 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
938 */
939 BOOL WINAPI SetupDiClassGuidsFromNameExW(
940 LPCWSTR ClassName,
941 LPGUID ClassGuidList,
942 DWORD ClassGuidListSize,
943 PDWORD RequiredSize,
944 LPCWSTR MachineName,
945 PVOID Reserved)
946 {
947 WCHAR szKeyName[40];
948 WCHAR szClassName[MAX_CLASS_NAME_LEN];
949 HKEY hClassesKey;
950 HKEY hClassKey;
951 DWORD dwLength;
952 DWORD dwIndex;
953 LONG lError;
954 DWORD dwGuidListIndex = 0;
955
956 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
957 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
958
959 if (!ClassName || !RequiredSize)
960 {
961 SetLastError(ERROR_INVALID_PARAMETER);
962 return FALSE;
963 }
964 if (!ClassGuidList && ClassGuidListSize > 0)
965 {
966 SetLastError(ERROR_INVALID_PARAMETER);
967 return FALSE;
968 }
969 *RequiredSize = 0;
970
971 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
972 KEY_ENUMERATE_SUB_KEYS,
973 DIOCR_INSTALLER,
974 MachineName,
975 Reserved);
976 if (hClassesKey == INVALID_HANDLE_VALUE)
977 {
978 return FALSE;
979 }
980
981 for (dwIndex = 0; ; dwIndex++)
982 {
983 dwLength = 40;
984 lError = RegEnumKeyExW(hClassesKey,
985 dwIndex,
986 szKeyName,
987 &dwLength,
988 NULL,
989 NULL,
990 NULL,
991 NULL);
992 TRACE("RegEnumKeyExW() returns %d\n", lError);
993 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
994 {
995 TRACE("Key name: %p\n", szKeyName);
996
997 if (RegOpenKeyExW(hClassesKey,
998 szKeyName,
999 0,
1000 KEY_QUERY_VALUE,
1001 &hClassKey))
1002 {
1003 RegCloseKey(hClassesKey);
1004 return FALSE;
1005 }
1006
1007 dwLength = MAX_CLASS_NAME_LEN * sizeof(WCHAR);
1008 if (!RegQueryValueExW(hClassKey,
1009 REGSTR_VAL_CLASS,
1010 NULL,
1011 NULL,
1012 (LPBYTE)szClassName,
1013 &dwLength))
1014 {
1015 TRACE("Class name: %p\n", szClassName);
1016
1017 if (strcmpiW(szClassName, ClassName) == 0)
1018 {
1019 TRACE("Found matching class name\n");
1020
1021 TRACE("Guid: %p\n", szKeyName);
1022 if (dwGuidListIndex < ClassGuidListSize)
1023 {
1024 if (szKeyName[0] == '{' && szKeyName[37] == '}')
1025 {
1026 szKeyName[37] = 0;
1027 }
1028 TRACE("Guid: %p\n", &szKeyName[1]);
1029
1030 UuidFromStringW(&szKeyName[1],
1031 &ClassGuidList[dwGuidListIndex]);
1032 }
1033
1034 dwGuidListIndex++;
1035 }
1036 }
1037
1038 RegCloseKey(hClassKey);
1039 }
1040
1041 if (lError != ERROR_SUCCESS)
1042 break;
1043 }
1044
1045 RegCloseKey(hClassesKey);
1046
1047 if (RequiredSize != NULL)
1048 *RequiredSize = dwGuidListIndex;
1049
1050 if (ClassGuidListSize < dwGuidListIndex)
1051 {
1052 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1053 return FALSE;
1054 }
1055
1056 return TRUE;
1057 }
1058
1059 /***********************************************************************
1060 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1061 */
1062 BOOL WINAPI SetupDiClassNameFromGuidA(
1063 const GUID* ClassGuid,
1064 PSTR ClassName,
1065 DWORD ClassNameSize,
1066 PDWORD RequiredSize)
1067 {
1068 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
1069 ClassNameSize, RequiredSize,
1070 NULL, NULL);
1071 }
1072
1073 /***********************************************************************
1074 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1075 */
1076 BOOL WINAPI SetupDiClassNameFromGuidW(
1077 const GUID* ClassGuid,
1078 PWSTR ClassName,
1079 DWORD ClassNameSize,
1080 PDWORD RequiredSize)
1081 {
1082 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
1083 ClassNameSize, RequiredSize,
1084 NULL, NULL);
1085 }
1086
1087 /***********************************************************************
1088 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1089 */
1090 BOOL WINAPI SetupDiClassNameFromGuidExA(
1091 const GUID* ClassGuid,
1092 PSTR ClassName,
1093 DWORD ClassNameSize,
1094 PDWORD RequiredSize,
1095 PCSTR MachineName,
1096 PVOID Reserved)
1097 {
1098 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
1099 LPWSTR MachineNameW = NULL;
1100 BOOL ret;
1101
1102 if (MachineName)
1103 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
1104 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
1105 RequiredSize, MachineNameW, Reserved);
1106 if (ret)
1107 {
1108 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
1109 ClassNameSize, NULL, NULL);
1110 if (len == 0 || len > ClassNameSize)
1111 {
1112 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1113 ret = FALSE;
1114 }
1115 }
1116 MyFree(MachineNameW);
1117 return ret;
1118 }
1119
1120 /***********************************************************************
1121 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1122 */
1123 BOOL WINAPI SetupDiClassNameFromGuidExW(
1124 const GUID* ClassGuid,
1125 PWSTR ClassName,
1126 DWORD ClassNameSize,
1127 PDWORD RequiredSize,
1128 PCWSTR MachineName,
1129 PVOID Reserved)
1130 {
1131 HKEY hKey;
1132 DWORD dwLength;
1133 DWORD dwRegType;
1134 LONG rc;
1135 PWSTR Buffer;
1136
1137 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
1138 ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
1139
1140 /* Make sure there's a GUID */
1141 if (ClassGuid == NULL)
1142 {
1143 SetLastError(ERROR_INVALID_CLASS); /* On Vista: ERROR_INVALID_USER_BUFFER */
1144 return FALSE;
1145 }
1146
1147 /* Make sure there's a real buffer when there's a size */
1148 if ((ClassNameSize > 0) && (ClassName == NULL))
1149 {
1150 SetLastError(ERROR_INVALID_PARAMETER); /* On Vista: ERROR_INVALID_USER_BUFFER */
1151 return FALSE;
1152 }
1153
1154 /* Open the key for the GUID */
1155 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INSTALLER, MachineName, Reserved);
1156
1157 if (hKey == INVALID_HANDLE_VALUE)
1158 return FALSE;
1159
1160 /* Retrieve the class name data and close the key */
1161 rc = QueryRegistryValue(hKey, REGSTR_VAL_CLASS, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
1162 RegCloseKey(hKey);
1163
1164 /* Make sure we got the data */
1165 if (rc != ERROR_SUCCESS)
1166 {
1167 SetLastError(rc);
1168 return FALSE;
1169 }
1170
1171 /* Make sure the data is a string */
1172 if (dwRegType != REG_SZ)
1173 {
1174 MyFree(Buffer);
1175 SetLastError(ERROR_GEN_FAILURE);
1176 return FALSE;
1177 }
1178
1179 /* Determine the length of the class name */
1180 dwLength /= sizeof(WCHAR);
1181
1182 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
1183 /* Count the null-terminator */
1184 dwLength++;
1185
1186 /* Inform the caller about the class name */
1187 if ((ClassName != NULL) && (dwLength <= ClassNameSize))
1188 {
1189 memcpy(ClassName, Buffer, (dwLength - 1) * sizeof(WCHAR));
1190 ClassName[dwLength - 1] = UNICODE_NULL;
1191 }
1192
1193 /* Inform the caller about the required size */
1194 if (RequiredSize != NULL)
1195 *RequiredSize = dwLength;
1196
1197 /* Clean up the buffer */
1198 MyFree(Buffer);
1199
1200 /* Make sure the buffer was large enough */
1201 if ((ClassName == NULL) || (dwLength > ClassNameSize))
1202 {
1203 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1204 return FALSE;
1205 }
1206
1207 return TRUE;
1208 }
1209
1210 /***********************************************************************
1211 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1212 */
1213 HDEVINFO WINAPI
1214 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1215 HWND hwndParent)
1216 {
1217 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1218 }
1219
1220 /***********************************************************************
1221 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1222 */
1223 HDEVINFO WINAPI
1224 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1225 HWND hwndParent,
1226 PCSTR MachineName,
1227 PVOID Reserved)
1228 {
1229 LPWSTR MachineNameW = NULL;
1230 HDEVINFO hDevInfo;
1231
1232 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1233 debugstr_a(MachineName), Reserved);
1234
1235 if (MachineName)
1236 {
1237 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
1238 if (MachineNameW == NULL)
1239 return INVALID_HANDLE_VALUE;
1240 }
1241
1242 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1243 MachineNameW, Reserved);
1244
1245 MyFree(MachineNameW);
1246
1247 return hDevInfo;
1248 }
1249
1250 /***********************************************************************
1251 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1252 *
1253 * Create an empty DeviceInfoSet list.
1254 *
1255 * PARAMS
1256 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1257 * with this list.
1258 * hwndParent [I] hwnd needed for interface related actions.
1259 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1260 * local registry will be used.
1261 * Reserved [I] must be NULL
1262 *
1263 * RETURNS
1264 * Success: empty list.
1265 * Failure: INVALID_HANDLE_VALUE.
1266 */
1267 HDEVINFO WINAPI
1268 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1269 HWND hwndParent,
1270 PCWSTR MachineName,
1271 PVOID Reserved)
1272 {
1273 struct DeviceInfoSet *list = NULL;
1274 DWORD size = FIELD_OFFSET(struct DeviceInfoSet, szData);
1275 DWORD rc;
1276 CONFIGRET cr;
1277 HDEVINFO ret = INVALID_HANDLE_VALUE;
1278
1279 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1280 debugstr_w(MachineName), Reserved);
1281
1282 if (MachineName != NULL)
1283 {
1284 SIZE_T len = strlenW(MachineName);
1285 if (len >= SP_MAX_MACHINENAME_LENGTH - 4)
1286 {
1287 SetLastError(ERROR_INVALID_MACHINENAME);
1288 goto cleanup;
1289 }
1290 if(len > 0)
1291 size += (len + 3) * sizeof(WCHAR);
1292 else
1293 MachineName = NULL;
1294 }
1295
1296 if (Reserved != NULL)
1297 {
1298 SetLastError(ERROR_INVALID_PARAMETER);
1299 return INVALID_HANDLE_VALUE;
1300 }
1301
1302 list = MyMalloc(size);
1303 if (!list)
1304 {
1305 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1306 return INVALID_HANDLE_VALUE;
1307 }
1308 ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData));
1309
1310 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1311 memcpy(&list->ClassGuid,
1312 ClassGuid ? ClassGuid : &GUID_NULL,
1313 sizeof(list->ClassGuid));
1314 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1315 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
1316 list->InstallParams.hwndParent = hwndParent;
1317 if (MachineName)
1318 {
1319 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
1320 if (rc != ERROR_SUCCESS)
1321 {
1322 SetLastError(ERROR_INVALID_MACHINENAME);
1323 goto cleanup;
1324 }
1325
1326 list->szData[0] = list->szData[1] = '\\';
1327 strcpyW(list->szData + 2, MachineName);
1328 list->MachineName = list->szData;
1329 }
1330 else
1331 {
1332 list->HKLM = HKEY_LOCAL_MACHINE;
1333 list->MachineName = NULL;
1334 }
1335 cr = CM_Connect_MachineW(list->MachineName, &list->hMachine);
1336 if (cr != CR_SUCCESS)
1337 {
1338 SetLastError(GetErrorCodeFromCrCode(cr));
1339 goto cleanup;
1340 }
1341 InitializeListHead(&list->DriverListHead);
1342 InitializeListHead(&list->ListHead);
1343
1344 return (HDEVINFO)list;
1345
1346 cleanup:
1347 if (ret == INVALID_HANDLE_VALUE)
1348 {
1349 if (list)
1350 {
1351 if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
1352 RegCloseKey(list->HKLM);
1353 MyFree(list);
1354 }
1355 }
1356 return ret;
1357 }
1358
1359 /***********************************************************************
1360 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1361 */
1362 HKEY WINAPI SetupDiCreateDevRegKeyA(
1363 HDEVINFO DeviceInfoSet,
1364 PSP_DEVINFO_DATA DeviceInfoData,
1365 DWORD Scope,
1366 DWORD HwProfile,
1367 DWORD KeyType,
1368 HINF InfHandle,
1369 PCSTR InfSectionName)
1370 {
1371 PWSTR InfSectionNameW = NULL;
1372 HKEY key;
1373
1374 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1375 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1376
1377 if (InfHandle)
1378 {
1379 if (!InfSectionName)
1380 {
1381 SetLastError(ERROR_INVALID_PARAMETER);
1382 return INVALID_HANDLE_VALUE;
1383 }
1384 else
1385 {
1386 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
1387 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1388 }
1389 }
1390 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
1391 HwProfile, KeyType, InfHandle, InfSectionNameW);
1392 MyFree(InfSectionNameW);
1393 return key;
1394 }
1395
1396 static HKEY
1397 OpenHardwareProfileKey(
1398 IN HKEY HKLM,
1399 IN DWORD HwProfile,
1400 IN DWORD samDesired);
1401
1402 /***********************************************************************
1403 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1404 */
1405 HKEY WINAPI SetupDiCreateDevRegKeyW(
1406 HDEVINFO DeviceInfoSet,
1407 PSP_DEVINFO_DATA DeviceInfoData,
1408 DWORD Scope,
1409 DWORD HwProfile,
1410 DWORD KeyType,
1411 HINF InfHandle,
1412 PCWSTR InfSectionName)
1413 {
1414 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1415 struct DeviceInfo *deviceInfo;
1416 HKEY key = INVALID_HANDLE_VALUE;
1417 DWORD rc;
1418 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
1419 HKEY hKey = NULL;
1420 HKEY RootKey;
1421
1422 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1423 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1424
1425 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1426 {
1427 SetLastError(ERROR_INVALID_HANDLE);
1428 return INVALID_HANDLE_VALUE;
1429 }
1430 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1431 {
1432 SetLastError(ERROR_INVALID_HANDLE);
1433 return INVALID_HANDLE_VALUE;
1434 }
1435 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1436 || !DeviceInfoData->Reserved)
1437 {
1438 SetLastError(ERROR_INVALID_PARAMETER);
1439 return INVALID_HANDLE_VALUE;
1440 }
1441 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1442 {
1443 SetLastError(ERROR_INVALID_FLAGS);
1444 return INVALID_HANDLE_VALUE;
1445 }
1446 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1447 {
1448 SetLastError(ERROR_INVALID_FLAGS);
1449 return INVALID_HANDLE_VALUE;
1450 }
1451 if (InfHandle && !InfSectionName)
1452 {
1453 SetLastError(ERROR_INVALID_PARAMETER);
1454 return INVALID_HANDLE_VALUE;
1455 }
1456 if (!InfHandle && InfSectionName)
1457 {
1458 SetLastError(ERROR_INVALID_PARAMETER);
1459 return INVALID_HANDLE_VALUE;
1460 }
1461
1462 deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1463
1464 if (Scope == DICS_FLAG_GLOBAL)
1465 RootKey = set->HKLM;
1466 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1467 {
1468 hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
1469 if (hHWProfileKey == INVALID_HANDLE_VALUE)
1470 goto cleanup;
1471 RootKey = hHWProfileKey;
1472 }
1473
1474 if (KeyType == DIREG_DEV)
1475 {
1476 #if _WIN32_WINNT >= 0x502
1477 hKey = SETUPDI_CreateDevKey(RootKey, deviceInfo, KEY_READ | KEY_WRITE);
1478 #else
1479 hKey = SETUPDI_CreateDevKey(RootKey, deviceInfo, KEY_ALL_ACCESS);
1480 #endif
1481 if (hKey == INVALID_HANDLE_VALUE)
1482 goto cleanup;
1483
1484 if (Scope == DICS_FLAG_GLOBAL)
1485 {
1486 HKEY hTempKey = hKey;
1487
1488 rc = RegCreateKeyExW(hTempKey,
1489 L"Device Parameters",
1490 0,
1491 NULL,
1492 REG_OPTION_NON_VOLATILE,
1493 #if _WIN32_WINNT >= 0x502
1494 KEY_READ | KEY_WRITE,
1495 #else
1496 KEY_ALL_ACCESS,
1497 #endif
1498 NULL,
1499 &hKey,
1500 NULL);
1501 if (rc == ERROR_SUCCESS)
1502 RegCloseKey(hTempKey);
1503 }
1504 }
1505 else /* KeyType == DIREG_DRV */
1506 {
1507 #if _WIN32_WINNT >= 0x502
1508 hKey = SETUPDI_CreateDrvKey(RootKey, deviceInfo, (UUID*)&DeviceInfoData->ClassGuid, KEY_READ | KEY_WRITE);
1509 #else
1510 hKey = SETUPDI_CreateDrvKey(RootKey, deviceInfo, (UUID*)&DeviceInfoData->ClassGuid, KEY_ALL_ACCESS);
1511 #endif
1512 if (hKey == INVALID_HANDLE_VALUE)
1513 goto cleanup;
1514 }
1515
1516 /* Do installation of the specified section */
1517 if (InfHandle)
1518 {
1519 FIXME("Need to install section %s in file %p\n",
1520 debugstr_w(InfSectionName), InfHandle);
1521 }
1522 key = hKey;
1523
1524 cleanup:
1525 if (hHWProfileKey != INVALID_HANDLE_VALUE)
1526 RegCloseKey(hHWProfileKey);
1527 if (hKey != NULL && hKey != key)
1528 RegCloseKey(hKey);
1529
1530 TRACE("Returning 0x%p\n", key);
1531 return key;
1532 }
1533
1534 /***********************************************************************
1535 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1536 */
1537 BOOL WINAPI SetupDiCreateDeviceInfoA(
1538 HDEVINFO DeviceInfoSet,
1539 PCSTR DeviceName,
1540 CONST GUID *ClassGuid,
1541 PCSTR DeviceDescription,
1542 HWND hwndParent,
1543 DWORD CreationFlags,
1544 PSP_DEVINFO_DATA DeviceInfoData)
1545 {
1546 BOOL ret;
1547 LPWSTR DeviceNameW = NULL;
1548 LPWSTR DeviceDescriptionW = NULL;
1549
1550 TRACE("\n");
1551
1552 if (DeviceName)
1553 {
1554 DeviceNameW = pSetupMultiByteToUnicode(DeviceName, CP_ACP);
1555 if (DeviceNameW == NULL) return FALSE;
1556 }
1557 if (DeviceDescription)
1558 {
1559 DeviceDescriptionW = pSetupMultiByteToUnicode(DeviceDescription, CP_ACP);
1560 if (DeviceDescriptionW == NULL)
1561 {
1562 MyFree(DeviceNameW);
1563 return FALSE;
1564 }
1565 }
1566
1567 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1568 hwndParent, CreationFlags, DeviceInfoData);
1569
1570 MyFree(DeviceNameW);
1571 MyFree(DeviceDescriptionW);
1572
1573 return ret;
1574 }
1575
1576 /***********************************************************************
1577 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1578 */
1579 BOOL WINAPI SetupDiCreateDeviceInfoW(
1580 HDEVINFO DeviceInfoSet,
1581 PCWSTR DeviceName,
1582 CONST GUID *ClassGuid,
1583 PCWSTR DeviceDescription,
1584 HWND hwndParent,
1585 DWORD CreationFlags,
1586 PSP_DEVINFO_DATA DeviceInfoData)
1587 {
1588 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1589 struct DeviceInfo *deviceInfo = NULL;
1590 BOOL ret = FALSE;
1591 CONFIGRET cr;
1592 DEVINST RootDevInst;
1593 DEVINST DevInst;
1594 WCHAR GenInstanceId[MAX_DEVICE_ID_LEN];
1595
1596 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1597 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1598 hwndParent, CreationFlags, DeviceInfoData);
1599
1600 if (!DeviceName)
1601 {
1602 SetLastError(ERROR_INVALID_DEVINST_NAME);
1603 return FALSE;
1604 }
1605 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1606 {
1607 SetLastError(ERROR_INVALID_HANDLE);
1608 return FALSE;
1609 }
1610 if (!ClassGuid)
1611 {
1612 SetLastError(ERROR_INVALID_PARAMETER);
1613 return FALSE;
1614 }
1615 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1616 {
1617 SetLastError(ERROR_INVALID_HANDLE);
1618 return FALSE;
1619 }
1620 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1621 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1622 {
1623 SetLastError(ERROR_CLASS_MISMATCH);
1624 return FALSE;
1625 }
1626 if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
1627 {
1628 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
1629 SetLastError(ERROR_INVALID_FLAGS);
1630 return FALSE;
1631 }
1632
1633 /* Get the root device instance */
1634 cr = CM_Locate_DevInst_ExW(&RootDevInst,
1635 NULL,
1636 CM_LOCATE_DEVINST_NORMAL,
1637 set->hMachine);
1638 if (cr != CR_SUCCESS)
1639 {
1640 SetLastError(ERROR_INVALID_DATA);
1641 return FALSE;
1642 }
1643
1644 /* Create the new device instance */
1645 cr = CM_Create_DevInst_ExW(&DevInst,
1646 (DEVINSTID)DeviceName,
1647 RootDevInst,
1648 (CreationFlags & DICD_GENERATE_ID) ?
1649 CM_CREATE_DEVINST_GENERATE_ID : 0,
1650 set->hMachine);
1651 if (cr != CR_SUCCESS)
1652 {
1653 SetLastError(GetErrorCodeFromCrCode(cr));
1654 return FALSE;
1655 }
1656
1657 if (CreationFlags & DICD_GENERATE_ID)
1658 {
1659 /* Grab the actual instance ID that was created */
1660 cr = CM_Get_Device_ID_Ex(DevInst,
1661 GenInstanceId,
1662 MAX_DEVICE_ID_LEN,
1663 0,
1664 set->hMachine);
1665 if (cr != CR_SUCCESS)
1666 {
1667 SetLastError(GetErrorCodeFromCrCode(cr));
1668 return FALSE;
1669 }
1670
1671 DeviceName = GenInstanceId;
1672 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName));
1673 }
1674
1675 if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo))
1676 {
1677 InsertTailList(&set->ListHead, &deviceInfo->ListEntry);
1678
1679 if (!DeviceInfoData)
1680 ret = TRUE;
1681 else
1682 {
1683 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1684 {
1685 SetLastError(ERROR_INVALID_USER_BUFFER);
1686 }
1687 else
1688 {
1689 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
1690 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
1691 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
1692 ret = TRUE;
1693 }
1694 }
1695 }
1696
1697 if (ret == FALSE)
1698 {
1699 if (deviceInfo != NULL)
1700 {
1701 /* Remove deviceInfo from List */
1702 RemoveEntryList(&deviceInfo->ListEntry);
1703
1704 /* Destroy deviceInfo */
1705 DestroyDeviceInfo(deviceInfo);
1706 }
1707 }
1708
1709 TRACE("Returning %d\n", ret);
1710 return ret;
1711 }
1712
1713 /***********************************************************************
1714 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1715 */
1716 BOOL WINAPI SetupDiRegisterDeviceInfo(
1717 HDEVINFO DeviceInfoSet,
1718 PSP_DEVINFO_DATA DeviceInfoData,
1719 DWORD Flags,
1720 PSP_DETSIG_CMPPROC CompareProc,
1721 PVOID CompareContext,
1722 PSP_DEVINFO_DATA DupDeviceInfoData)
1723 {
1724 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1725 WCHAR DevInstId[MAX_DEVICE_ID_LEN];
1726 DEVINST ParentDevInst;
1727 CONFIGRET cr;
1728 DWORD dwError = ERROR_SUCCESS;
1729
1730 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1731 CompareProc, CompareContext, DupDeviceInfoData);
1732
1733 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1734 {
1735 SetLastError(ERROR_INVALID_HANDLE);
1736 return FALSE;
1737 }
1738 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1739 {
1740 SetLastError(ERROR_INVALID_HANDLE);
1741 return FALSE;
1742 }
1743 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1744 || !DeviceInfoData->Reserved)
1745 {
1746 SetLastError(ERROR_INVALID_PARAMETER);
1747 return FALSE;
1748 }
1749
1750 if (Flags & ~SPRDI_FIND_DUPS)
1751 {
1752 TRACE("Unknown flags: 0x%08lx\n", Flags & ~SPRDI_FIND_DUPS);
1753 SetLastError(ERROR_INVALID_FLAGS);
1754 return FALSE;
1755 }
1756
1757 if (Flags & SPRDI_FIND_DUPS)
1758 {
1759 FIXME("Unimplemented codepath!\n");
1760 }
1761
1762 CM_Get_Device_ID_Ex(DeviceInfoData->DevInst,
1763 DevInstId,
1764 MAX_DEVICE_ID_LEN,
1765 0,
1766 set->hMachine);
1767
1768 CM_Get_Parent_Ex(&ParentDevInst,
1769 DeviceInfoData->DevInst,
1770 0,
1771 set->hMachine);
1772
1773 cr = CM_Create_DevInst_Ex(&DeviceInfoData->DevInst,
1774 DevInstId,
1775 ParentDevInst,
1776 CM_CREATE_DEVINST_NORMAL | CM_CREATE_DEVINST_DO_NOT_INSTALL,
1777 set->hMachine);
1778 if (cr != CR_SUCCESS &&
1779 cr != CR_ALREADY_SUCH_DEVINST)
1780 {
1781 dwError = ERROR_NO_SUCH_DEVINST;
1782 }
1783
1784 SetLastError(dwError);
1785
1786 return (dwError == ERROR_SUCCESS);
1787 }
1788
1789 /***********************************************************************
1790 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1791 */
1792 BOOL WINAPI SetupDiEnumDeviceInfo(
1793 HDEVINFO devinfo,
1794 DWORD index,
1795 PSP_DEVINFO_DATA info)
1796 {
1797 BOOL ret = FALSE;
1798
1799 TRACE("%p %d %p\n", devinfo, index, info);
1800
1801 if(info==NULL)
1802 {
1803 SetLastError(ERROR_INVALID_PARAMETER);
1804 return FALSE;
1805 }
1806 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1807 {
1808 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1809 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1810 {
1811 if (info->cbSize != sizeof(SP_DEVINFO_DATA))
1812 SetLastError(ERROR_INVALID_USER_BUFFER);
1813 else
1814 {
1815 PLIST_ENTRY ItemList = list->ListHead.Flink;
1816 while (ItemList != &list->ListHead && index-- > 0)
1817 ItemList = ItemList->Flink;
1818 if (ItemList == &list->ListHead)
1819 SetLastError(ERROR_NO_MORE_ITEMS);
1820 else
1821 {
1822 struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
1823 memcpy(&info->ClassGuid,
1824 &DevInfo->ClassGuid,
1825 sizeof(GUID));
1826 info->DevInst = DevInfo->dnDevInst;
1827 info->Reserved = (ULONG_PTR)DevInfo;
1828 ret = TRUE;
1829 }
1830 }
1831 }
1832 else
1833 SetLastError(ERROR_INVALID_HANDLE);
1834 }
1835 else
1836 SetLastError(ERROR_INVALID_HANDLE);
1837 return ret;
1838 }
1839
1840 /***********************************************************************
1841 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1842 */
1843 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1844 HDEVINFO DeviceInfoSet,
1845 PSP_DEVINFO_DATA DeviceInfoData,
1846 PSTR DeviceInstanceId,
1847 DWORD DeviceInstanceIdSize,
1848 PDWORD RequiredSize)
1849 {
1850 BOOL ret = FALSE;
1851 DWORD size;
1852 PWSTR instanceId;
1853
1854 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1855 DeviceInstanceIdSize, RequiredSize);
1856
1857 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1858 {
1859 SetLastError(ERROR_INVALID_PARAMETER);
1860 return FALSE;
1861 }
1862
1863 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1864 DeviceInfoData,
1865 NULL,
1866 0,
1867 &size);
1868 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1869 return FALSE;
1870 instanceId = MyMalloc(size * sizeof(WCHAR));
1871 if (instanceId)
1872 {
1873 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1874 DeviceInfoData,
1875 instanceId,
1876 size,
1877 &size);
1878 if (ret)
1879 {
1880 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1881 DeviceInstanceId,
1882 DeviceInstanceIdSize, NULL, NULL);
1883
1884 if (!len)
1885 ret = FALSE;
1886 else
1887 {
1888 if (len > DeviceInstanceIdSize)
1889 {
1890 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1891 ret = FALSE;
1892 }
1893 if (RequiredSize)
1894 *RequiredSize = len;
1895 }
1896 }
1897 MyFree(instanceId);
1898 }
1899 else
1900 {
1901 if (RequiredSize)
1902 *RequiredSize = size;
1903 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1904 ret = FALSE;
1905 }
1906 return ret;
1907 }
1908
1909 /***********************************************************************
1910 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1911 */
1912 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1913 HDEVINFO DeviceInfoSet,
1914 PSP_DEVINFO_DATA DeviceInfoData,
1915 PWSTR DeviceInstanceId,
1916 DWORD DeviceInstanceIdSize,
1917 PDWORD RequiredSize)
1918 {
1919 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1920 struct DeviceInfo *devInfo;
1921
1922 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1923 DeviceInstanceIdSize, RequiredSize);
1924
1925 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1926 {
1927 SetLastError(ERROR_INVALID_HANDLE);
1928 return FALSE;
1929 }
1930 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1931 {
1932 SetLastError(ERROR_INVALID_HANDLE);
1933 return FALSE;
1934 }
1935 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1936 || !DeviceInfoData->Reserved)
1937 {
1938 SetLastError(ERROR_INVALID_PARAMETER);
1939 return FALSE;
1940 }
1941 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1942 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1943 {
1944 SetLastError(ERROR_INVALID_PARAMETER);
1945 return FALSE;
1946 }
1947 if (DeviceInstanceId && DeviceInstanceIdSize == 0)
1948 {
1949 SetLastError(ERROR_INVALID_PARAMETER);
1950 return FALSE;
1951 }
1952 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1953 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1954 {
1955 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1956 if (RequiredSize)
1957 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1958 return FALSE;
1959 }
1960 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1961 if (RequiredSize)
1962 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1963 return TRUE;
1964 }
1965
1966 /***********************************************************************
1967 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1968 */
1969 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1970 HINF InfHandle,
1971 PCSTR InfSectionName,
1972 PSTR InfSectionWithExt,
1973 DWORD InfSectionWithExtSize,
1974 PDWORD RequiredSize,
1975 PSTR *Extension)
1976 {
1977 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
1978 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
1979 Extension, NULL);
1980 }
1981
1982 /***********************************************************************
1983 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1984 */
1985 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1986 HINF InfHandle,
1987 PCWSTR InfSectionName,
1988 PWSTR InfSectionWithExt,
1989 DWORD InfSectionWithExtSize,
1990 PDWORD RequiredSize,
1991 PWSTR *Extension)
1992 {
1993 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
1994 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
1995 Extension, NULL);
1996 }
1997
1998 /***********************************************************************
1999 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2000 */
2001 BOOL WINAPI
2002 SetupDiGetActualSectionToInstallExA(
2003 IN HINF InfHandle,
2004 IN PCSTR InfSectionName,
2005 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
2006 OUT PSTR InfSectionWithExt OPTIONAL,
2007 IN DWORD InfSectionWithExtSize,
2008 OUT PDWORD RequiredSize OPTIONAL,
2009 OUT PSTR* Extension OPTIONAL,
2010 IN PVOID Reserved)
2011 {
2012 LPWSTR InfSectionNameW = NULL;
2013 LPWSTR InfSectionWithExtW = NULL;
2014 PWSTR ExtensionW;
2015 BOOL bResult = FALSE;
2016
2017 TRACE("\n");
2018
2019 if (InfSectionName)
2020 {
2021 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
2022 if (InfSectionNameW == NULL)
2023 goto cleanup;
2024 }
2025 if (InfSectionWithExt)
2026 {
2027 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
2028 if (InfSectionWithExtW == NULL)
2029 goto cleanup;
2030 }
2031
2032 bResult = SetupDiGetActualSectionToInstallExW(
2033 InfHandle, InfSectionNameW, AlternatePlatformInfo,
2034 InfSectionWithExt ? InfSectionWithExtW : NULL,
2035 InfSectionWithExtSize,
2036 RequiredSize,
2037 Extension ? &ExtensionW : NULL,
2038 Reserved);
2039
2040 if (bResult && InfSectionWithExt)
2041 {
2042 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
2043 InfSectionWithExtSize, NULL, NULL) != 0;
2044 }
2045 if (bResult && Extension)
2046 {
2047 if (ExtensionW == NULL)
2048 *Extension = NULL;
2049 else
2050 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
2051 }
2052
2053 cleanup:
2054 MyFree(InfSectionNameW);
2055 MyFree(InfSectionWithExtW);
2056
2057 return bResult;
2058 }
2059
2060 /***********************************************************************
2061 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2062 */
2063 BOOL WINAPI SetupDiGetClassDescriptionA(
2064 const GUID* ClassGuid,
2065 PSTR ClassDescription,
2066 DWORD ClassDescriptionSize,
2067 PDWORD RequiredSize)
2068 {
2069 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
2070 ClassDescriptionSize,
2071 RequiredSize, NULL, NULL);
2072 }
2073
2074 /***********************************************************************
2075 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2076 */
2077 BOOL WINAPI SetupDiGetClassDescriptionW(
2078 const GUID* ClassGuid,
2079 PWSTR ClassDescription,
2080 DWORD ClassDescriptionSize,
2081 PDWORD RequiredSize)
2082 {
2083 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
2084 ClassDescriptionSize,
2085 RequiredSize, NULL, NULL);
2086 }
2087
2088 /***********************************************************************
2089 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2090 */
2091 BOOL WINAPI SetupDiGetClassDescriptionExA(
2092 const GUID* ClassGuid,
2093 PSTR ClassDescription,
2094 DWORD ClassDescriptionSize,
2095 PDWORD RequiredSize,
2096 PCSTR MachineName,
2097 PVOID Reserved)
2098 {
2099 PWCHAR ClassDescriptionW = NULL;
2100 LPWSTR MachineNameW = NULL;
2101 BOOL ret = FALSE;
2102
2103 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2104 ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved);
2105
2106 if (ClassDescriptionSize > 0)
2107 {
2108 ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR));
2109 if (!ClassDescriptionW)
2110 {
2111 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2112 goto cleanup;
2113 }
2114 }
2115
2116 if (MachineName)
2117 {
2118 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
2119 if (!MachineNameW)
2120 {
2121 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2122 goto cleanup;
2123 }
2124 }
2125
2126 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW,
2127 ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved);
2128 if (ret)
2129 {
2130 DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
2131 ClassDescriptionSize, NULL, NULL);
2132 if (len == 0 || len > ClassDescriptionSize)
2133 {
2134 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2135 ret = FALSE;
2136 }
2137 }
2138
2139 cleanup:
2140 MyFree(ClassDescriptionW);
2141 MyFree(MachineNameW);
2142 return ret;
2143 }
2144
2145 /***********************************************************************
2146 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2147 */
2148 BOOL WINAPI SetupDiGetClassDescriptionExW(
2149 const GUID* ClassGuid,
2150 PWSTR ClassDescription,
2151 DWORD ClassDescriptionSize,
2152 PDWORD RequiredSize,
2153 PCWSTR MachineName,
2154 PVOID Reserved)
2155 {
2156 HKEY hKey;
2157 DWORD dwLength;
2158 DWORD dwRegType;
2159 LONG rc;
2160 PWSTR Buffer;
2161
2162 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2163 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
2164
2165 /* Make sure there's a GUID */
2166 if (!ClassGuid)
2167 {
2168 SetLastError(ERROR_INVALID_PARAMETER);
2169 return FALSE;
2170 }
2171
2172 /* Make sure there's a real buffer when there's a size */
2173 if (!ClassDescription && ClassDescriptionSize > 0)
2174 {
2175 SetLastError(ERROR_INVALID_PARAMETER);
2176 return FALSE;
2177 }
2178
2179 /* Open the key for the GUID */
2180 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
2181 KEY_QUERY_VALUE,
2182 DIOCR_INSTALLER,
2183 MachineName,
2184 Reserved);
2185 if (hKey == INVALID_HANDLE_VALUE)
2186 return FALSE;
2187
2188 /* Retrieve the class description data and close the key */
2189 rc = QueryRegistryValue(hKey, NULL, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
2190 RegCloseKey(hKey);
2191
2192 /* Make sure we got the data */
2193 if (rc != ERROR_SUCCESS)
2194 {
2195 SetLastError(rc);
2196 return FALSE;
2197 }
2198
2199 /* Make sure the data is a string */
2200 if (dwRegType != REG_SZ)
2201 {
2202 MyFree(Buffer);
2203 SetLastError(ERROR_GEN_FAILURE);
2204 return FALSE;
2205 }
2206
2207 /* Determine the length of the class description */
2208 dwLength /= sizeof(WCHAR);
2209
2210 /* Count the null-terminator if none is present */
2211 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
2212 dwLength++;
2213
2214 /* Inform the caller about the class description */
2215 if ((ClassDescription != NULL) && (dwLength <= ClassDescriptionSize))
2216 {
2217 memcpy(ClassDescription, Buffer, (dwLength - 1) * sizeof(WCHAR));
2218 ClassDescription[dwLength - 1] = UNICODE_NULL;
2219 }
2220
2221 /* Inform the caller about the required size */
2222 if (RequiredSize != NULL)
2223 *RequiredSize = dwLength;
2224
2225 /* Clean up the buffer */
2226 MyFree(Buffer);
2227
2228 /* Make sure the buffer was large enough */
2229 if ((ClassDescription == NULL) || (dwLength > ClassDescriptionSize))
2230 {
2231 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2232 return FALSE;
2233 }
2234
2235 return TRUE;
2236 }
2237
2238 /***********************************************************************
2239 * SetupDiGetClassDevsA (SETUPAPI.@)
2240 */
2241 HDEVINFO WINAPI SetupDiGetClassDevsA(
2242 CONST GUID *class,
2243 LPCSTR enumstr,
2244 HWND parent,
2245 DWORD flags)
2246 {
2247 return SetupDiGetClassDevsExA(class, enumstr, parent,
2248 flags, NULL, NULL, NULL);
2249 }
2250
2251 /***********************************************************************
2252 * SetupDiGetClassDevsExA (SETUPAPI.@)
2253 */
2254 HDEVINFO WINAPI SetupDiGetClassDevsExA(
2255 const GUID *class,
2256 PCSTR enumstr,
2257 HWND parent,
2258 DWORD flags,
2259 HDEVINFO deviceset,
2260 PCSTR machine,
2261 PVOID reserved)
2262 {
2263 HDEVINFO ret;
2264 LPWSTR enumstrW = NULL, machineW = NULL;
2265
2266 if (enumstr)
2267 {
2268 enumstrW = pSetupMultiByteToUnicode(enumstr, CP_ACP);
2269 if (!enumstrW)
2270 {
2271 ret = INVALID_HANDLE_VALUE;
2272 goto end;
2273 }
2274 }
2275 if (machine)
2276 {
2277 machineW = pSetupMultiByteToUnicode(machine, CP_ACP);
2278 if (!machineW)
2279 {
2280 MyFree(enumstrW);
2281 ret = INVALID_HANDLE_VALUE;
2282 goto end;
2283 }
2284 }
2285 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
2286 machineW, reserved);
2287 MyFree(enumstrW);
2288 MyFree(machineW);
2289
2290 end:
2291 return ret;
2292 }
2293
2294 /***********************************************************************
2295 * SetupDiGetClassDevsW (SETUPAPI.@)
2296 */
2297 HDEVINFO WINAPI SetupDiGetClassDevsW(
2298 CONST GUID *class,
2299 LPCWSTR enumstr,
2300 HWND parent,
2301 DWORD flags)
2302 {
2303 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2304 NULL);
2305 }
2306
2307 /***********************************************************************
2308 * SetupDiGetClassDevsExW (SETUPAPI.@)
2309 */
2310 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2311 CONST GUID *class,
2312 PCWSTR enumstr,
2313 HWND parent,
2314 DWORD flags,
2315 HDEVINFO deviceset,
2316 PCWSTR machine,
2317 PVOID reserved)
2318 {
2319 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2320 struct DeviceInfoSet *list;
2321 CONST GUID *pClassGuid;
2322 LONG rc;
2323 HDEVINFO set = INVALID_HANDLE_VALUE;
2324
2325 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2326 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2327 reserved);
2328
2329 if (!(flags & DIGCF_ALLCLASSES) && !class)
2330 {
2331 SetLastError(ERROR_INVALID_PARAMETER);
2332 return INVALID_HANDLE_VALUE;
2333 }
2334
2335 /* Create the deviceset if not set */
2336 if (deviceset)
2337 {
2338 list = (struct DeviceInfoSet *)deviceset;
2339 if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2340 {
2341 SetLastError(ERROR_INVALID_HANDLE);
2342 goto cleanup;
2343 }
2344 hDeviceInfo = deviceset;
2345 }
2346 else
2347 {
2348 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
2349 flags & (DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES) ? NULL : class,
2350 NULL, machine, NULL);
2351 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2352 goto cleanup;
2353 list = (struct DeviceInfoSet *)hDeviceInfo;
2354 }
2355
2356 if (flags & DIGCF_PROFILE)
2357 FIXME(": flag DIGCF_PROFILE ignored\n");
2358
2359 if (flags & DIGCF_DEVICEINTERFACE)
2360 {
2361 if (!class)
2362 {
2363 SetLastError(ERROR_INVALID_PARAMETER);
2364 goto cleanup;
2365 }
2366 rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT);
2367 }
2368 else
2369 {
2370 /* Determine which class(es) should be included in the deviceset */
2371 if (flags & DIGCF_ALLCLASSES)
2372 {
2373 /* The caller wants all classes. Check if
2374 * the deviceset limits us to one class */
2375 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2376 pClassGuid = NULL;
2377 else
2378 pClassGuid = &list->ClassGuid;
2379 }
2380 else if (class)
2381 {
2382 /* The caller wants one class. Check if it matches deviceset class */
2383 if (IsEqualIID(&list->ClassGuid, class)
2384 || IsEqualIID(&list->ClassGuid, &GUID_NULL))
2385 {
2386 pClassGuid = class;
2387 }
2388 else
2389 {
2390 SetLastError(ERROR_INVALID_PARAMETER);
2391 goto cleanup;
2392 }
2393 }
2394 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL))
2395 {
2396 /* No class specified. Try to use the one of the deviceset */
2397 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2398 pClassGuid = &list->ClassGuid;
2399 else
2400 {
2401 SetLastError(ERROR_INVALID_PARAMETER);
2402 goto cleanup;
2403 }
2404 }
2405 else
2406 {
2407 SetLastError(ERROR_INVALID_PARAMETER);
2408 goto cleanup;
2409 }
2410 rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr);
2411 }
2412 if (rc != ERROR_SUCCESS)
2413 {
2414 SetLastError(rc);
2415 goto cleanup;
2416 }
2417 set = hDeviceInfo;
2418
2419 cleanup:
2420 if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set)
2421 SetupDiDestroyDeviceInfoList(hDeviceInfo);
2422 return set;
2423 }
2424
2425 /***********************************************************************
2426 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2427 */
2428 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2429 HDEVINFO DeviceInfoSet,
2430 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2431 {
2432 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2433
2434 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2435
2436 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2437 {
2438 SetLastError(ERROR_INVALID_HANDLE);
2439 return FALSE;
2440 }
2441 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2442 {
2443 SetLastError(ERROR_INVALID_HANDLE);
2444 return FALSE;
2445 }
2446 if (!DevInfoData ||
2447 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2448 {
2449 SetLastError(ERROR_INVALID_PARAMETER);
2450 return FALSE;
2451 }
2452 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2453 DevInfoData->RemoteMachineHandle = set->hMachine;
2454 if (set->MachineName)
2455 {
2456 FIXME("Stub\n");
2457 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2458 return FALSE;
2459 }
2460 else
2461 DevInfoData->RemoteMachineName[0] = 0;
2462
2463 return TRUE;
2464 }
2465
2466 /***********************************************************************
2467 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2468 */
2469 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2470 HDEVINFO DeviceInfoSet,
2471 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2472 {
2473 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2474
2475 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2476
2477 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2478 {
2479 SetLastError(ERROR_INVALID_HANDLE);
2480 return FALSE;
2481 }
2482 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2483 {
2484 SetLastError(ERROR_INVALID_HANDLE);
2485 return FALSE;
2486 }
2487 if (!DevInfoData ||
2488 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2489 {
2490 SetLastError(ERROR_INVALID_PARAMETER);
2491 return FALSE;
2492 }
2493 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2494 DevInfoData->RemoteMachineHandle = set->hMachine;
2495 if (set->MachineName)
2496 strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2);
2497 else
2498 DevInfoData->RemoteMachineName[0] = 0;
2499
2500 return TRUE;
2501 }
2502
2503 /***********************************************************************
2504 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2505 */
2506 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2507 HDEVINFO DeviceInfoSet,
2508 PSP_DEVINFO_DATA DeviceInfoData,
2509 const GUID *InterfaceClassGuid,
2510 PCSTR ReferenceString,
2511 DWORD CreationFlags,
2512 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2513 {
2514 BOOL ret;
2515 LPWSTR ReferenceStringW = NULL;
2516
2517 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2518 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2519 CreationFlags, DeviceInterfaceData);
2520
2521 if (ReferenceString)
2522 {
2523 ReferenceStringW = pSetupMultiByteToUnicode(ReferenceString, CP_ACP);
2524 if (ReferenceStringW == NULL) return FALSE;
2525 }
2526
2527 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2528 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2529 DeviceInterfaceData);
2530
2531 MyFree(ReferenceStringW);
2532
2533 return ret;
2534 }
2535
2536 /***********************************************************************
2537 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2538 */
2539 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2540 HDEVINFO DeviceInfoSet,
2541 PSP_DEVINFO_DATA DeviceInfoData,
2542 const GUID *InterfaceClassGuid,
2543 PCWSTR ReferenceString,
2544 DWORD CreationFlags,
2545 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2546 {
2547 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2548 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2549 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2550 CreationFlags, DeviceInterfaceData);
2551
2552 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2553 {
2554 SetLastError(ERROR_INVALID_HANDLE);
2555 return FALSE;
2556 }
2557 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2558 {
2559 SetLastError(ERROR_INVALID_HANDLE);
2560 return FALSE;
2561 }
2562 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2563 || !DeviceInfoData->Reserved)
2564 {
2565 SetLastError(ERROR_INVALID_PARAMETER);
2566 return FALSE;
2567 }
2568 if (!InterfaceClassGuid)
2569 {
2570 SetLastError(ERROR_INVALID_USER_BUFFER);
2571 return FALSE;
2572 }
2573
2574 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2575 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2576 CreationFlags, DeviceInterfaceData);
2577 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2578 return FALSE;
2579 }
2580
2581 /***********************************************************************
2582 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2583 */
2584 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2585 HDEVINFO DeviceInfoSet,
2586 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2587 DWORD Reserved,
2588 REGSAM samDesired,
2589 HINF InfHandle,
2590 PCSTR InfSectionName)
2591 {
2592 HKEY key;
2593 PWSTR InfSectionNameW = NULL;
2594
2595 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2596 samDesired, InfHandle, InfSectionName);
2597 if (InfHandle)
2598 {
2599 if (!InfSectionName)
2600 {
2601 SetLastError(ERROR_INVALID_PARAMETER);
2602 return INVALID_HANDLE_VALUE;
2603 }
2604 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
2605 if (!InfSectionNameW)
2606 return INVALID_HANDLE_VALUE;
2607 }
2608 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2609 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2610 InfSectionNameW);
2611 MyFree(InfSectionNameW);
2612 return key;
2613 }
2614
2615 /***********************************************************************
2616 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2617 */
2618 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2619 HDEVINFO DeviceInfoSet,
2620 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2621 DWORD Reserved,
2622 REGSAM samDesired,
2623 HINF InfHandle,
2624 PCWSTR InfSectionName)
2625 {
2626 HKEY hKey, hDevKey;
2627 LPWSTR SymbolicLink;
2628 DWORD Length, Index;
2629 LONG rc;
2630 WCHAR bracedGuidString[39];
2631 struct DeviceInterface *DevItf;
2632 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2633
2634 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2635 samDesired, InfHandle, InfSectionName);
2636
2637 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2638 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2639 {
2640 SetLastError(ERROR_INVALID_HANDLE);
2641 return INVALID_HANDLE_VALUE;
2642 }
2643 if (!DeviceInterfaceData ||
2644 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2645 !DeviceInterfaceData->Reserved)
2646 {
2647 SetLastError(ERROR_INVALID_PARAMETER);
2648 return INVALID_HANDLE_VALUE;
2649 }
2650 if (InfHandle && !InfSectionName)
2651 {
2652 SetLastError(ERROR_INVALID_PARAMETER);
2653 return INVALID_HANDLE_VALUE;
2654 }
2655
2656 hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL);
2657 if (hKey == INVALID_HANDLE_VALUE)
2658 {
2659 hKey = SetupDiOpenClassRegKeyExW(NULL, samDesired, DIOCR_INTERFACE, NULL, NULL);
2660 if (hKey == INVALID_HANDLE_VALUE)
2661 {
2662 SetLastError(ERROR_INVALID_PARAMETER);
2663 return INVALID_HANDLE_VALUE;
2664 }
2665 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString);
2666
2667 if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS)
2668 {
2669 SetLastError(ERROR_INVALID_PARAMETER);
2670 return INVALID_HANDLE_VALUE;
2671 }
2672 RegCloseKey(hKey);
2673 hKey = hDevKey;
2674 }
2675
2676 DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2677
2678 Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR);
2679 SymbolicLink = HeapAlloc(GetProcessHeap(), 0, Length);
2680 if (!SymbolicLink)
2681 {
2682 RegCloseKey(hKey);
2683 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2684 return INVALID_HANDLE_VALUE;
2685 }
2686
2687 wcscpy(SymbolicLink, DevItf->SymbolicLink);
2688
2689 Index = 0;
2690 while(SymbolicLink[Index])
2691 {
2692 if (SymbolicLink[Index] == L'\\')
2693 {
2694 SymbolicLink[Index] = L'#';
2695 }
2696 Index++;
2697 }
2698
2699 rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL);
2700
2701 RegCloseKey(hKey);
2702 HeapFree(GetProcessHeap(), 0, SymbolicLink);
2703
2704 if (rc == ERROR_SUCCESS)
2705 {
2706 if (InfHandle && InfSectionName)
2707 {
2708 if (!SetupInstallFromInfSection(NULL /*FIXME */,
2709 InfHandle,
2710 InfSectionName,
2711 SPINST_INIFILES | SPINST_REGISTRY | SPINST_INI2REG | SPINST_FILES | SPINST_BITREG | SPINST_REGSVR | SPINST_UNREGSVR | SPINST_PROFILEITEMS | SPINST_COPYINF,
2712 hDevKey,
2713 NULL,
2714 0,
2715 set->SelectedDevice->InstallParams.InstallMsgHandler,
2716 set->SelectedDevice->InstallParams.InstallMsgHandlerContext,
2717 INVALID_HANDLE_VALUE,
2718 NULL))
2719 {
2720 RegCloseKey(hDevKey);
2721 return INVALID_HANDLE_VALUE;
2722 }
2723 }
2724 }
2725
2726 SetLastError(rc);
2727 return hDevKey;
2728 }
2729
2730 /***********************************************************************
2731 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2732 */
2733 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2734 HDEVINFO DeviceInfoSet,
2735 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2736 DWORD Reserved)
2737 {
2738 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2739 BOOL ret = FALSE;
2740
2741 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2742
2743 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2744 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2745 {
2746 SetLastError(ERROR_INVALID_HANDLE);
2747 return FALSE;
2748 }
2749 if (!DeviceInterfaceData ||
2750 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2751 !DeviceInterfaceData->Reserved)
2752 {
2753 SetLastError(ERROR_INVALID_PARAMETER);
2754 return FALSE;
2755 }
2756
2757 FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2758 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2759 return ret;
2760 }
2761
2762 /***********************************************************************
2763 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2764 *
2765 * PARAMS
2766 * DeviceInfoSet [I] Set of devices from which to enumerate
2767 * interfaces
2768 * DeviceInfoData [I] (Optional) If specified, a specific device
2769 * instance from which to enumerate interfaces.
2770 * If it isn't specified, all interfaces for all
2771 * devices in the set are enumerated.
2772 * InterfaceClassGuid [I] The interface class to enumerate.
2773 * MemberIndex [I] An index of the interface instance to enumerate.
2774 * A caller should start with MemberIndex set to 0,
2775 * and continue until the function fails with
2776 * ERROR_NO_MORE_ITEMS.
2777 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2778 * member must be set to
2779 * sizeof(SP_DEVICE_INTERFACE_DATA).
2780 *
2781 * RETURNS
2782 * Success: non-zero value.
2783 * Failure: FALSE. Call GetLastError() for more info.
2784 */
2785 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2786 HDEVINFO DeviceInfoSet,
2787 PSP_DEVINFO_DATA DeviceInfoData,
2788 CONST GUID * InterfaceClassGuid,
2789 DWORD MemberIndex,
2790 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2791 {
2792 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2793 BOOL ret = FALSE;
2794
2795 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2796 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2797
2798 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2799 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2800 {
2801 SetLastError(ERROR_INVALID_HANDLE);
2802 return FALSE;
2803 }
2804 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2805 !DeviceInfoData->Reserved))
2806 {
2807 SetLastError(ERROR_INVALID_PARAMETER);
2808 return FALSE;
2809 }
2810 if (!DeviceInterfaceData ||
2811 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2812 {
2813 SetLastError(ERROR_INVALID_PARAMETER);
2814 return FALSE;
2815 }
2816 if (DeviceInfoData)
2817 {
2818 struct DeviceInfo *devInfo =
2819 (struct DeviceInfo *)DeviceInfoData->Reserved;
2820 BOOL found = FALSE;
2821 PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2822 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2823 {
2824 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2825 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2826 {
2827 InterfaceListEntry = InterfaceListEntry->Flink;
2828 continue;
2829 }
2830 if (MemberIndex-- == 0)
2831 {
2832 /* return this item */
2833 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2834 &DevItf->InterfaceClassGuid,
2835 sizeof(GUID));
2836 DeviceInterfaceData->Flags = DevItf->Flags;
2837 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2838 found = TRUE;
2839 ret = TRUE;
2840 }
2841 InterfaceListEntry = InterfaceListEntry->Flink;
2842 }
2843 if (!found)
2844 SetLastError(ERROR_NO_MORE_ITEMS);
2845 }
2846 else
2847 {
2848 BOOL found = FALSE;
2849 PLIST_ENTRY ItemList = set->ListHead.Flink;
2850 while (ItemList != &set->ListHead && !found)
2851 {
2852 PLIST_ENTRY InterfaceListEntry;
2853 struct DeviceInfo *devInfo =
2854 CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
2855 InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2856 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2857 {
2858 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2859 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2860 {
2861 InterfaceListEntry = InterfaceListEntry->Flink;
2862 continue;
2863 }
2864 if (MemberIndex-- == 0)
2865 {
2866 /* return this item */
2867 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2868 &DevItf->InterfaceClassGuid,
2869 sizeof(GUID));
2870 DeviceInterfaceData->Flags = DevItf->Flags;
2871 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2872 found = TRUE;
2873 ret = TRUE;
2874 }
2875 InterfaceListEntry = InterfaceListEntry->Flink;
2876 }
2877 ItemList = ItemList->Flink;
2878
2879 }
2880 if (!found)
2881 SetLastError(ERROR_NO_MORE_ITEMS);
2882 }
2883 return ret;
2884 }
2885
2886 /***********************************************************************
2887 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2888 *
2889 * Destroy a DeviceInfoList and free all used memory of the list.
2890 *
2891 * PARAMS
2892 * devinfo [I] DeviceInfoList pointer to list to destroy
2893 *
2894 * RETURNS
2895 * Success: non zero value.
2896 * Failure: zero value.
2897 */
2898 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2899 {
2900 BOOL ret = FALSE;
2901
2902 TRACE("%p\n", devinfo);
2903 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
2904 {
2905 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2906
2907 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2908 {
2909 ret = DestroyDeviceInfoSet(list);
2910 }
2911 }
2912
2913 if (ret == FALSE)
2914 SetLastError(ERROR_INVALID_HANDLE);
2915
2916 return ret;
2917 }
2918
2919 /***********************************************************************
2920 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2921 */
2922 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2923 HDEVINFO DeviceInfoSet,
2924 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2925 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2926 DWORD DeviceInterfaceDetailDataSize,
2927 PDWORD RequiredSize,
2928 PSP_DEVINFO_DATA DeviceInfoData)
2929 {
2930 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2931 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2932 DWORD sizeW = 0, bytesNeeded;
2933 BOOL ret = FALSE;
2934
2935 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2936 DeviceInterfaceData, DeviceInterfaceDetailData,
2937 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2938
2939 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2940 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2941 {
2942 SetLastError(ERROR_INVALID_HANDLE);
2943 return FALSE;
2944 }
2945 if (!DeviceInterfaceData ||
2946 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2947 !DeviceInterfaceData->Reserved)
2948 {
2949 SetLastError(ERROR_INVALID_PARAMETER);
2950 return FALSE;
2951 }
2952 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2953 {
2954 SetLastError(ERROR_INVALID_USER_BUFFER);
2955 return FALSE;
2956 }
2957
2958 if((DeviceInterfaceDetailDataSize != 0) &&
2959 (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(CHAR))))
2960 {
2961 SetLastError(ERROR_INVALID_USER_BUFFER);
2962 return FALSE;
2963 }
2964
2965 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2966 {
2967 SetLastError(ERROR_INVALID_USER_BUFFER);
2968 return FALSE;
2969 }
2970
2971
2972 if (DeviceInterfaceDetailData != NULL)
2973 {
2974 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2975 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2976 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW);
2977 if (!DeviceInterfaceDetailDataW)
2978 {
2979 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2980 }
2981 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2982 }
2983 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2984 {
2985 ret = SetupDiGetDeviceInterfaceDetailW(
2986 DeviceInfoSet,
2987 DeviceInterfaceData,
2988 DeviceInterfaceDetailDataW,
2989 sizeW,
2990 &sizeW,
2991 DeviceInfoData);
2992 bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2993 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
2994 if (RequiredSize)
2995 *RequiredSize = bytesNeeded;
2996 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize >= bytesNeeded)
2997 {
2998 if (!WideCharToMultiByte(
2999 CP_ACP, 0,
3000 DeviceInterfaceDetailDataW->DevicePath, -1,
3001 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
3002 NULL, NULL))
3003 {
3004 ret = FALSE;
3005 }
3006 }
3007 }
3008 MyFree(DeviceInterfaceDetailDataW);
3009
3010 return ret;
3011 }
3012
3013 /***********************************************************************
3014 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3015 */
3016 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
3017 HDEVINFO DeviceInfoSet,
3018 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
3019 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
3020 DWORD DeviceInterfaceDetailDataSize,
3021 PDWORD RequiredSize,
3022 PSP_DEVINFO_DATA DeviceInfoData)
3023 {
3024 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3025 BOOL ret = FALSE;
3026
3027 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
3028 DeviceInterfaceData, DeviceInterfaceDetailData,
3029 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
3030
3031 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
3032 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3033 {
3034 SetLastError(ERROR_INVALID_HANDLE);
3035 return FALSE;
3036 }
3037 if (!DeviceInterfaceData ||
3038 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
3039 !DeviceInterfaceData->Reserved)
3040 {
3041 SetLastError(ERROR_INVALID_PARAMETER);
3042 return FALSE;
3043 }
3044 if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
3045 {
3046 SetLastError(ERROR_INVALID_USER_BUFFER);
3047 return FALSE;
3048 }
3049 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
3050 {
3051 SetLastError(ERROR_INVALID_USER_BUFFER);
3052 return FALSE;
3053 }
3054 if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3055 {
3056 SetLastError(ERROR_INVALID_PARAMETER);
3057 return FALSE;
3058 }
3059 if ((DeviceInterfaceDetailData != NULL)
3060 && (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) + sizeof(WCHAR)))
3061 {
3062 SetLastError(ERROR_INVALID_PARAMETER);
3063 return FALSE;
3064 }
3065 else
3066 {
3067 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
3068 LPCWSTR devName = deviceInterface->SymbolicLink;
3069 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
3070 (lstrlenW(devName) + 1) * sizeof(WCHAR);
3071
3072 if (sizeRequired > DeviceInterfaceDetailDataSize)
3073 {
3074 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3075 if (RequiredSize)
3076 *RequiredSize = sizeRequired;
3077 }
3078 else
3079 {
3080 strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
3081 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
3082 if (DeviceInfoData)
3083 {
3084 memcpy(&DeviceInfoData->ClassGuid,
3085 &deviceInterface->DeviceInfo->ClassGuid,
3086 sizeof(GUID));
3087 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
3088 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
3089 }
3090 ret = TRUE;
3091 }
3092 }
3093 return ret;
3094 }
3095
3096 struct PropertyMapEntry
3097 {
3098 DWORD regType;
3099 LPCSTR nameA;
3100 LPCWSTR nameW;
3101 };
3102
3103 static struct PropertyMapEntry PropertyMap[] = {
3104 { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC },
3105 { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID },
3106 { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS },
3107 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
3108 { REG_SZ, "Service", REGSTR_VAL_SERVICE },
3109 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
3110 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
3111 { REG_SZ, "Class", REGSTR_VAL_CLASS },
3112 { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID },
3113 { REG_SZ, "Driver", REGSTR_VAL_DRIVER },
3114 { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS },
3115 { REG_SZ, "Mfg", REGSTR_VAL_MFG },
3116 { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME },
3117 { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION },
3118 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3119 { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES },
3120 { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER },
3121 { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS },
3122 { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS },
3123 { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */
3124 { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */
3125 { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */
3126 { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */
3127 { REG_BINARY, "Security", REGSTR_SECURITY },
3128 { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */
3129 { 0, NULL, NULL }, /* SPDRP_DEVTYPE */
3130 { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */
3131 { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */
3132 { 0, NULL, NULL }, /* SPDRP_ADDRESS */
3133 { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT },
3134 { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */
3135 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */
3136 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3137 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3138 { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */
3139 };
3140
3141 /***********************************************************************
3142 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3143 */
3144 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
3145 HDEVINFO DeviceInfoSet,
3146 PSP_DEVINFO_DATA DeviceInfoData,
3147 DWORD Property,
3148 PDWORD PropertyRegDataType,
3149 PBYTE PropertyBuffer,
3150 DWORD PropertyBufferSize,
3151 PDWORD RequiredSize)
3152 {
3153 BOOL ret;
3154 BOOL bIsStringProperty;
3155 DWORD RegType;
3156 DWORD RequiredSizeA, RequiredSizeW;
3157 DWORD PropertyBufferSizeW = 0;
3158 PBYTE PropertyBufferW = NULL;
3159
3160 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3161 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3162 RequiredSize);
3163
3164 if (PropertyBufferSize != 0)
3165 {
3166 PropertyBufferSizeW = PropertyBufferSize * 2;
3167 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
3168 if (!PropertyBufferW)
3169 {
3170 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3171 return FALSE;
3172 }
3173 }
3174
3175 ret = SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet,
3176 DeviceInfoData,
3177 Property,
3178 &RegType,
3179 PropertyBufferW,
3180 PropertyBufferSizeW,
3181 &RequiredSizeW);
3182
3183 if (ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3184 {
3185 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
3186
3187 if (bIsStringProperty)
3188 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
3189 else
3190 RequiredSizeA = RequiredSizeW;
3191 if (RequiredSize)
3192 *RequiredSize = RequiredSizeA;
3193 if (PropertyRegDataType)
3194 *PropertyRegDataType = RegType;
3195 }
3196
3197 if (!ret)
3198 {
3199 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3200 return ret;
3201 }
3202
3203 if (RequiredSizeA <= PropertyBufferSize)
3204 {
3205 if (bIsStringProperty && PropertyBufferSize > 0)
3206 {
3207 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
3208 {
3209 /* Last error is already set by WideCharToMultiByte */
3210 ret = FALSE;
3211 }
3212 }
3213 else
3214 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
3215 }
3216 else
3217 {
3218 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3219 ret = FALSE;
3220 }
3221
3222 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3223 return ret;
3224 }
3225
3226 /***********************************************************************
3227 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3228 */
3229 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
3230 HDEVINFO DeviceInfoSet,
3231 PSP_DEVINFO_DATA DeviceInfoData,
3232 DWORD Property,
3233 PDWORD PropertyRegDataType,
3234 PBYTE PropertyBuffer,
3235 DWORD PropertyBufferSize,
3236 PDWORD RequiredSize)
3237 {
3238 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3239 struct DeviceInfo *devInfo;
3240 CONFIGRET cr;
3241 LONG lError = ERROR_SUCCESS;
3242 DWORD size;
3243
3244 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3245 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3246 RequiredSize);
3247
3248 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3249 {
3250 SetLastError(ERROR_INVALID_HANDLE);
3251 return FALSE;
3252 }
3253 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3254 {
3255 SetLastError(ERROR_INVALID_HANDLE);
3256 return FALSE;
3257 }
3258 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3259 || !DeviceInfoData->Reserved)
3260 {
3261 SetLastError(ERROR_INVALID_PARAMETER);
3262 return FALSE;
3263 }
3264
3265 if (Property >= SPDRP_MAXIMUM_PROPERTY)
3266 {
3267 SetLastError(ERROR_INVALID_REG_PROPERTY);
3268 return FALSE;
3269 }
3270
3271 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3272
3273 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3274 && PropertyMap[Property].nameW)
3275 {
3276 HKEY hKey;
3277 size = PropertyBufferSize;
3278 hKey = SETUPDI_OpenDevKey(set->HKLM, devInfo, KEY_QUERY_VALUE);
3279 if (hKey == INVALID_HANDLE_VALUE)
3280 return FALSE;
3281 lError = RegQueryValueExW(hKey, PropertyMap[Property].nameW,
3282 NULL, PropertyRegDataType, PropertyBuffer, &size);
3283 RegCloseKey(hKey);
3284
3285 if (RequiredSize)
3286 *RequiredSize = size;
3287