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