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