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 /* Unicode constants */
25 static const WCHAR BackSlash
[] = {'\\',0};
26 static const WCHAR DateFormat
[] = {'%','u','-','%','u','-','%','u',0};
27 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
28 static const WCHAR DotHW
[] = {'.','H','W',0};
29 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
30 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
31 static const WCHAR InstanceKeyFormat
[] = {'%','0','4','l','u',0};
32 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
33 static const WCHAR VersionFormat
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
35 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
36 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
37 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
38 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
39 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};
42 (CALLBACK
* CLASS_INSTALL_PROC
) (
43 IN DI_FUNCTION InstallFunction
,
44 IN HDEVINFO DeviceInfoSet
,
45 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
47 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
48 IN HDEVINFO DeviceInfoSet
,
49 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
51 (CALLBACK
* COINSTALLER_PROC
) (
52 IN DI_FUNCTION InstallFunction
,
53 IN HDEVINFO DeviceInfoSet
,
54 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
55 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
57 struct CoInstallerElement
62 COINSTALLER_PROC Function
;
63 BOOL DoPostProcessing
;
67 struct GetSectionCallbackInfo
69 PSP_ALTPLATFORM_INFO PlatformInfo
;
73 WCHAR BestSection
[LINE_LEN
+ 1];
74 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
79 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
81 static const WCHAR fmt
[] = {'{','%','0','8','X','-','%','0','4','X','-',
82 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
83 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
86 sprintfW(guidStr
, fmt
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
87 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
88 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
92 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
96 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
97 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
98 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
99 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
100 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
101 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
102 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
103 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
104 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
105 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
106 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
107 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
108 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
109 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
110 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
111 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
112 case CR_ALREADY_SUCH_DEVINST
: return ERROR_DEVINST_ALREADY_EXISTS
;
113 case CR_SUCCESS
: return ERROR_SUCCESS
;
114 default: return ERROR_GEN_FAILURE
;
117 /* Does not happen */
120 /* Lower scores are best ones */
123 IN LPCWSTR SectionName
,
124 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
127 OUT PDWORD ScorePlatform
,
128 OUT PDWORD ScoreMajorVersion
,
129 OUT PDWORD ScoreMinorVersion
,
130 OUT PDWORD ScoreProductType
,
131 OUT PDWORD ScoreSuiteMask
)
133 LPWSTR Section
= NULL
;
134 //LPCWSTR pExtensionPlatform;
135 LPCWSTR pExtensionArchitecture
;
140 //static const WCHAR ExtensionPlatformNone[] = {'.',0};
141 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
142 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
144 static const WCHAR ExtensionArchitectureNone
[] = {0};
145 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
146 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
147 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
148 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
149 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
150 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
152 TRACE("%s(%s %p 0x%x 0x%x)\n",
153 __FUNCTION__
, debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
155 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
157 Section
= pSetupDuplicateString(SectionName
);
160 TRACE("pSetupDuplicateString() failed\n");
164 /* Set various extensions values */
165 switch (PlatformInfo
->Platform
)
167 case VER_PLATFORM_WIN32_WINDOWS
:
168 //pExtensionPlatform = ExtensionPlatformWindows;
170 case VER_PLATFORM_WIN32_NT
:
171 //pExtensionPlatform = ExtensionPlatformNT;
174 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
175 //pExtensionPlatform = ExtensionPlatformNone;
178 switch (PlatformInfo
->ProcessorArchitecture
)
180 case PROCESSOR_ARCHITECTURE_ALPHA
:
181 pExtensionArchitecture
= ExtensionArchitecturealpha
;
183 case PROCESSOR_ARCHITECTURE_AMD64
:
184 pExtensionArchitecture
= ExtensionArchitectureamd64
;
186 case PROCESSOR_ARCHITECTURE_IA64
:
187 pExtensionArchitecture
= ExtensionArchitectureia64
;
189 case PROCESSOR_ARCHITECTURE_INTEL
:
190 pExtensionArchitecture
= ExtensionArchitecturex86
;
192 case PROCESSOR_ARCHITECTURE_MIPS
:
193 pExtensionArchitecture
= ExtensionArchitecturemips
;
195 case PROCESSOR_ARCHITECTURE_PPC
:
196 pExtensionArchitecture
= ExtensionArchitectureppc
;
199 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
200 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
201 pExtensionArchitecture
= ExtensionArchitectureNone
;
207 * Field[1] Architecture
208 * Field[2] Major version
209 * Field[3] Minor version
210 * Field[4] Product type
211 * Field[5] Suite mask
212 * Remark: these fields may be NULL if the information is not provided
215 if (Fields
[0] == NULL
)
217 TRACE("No extension found\n");
218 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
222 Fields
[1] = Fields
[0] + 1;
223 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
224 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
226 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
230 *(Fields
[i
] - 1) = UNICODE_NULL
;
233 /* Take care of first 2 fields */
234 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
236 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
238 TRACE("Mismatch on platform field\n");
241 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
243 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
245 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
247 TRACE("Mismatch on platform field\n");
250 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
254 /* No platform specified */
255 *ScorePlatform
|= 0x02;
257 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
259 /* No architecture specified */
260 *ScorePlatform
|= 0x01;
262 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
264 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
265 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
269 /* Check if informations are matching */
270 if (Fields
[2] && *Fields
[2])
272 DWORD MajorVersion
, MinorVersion
= 0;
273 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
274 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
275 (errno
== ERANGE
|| errno
== EINVAL
))
277 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
280 if (Fields
[3] && *Fields
[3])
282 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
283 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
284 (errno
== ERANGE
|| errno
== EINVAL
))
286 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
290 if (PlatformInfo
->MajorVersion
< MajorVersion
||
291 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
293 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
294 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
297 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
298 if (MajorVersion
== PlatformInfo
->MajorVersion
)
299 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
301 *ScoreMinorVersion
= MinorVersion
;
303 else if (Fields
[3] && *Fields
[3])
305 TRACE("Minor version found without major version\n");
310 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
311 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
314 if (Fields
[4] && *Fields
[4])
316 DWORD CurrentProductType
;
317 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
318 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
319 (errno
== ERANGE
|| errno
== EINVAL
))
321 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
324 if (CurrentProductType
!= ProductType
)
326 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
327 CurrentProductType
, ProductType
);
332 *ScoreProductType
= 1;
334 if (Fields
[5] && *Fields
[5])
336 DWORD CurrentSuiteMask
;
337 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
338 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
339 (errno
== ERANGE
|| errno
== EINVAL
))
341 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
344 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
346 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
347 CurrentSuiteMask
, SuiteMask
);
350 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
353 *ScoreSuiteMask
= SuiteMask
;
364 IN LPCWSTR SectionName
,
367 struct GetSectionCallbackInfo
*info
= Context
;
368 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
371 if (SectionName
[info
->PrefixLength
] != '.')
374 ret
= CheckSectionValid(
375 &SectionName
[info
->PrefixLength
],
379 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
382 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
385 if (Score1
> info
->BestScore1
) goto done
;
386 if (Score1
< info
->BestScore1
) goto bettersection
;
387 if (Score2
> info
->BestScore2
) goto done
;
388 if (Score2
< info
->BestScore2
) goto bettersection
;
389 if (Score3
> info
->BestScore3
) goto done
;
390 if (Score3
< info
->BestScore3
) goto bettersection
;
391 if (Score4
> info
->BestScore4
) goto done
;
392 if (Score4
< info
->BestScore4
) goto bettersection
;
393 if (Score5
> info
->BestScore5
) goto done
;
394 if (Score5
< info
->BestScore5
) goto bettersection
;
398 strcpyW(info
->BestSection
, SectionName
);
399 info
->BestScore1
= Score1
;
400 info
->BestScore2
= Score2
;
401 info
->BestScore3
= Score3
;
402 info
->BestScore4
= Score4
;
403 info
->BestScore5
= Score5
;
409 /***********************************************************************
410 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
413 SetupDiGetActualSectionToInstallExW(
415 IN PCWSTR InfSectionName
,
416 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
417 OUT PWSTR InfSectionWithExt OPTIONAL
,
418 IN DWORD InfSectionWithExtSize
,
419 OUT PDWORD RequiredSize OPTIONAL
,
420 OUT PWSTR
* Extension OPTIONAL
,
425 TRACE("%s(%p %s %p %p %lu %p %p %p)\n", __FUNCTION__
, InfHandle
, debugstr_w(InfSectionName
),
426 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
427 RequiredSize
, Extension
, Reserved
);
429 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
430 SetLastError(ERROR_INVALID_HANDLE
);
431 else if (!InfSectionName
)
432 SetLastError(ERROR_INVALID_PARAMETER
);
433 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
434 SetLastError(ERROR_INVALID_USER_BUFFER
);
435 else if (Reserved
!= NULL
)
436 SetLastError(ERROR_INVALID_PARAMETER
);
439 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
440 static BYTE CurrentProductType
= 0;
441 static WORD CurrentSuiteMask
= 0;
442 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
443 struct GetSectionCallbackInfo CallbackInfo
;
448 /* Fill platform info if needed */
449 if (AlternatePlatformInfo
)
451 pPlatformInfo
= AlternatePlatformInfo
;
457 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
459 /* That's the first time we go here. We need to fill in the structure */
460 SYSTEM_INFO SystemInfo
;
461 GetSystemInfo(&SystemInfo
);
462 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
463 CurrentPlatform
.Platform
= OsVersionInfo
.dwPlatformId
;
464 CurrentPlatform
.MajorVersion
= OsVersionInfo
.dwMajorVersion
;
465 CurrentPlatform
.MinorVersion
= OsVersionInfo
.dwMinorVersion
;
466 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
467 CurrentPlatform
.Reserved
= 0;
468 CurrentProductType
= OsVersionInfo
.wProductType
;
469 CurrentSuiteMask
= OsVersionInfo
.wSuiteMask
;
471 ProductType
= CurrentProductType
;
472 SuiteMask
= CurrentSuiteMask
;
475 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
476 CallbackInfo
.ProductType
= ProductType
;
477 CallbackInfo
.SuiteMask
= SuiteMask
;
478 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
479 CallbackInfo
.BestScore1
= ULONG_MAX
;
480 CallbackInfo
.BestScore2
= ULONG_MAX
;
481 CallbackInfo
.BestScore3
= ULONG_MAX
;
482 CallbackInfo
.BestScore4
= ULONG_MAX
;
483 CallbackInfo
.BestScore5
= ULONG_MAX
;
484 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
485 TRACE("EnumerateSectionsStartingWith(InfSectionName = %S)\n", InfSectionName
);
486 if (!EnumerateSectionsStartingWith(
492 SetLastError(ERROR_GEN_FAILURE
);
495 TRACE("CallbackInfo.BestSection = %S\n", CallbackInfo
.BestSection
);
497 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
498 if (RequiredSize
!= NULL
)
499 *RequiredSize
= dwFullLength
+ 1;
501 if (InfSectionWithExtSize
> 0)
503 if (InfSectionWithExtSize
< dwFullLength
+ 1)
505 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
508 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
511 DWORD dwLength
= lstrlenW(InfSectionName
);
512 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
520 TRACE("Returning %d\n", ret
);
527 IN
struct DeviceInfoSet
*list
,
528 IN LPCWSTR InstancePath
,
529 IN LPCGUID pClassGuid
,
530 OUT
struct DeviceInfo
**pDeviceInfo
)
534 struct DeviceInfo
*deviceInfo
;
538 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
539 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
542 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
545 ZeroMemory(deviceInfo
, size
);
547 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
548 if (cr
!= CR_SUCCESS
)
550 SetLastError(GetErrorCodeFromCrCode(cr
));
554 deviceInfo
->set
= list
;
555 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
556 strcpyW(deviceInfo
->Data
, InstancePath
);
557 deviceInfo
->instanceId
= deviceInfo
->Data
;
558 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
559 deviceInfo
->DeviceDescription
= NULL
;
560 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
561 deviceInfo
->CreationFlags
= 0;
562 InitializeListHead(&deviceInfo
->DriverListHead
);
563 InitializeListHead(&deviceInfo
->InterfaceListHead
);
565 *pDeviceInfo
= deviceInfo
;
571 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
573 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
574 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
579 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
581 PLIST_ENTRY ListEntry
;
582 struct DriverInfoElement
*driverInfo
;
583 struct DeviceInterface
*deviceInterface
;
585 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
587 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
588 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
589 if (!DestroyDriverInfoElement(driverInfo
))
592 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
594 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
595 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
596 if (!DestroyDeviceInterface(deviceInterface
))
599 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
600 if (deviceInfo
->hmodDevicePropPageProvider
)
601 FreeLibrary(deviceInfo
->hmodDevicePropPageProvider
);
602 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
606 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
608 PLIST_ENTRY ListEntry
;
609 struct DeviceInfo
*deviceInfo
;
611 while (!IsListEmpty(&list
->ListHead
))
613 ListEntry
= RemoveHeadList(&list
->ListHead
);
614 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
);
615 if (!DestroyDeviceInfo(deviceInfo
))
618 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
619 RegCloseKey(list
->HKLM
);
620 CM_Disconnect_Machine(list
->hMachine
);
621 DestroyClassInstallParams(&list
->ClassInstallParams
);
622 if (list
->hmodClassPropPageProvider
)
623 FreeLibrary(list
->hmodClassPropPageProvider
);
624 return HeapFree(GetProcessHeap(), 0, list
);
627 /***********************************************************************
628 * SetupDiBuildClassInfoList (SETUPAPI.@)
630 * Returns a list of setup class GUIDs that identify the classes
631 * that are installed on a local machine.
634 * Flags [I] control exclusion of classes from the list.
635 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
636 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
637 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
643 BOOL WINAPI
SetupDiBuildClassInfoList(
645 LPGUID ClassGuidList
,
646 DWORD ClassGuidListSize
,
650 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
651 ClassGuidListSize
, RequiredSize
,
655 /***********************************************************************
656 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
658 * Returns a list of setup class GUIDs that identify the classes
659 * that are installed on a local or remote machine.
662 * Flags [I] control exclusion of classes from the list.
663 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
664 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
665 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
666 * MachineName [I] name of a remote machine.
667 * Reserved [I] must be NULL.
673 BOOL WINAPI
SetupDiBuildClassInfoListExA(
675 LPGUID ClassGuidList
,
676 DWORD ClassGuidListSize
,
681 LPWSTR MachineNameW
= NULL
;
684 TRACE("%s(0x%lx %p %lu %p %s %p)\n", __FUNCTION__
, Flags
, ClassGuidList
,
685 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
689 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
690 if (MachineNameW
== NULL
) return FALSE
;
693 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
694 ClassGuidListSize
, RequiredSize
,
695 MachineNameW
, Reserved
);
697 MyFree(MachineNameW
);
702 /***********************************************************************
703 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
705 * Returns a list of setup class GUIDs that identify the classes
706 * that are installed on a local or remote machine.
709 * Flags [I] control exclusion of classes from the list.
710 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
711 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
712 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
713 * MachineName [I] name of a remote machine.
714 * Reserved [I] must be NULL.
720 BOOL WINAPI
SetupDiBuildClassInfoListExW(
722 LPGUID ClassGuidList
,
723 DWORD ClassGuidListSize
,
728 GUID CurrentClassGuid
;
731 DWORD dwGuidListIndex
= 0;
732 HMACHINE hMachine
= NULL
;
735 TRACE("%s(0x%lx %p %lu %p %s %p)\n", __FUNCTION__
, Flags
, ClassGuidList
,
736 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
740 SetLastError(ERROR_INVALID_PARAMETER
);
743 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
745 SetLastError(ERROR_INVALID_PARAMETER
);
751 cr
= CM_Connect_MachineW(MachineName
, &hMachine
);
752 if (cr
!= CR_SUCCESS
)
754 SetLastError(GetErrorCodeFromCrCode(cr
));
759 for (dwIndex
= 0; ; dwIndex
++)
761 cr
= CM_Enumerate_Classes_Ex(dwIndex
,
765 if (cr
== CR_SUCCESS
)
767 TRACE("Guid: %s\n", debugstr_guid(&CurrentClassGuid
));
768 if (CM_Open_Class_Key_ExW(&CurrentClassGuid
,
771 RegDisposition_OpenExisting
,
773 CM_OPEN_CLASS_KEY_INSTALLER
,
774 hMachine
) != CR_SUCCESS
)
776 SetLastError(GetErrorCodeFromCrCode(cr
));
778 CM_Disconnect_Machine(hMachine
);
782 if (!RegQueryValueExW(hClassKey
,
783 REGSTR_VAL_NOUSECLASS
,
789 TRACE("'NoUseClass' value found!\n");
790 RegCloseKey(hClassKey
);
794 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
795 (!RegQueryValueExW(hClassKey
,
796 REGSTR_VAL_NOINSTALLCLASS
,
802 TRACE("'NoInstallClass' value found!\n");
803 RegCloseKey(hClassKey
);
807 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
808 (!RegQueryValueExW(hClassKey
,
809 REGSTR_VAL_NODISPLAYCLASS
,
815 TRACE("'NoDisplayClass' value found!\n");
816 RegCloseKey(hClassKey
);
820 RegCloseKey(hClassKey
);
822 if (dwGuidListIndex
< ClassGuidListSize
)
824 ClassGuidList
[dwGuidListIndex
] = CurrentClassGuid
;
830 if (cr
!= ERROR_SUCCESS
)
835 CM_Disconnect_Machine(hMachine
);
837 if (RequiredSize
!= NULL
)
838 *RequiredSize
= dwGuidListIndex
;
840 if (ClassGuidListSize
< dwGuidListIndex
)
842 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
849 /***********************************************************************
850 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
852 BOOL WINAPI
SetupDiClassGuidsFromNameA(
854 LPGUID ClassGuidList
,
855 DWORD ClassGuidListSize
,
858 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
859 ClassGuidListSize
, RequiredSize
,
863 /***********************************************************************
864 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
866 BOOL WINAPI
SetupDiClassGuidsFromNameW(
868 LPGUID ClassGuidList
,
869 DWORD ClassGuidListSize
,
872 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
873 ClassGuidListSize
, RequiredSize
,
877 /***********************************************************************
878 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
880 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
882 LPGUID ClassGuidList
,
883 DWORD ClassGuidListSize
,
888 LPWSTR ClassNameW
= NULL
;
889 LPWSTR MachineNameW
= NULL
;
892 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_a(ClassName
), ClassGuidList
,
893 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
897 SetLastError(ERROR_INVALID_PARAMETER
);
901 ClassNameW
= pSetupMultiByteToUnicode(ClassName
, CP_ACP
);
902 if (ClassNameW
== NULL
)
907 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
908 if (MachineNameW
== NULL
)
915 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
916 ClassGuidListSize
, RequiredSize
,
917 MachineNameW
, Reserved
);
919 MyFree(MachineNameW
);
925 /***********************************************************************
926 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
928 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
930 LPGUID ClassGuidList
,
931 DWORD ClassGuidListSize
,
937 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
943 DWORD dwGuidListIndex
= 0;
945 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_w(ClassName
), ClassGuidList
,
946 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
948 if (!ClassName
|| !RequiredSize
)
950 SetLastError(ERROR_INVALID_PARAMETER
);
953 if (!ClassGuidList
&& ClassGuidListSize
> 0)
955 SetLastError(ERROR_INVALID_PARAMETER
);
960 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
961 KEY_ENUMERATE_SUB_KEYS
,
965 if (hClassesKey
== INVALID_HANDLE_VALUE
)
970 for (dwIndex
= 0; ; dwIndex
++)
973 lError
= RegEnumKeyExW(hClassesKey
,
981 TRACE("RegEnumKeyExW() returns %d\n", lError
);
982 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
984 TRACE("Key name: %p\n", szKeyName
);
986 if (RegOpenKeyExW(hClassesKey
,
992 RegCloseKey(hClassesKey
);
996 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
997 if (!RegQueryValueExW(hClassKey
,
1001 (LPBYTE
)szClassName
,
1004 TRACE("Class name: %p\n", szClassName
);
1006 if (strcmpiW(szClassName
, ClassName
) == 0)
1008 TRACE("Found matching class name\n");
1010 TRACE("Guid: %p\n", szKeyName
);
1011 if (dwGuidListIndex
< ClassGuidListSize
)
1013 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1017 TRACE("Guid: %p\n", &szKeyName
[1]);
1019 UuidFromStringW(&szKeyName
[1],
1020 &ClassGuidList
[dwGuidListIndex
]);
1027 RegCloseKey(hClassKey
);
1030 if (lError
!= ERROR_SUCCESS
)
1034 RegCloseKey(hClassesKey
);
1036 if (RequiredSize
!= NULL
)
1037 *RequiredSize
= dwGuidListIndex
;
1039 if (ClassGuidListSize
< dwGuidListIndex
)
1041 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1048 /***********************************************************************
1049 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1051 BOOL WINAPI
SetupDiClassNameFromGuidA(
1052 const GUID
* ClassGuid
,
1054 DWORD ClassNameSize
,
1055 PDWORD RequiredSize
)
1057 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1058 ClassNameSize
, RequiredSize
,
1062 /***********************************************************************
1063 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1065 BOOL WINAPI
SetupDiClassNameFromGuidW(
1066 const GUID
* ClassGuid
,
1068 DWORD ClassNameSize
,
1069 PDWORD RequiredSize
)
1071 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1072 ClassNameSize
, RequiredSize
,
1076 /***********************************************************************
1077 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1079 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1080 const GUID
* ClassGuid
,
1082 DWORD ClassNameSize
,
1083 PDWORD RequiredSize
,
1087 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1088 LPWSTR MachineNameW
= NULL
;
1092 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1093 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1094 RequiredSize
, MachineNameW
, Reserved
);
1097 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1098 ClassNameSize
, NULL
, NULL
);
1099 if (len
== 0 || len
> ClassNameSize
)
1101 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1105 MyFree(MachineNameW
);
1109 /***********************************************************************
1110 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1112 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1113 const GUID
* ClassGuid
,
1115 DWORD ClassNameSize
,
1116 PDWORD RequiredSize
,
1126 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), ClassName
,
1127 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1129 /* Make sure there's a GUID */
1130 if (ClassGuid
== NULL
)
1132 SetLastError(ERROR_INVALID_CLASS
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1136 /* Make sure there's a real buffer when there's a size */
1137 if ((ClassNameSize
> 0) && (ClassName
== NULL
))
1139 SetLastError(ERROR_INVALID_PARAMETER
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1143 /* Open the key for the GUID */
1144 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INSTALLER
, MachineName
, Reserved
);
1146 if (hKey
== INVALID_HANDLE_VALUE
)
1149 /* Retrieve the class name data and close the key */
1150 rc
= QueryRegistryValue(hKey
, REGSTR_VAL_CLASS
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
1153 /* Make sure we got the data */
1154 if (rc
!= ERROR_SUCCESS
)
1160 /* Make sure the data is a string */
1161 if (dwRegType
!= REG_SZ
)
1164 SetLastError(ERROR_GEN_FAILURE
);
1168 /* Determine the length of the class name */
1169 dwLength
/= sizeof(WCHAR
);
1171 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
1172 /* Count the null-terminator */
1175 /* Inform the caller about the class name */
1176 if ((ClassName
!= NULL
) && (dwLength
<= ClassNameSize
))
1178 memcpy(ClassName
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
1179 ClassName
[dwLength
- 1] = UNICODE_NULL
;
1182 /* Inform the caller about the required size */
1183 if (RequiredSize
!= NULL
)
1184 *RequiredSize
= dwLength
;
1186 /* Clean up the buffer */
1189 /* Make sure the buffer was large enough */
1190 if ((ClassName
== NULL
) || (dwLength
> ClassNameSize
))
1192 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1199 /***********************************************************************
1200 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1203 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1206 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1209 /***********************************************************************
1210 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1213 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1218 LPWSTR MachineNameW
= NULL
;
1221 TRACE("%s(%s %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), hwndParent
,
1222 debugstr_a(MachineName
), Reserved
);
1226 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1227 if (MachineNameW
== NULL
)
1228 return INVALID_HANDLE_VALUE
;
1231 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1232 MachineNameW
, Reserved
);
1234 MyFree(MachineNameW
);
1239 /***********************************************************************
1240 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1242 * Create an empty DeviceInfoSet list.
1245 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1247 * hwndParent [I] hwnd needed for interface related actions.
1248 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1249 * local registry will be used.
1250 * Reserved [I] must be NULL
1253 * Success: empty list.
1254 * Failure: INVALID_HANDLE_VALUE.
1257 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1262 struct DeviceInfoSet
*list
= NULL
;
1263 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1266 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1268 TRACE("%s(%s %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), hwndParent
,
1269 debugstr_w(MachineName
), Reserved
);
1271 if (MachineName
!= NULL
)
1273 SIZE_T len
= strlenW(MachineName
);
1274 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1276 SetLastError(ERROR_INVALID_MACHINENAME
);
1280 size
+= (len
+ 3) * sizeof(WCHAR
);
1285 if (Reserved
!= NULL
)
1287 SetLastError(ERROR_INVALID_PARAMETER
);
1288 return INVALID_HANDLE_VALUE
;
1291 list
= MyMalloc(size
);
1294 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1295 return INVALID_HANDLE_VALUE
;
1297 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1299 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1300 memcpy(&list
->ClassGuid
,
1301 ClassGuid
? ClassGuid
: &GUID_NULL
,
1302 sizeof(list
->ClassGuid
));
1303 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1304 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1305 list
->InstallParams
.hwndParent
= hwndParent
;
1308 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1309 if (rc
!= ERROR_SUCCESS
)
1311 SetLastError(ERROR_INVALID_MACHINENAME
);
1315 list
->szData
[0] = list
->szData
[1] = '\\';
1316 strcpyW(list
->szData
+ 2, MachineName
);
1317 list
->MachineName
= list
->szData
;
1321 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1322 list
->MachineName
= NULL
;
1324 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1325 if (cr
!= CR_SUCCESS
)
1327 SetLastError(GetErrorCodeFromCrCode(cr
));
1330 InitializeListHead(&list
->DriverListHead
);
1331 InitializeListHead(&list
->ListHead
);
1333 return (HDEVINFO
)list
;
1336 if (ret
== INVALID_HANDLE_VALUE
)
1340 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1341 RegCloseKey(list
->HKLM
);
1348 /***********************************************************************
1349 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1351 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1352 HDEVINFO DeviceInfoSet
,
1353 PSP_DEVINFO_DATA DeviceInfoData
,
1358 PCSTR InfSectionName
)
1360 PWSTR InfSectionNameW
= NULL
;
1363 TRACE("%s(%p %p %d %d %d %p %s)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Scope
,
1364 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1368 if (!InfSectionName
)
1370 SetLastError(ERROR_INVALID_PARAMETER
);
1371 return INVALID_HANDLE_VALUE
;
1375 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
1376 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1379 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1380 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1381 MyFree(InfSectionNameW
);
1386 OpenHardwareProfileKey(
1389 IN DWORD samDesired
);
1391 /***********************************************************************
1392 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1394 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1395 HDEVINFO DeviceInfoSet
,
1396 PSP_DEVINFO_DATA DeviceInfoData
,
1401 PCWSTR InfSectionName
)
1403 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1404 struct DeviceInfo
*deviceInfo
;
1405 HKEY key
= INVALID_HANDLE_VALUE
;
1407 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1411 TRACE("%s(%p %p %lu %lu %lu %p %s)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Scope
,
1412 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1414 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1416 SetLastError(ERROR_INVALID_HANDLE
);
1417 return INVALID_HANDLE_VALUE
;
1419 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1421 SetLastError(ERROR_INVALID_HANDLE
);
1422 return INVALID_HANDLE_VALUE
;
1424 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1425 || !DeviceInfoData
->Reserved
)
1427 SetLastError(ERROR_INVALID_PARAMETER
);
1428 return INVALID_HANDLE_VALUE
;
1430 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1432 SetLastError(ERROR_INVALID_FLAGS
);
1433 return INVALID_HANDLE_VALUE
;
1435 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1437 SetLastError(ERROR_INVALID_FLAGS
);
1438 return INVALID_HANDLE_VALUE
;
1440 if (InfHandle
&& !InfSectionName
)
1442 SetLastError(ERROR_INVALID_PARAMETER
);
1443 return INVALID_HANDLE_VALUE
;
1445 if (!InfHandle
&& InfSectionName
)
1447 SetLastError(ERROR_INVALID_PARAMETER
);
1448 return INVALID_HANDLE_VALUE
;
1451 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1453 if (Scope
== DICS_FLAG_GLOBAL
)
1454 RootKey
= set
->HKLM
;
1455 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1457 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1458 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1460 RootKey
= hHWProfileKey
;
1463 if (KeyType
== DIREG_DEV
)
1465 #if _WIN32_WINNT >= 0x502
1466 hKey
= SETUPDI_CreateDevKey(RootKey
, deviceInfo
, KEY_READ
| KEY_WRITE
);
1468 hKey
= SETUPDI_CreateDevKey(RootKey
, deviceInfo
, KEY_ALL_ACCESS
);
1470 if (hKey
== INVALID_HANDLE_VALUE
)
1473 if (Scope
== DICS_FLAG_GLOBAL
)
1475 HKEY hTempKey
= hKey
;
1477 rc
= RegCreateKeyExW(hTempKey
,
1478 L
"Device Parameters",
1481 REG_OPTION_NON_VOLATILE
,
1482 #if _WIN32_WINNT >= 0x502
1483 KEY_READ
| KEY_WRITE
,
1490 if (rc
== ERROR_SUCCESS
)
1491 RegCloseKey(hTempKey
);
1494 else /* KeyType == DIREG_DRV */
1496 #if _WIN32_WINNT >= 0x502
1497 hKey
= SETUPDI_CreateDrvKey(RootKey
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_READ
| KEY_WRITE
);
1499 hKey
= SETUPDI_CreateDrvKey(RootKey
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_ALL_ACCESS
);
1501 if (hKey
== INVALID_HANDLE_VALUE
)
1505 /* Do installation of the specified section */
1508 FIXME("Need to install section %s in file %p\n",
1509 debugstr_w(InfSectionName
), InfHandle
);
1514 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1515 RegCloseKey(hHWProfileKey
);
1516 if (hKey
!= NULL
&& hKey
!= key
)
1519 TRACE("Returning 0x%p\n", key
);
1523 /***********************************************************************
1524 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1526 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1527 HDEVINFO DeviceInfoSet
,
1529 CONST GUID
*ClassGuid
,
1530 PCSTR DeviceDescription
,
1532 DWORD CreationFlags
,
1533 PSP_DEVINFO_DATA DeviceInfoData
)
1536 LPWSTR DeviceNameW
= NULL
;
1537 LPWSTR DeviceDescriptionW
= NULL
;
1543 DeviceNameW
= pSetupMultiByteToUnicode(DeviceName
, CP_ACP
);
1544 if (DeviceNameW
== NULL
) return FALSE
;
1546 if (DeviceDescription
)
1548 DeviceDescriptionW
= pSetupMultiByteToUnicode(DeviceDescription
, CP_ACP
);
1549 if (DeviceDescriptionW
== NULL
)
1551 MyFree(DeviceNameW
);
1556 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1557 hwndParent
, CreationFlags
, DeviceInfoData
);
1559 MyFree(DeviceNameW
);
1560 MyFree(DeviceDescriptionW
);
1565 /***********************************************************************
1566 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1568 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1569 HDEVINFO DeviceInfoSet
,
1571 CONST GUID
*ClassGuid
,
1572 PCWSTR DeviceDescription
,
1574 DWORD CreationFlags
,
1575 PSP_DEVINFO_DATA DeviceInfoData
)
1577 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1578 struct DeviceInfo
*deviceInfo
= NULL
;
1581 DEVINST RootDevInst
;
1583 WCHAR GenInstanceId
[MAX_DEVICE_ID_LEN
];
1585 TRACE("%s(%p %s %s %s %p %x %p)\n", __FUNCTION__
, DeviceInfoSet
, debugstr_w(DeviceName
),
1586 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1587 hwndParent
, CreationFlags
, DeviceInfoData
);
1591 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1594 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1596 SetLastError(ERROR_INVALID_HANDLE
);
1601 SetLastError(ERROR_INVALID_PARAMETER
);
1604 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1606 SetLastError(ERROR_INVALID_HANDLE
);
1609 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1610 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1612 SetLastError(ERROR_CLASS_MISMATCH
);
1615 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1617 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1618 SetLastError(ERROR_INVALID_FLAGS
);
1622 /* Get the root device instance */
1623 cr
= CM_Locate_DevInst_ExW(&RootDevInst
,
1625 CM_LOCATE_DEVINST_NORMAL
,
1627 if (cr
!= CR_SUCCESS
)
1629 SetLastError(ERROR_INVALID_DATA
);
1633 /* Create the new device instance */
1634 cr
= CM_Create_DevInst_ExW(&DevInst
,
1635 (DEVINSTID
)DeviceName
,
1637 (CreationFlags
& DICD_GENERATE_ID
) ?
1638 CM_CREATE_DEVINST_GENERATE_ID
: 0,
1640 if (cr
!= CR_SUCCESS
)
1642 SetLastError(GetErrorCodeFromCrCode(cr
));
1646 if (CreationFlags
& DICD_GENERATE_ID
)
1648 /* Grab the actual instance ID that was created */
1649 cr
= CM_Get_Device_ID_Ex(DevInst
,
1654 if (cr
!= CR_SUCCESS
)
1656 SetLastError(GetErrorCodeFromCrCode(cr
));
1660 DeviceName
= GenInstanceId
;
1661 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName
));
1664 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1666 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1668 if (!DeviceInfoData
)
1672 if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1674 SetLastError(ERROR_INVALID_USER_BUFFER
);
1678 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1679 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1680 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1688 if (deviceInfo
!= NULL
)
1690 /* Remove deviceInfo from List */
1691 RemoveEntryList(&deviceInfo
->ListEntry
);
1693 /* Destroy deviceInfo */
1694 DestroyDeviceInfo(deviceInfo
);
1698 TRACE("Returning %d\n", ret
);
1702 /***********************************************************************
1703 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1705 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1706 HDEVINFO DeviceInfoSet
,
1707 PSP_DEVINFO_DATA DeviceInfoData
,
1709 PSP_DETSIG_CMPPROC CompareProc
,
1710 PVOID CompareContext
,
1711 PSP_DEVINFO_DATA DupDeviceInfoData
)
1713 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1714 WCHAR DevInstId
[MAX_DEVICE_ID_LEN
];
1715 DEVINST ParentDevInst
;
1717 DWORD dwError
= ERROR_SUCCESS
;
1719 TRACE("%s(%p %p %08x %p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Flags
,
1720 CompareProc
, CompareContext
, DupDeviceInfoData
);
1722 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1724 SetLastError(ERROR_INVALID_HANDLE
);
1727 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1729 SetLastError(ERROR_INVALID_HANDLE
);
1732 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1733 || !DeviceInfoData
->Reserved
)
1735 SetLastError(ERROR_INVALID_PARAMETER
);
1739 if (Flags
& ~SPRDI_FIND_DUPS
)
1741 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~SPRDI_FIND_DUPS
);
1742 SetLastError(ERROR_INVALID_FLAGS
);
1746 if (Flags
& SPRDI_FIND_DUPS
)
1748 FIXME("Unimplemented codepath!\n");
1751 CM_Get_Device_ID_Ex(DeviceInfoData
->DevInst
,
1757 CM_Get_Parent_Ex(&ParentDevInst
,
1758 DeviceInfoData
->DevInst
,
1762 cr
= CM_Create_DevInst_Ex(&DeviceInfoData
->DevInst
,
1765 CM_CREATE_DEVINST_NORMAL
| CM_CREATE_DEVINST_DO_NOT_INSTALL
,
1767 if (cr
!= CR_SUCCESS
&&
1768 cr
!= CR_ALREADY_SUCH_DEVINST
)
1770 dwError
= ERROR_NO_SUCH_DEVINST
;
1773 SetLastError(dwError
);
1775 return (dwError
== ERROR_SUCCESS
);
1778 /***********************************************************************
1779 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1781 BOOL WINAPI
SetupDiEnumDeviceInfo(
1784 PSP_DEVINFO_DATA info
)
1788 TRACE("%s(%p %d %p)\n", __FUNCTION__
, devinfo
, index
, info
);
1792 SetLastError(ERROR_INVALID_PARAMETER
);
1795 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1797 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1798 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1800 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1801 SetLastError(ERROR_INVALID_USER_BUFFER
);
1804 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1805 while (ItemList
!= &list
->ListHead
&& index
-- > 0)
1806 ItemList
= ItemList
->Flink
;
1807 if (ItemList
== &list
->ListHead
)
1808 SetLastError(ERROR_NO_MORE_ITEMS
);
1811 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1812 memcpy(&info
->ClassGuid
,
1813 &DevInfo
->ClassGuid
,
1815 info
->DevInst
= DevInfo
->dnDevInst
;
1816 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1822 SetLastError(ERROR_INVALID_HANDLE
);
1825 SetLastError(ERROR_INVALID_HANDLE
);
1829 /***********************************************************************
1830 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1832 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1833 HDEVINFO DeviceInfoSet
,
1834 PSP_DEVINFO_DATA DeviceInfoData
,
1835 PSTR DeviceInstanceId
,
1836 DWORD DeviceInstanceIdSize
,
1837 PDWORD RequiredSize
)
1843 TRACE("%s(%p %p %p %d %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1844 DeviceInstanceIdSize
, RequiredSize
);
1846 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1848 SetLastError(ERROR_INVALID_PARAMETER
);
1852 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1857 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1859 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
1862 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1869 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
1871 DeviceInstanceIdSize
, NULL
, NULL
);
1877 if (len
> DeviceInstanceIdSize
)
1879 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1883 *RequiredSize
= len
;
1891 *RequiredSize
= size
;
1892 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1898 /***********************************************************************
1899 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1901 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
1902 HDEVINFO DeviceInfoSet
,
1903 PSP_DEVINFO_DATA DeviceInfoData
,
1904 PWSTR DeviceInstanceId
,
1905 DWORD DeviceInstanceIdSize
,
1906 PDWORD RequiredSize
)
1908 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1909 struct DeviceInfo
*devInfo
;
1911 TRACE("%s(%p %p %p %d %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1912 DeviceInstanceIdSize
, RequiredSize
);
1914 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1916 SetLastError(ERROR_INVALID_HANDLE
);
1919 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1921 SetLastError(ERROR_INVALID_HANDLE
);
1924 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1925 || !DeviceInfoData
->Reserved
)
1927 SetLastError(ERROR_INVALID_PARAMETER
);
1930 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1931 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1933 SetLastError(ERROR_INVALID_PARAMETER
);
1936 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
1938 SetLastError(ERROR_INVALID_PARAMETER
);
1941 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
1942 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
1944 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1946 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1949 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
1951 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1955 /***********************************************************************
1956 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1958 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
1960 PCSTR InfSectionName
,
1961 PSTR InfSectionWithExt
,
1962 DWORD InfSectionWithExtSize
,
1963 PDWORD RequiredSize
,
1966 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
1967 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
1971 /***********************************************************************
1972 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1974 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
1976 PCWSTR InfSectionName
,
1977 PWSTR InfSectionWithExt
,
1978 DWORD InfSectionWithExtSize
,
1979 PDWORD RequiredSize
,
1982 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
1983 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
1987 /***********************************************************************
1988 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
1991 SetupDiGetActualSectionToInstallExA(
1993 IN PCSTR InfSectionName
,
1994 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
1995 OUT PSTR InfSectionWithExt OPTIONAL
,
1996 IN DWORD InfSectionWithExtSize
,
1997 OUT PDWORD RequiredSize OPTIONAL
,
1998 OUT PSTR
* Extension OPTIONAL
,
2001 LPWSTR InfSectionNameW
= NULL
;
2002 LPWSTR InfSectionWithExtW
= NULL
;
2004 BOOL bResult
= FALSE
;
2006 TRACE("%s()\n", __FUNCTION__
);
2010 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2011 if (InfSectionNameW
== NULL
)
2014 if (InfSectionWithExt
)
2016 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2017 if (InfSectionWithExtW
== NULL
)
2021 bResult
= SetupDiGetActualSectionToInstallExW(
2022 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2023 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2024 InfSectionWithExtSize
,
2026 Extension
? &ExtensionW
: NULL
,
2029 if (bResult
&& InfSectionWithExt
)
2031 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2032 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2034 if (bResult
&& Extension
)
2036 if (ExtensionW
== NULL
)
2039 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2043 MyFree(InfSectionNameW
);
2044 MyFree(InfSectionWithExtW
);
2049 /***********************************************************************
2050 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2052 BOOL WINAPI
SetupDiGetClassDescriptionA(
2053 const GUID
* ClassGuid
,
2054 PSTR ClassDescription
,
2055 DWORD ClassDescriptionSize
,
2056 PDWORD RequiredSize
)
2058 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2059 ClassDescriptionSize
,
2060 RequiredSize
, NULL
, NULL
);
2063 /***********************************************************************
2064 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2066 BOOL WINAPI
SetupDiGetClassDescriptionW(
2067 const GUID
* ClassGuid
,
2068 PWSTR ClassDescription
,
2069 DWORD ClassDescriptionSize
,
2070 PDWORD RequiredSize
)
2072 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2073 ClassDescriptionSize
,
2074 RequiredSize
, NULL
, NULL
);
2077 /***********************************************************************
2078 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2080 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2081 const GUID
* ClassGuid
,
2082 PSTR ClassDescription
,
2083 DWORD ClassDescriptionSize
,
2084 PDWORD RequiredSize
,
2088 PWCHAR ClassDescriptionW
= NULL
;
2089 LPWSTR MachineNameW
= NULL
;
2092 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), ClassDescription
,
2093 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2095 if (ClassDescriptionSize
> 0)
2097 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2098 if (!ClassDescriptionW
)
2100 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2107 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
2110 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2115 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2116 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2119 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2120 ClassDescriptionSize
, NULL
, NULL
);
2121 if (len
== 0 || len
> ClassDescriptionSize
)
2123 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2129 MyFree(ClassDescriptionW
);
2130 MyFree(MachineNameW
);
2134 /***********************************************************************
2135 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2137 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2138 const GUID
* ClassGuid
,
2139 PWSTR ClassDescription
,
2140 DWORD ClassDescriptionSize
,
2141 PDWORD RequiredSize
,
2151 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), ClassDescription
,
2152 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2154 /* Make sure there's a GUID */
2157 SetLastError(ERROR_INVALID_PARAMETER
);
2161 /* Make sure there's a real buffer when there's a size */
2162 if (!ClassDescription
&& ClassDescriptionSize
> 0)
2164 SetLastError(ERROR_INVALID_PARAMETER
);
2168 /* Open the key for the GUID */
2169 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2174 if (hKey
== INVALID_HANDLE_VALUE
)
2177 /* Retrieve the class description data and close the key */
2178 rc
= QueryRegistryValue(hKey
, NULL
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
2181 /* Make sure we got the data */
2182 if (rc
!= ERROR_SUCCESS
)
2188 /* Make sure the data is a string */
2189 if (dwRegType
!= REG_SZ
)
2192 SetLastError(ERROR_GEN_FAILURE
);
2196 /* Determine the length of the class description */
2197 dwLength
/= sizeof(WCHAR
);
2199 /* Count the null-terminator if none is present */
2200 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
2203 /* Inform the caller about the class description */
2204 if ((ClassDescription
!= NULL
) && (dwLength
<= ClassDescriptionSize
))
2206 memcpy(ClassDescription
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
2207 ClassDescription
[dwLength
- 1] = UNICODE_NULL
;
2210 /* Inform the caller about the required size */
2211 if (RequiredSize
!= NULL
)
2212 *RequiredSize
= dwLength
;
2214 /* Clean up the buffer */
2217 /* Make sure the buffer was large enough */
2218 if ((ClassDescription
== NULL
) || (dwLength
> ClassDescriptionSize
))
2220 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2227 /***********************************************************************
2228 * SetupDiGetClassDevsA (SETUPAPI.@)
2230 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2236 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2237 flags
, NULL
, NULL
, NULL
);
2240 /***********************************************************************
2241 * SetupDiGetClassDevsExA (SETUPAPI.@)
2243 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2253 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2257 enumstrW
= pSetupMultiByteToUnicode(enumstr
, CP_ACP
);
2260 ret
= INVALID_HANDLE_VALUE
;
2266 machineW
= pSetupMultiByteToUnicode(machine
, CP_ACP
);
2270 ret
= INVALID_HANDLE_VALUE
;
2274 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2275 machineW
, reserved
);
2283 /***********************************************************************
2284 * SetupDiGetClassDevsW (SETUPAPI.@)
2286 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2292 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2296 /***********************************************************************
2297 * SetupDiGetClassDevsExW (SETUPAPI.@)
2299 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2308 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2309 struct DeviceInfoSet
*list
;
2310 CONST GUID
*pClassGuid
;
2312 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2314 TRACE("%s(%s %s %p 0x%08x %p %s %p)\n", __FUNCTION__
, debugstr_guid(class),
2315 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2318 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2320 SetLastError(ERROR_INVALID_PARAMETER
);
2321 return INVALID_HANDLE_VALUE
;
2324 /* Create the deviceset if not set */
2327 list
= (struct DeviceInfoSet
*)deviceset
;
2328 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2330 SetLastError(ERROR_INVALID_HANDLE
);
2333 hDeviceInfo
= deviceset
;
2337 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2338 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2339 NULL
, machine
, NULL
);
2340 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2342 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2345 if (flags
& DIGCF_PROFILE
)
2346 FIXME(": flag DIGCF_PROFILE ignored\n");
2348 if (flags
& DIGCF_DEVICEINTERFACE
)
2352 SetLastError(ERROR_INVALID_PARAMETER
);
2355 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2359 /* Determine which class(es) should be included in the deviceset */
2360 if (flags
& DIGCF_ALLCLASSES
)
2362 /* The caller wants all classes. Check if
2363 * the deviceset limits us to one class */
2364 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2367 pClassGuid
= &list
->ClassGuid
;
2371 /* The caller wants one class. Check if it matches deviceset class */
2372 if (IsEqualIID(&list
->ClassGuid
, class)
2373 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2379 SetLastError(ERROR_INVALID_PARAMETER
);
2383 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2385 /* No class specified. Try to use the one of the deviceset */
2386 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2387 pClassGuid
= &list
->ClassGuid
;
2390 SetLastError(ERROR_INVALID_PARAMETER
);
2396 SetLastError(ERROR_INVALID_PARAMETER
);
2399 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2401 if (rc
!= ERROR_SUCCESS
)
2409 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2410 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2414 /***********************************************************************
2415 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2417 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2418 HDEVINFO DeviceInfoSet
,
2419 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2421 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2423 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DevInfoData
);
2425 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2427 SetLastError(ERROR_INVALID_HANDLE
);
2430 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2432 SetLastError(ERROR_INVALID_HANDLE
);
2436 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2438 SetLastError(ERROR_INVALID_PARAMETER
);
2441 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2442 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2443 if (set
->MachineName
)
2446 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2450 DevInfoData
->RemoteMachineName
[0] = 0;
2455 /***********************************************************************
2456 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2458 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2459 HDEVINFO DeviceInfoSet
,
2460 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2462 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2464 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DevInfoData
);
2466 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2468 SetLastError(ERROR_INVALID_HANDLE
);
2471 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2473 SetLastError(ERROR_INVALID_HANDLE
);
2477 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2479 SetLastError(ERROR_INVALID_PARAMETER
);
2482 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2483 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2484 if (set
->MachineName
)
2485 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2487 DevInfoData
->RemoteMachineName
[0] = 0;
2492 /***********************************************************************
2493 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2495 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2496 HDEVINFO DeviceInfoSet
,
2497 PSP_DEVINFO_DATA DeviceInfoData
,
2498 const GUID
*InterfaceClassGuid
,
2499 PCSTR ReferenceString
,
2500 DWORD CreationFlags
,
2501 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2504 LPWSTR ReferenceStringW
= NULL
;
2506 TRACE("%s(%p %p %s %s %08x %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
2507 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2508 CreationFlags
, DeviceInterfaceData
);
2510 if (ReferenceString
)
2512 ReferenceStringW
= pSetupMultiByteToUnicode(ReferenceString
, CP_ACP
);
2513 if (ReferenceStringW
== NULL
) return FALSE
;
2516 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2517 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2518 DeviceInterfaceData
);
2520 MyFree(ReferenceStringW
);
2525 /***********************************************************************
2526 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2528 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2529 HDEVINFO DeviceInfoSet
,
2530 PSP_DEVINFO_DATA DeviceInfoData
,
2531 const GUID
*InterfaceClassGuid
,
2532 PCWSTR ReferenceString
,
2533 DWORD CreationFlags
,
2534 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2536 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2537 TRACE("%s(%p %p %s %s %08x %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
2538 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2539 CreationFlags
, DeviceInterfaceData
);
2541 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2543 SetLastError(ERROR_INVALID_HANDLE
);
2546 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2548 SetLastError(ERROR_INVALID_HANDLE
);
2551 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2552 || !DeviceInfoData
->Reserved
)
2554 SetLastError(ERROR_INVALID_PARAMETER
);
2557 if (!InterfaceClassGuid
)
2559 SetLastError(ERROR_INVALID_USER_BUFFER
);
2563 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2564 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2565 CreationFlags
, DeviceInterfaceData
);
2566 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2570 /***********************************************************************
2571 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2573 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2574 HDEVINFO DeviceInfoSet
,
2575 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2579 PCSTR InfSectionName
)
2582 PWSTR InfSectionNameW
= NULL
;
2584 TRACE("%s(%p %p %d %08x %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2585 samDesired
, InfHandle
, InfSectionName
);
2588 if (!InfSectionName
)
2590 SetLastError(ERROR_INVALID_PARAMETER
);
2591 return INVALID_HANDLE_VALUE
;
2593 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2594 if (!InfSectionNameW
)
2595 return INVALID_HANDLE_VALUE
;
2597 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2598 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2600 MyFree(InfSectionNameW
);
2604 /***********************************************************************
2605 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2607 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2608 HDEVINFO DeviceInfoSet
,
2609 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2613 PCWSTR InfSectionName
)
2616 LPWSTR SymbolicLink
;
2617 DWORD Length
, Index
;
2619 WCHAR bracedGuidString
[39];
2620 struct DeviceInterface
*DevItf
;
2621 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2623 TRACE("%s(%p %p %d %08x %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2624 samDesired
, InfHandle
, InfSectionName
);
2626 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2627 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2629 SetLastError(ERROR_INVALID_HANDLE
);
2630 return INVALID_HANDLE_VALUE
;
2632 if (!DeviceInterfaceData
||
2633 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2634 !DeviceInterfaceData
->Reserved
)
2636 SetLastError(ERROR_INVALID_PARAMETER
);
2637 return INVALID_HANDLE_VALUE
;
2639 if (InfHandle
&& !InfSectionName
)
2641 SetLastError(ERROR_INVALID_PARAMETER
);
2642 return INVALID_HANDLE_VALUE
;
2645 hKey
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2646 if (hKey
== INVALID_HANDLE_VALUE
)
2648 hKey
= SetupDiOpenClassRegKeyExW(NULL
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2649 if (hKey
== INVALID_HANDLE_VALUE
)
2651 SetLastError(ERROR_INVALID_PARAMETER
);
2652 return INVALID_HANDLE_VALUE
;
2654 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
, bracedGuidString
);
2656 if (RegCreateKeyExW(hKey
, bracedGuidString
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
) != ERROR_SUCCESS
)
2658 SetLastError(ERROR_INVALID_PARAMETER
);
2659 return INVALID_HANDLE_VALUE
;
2665 DevItf
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2667 Length
= (wcslen(DevItf
->SymbolicLink
)+1) * sizeof(WCHAR
);
2668 SymbolicLink
= HeapAlloc(GetProcessHeap(), 0, Length
);
2672 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2673 return INVALID_HANDLE_VALUE
;
2676 wcscpy(SymbolicLink
, DevItf
->SymbolicLink
);
2679 while(SymbolicLink
[Index
])
2681 if (SymbolicLink
[Index
] == L
'\\')
2683 SymbolicLink
[Index
] = L
'#';
2688 rc
= RegCreateKeyExW(hKey
, SymbolicLink
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
);
2691 HeapFree(GetProcessHeap(), 0, SymbolicLink
);
2693 if (rc
== ERROR_SUCCESS
)
2695 if (InfHandle
&& InfSectionName
)
2697 if (!SetupInstallFromInfSection(NULL
/*FIXME */,
2700 SPINST_INIFILES
| SPINST_REGISTRY
| SPINST_INI2REG
| SPINST_FILES
| SPINST_BITREG
| SPINST_REGSVR
| SPINST_UNREGSVR
| SPINST_PROFILEITEMS
| SPINST_COPYINF
,
2704 set
->SelectedDevice
->InstallParams
.InstallMsgHandler
,
2705 set
->SelectedDevice
->InstallParams
.InstallMsgHandlerContext
,
2706 INVALID_HANDLE_VALUE
,
2709 RegCloseKey(hDevKey
);
2710 return INVALID_HANDLE_VALUE
;
2719 /***********************************************************************
2720 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2722 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2723 HDEVINFO DeviceInfoSet
,
2724 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2727 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2730 TRACE("%s(%p %p %d)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2732 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2733 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2735 SetLastError(ERROR_INVALID_HANDLE
);
2738 if (!DeviceInterfaceData
||
2739 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2740 !DeviceInterfaceData
->Reserved
)
2742 SetLastError(ERROR_INVALID_PARAMETER
);
2746 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2747 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2751 /***********************************************************************
2752 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2755 * DeviceInfoSet [I] Set of devices from which to enumerate
2757 * DeviceInfoData [I] (Optional) If specified, a specific device
2758 * instance from which to enumerate interfaces.
2759 * If it isn't specified, all interfaces for all
2760 * devices in the set are enumerated.
2761 * InterfaceClassGuid [I] The interface class to enumerate.
2762 * MemberIndex [I] An index of the interface instance to enumerate.
2763 * A caller should start with MemberIndex set to 0,
2764 * and continue until the function fails with
2765 * ERROR_NO_MORE_ITEMS.
2766 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2767 * member must be set to
2768 * sizeof(SP_DEVICE_INTERFACE_DATA).
2771 * Success: non-zero value.
2772 * Failure: FALSE. Call GetLastError() for more info.
2774 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2775 HDEVINFO DeviceInfoSet
,
2776 PSP_DEVINFO_DATA DeviceInfoData
,
2777 CONST GUID
* InterfaceClassGuid
,
2779 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2781 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2784 TRACE("%s(%p, %p, %s, %d, %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
2785 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2787 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2788 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2790 SetLastError(ERROR_INVALID_HANDLE
);
2793 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2794 !DeviceInfoData
->Reserved
))
2796 SetLastError(ERROR_INVALID_PARAMETER
);
2799 if (!DeviceInterfaceData
||
2800 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2802 SetLastError(ERROR_INVALID_PARAMETER
);
2807 struct DeviceInfo
*devInfo
=
2808 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2810 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2811 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2813 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2814 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2816 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2819 if (MemberIndex
-- == 0)
2821 /* return this item */
2822 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2823 &DevItf
->InterfaceClassGuid
,
2825 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2826 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2830 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2833 SetLastError(ERROR_NO_MORE_ITEMS
);
2838 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
2839 while (ItemList
!= &set
->ListHead
&& !found
)
2841 PLIST_ENTRY InterfaceListEntry
;
2842 struct DeviceInfo
*devInfo
=
2843 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
2844 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2845 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2847 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2848 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2850 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2853 if (MemberIndex
-- == 0)
2855 /* return this item */
2856 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2857 &DevItf
->InterfaceClassGuid
,
2859 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2860 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2864 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2866 ItemList
= ItemList
->Flink
;
2870 SetLastError(ERROR_NO_MORE_ITEMS
);
2875 /***********************************************************************
2876 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2878 * Destroy a DeviceInfoList and free all used memory of the list.
2881 * devinfo [I] DeviceInfoList pointer to list to destroy
2884 * Success: non zero value.
2885 * Failure: zero value.
2887 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2891 TRACE("%s(%p)\n", __FUNCTION__
, devinfo
);
2892 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
2894 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2896 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
2898 ret
= DestroyDeviceInfoSet(list
);
2903 SetLastError(ERROR_INVALID_HANDLE
);
2908 /***********************************************************************
2909 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2911 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2912 HDEVINFO DeviceInfoSet
,
2913 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2914 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2915 DWORD DeviceInterfaceDetailDataSize
,
2916 PDWORD RequiredSize
,
2917 PSP_DEVINFO_DATA DeviceInfoData
)
2919 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2920 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2921 DWORD sizeW
= 0, bytesNeeded
;
2924 TRACE("%s(%p, %p, %p, %d, %p, %p)\n", __FUNCTION__
, DeviceInfoSet
,
2925 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2926 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2928 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2929 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2931 SetLastError(ERROR_INVALID_HANDLE
);
2934 if (!DeviceInterfaceData
||
2935 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2936 !DeviceInterfaceData
->Reserved
)
2938 SetLastError(ERROR_INVALID_PARAMETER
);
2941 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
2943 SetLastError(ERROR_INVALID_USER_BUFFER
);
2947 if((DeviceInterfaceDetailDataSize
!= 0) &&
2948 (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + sizeof(CHAR
))))
2950 SetLastError(ERROR_INVALID_USER_BUFFER
);
2954 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2956 SetLastError(ERROR_INVALID_USER_BUFFER
);
2961 if (DeviceInterfaceDetailData
!= NULL
)
2963 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2964 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2965 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
2966 if (!DeviceInterfaceDetailDataW
)
2968 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2970 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2972 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2974 ret
= SetupDiGetDeviceInterfaceDetailW(
2976 DeviceInterfaceData
,
2977 DeviceInterfaceDetailDataW
,
2981 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2982 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2984 *RequiredSize
= bytesNeeded
;
2985 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
>= bytesNeeded
)
2987 if (!WideCharToMultiByte(
2989 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2990 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2997 MyFree(DeviceInterfaceDetailDataW
);
3002 /***********************************************************************
3003 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3005 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
3006 HDEVINFO DeviceInfoSet
,
3007 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3008 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
3009 DWORD DeviceInterfaceDetailDataSize
,
3010 PDWORD RequiredSize
,
3011 PSP_DEVINFO_DATA DeviceInfoData
)
3013 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3016 TRACE("%s(%p, %p, %p, %d, %p, %p)\n", __FUNCTION__
, DeviceInfoSet
,
3017 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3018 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3020 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3021 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3023 SetLastError(ERROR_INVALID_HANDLE
);
3026 if (!DeviceInterfaceData
||
3027 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3028 !DeviceInterfaceData
->Reserved
)
3030 SetLastError(ERROR_INVALID_PARAMETER
);
3033 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
3035 SetLastError(ERROR_INVALID_USER_BUFFER
);
3038 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3040 SetLastError(ERROR_INVALID_USER_BUFFER
);
3043 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3045 SetLastError(ERROR_INVALID_PARAMETER
);
3048 if ((DeviceInterfaceDetailData
!= NULL
)
3049 && (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) + sizeof(WCHAR
)))
3051 SetLastError(ERROR_INVALID_PARAMETER
);
3056 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
3057 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
3058 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
3059 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
3061 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
3063 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3065 *RequiredSize
= sizeRequired
;
3069 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3070 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3073 memcpy(&DeviceInfoData
->ClassGuid
,
3074 &deviceInterface
->DeviceInfo
->ClassGuid
,
3076 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3077 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3085 struct PropertyMapEntry
3092 static struct PropertyMapEntry PropertyMap
[] = {
3093 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3094 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3095 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3096 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3097 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3098 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3099 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3100 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3101 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3102 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3103 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3104 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3105 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3106 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3107 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3108 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3109 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3110 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3111 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3112 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3113 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3114 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3115 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3116 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3117 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3118 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3119 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3120 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3121 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3122 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3123 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3124 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3125 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3126 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3127 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3130 /***********************************************************************
3131 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3133 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3134 HDEVINFO DeviceInfoSet
,
3135 PSP_DEVINFO_DATA DeviceInfoData
,
3137 PDWORD PropertyRegDataType
,
3138 PBYTE PropertyBuffer
,
3139 DWORD PropertyBufferSize
,
3140 PDWORD RequiredSize
)
3143 BOOL bIsStringProperty
;
3145 DWORD RequiredSizeA
, RequiredSizeW
;
3146 DWORD PropertyBufferSizeW
= 0;
3147 PBYTE PropertyBufferW
= NULL
;
3149 TRACE("%s(%p %p %d %p %p %d %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
3150 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3153 if (PropertyBufferSize
!= 0)
3155 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3156 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3157 if (!PropertyBufferW
)
3159 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3164 ret
= SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
3169 PropertyBufferSizeW
,
3172 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3174 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
3176 if (bIsStringProperty
)
3177 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
3179 RequiredSizeA
= RequiredSizeW
;
3181 *RequiredSize
= RequiredSizeA
;
3182 if (PropertyRegDataType
)
3183 *PropertyRegDataType
= RegType
;
3188 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3192 if (RequiredSizeA
<= PropertyBufferSize
)
3194 if (bIsStringProperty
&& PropertyBufferSize
> 0)
3196 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
3198 /* Last error is already set by WideCharToMultiByte */
3203 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
3207 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3211 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3215 /***********************************************************************
3216 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3218 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3219 HDEVINFO DeviceInfoSet
,
3220 PSP_DEVINFO_DATA DeviceInfoData
,
3222 PDWORD PropertyRegDataType
,
3223 PBYTE PropertyBuffer
,
3224 DWORD PropertyBufferSize
,
3225 PDWORD RequiredSize
)
3227 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3228 struct DeviceInfo
*devInfo
;
3230 LONG lError
= ERROR_SUCCESS
;
3233 TRACE("%s(%p %p %d %p %p %d %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
3234 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3237 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3239 SetLastError(ERROR_INVALID_HANDLE
);
3242 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3244 SetLastError(ERROR_INVALID_HANDLE
);
3247 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3248 || !DeviceInfoData
->Reserved
)
3250 SetLastError(ERROR_INVALID_PARAMETER
);
3254 if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
3256 SetLastError(ERROR_INVALID_REG_PROPERTY
);
3260 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3262 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3263 && PropertyMap
[Property
].nameW
)
3266 size
= PropertyBufferSize
;
3267 hKey
= SETUPDI_OpenDevKey(set
->HKLM
, devInfo
, KEY_QUERY_VALUE
);
3268 if (hKey
== INVALID_HANDLE_VALUE
)
3270 lError
= RegQueryValueExW(hKey
, PropertyMap
[Property
].nameW
,
3271 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3275 *RequiredSize
= size
;
3280 if (PropertyBuffer
== NULL
&& size
!= 0)
3281 lError
= ERROR_INSUFFICIENT_BUFFER
;
3283 case ERROR_MORE_DATA
:
3284 lError
= ERROR_INSUFFICIENT_BUFFER
;
3290 else if (Property
== SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
)
3292 size
= (strlenW(devInfo
->Data
) + 1) * sizeof(WCHAR
);
3294 if (PropertyRegDataType
)
3295 *PropertyRegDataType
= REG_SZ
;
3297 *RequiredSize
= size
;
3298 if (PropertyBufferSize
>= size
)
3300 strcpyW((LPWSTR
)PropertyBuffer
, devInfo
->Data
);
3303 lError
= ERROR_INSUFFICIENT_BUFFER
;
3307 size
= PropertyBufferSize
;
3309 cr
= CM_Get_DevNode_Registry_Property_ExW(devInfo
->dnDevInst
,
3310 Property
+ (CM_DRP_DEVICEDESC
- SPDRP_DEVICEDESC
),
3311 PropertyRegDataType
,
3316 if ((cr
== CR_SUCCESS
) || (cr
== CR_BUFFER_SMALL
))
3319 *RequiredSize
= size
;
3322 if (cr
!= CR_SUCCESS
)
3326 case CR_INVALID_DEVINST
:
3327 lError
= ERROR_NO_SUCH_DEVINST
;
3330 case CR_INVALID_PROPERTY
:
3331 lError
= ERROR_INVALID_REG_PROPERTY
;
3334 case CR_BUFFER_SMALL
:
3335 lError
= ERROR_INSUFFICIENT_BUFFER
;
3339 lError
= ERROR_INVALID_DATA
;
3345 SetLastError(lError
);
3346 return (lError
== ERROR_SUCCESS
);
3349 /***********************************************************************
3350 * Internal for SetupDiSetDeviceRegistryPropertyA/W
3352 BOOL WINAPI
IntSetupDiSetDeviceRegistryPropertyAW(
3353 HDEVINFO DeviceInfoSet
,
3354 PSP_DEVINFO_DATA DeviceInfoData
,
3356 const BYTE
*PropertyBuffer
,
3357 DWORD PropertyBufferSize
,
3361 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3362 struct DeviceInfo
*deviceInfo
;
3364 TRACE("%s(%p %p %d %p %d)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Property
,
3365 PropertyBuffer
, PropertyBufferSize
);
3367 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3369 SetLastError(ERROR_INVALID_HANDLE
);
3372 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3374 SetLastError(ERROR_INVALID_HANDLE
);
3377 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3378 || !DeviceInfoData
->Reserved
)
3380 SetLastError(ERROR_INVALID_PARAMETER
);
3384 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3386 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3387 && PropertyMap
[Property
].nameW
3388 && PropertyMap
[Property
].nameA
)
3392 hKey
= SETUPDI_OpenDevKey(set
->HKLM
, deviceInfo
, KEY_SET_VALUE
);
3393 if (hKey
== INVALID_HANDLE_VALUE
)
3395 /* Write new data */
3399 hKey
, PropertyMap
[Property
].nameA
, 0,
3400 PropertyMap
[Property
].regType
, PropertyBuffer
,
3401 PropertyBufferSize
);
3406 hKey
, PropertyMap
[Property
].nameW
, 0,
3407 PropertyMap
[Property
].regType
, PropertyBuffer
,
3408 PropertyBufferSize
);
3418 ERR("Property 0x%lx not implemented\n", Property
);
3419 SetLastError(ERROR_NOT_SUPPORTED
);
3422 TRACE("Returning %d\n", ret
);
3425 /***********************************************************************
3426 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3428 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3429 HDEVINFO DeviceInfoSet
,
3430 PSP_DEVINFO_DATA DeviceInfoData
,
3432 const BYTE
*PropertyBuffer
,
3433 DWORD PropertyBufferSize
)
3435 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet
,
3443 /***********************************************************************
3444 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3446 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3447 HDEVINFO DeviceInfoSet
,
3448 PSP_DEVINFO_DATA DeviceInfoData
,
3450 const BYTE
*PropertyBuffer
,
3451 DWORD PropertyBufferSize
)
3453 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet
,
3461 /***********************************************************************
3462 * SetupDiInstallClassA (SETUPAPI.@)
3464 BOOL WINAPI
SetupDiInstallClassA(
3470 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3473 /***********************************************************************
3474 * SetupDiInstallClassExA (SETUPAPI.@)
3477 SetupDiInstallClassExA(
3478 IN HWND hwndParent OPTIONAL
,
3479 IN PCSTR InfFileName OPTIONAL
,
3481 IN HSPFILEQ FileQueue OPTIONAL
,
3482 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3486 PWSTR InfFileNameW
= NULL
;
3491 SetLastError(ERROR_INVALID_PARAMETER
);
3496 InfFileNameW
= pSetupMultiByteToUnicode(InfFileName
, CP_ACP
);
3497 if (InfFileNameW
== NULL
)
3499 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3504 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3505 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3507 MyFree(InfFileNameW
);
3512 HKEY
SETUP_CreateClassKey(HINF hInf
)
3514 WCHAR FullBuffer
[MAX_PATH
];
3515 WCHAR Buffer
[MAX_PATH
];
3520 /* Obtain the Class GUID for this class */
3521 if (!SetupGetLineTextW(NULL
,
3524 REGSTR_VAL_CLASSGUID
,
3526 sizeof(Buffer
) / sizeof(WCHAR
),
3529 return INVALID_HANDLE_VALUE
;
3532 /* Build the corresponding registry key name */
3533 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3534 lstrcatW(FullBuffer
, BackSlash
);
3535 lstrcatW(FullBuffer
, Buffer
);
3537 /* Obtain the Class name for this class */
3538 if (!SetupGetLineTextW(NULL
,
3543 sizeof(Buffer
) / sizeof(WCHAR
),
3546 return INVALID_HANDLE_VALUE
;
3549 /* Try to open or create the registry key */
3550 TRACE("Opening class key %s\n", debugstr_w(FullBuffer
));
3551 #if 0 // I keep this for reference...
3552 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3558 /* Use RegCreateKeyExW */
3561 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3565 REG_OPTION_NON_VOLATILE
,
3571 ERR("RegCreateKeyExW(%s) failed\n", debugstr_w(FullBuffer
));
3572 return INVALID_HANDLE_VALUE
;
3574 if (Disposition
== REG_CREATED_NEW_KEY
)
3575 TRACE("The class key %s was successfully created\n", debugstr_w(FullBuffer
));
3577 TRACE("The class key %s was successfully opened\n", debugstr_w(FullBuffer
));
3579 TRACE( "setting value %s to %s\n", debugstr_w(REGSTR_VAL_CLASS
), debugstr_w(Buffer
) );
3580 if (RegSetValueExW(hClassKey
,
3585 RequiredSize
* sizeof(WCHAR
)))
3587 RegCloseKey(hClassKey
);
3588 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3590 return INVALID_HANDLE_VALUE
;
3596 /***********************************************************************
3597 * SetupDiInstallClassW (SETUPAPI.@)
3599 BOOL WINAPI
SetupDiInstallClassW(
3605 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3609 /***********************************************************************
3610 * SetupDiOpenClassRegKey (SETUPAPI.@)
3612 HKEY WINAPI
SetupDiOpenClassRegKey(
3613 const GUID
* ClassGuid
,
3616 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3617 DIOCR_INSTALLER
, NULL
, NULL
);
3621 /***********************************************************************
3622 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3624 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3625 const GUID
* ClassGuid
,
3631 PWSTR MachineNameW
= NULL
;
3634 TRACE("%s(%s 0x%lx 0x%lx %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), samDesired
,
3635 Flags
, debugstr_a(MachineName
), Reserved
);
3639 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
3640 if (MachineNameW
== NULL
)
3641 return INVALID_HANDLE_VALUE
;
3644 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3645 Flags
, MachineNameW
, Reserved
);
3647 MyFree(MachineNameW
);
3653 /***********************************************************************
3654 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3656 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3657 const GUID
* ClassGuid
,
3669 TRACE("%s(%s 0x%lx 0x%lx %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), samDesired
,
3670 Flags
, debugstr_w(MachineName
), Reserved
);
3672 if (MachineName
!= NULL
)
3674 l
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3675 if (l
!= ERROR_SUCCESS
)
3678 return INVALID_HANDLE_VALUE
;
3682 HKLM
= HKEY_LOCAL_MACHINE
;
3684 if (Flags
== DIOCR_INSTALLER
)
3686 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3688 else if (Flags
== DIOCR_INTERFACE
)
3690 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3694 ERR("Invalid Flags parameter!\n");
3695 SetLastError(ERROR_INVALID_FLAGS
);
3696 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3697 return INVALID_HANDLE_VALUE
;
3702 if ((l
= RegOpenKeyExW(HKLM
,
3708 SetLastError(ERROR_INVALID_CLASS
);
3709 hClassesKey
= INVALID_HANDLE_VALUE
;
3711 if (MachineName
!= NULL
)
3717 WCHAR bracedGuidString
[39];
3719 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3721 if (!(l
= RegOpenKeyExW(HKLM
,
3727 if (MachineName
!= NULL
)
3730 if ((l
= RegOpenKeyExW(hClassesKey
,
3737 key
= INVALID_HANDLE_VALUE
;
3739 RegCloseKey(hClassesKey
);
3743 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3745 key
= INVALID_HANDLE_VALUE
;
3752 /***********************************************************************
3753 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3755 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3756 HDEVINFO DeviceInfoSet
,
3759 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3761 struct DeviceInfoSet
* list
;
3763 DWORD dwLength
, dwError
, dwIndex
, dwKeyName
, dwSubIndex
;
3765 WCHAR Buffer
[MAX_PATH
+ 1];
3766 WCHAR SymBuffer
[MAX_PATH
+ 1];
3767 WCHAR InstancePath
[MAX_PATH
+ 1];
3768 HKEY hKey
, hDevKey
, hSymKey
;
3769 struct DeviceInfo
* deviceInfo
;
3770 struct DeviceInterface
*deviceInterface
;
3772 PLIST_ENTRY ItemList
;
3773 PLIST_ENTRY InterfaceListEntry
;
3775 TRACE("%s(%p %s %08x %p)\n", __FUNCTION__
,
3776 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3779 if (DeviceInterfaceData
&& DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
3781 SetLastError(ERROR_INVALID_PARAMETER
);
3785 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3787 SetLastError(ERROR_INVALID_HANDLE
);
3791 list
= (struct DeviceInfoSet
* )DeviceInfoSet
;
3793 dwLength
= wcslen(DevicePath
);
3796 /* path must be at least a guid length + L'\0' */
3797 SetLastError(ERROR_BAD_PATHNAME
);
3801 if (DevicePath
[0] != L
'\\' ||
3802 DevicePath
[1] != L
'\\' ||
3803 (DevicePath
[2] != L
'?' && DevicePath
[2] != L
'.') ||
3804 DevicePath
[3] != L
'\\')
3806 /* invalid formatted path */
3807 SetLastError(ERROR_BAD_PATHNAME
);
3811 /* check for reference strings */
3812 pEnd
= wcschr(&DevicePath
[4], L
'\\');
3815 /* no reference string */
3816 pEnd
= DevicePath
+ dwLength
;
3820 wcscpy(Buffer
, pEnd
- 37);
3823 dwError
= UuidFromStringW(Buffer
, &ClassId
);
3824 if (dwError
!= NOERROR
)
3826 /* invalid formatted path */
3827 SetLastError(ERROR_BAD_PATHNAME
);
3831 hKey
= SetupDiOpenClassRegKeyExW(&ClassId
, KEY_READ
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
3833 if (hKey
== INVALID_HANDLE_VALUE
)
3835 /* invalid device class */
3839 ItemList
= list
->ListHead
.Flink
;
3840 while (ItemList
!= &list
->ListHead
)
3842 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
3843 InterfaceListEntry
= deviceInfo
->InterfaceListHead
.Flink
;
3844 while (InterfaceListEntry
!= &deviceInfo
->InterfaceListHead
)
3846 deviceInterface
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
3847 if (!IsEqualIID(&deviceInterface
->InterfaceClassGuid
, &ClassId
))
3849 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3853 if (!wcsicmp(deviceInterface
->SymbolicLink
, DevicePath
))
3855 if (DeviceInterfaceData
)
3857 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3858 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3859 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3873 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3874 dwError
= RegEnumKeyExW(hKey
, dwIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3876 if (dwError
!= ERROR_SUCCESS
)
3879 if (RegOpenKeyExW(hKey
, Buffer
, 0, KEY_READ
, &hDevKey
) != ERROR_SUCCESS
)
3883 InstancePath
[0] = 0;
3884 dwKeyName
= sizeof(InstancePath
);
3886 dwError
= RegQueryValueExW(hDevKey
, L
"DeviceInstance", NULL
, NULL
, (LPBYTE
)InstancePath
, &dwKeyName
);
3891 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3892 dwError
= RegEnumKeyExW(hDevKey
, dwSubIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3894 if (dwError
!= ERROR_SUCCESS
)
3897 dwError
= RegOpenKeyExW(hDevKey
, Buffer
, 0, KEY_READ
, &hSymKey
);
3898 if (dwError
!= ERROR_SUCCESS
)
3901 /* query for symbolic link */
3902 dwKeyName
= sizeof(SymBuffer
);
3903 SymBuffer
[0] = L
'\0';
3904 dwError
= RegQueryValueExW(hSymKey
, L
"SymbolicLink", NULL
, NULL
, (LPBYTE
)SymBuffer
, &dwKeyName
);
3906 if (dwError
!= ERROR_SUCCESS
)
3908 RegCloseKey(hSymKey
);
3912 if (!wcsicmp(SymBuffer
, DevicePath
))
3914 Ret
= CreateDeviceInfo(list
, InstancePath
, &ClassId
, &deviceInfo
);
3915 RegCloseKey(hSymKey
);
3916 RegCloseKey(hDevKey
);
3921 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymBuffer
) + 1) * sizeof(WCHAR
));
3922 if (deviceInterface
)
3925 CopyMemory(&deviceInterface
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3926 deviceInterface
->DeviceInfo
= deviceInfo
;
3927 deviceInterface
->Flags
= SPINT_ACTIVE
; //FIXME
3929 wcscpy(deviceInterface
->SymbolicLink
, SymBuffer
);
3931 InsertTailList(&deviceInfo
->InterfaceListHead
, &deviceInterface
->ListEntry
);
3932 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3935 if (DeviceInterfaceData
)
3937 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3938 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3939 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3944 SetLastError(ERROR_INVALID_USER_BUFFER
);
3950 HeapFree(GetProcessHeap(), 0, deviceInfo
);
3955 RegCloseKey(hSymKey
);
3959 RegCloseKey(hDevKey
);
3967 /***********************************************************************
3968 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3970 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3971 HDEVINFO DeviceInfoSet
,
3974 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3976 LPWSTR DevicePathW
= NULL
;
3979 TRACE("%s(%p %s %08lx %p)\n", __FUNCTION__
, DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3981 DevicePathW
= pSetupMultiByteToUnicode(DevicePath
, CP_ACP
);
3982 if (DevicePathW
== NULL
)
3985 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3986 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3988 MyFree(DevicePathW
);
3993 /***********************************************************************
3994 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3996 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3997 HDEVINFO DeviceInfoSet
,
3998 PSP_DEVINFO_DATA DeviceInfoData
,
3999 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
4000 DWORD ClassInstallParamsSize
)
4002 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
4003 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
4008 IntSetupDiRegisterDeviceInfo(
4009 IN HDEVINFO DeviceInfoSet
,
4010 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
4012 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
4015 /***********************************************************************
4016 * SetupDiCallClassInstaller (SETUPAPI.@)
4018 BOOL WINAPI
SetupDiCallClassInstaller(
4019 DI_FUNCTION InstallFunction
,
4020 HDEVINFO DeviceInfoSet
,
4021 PSP_DEVINFO_DATA DeviceInfoData
)
4025 TRACE("%s(%u %p %p)\n", __FUNCTION__
, InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4028 SetLastError(ERROR_INVALID_PARAMETER
);
4029 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4030 SetLastError(ERROR_INVALID_HANDLE
);
4031 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4032 SetLastError(ERROR_INVALID_HANDLE
);
4033 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
4034 SetLastError(ERROR_INVALID_HANDLE
);
4035 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4036 SetLastError(ERROR_INVALID_USER_BUFFER
);
4039 SP_DEVINSTALL_PARAMS_W InstallParams
;
4040 #define CLASS_COINSTALLER 0x1
4041 #define DEVICE_COINSTALLER 0x2
4042 #define CLASS_INSTALLER 0x4
4043 UCHAR CanHandle
= 0;
4044 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
4046 switch (InstallFunction
)
4048 case DIF_ADDPROPERTYPAGE_ADVANCED
:
4049 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4051 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
4052 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4054 case DIF_ALLOW_INSTALL
:
4055 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4058 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4060 case DIF_DESTROYPRIVATEDATA
:
4061 CanHandle
= CLASS_INSTALLER
;
4063 case DIF_INSTALLDEVICE
:
4064 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4065 DefaultHandler
= SetupDiInstallDevice
;
4067 case DIF_INSTALLDEVICEFILES
:
4068 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4069 DefaultHandler
= SetupDiInstallDriverFiles
;
4071 case DIF_INSTALLINTERFACES
:
4072 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4073 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
4075 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
4076 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4078 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
4079 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4081 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
4082 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4084 case DIF_NEWDEVICEWIZARD_PRESELECT
:
4085 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4087 case DIF_NEWDEVICEWIZARD_SELECT
:
4088 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4090 case DIF_POWERMESSAGEWAKE
:
4091 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4093 case DIF_PROPERTYCHANGE
:
4094 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4095 DefaultHandler
= SetupDiChangeState
;
4097 case DIF_REGISTER_COINSTALLERS
:
4098 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4099 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
4101 case DIF_REGISTERDEVICE
:
4102 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4103 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
4106 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4107 DefaultHandler
= SetupDiRemoveDevice
;
4109 case DIF_SELECTBESTCOMPATDRV
:
4110 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4111 DefaultHandler
= SetupDiSelectBestCompatDrv
;
4113 case DIF_SELECTDEVICE
:
4114 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4115 DefaultHandler
= SetupDiSelectDevice
;
4117 case DIF_TROUBLESHOOTER
:
4118 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4121 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4122 DefaultHandler
= SetupDiUnremoveDevice
;
4125 ERR("Install function %u not supported\n", InstallFunction
);
4126 SetLastError(ERROR_NOT_SUPPORTED
);
4129 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4130 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4131 /* Don't process this call, as a parameter is invalid */
4136 LIST_ENTRY ClassCoInstallersListHead
;
4137 LIST_ENTRY DeviceCoInstallersListHead
;
4138 HMODULE ClassInstallerLibrary
= NULL
;
4139 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
4140 COINSTALLER_CONTEXT_DATA Context
;
4141 PLIST_ENTRY ListEntry
;
4143 DWORD dwRegType
, dwLength
;
4144 DWORD rc
= NO_ERROR
;
4146 InitializeListHead(&ClassCoInstallersListHead
);
4147 InitializeListHead(&DeviceCoInstallersListHead
);
4149 if (CanHandle
& DEVICE_COINSTALLER
)
4151 hKey
= SETUPDI_OpenDrvKey(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
, (struct DeviceInfo
*)DeviceInfoData
->Reserved
, KEY_QUERY_VALUE
);
4152 if (hKey
!= INVALID_HANDLE_VALUE
)
4154 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4155 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4157 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4158 if (KeyBuffer
!= NULL
)
4160 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4161 if (rc
== ERROR_SUCCESS
)
4164 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4166 /* Add coinstaller to DeviceCoInstallersListHead list */
4167 struct CoInstallerElement
*coinstaller
;
4168 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
4169 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4172 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4173 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4174 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
4176 HeapFree(GetProcessHeap(), 0, coinstaller
);
4179 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4185 if (CanHandle
& CLASS_COINSTALLER
)
4189 REGSTR_PATH_CODEVICEINSTALLERS
,
4193 if (rc
== ERROR_SUCCESS
)
4195 WCHAR szGuidString
[40];
4196 if (pSetupStringFromGuid(&DeviceInfoData
->ClassGuid
, szGuidString
, ARRAYSIZE(szGuidString
)) == ERROR_SUCCESS
)
4198 rc
= RegQueryValueExW(hKey
, szGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
4199 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4201 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4202 if (KeyBuffer
!= NULL
)
4204 rc
= RegQueryValueExW(hKey
, szGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4205 if (rc
== ERROR_SUCCESS
)
4208 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4210 /* Add coinstaller to ClassCoInstallersListHead list */
4211 struct CoInstallerElement
*coinstaller
;
4212 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
4213 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4216 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4217 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4218 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
4220 HeapFree(GetProcessHeap(), 0, coinstaller
);
4223 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4230 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4232 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4233 if (hKey
!= INVALID_HANDLE_VALUE
)
4235 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4236 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4238 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4239 if (KeyBuffer
!= NULL
)
4241 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4242 if (rc
== ERROR_SUCCESS
)
4244 /* Get ClassInstaller function pointer */
4245 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4246 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4248 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4249 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4252 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4259 /* Call Class co-installers */
4260 Context
.PostProcessing
= FALSE
;
4262 ListEntry
= ClassCoInstallersListHead
.Flink
;
4263 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4265 struct CoInstallerElement
*coinstaller
;
4266 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4267 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4268 coinstaller
->PrivateData
= Context
.PrivateData
;
4269 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4271 coinstaller
->DoPostProcessing
= TRUE
;
4274 ListEntry
= ListEntry
->Flink
;
4277 /* Call Device co-installers */
4278 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4279 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4281 struct CoInstallerElement
*coinstaller
;
4282 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4283 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4284 coinstaller
->PrivateData
= Context
.PrivateData
;
4285 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4287 coinstaller
->DoPostProcessing
= TRUE
;
4290 ListEntry
= ListEntry
->Flink
;
4293 /* Call Class installer */
4296 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4297 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4300 rc
= ERROR_DI_DO_DEFAULT
;
4302 /* Call default handler */
4303 if (rc
== ERROR_DI_DO_DEFAULT
)
4305 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4307 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4310 rc
= GetLastError();
4316 /* Call Class co-installers that required postprocessing */
4317 Context
.PostProcessing
= TRUE
;
4318 ListEntry
= ClassCoInstallersListHead
.Flink
;
4319 while (ListEntry
!= &ClassCoInstallersListHead
)
4321 struct CoInstallerElement
*coinstaller
;
4322 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4323 if (coinstaller
->DoPostProcessing
)
4325 Context
.InstallResult
= rc
;
4326 Context
.PrivateData
= coinstaller
->PrivateData
;
4327 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4329 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4330 ListEntry
= ListEntry
->Flink
;
4333 /* Call Device co-installers that required postprocessing */
4334 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4335 while (ListEntry
!= &DeviceCoInstallersListHead
)
4337 struct CoInstallerElement
*coinstaller
;
4338 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4339 if (coinstaller
->DoPostProcessing
)
4341 Context
.InstallResult
= rc
;
4342 Context
.PrivateData
= coinstaller
->PrivateData
;
4343 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4345 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4346 ListEntry
= ListEntry
->Flink
;
4349 /* Free allocated memory */
4350 while (!IsListEmpty(&ClassCoInstallersListHead
))
4352 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4353 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4355 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4357 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4358 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4361 ret
= (rc
== NO_ERROR
);
4365 TRACE("Returning %d\n", ret
);
4369 /***********************************************************************
4370 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4372 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4373 HDEVINFO DeviceInfoSet
,
4374 PSP_DEVINFO_DATA DeviceInfoData
,
4375 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4377 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4380 TRACE("%s(%p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4382 if (DeviceInstallParams
== NULL
)
4383 SetLastError(ERROR_INVALID_PARAMETER
);
4384 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4385 SetLastError(ERROR_INVALID_USER_BUFFER
);
4388 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4389 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4393 /* Do W->A conversion */
4395 DeviceInstallParams
,
4396 &deviceInstallParamsW
,
4397 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4398 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4399 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4401 DeviceInstallParams
->DriverPath
[0] = '\0';
4407 TRACE("Returning %d\n", ret
);
4411 /***********************************************************************
4412 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4415 SetupDiGetDeviceInfoListClass(
4416 IN HDEVINFO DeviceInfoSet
,
4417 OUT LPGUID ClassGuid
)
4419 struct DeviceInfoSet
*list
;
4422 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, ClassGuid
);
4425 SetLastError(ERROR_INVALID_HANDLE
);
4426 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4427 SetLastError(ERROR_INVALID_HANDLE
);
4428 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4429 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4432 *ClassGuid
= list
->ClassGuid
;
4437 TRACE("Returning %d\n", ret
);
4441 /***********************************************************************
4442 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4445 SetupDiGetDeviceInstallParamsW(
4446 IN HDEVINFO DeviceInfoSet
,
4447 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4448 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4450 struct DeviceInfoSet
*list
;
4453 TRACE("%s(%p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4456 SetLastError(ERROR_INVALID_HANDLE
);
4457 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4458 SetLastError(ERROR_INVALID_HANDLE
);
4459 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4460 SetLastError(ERROR_INVALID_USER_BUFFER
);
4461 else if (!DeviceInstallParams
)
4462 SetLastError(ERROR_INVALID_PARAMETER
);
4463 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4464 SetLastError(ERROR_INVALID_USER_BUFFER
);
4467 PSP_DEVINSTALL_PARAMS_W Source
;
4470 Source
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4472 Source
= &list
->InstallParams
;
4478 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4480 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4482 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4488 TRACE("Returning %d\n", ret
);
4493 CheckDeviceInstallParameters(
4494 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4496 DWORD SupportedFlags
=
4497 DI_NOVCP
| /* 0x00000008 */
4498 DI_DIDCOMPAT
| /* 0x00000010 */
4499 DI_DIDCLASS
| /* 0x00000020 */
4500 DI_NEEDRESTART
| /* 0x00000080 */
4501 DI_NEEDREBOOT
| /* 0x00000100 */
4502 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4503 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4504 DI_ENUMSINGLEINF
| /* 0x00010000 */
4505 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
4506 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4507 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4508 DI_QUIETINSTALL
| /* 0x00800000 */
4509 DI_NOFILECOPY
| /* 0x01000000 */
4510 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4511 DWORD SupportedFlagsEx
=
4512 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4513 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4514 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4515 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4516 DI_FLAGSEX_NO_DRVREG_MODIFY
| /* 0x00008000 */
4517 DI_FLAGSEX_INSTALLEDDRIVER
; /* 0x04000000 */
4520 /* FIXME: add support for more flags */
4522 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4523 * It should be checked before accessing to other values
4524 * of the SP_DEVINSTALL_PARAMS structure */
4526 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4528 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4529 SetLastError(ERROR_INVALID_FLAGS
);
4531 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4533 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4534 SetLastError(ERROR_INVALID_FLAGS
);
4536 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4537 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4538 SetLastError(ERROR_INVALID_USER_BUFFER
);
4541 /* FIXME: check Reserved field */
4548 /***********************************************************************
4549 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4552 SetupDiSetDeviceInstallParamsW(
4553 IN HDEVINFO DeviceInfoSet
,
4554 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4555 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4557 struct DeviceInfoSet
*list
;
4560 TRACE("%s(%p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4563 SetLastError(ERROR_INVALID_HANDLE
);
4564 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4565 SetLastError(ERROR_INVALID_HANDLE
);
4566 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4567 SetLastError(ERROR_INVALID_USER_BUFFER
);
4568 else if (!DeviceInstallParams
)
4569 SetLastError(ERROR_INVALID_PARAMETER
);
4570 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4571 SetLastError(ERROR_INVALID_USER_BUFFER
);
4572 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4574 PSP_DEVINSTALL_PARAMS_W Destination
;
4577 Destination
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4579 Destination
= &list
->InstallParams
;
4580 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4584 TRACE("Returning %d\n", ret
);
4588 /***********************************************************************
4589 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4592 SetupDiSetDeviceInstallParamsA(
4593 HDEVINFO DeviceInfoSet
,
4594 PSP_DEVINFO_DATA DeviceInfoData
,
4595 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4597 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4601 TRACE("%s(%p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4603 if (DeviceInstallParams
== NULL
)
4604 SetLastError(ERROR_INVALID_PARAMETER
);
4605 else if (DeviceInstallParams
->cbSize
< sizeof(SP_DEVINSTALL_PARAMS_A
))
4606 SetLastError(ERROR_INVALID_USER_BUFFER
);
4609 memcpy(&deviceInstallParamsW
, DeviceInstallParams
, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A
, DriverPath
));
4610 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4611 len
= MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, NULL
, 0);
4614 ERR("DrivePath is NULL\n");
4619 MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, deviceInstallParamsW
.DriverPath
, len
);
4620 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4624 TRACE("Returning %d\n", ret
);
4629 OpenHardwareProfileKey(
4632 IN DWORD samDesired
)
4634 HKEY hHWProfilesKey
= NULL
;
4635 HKEY hHWProfileKey
= NULL
;
4636 HKEY ret
= INVALID_HANDLE_VALUE
;
4639 rc
= RegOpenKeyExW(HKLM
,
4640 REGSTR_PATH_HWPROFILES
,
4644 if (rc
!= ERROR_SUCCESS
)
4651 rc
= RegOpenKeyExW(hHWProfilesKey
,
4660 snprintfW(subKey
, 4, InstanceKeyFormat
, HwProfile
);
4662 rc
= RegOpenKeyExW(hHWProfilesKey
,
4668 if (rc
!= ERROR_SUCCESS
)
4673 ret
= hHWProfileKey
;
4676 if (hHWProfilesKey
!= NULL
)
4677 RegCloseKey(hHWProfilesKey
);
4678 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4679 RegCloseKey(hHWProfileKey
);
4684 IsDeviceInfoInDeviceInfoSet(
4685 struct DeviceInfoSet
*deviceInfoSet
,
4686 struct DeviceInfo
*deviceInfo
)
4688 PLIST_ENTRY ListEntry
;
4690 ListEntry
= deviceInfoSet
->ListHead
.Flink
;
4691 while (ListEntry
!= &deviceInfoSet
->ListHead
)
4693 if (deviceInfo
== CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
))
4696 ListEntry
= ListEntry
->Flink
;
4702 /***********************************************************************
4703 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4706 SetupDiDeleteDeviceInfo(
4707 IN HDEVINFO DeviceInfoSet
,
4708 IN PSP_DEVINFO_DATA DeviceInfoData
)
4710 struct DeviceInfoSet
*deviceInfoSet
;
4711 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
;
4714 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
4717 SetLastError(ERROR_INVALID_HANDLE
);
4718 else if ((deviceInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4719 SetLastError(ERROR_INVALID_HANDLE
);
4720 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4721 SetLastError(ERROR_INVALID_USER_BUFFER
);
4722 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet
, deviceInfo
))
4723 SetLastError(ERROR_INVALID_PARAMETER
);
4726 RemoveEntryList(&deviceInfo
->ListEntry
);
4727 DestroyDeviceInfo(deviceInfo
);
4735 /***********************************************************************
4736 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4739 SetupDiOpenDeviceInfoA(
4740 IN HDEVINFO DeviceInfoSet
,
4741 IN PCSTR DeviceInstanceId
,
4742 IN HWND hwndParent OPTIONAL
,
4744 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4746 LPWSTR DeviceInstanceIdW
= NULL
;
4749 TRACE("%s(%p %s %p %lx %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4751 DeviceInstanceIdW
= pSetupMultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4752 if (DeviceInstanceIdW
== NULL
)
4755 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4756 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4758 MyFree(DeviceInstanceIdW
);
4764 /***********************************************************************
4765 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4768 SetupDiOpenDeviceInfoW(
4769 IN HDEVINFO DeviceInfoSet
,
4770 IN PCWSTR DeviceInstanceId
,
4771 IN HWND hwndParent OPTIONAL
,
4773 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4775 struct DeviceInfoSet
*list
;
4776 HKEY hEnumKey
, hKey
= NULL
;
4780 TRACE("%s(%p %s %p %lx %p)\n", __FUNCTION__
,
4781 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
4782 hwndParent
, OpenFlags
, DeviceInfoData
);
4784 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4785 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4788 SetLastError(ERROR_INVALID_HANDLE
);
4789 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4790 SetLastError(ERROR_INVALID_HANDLE
);
4791 else if (!DeviceInstanceId
)
4792 SetLastError(ERROR_INVALID_PARAMETER
);
4793 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4795 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4796 SetLastError(ERROR_INVALID_FLAGS
);
4798 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4799 SetLastError(ERROR_INVALID_USER_BUFFER
);
4802 struct DeviceInfo
*deviceInfo
= NULL
;
4803 /* Search if device already exists in DeviceInfoSet.
4804 * If yes, return the existing element
4805 * If no, create a new element using information in registry
4807 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4808 while (ItemList
!= &list
->ListHead
)
4810 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
4811 if (!wcscmp(deviceInfo
->instanceId
, DeviceInstanceId
))
4814 ItemList
= ItemList
->Flink
;
4819 /* good one found */
4825 WCHAR szClassGuid
[MAX_GUID_STRING_LEN
];
4827 /* Open supposed registry key */
4830 REGSTR_PATH_SYSTEMENUM
,
4834 if (rc
!= ERROR_SUCCESS
)
4845 RegCloseKey(hEnumKey
);
4846 if (rc
!= ERROR_SUCCESS
)
4848 if (rc
== ERROR_FILE_NOT_FOUND
)
4849 rc
= ERROR_NO_SUCH_DEVINST
;
4854 ClassGUID
= GUID_NULL
;
4855 dwSize
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
4857 if (RegQueryValueExW(hKey
,
4858 REGSTR_VAL_CLASSGUID
,
4861 (LPBYTE
)szClassGuid
,
4862 &dwSize
) == ERROR_SUCCESS
)
4864 szClassGuid
[MAX_GUID_STRING_LEN
- 2] = UNICODE_NULL
;
4866 /* Convert a string to a ClassGuid */
4867 UuidFromStringW(&szClassGuid
[1], &ClassGUID
);
4870 if (!CreateDeviceInfo(list
, DeviceInstanceId
, &ClassGUID
, &deviceInfo
))
4873 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4878 if (ret
&& deviceInfo
&& DeviceInfoData
)
4880 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4881 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4882 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4893 /***********************************************************************
4894 * SetupDiGetSelectedDevice (SETUPAPI.@)
4897 SetupDiGetSelectedDevice(
4898 IN HDEVINFO DeviceInfoSet
,
4899 OUT PSP_DEVINFO_DATA DeviceInfoData
)
4901 struct DeviceInfoSet
*list
;
4904 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
4907 SetLastError(ERROR_INVALID_HANDLE
);
4908 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4909 SetLastError(ERROR_INVALID_HANDLE
);
4910 else if (list
->SelectedDevice
== NULL
)
4911 SetLastError(ERROR_NO_DEVICE_SELECTED
);
4912 else if (!DeviceInfoData
)
4913 SetLastError(ERROR_INVALID_PARAMETER
);
4914 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4915 SetLastError(ERROR_INVALID_USER_BUFFER
);
4918 memcpy(&DeviceInfoData
->ClassGuid
,
4919 &list
->SelectedDevice
->ClassGuid
,
4921 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
4922 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
4926 TRACE("Returning %d\n", ret
);
4931 /***********************************************************************
4932 * SetupDiSetSelectedDevice (SETUPAPI.@)
4935 SetupDiSetSelectedDevice(
4936 IN HDEVINFO DeviceInfoSet
,
4937 IN PSP_DEVINFO_DATA DeviceInfoData
)
4939 struct DeviceInfoSet
*list
;
4942 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
4945 SetLastError(ERROR_INVALID_HANDLE
);
4946 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4947 SetLastError(ERROR_INVALID_HANDLE
);
4948 else if (!DeviceInfoData
)
4949 SetLastError(ERROR_INVALID_PARAMETER
);
4950 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4951 SetLastError(ERROR_INVALID_USER_BUFFER
);
4952 else if (DeviceInfoData
->Reserved
== 0)
4953 SetLastError(ERROR_INVALID_USER_BUFFER
);
4956 list
->SelectedDevice
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
4960 TRACE("Returning %d\n", ret
);
4965 /* Return the current hardware profile id, or -1 if error */
4967 SETUPAPI_GetCurrentHwProfile(
4968 IN HDEVINFO DeviceInfoSet
)
4971 DWORD dwRegType
, dwLength
;
4974 DWORD ret
= (DWORD
)-1;
4976 rc
= RegOpenKeyExW(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
4977 REGSTR_PATH_IDCONFIGDB
,
4981 if (rc
!= ERROR_SUCCESS
)
4987 dwLength
= sizeof(DWORD
);
4988 rc
= RegQueryValueExW(hKey
,
4989 REGSTR_VAL_CURRENTCONFIG
,
4992 (LPBYTE
)&hwProfile
, &dwLength
);
4993 if (rc
!= ERROR_SUCCESS
)
4998 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5000 SetLastError(ERROR_GEN_FAILURE
);
5015 IN HDEVINFO DeviceInfoSet
,
5016 IN PSP_DEVINFO_DATA DeviceInfoData
)
5019 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5020 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5023 cr
= CM_Enable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
5024 if (cr
!= CR_SUCCESS
)
5026 SetLastError(GetErrorCodeFromCrCode(cr
));
5032 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5039 IN HDEVINFO DeviceInfoSet
,
5040 IN PSP_DEVINFO_DATA DeviceInfoData
)
5043 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5044 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5047 cr
= CM_Disable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
5048 if (cr
!= CR_SUCCESS
)
5050 SetLastError(GetErrorCodeFromCrCode(cr
));
5056 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5061 /***********************************************************************
5062 * SetupDiChangeState (SETUPAPI.@)
5066 IN HDEVINFO DeviceInfoSet
,
5067 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5069 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5070 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5071 PSP_PROPCHANGE_PARAMS PropChange
;
5072 HKEY hRootKey
= INVALID_HANDLE_VALUE
, hKey
= INVALID_HANDLE_VALUE
;
5073 LPCWSTR RegistryValueName
;
5074 DWORD dwConfigFlags
, dwLength
, dwRegType
;
5078 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
5080 if (!DeviceInfoData
)
5081 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChangeParams
;
5083 PropChange
= ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChangeParams
;
5086 SetLastError(ERROR_INVALID_PARAMETER
);
5090 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
5091 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
5093 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
5095 switch (PropChange
->StateChange
)
5100 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
5101 hRootKey
= set
->HKLM
;
5102 else /* PropChange->Scope == DICS_FLAG_CONFIGSPECIFIC */
5104 hRootKey
= OpenHardwareProfileKey(set
->HKLM
, PropChange
->HwProfile
, KEY_CREATE_SUB_KEY
);
5105 if (hRootKey
== INVALID_HANDLE_VALUE
)
5109 /* Enable/disable device in registry */
5110 hKey
= SETUPDI_OpenDrvKey(hRootKey
, deviceInfo
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5111 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5112 hKey
= SETUPDI_CreateDevKey(hRootKey
, deviceInfo
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5113 if (hKey
== INVALID_HANDLE_VALUE
)
5115 dwLength
= sizeof(DWORD
);
5116 rc
= RegQueryValueExW(
5121 (LPBYTE
)&dwConfigFlags
, &dwLength
);
5122 if (rc
== ERROR_FILE_NOT_FOUND
)
5124 else if (rc
!= ERROR_SUCCESS
)
5129 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5131 SetLastError(ERROR_GEN_FAILURE
);
5134 if (PropChange
->StateChange
== DICS_ENABLE
)
5135 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5137 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5138 rc
= RegSetValueExW(
5143 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
5144 if (rc
!= ERROR_SUCCESS
)
5150 /* Enable/disable device if needed */
5151 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
5152 || PropChange
->HwProfile
== 0
5153 || PropChange
->HwProfile
== SETUPAPI_GetCurrentHwProfile(DeviceInfoSet
))
5155 if (PropChange
->StateChange
== DICS_ENABLE
)
5156 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5158 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
5164 case DICS_PROPCHANGE
:
5166 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5171 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
5172 SetLastError(ERROR_NOT_SUPPORTED
);
5177 if (hRootKey
!= INVALID_HANDLE_VALUE
&& hRootKey
!= set
->HKLM
)
5178 RegCloseKey(hRootKey
);
5180 if (hKey
!= INVALID_HANDLE_VALUE
)
5183 TRACE("Returning %d\n", ret
);
5187 /***********************************************************************
5188 * SetupDiSelectDevice (SETUPAPI.@)
5191 SetupDiSelectDevice(
5192 IN HDEVINFO DeviceInfoSet
,
5193 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5195 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5196 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5201 /***********************************************************************
5202 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5205 SetupDiRegisterCoDeviceInstallers(
5206 IN HDEVINFO DeviceInfoSet
,
5207 IN PSP_DEVINFO_DATA DeviceInfoData
)
5209 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5210 struct DeviceInfo
*deviceInfo
;
5211 BOOL ret
= FALSE
; /* Return value */
5213 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
5216 SetLastError(ERROR_INVALID_PARAMETER
);
5217 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5218 SetLastError(ERROR_INVALID_HANDLE
);
5219 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5220 SetLastError(ERROR_INVALID_HANDLE
);
5221 else if (!DeviceInfoData
)
5222 SetLastError(ERROR_INVALID_PARAMETER
);
5223 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5224 SetLastError(ERROR_INVALID_USER_BUFFER
);
5227 SP_DEVINSTALL_PARAMS_W InstallParams
;
5228 struct DriverInfoElement
*SelectedDriver
;
5231 WCHAR SectionName
[MAX_PATH
];
5232 DWORD SectionNameLength
= 0;
5233 HKEY hKey
= INVALID_HANDLE_VALUE
;
5234 PVOID Context
= NULL
;
5236 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5237 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5241 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.ClassInstallReserved
;
5242 if (SelectedDriver
== NULL
)
5244 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5248 /* Get .CoInstallers section name */
5249 Result
= SetupDiGetActualSectionToInstallW(
5250 SelectedDriver
->InfFileDetails
->hInf
,
5251 SelectedDriver
->Details
.SectionName
,
5252 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5253 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
5255 lstrcatW(SectionName
, DotCoInstallers
);
5257 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5259 /* Open/Create driver key information */
5260 #if _WIN32_WINNT >= 0x502
5261 hKey
= SETUPDI_OpenDrvKey(set
->HKLM
, deviceInfo
, KEY_READ
| KEY_WRITE
);
5263 hKey
= SETUPDI_OpenDrvKey(set
->HKLM
, deviceInfo
, KEY_ALL_ACCESS
);
5265 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5266 #if _WIN32_WINNT >= 0x502
5267 hKey
= SETUPDI_CreateDrvKey(set
->HKLM
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_READ
| KEY_WRITE
);
5269 hKey
= SETUPDI_CreateDrvKey(set
->HKLM
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_ALL_ACCESS
);
5271 if (hKey
== INVALID_HANDLE_VALUE
)
5274 /* Install .CoInstallers section */
5275 DoAction
= SPINST_REGISTRY
;
5276 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5278 DoAction
|= SPINST_FILES
;
5279 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5283 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5284 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5285 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5286 SetupDefaultQueueCallbackW
, Context
,
5287 DeviceInfoSet
, DeviceInfoData
);
5295 SetupTermDefaultQueueCallback(Context
);
5296 if (hKey
!= INVALID_HANDLE_VALUE
)
5300 TRACE("Returning %d\n", ret
);
5305 InfIsFromOEMLocation(
5307 OUT LPBOOL IsOEMLocation
)
5311 last
= strrchrW(FullName
, '\\');
5314 /* No directory specified */
5315 *IsOEMLocation
= FALSE
;
5322 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
5325 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5329 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
5330 if (ret
== 0 || ret
> MAX_PATH
)
5333 SetLastError(ERROR_GEN_FAILURE
);
5336 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
5337 strcatW(Windir
, BackSlash
);
5338 strcatW(Windir
, InfDirectory
);
5340 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
5342 /* The path is %SYSTEMROOT%\Inf */
5343 *IsOEMLocation
= FALSE
;
5347 /* The file is in another place */
5348 *IsOEMLocation
= TRUE
;
5355 /***********************************************************************
5356 * SetupDiInstallDevice (SETUPAPI.@)
5359 SetupDiInstallDevice(
5360 IN HDEVINFO DeviceInfoSet
,
5361 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5363 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5364 struct DeviceInfo
*deviceInfo
;
5365 SP_DEVINSTALL_PARAMS_W InstallParams
;
5366 struct DriverInfoElement
*SelectedDriver
;
5367 SYSTEMTIME DriverDate
;
5368 WCHAR SectionName
[MAX_PATH
];
5370 DWORD SectionNameLength
= 0;
5371 BOOL Result
= FALSE
;
5374 LPWSTR pSectionName
= NULL
;
5375 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5377 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5378 BOOL RebootRequired
= FALSE
;
5379 HKEY hKey
= INVALID_HANDLE_VALUE
;
5380 BOOL NeedtoCopyFile
;
5381 LARGE_INTEGER fullVersion
;
5383 PVOID Context
= NULL
;
5384 BOOL ret
= FALSE
; /* Return value */
5386 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
5389 SetLastError(ERROR_INVALID_PARAMETER
);
5390 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5391 SetLastError(ERROR_INVALID_HANDLE
);
5392 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5393 SetLastError(ERROR_INVALID_HANDLE
);
5394 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5395 SetLastError(ERROR_INVALID_USER_BUFFER
);
5401 /* One parameter is bad */
5405 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5406 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5410 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5412 /* Set FAILEDINSTALL in ConfigFlags registry value */
5413 DWORD ConfigFlags
, regType
;
5414 Result
= SetupDiGetDeviceRegistryPropertyW(
5419 (PBYTE
)&ConfigFlags
,
5420 sizeof(ConfigFlags
),
5422 if (!Result
|| regType
!= REG_DWORD
)
5424 SetLastError(ERROR_GEN_FAILURE
);
5427 ConfigFlags
|= CONFIGFLAG_FAILEDINSTALL
;
5428 Result
= SetupDiSetDeviceRegistryPropertyW(
5432 (PBYTE
)&ConfigFlags
,
5433 sizeof(ConfigFlags
));
5436 SetLastError(ERROR_GEN_FAILURE
);
5444 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.ClassInstallReserved
;
5445 if (SelectedDriver
== NULL
)
5447 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5451 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5453 Result
= SetupDiGetActualSectionToInstallW(
5454 SelectedDriver
->InfFileDetails
->hInf
,
5455 SelectedDriver
->Details
.SectionName
,
5456 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5457 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
5459 pSectionName
= &SectionName
[strlenW(SectionName
)];
5461 /* Get information from [Version] section */
5462 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5464 /* Format ClassGuid to a string */
5465 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5467 RequiredSize
= lstrlenW(lpGuidString
);
5468 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5469 if (!lpFullGuidString
)
5471 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5474 lpFullGuidString
[0] = '{';
5475 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5476 lpFullGuidString
[RequiredSize
+ 1] = '}';
5477 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5479 /* Copy .inf file to Inf\ directory (if needed) */
5480 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
5485 WCHAR NewFileName
[MAX_PATH
];
5486 struct InfFileDetails
*newInfFileDetails
;
5487 Result
= SetupCopyOEMInfW(
5488 SelectedDriver
->Details
.InfFileName
,
5491 SP_COPY_NOOVERWRITE
,
5492 NewFileName
, MAX_PATH
,
5495 if (!Result
&& GetLastError() != ERROR_FILE_EXISTS
)
5497 /* Create a new struct InfFileDetails, and set it to
5498 * SelectedDriver->InfFileDetails, to release use of
5499 * current InfFile */
5500 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
5501 if (!newInfFileDetails
)
5503 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
5504 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
5505 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
5508 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5510 /* Open/Create driver key information */
5511 #if _WIN32_WINNT >= 0x502
5512 hKey
= SETUPDI_OpenDrvKey(set
->HKLM
, deviceInfo
, KEY_READ
| KEY_WRITE
);
5514 hKey
= SETUPDI_OpenDrvKey(set
->HKLM
, deviceInfo
, KEY_ALL_ACCESS
);
5516 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5517 #if _WIN32_WINNT >= 0x502
5518 hKey
= SETUPDI_CreateDrvKey(set
->HKLM
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_READ
| KEY_WRITE
);
5520 hKey
= SETUPDI_CreateDrvKey(set
->HKLM
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_ALL_ACCESS
);
5522 if (hKey
== INVALID_HANDLE_VALUE
)
5525 /* Install main section */
5527 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5528 DoAction
|= SPINST_REGISTRY
;
5529 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5531 DoAction
|= SPINST_FILES
;
5532 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5536 *pSectionName
= '\0';
5537 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5538 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5539 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5540 SetupDefaultQueueCallbackW
, Context
,
5541 DeviceInfoSet
, DeviceInfoData
);
5544 InstallParams
.Flags
|= DI_NOFILECOPY
;
5545 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5547 /* Write information to driver key */
5548 *pSectionName
= UNICODE_NULL
;
5549 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
5550 TRACE("Write information to driver key\n");
5551 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5552 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5553 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5554 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
5555 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
5556 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
5557 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
5558 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
5559 sprintfW(Buffer
, DateFormat
, DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5560 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5561 if (rc
== ERROR_SUCCESS
)
5562 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5563 if (rc
== ERROR_SUCCESS
)
5564 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5565 if (rc
== ERROR_SUCCESS
)
5567 sprintfW(Buffer
, VersionFormat
, fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5568 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5570 if (rc
== ERROR_SUCCESS
)
5571 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
5572 if (rc
== ERROR_SUCCESS
)
5573 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5574 if (rc
== ERROR_SUCCESS
)
5575 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
));
5576 if (rc
== ERROR_SUCCESS
)
5577 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5578 if (rc
== ERROR_SUCCESS
)
5579 rc
= RegSetValueExW(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5580 if (rc
!= ERROR_SUCCESS
)
5586 hKey
= INVALID_HANDLE_VALUE
;
5588 /* FIXME: Process .LogConfigOverride section */
5590 /* Install .Services section */
5591 strcpyW(pSectionName
, DotServices
);
5592 Result
= SetupInstallServicesFromInfSectionExW(
5593 SelectedDriver
->InfFileDetails
->hInf
,
5602 if (GetLastError() != ERROR_SECTION_NOT_FOUND
)
5604 SetLastError(ERROR_SUCCESS
);
5606 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5607 RebootRequired
= TRUE
;
5609 /* Open device registry key */
5610 hKey
= SETUPDI_OpenDevKey(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
, (struct DeviceInfo
*)DeviceInfoData
->Reserved
, KEY_SET_VALUE
);
5611 if (hKey
== INVALID_HANDLE_VALUE
)
5614 /* Install .HW section */
5616 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5617 DoAction
|= SPINST_REGISTRY
;
5618 strcpyW(pSectionName
, DotHW
);
5619 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5620 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5621 DoAction
, hKey
, NULL
, 0,
5623 DeviceInfoSet
, DeviceInfoData
);
5627 /* Write information to enum key */
5628 TRACE("Write information to enum key\n");
5629 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
5630 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
5631 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5632 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
5633 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
5634 if (rc
== ERROR_SUCCESS
)
5635 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5636 if (rc
== ERROR_SUCCESS
)
5637 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5638 if (rc
== ERROR_SUCCESS
)
5639 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5640 if (rc
!= ERROR_SUCCESS
)
5646 /* Start the device */
5647 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5648 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5653 /* End of installation */
5654 if (hKey
!= INVALID_HANDLE_VALUE
)
5657 RpcStringFreeW(&lpGuidString
);
5658 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5660 SetupTermDefaultQueueCallback(Context
);
5661 TRACE("Returning %d\n", ret
);
5665 HKEY
SETUPDI_CreateDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5667 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5670 l
= RegCreateKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_CREATE_SUB_KEY
, NULL
, &enumKey
, NULL
);
5673 l
= RegCreateKeyExW(enumKey
, devInfo
->instanceId
, 0, NULL
, REG_OPTION_NON_VOLATILE
, samDesired
, NULL
, &key
, NULL
);
5674 RegCloseKey(enumKey
);
5681 HKEY
SETUPDI_CreateDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, UUID
*ClassGuid
, REGSAM samDesired
)
5683 HKEY key
= INVALID_HANDLE_VALUE
;
5684 LPWSTR lpGuidString
= NULL
;
5685 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
5686 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
5687 DWORD Index
; /* Index used in the DriverKey name */
5691 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
5692 HKEY hEnumKey
= NULL
;
5693 HKEY hClassKey
= NULL
;
5694 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
5697 /* Open device key, to read Driver value */
5698 hDeviceKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5699 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
5702 rc
= RegOpenKeyExW(RootKey
, REGSTR_PATH_CLASS_NT
, 0, KEY_CREATE_SUB_KEY
, &hClassKey
);
5703 if (rc
!= ERROR_SUCCESS
)
5709 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, NULL
, &dwSize
);
5710 if (rc
!= ERROR_SUCCESS
)
5712 /* Create a new driver key */
5714 if (UuidToStringW(ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5717 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
5718 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
5721 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5726 strcpyW(&DriverKey
[1], lpGuidString
);
5727 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
5728 *pDeviceInstance
++ = '}';
5729 *pDeviceInstance
++ = '\\';
5731 /* Try all values for Index between 0 and 9999 */
5733 while (Index
<= 9999)
5735 sprintfW(pDeviceInstance
, InstanceKeyFormat
, Index
);
5736 rc
= RegCreateKeyExW(hClassKey
,
5740 REG_OPTION_NON_VOLATILE
,
5741 #if _WIN32_WINNT >= 0x502
5742 KEY_READ
| KEY_WRITE
,
5749 if (rc
!= ERROR_SUCCESS
)
5754 if (Disposition
== REG_CREATED_NEW_KEY
)
5763 /* Unable to create more than 9999 devices within the same class */
5764 SetLastError(ERROR_GEN_FAILURE
);
5768 /* Write the new Driver value */
5769 rc
= RegSetValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
5770 if (rc
!= ERROR_SUCCESS
)
5778 /* Open the existing driver key */
5780 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
5783 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5787 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, (LPBYTE
)DriverKey
, &dwSize
);
5788 if (rc
!= ERROR_SUCCESS
)
5794 rc
= RegCreateKeyExW(hClassKey
,
5798 REG_OPTION_NON_VOLATILE
,
5799 #if _WIN32_WINNT >= 0x502
5800 KEY_READ
| KEY_WRITE
,
5807 if (rc
!= ERROR_SUCCESS
)
5818 RpcStringFreeW(&lpGuidString
);
5819 HeapFree(GetProcessHeap(), 0, DriverKey
);
5820 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5821 RegCloseKey(hHWProfileKey
);
5822 if (hEnumKey
!= NULL
)
5823 RegCloseKey(hEnumKey
);
5824 if (hClassKey
!= NULL
)
5825 RegCloseKey(hClassKey
);
5826 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
5827 RegCloseKey(hDeviceKey
);
5828 if (hKey
!= NULL
&& hKey
!= key
)
5831 TRACE("Returning 0x%p\n", hKey
);
5835 HKEY
SETUPDI_OpenDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5837 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5840 l
= RegOpenKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, READ_CONTROL
, &enumKey
);
5843 l
= RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
5844 RegCloseKey(enumKey
);
5851 HKEY
SETUPDI_OpenDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5853 LPWSTR DriverKey
= NULL
;
5857 HKEY hEnumKey
= NULL
;
5859 HKEY key
= INVALID_HANDLE_VALUE
;
5861 hKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
);
5862 if (hKey
== INVALID_HANDLE_VALUE
)
5864 /* Read the 'Driver' key */
5865 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5866 if (rc
!= ERROR_SUCCESS
)
5871 else if (dwRegType
!= REG_SZ
)
5873 SetLastError(ERROR_GEN_FAILURE
);
5876 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5879 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5882 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5883 if (rc
!= ERROR_SUCCESS
)
5890 /* Need to open the driver key */
5893 REGSTR_PATH_CLASS_NT
,
5897 if (rc
!= ERROR_SUCCESS
)
5908 if (rc
!= ERROR_SUCCESS
)
5916 if (hEnumKey
!= NULL
)
5917 RegCloseKey(hEnumKey
);
5918 if (hKey
!= NULL
&& hKey
!= key
)
5921 HeapFree(GetProcessHeap(), 0, DriverKey
);
5925 /***********************************************************************
5926 * SetupDiOpenDevRegKey (SETUPAPI.@)
5928 HKEY WINAPI
SetupDiOpenDevRegKey(
5929 HDEVINFO DeviceInfoSet
,
5930 PSP_DEVINFO_DATA DeviceInfoData
,
5936 struct DeviceInfoSet
*set
= DeviceInfoSet
;
5937 struct DeviceInfo
*devInfo
;
5938 HKEY key
= INVALID_HANDLE_VALUE
;
5941 TRACE("%s(%p %p %d %d %d %x)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
5942 Scope
, HwProfile
, KeyType
, samDesired
);
5944 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5946 SetLastError(ERROR_INVALID_HANDLE
);
5947 return INVALID_HANDLE_VALUE
;
5949 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5951 SetLastError(ERROR_INVALID_HANDLE
);
5952 return INVALID_HANDLE_VALUE
;
5954 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5955 || !DeviceInfoData
->Reserved
)
5957 SetLastError(ERROR_INVALID_PARAMETER
);
5958 return INVALID_HANDLE_VALUE
;
5960 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5962 SetLastError(ERROR_INVALID_FLAGS
);
5963 return INVALID_HANDLE_VALUE
;
5965 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
5967 SetLastError(ERROR_INVALID_FLAGS
);
5968 return INVALID_HANDLE_VALUE
;
5970 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5971 if (devInfo
->set
!= set
)
5973 SetLastError(ERROR_INVALID_PARAMETER
);
5974 return INVALID_HANDLE_VALUE
;
5976 if (Scope
!= DICS_FLAG_GLOBAL
)
5978 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5979 if (RootKey
== INVALID_HANDLE_VALUE
)
5980 return INVALID_HANDLE_VALUE
;
5983 RootKey
= set
->HKLM
;
5987 key
= SETUPDI_OpenDevKey(RootKey
, devInfo
, samDesired
);
5988 if (Scope
== DICS_FLAG_GLOBAL
)
5991 HKEY hTempKey
= key
;
5992 rc
= RegOpenKeyExW(hTempKey
,
5993 L
"Device Parameters",
5997 if (rc
== ERROR_SUCCESS
)
5998 RegCloseKey(hTempKey
);
6002 key
= SETUPDI_OpenDrvKey(RootKey
, devInfo
, samDesired
);
6005 WARN("unknown KeyType %d\n", KeyType
);
6007 if (RootKey
!= set
->HKLM
)
6008 RegCloseKey(RootKey
);
6012 static BOOL
SETUPDI_DeleteDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
6018 static BOOL
SETUPDI_DeleteDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
6024 /***********************************************************************
6025 * SetupDiDeleteDevRegKey (SETUPAPI.@)
6027 BOOL WINAPI
SetupDiDeleteDevRegKey(
6028 HDEVINFO DeviceInfoSet
,
6029 PSP_DEVINFO_DATA DeviceInfoData
,
6034 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
6035 struct DeviceInfo
*devInfo
;
6039 TRACE("%s(%p %p %d %d %d)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
6042 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
6044 SetLastError(ERROR_INVALID_HANDLE
);
6047 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
6049 SetLastError(ERROR_INVALID_HANDLE
);
6052 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
6053 || !DeviceInfoData
->Reserved
)
6055 SetLastError(ERROR_INVALID_PARAMETER
);
6058 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
6060 SetLastError(ERROR_INVALID_FLAGS
);
6063 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
&& KeyType
!= DIREG_BOTH
)
6065 SetLastError(ERROR_INVALID_FLAGS
);
6068 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
6069 if (devInfo
->set
!= set
)
6071 SetLastError(ERROR_INVALID_PARAMETER
);
6074 if (Scope
!= DICS_FLAG_GLOBAL
)
6076 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
6077 if (RootKey
== INVALID_HANDLE_VALUE
)
6081 RootKey
= set
->HKLM
;
6085 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
6088 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
6091 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
6093 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
6096 WARN("unknown KeyType %d\n", KeyType
);
6098 if (RootKey
!= set
->HKLM
)
6099 RegCloseKey(RootKey
);
6103 /***********************************************************************
6104 * SetupDiRestartDevices (SETUPAPI.@)
6108 SetupDiRestartDevices(
6109 HDEVINFO DeviceInfoSet
,
6110 PSP_DEVINFO_DATA DeviceInfoData
)
6112 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
6113 struct DeviceInfo
*devInfo
;
6116 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
6118 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
6120 SetLastError(ERROR_INVALID_HANDLE
);
6123 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
6125 SetLastError(ERROR_INVALID_HANDLE
);
6129 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
6130 || !DeviceInfoData
->Reserved
)
6132 SetLastError(ERROR_INVALID_PARAMETER
);
6136 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
6138 cr
= CM_Enable_DevNode_Ex(devInfo
->dnDevInst
, 0, set
->hMachine
);
6139 if (cr
!= CR_SUCCESS
)
6141 SetLastError(GetErrorCodeFromCrCode(cr
));