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