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