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