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