2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
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.
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.
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
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
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};
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};
46 (CALLBACK
* CLASS_INSTALL_PROC
) (
47 IN DI_FUNCTION InstallFunction
,
48 IN HDEVINFO DeviceInfoSet
,
49 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
51 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
52 IN HDEVINFO DeviceInfoSet
,
53 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
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
);
61 struct CoInstallerElement
66 COINSTALLER_PROC Function
;
67 BOOL DoPostProcessing
;
71 struct GetSectionCallbackInfo
73 PSP_ALTPLATFORM_INFO PlatformInfo
;
77 WCHAR BestSection
[LINE_LEN
+ 1];
78 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
83 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
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','%',
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]);
96 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
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
;
120 /* Does not happen */
123 /* Lower scores are best ones */
126 IN LPCWSTR SectionName
,
127 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
130 OUT PDWORD ScorePlatform
,
131 OUT PDWORD ScoreMajorVersion
,
132 OUT PDWORD ScoreMinorVersion
,
133 OUT PDWORD ScoreProductType
,
134 OUT PDWORD ScoreSuiteMask
)
136 LPWSTR Section
= NULL
;
137 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
142 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
143 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
144 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
146 static const WCHAR ExtensionArchitectureNone
[] = {0};
147 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
148 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
149 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
150 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
151 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
152 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
154 TRACE("%s %p 0x%x 0x%x\n",
155 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
157 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
159 Section
= DuplicateString(SectionName
);
162 TRACE("DuplicateString() failed\n");
166 /* Set various extensions values */
167 switch (PlatformInfo
->Platform
)
169 case VER_PLATFORM_WIN32_WINDOWS
:
170 pExtensionPlatform
= ExtensionPlatformWindows
;
172 case VER_PLATFORM_WIN32_NT
:
173 pExtensionPlatform
= ExtensionPlatformNT
;
176 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
177 pExtensionPlatform
= ExtensionPlatformNone
;
180 switch (PlatformInfo
->ProcessorArchitecture
)
182 case PROCESSOR_ARCHITECTURE_ALPHA
:
183 pExtensionArchitecture
= ExtensionArchitecturealpha
;
185 case PROCESSOR_ARCHITECTURE_AMD64
:
186 pExtensionArchitecture
= ExtensionArchitectureamd64
;
188 case PROCESSOR_ARCHITECTURE_IA64
:
189 pExtensionArchitecture
= ExtensionArchitectureia64
;
191 case PROCESSOR_ARCHITECTURE_INTEL
:
192 pExtensionArchitecture
= ExtensionArchitecturex86
;
194 case PROCESSOR_ARCHITECTURE_MIPS
:
195 pExtensionArchitecture
= ExtensionArchitecturemips
;
197 case PROCESSOR_ARCHITECTURE_PPC
:
198 pExtensionArchitecture
= ExtensionArchitectureppc
;
201 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
202 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
203 pExtensionArchitecture
= ExtensionArchitectureNone
;
209 * Field[1] Architecture
210 * Field[2] Major version
211 * Field[3] Minor version
212 * Field[4] Product type
213 * Field[5] Suite mask
214 * Remark: lastests fields may be NULL if the information is not provided
217 if (Fields
[0] == NULL
)
219 TRACE("No extension found\n");
220 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
224 Fields
[1] = Fields
[0] + 1;
225 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
226 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
228 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
232 *(Fields
[i
] - 1) = UNICODE_NULL
;
235 /* Take care of first 2 fields */
236 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
238 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
240 TRACE("Mismatch on platform field\n");
243 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
245 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
247 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
249 TRACE("Mismatch on platform field\n");
252 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
256 /* No platform specified */
257 *ScorePlatform
|= 0x02;
259 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
261 /* No architecture specified */
262 *ScorePlatform
|= 0x01;
264 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
266 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
267 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
271 /* Check if informations are matching */
272 if (Fields
[2] && *Fields
[2])
274 DWORD MajorVersion
, MinorVersion
= 0;
275 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
276 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
277 (errno
== ERANGE
|| errno
== EINVAL
))
279 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
282 if (Fields
[3] && *Fields
[3])
284 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
285 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
286 (errno
== ERANGE
|| errno
== EINVAL
))
288 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
292 if (PlatformInfo
->MajorVersion
< MajorVersion
||
293 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
295 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
296 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
299 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
300 if (MajorVersion
== PlatformInfo
->MajorVersion
)
301 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
303 *ScoreMinorVersion
= MinorVersion
;
305 else if (Fields
[3] && *Fields
[3])
307 TRACE("Minor version found without major version\n");
312 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
313 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
316 if (Fields
[4] && *Fields
[4])
318 DWORD CurrentProductType
;
319 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
320 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
321 (errno
== ERANGE
|| errno
== EINVAL
))
323 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
326 if (CurrentProductType
!= ProductType
)
328 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
329 CurrentProductType
, ProductType
);
334 *ScoreProductType
= 1;
336 if (Fields
[5] && *Fields
[5])
338 DWORD CurrentSuiteMask
;
339 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
340 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
341 (errno
== ERANGE
|| errno
== EINVAL
))
343 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
346 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
348 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
349 CurrentSuiteMask
, SuiteMask
);
352 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
355 *ScoreSuiteMask
= SuiteMask
;
366 IN LPCWSTR SectionName
,
369 struct GetSectionCallbackInfo
*info
= Context
;
370 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
373 if (SectionName
[info
->PrefixLength
] != '.')
376 ret
= CheckSectionValid(
377 &SectionName
[info
->PrefixLength
],
381 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
384 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
387 if (Score1
> info
->BestScore1
) goto done
;
388 if (Score1
< info
->BestScore1
) goto bettersection
;
389 if (Score2
> info
->BestScore2
) goto done
;
390 if (Score2
< info
->BestScore2
) goto bettersection
;
391 if (Score3
> info
->BestScore3
) goto done
;
392 if (Score3
< info
->BestScore3
) goto bettersection
;
393 if (Score4
> info
->BestScore4
) goto done
;
394 if (Score4
< info
->BestScore4
) goto bettersection
;
395 if (Score5
> info
->BestScore5
) goto done
;
396 if (Score5
< info
->BestScore5
) goto bettersection
;
400 strcpyW(info
->BestSection
, SectionName
);
401 info
->BestScore1
= Score1
;
402 info
->BestScore2
= Score2
;
403 info
->BestScore3
= Score3
;
404 info
->BestScore4
= Score4
;
405 info
->BestScore5
= Score5
;
411 /***********************************************************************
412 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
415 SetupDiGetActualSectionToInstallExW(
417 IN PCWSTR InfSectionName
,
418 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
419 OUT PWSTR InfSectionWithExt OPTIONAL
,
420 IN DWORD InfSectionWithExtSize
,
421 OUT PDWORD RequiredSize OPTIONAL
,
422 OUT PWSTR
* Extension OPTIONAL
,
427 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
428 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
429 RequiredSize
, Extension
, Reserved
);
431 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
432 SetLastError(ERROR_INVALID_HANDLE
);
433 else if (!InfSectionName
)
434 SetLastError(ERROR_INVALID_PARAMETER
);
435 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
436 SetLastError(ERROR_INVALID_USER_BUFFER
);
437 else if (Reserved
!= NULL
)
438 SetLastError(ERROR_INVALID_PARAMETER
);
441 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
442 static BYTE CurrentProductType
= 0;
443 static WORD CurrentSuiteMask
= 0;
444 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
445 struct GetSectionCallbackInfo CallbackInfo
;
450 /* Fill platform info if needed */
451 if (AlternatePlatformInfo
)
453 pPlatformInfo
= AlternatePlatformInfo
;
459 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
461 /* That's the first time we go here. We need to fill in the structure */
462 OSVERSIONINFOEX VersionInfo
;
463 SYSTEM_INFO SystemInfo
;
464 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
465 ret
= GetVersionExW((OSVERSIONINFO
*)&VersionInfo
);
468 GetSystemInfo(&SystemInfo
);
469 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
470 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
471 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
472 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
473 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
474 CurrentPlatform
.Reserved
= 0;
475 CurrentProductType
= VersionInfo
.wProductType
;
476 CurrentSuiteMask
= VersionInfo
.wSuiteMask
;
478 ProductType
= CurrentProductType
;
479 SuiteMask
= CurrentSuiteMask
;
482 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
483 CallbackInfo
.ProductType
= ProductType
;
484 CallbackInfo
.SuiteMask
= SuiteMask
;
485 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
486 CallbackInfo
.BestScore1
= ULONG_MAX
;
487 CallbackInfo
.BestScore2
= ULONG_MAX
;
488 CallbackInfo
.BestScore3
= ULONG_MAX
;
489 CallbackInfo
.BestScore4
= ULONG_MAX
;
490 CallbackInfo
.BestScore5
= ULONG_MAX
;
491 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
492 if (!EnumerateSectionsStartingWith(
498 SetLastError(ERROR_GEN_FAILURE
);
502 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
503 if (RequiredSize
!= NULL
)
504 *RequiredSize
= dwFullLength
+ 1;
506 if (InfSectionWithExtSize
> 0)
508 if (InfSectionWithExtSize
< dwFullLength
+ 1)
510 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
513 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
516 DWORD dwLength
= lstrlenW(InfSectionName
);
517 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
525 TRACE("Returning %d\n", ret
);
532 IN
struct DeviceInfoSet
*list
,
533 IN LPCWSTR InstancePath
,
534 IN LPCGUID pClassGuid
,
535 OUT
struct DeviceInfo
**pDeviceInfo
)
539 struct DeviceInfo
*deviceInfo
;
543 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
544 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
547 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
550 ZeroMemory(deviceInfo
, size
);
552 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
553 if (cr
!= CR_SUCCESS
)
555 SetLastError(GetErrorCodeFromCrCode(cr
));
559 deviceInfo
->set
= list
;
560 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
561 strcpyW(deviceInfo
->Data
, InstancePath
);
562 deviceInfo
->instanceId
= deviceInfo
->Data
;
563 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
564 deviceInfo
->DeviceDescription
= NULL
;
565 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
566 deviceInfo
->CreationFlags
= 0;
567 InitializeListHead(&deviceInfo
->DriverListHead
);
568 InitializeListHead(&deviceInfo
->InterfaceListHead
);
570 *pDeviceInfo
= deviceInfo
;
576 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
578 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
579 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
584 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
586 PLIST_ENTRY ListEntry
;
587 struct DriverInfoElement
*driverInfo
;
588 struct DeviceInterface
*deviceInterface
;
590 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
592 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
593 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
594 if (!DestroyDriverInfoElement(driverInfo
))
597 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
599 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
600 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
601 if (!DestroyDeviceInterface(deviceInterface
))
604 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
605 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
609 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
611 PLIST_ENTRY ListEntry
;
612 struct DeviceInfo
*deviceInfo
;
614 while (!IsListEmpty(&list
->ListHead
))
616 ListEntry
= RemoveHeadList(&list
->ListHead
);
617 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
);
618 if (!DestroyDeviceInfo(deviceInfo
))
621 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
622 RegCloseKey(list
->HKLM
);
623 CM_Disconnect_Machine(list
->hMachine
);
624 DestroyClassInstallParams(&list
->ClassInstallParams
);
625 return HeapFree(GetProcessHeap(), 0, list
);
628 /***********************************************************************
629 * SetupDiBuildClassInfoList (SETUPAPI.@)
631 * Returns a list of setup class GUIDs that identify the classes
632 * that are installed on a local machine.
635 * Flags [I] control exclusion of classes from the list.
636 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
637 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
638 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
644 BOOL WINAPI
SetupDiBuildClassInfoList(
646 LPGUID ClassGuidList
,
647 DWORD ClassGuidListSize
,
651 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
652 ClassGuidListSize
, RequiredSize
,
656 /***********************************************************************
657 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
659 * Returns a list of setup class GUIDs that identify the classes
660 * that are installed on a local or remote macine.
663 * Flags [I] control exclusion of classes from the list.
664 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
665 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
666 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
667 * MachineName [I] name of a remote machine.
668 * Reserved [I] must be NULL.
674 BOOL WINAPI
SetupDiBuildClassInfoListExA(
676 LPGUID ClassGuidList
,
677 DWORD ClassGuidListSize
,
682 LPWSTR MachineNameW
= NULL
;
685 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
686 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
690 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
691 if (MachineNameW
== NULL
) return FALSE
;
694 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
695 ClassGuidListSize
, RequiredSize
,
696 MachineNameW
, Reserved
);
698 MyFree(MachineNameW
);
703 /***********************************************************************
704 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
706 * Returns a list of setup class GUIDs that identify the classes
707 * that are installed on a local or remote macine.
710 * Flags [I] control exclusion of classes from the list.
711 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
712 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
713 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
714 * MachineName [I] name of a remote machine.
715 * Reserved [I] must be NULL.
721 BOOL WINAPI
SetupDiBuildClassInfoListExW(
723 LPGUID ClassGuidList
,
724 DWORD ClassGuidListSize
,
730 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
735 DWORD dwGuidListIndex
= 0;
737 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
738 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
742 SetLastError(ERROR_INVALID_PARAMETER
);
745 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
747 SetLastError(ERROR_INVALID_PARAMETER
);
751 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
752 KEY_ENUMERATE_SUB_KEYS
,
756 if (hClassesKey
== INVALID_HANDLE_VALUE
)
761 for (dwIndex
= 0; ; dwIndex
++)
764 lError
= RegEnumKeyExW(hClassesKey
,
772 TRACE("RegEnumKeyExW() returns %d\n", lError
);
773 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
775 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
777 if (RegOpenKeyExW(hClassesKey
,
783 RegCloseKey(hClassesKey
);
787 if (!RegQueryValueExW(hClassKey
,
788 REGSTR_VAL_NOUSECLASS
,
794 TRACE("'NoUseClass' value found!\n");
795 RegCloseKey(hClassKey
);
799 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
800 (!RegQueryValueExW(hClassKey
,
801 REGSTR_VAL_NOINSTALLCLASS
,
807 TRACE("'NoInstallClass' value found!\n");
808 RegCloseKey(hClassKey
);
812 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
813 (!RegQueryValueExW(hClassKey
,
814 REGSTR_VAL_NODISPLAYCLASS
,
820 TRACE("'NoDisplayClass' value found!\n");
821 RegCloseKey(hClassKey
);
825 RegCloseKey(hClassKey
);
827 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
828 if (dwGuidListIndex
< ClassGuidListSize
)
830 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
834 TRACE("Guid: %p\n", &szKeyName
[1]);
836 UuidFromStringW(&szKeyName
[1],
837 &ClassGuidList
[dwGuidListIndex
]);
843 if (lError
!= ERROR_SUCCESS
)
847 RegCloseKey(hClassesKey
);
849 if (RequiredSize
!= NULL
)
850 *RequiredSize
= dwGuidListIndex
;
852 if (ClassGuidListSize
< dwGuidListIndex
)
854 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
861 /***********************************************************************
862 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
864 BOOL WINAPI
SetupDiClassGuidsFromNameA(
866 LPGUID ClassGuidList
,
867 DWORD ClassGuidListSize
,
870 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
871 ClassGuidListSize
, RequiredSize
,
875 /***********************************************************************
876 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
878 BOOL WINAPI
SetupDiClassGuidsFromNameW(
880 LPGUID ClassGuidList
,
881 DWORD ClassGuidListSize
,
884 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
885 ClassGuidListSize
, RequiredSize
,
889 /***********************************************************************
890 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
892 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
894 LPGUID ClassGuidList
,
895 DWORD ClassGuidListSize
,
900 LPWSTR ClassNameW
= NULL
;
901 LPWSTR MachineNameW
= NULL
;
904 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName
), ClassGuidList
,
905 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
909 SetLastError(ERROR_INVALID_PARAMETER
);
913 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
914 if (ClassNameW
== NULL
)
919 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
920 if (MachineNameW
== NULL
)
927 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
928 ClassGuidListSize
, RequiredSize
,
929 MachineNameW
, Reserved
);
931 MyFree(MachineNameW
);
937 /***********************************************************************
938 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
940 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
942 LPGUID ClassGuidList
,
943 DWORD ClassGuidListSize
,
949 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
955 DWORD dwGuidListIndex
= 0;
957 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
958 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
960 if (!ClassName
|| !RequiredSize
)
962 SetLastError(ERROR_INVALID_PARAMETER
);
965 if (!ClassGuidList
&& ClassGuidListSize
> 0)
967 SetLastError(ERROR_INVALID_PARAMETER
);
972 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
973 KEY_ENUMERATE_SUB_KEYS
,
977 if (hClassesKey
== INVALID_HANDLE_VALUE
)
982 for (dwIndex
= 0; ; dwIndex
++)
985 lError
= RegEnumKeyExW(hClassesKey
,
993 TRACE("RegEnumKeyExW() returns %d\n", lError
);
994 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
996 TRACE("Key name: %p\n", szKeyName
);
998 if (RegOpenKeyExW(hClassesKey
,
1004 RegCloseKey(hClassesKey
);
1008 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
1009 if (!RegQueryValueExW(hClassKey
,
1013 (LPBYTE
)szClassName
,
1016 TRACE("Class name: %p\n", szClassName
);
1018 if (strcmpiW(szClassName
, ClassName
) == 0)
1020 TRACE("Found matching class name\n");
1022 TRACE("Guid: %p\n", szKeyName
);
1023 if (dwGuidListIndex
< ClassGuidListSize
)
1025 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1029 TRACE("Guid: %p\n", &szKeyName
[1]);
1031 UuidFromStringW(&szKeyName
[1],
1032 &ClassGuidList
[dwGuidListIndex
]);
1039 RegCloseKey(hClassKey
);
1042 if (lError
!= ERROR_SUCCESS
)
1046 RegCloseKey(hClassesKey
);
1048 if (RequiredSize
!= NULL
)
1049 *RequiredSize
= dwGuidListIndex
;
1051 if (ClassGuidListSize
< dwGuidListIndex
)
1053 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1060 /***********************************************************************
1061 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1063 BOOL WINAPI
SetupDiClassNameFromGuidA(
1064 const GUID
* ClassGuid
,
1066 DWORD ClassNameSize
,
1067 PDWORD RequiredSize
)
1069 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1070 ClassNameSize
, RequiredSize
,
1074 /***********************************************************************
1075 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1077 BOOL WINAPI
SetupDiClassNameFromGuidW(
1078 const GUID
* ClassGuid
,
1080 DWORD ClassNameSize
,
1081 PDWORD RequiredSize
)
1083 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1084 ClassNameSize
, RequiredSize
,
1088 /***********************************************************************
1089 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1091 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1092 const GUID
* ClassGuid
,
1094 DWORD ClassNameSize
,
1095 PDWORD RequiredSize
,
1099 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1100 LPWSTR MachineNameW
= NULL
;
1104 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1105 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1106 NULL
, MachineNameW
, Reserved
);
1109 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1110 ClassNameSize
, NULL
, NULL
);
1111 if (len
== 0 || len
> ClassNameSize
)
1113 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1116 else if (RequiredSize
)
1117 *RequiredSize
= len
;
1119 MyFree(MachineNameW
);
1123 /***********************************************************************
1124 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1126 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1127 const GUID
* ClassGuid
,
1129 DWORD ClassNameSize
,
1130 PDWORD RequiredSize
,
1139 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
1140 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1142 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1147 if (hKey
== INVALID_HANDLE_VALUE
)
1152 if (RequiredSize
!= NULL
)
1155 if (RegQueryValueExW(hKey
,
1166 *RequiredSize
= dwLength
/ sizeof(WCHAR
) + 1;
1171 SetLastError(ERROR_INVALID_CLASS
);
1175 if (!ClassName
&& ClassNameSize
> 0)
1177 SetLastError(ERROR_INVALID_PARAMETER
);
1182 dwLength
= ClassNameSize
* sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
1183 rc
= RegQueryValueExW(hKey
,
1189 if (rc
!= ERROR_SUCCESS
)
1195 if (dwRegType
!= REG_SZ
)
1197 SetLastError(ERROR_GEN_FAILURE
);
1202 if (ClassNameSize
> 1)
1203 ClassName
[ClassNameSize
] = UNICODE_NULL
;
1209 /***********************************************************************
1210 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1213 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1216 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1219 /***********************************************************************
1220 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1223 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1228 LPWSTR MachineNameW
= NULL
;
1231 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1232 debugstr_a(MachineName
), Reserved
);
1236 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1237 if (MachineNameW
== NULL
)
1238 return INVALID_HANDLE_VALUE
;
1241 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1242 MachineNameW
, Reserved
);
1244 MyFree(MachineNameW
);
1249 /***********************************************************************
1250 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1252 * Create an empty DeviceInfoSet list.
1255 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1257 * hwndParent [I] hwnd needed for interface related actions.
1258 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1259 * local registry will be used.
1260 * Reserved [I] must be NULL
1263 * Success: empty list.
1264 * Failure: INVALID_HANDLE_VALUE.
1267 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1272 struct DeviceInfoSet
*list
= NULL
;
1273 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1276 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1278 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1279 debugstr_w(MachineName
), Reserved
);
1281 if (MachineName
!= NULL
)
1283 SIZE_T len
= strlenW(MachineName
);
1284 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1286 SetLastError(ERROR_INVALID_MACHINENAME
);
1289 size
+= (len
+ 3) * sizeof(WCHAR
);
1292 if (Reserved
!= NULL
)
1294 SetLastError(ERROR_INVALID_PARAMETER
);
1295 return INVALID_HANDLE_VALUE
;
1298 list
= MyMalloc(size
);
1301 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1302 return INVALID_HANDLE_VALUE
;
1304 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1306 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1307 memcpy(&list
->ClassGuid
,
1308 ClassGuid
? ClassGuid
: &GUID_NULL
,
1309 sizeof(list
->ClassGuid
));
1310 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1311 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1312 list
->InstallParams
.hwndParent
= hwndParent
;
1315 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1316 if (rc
!= ERROR_SUCCESS
)
1318 SetLastError(ERROR_INVALID_MACHINENAME
);
1322 list
->szData
[0] = list
->szData
[1] = '\\';
1323 strcpyW(list
->szData
+ 2, MachineName
);
1324 list
->MachineName
= list
->szData
;
1328 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1329 list
->MachineName
= NULL
;
1331 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1332 if (cr
!= CR_SUCCESS
)
1334 SetLastError(GetErrorCodeFromCrCode(cr
));
1337 InitializeListHead(&list
->DriverListHead
);
1338 InitializeListHead(&list
->ListHead
);
1340 return (HDEVINFO
)list
;
1343 if (ret
== INVALID_HANDLE_VALUE
)
1347 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1348 RegCloseKey(list
->HKLM
);
1355 /***********************************************************************
1356 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1358 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1359 HDEVINFO DeviceInfoSet
,
1360 PSP_DEVINFO_DATA DeviceInfoData
,
1365 PCSTR InfSectionName
)
1367 PWSTR InfSectionNameW
= NULL
;
1370 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1371 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1375 if (!InfSectionName
)
1377 SetLastError(ERROR_INVALID_PARAMETER
);
1378 return INVALID_HANDLE_VALUE
;
1382 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
1383 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1386 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1387 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1388 MyFree(InfSectionNameW
);
1393 OpenHardwareProfileKey(
1396 IN DWORD samDesired
);
1398 /***********************************************************************
1399 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1401 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1402 HDEVINFO DeviceInfoSet
,
1403 PSP_DEVINFO_DATA DeviceInfoData
,
1408 PCWSTR InfSectionName
)
1410 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1411 HKEY key
= INVALID_HANDLE_VALUE
;
1412 LPWSTR lpGuidString
= NULL
;
1413 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
1414 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
1415 DWORD Index
; /* Index used in the DriverKey name */
1417 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1418 HKEY hEnumKey
= NULL
;
1419 HKEY hClassKey
= NULL
;
1420 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
1424 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1425 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1427 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1429 SetLastError(ERROR_INVALID_HANDLE
);
1430 return INVALID_HANDLE_VALUE
;
1432 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1434 SetLastError(ERROR_INVALID_HANDLE
);
1435 return INVALID_HANDLE_VALUE
;
1437 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1438 || !DeviceInfoData
->Reserved
)
1440 SetLastError(ERROR_INVALID_PARAMETER
);
1441 return INVALID_HANDLE_VALUE
;
1443 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1445 SetLastError(ERROR_INVALID_FLAGS
);
1446 return INVALID_HANDLE_VALUE
;
1448 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1450 SetLastError(ERROR_INVALID_FLAGS
);
1451 return INVALID_HANDLE_VALUE
;
1453 if (InfHandle
&& !InfSectionName
)
1455 SetLastError(ERROR_INVALID_PARAMETER
);
1456 return INVALID_HANDLE_VALUE
;
1458 if (!InfHandle
&& InfSectionName
)
1460 SetLastError(ERROR_INVALID_PARAMETER
);
1461 return INVALID_HANDLE_VALUE
;
1464 if (Scope
== DICS_FLAG_GLOBAL
)
1465 RootKey
= set
->HKLM
;
1466 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1468 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1469 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1471 RootKey
= hHWProfileKey
;
1474 if (KeyType
== DIREG_DEV
)
1476 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1478 rc
= RegCreateKeyExW(
1480 REGSTR_PATH_SYSTEMENUM
,
1483 REG_OPTION_NON_VOLATILE
,
1488 if (rc
!= ERROR_SUCCESS
)
1493 rc
= RegCreateKeyExW(
1495 deviceInfo
->instanceId
,
1498 REG_OPTION_NON_VOLATILE
,
1499 #if _WIN32_WINNT >= 0x502
1500 KEY_READ
| KEY_WRITE
,
1507 if (rc
!= ERROR_SUCCESS
)
1513 else /* KeyType == DIREG_DRV */
1515 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
1517 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1518 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
1521 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1525 strcpyW(&DriverKey
[1], lpGuidString
);
1526 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
1527 *pDeviceInstance
++ = '}';
1528 *pDeviceInstance
++ = '\\';
1529 rc
= RegOpenKeyExW(RootKey
,
1530 REGSTR_PATH_CLASS_NT
,
1534 if (rc
!= ERROR_SUCCESS
)
1540 /* Try all values for Index between 0 and 9999 */
1542 while (Index
<= 9999)
1545 sprintfW(pDeviceInstance
, InstanceKeyFormat
, Index
);
1546 rc
= RegCreateKeyExW(hClassKey
,
1550 REG_OPTION_NON_VOLATILE
,
1551 #if _WIN32_WINNT >= 0x502
1552 KEY_READ
| KEY_WRITE
,
1559 if (rc
!= ERROR_SUCCESS
)
1564 if (Disposition
== REG_CREATED_NEW_KEY
)
1572 /* Unable to create more than 9999 devices within the same class */
1573 SetLastError(ERROR_GEN_FAILURE
);
1577 /* Open device key, to write Driver value */
1578 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
1579 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
1581 rc
= RegSetValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
1582 if (rc
!= ERROR_SUCCESS
)
1589 /* Do installation of the specified section */
1592 FIXME("Need to install section %s in file %p\n",
1593 debugstr_w(InfSectionName
), InfHandle
);
1599 RpcStringFreeW(&lpGuidString
);
1600 HeapFree(GetProcessHeap(), 0, DriverKey
);
1601 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1602 RegCloseKey(hHWProfileKey
);
1603 if (hEnumKey
!= NULL
)
1604 RegCloseKey(hEnumKey
);
1605 if (hClassKey
!= NULL
)
1606 RegCloseKey(hClassKey
);
1607 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
1608 RegCloseKey(hDeviceKey
);
1609 if (hKey
!= NULL
&& hKey
!= key
)
1612 TRACE("Returning 0x%p\n", key
);
1616 /***********************************************************************
1617 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1619 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1620 HDEVINFO DeviceInfoSet
,
1622 CONST GUID
*ClassGuid
,
1623 PCSTR DeviceDescription
,
1625 DWORD CreationFlags
,
1626 PSP_DEVINFO_DATA DeviceInfoData
)
1629 LPWSTR DeviceNameW
= NULL
;
1630 LPWSTR DeviceDescriptionW
= NULL
;
1636 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
1637 if (DeviceNameW
== NULL
) return FALSE
;
1639 if (DeviceDescription
)
1641 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
1642 if (DeviceDescriptionW
== NULL
)
1644 MyFree(DeviceNameW
);
1649 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1650 hwndParent
, CreationFlags
, DeviceInfoData
);
1652 MyFree(DeviceNameW
);
1653 MyFree(DeviceDescriptionW
);
1658 /***********************************************************************
1659 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1661 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1662 HDEVINFO DeviceInfoSet
,
1664 CONST GUID
*ClassGuid
,
1665 PCWSTR DeviceDescription
,
1667 DWORD CreationFlags
,
1668 PSP_DEVINFO_DATA DeviceInfoData
)
1670 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1672 SP_DEVINFO_DATA DevInfo
;
1674 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1675 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1676 hwndParent
, CreationFlags
, DeviceInfoData
);
1680 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1683 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1685 SetLastError(ERROR_INVALID_HANDLE
);
1690 SetLastError(ERROR_INVALID_PARAMETER
);
1693 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1695 SetLastError(ERROR_INVALID_HANDLE
);
1698 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1699 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1701 SetLastError(ERROR_CLASS_MISMATCH
);
1704 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1706 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1707 SetLastError(ERROR_INVALID_FLAGS
);
1711 if (CreationFlags
& DICD_GENERATE_ID
)
1713 /* Generate a new unique ID for this device */
1714 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1715 FIXME("not implemented\n");
1719 /* Device name is fully qualified. Try to open it */
1722 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1723 rc
= SetupDiOpenDeviceInfoW(
1726 NULL
, /* hwndParent */
1727 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
1732 /* SetupDiOpenDeviceInfoW has already added
1733 * the device info to the device info set
1735 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
1737 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
1739 struct DeviceInfo
*deviceInfo
;
1741 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1743 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1745 if (!DeviceInfoData
)
1749 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
1751 SetLastError(ERROR_INVALID_USER_BUFFER
);
1755 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1756 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1757 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1765 TRACE("Returning %d\n", ret
);
1769 /***********************************************************************
1770 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1772 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1773 HDEVINFO DeviceInfoSet
,
1774 PSP_DEVINFO_DATA DeviceInfoData
,
1776 PSP_DETSIG_CMPPROC CompareProc
,
1777 PVOID CompareContext
,
1778 PSP_DEVINFO_DATA DupDeviceInfoData
)
1780 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1782 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1783 CompareProc
, CompareContext
, DupDeviceInfoData
);
1785 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1787 SetLastError(ERROR_INVALID_HANDLE
);
1790 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1792 SetLastError(ERROR_INVALID_HANDLE
);
1795 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1796 || !DeviceInfoData
->Reserved
)
1798 SetLastError(ERROR_INVALID_PARAMETER
);
1801 FIXME("Stub %p %p 0x%lx %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1802 CompareProc
, CompareContext
, DupDeviceInfoData
);
1803 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1807 /***********************************************************************
1808 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1810 BOOL WINAPI
SetupDiEnumDeviceInfo(
1813 PSP_DEVINFO_DATA info
)
1817 TRACE("%p %d %p\n", devinfo
, index
, info
);
1821 SetLastError(ERROR_INVALID_PARAMETER
);
1824 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1826 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1827 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1829 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1830 SetLastError(ERROR_INVALID_USER_BUFFER
);
1833 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1834 while (ItemList
!= &list
->ListHead
&& index
-- > 0)
1835 ItemList
= ItemList
->Flink
;
1836 if (ItemList
== &list
->ListHead
)
1837 SetLastError(ERROR_NO_MORE_ITEMS
);
1840 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1841 memcpy(&info
->ClassGuid
,
1842 &DevInfo
->ClassGuid
,
1844 info
->DevInst
= DevInfo
->dnDevInst
;
1845 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1851 SetLastError(ERROR_INVALID_HANDLE
);
1854 SetLastError(ERROR_INVALID_HANDLE
);
1858 /***********************************************************************
1859 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1861 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1862 HDEVINFO DeviceInfoSet
,
1863 PSP_DEVINFO_DATA DeviceInfoData
,
1864 PSTR DeviceInstanceId
,
1865 DWORD DeviceInstanceIdSize
,
1866 PDWORD RequiredSize
)
1872 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1873 DeviceInstanceIdSize
, RequiredSize
);
1875 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1877 SetLastError(ERROR_INVALID_PARAMETER
);
1881 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1886 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1888 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
1891 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1898 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
1900 DeviceInstanceIdSize
, NULL
, NULL
);
1906 if (len
> DeviceInstanceIdSize
)
1908 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1912 *RequiredSize
= len
;
1920 *RequiredSize
= size
;
1921 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1927 /***********************************************************************
1928 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1930 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
1931 HDEVINFO DeviceInfoSet
,
1932 PSP_DEVINFO_DATA DeviceInfoData
,
1933 PWSTR DeviceInstanceId
,
1934 DWORD DeviceInstanceIdSize
,
1935 PDWORD RequiredSize
)
1937 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1938 struct DeviceInfo
*devInfo
;
1940 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1941 DeviceInstanceIdSize
, RequiredSize
);
1943 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1945 SetLastError(ERROR_INVALID_HANDLE
);
1948 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1950 SetLastError(ERROR_INVALID_HANDLE
);
1953 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1954 || !DeviceInfoData
->Reserved
)
1956 SetLastError(ERROR_INVALID_PARAMETER
);
1959 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1960 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1962 SetLastError(ERROR_INVALID_PARAMETER
);
1965 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
1967 SetLastError(ERROR_INVALID_PARAMETER
);
1970 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
1971 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
1973 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1975 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1978 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
1980 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1984 /***********************************************************************
1985 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1987 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
1989 PCSTR InfSectionName
,
1990 PSTR InfSectionWithExt
,
1991 DWORD InfSectionWithExtSize
,
1992 PDWORD RequiredSize
,
1995 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
1996 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2000 /***********************************************************************
2001 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2003 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
2005 PCWSTR InfSectionName
,
2006 PWSTR InfSectionWithExt
,
2007 DWORD InfSectionWithExtSize
,
2008 PDWORD RequiredSize
,
2011 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
2012 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2016 /***********************************************************************
2017 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2020 SetupDiGetActualSectionToInstallExA(
2022 IN PCSTR InfSectionName
,
2023 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
2024 OUT PSTR InfSectionWithExt OPTIONAL
,
2025 IN DWORD InfSectionWithExtSize
,
2026 OUT PDWORD RequiredSize OPTIONAL
,
2027 OUT PSTR
* Extension OPTIONAL
,
2030 LPWSTR InfSectionNameW
= NULL
;
2031 LPWSTR InfSectionWithExtW
= NULL
;
2033 BOOL bResult
= FALSE
;
2039 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
2040 if (InfSectionNameW
== NULL
)
2043 if (InfSectionWithExt
)
2045 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2046 if (InfSectionWithExtW
== NULL
)
2050 bResult
= SetupDiGetActualSectionToInstallExW(
2051 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2052 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2053 InfSectionWithExtSize
,
2055 Extension
? &ExtensionW
: NULL
,
2058 if (bResult
&& InfSectionWithExt
)
2060 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2061 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2063 if (bResult
&& Extension
)
2065 if (ExtensionW
== NULL
)
2068 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2072 MyFree(InfSectionNameW
);
2073 MyFree(InfSectionWithExtW
);
2078 /***********************************************************************
2079 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2081 BOOL WINAPI
SetupDiGetClassDescriptionA(
2082 const GUID
* ClassGuid
,
2083 PSTR ClassDescription
,
2084 DWORD ClassDescriptionSize
,
2085 PDWORD RequiredSize
)
2087 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2088 ClassDescriptionSize
,
2089 RequiredSize
, NULL
, NULL
);
2092 /***********************************************************************
2093 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2095 BOOL WINAPI
SetupDiGetClassDescriptionW(
2096 const GUID
* ClassGuid
,
2097 PWSTR ClassDescription
,
2098 DWORD ClassDescriptionSize
,
2099 PDWORD RequiredSize
)
2101 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2102 ClassDescriptionSize
,
2103 RequiredSize
, NULL
, NULL
);
2106 /***********************************************************************
2107 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2109 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2110 const GUID
* ClassGuid
,
2111 PSTR ClassDescription
,
2112 DWORD ClassDescriptionSize
,
2113 PDWORD RequiredSize
,
2117 PWCHAR ClassDescriptionW
= NULL
;
2118 LPWSTR MachineNameW
= NULL
;
2121 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2122 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2124 if (ClassDescriptionSize
> 0)
2126 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2127 if (!ClassDescriptionW
)
2129 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2136 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2139 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2144 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2145 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2148 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2149 ClassDescriptionSize
, NULL
, NULL
);
2150 if (len
== 0 || len
> ClassDescriptionSize
)
2152 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2158 MyFree(ClassDescriptionW
);
2159 MyFree(MachineNameW
);
2163 /***********************************************************************
2164 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2166 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2167 const GUID
* ClassGuid
,
2168 PWSTR ClassDescription
,
2169 DWORD ClassDescriptionSize
,
2170 PDWORD RequiredSize
,
2179 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2180 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2184 SetLastError(ERROR_INVALID_PARAMETER
);
2187 else if (!ClassDescription
&& ClassDescriptionSize
> 0)
2189 SetLastError(ERROR_INVALID_PARAMETER
);
2193 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2198 if (hKey
== INVALID_HANDLE_VALUE
)
2200 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
2204 if (ClassDescriptionSize
< sizeof(UNICODE_NULL
) || !ClassDescription
)
2207 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
2209 rc
= RegQueryValueExW(hKey
,
2213 (LPBYTE
)ClassDescription
,
2216 if (rc
!= ERROR_MORE_DATA
&& rc
!= ERROR_SUCCESS
)
2221 else if (dwRegType
!= REG_SZ
)
2223 SetLastError(ERROR_GEN_FAILURE
);
2228 *RequiredSize
= dwLength
/ sizeof(WCHAR
) + 1;
2230 if (ClassDescriptionSize
* sizeof(WCHAR
) >= dwLength
+ sizeof(UNICODE_NULL
))
2232 if (ClassDescriptionSize
> sizeof(UNICODE_NULL
))
2233 ClassDescription
[ClassDescriptionSize
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2238 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2243 /***********************************************************************
2244 * SetupDiGetClassDevsA (SETUPAPI.@)
2246 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2252 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2253 flags
, NULL
, NULL
, NULL
);
2256 /***********************************************************************
2257 * SetupDiGetClassDevsExA (SETUPAPI.@)
2259 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2269 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2273 enumstrW
= MultiByteToUnicode(enumstr
, CP_ACP
);
2276 ret
= INVALID_HANDLE_VALUE
;
2282 machineW
= MultiByteToUnicode(machine
, CP_ACP
);
2286 ret
= INVALID_HANDLE_VALUE
;
2290 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2291 machineW
, reserved
);
2299 /***********************************************************************
2300 * SetupDiGetClassDevsW (SETUPAPI.@)
2302 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2308 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2312 /***********************************************************************
2313 * SetupDiGetClassDevsExW (SETUPAPI.@)
2315 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2324 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2325 struct DeviceInfoSet
*list
;
2326 CONST GUID
*pClassGuid
;
2328 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2330 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2331 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2334 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2336 SetLastError(ERROR_INVALID_PARAMETER
);
2340 /* Create the deviceset if not set */
2343 list
= (struct DeviceInfoSet
*)deviceset
;
2344 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2346 SetLastError(ERROR_INVALID_HANDLE
);
2349 hDeviceInfo
= deviceset
;
2353 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2354 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2355 NULL
, machine
, NULL
);
2356 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2358 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2361 if (flags
& DIGCF_PROFILE
)
2362 FIXME(": flag DIGCF_PROFILE ignored\n");
2364 if (flags
& DIGCF_DEVICEINTERFACE
)
2368 SetLastError(ERROR_INVALID_PARAMETER
);
2371 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2375 /* Determine which class(es) should be included in the deviceset */
2376 if (flags
& DIGCF_ALLCLASSES
)
2378 /* The caller wants all classes. Check if
2379 * the deviceset limits us to one class */
2380 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2383 pClassGuid
= &list
->ClassGuid
;
2387 /* The caller wants one class. Check if it matches deviceset class */
2388 if (IsEqualIID(&list
->ClassGuid
, class)
2389 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2395 SetLastError(ERROR_INVALID_PARAMETER
);
2399 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2401 /* No class specified. Try to use the one of the deviceset */
2402 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2403 pClassGuid
= &list
->ClassGuid
;
2406 SetLastError(ERROR_INVALID_PARAMETER
);
2412 SetLastError(ERROR_INVALID_PARAMETER
);
2415 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2417 if (rc
!= ERROR_SUCCESS
)
2425 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2426 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2430 /***********************************************************************
2431 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2433 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2434 HDEVINFO DeviceInfoSet
,
2435 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2437 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2439 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2441 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2443 SetLastError(ERROR_INVALID_HANDLE
);
2446 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2448 SetLastError(ERROR_INVALID_HANDLE
);
2452 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2454 SetLastError(ERROR_INVALID_PARAMETER
);
2457 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2458 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2459 if (set
->MachineName
)
2462 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2466 DevInfoData
->RemoteMachineName
[0] = 0;
2471 /***********************************************************************
2472 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2474 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2475 HDEVINFO DeviceInfoSet
,
2476 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2478 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2480 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2482 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2484 SetLastError(ERROR_INVALID_HANDLE
);
2487 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2489 SetLastError(ERROR_INVALID_HANDLE
);
2493 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2495 SetLastError(ERROR_INVALID_PARAMETER
);
2498 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2499 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2500 if (set
->MachineName
)
2501 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2503 DevInfoData
->RemoteMachineName
[0] = 0;
2508 /***********************************************************************
2509 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2511 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2512 HDEVINFO DeviceInfoSet
,
2513 PSP_DEVINFO_DATA DeviceInfoData
,
2514 const GUID
*InterfaceClassGuid
,
2515 PCSTR ReferenceString
,
2516 DWORD CreationFlags
,
2517 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2520 LPWSTR ReferenceStringW
= NULL
;
2522 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2523 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2524 CreationFlags
, DeviceInterfaceData
);
2526 if (ReferenceString
)
2528 ReferenceStringW
= MultiByteToUnicode(ReferenceString
, CP_ACP
);
2529 if (ReferenceStringW
== NULL
) return FALSE
;
2532 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2533 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2534 DeviceInterfaceData
);
2536 MyFree(ReferenceStringW
);
2541 /***********************************************************************
2542 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2544 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2545 HDEVINFO DeviceInfoSet
,
2546 PSP_DEVINFO_DATA DeviceInfoData
,
2547 const GUID
*InterfaceClassGuid
,
2548 PCWSTR ReferenceString
,
2549 DWORD CreationFlags
,
2550 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2552 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2553 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2554 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2555 CreationFlags
, DeviceInterfaceData
);
2557 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2559 SetLastError(ERROR_INVALID_HANDLE
);
2562 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2564 SetLastError(ERROR_INVALID_HANDLE
);
2567 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2568 || !DeviceInfoData
->Reserved
)
2570 SetLastError(ERROR_INVALID_PARAMETER
);
2573 if (!InterfaceClassGuid
)
2575 SetLastError(ERROR_INVALID_USER_BUFFER
);
2579 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2580 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2581 CreationFlags
, DeviceInterfaceData
);
2582 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2586 /***********************************************************************
2587 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2589 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2590 HDEVINFO DeviceInfoSet
,
2591 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2595 PCSTR InfSectionName
)
2598 PWSTR InfSectionNameW
= NULL
;
2600 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2601 samDesired
, InfHandle
, InfSectionName
);
2604 if (!InfSectionName
)
2606 SetLastError(ERROR_INVALID_PARAMETER
);
2607 return INVALID_HANDLE_VALUE
;
2609 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
2610 if (!InfSectionNameW
)
2611 return INVALID_HANDLE_VALUE
;
2613 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2614 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2616 MyFree(InfSectionNameW
);
2620 /***********************************************************************
2621 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2623 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2624 HDEVINFO DeviceInfoSet
,
2625 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2629 PCWSTR InfSectionName
)
2631 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2632 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2633 samDesired
, InfHandle
, InfSectionName
);
2635 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2636 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2638 SetLastError(ERROR_INVALID_HANDLE
);
2639 return INVALID_HANDLE_VALUE
;
2641 if (!DeviceInterfaceData
||
2642 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2643 !DeviceInterfaceData
->Reserved
)
2645 SetLastError(ERROR_INVALID_PARAMETER
);
2646 return INVALID_HANDLE_VALUE
;
2648 if (InfHandle
&& !InfSectionName
)
2650 SetLastError(ERROR_INVALID_PARAMETER
);
2651 return INVALID_HANDLE_VALUE
;
2654 FIXME("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2655 samDesired
, InfHandle
, InfSectionName
);
2656 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2657 return INVALID_HANDLE_VALUE
;
2660 /***********************************************************************
2661 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2663 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2664 HDEVINFO DeviceInfoSet
,
2665 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2668 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2671 TRACE("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2673 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2674 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2676 SetLastError(ERROR_INVALID_HANDLE
);
2679 if (!DeviceInterfaceData
||
2680 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2681 !DeviceInterfaceData
->Reserved
)
2683 SetLastError(ERROR_INVALID_PARAMETER
);
2687 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2688 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2692 /***********************************************************************
2693 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2696 * DeviceInfoSet [I] Set of devices from which to enumerate
2698 * DeviceInfoData [I] (Optional) If specified, a specific device
2699 * instance from which to enumerate interfaces.
2700 * If it isn't specified, all interfaces for all
2701 * devices in the set are enumerated.
2702 * InterfaceClassGuid [I] The interface class to enumerate.
2703 * MemberIndex [I] An index of the interface instance to enumerate.
2704 * A caller should start with MemberIndex set to 0,
2705 * and continue until the function fails with
2706 * ERROR_NO_MORE_ITEMS.
2707 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2708 * member must be set to
2709 * sizeof(SP_DEVICE_INTERFACE_DATA).
2712 * Success: non-zero value.
2713 * Failure: FALSE. Call GetLastError() for more info.
2715 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2716 HDEVINFO DeviceInfoSet
,
2717 PSP_DEVINFO_DATA DeviceInfoData
,
2718 CONST GUID
* InterfaceClassGuid
,
2720 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2722 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2725 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet
, DeviceInfoData
,
2726 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2728 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2729 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2731 SetLastError(ERROR_INVALID_HANDLE
);
2734 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2735 !DeviceInfoData
->Reserved
))
2737 SetLastError(ERROR_INVALID_PARAMETER
);
2740 if (!DeviceInterfaceData
||
2741 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2743 SetLastError(ERROR_INVALID_PARAMETER
);
2748 struct DeviceInfo
*devInfo
=
2749 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2751 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2752 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2754 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2755 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2757 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2760 if (MemberIndex
-- == 0)
2762 /* return this item */
2763 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2764 &DevItf
->InterfaceClassGuid
,
2766 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2767 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2771 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2774 SetLastError(ERROR_NO_MORE_ITEMS
);
2779 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
2780 while (ItemList
!= &set
->ListHead
&& !found
)
2782 PLIST_ENTRY InterfaceListEntry
;
2783 struct DeviceInfo
*devInfo
=
2784 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
2785 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2786 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2788 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2789 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2791 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2794 if (MemberIndex
-- == 0)
2796 /* return this item */
2797 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2798 &DevItf
->InterfaceClassGuid
,
2800 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2801 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2805 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2807 ItemList
= ItemList
->Flink
;
2811 SetLastError(ERROR_NO_MORE_ITEMS
);
2816 /***********************************************************************
2817 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2819 * Destroy a DeviceInfoList and free all used memory of the list.
2822 * devinfo [I] DeviceInfoList pointer to list to destroy
2825 * Success: non zero value.
2826 * Failure: zero value.
2828 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2832 TRACE("%p\n", devinfo
);
2833 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
2835 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2837 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
2839 ret
= DestroyDeviceInfoSet(list
);
2844 SetLastError(ERROR_INVALID_HANDLE
);
2849 /***********************************************************************
2850 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2852 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2853 HDEVINFO DeviceInfoSet
,
2854 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2855 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2856 DWORD DeviceInterfaceDetailDataSize
,
2857 PDWORD RequiredSize
,
2858 PSP_DEVINFO_DATA DeviceInfoData
)
2860 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2861 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2862 DWORD sizeW
= 0, bytesNeeded
;
2865 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
2866 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2867 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2869 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2870 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2872 SetLastError(ERROR_INVALID_HANDLE
);
2875 if (!DeviceInterfaceData
||
2876 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2877 !DeviceInterfaceData
->Reserved
)
2879 SetLastError(ERROR_INVALID_PARAMETER
);
2882 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
<
2883 FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1 ||
2884 DeviceInterfaceDetailData
->cbSize
> sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
2886 SetLastError(ERROR_INVALID_USER_BUFFER
);
2889 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2891 SetLastError(ERROR_INVALID_USER_BUFFER
);
2896 if (DeviceInterfaceDetailData
!= NULL
)
2898 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2899 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2900 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
2901 if (!DeviceInterfaceDetailDataW
)
2903 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2906 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2908 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2909 ret
= SetupDiGetDeviceInterfaceDetailW(
2911 DeviceInterfaceData
,
2912 DeviceInterfaceDetailDataW
,
2916 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2917 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2919 *RequiredSize
= bytesNeeded
;
2920 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= bytesNeeded
)
2922 if (!WideCharToMultiByte(
2924 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2925 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2932 MyFree(DeviceInterfaceDetailDataW
);
2937 /***********************************************************************
2938 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2940 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2941 HDEVINFO DeviceInfoSet
,
2942 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2943 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2944 DWORD DeviceInterfaceDetailDataSize
,
2945 PDWORD RequiredSize
,
2946 PSP_DEVINFO_DATA DeviceInfoData
)
2948 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2951 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
2952 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2953 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2955 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2956 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2958 SetLastError(ERROR_INVALID_HANDLE
);
2961 if (!DeviceInterfaceData
||
2962 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2963 !DeviceInterfaceData
->Reserved
)
2965 SetLastError(ERROR_INVALID_PARAMETER
);
2968 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2970 SetLastError(ERROR_INVALID_USER_BUFFER
);
2973 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2975 SetLastError(ERROR_INVALID_USER_BUFFER
);
2978 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2980 SetLastError(ERROR_INVALID_PARAMETER
);
2983 if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2985 SetLastError(ERROR_INVALID_PARAMETER
);
2990 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2991 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2992 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2993 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2995 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2997 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2999 *RequiredSize
= sizeRequired
;
3003 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3004 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3007 memcpy(&DeviceInfoData
->ClassGuid
,
3008 &deviceInterface
->DeviceInfo
->ClassGuid
,
3010 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3011 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3019 struct PropertyMapEntry
3026 static struct PropertyMapEntry PropertyMap
[] = {
3027 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3028 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3029 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3030 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3031 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3032 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3033 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3034 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3035 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3036 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3037 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3038 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3039 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3040 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3041 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3042 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3043 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3044 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3045 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3046 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3047 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3048 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3049 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3050 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3051 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3052 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3053 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3054 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3055 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3056 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3057 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3058 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3059 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3060 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3061 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3064 /***********************************************************************
3065 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3067 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3068 HDEVINFO DeviceInfoSet
,
3069 PSP_DEVINFO_DATA DeviceInfoData
,
3071 PDWORD PropertyRegDataType
,
3072 PBYTE PropertyBuffer
,
3073 DWORD PropertyBufferSize
,
3074 PDWORD RequiredSize
)
3077 BOOL bIsStringProperty
;
3079 DWORD RequiredSizeA
, RequiredSizeW
;
3080 DWORD PropertyBufferSizeW
= 0;
3081 PBYTE PropertyBufferW
= NULL
;
3083 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3084 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3087 if (PropertyBufferSize
!= 0)
3089 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3090 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3091 if (!PropertyBufferW
)
3093 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3098 ret
= SetupDiGetDeviceRegistryPropertyW(
3104 PropertyBufferSizeW
,
3107 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3109 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
3111 if (bIsStringProperty
)
3112 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
3114 RequiredSizeA
= RequiredSizeW
;
3116 *RequiredSize
= RequiredSizeA
;
3117 if (PropertyRegDataType
)
3118 *PropertyRegDataType
= RegType
;
3123 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3127 if (RequiredSizeA
<= PropertyBufferSize
)
3129 if (bIsStringProperty
&& PropertyBufferSize
> 0)
3131 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
3133 /* Last error is already set by WideCharToMultiByte */
3138 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
3142 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3146 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3150 /***********************************************************************
3151 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3153 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3154 HDEVINFO DeviceInfoSet
,
3155 PSP_DEVINFO_DATA DeviceInfoData
,
3157 PDWORD PropertyRegDataType
,
3158 PBYTE PropertyBuffer
,
3159 DWORD PropertyBufferSize
,
3160 PDWORD RequiredSize
)
3163 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3164 struct DeviceInfo
*devInfo
;
3166 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3167 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3170 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3172 SetLastError(ERROR_INVALID_HANDLE
);
3175 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3177 SetLastError(ERROR_INVALID_HANDLE
);
3180 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3181 || !DeviceInfoData
->Reserved
)
3183 SetLastError(ERROR_INVALID_PARAMETER
);
3186 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3187 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3188 && PropertyMap
[Property
].nameW
)
3190 DWORD size
= PropertyBufferSize
;
3193 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_QUERY_VALUE
);
3194 if (hKey
== INVALID_HANDLE_VALUE
)
3196 l
= RegQueryValueExW(hKey
, PropertyMap
[Property
].nameW
,
3197 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3201 *RequiredSize
= size
;
3204 if (PropertyBuffer
!= NULL
|| size
== 0)
3207 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3209 case ERROR_MORE_DATA
:
3210 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3216 else if (Property
== SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
)
3218 DWORD required
= (strlenW(devInfo
->Data
) + 1) * sizeof(WCHAR
);
3220 if (PropertyRegDataType
)
3221 *PropertyRegDataType
= REG_SZ
;
3223 *RequiredSize
= required
;
3224 if (PropertyBufferSize
>= required
)
3226 strcpyW((LPWSTR
)PropertyBuffer
, devInfo
->Data
);
3230 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3234 ERR("Property 0x%lx not implemented\n", Property
);
3235 SetLastError(ERROR_NOT_SUPPORTED
);
3240 /***********************************************************************
3241 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3243 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3244 HDEVINFO DeviceInfoSet
,
3245 PSP_DEVINFO_DATA DeviceInfoData
,
3247 const BYTE
*PropertyBuffer
,
3248 DWORD PropertyBufferSize
)
3251 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3253 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3254 PropertyBuffer
, PropertyBufferSize
);
3256 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3258 SetLastError(ERROR_INVALID_HANDLE
);
3261 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3263 SetLastError(ERROR_INVALID_HANDLE
);
3266 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3267 || !DeviceInfoData
->Reserved
)
3269 SetLastError(ERROR_INVALID_PARAMETER
);
3273 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3274 Property
, PropertyBuffer
, PropertyBufferSize
);
3275 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3279 /***********************************************************************
3280 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3282 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3283 HDEVINFO DeviceInfoSet
,
3284 PSP_DEVINFO_DATA DeviceInfoData
,
3286 const BYTE
*PropertyBuffer
,
3287 DWORD PropertyBufferSize
)
3290 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3292 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3293 PropertyBuffer
, PropertyBufferSize
);
3295 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3297 SetLastError(ERROR_INVALID_HANDLE
);
3300 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3302 SetLastError(ERROR_INVALID_HANDLE
);
3305 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3306 || !DeviceInfoData
->Reserved
)
3308 SetLastError(ERROR_INVALID_PARAMETER
);
3311 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3312 && PropertyMap
[Property
].nameW
)
3316 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3317 if (hKey
== INVALID_HANDLE_VALUE
)
3319 /* Write new data */
3321 hKey
, PropertyMap
[Property
].nameW
, 0,
3322 PropertyMap
[Property
].regType
, PropertyBuffer
,
3323 PropertyBufferSize
);
3332 ERR("Property 0x%lx not implemented\n", Property
);
3333 SetLastError(ERROR_NOT_SUPPORTED
);
3336 TRACE("Returning %d\n", ret
);
3340 /***********************************************************************
3341 * SetupDiInstallClassA (SETUPAPI.@)
3343 BOOL WINAPI
SetupDiInstallClassA(
3349 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3352 /***********************************************************************
3353 * SetupDiInstallClassExA (SETUPAPI.@)
3356 SetupDiInstallClassExA(
3357 IN HWND hwndParent OPTIONAL
,
3358 IN PCSTR InfFileName OPTIONAL
,
3360 IN HSPFILEQ FileQueue OPTIONAL
,
3361 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3365 PWSTR InfFileNameW
= NULL
;
3370 SetLastError(ERROR_INVALID_PARAMETER
);
3375 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3376 if (InfFileNameW
== NULL
)
3378 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3383 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3384 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3386 MyFree(InfFileNameW
);
3391 HKEY
SETUP_CreateClassKey(HINF hInf
)
3393 static const WCHAR slash
[] = { '\\',0 };
3394 WCHAR FullBuffer
[MAX_PATH
];
3395 WCHAR Buffer
[MAX_PATH
];
3399 if (!SetupGetLineTextW(NULL
,
3407 return INVALID_HANDLE_VALUE
;
3410 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3411 lstrcatW(FullBuffer
, slash
);
3412 lstrcatW(FullBuffer
, Buffer
);
3414 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3420 if (!SetupGetLineTextW(NULL
,
3428 return INVALID_HANDLE_VALUE
;
3431 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3435 REG_OPTION_NON_VOLATILE
,
3441 return INVALID_HANDLE_VALUE
;
3446 if (RegSetValueExW(hClassKey
,
3451 RequiredSize
* sizeof(WCHAR
)))
3453 RegCloseKey(hClassKey
);
3454 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3456 return INVALID_HANDLE_VALUE
;
3462 /***********************************************************************
3463 * SetupDiInstallClassW (SETUPAPI.@)
3465 BOOL WINAPI
SetupDiInstallClassW(
3471 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3475 /***********************************************************************
3476 * SetupDiOpenClassRegKey (SETUPAPI.@)
3478 HKEY WINAPI
SetupDiOpenClassRegKey(
3479 const GUID
* ClassGuid
,
3482 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3483 DIOCR_INSTALLER
, NULL
, NULL
);
3487 /***********************************************************************
3488 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3490 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3491 const GUID
* ClassGuid
,
3497 PWSTR MachineNameW
= NULL
;
3500 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3501 Flags
, debugstr_a(MachineName
), Reserved
);
3505 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3506 if (MachineNameW
== NULL
)
3507 return INVALID_HANDLE_VALUE
;
3510 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3511 Flags
, MachineNameW
, Reserved
);
3513 MyFree(MachineNameW
);
3519 /***********************************************************************
3520 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3522 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3523 const GUID
* ClassGuid
,
3535 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3536 Flags
, debugstr_w(MachineName
), Reserved
);
3538 if (MachineName
!= NULL
)
3540 l
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3541 if (l
!= ERROR_SUCCESS
)
3544 return INVALID_HANDLE_VALUE
;
3548 HKLM
= HKEY_LOCAL_MACHINE
;
3550 if (Flags
== DIOCR_INSTALLER
)
3552 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3554 else if (Flags
== DIOCR_INTERFACE
)
3556 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3560 ERR("Invalid Flags parameter!\n");
3561 SetLastError(ERROR_INVALID_FLAGS
);
3562 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3563 return INVALID_HANDLE_VALUE
;
3568 if ((l
= RegOpenKeyExW(HKLM
,
3574 SetLastError(ERROR_INVALID_CLASS
);
3575 hClassesKey
= INVALID_HANDLE_VALUE
;
3577 if (MachineName
!= NULL
)
3583 WCHAR bracedGuidString
[39];
3585 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3587 if (!(l
= RegOpenKeyExW(HKLM
,
3593 if (MachineName
!= NULL
)
3596 if ((l
= RegOpenKeyExW(hClassesKey
,
3603 key
= INVALID_HANDLE_VALUE
;
3605 RegCloseKey(hClassesKey
);
3609 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3611 key
= INVALID_HANDLE_VALUE
;
3617 /***********************************************************************
3618 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3620 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3621 HDEVINFO DeviceInfoSet
,
3624 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3626 FIXME("%p %s %08x %p\n",
3627 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3631 /***********************************************************************
3632 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3634 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3635 HDEVINFO DeviceInfoSet
,
3638 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3640 LPWSTR DevicePathW
= NULL
;
3643 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3645 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3646 if (DevicePathW
== NULL
)
3649 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3650 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3652 MyFree(DevicePathW
);
3657 /***********************************************************************
3658 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3660 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3661 HDEVINFO DeviceInfoSet
,
3662 PSP_DEVINFO_DATA DeviceInfoData
,
3663 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3664 DWORD ClassInstallParamsSize
)
3666 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
3667 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3672 IntSetupDiRegisterDeviceInfo(
3673 IN HDEVINFO DeviceInfoSet
,
3674 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3676 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
3679 /***********************************************************************
3680 * SetupDiCallClassInstaller (SETUPAPI.@)
3682 BOOL WINAPI
SetupDiCallClassInstaller(
3683 DI_FUNCTION InstallFunction
,
3684 HDEVINFO DeviceInfoSet
,
3685 PSP_DEVINFO_DATA DeviceInfoData
)
3689 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3692 SetLastError(ERROR_INVALID_PARAMETER
);
3693 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3694 SetLastError(ERROR_INVALID_HANDLE
);
3695 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3696 SetLastError(ERROR_INVALID_HANDLE
);
3697 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3698 SetLastError(ERROR_INVALID_HANDLE
);
3699 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3700 SetLastError(ERROR_INVALID_USER_BUFFER
);
3703 SP_DEVINSTALL_PARAMS_W InstallParams
;
3704 #define CLASS_COINSTALLER 0x1
3705 #define DEVICE_COINSTALLER 0x2
3706 #define CLASS_INSTALLER 0x4
3707 UCHAR CanHandle
= 0;
3708 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3710 switch (InstallFunction
)
3712 case DIF_ADDPROPERTYPAGE_ADVANCED
:
3713 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3715 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
3716 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3718 case DIF_ALLOW_INSTALL
:
3719 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3722 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3724 case DIF_DESTROYPRIVATEDATA
:
3725 CanHandle
= CLASS_INSTALLER
;
3727 case DIF_INSTALLDEVICE
:
3728 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3729 DefaultHandler
= SetupDiInstallDevice
;
3731 case DIF_INSTALLDEVICEFILES
:
3732 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3733 DefaultHandler
= SetupDiInstallDriverFiles
;
3735 case DIF_INSTALLINTERFACES
:
3736 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3737 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3739 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3740 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3742 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3743 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3745 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3746 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3748 case DIF_NEWDEVICEWIZARD_PRESELECT
:
3749 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3751 case DIF_NEWDEVICEWIZARD_SELECT
:
3752 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3754 case DIF_POWERMESSAGEWAKE
:
3755 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3757 case DIF_PROPERTYCHANGE
:
3758 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3759 DefaultHandler
= SetupDiChangeState
;
3761 case DIF_REGISTER_COINSTALLERS
:
3762 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3763 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3765 case DIF_REGISTERDEVICE
:
3766 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3767 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
3770 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3771 DefaultHandler
= SetupDiRemoveDevice
;
3773 case DIF_SELECTBESTCOMPATDRV
:
3774 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3775 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3777 case DIF_SELECTDEVICE
:
3778 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3779 DefaultHandler
= SetupDiSelectDevice
;
3781 case DIF_TROUBLESHOOTER
:
3782 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3785 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3786 DefaultHandler
= SetupDiUnremoveDevice
;
3789 ERR("Install function %u not supported\n", InstallFunction
);
3790 SetLastError(ERROR_NOT_SUPPORTED
);
3793 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3794 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3795 /* Don't process this call, as a parameter is invalid */
3800 LIST_ENTRY ClassCoInstallersListHead
;
3801 LIST_ENTRY DeviceCoInstallersListHead
;
3802 HMODULE ClassInstallerLibrary
= NULL
;
3803 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3804 COINSTALLER_CONTEXT_DATA Context
;
3805 PLIST_ENTRY ListEntry
;
3807 DWORD dwRegType
, dwLength
;
3808 DWORD rc
= NO_ERROR
;
3810 InitializeListHead(&ClassCoInstallersListHead
);
3811 InitializeListHead(&DeviceCoInstallersListHead
);
3813 if (CanHandle
& DEVICE_COINSTALLER
)
3815 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3816 if (hKey
!= INVALID_HANDLE_VALUE
)
3818 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3819 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3821 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3822 if (KeyBuffer
!= NULL
)
3824 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3825 if (rc
== ERROR_SUCCESS
)
3828 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3830 /* Add coinstaller to DeviceCoInstallersListHead list */
3831 struct CoInstallerElement
*coinstaller
;
3832 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3833 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3836 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
3837 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3838 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3840 HeapFree(GetProcessHeap(), 0, coinstaller
);
3843 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3849 if (CanHandle
& CLASS_COINSTALLER
)
3853 REGSTR_PATH_CODEVICEINSTALLERS
,
3857 if (rc
== ERROR_SUCCESS
)
3859 LPWSTR lpGuidString
;
3860 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3862 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3863 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3865 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3866 if (KeyBuffer
!= NULL
)
3868 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3869 if (rc
== ERROR_SUCCESS
)
3872 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3874 /* Add coinstaller to ClassCoInstallersListHead list */
3875 struct CoInstallerElement
*coinstaller
;
3876 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3877 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3880 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
3881 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3882 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3884 HeapFree(GetProcessHeap(), 0, coinstaller
);
3887 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3890 RpcStringFreeW(&lpGuidString
);
3895 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3897 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3898 if (hKey
!= INVALID_HANDLE_VALUE
)
3900 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3901 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3903 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3904 if (KeyBuffer
!= NULL
)
3906 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3907 if (rc
== ERROR_SUCCESS
)
3909 /* Get ClassInstaller function pointer */
3910 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3911 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3913 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3914 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3917 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3924 /* Call Class co-installers */
3925 Context
.PostProcessing
= FALSE
;
3927 ListEntry
= ClassCoInstallersListHead
.Flink
;
3928 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3930 struct CoInstallerElement
*coinstaller
;
3931 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
3932 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3933 coinstaller
->PrivateData
= Context
.PrivateData
;
3934 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3936 coinstaller
->DoPostProcessing
= TRUE
;
3939 ListEntry
= ListEntry
->Flink
;
3942 /* Call Device co-installers */
3943 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3944 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3946 struct CoInstallerElement
*coinstaller
;
3947 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
3948 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3949 coinstaller
->PrivateData
= Context
.PrivateData
;
3950 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3952 coinstaller
->DoPostProcessing
= TRUE
;
3955 ListEntry
= ListEntry
->Flink
;
3958 /* Call Class installer */
3961 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3962 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3965 rc
= ERROR_DI_DO_DEFAULT
;
3967 /* Call default handler */
3968 if (rc
== ERROR_DI_DO_DEFAULT
)
3970 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3972 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3975 rc
= GetLastError();
3981 /* Call Class co-installers that required postprocessing */
3982 Context
.PostProcessing
= TRUE
;
3983 ListEntry
= ClassCoInstallersListHead
.Flink
;
3984 while (ListEntry
!= &ClassCoInstallersListHead
)
3986 struct CoInstallerElement
*coinstaller
;
3987 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
3988 if (coinstaller
->DoPostProcessing
)
3990 Context
.InstallResult
= rc
;
3991 Context
.PrivateData
= coinstaller
->PrivateData
;
3992 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3994 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3995 ListEntry
= ListEntry
->Flink
;
3998 /* Call Device co-installers that required postprocessing */
3999 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4000 while (ListEntry
!= &DeviceCoInstallersListHead
)
4002 struct CoInstallerElement
*coinstaller
;
4003 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4004 if (coinstaller
->DoPostProcessing
)
4006 Context
.InstallResult
= rc
;
4007 Context
.PrivateData
= coinstaller
->PrivateData
;
4008 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4010 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4011 ListEntry
= ListEntry
->Flink
;
4014 /* Free allocated memory */
4015 while (!IsListEmpty(&ClassCoInstallersListHead
))
4017 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4018 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4020 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4022 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4023 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4026 ret
= (rc
== NO_ERROR
);
4030 TRACE("Returning %d\n", ret
);
4034 /***********************************************************************
4035 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4037 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4038 HDEVINFO DeviceInfoSet
,
4039 PSP_DEVINFO_DATA DeviceInfoData
,
4040 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4042 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4045 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4047 if (DeviceInstallParams
== NULL
)
4048 SetLastError(ERROR_INVALID_PARAMETER
);
4049 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4050 SetLastError(ERROR_INVALID_USER_BUFFER
);
4053 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4054 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4058 /* Do W->A conversion */
4060 DeviceInstallParams
,
4061 &deviceInstallParamsW
,
4062 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4063 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4064 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4066 DeviceInstallParams
->DriverPath
[0] = '\0';
4072 TRACE("Returning %d\n", ret
);
4076 /***********************************************************************
4077 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4080 SetupDiGetDeviceInfoListClass(
4081 IN HDEVINFO DeviceInfoSet
,
4082 OUT LPGUID ClassGuid
)
4084 struct DeviceInfoSet
*list
;
4087 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4090 SetLastError(ERROR_INVALID_HANDLE
);
4091 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4092 SetLastError(ERROR_INVALID_HANDLE
);
4093 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4094 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4097 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4102 TRACE("Returning %d\n", ret
);
4106 /***********************************************************************
4107 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4110 SetupDiGetDeviceInstallParamsW(
4111 IN HDEVINFO DeviceInfoSet
,
4112 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4113 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4115 struct DeviceInfoSet
*list
;
4118 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4121 SetLastError(ERROR_INVALID_HANDLE
);
4122 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4123 SetLastError(ERROR_INVALID_HANDLE
);
4124 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4125 SetLastError(ERROR_INVALID_USER_BUFFER
);
4126 else if (!DeviceInstallParams
)
4127 SetLastError(ERROR_INVALID_PARAMETER
);
4128 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4129 SetLastError(ERROR_INVALID_USER_BUFFER
);
4132 PSP_DEVINSTALL_PARAMS_W Source
;
4135 Source
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4137 Source
= &list
->InstallParams
;
4143 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4145 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4147 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4153 TRACE("Returning %d\n", ret
);
4158 CheckDeviceInstallParameters(
4159 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4161 DWORD SupportedFlags
=
4162 DI_NOVCP
| /* 0x00000008 */
4163 DI_DIDCOMPAT
| /* 0x00000010 */
4164 DI_DIDCLASS
| /* 0x00000020 */
4165 DI_NEEDRESTART
| /* 0x00000080 */
4166 DI_NEEDREBOOT
| /* 0x00000100 */
4167 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4168 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4169 DI_ENUMSINGLEINF
| /* 0x00010000 */
4170 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
4171 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4172 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4173 DI_QUIETINSTALL
| /* 0x00800000 */
4174 DI_NOFILECOPY
| /* 0x01000000 */
4175 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4176 DWORD SupportedFlagsEx
=
4177 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4178 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4179 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4180 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4181 DI_FLAGSEX_NO_DRVREG_MODIFY
| /* 0x00008000 */
4182 DI_FLAGSEX_INSTALLEDDRIVER
; /* 0x04000000 */
4185 /* FIXME: add support for more flags */
4187 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4188 * It should be checked before accessing to other values
4189 * of the SP_DEVINSTALL_PARAMS structure */
4191 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4193 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4194 SetLastError(ERROR_INVALID_FLAGS
);
4196 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4198 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4199 SetLastError(ERROR_INVALID_FLAGS
);
4201 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4202 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4203 SetLastError(ERROR_INVALID_USER_BUFFER
);
4206 /* FIXME: check Reserved field */
4213 /***********************************************************************
4214 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4217 SetupDiSetDeviceInstallParamsW(
4218 IN HDEVINFO DeviceInfoSet
,
4219 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4220 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4222 struct DeviceInfoSet
*list
;
4225 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4228 SetLastError(ERROR_INVALID_HANDLE
);
4229 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4230 SetLastError(ERROR_INVALID_HANDLE
);
4231 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4232 SetLastError(ERROR_INVALID_USER_BUFFER
);
4233 else if (!DeviceInstallParams
)
4234 SetLastError(ERROR_INVALID_PARAMETER
);
4235 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4236 SetLastError(ERROR_INVALID_USER_BUFFER
);
4237 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4239 PSP_DEVINSTALL_PARAMS_W Destination
;
4242 Destination
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4244 Destination
= &list
->InstallParams
;
4245 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4249 TRACE("Returning %d\n", ret
);
4253 BOOL WINAPI
SetupDiSetDeviceInstallParamsA(
4254 HDEVINFO DeviceInfoSet
,
4255 PSP_DEVINFO_DATA DeviceInfoData
,
4256 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4258 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4262 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4264 if (DeviceInstallParams
== NULL
)
4265 SetLastError(ERROR_INVALID_PARAMETER
);
4266 else if (DeviceInstallParams
->cbSize
< sizeof(SP_DEVINSTALL_PARAMS_A
))
4267 SetLastError(ERROR_INVALID_USER_BUFFER
);
4270 memcpy(&deviceInstallParamsW
, DeviceInstallParams
, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A
, DriverPath
));
4271 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4272 len
= MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, NULL
, 0);
4275 ERR("DrivePath is NULL\n");
4280 MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, deviceInstallParamsW
.DriverPath
, len
);
4281 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4285 TRACE("Returning %d\n", ret
);
4290 OpenHardwareProfileKey(
4293 IN DWORD samDesired
)
4295 HKEY hHWProfilesKey
= NULL
;
4296 HKEY hHWProfileKey
= NULL
;
4297 HKEY ret
= INVALID_HANDLE_VALUE
;
4300 rc
= RegOpenKeyExW(HKLM
,
4301 REGSTR_PATH_HWPROFILES
,
4305 if (rc
!= ERROR_SUCCESS
)
4322 snprintfW(subKey
, 4, InstanceKeyFormat
, HwProfile
);
4331 if (rc
!= ERROR_SUCCESS
)
4336 ret
= hHWProfileKey
;
4339 if (hHWProfilesKey
!= NULL
)
4340 RegCloseKey(hHWProfilesKey
);
4341 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4342 RegCloseKey(hHWProfileKey
);
4346 /***********************************************************************
4347 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4350 SetupDiDeleteDeviceInfo(
4351 IN HDEVINFO DeviceInfoSet
,
4352 IN PSP_DEVINFO_DATA DeviceInfoData
)
4354 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4356 FIXME("not implemented\n");
4357 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4362 /***********************************************************************
4363 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4366 SetupDiOpenDeviceInfoA(
4367 IN HDEVINFO DeviceInfoSet
,
4368 IN PCSTR DeviceInstanceId
,
4369 IN HWND hwndParent OPTIONAL
,
4371 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4373 LPWSTR DeviceInstanceIdW
= NULL
;
4376 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4378 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4379 if (DeviceInstanceIdW
== NULL
)
4382 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4383 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4385 MyFree(DeviceInstanceIdW
);
4391 /***********************************************************************
4392 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4395 SetupDiOpenDeviceInfoW(
4396 IN HDEVINFO DeviceInfoSet
,
4397 IN PCWSTR DeviceInstanceId
,
4398 IN HWND hwndParent OPTIONAL
,
4400 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4402 struct DeviceInfoSet
*list
;
4403 HKEY hEnumKey
, hKey
= NULL
;
4407 TRACE("%p %s %p %lx %p\n",
4408 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
4409 hwndParent
, OpenFlags
, DeviceInfoData
);
4411 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4412 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4415 SetLastError(ERROR_INVALID_HANDLE
);
4416 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4417 SetLastError(ERROR_INVALID_HANDLE
);
4418 else if (!DeviceInstanceId
)
4419 SetLastError(ERROR_INVALID_PARAMETER
);
4420 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4422 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4423 SetLastError(ERROR_INVALID_FLAGS
);
4425 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4426 SetLastError(ERROR_INVALID_USER_BUFFER
);
4429 struct DeviceInfo
*deviceInfo
= NULL
;
4430 /* Search if device already exists in DeviceInfoSet.
4431 * If yes, return the existing element
4432 * If no, create a new element using information in registry
4434 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4435 while (ItemList
!= &list
->ListHead
)
4440 FIXME("not implemented\n");
4441 ItemList
= ItemList
->Flink
;
4446 /* good one found */
4452 WCHAR szClassGuid
[MAX_GUID_STRING_LEN
];
4454 /* Open supposed registry key */
4457 REGSTR_PATH_SYSTEMENUM
,
4461 if (rc
!= ERROR_SUCCESS
)
4472 RegCloseKey(hEnumKey
);
4473 if (rc
!= ERROR_SUCCESS
)
4475 if (rc
== ERROR_FILE_NOT_FOUND
)
4476 rc
= ERROR_NO_SUCH_DEVINST
;
4481 ClassGUID
= GUID_NULL
;
4482 dwSize
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
4484 if (RegQueryValueExW(hKey
,
4485 REGSTR_VAL_CLASSGUID
,
4488 (LPBYTE
)szClassGuid
,
4489 &dwSize
) == ERROR_SUCCESS
)
4491 szClassGuid
[MAX_GUID_STRING_LEN
- 2] = UNICODE_NULL
;
4493 /* Convert a string to a ClassGuid */
4494 UuidFromStringW(&szClassGuid
[1], &ClassGUID
);
4497 if (!CreateDeviceInfo(list
, DeviceInstanceId
, &ClassGUID
, &deviceInfo
))
4500 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4505 if (ret
&& deviceInfo
&& DeviceInfoData
)
4507 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4508 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4509 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4520 /***********************************************************************
4521 * SetupDiGetSelectedDevice (SETUPAPI.@)
4524 SetupDiGetSelectedDevice(
4525 IN HDEVINFO DeviceInfoSet
,
4526 OUT PSP_DEVINFO_DATA DeviceInfoData
)
4528 struct DeviceInfoSet
*list
;
4531 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4534 SetLastError(ERROR_INVALID_HANDLE
);
4535 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4536 SetLastError(ERROR_INVALID_HANDLE
);
4537 else if (list
->SelectedDevice
== NULL
)
4538 SetLastError(ERROR_NO_DEVICE_SELECTED
);
4539 else if (!DeviceInfoData
)
4540 SetLastError(ERROR_INVALID_PARAMETER
);
4541 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4542 SetLastError(ERROR_INVALID_USER_BUFFER
);
4545 memcpy(&DeviceInfoData
->ClassGuid
,
4546 &list
->SelectedDevice
->ClassGuid
,
4548 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
4549 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
4553 TRACE("Returning %d\n", ret
);
4558 /***********************************************************************
4559 * SetupDiSetSelectedDevice (SETUPAPI.@)
4562 SetupDiSetSelectedDevice(
4563 IN HDEVINFO DeviceInfoSet
,
4564 IN PSP_DEVINFO_DATA DeviceInfoData
)
4566 struct DeviceInfoSet
*list
;
4569 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4572 SetLastError(ERROR_INVALID_HANDLE
);
4573 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4574 SetLastError(ERROR_INVALID_HANDLE
);
4575 else if (!DeviceInfoData
)
4576 SetLastError(ERROR_INVALID_PARAMETER
);
4577 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4578 SetLastError(ERROR_INVALID_USER_BUFFER
);
4579 else if (DeviceInfoData
->Reserved
== 0)
4580 SetLastError(ERROR_INVALID_USER_BUFFER
);
4583 list
->SelectedDevice
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
4587 TRACE("Returning %d\n", ret
);
4592 /* Return the current hardware profile id, or -1 if error */
4594 SETUPAPI_GetCurrentHwProfile(
4595 IN HDEVINFO DeviceInfoSet
)
4598 DWORD dwRegType
, dwLength
;
4601 DWORD ret
= (DWORD
)-1;
4604 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
4605 REGSTR_PATH_IDCONFIGDB
,
4609 if (rc
!= ERROR_SUCCESS
)
4615 dwLength
= sizeof(DWORD
);
4616 rc
= RegQueryValueExW(
4618 REGSTR_VAL_CURRENTCONFIG
,
4621 (LPBYTE
)&hwProfile
, &dwLength
);
4622 if (rc
!= ERROR_SUCCESS
)
4627 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
4629 SetLastError(ERROR_GEN_FAILURE
);
4644 IN HDEVINFO DeviceInfoSet
,
4645 IN PSP_DEVINFO_DATA DeviceInfoData
)
4648 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
4649 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
4652 cr
= CM_Enable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
4653 if (cr
!= CR_SUCCESS
)
4655 SetLastError(GetErrorCodeFromCrCode(cr
));
4661 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
4666 static BOOL
StopDevice(
4667 IN HDEVINFO DeviceInfoSet
,
4668 IN PSP_DEVINFO_DATA DeviceInfoData
)
4670 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
4674 /***********************************************************************
4675 * SetupDiChangeState (SETUPAPI.@)
4679 IN HDEVINFO DeviceInfoSet
,
4680 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
4682 PSP_PROPCHANGE_PARAMS PropChange
;
4683 HKEY hKey
= INVALID_HANDLE_VALUE
;
4684 LPCWSTR RegistryValueName
;
4685 DWORD dwConfigFlags
, dwLength
, dwRegType
;
4689 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4691 if (!DeviceInfoData
)
4692 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChangeParams
;
4694 PropChange
= ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChangeParams
;
4697 SetLastError(ERROR_INVALID_PARAMETER
);
4701 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
4702 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
4704 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
4706 switch (PropChange
->StateChange
)
4711 /* Enable/disable device in registry */
4712 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
4713 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4714 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
4715 if (hKey
== INVALID_HANDLE_VALUE
)
4717 dwLength
= sizeof(DWORD
);
4718 rc
= RegQueryValueExW(
4723 (LPBYTE
)&dwConfigFlags
, &dwLength
);
4724 if (rc
== ERROR_FILE_NOT_FOUND
)
4726 else if (rc
!= ERROR_SUCCESS
)
4731 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
4733 SetLastError(ERROR_GEN_FAILURE
);
4736 if (PropChange
->StateChange
== DICS_ENABLE
)
4737 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
4739 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
4740 rc
= RegSetValueExW(
4745 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
4746 if (rc
!= ERROR_SUCCESS
)
4752 /* Enable/disable device if needed */
4753 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
4754 || PropChange
->HwProfile
== 0
4755 || PropChange
->HwProfile
== SETUPAPI_GetCurrentHwProfile(DeviceInfoSet
))
4757 if (PropChange
->StateChange
== DICS_ENABLE
)
4758 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
4760 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
4766 case DICS_PROPCHANGE
:
4768 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
4773 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
4774 SetLastError(ERROR_NOT_SUPPORTED
);
4779 if (hKey
!= INVALID_HANDLE_VALUE
)
4782 TRACE("Returning %d\n", ret
);
4786 /***********************************************************************
4787 * SetupDiSelectDevice (SETUPAPI.@)
4790 SetupDiSelectDevice(
4791 IN HDEVINFO DeviceInfoSet
,
4792 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4794 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4795 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4800 /***********************************************************************
4801 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4804 SetupDiRegisterCoDeviceInstallers(
4805 IN HDEVINFO DeviceInfoSet
,
4806 IN PSP_DEVINFO_DATA DeviceInfoData
)
4808 BOOL ret
= FALSE
; /* Return value */
4810 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4813 SetLastError(ERROR_INVALID_PARAMETER
);
4814 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4815 SetLastError(ERROR_INVALID_HANDLE
);
4816 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4817 SetLastError(ERROR_INVALID_HANDLE
);
4818 else if (!DeviceInfoData
)
4819 SetLastError(ERROR_INVALID_PARAMETER
);
4820 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4821 SetLastError(ERROR_INVALID_USER_BUFFER
);
4824 SP_DEVINSTALL_PARAMS_W InstallParams
;
4825 struct DriverInfoElement
*SelectedDriver
;
4828 WCHAR SectionName
[MAX_PATH
];
4829 DWORD SectionNameLength
= 0;
4830 HKEY hKey
= INVALID_HANDLE_VALUE
;
4831 PVOID Context
= NULL
;
4833 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4834 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4838 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
4839 if (SelectedDriver
== NULL
)
4841 SetLastError(ERROR_NO_DRIVER_SELECTED
);
4845 /* Get .CoInstallers section name */
4846 Result
= SetupDiGetActualSectionToInstallW(
4847 SelectedDriver
->InfFileDetails
->hInf
,
4848 SelectedDriver
->Details
.SectionName
,
4849 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
4850 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
4852 lstrcatW(SectionName
, DotCoInstallers
);
4854 /* Open/Create driver key information */
4855 #if _WIN32_WINNT >= 0x502
4856 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
4858 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
4860 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
4861 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
4862 if (hKey
== INVALID_HANDLE_VALUE
)
4865 /* Install .CoInstallers section */
4866 DoAction
= SPINST_REGISTRY
;
4867 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
4869 DoAction
|= SPINST_FILES
;
4870 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
4874 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
4875 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
4876 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
4877 SetupDefaultQueueCallbackW
, Context
,
4878 DeviceInfoSet
, DeviceInfoData
);
4886 SetupTermDefaultQueueCallback(Context
);
4887 if (hKey
!= INVALID_HANDLE_VALUE
)
4891 TRACE("Returning %d\n", ret
);
4896 InfIsFromOEMLocation(
4898 OUT LPBOOL IsOEMLocation
)
4902 last
= strrchrW(FullName
, '\\');
4905 /* No directory specified */
4906 *IsOEMLocation
= FALSE
;
4913 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
4916 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4920 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
4921 if (ret
== 0 || ret
> MAX_PATH
)
4924 SetLastError(ERROR_GEN_FAILURE
);
4927 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
4928 strcatW(Windir
, BackSlash
);
4929 strcatW(Windir
, InfDirectory
);
4931 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
4933 /* The path is %SYSTEMROOT%\Inf */
4934 *IsOEMLocation
= FALSE
;
4938 /* The file is in another place */
4939 *IsOEMLocation
= TRUE
;
4946 /***********************************************************************
4947 * SetupDiInstallDevice (SETUPAPI.@)
4950 SetupDiInstallDevice(
4951 IN HDEVINFO DeviceInfoSet
,
4952 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
4954 SP_DEVINSTALL_PARAMS_W InstallParams
;
4955 struct DriverInfoElement
*SelectedDriver
;
4956 SYSTEMTIME DriverDate
;
4957 WCHAR SectionName
[MAX_PATH
];
4959 DWORD SectionNameLength
= 0;
4960 BOOL Result
= FALSE
;
4963 LPWSTR pSectionName
= NULL
;
4964 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
4966 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
4967 BOOL RebootRequired
= FALSE
;
4968 HKEY hKey
= INVALID_HANDLE_VALUE
;
4969 BOOL NeedtoCopyFile
;
4970 LARGE_INTEGER fullVersion
;
4972 PVOID Context
= NULL
;
4973 BOOL ret
= FALSE
; /* Return value */
4975 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4978 SetLastError(ERROR_INVALID_PARAMETER
);
4979 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4980 SetLastError(ERROR_INVALID_HANDLE
);
4981 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4982 SetLastError(ERROR_INVALID_HANDLE
);
4983 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4984 SetLastError(ERROR_INVALID_USER_BUFFER
);
4990 /* One parameter is bad */
4994 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4995 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4999 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5001 /* Set FAILEDINSTALL in ConfigFlags registry value */
5002 DWORD ConfigFlags
, regType
;
5003 Result
= SetupDiGetDeviceRegistryPropertyW(
5008 (PBYTE
)&ConfigFlags
,
5009 sizeof(ConfigFlags
),
5011 if (!Result
|| regType
!= REG_DWORD
)
5013 SetLastError(ERROR_GEN_FAILURE
);
5016 ConfigFlags
|= DNF_DISABLED
;
5017 Result
= SetupDiSetDeviceRegistryPropertyW(
5021 (PBYTE
)&ConfigFlags
,
5022 sizeof(ConfigFlags
));
5025 SetLastError(ERROR_GEN_FAILURE
);
5033 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5034 if (SelectedDriver
== NULL
)
5036 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5040 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5042 Result
= SetupDiGetActualSectionToInstallW(
5043 SelectedDriver
->InfFileDetails
->hInf
,
5044 SelectedDriver
->Details
.SectionName
,
5045 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5046 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
5048 pSectionName
= &SectionName
[strlenW(SectionName
)];
5050 /* Get information from [Version] section */
5051 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5053 /* Format ClassGuid to a string */
5054 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5056 RequiredSize
= lstrlenW(lpGuidString
);
5057 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5058 if (!lpFullGuidString
)
5060 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5063 lpFullGuidString
[0] = '{';
5064 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5065 lpFullGuidString
[RequiredSize
+ 1] = '}';
5066 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5068 /* Copy .inf file to Inf\ directory (if needed) */
5069 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
5074 WCHAR NewFileName
[MAX_PATH
];
5075 struct InfFileDetails
*newInfFileDetails
;
5076 Result
= SetupCopyOEMInfW(
5077 SelectedDriver
->Details
.InfFileName
,
5080 SP_COPY_NOOVERWRITE
,
5081 NewFileName
, MAX_PATH
,
5086 /* Create a new struct InfFileDetails, and set it to
5087 * SelectedDriver->InfFileDetails, to release use of
5088 * current InfFile */
5089 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
5090 if (!newInfFileDetails
)
5092 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
5093 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
5094 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
5097 /* Open/Create driver key information */
5098 #if _WIN32_WINNT >= 0x502
5099 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5101 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5103 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5104 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5105 if (hKey
== INVALID_HANDLE_VALUE
)
5108 /* Install main section */
5110 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5111 DoAction
|= SPINST_REGISTRY
;
5112 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5114 DoAction
|= SPINST_FILES
;
5115 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5119 *pSectionName
= '\0';
5120 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5121 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5122 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5123 SetupDefaultQueueCallbackW
, Context
,
5124 DeviceInfoSet
, DeviceInfoData
);
5127 InstallParams
.Flags
|= DI_NOFILECOPY
;
5128 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5130 /* Write information to driver key */
5131 *pSectionName
= UNICODE_NULL
;
5132 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
5133 TRACE("Write information to driver key\n");
5134 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5135 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5136 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5137 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
5138 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
5139 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
5140 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
5141 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
5142 sprintfW(Buffer
, DateFormat
, DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5143 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5144 if (rc
== ERROR_SUCCESS
)
5145 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5146 if (rc
== ERROR_SUCCESS
)
5147 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5148 if (rc
== ERROR_SUCCESS
)
5150 sprintfW(Buffer
, VersionFormat
, fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5151 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5153 if (rc
== ERROR_SUCCESS
)
5154 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
5155 if (rc
== ERROR_SUCCESS
)
5156 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5157 if (rc
== ERROR_SUCCESS
)
5158 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
));
5159 if (rc
== ERROR_SUCCESS
)
5160 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5161 if (rc
== ERROR_SUCCESS
)
5162 rc
= RegSetValueExW(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5163 if (rc
!= ERROR_SUCCESS
)
5169 hKey
= INVALID_HANDLE_VALUE
;
5171 /* FIXME: Process .LogConfigOverride section */
5173 /* Install .Services section */
5174 strcpyW(pSectionName
, DotServices
);
5175 Result
= SetupInstallServicesFromInfSectionExW(
5176 SelectedDriver
->InfFileDetails
->hInf
,
5185 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5186 RebootRequired
= TRUE
;
5188 /* Open device registry key */
5189 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5190 if (hKey
== INVALID_HANDLE_VALUE
)
5193 /* Install .HW section */
5195 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5196 DoAction
|= SPINST_REGISTRY
;
5197 strcpyW(pSectionName
, DotHW
);
5198 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5199 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5200 DoAction
, hKey
, NULL
, 0,
5202 DeviceInfoSet
, DeviceInfoData
);
5206 /* Write information to enum key */
5207 TRACE("Write information to enum key\n");
5208 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
5209 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
5210 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5211 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
5212 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
5213 if (rc
== ERROR_SUCCESS
)
5214 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5215 if (rc
== ERROR_SUCCESS
)
5216 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5217 if (rc
== ERROR_SUCCESS
)
5218 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5219 if (rc
!= ERROR_SUCCESS
)
5225 /* Start the device */
5226 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5227 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5232 /* End of installation */
5233 if (hKey
!= INVALID_HANDLE_VALUE
)
5236 RpcStringFreeW(&lpGuidString
);
5237 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5239 SetupTermDefaultQueueCallback(Context
);
5240 TRACE("Returning %d\n", ret
);
5244 static HKEY
SETUPDI_OpenDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5246 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5249 l
= RegOpenKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, 0, &enumKey
);
5252 l
= RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
5253 RegCloseKey(enumKey
);
5260 static HKEY
SETUPDI_OpenDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5262 LPWSTR DriverKey
= NULL
;
5266 HKEY hEnumKey
= NULL
;
5268 HKEY key
= INVALID_HANDLE_VALUE
;
5270 hKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
);
5271 if (hKey
== INVALID_HANDLE_VALUE
)
5273 /* Read the 'Driver' key */
5274 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5275 if (rc
!= ERROR_SUCCESS
)
5280 else if (dwRegType
!= REG_SZ
)
5282 SetLastError(ERROR_GEN_FAILURE
);
5285 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5288 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5291 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5292 if (rc
!= ERROR_SUCCESS
)
5299 /* Need to open the driver key */
5302 REGSTR_PATH_CLASS_NT
,
5306 if (rc
!= ERROR_SUCCESS
)
5317 if (rc
!= ERROR_SUCCESS
)
5325 if (hEnumKey
!= NULL
)
5326 RegCloseKey(hEnumKey
);
5327 if (hKey
!= NULL
&& hKey
!= key
)
5332 /***********************************************************************
5333 * SetupDiOpenDevRegKey (SETUPAPI.@)
5335 HKEY WINAPI
SetupDiOpenDevRegKey(
5336 HDEVINFO DeviceInfoSet
,
5337 PSP_DEVINFO_DATA DeviceInfoData
,
5343 struct DeviceInfoSet
*set
= DeviceInfoSet
;
5344 struct DeviceInfo
*devInfo
;
5345 HKEY key
= INVALID_HANDLE_VALUE
;
5348 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet
, DeviceInfoData
,
5349 Scope
, HwProfile
, KeyType
, samDesired
);
5351 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5353 SetLastError(ERROR_INVALID_HANDLE
);
5354 return INVALID_HANDLE_VALUE
;
5356 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5358 SetLastError(ERROR_INVALID_HANDLE
);
5359 return INVALID_HANDLE_VALUE
;
5361 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5362 || !DeviceInfoData
->Reserved
)
5364 SetLastError(ERROR_INVALID_PARAMETER
);
5365 return INVALID_HANDLE_VALUE
;
5367 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5369 SetLastError(ERROR_INVALID_FLAGS
);
5370 return INVALID_HANDLE_VALUE
;
5372 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
5374 SetLastError(ERROR_INVALID_FLAGS
);
5375 return INVALID_HANDLE_VALUE
;
5377 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5378 if (devInfo
->set
!= set
)
5380 SetLastError(ERROR_INVALID_PARAMETER
);
5381 return INVALID_HANDLE_VALUE
;
5383 if (Scope
!= DICS_FLAG_GLOBAL
)
5385 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5386 if (RootKey
== INVALID_HANDLE_VALUE
)
5387 return INVALID_HANDLE_VALUE
;
5390 RootKey
= set
->HKLM
;
5394 key
= SETUPDI_OpenDevKey(RootKey
, devInfo
, samDesired
);
5397 key
= SETUPDI_OpenDrvKey(RootKey
, devInfo
, samDesired
);
5400 WARN("unknown KeyType %d\n", KeyType
);
5402 if (RootKey
!= set
->HKLM
)
5403 RegCloseKey(RootKey
);
5407 static BOOL
SETUPDI_DeleteDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5413 static BOOL
SETUPDI_DeleteDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5419 /***********************************************************************
5420 * SetupDiDeleteDevRegKey (SETUPAPI.@)
5422 BOOL WINAPI
SetupDiDeleteDevRegKey(
5423 HDEVINFO DeviceInfoSet
,
5424 PSP_DEVINFO_DATA DeviceInfoData
,
5429 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5430 struct DeviceInfo
*devInfo
;
5434 TRACE("%p %p %d %d %d\n", DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
5437 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5439 SetLastError(ERROR_INVALID_HANDLE
);
5442 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5444 SetLastError(ERROR_INVALID_HANDLE
);
5447 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5448 || !DeviceInfoData
->Reserved
)
5450 SetLastError(ERROR_INVALID_PARAMETER
);
5453 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5455 SetLastError(ERROR_INVALID_FLAGS
);
5458 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
&& KeyType
!= DIREG_BOTH
)
5460 SetLastError(ERROR_INVALID_FLAGS
);
5463 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5464 if (devInfo
->set
!= set
)
5466 SetLastError(ERROR_INVALID_PARAMETER
);
5469 if (Scope
!= DICS_FLAG_GLOBAL
)
5471 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5472 if (RootKey
== INVALID_HANDLE_VALUE
)
5476 RootKey
= set
->HKLM
;
5480 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5483 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5486 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5488 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5491 WARN("unknown KeyType %d\n", KeyType
);
5493 if (RootKey
!= set
->HKLM
)
5494 RegCloseKey(RootKey
);