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 #include <pseh/pseh2.h>
26 /* Unicode constants */
27 static const WCHAR BackSlash
[] = {'\\',0};
28 static const WCHAR DateFormat
[] = {'%','u','-','%','u','-','%','u',0};
29 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
30 static const WCHAR DotHW
[] = {'.','H','W',0};
31 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
32 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
33 static const WCHAR InstanceKeyFormat
[] = {'%','0','4','l','u',0};
34 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
35 static const WCHAR VersionFormat
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
37 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
38 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
39 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
40 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
41 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
44 (CALLBACK
* CLASS_INSTALL_PROC
) (
45 IN DI_FUNCTION InstallFunction
,
46 IN HDEVINFO DeviceInfoSet
,
47 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
49 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
50 IN HDEVINFO DeviceInfoSet
,
51 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
53 (CALLBACK
* COINSTALLER_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
57 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
59 struct CoInstallerElement
64 COINSTALLER_PROC Function
;
65 BOOL DoPostProcessing
;
69 struct GetSectionCallbackInfo
71 PSP_ALTPLATFORM_INFO PlatformInfo
;
75 WCHAR BestSection
[LINE_LEN
+ 1];
76 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
81 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
83 static const WCHAR fmt
[] = {'{','%','0','8','X','-','%','0','4','X','-',
84 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
85 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
88 sprintfW(guidStr
, fmt
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
89 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
90 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
94 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
98 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
99 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
100 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
101 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
102 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
103 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
104 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
105 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
106 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
107 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
108 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
109 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
110 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
111 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
112 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
113 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
114 case CR_ALREADY_SUCH_DEVINST
: return ERROR_DEVINST_ALREADY_EXISTS
;
115 case CR_SUCCESS
: return ERROR_SUCCESS
;
116 default: return ERROR_GEN_FAILURE
;
119 /* Does not happen */
122 /* Lower scores are best ones */
125 IN LPCWSTR SectionName
,
126 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
129 OUT PDWORD ScorePlatform
,
130 OUT PDWORD ScoreMajorVersion
,
131 OUT PDWORD ScoreMinorVersion
,
132 OUT PDWORD ScoreProductType
,
133 OUT PDWORD ScoreSuiteMask
)
135 LPWSTR Section
= NULL
;
136 //LPCWSTR pExtensionPlatform;
137 LPCWSTR pExtensionArchitecture
;
142 //static const WCHAR ExtensionPlatformNone[] = {'.',0};
143 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
144 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
146 static const WCHAR ExtensionArchitectureNone
[] = {0};
147 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
148 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
149 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
150 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
151 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
152 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
154 TRACE("%s(%s %p 0x%x 0x%x)\n",
155 __FUNCTION__
, debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
157 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
159 Section
= pSetupDuplicateString(SectionName
);
162 TRACE("pSetupDuplicateString() failed\n");
166 /* Set various extensions values */
167 switch (PlatformInfo
->Platform
)
169 case VER_PLATFORM_WIN32_WINDOWS
:
170 //pExtensionPlatform = ExtensionPlatformWindows;
172 case VER_PLATFORM_WIN32_NT
:
173 //pExtensionPlatform = ExtensionPlatformNT;
176 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
177 //pExtensionPlatform = ExtensionPlatformNone;
180 switch (PlatformInfo
->ProcessorArchitecture
)
182 case PROCESSOR_ARCHITECTURE_ALPHA
:
183 pExtensionArchitecture
= ExtensionArchitecturealpha
;
185 case PROCESSOR_ARCHITECTURE_AMD64
:
186 pExtensionArchitecture
= ExtensionArchitectureamd64
;
188 case PROCESSOR_ARCHITECTURE_IA64
:
189 pExtensionArchitecture
= ExtensionArchitectureia64
;
191 case PROCESSOR_ARCHITECTURE_INTEL
:
192 pExtensionArchitecture
= ExtensionArchitecturex86
;
194 case PROCESSOR_ARCHITECTURE_MIPS
:
195 pExtensionArchitecture
= ExtensionArchitecturemips
;
197 case PROCESSOR_ARCHITECTURE_PPC
:
198 pExtensionArchitecture
= ExtensionArchitectureppc
;
201 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
202 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
203 pExtensionArchitecture
= ExtensionArchitectureNone
;
209 * Field[1] Architecture
210 * Field[2] Major version
211 * Field[3] Minor version
212 * Field[4] Product type
213 * Field[5] Suite mask
214 * Remark: these fields may be NULL if the information is not provided
217 if (Fields
[0] == NULL
)
219 TRACE("No extension found\n");
220 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
224 Fields
[1] = Fields
[0] + 1;
225 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
226 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
228 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
232 *(Fields
[i
] - 1) = UNICODE_NULL
;
235 /* Take care of first 2 fields */
236 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
238 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
240 TRACE("Mismatch on platform field\n");
243 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
245 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
247 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
249 TRACE("Mismatch on platform field\n");
252 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
256 /* No platform specified */
257 *ScorePlatform
|= 0x02;
259 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
261 /* No architecture specified */
262 *ScorePlatform
|= 0x01;
264 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
266 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
267 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
271 /* Check if informations are matching */
272 if (Fields
[2] && *Fields
[2])
274 DWORD MajorVersion
, MinorVersion
= 0;
275 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
276 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
277 (errno
== ERANGE
|| errno
== EINVAL
))
279 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
282 if (Fields
[3] && *Fields
[3])
284 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
285 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
286 (errno
== ERANGE
|| errno
== EINVAL
))
288 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
292 if (PlatformInfo
->MajorVersion
< MajorVersion
||
293 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
295 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
296 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
299 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
300 if (MajorVersion
== PlatformInfo
->MajorVersion
)
301 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
303 *ScoreMinorVersion
= MinorVersion
;
305 else if (Fields
[3] && *Fields
[3])
307 TRACE("Minor version found without major version\n");
312 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
313 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
316 if (Fields
[4] && *Fields
[4])
318 DWORD CurrentProductType
;
319 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
320 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
321 (errno
== ERANGE
|| errno
== EINVAL
))
323 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
326 if (CurrentProductType
!= ProductType
)
328 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
329 CurrentProductType
, ProductType
);
334 *ScoreProductType
= 1;
336 if (Fields
[5] && *Fields
[5])
338 DWORD CurrentSuiteMask
;
339 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
340 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
341 (errno
== ERANGE
|| errno
== EINVAL
))
343 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
346 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
348 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
349 CurrentSuiteMask
, SuiteMask
);
352 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
355 *ScoreSuiteMask
= SuiteMask
;
366 IN LPCWSTR SectionName
,
369 struct GetSectionCallbackInfo
*info
= Context
;
370 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
373 if (SectionName
[info
->PrefixLength
] != '.')
376 ret
= CheckSectionValid(
377 &SectionName
[info
->PrefixLength
],
381 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
384 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
387 if (Score1
> info
->BestScore1
) goto done
;
388 if (Score1
< info
->BestScore1
) goto bettersection
;
389 if (Score2
> info
->BestScore2
) goto done
;
390 if (Score2
< info
->BestScore2
) goto bettersection
;
391 if (Score3
> info
->BestScore3
) goto done
;
392 if (Score3
< info
->BestScore3
) goto bettersection
;
393 if (Score4
> info
->BestScore4
) goto done
;
394 if (Score4
< info
->BestScore4
) goto bettersection
;
395 if (Score5
> info
->BestScore5
) goto done
;
396 if (Score5
< info
->BestScore5
) goto bettersection
;
400 strcpyW(info
->BestSection
, SectionName
);
401 info
->BestScore1
= Score1
;
402 info
->BestScore2
= Score2
;
403 info
->BestScore3
= Score3
;
404 info
->BestScore4
= Score4
;
405 info
->BestScore5
= Score5
;
411 /***********************************************************************
412 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
415 SetupDiGetActualSectionToInstallExW(
417 IN PCWSTR InfSectionName
,
418 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
419 OUT PWSTR InfSectionWithExt OPTIONAL
,
420 IN DWORD InfSectionWithExtSize
,
421 OUT PDWORD RequiredSize OPTIONAL
,
422 OUT PWSTR
* Extension OPTIONAL
,
427 TRACE("%s(%p %s %p %p %lu %p %p %p)\n", __FUNCTION__
, InfHandle
, debugstr_w(InfSectionName
),
428 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
429 RequiredSize
, Extension
, Reserved
);
431 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
432 SetLastError(ERROR_INVALID_HANDLE
);
433 else if (!InfSectionName
)
434 SetLastError(ERROR_INVALID_PARAMETER
);
435 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
436 SetLastError(ERROR_INVALID_USER_BUFFER
);
437 else if (Reserved
!= NULL
)
438 SetLastError(ERROR_INVALID_PARAMETER
);
441 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
442 static BYTE CurrentProductType
= 0;
443 static WORD CurrentSuiteMask
= 0;
444 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
445 struct GetSectionCallbackInfo CallbackInfo
;
450 /* Fill platform info if needed */
451 if (AlternatePlatformInfo
)
453 pPlatformInfo
= AlternatePlatformInfo
;
459 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
461 /* That's the first time we go here. We need to fill in the structure */
462 SYSTEM_INFO SystemInfo
;
463 GetSystemInfo(&SystemInfo
);
464 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
465 CurrentPlatform
.Platform
= OsVersionInfo
.dwPlatformId
;
466 CurrentPlatform
.MajorVersion
= OsVersionInfo
.dwMajorVersion
;
467 CurrentPlatform
.MinorVersion
= OsVersionInfo
.dwMinorVersion
;
468 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
469 CurrentPlatform
.Reserved
= 0;
470 CurrentProductType
= OsVersionInfo
.wProductType
;
471 CurrentSuiteMask
= OsVersionInfo
.wSuiteMask
;
473 ProductType
= CurrentProductType
;
474 SuiteMask
= CurrentSuiteMask
;
477 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
478 CallbackInfo
.ProductType
= ProductType
;
479 CallbackInfo
.SuiteMask
= SuiteMask
;
480 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
481 CallbackInfo
.BestScore1
= ULONG_MAX
;
482 CallbackInfo
.BestScore2
= ULONG_MAX
;
483 CallbackInfo
.BestScore3
= ULONG_MAX
;
484 CallbackInfo
.BestScore4
= ULONG_MAX
;
485 CallbackInfo
.BestScore5
= ULONG_MAX
;
486 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
487 TRACE("EnumerateSectionsStartingWith(InfSectionName = %S)\n", InfSectionName
);
488 if (!EnumerateSectionsStartingWith(
494 SetLastError(ERROR_GEN_FAILURE
);
497 TRACE("CallbackInfo.BestSection = %S\n", CallbackInfo
.BestSection
);
499 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
500 if (RequiredSize
!= NULL
)
501 *RequiredSize
= dwFullLength
+ 1;
503 if (InfSectionWithExtSize
> 0)
505 if (InfSectionWithExtSize
< dwFullLength
+ 1)
507 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
510 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
513 DWORD dwLength
= lstrlenW(InfSectionName
);
514 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
522 TRACE("Returning %d\n", ret
);
529 IN
struct DeviceInfoSet
*list
,
530 IN LPCWSTR InstancePath
,
531 IN LPCGUID pClassGuid
,
532 OUT
struct DeviceInfo
**pDeviceInfo
)
536 struct DeviceInfo
*deviceInfo
;
540 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
541 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
544 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
547 ZeroMemory(deviceInfo
, size
);
549 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
550 if (cr
!= CR_SUCCESS
)
552 SetLastError(GetErrorCodeFromCrCode(cr
));
556 deviceInfo
->set
= list
;
557 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
558 strcpyW(deviceInfo
->Data
, InstancePath
);
559 deviceInfo
->instanceId
= deviceInfo
->Data
;
560 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
561 deviceInfo
->DeviceDescription
= NULL
;
562 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
563 deviceInfo
->CreationFlags
= 0;
564 InitializeListHead(&deviceInfo
->DriverListHead
);
565 InitializeListHead(&deviceInfo
->InterfaceListHead
);
567 *pDeviceInfo
= deviceInfo
;
573 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
575 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
576 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
581 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
583 PLIST_ENTRY ListEntry
;
584 struct DriverInfoElement
*driverInfo
;
585 struct DeviceInterface
*deviceInterface
;
587 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
589 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
590 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
591 if (!DestroyDriverInfoElement(driverInfo
))
594 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
596 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
597 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
598 if (!DestroyDeviceInterface(deviceInterface
))
601 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
602 if (deviceInfo
->hmodDevicePropPageProvider
)
603 FreeLibrary(deviceInfo
->hmodDevicePropPageProvider
);
604 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
608 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
610 PLIST_ENTRY ListEntry
;
611 struct DeviceInfo
*deviceInfo
;
613 while (!IsListEmpty(&list
->ListHead
))
615 ListEntry
= RemoveHeadList(&list
->ListHead
);
616 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
);
617 if (!DestroyDeviceInfo(deviceInfo
))
620 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
621 RegCloseKey(list
->HKLM
);
622 CM_Disconnect_Machine(list
->hMachine
);
623 DestroyClassInstallParams(&list
->ClassInstallParams
);
624 if (list
->hmodClassPropPageProvider
)
625 FreeLibrary(list
->hmodClassPropPageProvider
);
626 return HeapFree(GetProcessHeap(), 0, list
);
629 /***********************************************************************
630 * SetupDiBuildClassInfoList (SETUPAPI.@)
632 * Returns a list of setup class GUIDs that identify the classes
633 * that are installed on a local machine.
636 * Flags [I] control exclusion of classes from the list.
637 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
638 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
639 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
645 BOOL WINAPI
SetupDiBuildClassInfoList(
647 LPGUID ClassGuidList
,
648 DWORD ClassGuidListSize
,
652 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
653 ClassGuidListSize
, RequiredSize
,
657 /***********************************************************************
658 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
660 * Returns a list of setup class GUIDs that identify the classes
661 * that are installed on a local or remote machine.
664 * Flags [I] control exclusion of classes from the list.
665 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
666 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
667 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
668 * MachineName [I] name of a remote machine.
669 * Reserved [I] must be NULL.
675 BOOL WINAPI
SetupDiBuildClassInfoListExA(
677 LPGUID ClassGuidList
,
678 DWORD ClassGuidListSize
,
683 LPWSTR MachineNameW
= NULL
;
686 TRACE("%s(0x%lx %p %lu %p %s %p)\n", __FUNCTION__
, Flags
, ClassGuidList
,
687 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
691 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
692 if (MachineNameW
== NULL
) return FALSE
;
695 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
696 ClassGuidListSize
, RequiredSize
,
697 MachineNameW
, Reserved
);
699 MyFree(MachineNameW
);
704 /***********************************************************************
705 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
707 * Returns a list of setup class GUIDs that identify the classes
708 * that are installed on a local or remote machine.
711 * Flags [I] control exclusion of classes from the list.
712 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
713 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
714 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
715 * MachineName [I] name of a remote machine.
716 * Reserved [I] must be NULL.
722 BOOL WINAPI
SetupDiBuildClassInfoListExW(
724 LPGUID ClassGuidList
,
725 DWORD ClassGuidListSize
,
730 GUID CurrentClassGuid
;
733 DWORD dwGuidListIndex
= 0;
734 HMACHINE hMachine
= NULL
;
737 TRACE("%s(0x%lx %p %lu %p %s %p)\n", __FUNCTION__
, Flags
, ClassGuidList
,
738 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
742 SetLastError(ERROR_INVALID_PARAMETER
);
745 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
747 SetLastError(ERROR_INVALID_PARAMETER
);
753 cr
= CM_Connect_MachineW(MachineName
, &hMachine
);
754 if (cr
!= CR_SUCCESS
)
756 SetLastError(GetErrorCodeFromCrCode(cr
));
761 for (dwIndex
= 0; ; dwIndex
++)
763 cr
= CM_Enumerate_Classes_Ex(dwIndex
,
767 if (cr
== CR_SUCCESS
)
769 TRACE("Guid: %s\n", debugstr_guid(&CurrentClassGuid
));
770 if (CM_Open_Class_Key_ExW(&CurrentClassGuid
,
773 RegDisposition_OpenExisting
,
775 CM_OPEN_CLASS_KEY_INSTALLER
,
776 hMachine
) != CR_SUCCESS
)
778 SetLastError(GetErrorCodeFromCrCode(cr
));
780 CM_Disconnect_Machine(hMachine
);
784 if (!RegQueryValueExW(hClassKey
,
785 REGSTR_VAL_NOUSECLASS
,
791 TRACE("'NoUseClass' value found!\n");
792 RegCloseKey(hClassKey
);
796 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
797 (!RegQueryValueExW(hClassKey
,
798 REGSTR_VAL_NOINSTALLCLASS
,
804 TRACE("'NoInstallClass' value found!\n");
805 RegCloseKey(hClassKey
);
809 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
810 (!RegQueryValueExW(hClassKey
,
811 REGSTR_VAL_NODISPLAYCLASS
,
817 TRACE("'NoDisplayClass' value found!\n");
818 RegCloseKey(hClassKey
);
822 RegCloseKey(hClassKey
);
824 if (dwGuidListIndex
< ClassGuidListSize
)
826 ClassGuidList
[dwGuidListIndex
] = CurrentClassGuid
;
832 if (cr
!= ERROR_SUCCESS
)
837 CM_Disconnect_Machine(hMachine
);
839 if (RequiredSize
!= NULL
)
840 *RequiredSize
= dwGuidListIndex
;
842 if (ClassGuidListSize
< dwGuidListIndex
)
844 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
851 /***********************************************************************
852 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
854 BOOL WINAPI
SetupDiClassGuidsFromNameA(
856 LPGUID ClassGuidList
,
857 DWORD ClassGuidListSize
,
860 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
861 ClassGuidListSize
, RequiredSize
,
865 /***********************************************************************
866 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
868 BOOL WINAPI
SetupDiClassGuidsFromNameW(
870 LPGUID ClassGuidList
,
871 DWORD ClassGuidListSize
,
874 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
875 ClassGuidListSize
, RequiredSize
,
879 /***********************************************************************
880 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
882 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
884 LPGUID ClassGuidList
,
885 DWORD ClassGuidListSize
,
890 LPWSTR ClassNameW
= NULL
;
891 LPWSTR MachineNameW
= NULL
;
894 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_a(ClassName
), ClassGuidList
,
895 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
899 SetLastError(ERROR_INVALID_PARAMETER
);
903 ClassNameW
= pSetupMultiByteToUnicode(ClassName
, CP_ACP
);
904 if (ClassNameW
== NULL
)
909 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
910 if (MachineNameW
== NULL
)
917 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
918 ClassGuidListSize
, RequiredSize
,
919 MachineNameW
, Reserved
);
921 MyFree(MachineNameW
);
927 /***********************************************************************
928 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
930 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
932 LPGUID ClassGuidList
,
933 DWORD ClassGuidListSize
,
939 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
945 DWORD dwGuidListIndex
= 0;
947 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_w(ClassName
), ClassGuidList
,
948 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
950 if (!ClassName
|| !RequiredSize
)
952 SetLastError(ERROR_INVALID_PARAMETER
);
955 if (!ClassGuidList
&& ClassGuidListSize
> 0)
957 SetLastError(ERROR_INVALID_PARAMETER
);
962 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
963 KEY_ENUMERATE_SUB_KEYS
,
967 if (hClassesKey
== INVALID_HANDLE_VALUE
)
972 for (dwIndex
= 0; ; dwIndex
++)
975 lError
= RegEnumKeyExW(hClassesKey
,
983 TRACE("RegEnumKeyExW() returns %d\n", lError
);
984 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
986 TRACE("Key name: %p\n", szKeyName
);
988 if (RegOpenKeyExW(hClassesKey
,
994 RegCloseKey(hClassesKey
);
998 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
999 if (!RegQueryValueExW(hClassKey
,
1003 (LPBYTE
)szClassName
,
1006 TRACE("Class name: %p\n", szClassName
);
1008 if (strcmpiW(szClassName
, ClassName
) == 0)
1010 TRACE("Found matching class name\n");
1012 TRACE("Guid: %p\n", szKeyName
);
1013 if (dwGuidListIndex
< ClassGuidListSize
)
1015 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1019 TRACE("Guid: %p\n", &szKeyName
[1]);
1021 UuidFromStringW(&szKeyName
[1],
1022 &ClassGuidList
[dwGuidListIndex
]);
1029 RegCloseKey(hClassKey
);
1032 if (lError
!= ERROR_SUCCESS
)
1036 RegCloseKey(hClassesKey
);
1038 if (RequiredSize
!= NULL
)
1039 *RequiredSize
= dwGuidListIndex
;
1041 if (ClassGuidListSize
< dwGuidListIndex
)
1043 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1050 /***********************************************************************
1051 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1053 BOOL WINAPI
SetupDiClassNameFromGuidA(
1054 const GUID
* ClassGuid
,
1056 DWORD ClassNameSize
,
1057 PDWORD RequiredSize
)
1059 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1060 ClassNameSize
, RequiredSize
,
1064 /***********************************************************************
1065 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1067 BOOL WINAPI
SetupDiClassNameFromGuidW(
1068 const GUID
* ClassGuid
,
1070 DWORD ClassNameSize
,
1071 PDWORD RequiredSize
)
1073 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1074 ClassNameSize
, RequiredSize
,
1078 /***********************************************************************
1079 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1081 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1082 const GUID
* ClassGuid
,
1084 DWORD ClassNameSize
,
1085 PDWORD RequiredSize
,
1089 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1090 LPWSTR MachineNameW
= NULL
;
1094 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1095 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1096 RequiredSize
, MachineNameW
, Reserved
);
1099 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1100 ClassNameSize
, NULL
, NULL
);
1101 if (len
== 0 || len
> ClassNameSize
)
1103 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1107 MyFree(MachineNameW
);
1111 /***********************************************************************
1112 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1114 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1115 const GUID
* ClassGuid
,
1117 DWORD ClassNameSize
,
1118 PDWORD RequiredSize
,
1128 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), ClassName
,
1129 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1131 /* Make sure there's a GUID */
1132 if (ClassGuid
== NULL
)
1134 SetLastError(ERROR_INVALID_CLASS
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1138 /* Make sure there's a real buffer when there's a size */
1139 if ((ClassNameSize
> 0) && (ClassName
== NULL
))
1141 SetLastError(ERROR_INVALID_PARAMETER
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1145 /* Open the key for the GUID */
1146 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INSTALLER
, MachineName
, Reserved
);
1148 if (hKey
== INVALID_HANDLE_VALUE
)
1151 /* Retrieve the class name data and close the key */
1152 rc
= QueryRegistryValue(hKey
, REGSTR_VAL_CLASS
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
1155 /* Make sure we got the data */
1156 if (rc
!= ERROR_SUCCESS
)
1162 /* Make sure the data is a string */
1163 if (dwRegType
!= REG_SZ
)
1166 SetLastError(ERROR_GEN_FAILURE
);
1170 /* Determine the length of the class name */
1171 dwLength
/= sizeof(WCHAR
);
1173 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
1174 /* Count the null-terminator */
1177 /* Inform the caller about the class name */
1178 if ((ClassName
!= NULL
) && (dwLength
<= ClassNameSize
))
1180 memcpy(ClassName
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
1181 ClassName
[dwLength
- 1] = UNICODE_NULL
;
1184 /* Inform the caller about the required size */
1185 if (RequiredSize
!= NULL
)
1186 *RequiredSize
= dwLength
;
1188 /* Clean up the buffer */
1191 /* Make sure the buffer was large enough */
1192 if ((ClassName
== NULL
) || (dwLength
> ClassNameSize
))
1194 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1201 /***********************************************************************
1202 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1205 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1208 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1211 /***********************************************************************
1212 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1215 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1220 LPWSTR MachineNameW
= NULL
;
1223 TRACE("%s(%s %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), hwndParent
,
1224 debugstr_a(MachineName
), Reserved
);
1228 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1229 if (MachineNameW
== NULL
)
1230 return INVALID_HANDLE_VALUE
;
1233 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1234 MachineNameW
, Reserved
);
1236 MyFree(MachineNameW
);
1241 /***********************************************************************
1242 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1244 * Create an empty DeviceInfoSet list.
1247 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1249 * hwndParent [I] hwnd needed for interface related actions.
1250 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1251 * local registry will be used.
1252 * Reserved [I] must be NULL
1255 * Success: empty list.
1256 * Failure: INVALID_HANDLE_VALUE.
1259 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1264 struct DeviceInfoSet
*list
= NULL
;
1265 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1268 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1270 TRACE("%s(%s %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), hwndParent
,
1271 debugstr_w(MachineName
), Reserved
);
1273 if (MachineName
!= NULL
)
1275 SIZE_T len
= strlenW(MachineName
);
1276 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1278 SetLastError(ERROR_INVALID_MACHINENAME
);
1282 size
+= (len
+ 3) * sizeof(WCHAR
);
1287 if (Reserved
!= NULL
)
1289 SetLastError(ERROR_INVALID_PARAMETER
);
1290 return INVALID_HANDLE_VALUE
;
1293 list
= MyMalloc(size
);
1296 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1297 return INVALID_HANDLE_VALUE
;
1299 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1301 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1302 memcpy(&list
->ClassGuid
,
1303 ClassGuid
? ClassGuid
: &GUID_NULL
,
1304 sizeof(list
->ClassGuid
));
1305 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1306 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1307 list
->InstallParams
.hwndParent
= hwndParent
;
1310 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1311 if (rc
!= ERROR_SUCCESS
)
1313 SetLastError(ERROR_INVALID_MACHINENAME
);
1317 list
->szData
[0] = list
->szData
[1] = '\\';
1318 strcpyW(list
->szData
+ 2, MachineName
);
1319 list
->MachineName
= list
->szData
;
1323 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1324 list
->MachineName
= NULL
;
1326 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1327 if (cr
!= CR_SUCCESS
)
1329 SetLastError(GetErrorCodeFromCrCode(cr
));
1332 InitializeListHead(&list
->DriverListHead
);
1333 InitializeListHead(&list
->ListHead
);
1335 return (HDEVINFO
)list
;
1338 if (ret
== INVALID_HANDLE_VALUE
)
1342 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1343 RegCloseKey(list
->HKLM
);
1350 /***********************************************************************
1351 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1353 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1354 HDEVINFO DeviceInfoSet
,
1355 PSP_DEVINFO_DATA DeviceInfoData
,
1360 PCSTR InfSectionName
)
1362 PWSTR InfSectionNameW
= NULL
;
1365 TRACE("%s(%p %p %d %d %d %p %s)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Scope
,
1366 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1370 if (!InfSectionName
)
1372 SetLastError(ERROR_INVALID_PARAMETER
);
1373 return INVALID_HANDLE_VALUE
;
1377 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
1378 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1381 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1382 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1383 MyFree(InfSectionNameW
);
1388 OpenHardwareProfileKey(
1391 IN DWORD samDesired
);
1393 /***********************************************************************
1394 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1396 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1397 HDEVINFO DeviceInfoSet
,
1398 PSP_DEVINFO_DATA DeviceInfoData
,
1403 PCWSTR InfSectionName
)
1405 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1406 struct DeviceInfo
*deviceInfo
;
1407 HKEY key
= INVALID_HANDLE_VALUE
;
1409 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1413 TRACE("%s(%p %p %lu %lu %lu %p %s)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Scope
,
1414 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1416 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1418 SetLastError(ERROR_INVALID_HANDLE
);
1419 return INVALID_HANDLE_VALUE
;
1421 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1423 SetLastError(ERROR_INVALID_HANDLE
);
1424 return INVALID_HANDLE_VALUE
;
1426 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1427 || !DeviceInfoData
->Reserved
)
1429 SetLastError(ERROR_INVALID_PARAMETER
);
1430 return INVALID_HANDLE_VALUE
;
1432 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1434 SetLastError(ERROR_INVALID_FLAGS
);
1435 return INVALID_HANDLE_VALUE
;
1437 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1439 SetLastError(ERROR_INVALID_FLAGS
);
1440 return INVALID_HANDLE_VALUE
;
1442 if (InfHandle
&& !InfSectionName
)
1444 SetLastError(ERROR_INVALID_PARAMETER
);
1445 return INVALID_HANDLE_VALUE
;
1447 if (!InfHandle
&& InfSectionName
)
1449 SetLastError(ERROR_INVALID_PARAMETER
);
1450 return INVALID_HANDLE_VALUE
;
1453 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1455 if (Scope
== DICS_FLAG_GLOBAL
)
1456 RootKey
= set
->HKLM
;
1457 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1459 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1460 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1462 RootKey
= hHWProfileKey
;
1465 if (KeyType
== DIREG_DEV
)
1467 #if _WIN32_WINNT >= 0x502
1468 hKey
= SETUPDI_CreateDevKey(RootKey
, deviceInfo
, KEY_READ
| KEY_WRITE
);
1470 hKey
= SETUPDI_CreateDevKey(RootKey
, deviceInfo
, KEY_ALL_ACCESS
);
1472 if (hKey
== INVALID_HANDLE_VALUE
)
1475 if (Scope
== DICS_FLAG_GLOBAL
)
1477 HKEY hTempKey
= hKey
;
1479 rc
= RegCreateKeyExW(hTempKey
,
1480 L
"Device Parameters",
1483 REG_OPTION_NON_VOLATILE
,
1484 #if _WIN32_WINNT >= 0x502
1485 KEY_READ
| KEY_WRITE
,
1492 if (rc
== ERROR_SUCCESS
)
1493 RegCloseKey(hTempKey
);
1496 else /* KeyType == DIREG_DRV */
1498 #if _WIN32_WINNT >= 0x502
1499 hKey
= SETUPDI_CreateDrvKey(RootKey
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_READ
| KEY_WRITE
);
1501 hKey
= SETUPDI_CreateDrvKey(RootKey
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_ALL_ACCESS
);
1503 if (hKey
== INVALID_HANDLE_VALUE
)
1507 /* Do installation of the specified section */
1510 FIXME("Need to install section %s in file %p\n",
1511 debugstr_w(InfSectionName
), InfHandle
);
1516 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1517 RegCloseKey(hHWProfileKey
);
1518 if (hKey
!= NULL
&& hKey
!= key
)
1521 TRACE("Returning 0x%p\n", key
);
1525 /***********************************************************************
1526 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1528 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1529 HDEVINFO DeviceInfoSet
,
1531 CONST GUID
*ClassGuid
,
1532 PCSTR DeviceDescription
,
1534 DWORD CreationFlags
,
1535 PSP_DEVINFO_DATA DeviceInfoData
)
1538 LPWSTR DeviceNameW
= NULL
;
1539 LPWSTR DeviceDescriptionW
= NULL
;
1545 DeviceNameW
= pSetupMultiByteToUnicode(DeviceName
, CP_ACP
);
1546 if (DeviceNameW
== NULL
) return FALSE
;
1548 if (DeviceDescription
)
1550 DeviceDescriptionW
= pSetupMultiByteToUnicode(DeviceDescription
, CP_ACP
);
1551 if (DeviceDescriptionW
== NULL
)
1553 MyFree(DeviceNameW
);
1558 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1559 hwndParent
, CreationFlags
, DeviceInfoData
);
1561 MyFree(DeviceNameW
);
1562 MyFree(DeviceDescriptionW
);
1567 /***********************************************************************
1568 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1570 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1571 HDEVINFO DeviceInfoSet
,
1573 CONST GUID
*ClassGuid
,
1574 PCWSTR DeviceDescription
,
1576 DWORD CreationFlags
,
1577 PSP_DEVINFO_DATA DeviceInfoData
)
1579 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1580 struct DeviceInfo
*deviceInfo
= NULL
;
1583 DEVINST RootDevInst
;
1585 WCHAR GenInstanceId
[MAX_DEVICE_ID_LEN
];
1588 TRACE("%s(%p %s %s %s %p %x %p)\n", __FUNCTION__
, DeviceInfoSet
, debugstr_w(DeviceName
),
1589 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1590 hwndParent
, CreationFlags
, DeviceInfoData
);
1594 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1597 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1599 SetLastError(ERROR_INVALID_HANDLE
);
1604 SetLastError(ERROR_INVALID_PARAMETER
);
1607 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1609 SetLastError(ERROR_INVALID_HANDLE
);
1612 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1613 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1615 SetLastError(ERROR_CLASS_MISMATCH
);
1618 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1620 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1621 SetLastError(ERROR_INVALID_FLAGS
);
1625 /* Get the root device instance */
1626 cr
= CM_Locate_DevInst_ExW(&RootDevInst
,
1628 CM_LOCATE_DEVINST_NORMAL
,
1630 if (cr
!= CR_SUCCESS
)
1632 SetLastError(ERROR_INVALID_DATA
);
1636 dwFlags
= CM_CREATE_DEVINST_PHANTOM
;
1637 if (CreationFlags
& DICD_GENERATE_ID
)
1638 dwFlags
|= CM_CREATE_DEVINST_GENERATE_ID
;
1640 /* Create the new device instance */
1641 cr
= CM_Create_DevInst_ExW(&DevInst
,
1642 (DEVINSTID
)DeviceName
,
1646 if (cr
!= CR_SUCCESS
)
1648 SetLastError(GetErrorCodeFromCrCode(cr
));
1652 if (CreationFlags
& DICD_GENERATE_ID
)
1654 /* Grab the actual instance ID that was created */
1655 cr
= CM_Get_Device_ID_Ex(DevInst
,
1660 if (cr
!= CR_SUCCESS
)
1662 SetLastError(GetErrorCodeFromCrCode(cr
));
1666 DeviceName
= GenInstanceId
;
1667 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName
));
1670 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1672 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1674 if (!DeviceInfoData
)
1678 if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1680 SetLastError(ERROR_INVALID_USER_BUFFER
);
1684 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1685 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1686 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1694 if (deviceInfo
!= NULL
)
1696 /* Remove deviceInfo from List */
1697 RemoveEntryList(&deviceInfo
->ListEntry
);
1699 /* Destroy deviceInfo */
1700 DestroyDeviceInfo(deviceInfo
);
1704 TRACE("Returning %d\n", ret
);
1708 /***********************************************************************
1709 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1711 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1712 HDEVINFO DeviceInfoSet
,
1713 PSP_DEVINFO_DATA DeviceInfoData
,
1715 PSP_DETSIG_CMPPROC CompareProc
,
1716 PVOID CompareContext
,
1717 PSP_DEVINFO_DATA DupDeviceInfoData
)
1719 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1720 WCHAR DevInstId
[MAX_DEVICE_ID_LEN
];
1721 DEVINST ParentDevInst
;
1723 DWORD dwError
= ERROR_SUCCESS
;
1725 TRACE("%s(%p %p %08x %p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Flags
,
1726 CompareProc
, CompareContext
, DupDeviceInfoData
);
1728 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1730 SetLastError(ERROR_INVALID_HANDLE
);
1733 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1735 SetLastError(ERROR_INVALID_HANDLE
);
1738 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1739 || !DeviceInfoData
->Reserved
)
1741 SetLastError(ERROR_INVALID_PARAMETER
);
1745 if (Flags
& ~SPRDI_FIND_DUPS
)
1747 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~SPRDI_FIND_DUPS
);
1748 SetLastError(ERROR_INVALID_FLAGS
);
1752 if (Flags
& SPRDI_FIND_DUPS
)
1754 FIXME("Unimplemented codepath!\n");
1757 CM_Get_Device_ID_Ex(DeviceInfoData
->DevInst
,
1763 CM_Get_Parent_Ex(&ParentDevInst
,
1764 DeviceInfoData
->DevInst
,
1768 cr
= CM_Create_DevInst_Ex(&DeviceInfoData
->DevInst
,
1771 CM_CREATE_DEVINST_NORMAL
| CM_CREATE_DEVINST_DO_NOT_INSTALL
,
1773 if (cr
!= CR_SUCCESS
&&
1774 cr
!= CR_ALREADY_SUCH_DEVINST
)
1776 dwError
= ERROR_NO_SUCH_DEVINST
;
1779 SetLastError(dwError
);
1781 return (dwError
== ERROR_SUCCESS
);
1784 /***********************************************************************
1785 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1787 BOOL WINAPI
SetupDiEnumDeviceInfo(
1790 PSP_DEVINFO_DATA info
)
1794 TRACE("%s(%p %d %p)\n", __FUNCTION__
, devinfo
, index
, info
);
1798 SetLastError(ERROR_INVALID_PARAMETER
);
1801 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1803 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1804 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1806 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1807 SetLastError(ERROR_INVALID_USER_BUFFER
);
1810 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1811 while (ItemList
!= &list
->ListHead
&& index
-- > 0)
1812 ItemList
= ItemList
->Flink
;
1813 if (ItemList
== &list
->ListHead
)
1814 SetLastError(ERROR_NO_MORE_ITEMS
);
1817 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1818 memcpy(&info
->ClassGuid
,
1819 &DevInfo
->ClassGuid
,
1821 info
->DevInst
= DevInfo
->dnDevInst
;
1822 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1828 SetLastError(ERROR_INVALID_HANDLE
);
1831 SetLastError(ERROR_INVALID_HANDLE
);
1835 /***********************************************************************
1836 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1838 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1839 HDEVINFO DeviceInfoSet
,
1840 PSP_DEVINFO_DATA DeviceInfoData
,
1841 PSTR DeviceInstanceId
,
1842 DWORD DeviceInstanceIdSize
,
1843 PDWORD RequiredSize
)
1849 TRACE("%s(%p %p %p %d %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1850 DeviceInstanceIdSize
, RequiredSize
);
1852 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1854 SetLastError(ERROR_INVALID_PARAMETER
);
1858 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1863 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1865 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
1868 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1875 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
1877 DeviceInstanceIdSize
, NULL
, NULL
);
1883 if (len
> DeviceInstanceIdSize
)
1885 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1889 *RequiredSize
= len
;
1897 *RequiredSize
= size
;
1898 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1904 /***********************************************************************
1905 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1907 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
1908 HDEVINFO DeviceInfoSet
,
1909 PSP_DEVINFO_DATA DeviceInfoData
,
1910 PWSTR DeviceInstanceId
,
1911 DWORD DeviceInstanceIdSize
,
1912 PDWORD RequiredSize
)
1914 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1915 struct DeviceInfo
*devInfo
;
1917 TRACE("%s(%p %p %p %d %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1918 DeviceInstanceIdSize
, RequiredSize
);
1920 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1922 SetLastError(ERROR_INVALID_HANDLE
);
1925 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1927 SetLastError(ERROR_INVALID_HANDLE
);
1930 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1931 || !DeviceInfoData
->Reserved
)
1933 SetLastError(ERROR_INVALID_PARAMETER
);
1936 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1937 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1939 SetLastError(ERROR_INVALID_PARAMETER
);
1942 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
1944 SetLastError(ERROR_INVALID_PARAMETER
);
1947 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
1948 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
1950 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1952 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1955 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
1957 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1961 /***********************************************************************
1962 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1964 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
1966 PCSTR InfSectionName
,
1967 PSTR InfSectionWithExt
,
1968 DWORD InfSectionWithExtSize
,
1969 PDWORD RequiredSize
,
1972 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
1973 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
1977 /***********************************************************************
1978 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1980 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
1982 PCWSTR InfSectionName
,
1983 PWSTR InfSectionWithExt
,
1984 DWORD InfSectionWithExtSize
,
1985 PDWORD RequiredSize
,
1988 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
1989 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
1993 /***********************************************************************
1994 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
1997 SetupDiGetActualSectionToInstallExA(
1999 IN PCSTR InfSectionName
,
2000 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
2001 OUT PSTR InfSectionWithExt OPTIONAL
,
2002 IN DWORD InfSectionWithExtSize
,
2003 OUT PDWORD RequiredSize OPTIONAL
,
2004 OUT PSTR
* Extension OPTIONAL
,
2007 LPWSTR InfSectionNameW
= NULL
;
2008 LPWSTR InfSectionWithExtW
= NULL
;
2010 BOOL bResult
= FALSE
;
2012 TRACE("%s()\n", __FUNCTION__
);
2016 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2017 if (InfSectionNameW
== NULL
)
2020 if (InfSectionWithExt
)
2022 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2023 if (InfSectionWithExtW
== NULL
)
2027 bResult
= SetupDiGetActualSectionToInstallExW(
2028 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2029 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2030 InfSectionWithExtSize
,
2032 Extension
? &ExtensionW
: NULL
,
2035 if (bResult
&& InfSectionWithExt
)
2037 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2038 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2040 if (bResult
&& Extension
)
2042 if (ExtensionW
== NULL
)
2045 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2049 MyFree(InfSectionNameW
);
2050 MyFree(InfSectionWithExtW
);
2055 /***********************************************************************
2056 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2058 BOOL WINAPI
SetupDiGetClassDescriptionA(
2059 const GUID
* ClassGuid
,
2060 PSTR ClassDescription
,
2061 DWORD ClassDescriptionSize
,
2062 PDWORD RequiredSize
)
2064 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2065 ClassDescriptionSize
,
2066 RequiredSize
, NULL
, NULL
);
2069 /***********************************************************************
2070 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2072 BOOL WINAPI
SetupDiGetClassDescriptionW(
2073 const GUID
* ClassGuid
,
2074 PWSTR ClassDescription
,
2075 DWORD ClassDescriptionSize
,
2076 PDWORD RequiredSize
)
2078 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2079 ClassDescriptionSize
,
2080 RequiredSize
, NULL
, NULL
);
2083 /***********************************************************************
2084 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2086 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2087 const GUID
* ClassGuid
,
2088 PSTR ClassDescription
,
2089 DWORD ClassDescriptionSize
,
2090 PDWORD RequiredSize
,
2094 PWCHAR ClassDescriptionW
= NULL
;
2095 LPWSTR MachineNameW
= NULL
;
2098 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), ClassDescription
,
2099 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2101 if (ClassDescriptionSize
> 0)
2103 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2104 if (!ClassDescriptionW
)
2106 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2113 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
2116 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2121 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2122 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2125 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2126 ClassDescriptionSize
, NULL
, NULL
);
2127 if (len
== 0 || len
> ClassDescriptionSize
)
2129 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2135 MyFree(ClassDescriptionW
);
2136 MyFree(MachineNameW
);
2140 /***********************************************************************
2141 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2143 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2144 const GUID
* ClassGuid
,
2145 PWSTR ClassDescription
,
2146 DWORD ClassDescriptionSize
,
2147 PDWORD RequiredSize
,
2157 TRACE("%s(%s %p %lu %p %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), ClassDescription
,
2158 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2160 /* Make sure there's a GUID */
2163 SetLastError(ERROR_INVALID_PARAMETER
);
2167 /* Make sure there's a real buffer when there's a size */
2168 if (!ClassDescription
&& ClassDescriptionSize
> 0)
2170 SetLastError(ERROR_INVALID_PARAMETER
);
2174 /* Open the key for the GUID */
2175 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2180 if (hKey
== INVALID_HANDLE_VALUE
)
2183 /* Retrieve the class description data and close the key */
2184 rc
= QueryRegistryValue(hKey
, NULL
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
2187 /* Make sure we got the data */
2188 if (rc
!= ERROR_SUCCESS
)
2194 /* Make sure the data is a string */
2195 if (dwRegType
!= REG_SZ
)
2198 SetLastError(ERROR_GEN_FAILURE
);
2202 /* Determine the length of the class description */
2203 dwLength
/= sizeof(WCHAR
);
2205 /* Count the null-terminator if none is present */
2206 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
2209 /* Inform the caller about the class description */
2210 if ((ClassDescription
!= NULL
) && (dwLength
<= ClassDescriptionSize
))
2212 memcpy(ClassDescription
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
2213 ClassDescription
[dwLength
- 1] = UNICODE_NULL
;
2216 /* Inform the caller about the required size */
2217 if (RequiredSize
!= NULL
)
2218 *RequiredSize
= dwLength
;
2220 /* Clean up the buffer */
2223 /* Make sure the buffer was large enough */
2224 if ((ClassDescription
== NULL
) || (dwLength
> ClassDescriptionSize
))
2226 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2233 /***********************************************************************
2234 * SetupDiGetClassDevsA (SETUPAPI.@)
2236 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2242 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2243 flags
, NULL
, NULL
, NULL
);
2246 /***********************************************************************
2247 * SetupDiGetClassDevsExA (SETUPAPI.@)
2249 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2259 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2263 enumstrW
= pSetupMultiByteToUnicode(enumstr
, CP_ACP
);
2266 ret
= INVALID_HANDLE_VALUE
;
2272 machineW
= pSetupMultiByteToUnicode(machine
, CP_ACP
);
2276 ret
= INVALID_HANDLE_VALUE
;
2280 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2281 machineW
, reserved
);
2289 /***********************************************************************
2290 * SetupDiGetClassDevsW (SETUPAPI.@)
2292 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2298 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2302 /***********************************************************************
2303 * SetupDiGetClassDevsExW (SETUPAPI.@)
2305 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2314 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2315 struct DeviceInfoSet
*list
;
2316 CONST GUID
*pClassGuid
;
2318 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2320 TRACE("%s(%s %s %p 0x%08x %p %s %p)\n", __FUNCTION__
, debugstr_guid(class),
2321 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2324 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2326 SetLastError(ERROR_INVALID_PARAMETER
);
2327 return INVALID_HANDLE_VALUE
;
2330 /* Create the deviceset if not set */
2333 list
= (struct DeviceInfoSet
*)deviceset
;
2334 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2336 SetLastError(ERROR_INVALID_HANDLE
);
2339 hDeviceInfo
= deviceset
;
2343 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2344 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2345 NULL
, machine
, NULL
);
2346 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2348 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2351 if (flags
& DIGCF_PROFILE
)
2352 FIXME(": flag DIGCF_PROFILE ignored\n");
2354 if (flags
& DIGCF_DEVICEINTERFACE
)
2358 SetLastError(ERROR_INVALID_PARAMETER
);
2361 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2365 /* Determine which class(es) should be included in the deviceset */
2366 if (flags
& DIGCF_ALLCLASSES
)
2368 /* The caller wants all classes. Check if
2369 * the deviceset limits us to one class */
2370 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2373 pClassGuid
= &list
->ClassGuid
;
2377 /* The caller wants one class. Check if it matches deviceset class */
2378 if (IsEqualIID(&list
->ClassGuid
, class)
2379 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2385 SetLastError(ERROR_INVALID_PARAMETER
);
2389 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2391 /* No class specified. Try to use the one of the deviceset */
2392 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2393 pClassGuid
= &list
->ClassGuid
;
2396 SetLastError(ERROR_INVALID_PARAMETER
);
2402 SetLastError(ERROR_INVALID_PARAMETER
);
2405 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2407 if (rc
!= ERROR_SUCCESS
)
2415 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2416 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2420 /***********************************************************************
2421 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2423 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2424 HDEVINFO DeviceInfoSet
,
2425 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2427 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2429 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DevInfoData
);
2431 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2433 SetLastError(ERROR_INVALID_HANDLE
);
2436 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2438 SetLastError(ERROR_INVALID_HANDLE
);
2442 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2444 SetLastError(ERROR_INVALID_PARAMETER
);
2447 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2448 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2449 if (set
->MachineName
)
2452 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2456 DevInfoData
->RemoteMachineName
[0] = 0;
2461 /***********************************************************************
2462 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2464 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2465 HDEVINFO DeviceInfoSet
,
2466 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2468 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2470 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DevInfoData
);
2472 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2474 SetLastError(ERROR_INVALID_HANDLE
);
2477 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2479 SetLastError(ERROR_INVALID_HANDLE
);
2483 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2485 SetLastError(ERROR_INVALID_PARAMETER
);
2488 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2489 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2490 if (set
->MachineName
)
2491 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2493 DevInfoData
->RemoteMachineName
[0] = 0;
2498 /***********************************************************************
2499 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2501 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2502 HDEVINFO DeviceInfoSet
,
2503 PSP_DEVINFO_DATA DeviceInfoData
,
2504 const GUID
*InterfaceClassGuid
,
2505 PCSTR ReferenceString
,
2506 DWORD CreationFlags
,
2507 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2510 LPWSTR ReferenceStringW
= NULL
;
2512 TRACE("%s(%p %p %s %s %08x %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
2513 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2514 CreationFlags
, DeviceInterfaceData
);
2516 if (ReferenceString
)
2518 ReferenceStringW
= pSetupMultiByteToUnicode(ReferenceString
, CP_ACP
);
2519 if (ReferenceStringW
== NULL
) return FALSE
;
2522 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2523 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2524 DeviceInterfaceData
);
2526 MyFree(ReferenceStringW
);
2531 /***********************************************************************
2532 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2534 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2535 HDEVINFO DeviceInfoSet
,
2536 PSP_DEVINFO_DATA DeviceInfoData
,
2537 const GUID
*InterfaceClassGuid
,
2538 PCWSTR ReferenceString
,
2539 DWORD CreationFlags
,
2540 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2542 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2543 TRACE("%s(%p %p %s %s %08x %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
2544 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2545 CreationFlags
, DeviceInterfaceData
);
2547 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2549 SetLastError(ERROR_INVALID_HANDLE
);
2552 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2554 SetLastError(ERROR_INVALID_HANDLE
);
2557 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2558 || !DeviceInfoData
->Reserved
)
2560 SetLastError(ERROR_INVALID_PARAMETER
);
2563 if (!InterfaceClassGuid
)
2565 SetLastError(ERROR_INVALID_USER_BUFFER
);
2569 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2570 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2571 CreationFlags
, DeviceInterfaceData
);
2572 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2576 /***********************************************************************
2577 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2579 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2580 HDEVINFO DeviceInfoSet
,
2581 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2585 PCSTR InfSectionName
)
2588 PWSTR InfSectionNameW
= NULL
;
2590 TRACE("%s(%p %p %d %08x %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2591 samDesired
, InfHandle
, InfSectionName
);
2594 if (!InfSectionName
)
2596 SetLastError(ERROR_INVALID_PARAMETER
);
2597 return INVALID_HANDLE_VALUE
;
2599 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2600 if (!InfSectionNameW
)
2601 return INVALID_HANDLE_VALUE
;
2603 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2604 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2606 MyFree(InfSectionNameW
);
2610 /***********************************************************************
2611 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2613 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2614 HDEVINFO DeviceInfoSet
,
2615 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2619 PCWSTR InfSectionName
)
2622 LPWSTR SymbolicLink
;
2623 DWORD Length
, Index
;
2625 WCHAR bracedGuidString
[39];
2626 struct DeviceInterface
*DevItf
;
2627 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2629 TRACE("%s(%p %p %d %08x %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2630 samDesired
, InfHandle
, InfSectionName
);
2632 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2633 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2635 SetLastError(ERROR_INVALID_HANDLE
);
2636 return INVALID_HANDLE_VALUE
;
2638 if (!DeviceInterfaceData
||
2639 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2640 !DeviceInterfaceData
->Reserved
)
2642 SetLastError(ERROR_INVALID_PARAMETER
);
2643 return INVALID_HANDLE_VALUE
;
2645 if (InfHandle
&& !InfSectionName
)
2647 SetLastError(ERROR_INVALID_PARAMETER
);
2648 return INVALID_HANDLE_VALUE
;
2651 hKey
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2652 if (hKey
== INVALID_HANDLE_VALUE
)
2654 hKey
= SetupDiOpenClassRegKeyExW(NULL
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2655 if (hKey
== INVALID_HANDLE_VALUE
)
2657 SetLastError(ERROR_INVALID_PARAMETER
);
2658 return INVALID_HANDLE_VALUE
;
2660 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
, bracedGuidString
);
2662 if (RegCreateKeyExW(hKey
, bracedGuidString
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
) != ERROR_SUCCESS
)
2664 SetLastError(ERROR_INVALID_PARAMETER
);
2665 return INVALID_HANDLE_VALUE
;
2671 DevItf
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2673 Length
= (wcslen(DevItf
->SymbolicLink
)+1) * sizeof(WCHAR
);
2674 SymbolicLink
= HeapAlloc(GetProcessHeap(), 0, Length
);
2678 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2679 return INVALID_HANDLE_VALUE
;
2682 wcscpy(SymbolicLink
, DevItf
->SymbolicLink
);
2685 while(SymbolicLink
[Index
])
2687 if (SymbolicLink
[Index
] == L
'\\')
2689 SymbolicLink
[Index
] = L
'#';
2694 rc
= RegCreateKeyExW(hKey
, SymbolicLink
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
);
2697 HeapFree(GetProcessHeap(), 0, SymbolicLink
);
2699 if (rc
== ERROR_SUCCESS
)
2701 if (InfHandle
&& InfSectionName
)
2703 if (!SetupInstallFromInfSection(NULL
/*FIXME */,
2706 SPINST_INIFILES
| SPINST_REGISTRY
| SPINST_INI2REG
| SPINST_FILES
| SPINST_BITREG
| SPINST_REGSVR
| SPINST_UNREGSVR
| SPINST_PROFILEITEMS
| SPINST_COPYINF
,
2710 set
->SelectedDevice
->InstallParams
.InstallMsgHandler
,
2711 set
->SelectedDevice
->InstallParams
.InstallMsgHandlerContext
,
2712 INVALID_HANDLE_VALUE
,
2715 RegCloseKey(hDevKey
);
2716 return INVALID_HANDLE_VALUE
;
2725 /***********************************************************************
2726 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2728 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2729 HDEVINFO DeviceInfoSet
,
2730 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2733 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2736 TRACE("%s(%p %p %d)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2738 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2739 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2741 SetLastError(ERROR_INVALID_HANDLE
);
2744 if (!DeviceInterfaceData
||
2745 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2746 !DeviceInterfaceData
->Reserved
)
2748 SetLastError(ERROR_INVALID_PARAMETER
);
2752 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2753 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2757 /***********************************************************************
2758 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2761 * DeviceInfoSet [I] Set of devices from which to enumerate
2763 * DeviceInfoData [I] (Optional) If specified, a specific device
2764 * instance from which to enumerate interfaces.
2765 * If it isn't specified, all interfaces for all
2766 * devices in the set are enumerated.
2767 * InterfaceClassGuid [I] The interface class to enumerate.
2768 * MemberIndex [I] An index of the interface instance to enumerate.
2769 * A caller should start with MemberIndex set to 0,
2770 * and continue until the function fails with
2771 * ERROR_NO_MORE_ITEMS.
2772 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2773 * member must be set to
2774 * sizeof(SP_DEVICE_INTERFACE_DATA).
2777 * Success: non-zero value.
2778 * Failure: FALSE. Call GetLastError() for more info.
2780 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2781 HDEVINFO DeviceInfoSet
,
2782 PSP_DEVINFO_DATA DeviceInfoData
,
2783 CONST GUID
* InterfaceClassGuid
,
2785 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2787 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2790 TRACE("%s(%p, %p, %s, %d, %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
2791 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2793 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2794 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2796 SetLastError(ERROR_INVALID_HANDLE
);
2799 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2800 !DeviceInfoData
->Reserved
))
2802 SetLastError(ERROR_INVALID_PARAMETER
);
2805 if (!DeviceInterfaceData
||
2806 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2808 SetLastError(ERROR_INVALID_PARAMETER
);
2813 struct DeviceInfo
*devInfo
=
2814 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2816 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2817 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2819 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2820 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2822 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2825 if (MemberIndex
-- == 0)
2827 /* return this item */
2828 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2829 &DevItf
->InterfaceClassGuid
,
2831 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2832 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2836 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2839 SetLastError(ERROR_NO_MORE_ITEMS
);
2844 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
2845 while (ItemList
!= &set
->ListHead
&& !found
)
2847 PLIST_ENTRY InterfaceListEntry
;
2848 struct DeviceInfo
*devInfo
=
2849 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
2850 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2851 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2853 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2854 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2856 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2859 if (MemberIndex
-- == 0)
2861 /* return this item */
2862 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2863 &DevItf
->InterfaceClassGuid
,
2865 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2866 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2870 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2872 ItemList
= ItemList
->Flink
;
2876 SetLastError(ERROR_NO_MORE_ITEMS
);
2881 /***********************************************************************
2882 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2884 * Destroy a DeviceInfoList and free all used memory of the list.
2887 * devinfo [I] DeviceInfoList pointer to list to destroy
2890 * Success: non zero value.
2891 * Failure: zero value.
2893 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2897 TRACE("%s(%p)\n", __FUNCTION__
, devinfo
);
2898 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
2900 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2902 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
2904 ret
= DestroyDeviceInfoSet(list
);
2909 SetLastError(ERROR_INVALID_HANDLE
);
2914 /***********************************************************************
2915 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2917 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2918 HDEVINFO DeviceInfoSet
,
2919 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2920 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2921 DWORD DeviceInterfaceDetailDataSize
,
2922 PDWORD RequiredSize
,
2923 PSP_DEVINFO_DATA DeviceInfoData
)
2925 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2926 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2927 DWORD sizeW
= 0, bytesNeeded
;
2930 TRACE("%s(%p, %p, %p, %d, %p, %p)\n", __FUNCTION__
, DeviceInfoSet
,
2931 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2932 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2934 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2935 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2937 SetLastError(ERROR_INVALID_HANDLE
);
2940 if (!DeviceInterfaceData
||
2941 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2942 !DeviceInterfaceData
->Reserved
)
2944 SetLastError(ERROR_INVALID_PARAMETER
);
2947 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
2949 SetLastError(ERROR_INVALID_USER_BUFFER
);
2953 if((DeviceInterfaceDetailDataSize
!= 0) &&
2954 (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + sizeof(CHAR
))))
2956 SetLastError(ERROR_INVALID_USER_BUFFER
);
2960 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2962 SetLastError(ERROR_INVALID_USER_BUFFER
);
2967 if (DeviceInterfaceDetailData
!= NULL
)
2969 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2970 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2971 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
2972 if (!DeviceInterfaceDetailDataW
)
2974 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2976 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2978 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2980 ret
= SetupDiGetDeviceInterfaceDetailW(
2982 DeviceInterfaceData
,
2983 DeviceInterfaceDetailDataW
,
2987 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2988 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2990 *RequiredSize
= bytesNeeded
;
2991 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
>= bytesNeeded
)
2993 if (!WideCharToMultiByte(
2995 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2996 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
3003 MyFree(DeviceInterfaceDetailDataW
);
3008 /***********************************************************************
3009 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3011 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
3012 HDEVINFO DeviceInfoSet
,
3013 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3014 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
3015 DWORD DeviceInterfaceDetailDataSize
,
3016 PDWORD RequiredSize
,
3017 PSP_DEVINFO_DATA DeviceInfoData
)
3019 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3022 TRACE("%s(%p, %p, %p, %d, %p, %p)\n", __FUNCTION__
, DeviceInfoSet
,
3023 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3024 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3026 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3027 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3029 SetLastError(ERROR_INVALID_HANDLE
);
3032 if (!DeviceInterfaceData
||
3033 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3034 !DeviceInterfaceData
->Reserved
)
3036 SetLastError(ERROR_INVALID_PARAMETER
);
3039 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
3041 SetLastError(ERROR_INVALID_USER_BUFFER
);
3044 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3046 SetLastError(ERROR_INVALID_USER_BUFFER
);
3049 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3051 SetLastError(ERROR_INVALID_PARAMETER
);
3054 if ((DeviceInterfaceDetailData
!= NULL
)
3055 && (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) + sizeof(WCHAR
)))
3057 SetLastError(ERROR_INVALID_PARAMETER
);
3062 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
3063 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
3064 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
3065 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
3067 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
3069 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3071 *RequiredSize
= sizeRequired
;
3075 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3076 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3079 memcpy(&DeviceInfoData
->ClassGuid
,
3080 &deviceInterface
->DeviceInfo
->ClassGuid
,
3082 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3083 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3091 struct PropertyMapEntry
3098 static struct PropertyMapEntry PropertyMap
[] = {
3099 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3100 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3101 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3102 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3103 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3104 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3105 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3106 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3107 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3108 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3109 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3110 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3111 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3112 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3113 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3114 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3115 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3116 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3117 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3118 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3119 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3120 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3121 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3122 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3123 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3124 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3125 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3126 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3127 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3128 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3129 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3130 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3131 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3132 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3133 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3136 /***********************************************************************
3137 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3139 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3140 HDEVINFO DeviceInfoSet
,
3141 PSP_DEVINFO_DATA DeviceInfoData
,
3143 PDWORD PropertyRegDataType
,
3144 PBYTE PropertyBuffer
,
3145 DWORD PropertyBufferSize
,
3146 PDWORD RequiredSize
)
3149 BOOL bIsStringProperty
;
3151 DWORD RequiredSizeA
, RequiredSizeW
;
3152 DWORD PropertyBufferSizeW
= 0;
3153 PBYTE PropertyBufferW
= NULL
;
3155 TRACE("%s(%p %p %d %p %p %d %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
3156 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3159 if (PropertyBufferSize
!= 0)
3161 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3162 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3163 if (!PropertyBufferW
)
3165 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3170 ret
= SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
3175 PropertyBufferSizeW
,
3178 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3180 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
3182 if (bIsStringProperty
)
3183 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
3185 RequiredSizeA
= RequiredSizeW
;
3187 *RequiredSize
= RequiredSizeA
;
3188 if (PropertyRegDataType
)
3189 *PropertyRegDataType
= RegType
;
3194 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3198 if (RequiredSizeA
<= PropertyBufferSize
)
3200 if (bIsStringProperty
&& PropertyBufferSize
> 0)
3202 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
3204 /* Last error is already set by WideCharToMultiByte */
3209 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
3213 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3217 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3221 /***********************************************************************
3222 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3224 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3225 HDEVINFO DeviceInfoSet
,
3226 PSP_DEVINFO_DATA DeviceInfoData
,
3228 PDWORD PropertyRegDataType
,
3229 PBYTE PropertyBuffer
,
3230 DWORD PropertyBufferSize
,
3231 PDWORD RequiredSize
)
3233 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3234 struct DeviceInfo
*devInfo
;
3236 LONG lError
= ERROR_SUCCESS
;
3239 TRACE("%s(%p %p %d %p %p %d %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
3240 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3243 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3245 SetLastError(ERROR_INVALID_HANDLE
);
3248 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3250 SetLastError(ERROR_INVALID_HANDLE
);
3253 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3254 || !DeviceInfoData
->Reserved
)
3256 SetLastError(ERROR_INVALID_PARAMETER
);
3260 if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
3262 SetLastError(ERROR_INVALID_REG_PROPERTY
);
3266 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3268 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3269 && PropertyMap
[Property
].nameW
)
3272 size
= PropertyBufferSize
;
3273 hKey
= SETUPDI_OpenDevKey(set
->HKLM
, devInfo
, KEY_QUERY_VALUE
);
3274 if (hKey
== INVALID_HANDLE_VALUE
)
3276 lError
= RegQueryValueExW(hKey
, PropertyMap
[Property
].nameW
,
3277 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3281 *RequiredSize
= size
;
3286 if (PropertyBuffer
== NULL
&& size
!= 0)
3287 lError
= ERROR_INSUFFICIENT_BUFFER
;
3289 case ERROR_MORE_DATA
:
3290 lError
= ERROR_INSUFFICIENT_BUFFER
;
3296 else if (Property
== SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
)
3298 size
= (strlenW(devInfo
->Data
) + 1) * sizeof(WCHAR
);
3300 if (PropertyRegDataType
)
3301 *PropertyRegDataType
= REG_SZ
;
3303 *RequiredSize
= size
;
3304 if (PropertyBufferSize
>= size
)
3306 strcpyW((LPWSTR
)PropertyBuffer
, devInfo
->Data
);
3309 lError
= ERROR_INSUFFICIENT_BUFFER
;
3313 size
= PropertyBufferSize
;
3315 cr
= CM_Get_DevNode_Registry_Property_ExW(devInfo
->dnDevInst
,
3316 Property
+ (CM_DRP_DEVICEDESC
- SPDRP_DEVICEDESC
),
3317 PropertyRegDataType
,
3322 if ((cr
== CR_SUCCESS
) || (cr
== CR_BUFFER_SMALL
))
3325 *RequiredSize
= size
;
3328 if (cr
!= CR_SUCCESS
)
3332 case CR_INVALID_DEVINST
:
3333 lError
= ERROR_NO_SUCH_DEVINST
;
3336 case CR_INVALID_PROPERTY
:
3337 lError
= ERROR_INVALID_REG_PROPERTY
;
3340 case CR_BUFFER_SMALL
:
3341 lError
= ERROR_INSUFFICIENT_BUFFER
;
3345 lError
= ERROR_INVALID_DATA
;
3351 SetLastError(lError
);
3352 return (lError
== ERROR_SUCCESS
);
3355 /***********************************************************************
3356 * Internal for SetupDiSetDeviceRegistryPropertyA/W
3358 BOOL WINAPI
IntSetupDiSetDeviceRegistryPropertyAW(
3359 HDEVINFO DeviceInfoSet
,
3360 PSP_DEVINFO_DATA DeviceInfoData
,
3362 const BYTE
*PropertyBuffer
,
3363 DWORD PropertyBufferSize
,
3367 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3368 struct DeviceInfo
*deviceInfo
;
3370 TRACE("%s(%p %p %d %p %d)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Property
,
3371 PropertyBuffer
, PropertyBufferSize
);
3373 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3375 SetLastError(ERROR_INVALID_HANDLE
);
3378 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3380 SetLastError(ERROR_INVALID_HANDLE
);
3383 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3384 || !DeviceInfoData
->Reserved
)
3386 SetLastError(ERROR_INVALID_PARAMETER
);
3390 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3392 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3393 && PropertyMap
[Property
].nameW
3394 && PropertyMap
[Property
].nameA
)
3398 hKey
= SETUPDI_OpenDevKey(set
->HKLM
, deviceInfo
, KEY_SET_VALUE
);
3399 if (hKey
== INVALID_HANDLE_VALUE
)
3401 /* Write new data */
3405 hKey
, PropertyMap
[Property
].nameA
, 0,
3406 PropertyMap
[Property
].regType
, PropertyBuffer
,
3407 PropertyBufferSize
);
3412 hKey
, PropertyMap
[Property
].nameW
, 0,
3413 PropertyMap
[Property
].regType
, PropertyBuffer
,
3414 PropertyBufferSize
);
3424 ERR("Property 0x%lx not implemented\n", Property
);
3425 SetLastError(ERROR_NOT_SUPPORTED
);
3428 TRACE("Returning %d\n", ret
);
3431 /***********************************************************************
3432 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3434 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3435 HDEVINFO DeviceInfoSet
,
3436 PSP_DEVINFO_DATA DeviceInfoData
,
3438 const BYTE
*PropertyBuffer
,
3439 DWORD PropertyBufferSize
)
3441 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet
,
3449 /***********************************************************************
3450 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3452 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3453 HDEVINFO DeviceInfoSet
,
3454 PSP_DEVINFO_DATA DeviceInfoData
,
3456 const BYTE
*PropertyBuffer
,
3457 DWORD PropertyBufferSize
)
3459 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet
,
3467 /***********************************************************************
3468 * SetupDiInstallClassA (SETUPAPI.@)
3470 BOOL WINAPI
SetupDiInstallClassA(
3476 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3479 /***********************************************************************
3480 * SetupDiInstallClassExA (SETUPAPI.@)
3483 SetupDiInstallClassExA(
3484 IN HWND hwndParent OPTIONAL
,
3485 IN PCSTR InfFileName OPTIONAL
,
3487 IN HSPFILEQ FileQueue OPTIONAL
,
3488 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3492 PWSTR InfFileNameW
= NULL
;
3497 SetLastError(ERROR_INVALID_PARAMETER
);
3502 InfFileNameW
= pSetupMultiByteToUnicode(InfFileName
, CP_ACP
);
3503 if (InfFileNameW
== NULL
)
3505 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3510 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3511 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3513 MyFree(InfFileNameW
);
3518 HKEY
SETUP_CreateClassKey(HINF hInf
)
3520 WCHAR FullBuffer
[MAX_PATH
];
3521 WCHAR Buffer
[MAX_PATH
];
3526 /* Obtain the Class GUID for this class */
3527 if (!SetupGetLineTextW(NULL
,
3530 REGSTR_VAL_CLASSGUID
,
3532 sizeof(Buffer
) / sizeof(WCHAR
),
3535 return INVALID_HANDLE_VALUE
;
3538 /* Build the corresponding registry key name */
3539 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3540 lstrcatW(FullBuffer
, BackSlash
);
3541 lstrcatW(FullBuffer
, Buffer
);
3543 /* Obtain the Class name for this class */
3544 if (!SetupGetLineTextW(NULL
,
3549 sizeof(Buffer
) / sizeof(WCHAR
),
3552 return INVALID_HANDLE_VALUE
;
3555 /* Try to open or create the registry key */
3556 TRACE("Opening class key %s\n", debugstr_w(FullBuffer
));
3557 #if 0 // I keep this for reference...
3558 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3564 /* Use RegCreateKeyExW */
3567 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3571 REG_OPTION_NON_VOLATILE
,
3577 ERR("RegCreateKeyExW(%s) failed\n", debugstr_w(FullBuffer
));
3578 return INVALID_HANDLE_VALUE
;
3580 if (Disposition
== REG_CREATED_NEW_KEY
)
3581 TRACE("The class key %s was successfully created\n", debugstr_w(FullBuffer
));
3583 TRACE("The class key %s was successfully opened\n", debugstr_w(FullBuffer
));
3585 TRACE( "setting value %s to %s\n", debugstr_w(REGSTR_VAL_CLASS
), debugstr_w(Buffer
) );
3586 if (RegSetValueExW(hClassKey
,
3591 RequiredSize
* sizeof(WCHAR
)))
3593 RegCloseKey(hClassKey
);
3594 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3596 return INVALID_HANDLE_VALUE
;
3602 /***********************************************************************
3603 * SetupDiInstallClassW (SETUPAPI.@)
3605 BOOL WINAPI
SetupDiInstallClassW(
3611 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3615 /***********************************************************************
3616 * SetupDiOpenClassRegKey (SETUPAPI.@)
3618 HKEY WINAPI
SetupDiOpenClassRegKey(
3619 const GUID
* ClassGuid
,
3622 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3623 DIOCR_INSTALLER
, NULL
, NULL
);
3627 /***********************************************************************
3628 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3630 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3631 const GUID
* ClassGuid
,
3637 PWSTR MachineNameW
= NULL
;
3640 TRACE("%s(%s 0x%lx 0x%lx %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), samDesired
,
3641 Flags
, debugstr_a(MachineName
), Reserved
);
3645 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
3646 if (MachineNameW
== NULL
)
3647 return INVALID_HANDLE_VALUE
;
3650 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3651 Flags
, MachineNameW
, Reserved
);
3653 MyFree(MachineNameW
);
3659 /***********************************************************************
3660 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3662 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3663 const GUID
* ClassGuid
,
3675 TRACE("%s(%s 0x%lx 0x%lx %s %p)\n", __FUNCTION__
, debugstr_guid(ClassGuid
), samDesired
,
3676 Flags
, debugstr_w(MachineName
), Reserved
);
3678 if (MachineName
!= NULL
)
3680 l
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3681 if (l
!= ERROR_SUCCESS
)
3684 return INVALID_HANDLE_VALUE
;
3688 HKLM
= HKEY_LOCAL_MACHINE
;
3690 if (Flags
== DIOCR_INSTALLER
)
3692 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3694 else if (Flags
== DIOCR_INTERFACE
)
3696 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3700 ERR("Invalid Flags parameter!\n");
3701 SetLastError(ERROR_INVALID_FLAGS
);
3702 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3703 return INVALID_HANDLE_VALUE
;
3708 if ((l
= RegOpenKeyExW(HKLM
,
3714 SetLastError(ERROR_INVALID_CLASS
);
3715 hClassesKey
= INVALID_HANDLE_VALUE
;
3717 if (MachineName
!= NULL
)
3723 WCHAR bracedGuidString
[39];
3725 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3727 if (!(l
= RegOpenKeyExW(HKLM
,
3733 if (MachineName
!= NULL
)
3736 if ((l
= RegOpenKeyExW(hClassesKey
,
3743 key
= INVALID_HANDLE_VALUE
;
3745 RegCloseKey(hClassesKey
);
3749 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3751 key
= INVALID_HANDLE_VALUE
;
3758 /***********************************************************************
3759 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3761 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3762 HDEVINFO DeviceInfoSet
,
3765 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3767 struct DeviceInfoSet
* list
;
3769 DWORD dwLength
, dwError
, dwIndex
, dwKeyName
, dwSubIndex
;
3771 WCHAR Buffer
[MAX_PATH
+ 1];
3772 WCHAR SymBuffer
[MAX_PATH
+ 1];
3773 WCHAR InstancePath
[MAX_PATH
+ 1];
3774 HKEY hKey
, hDevKey
, hSymKey
;
3775 struct DeviceInfo
* deviceInfo
;
3776 struct DeviceInterface
*deviceInterface
;
3778 PLIST_ENTRY ItemList
;
3779 PLIST_ENTRY InterfaceListEntry
;
3781 TRACE("%s(%p %s %08x %p)\n", __FUNCTION__
,
3782 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3785 if (DeviceInterfaceData
&& DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
3787 SetLastError(ERROR_INVALID_PARAMETER
);
3791 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3793 SetLastError(ERROR_INVALID_HANDLE
);
3797 list
= (struct DeviceInfoSet
* )DeviceInfoSet
;
3799 dwLength
= wcslen(DevicePath
);
3802 /* path must be at least a guid length + L'\0' */
3803 SetLastError(ERROR_BAD_PATHNAME
);
3807 if (DevicePath
[0] != L
'\\' ||
3808 DevicePath
[1] != L
'\\' ||
3809 (DevicePath
[2] != L
'?' && DevicePath
[2] != L
'.') ||
3810 DevicePath
[3] != L
'\\')
3812 /* invalid formatted path */
3813 SetLastError(ERROR_BAD_PATHNAME
);
3817 /* check for reference strings */
3818 pEnd
= wcschr(&DevicePath
[4], L
'\\');
3821 /* no reference string */
3822 pEnd
= DevicePath
+ dwLength
;
3826 wcscpy(Buffer
, pEnd
- 37);
3829 dwError
= UuidFromStringW(Buffer
, &ClassId
);
3830 if (dwError
!= NOERROR
)
3832 /* invalid formatted path */
3833 SetLastError(ERROR_BAD_PATHNAME
);
3837 hKey
= SetupDiOpenClassRegKeyExW(&ClassId
, KEY_READ
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
3839 if (hKey
== INVALID_HANDLE_VALUE
)
3841 /* invalid device class */
3845 ItemList
= list
->ListHead
.Flink
;
3846 while (ItemList
!= &list
->ListHead
)
3848 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
3849 InterfaceListEntry
= deviceInfo
->InterfaceListHead
.Flink
;
3850 while (InterfaceListEntry
!= &deviceInfo
->InterfaceListHead
)
3852 deviceInterface
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
3853 if (!IsEqualIID(&deviceInterface
->InterfaceClassGuid
, &ClassId
))
3855 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3859 if (!wcsicmp(deviceInterface
->SymbolicLink
, DevicePath
))
3861 if (DeviceInterfaceData
)
3863 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3864 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3865 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3879 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3880 dwError
= RegEnumKeyExW(hKey
, dwIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3882 if (dwError
!= ERROR_SUCCESS
)
3885 if (RegOpenKeyExW(hKey
, Buffer
, 0, KEY_READ
, &hDevKey
) != ERROR_SUCCESS
)
3889 InstancePath
[0] = 0;
3890 dwKeyName
= sizeof(InstancePath
);
3892 dwError
= RegQueryValueExW(hDevKey
, L
"DeviceInstance", NULL
, NULL
, (LPBYTE
)InstancePath
, &dwKeyName
);
3897 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3898 dwError
= RegEnumKeyExW(hDevKey
, dwSubIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3900 if (dwError
!= ERROR_SUCCESS
)
3903 dwError
= RegOpenKeyExW(hDevKey
, Buffer
, 0, KEY_READ
, &hSymKey
);
3904 if (dwError
!= ERROR_SUCCESS
)
3907 /* query for symbolic link */
3908 dwKeyName
= sizeof(SymBuffer
);
3909 SymBuffer
[0] = L
'\0';
3910 dwError
= RegQueryValueExW(hSymKey
, L
"SymbolicLink", NULL
, NULL
, (LPBYTE
)SymBuffer
, &dwKeyName
);
3912 if (dwError
!= ERROR_SUCCESS
)
3914 RegCloseKey(hSymKey
);
3918 if (!wcsicmp(SymBuffer
, DevicePath
))
3920 Ret
= CreateDeviceInfo(list
, InstancePath
, &ClassId
, &deviceInfo
);
3921 RegCloseKey(hSymKey
);
3922 RegCloseKey(hDevKey
);
3927 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymBuffer
) + 1) * sizeof(WCHAR
));
3928 if (deviceInterface
)
3931 CopyMemory(&deviceInterface
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3932 deviceInterface
->DeviceInfo
= deviceInfo
;
3933 deviceInterface
->Flags
= SPINT_ACTIVE
; //FIXME
3935 wcscpy(deviceInterface
->SymbolicLink
, SymBuffer
);
3937 InsertTailList(&deviceInfo
->InterfaceListHead
, &deviceInterface
->ListEntry
);
3938 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3941 if (DeviceInterfaceData
)
3943 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3944 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3945 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3950 SetLastError(ERROR_INVALID_USER_BUFFER
);
3956 HeapFree(GetProcessHeap(), 0, deviceInfo
);
3961 RegCloseKey(hSymKey
);
3965 RegCloseKey(hDevKey
);
3973 /***********************************************************************
3974 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3976 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3977 HDEVINFO DeviceInfoSet
,
3980 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3982 LPWSTR DevicePathW
= NULL
;
3985 TRACE("%s(%p %s %08lx %p)\n", __FUNCTION__
, DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3987 DevicePathW
= pSetupMultiByteToUnicode(DevicePath
, CP_ACP
);
3988 if (DevicePathW
== NULL
)
3991 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3992 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3994 MyFree(DevicePathW
);
3999 /***********************************************************************
4000 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
4002 BOOL WINAPI
SetupDiSetClassInstallParamsA(
4003 HDEVINFO DeviceInfoSet
,
4004 PSP_DEVINFO_DATA DeviceInfoData
,
4005 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
4006 DWORD ClassInstallParamsSize
)
4008 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
4009 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
4014 IntSetupDiRegisterDeviceInfo(
4015 IN HDEVINFO DeviceInfoSet
,
4016 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
4018 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
4021 /***********************************************************************
4022 * SetupDiCallClassInstaller (SETUPAPI.@)
4024 BOOL WINAPI
SetupDiCallClassInstaller(
4025 DI_FUNCTION InstallFunction
,
4026 HDEVINFO DeviceInfoSet
,
4027 PSP_DEVINFO_DATA DeviceInfoData
)
4031 TRACE("%s(%u %p %p)\n", __FUNCTION__
, InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4034 SetLastError(ERROR_INVALID_PARAMETER
);
4035 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4036 SetLastError(ERROR_INVALID_HANDLE
);
4037 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4038 SetLastError(ERROR_INVALID_HANDLE
);
4039 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
4040 SetLastError(ERROR_INVALID_HANDLE
);
4041 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4042 SetLastError(ERROR_INVALID_USER_BUFFER
);
4045 SP_DEVINSTALL_PARAMS_W InstallParams
;
4046 #define CLASS_COINSTALLER 0x1
4047 #define DEVICE_COINSTALLER 0x2
4048 #define CLASS_INSTALLER 0x4
4049 UCHAR CanHandle
= 0;
4050 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
4052 switch (InstallFunction
)
4054 case DIF_ADDPROPERTYPAGE_ADVANCED
:
4055 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4057 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
4058 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4060 case DIF_ALLOW_INSTALL
:
4061 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4064 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4066 case DIF_DESTROYPRIVATEDATA
:
4067 CanHandle
= CLASS_INSTALLER
;
4069 case DIF_INSTALLDEVICE
:
4070 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4071 DefaultHandler
= SetupDiInstallDevice
;
4073 case DIF_INSTALLDEVICEFILES
:
4074 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4075 DefaultHandler
= SetupDiInstallDriverFiles
;
4077 case DIF_INSTALLINTERFACES
:
4078 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4079 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
4081 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
4082 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4084 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
4085 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4087 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
4088 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4090 case DIF_NEWDEVICEWIZARD_PRESELECT
:
4091 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4093 case DIF_NEWDEVICEWIZARD_SELECT
:
4094 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4096 case DIF_POWERMESSAGEWAKE
:
4097 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4099 case DIF_PROPERTYCHANGE
:
4100 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4101 DefaultHandler
= SetupDiChangeState
;
4103 case DIF_REGISTER_COINSTALLERS
:
4104 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4105 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
4107 case DIF_REGISTERDEVICE
:
4108 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4109 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
4112 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4113 DefaultHandler
= SetupDiRemoveDevice
;
4115 case DIF_SELECTBESTCOMPATDRV
:
4116 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4117 DefaultHandler
= SetupDiSelectBestCompatDrv
;
4119 case DIF_SELECTDEVICE
:
4120 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4121 DefaultHandler
= SetupDiSelectDevice
;
4123 case DIF_TROUBLESHOOTER
:
4124 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4127 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4128 DefaultHandler
= SetupDiUnremoveDevice
;
4131 ERR("Install function %u not supported\n", InstallFunction
);
4132 SetLastError(ERROR_NOT_SUPPORTED
);
4135 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4136 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4137 /* Don't process this call, as a parameter is invalid */
4142 LIST_ENTRY ClassCoInstallersListHead
;
4143 LIST_ENTRY DeviceCoInstallersListHead
;
4144 HMODULE ClassInstallerLibrary
= NULL
;
4145 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
4146 COINSTALLER_CONTEXT_DATA Context
;
4147 PLIST_ENTRY ListEntry
;
4149 DWORD dwRegType
, dwLength
;
4150 DWORD rc
= NO_ERROR
;
4152 InitializeListHead(&ClassCoInstallersListHead
);
4153 InitializeListHead(&DeviceCoInstallersListHead
);
4155 if (CanHandle
& DEVICE_COINSTALLER
)
4157 hKey
= SETUPDI_OpenDrvKey(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
, (struct DeviceInfo
*)DeviceInfoData
->Reserved
, KEY_QUERY_VALUE
);
4158 if (hKey
!= INVALID_HANDLE_VALUE
)
4160 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4161 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4163 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4164 if (KeyBuffer
!= NULL
)
4166 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4167 if (rc
== ERROR_SUCCESS
)
4170 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4172 /* Add coinstaller to DeviceCoInstallersListHead list */
4173 struct CoInstallerElement
*coinstaller
;
4174 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
4175 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4178 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4179 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4180 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
4182 HeapFree(GetProcessHeap(), 0, coinstaller
);
4185 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4191 if (CanHandle
& CLASS_COINSTALLER
)
4195 REGSTR_PATH_CODEVICEINSTALLERS
,
4199 if (rc
== ERROR_SUCCESS
)
4201 WCHAR szGuidString
[40];
4202 if (pSetupStringFromGuid(&DeviceInfoData
->ClassGuid
, szGuidString
, ARRAYSIZE(szGuidString
)) == ERROR_SUCCESS
)
4204 rc
= RegQueryValueExW(hKey
, szGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
4205 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4207 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4208 if (KeyBuffer
!= NULL
)
4210 rc
= RegQueryValueExW(hKey
, szGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4211 if (rc
== ERROR_SUCCESS
)
4214 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4216 /* Add coinstaller to ClassCoInstallersListHead list */
4217 struct CoInstallerElement
*coinstaller
;
4218 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
4219 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4222 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4223 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4224 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
4226 HeapFree(GetProcessHeap(), 0, coinstaller
);
4229 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4236 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4238 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4239 if (hKey
!= INVALID_HANDLE_VALUE
)
4241 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4242 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4244 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4245 if (KeyBuffer
!= NULL
)
4247 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4248 if (rc
== ERROR_SUCCESS
)
4250 /* Get ClassInstaller function pointer */
4251 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4252 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4254 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4255 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4258 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4265 /* Call Class co-installers */
4266 Context
.PostProcessing
= FALSE
;
4268 ListEntry
= ClassCoInstallersListHead
.Flink
;
4269 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4271 struct CoInstallerElement
*coinstaller
;
4272 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4273 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4274 coinstaller
->PrivateData
= Context
.PrivateData
;
4275 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4277 coinstaller
->DoPostProcessing
= TRUE
;
4280 ListEntry
= ListEntry
->Flink
;
4283 /* Call Device co-installers */
4284 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4285 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4287 struct CoInstallerElement
*coinstaller
;
4288 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4289 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4290 coinstaller
->PrivateData
= Context
.PrivateData
;
4291 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4293 coinstaller
->DoPostProcessing
= TRUE
;
4296 ListEntry
= ListEntry
->Flink
;
4299 /* Call Class installer */
4302 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4303 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4306 rc
= ERROR_DI_DO_DEFAULT
;
4308 /* Call default handler */
4309 if (rc
== ERROR_DI_DO_DEFAULT
)
4311 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4313 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4316 rc
= GetLastError();
4322 /* Call Class co-installers that required postprocessing */
4323 Context
.PostProcessing
= TRUE
;
4324 ListEntry
= ClassCoInstallersListHead
.Flink
;
4325 while (ListEntry
!= &ClassCoInstallersListHead
)
4327 struct CoInstallerElement
*coinstaller
;
4328 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4329 if (coinstaller
->DoPostProcessing
)
4331 Context
.InstallResult
= rc
;
4332 Context
.PrivateData
= coinstaller
->PrivateData
;
4333 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4335 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4336 ListEntry
= ListEntry
->Flink
;
4339 /* Call Device co-installers that required postprocessing */
4340 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4341 while (ListEntry
!= &DeviceCoInstallersListHead
)
4343 struct CoInstallerElement
*coinstaller
;
4344 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4345 if (coinstaller
->DoPostProcessing
)
4347 Context
.InstallResult
= rc
;
4348 Context
.PrivateData
= coinstaller
->PrivateData
;
4349 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4351 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4352 ListEntry
= ListEntry
->Flink
;
4355 /* Free allocated memory */
4356 while (!IsListEmpty(&ClassCoInstallersListHead
))
4358 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4359 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4361 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4363 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4364 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4367 ret
= (rc
== NO_ERROR
);
4371 TRACE("Returning %d\n", ret
);
4375 /***********************************************************************
4376 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4378 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4379 HDEVINFO DeviceInfoSet
,
4380 PSP_DEVINFO_DATA DeviceInfoData
,
4381 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4383 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4386 TRACE("%s(%p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4388 if (DeviceInstallParams
== NULL
)
4389 SetLastError(ERROR_INVALID_PARAMETER
);
4390 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4391 SetLastError(ERROR_INVALID_USER_BUFFER
);
4394 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4395 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4399 /* Do W->A conversion */
4401 DeviceInstallParams
,
4402 &deviceInstallParamsW
,
4403 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4404 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4405 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4407 DeviceInstallParams
->DriverPath
[0] = '\0';
4413 TRACE("Returning %d\n", ret
);
4417 /***********************************************************************
4418 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4421 SetupDiGetDeviceInfoListClass(
4422 IN HDEVINFO DeviceInfoSet
,
4423 OUT LPGUID ClassGuid
)
4425 struct DeviceInfoSet
*list
;
4428 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, ClassGuid
);
4431 SetLastError(ERROR_INVALID_HANDLE
);
4432 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4433 SetLastError(ERROR_INVALID_HANDLE
);
4434 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4435 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4438 *ClassGuid
= list
->ClassGuid
;
4443 TRACE("Returning %d\n", ret
);
4447 /***********************************************************************
4448 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4451 SetupDiGetDeviceInstallParamsW(
4452 IN HDEVINFO DeviceInfoSet
,
4453 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4454 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4456 struct DeviceInfoSet
*list
;
4459 TRACE("%s(%p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4462 SetLastError(ERROR_INVALID_HANDLE
);
4463 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4464 SetLastError(ERROR_INVALID_HANDLE
);
4465 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4466 SetLastError(ERROR_INVALID_USER_BUFFER
);
4467 else if (!DeviceInstallParams
)
4468 SetLastError(ERROR_INVALID_PARAMETER
);
4469 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4470 SetLastError(ERROR_INVALID_USER_BUFFER
);
4473 PSP_DEVINSTALL_PARAMS_W Source
;
4476 Source
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4478 Source
= &list
->InstallParams
;
4484 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4486 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4488 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4494 TRACE("Returning %d\n", ret
);
4499 CheckDeviceInstallParameters(
4500 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4502 DWORD SupportedFlags
=
4503 DI_NOVCP
| /* 0x00000008 */
4504 DI_DIDCOMPAT
| /* 0x00000010 */
4505 DI_DIDCLASS
| /* 0x00000020 */
4506 DI_NEEDRESTART
| /* 0x00000080 */
4507 DI_NEEDREBOOT
| /* 0x00000100 */
4508 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4509 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4510 DI_ENUMSINGLEINF
| /* 0x00010000 */
4511 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
4512 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4513 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4514 DI_QUIETINSTALL
| /* 0x00800000 */
4515 DI_NOFILECOPY
| /* 0x01000000 */
4516 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4517 DWORD SupportedFlagsEx
=
4518 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4519 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4520 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4521 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4522 DI_FLAGSEX_NO_DRVREG_MODIFY
| /* 0x00008000 */
4523 DI_FLAGSEX_INSTALLEDDRIVER
; /* 0x04000000 */
4526 /* FIXME: add support for more flags */
4528 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4529 * It should be checked before accessing to other values
4530 * of the SP_DEVINSTALL_PARAMS structure */
4532 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4534 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4535 SetLastError(ERROR_INVALID_FLAGS
);
4537 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4539 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4540 SetLastError(ERROR_INVALID_FLAGS
);
4542 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4543 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4544 SetLastError(ERROR_INVALID_USER_BUFFER
);
4547 /* FIXME: check Reserved field */
4554 /***********************************************************************
4555 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4558 SetupDiSetDeviceInstallParamsW(
4559 IN HDEVINFO DeviceInfoSet
,
4560 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4561 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4563 struct DeviceInfoSet
*list
;
4566 TRACE("%s(%p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4569 SetLastError(ERROR_INVALID_HANDLE
);
4570 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4571 SetLastError(ERROR_INVALID_HANDLE
);
4572 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4573 SetLastError(ERROR_INVALID_USER_BUFFER
);
4574 else if (!DeviceInstallParams
)
4575 SetLastError(ERROR_INVALID_PARAMETER
);
4576 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4577 SetLastError(ERROR_INVALID_USER_BUFFER
);
4578 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4580 PSP_DEVINSTALL_PARAMS_W Destination
;
4583 Destination
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4585 Destination
= &list
->InstallParams
;
4586 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4590 TRACE("Returning %d\n", ret
);
4594 /***********************************************************************
4595 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4598 SetupDiSetDeviceInstallParamsA(
4599 HDEVINFO DeviceInfoSet
,
4600 PSP_DEVINFO_DATA DeviceInfoData
,
4601 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4603 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4607 TRACE("%s(%p %p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4609 if (DeviceInstallParams
== NULL
)
4610 SetLastError(ERROR_INVALID_PARAMETER
);
4611 else if (DeviceInstallParams
->cbSize
< sizeof(SP_DEVINSTALL_PARAMS_A
))
4612 SetLastError(ERROR_INVALID_USER_BUFFER
);
4615 memcpy(&deviceInstallParamsW
, DeviceInstallParams
, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A
, DriverPath
));
4616 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4617 len
= MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, NULL
, 0);
4620 ERR("DrivePath is NULL\n");
4625 MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, deviceInstallParamsW
.DriverPath
, len
);
4626 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4630 TRACE("Returning %d\n", ret
);
4635 OpenHardwareProfileKey(
4638 IN DWORD samDesired
)
4640 HKEY hHWProfilesKey
= NULL
;
4641 HKEY hHWProfileKey
= NULL
;
4642 HKEY ret
= INVALID_HANDLE_VALUE
;
4645 rc
= RegOpenKeyExW(HKLM
,
4646 REGSTR_PATH_HWPROFILES
,
4650 if (rc
!= ERROR_SUCCESS
)
4657 rc
= RegOpenKeyExW(hHWProfilesKey
,
4666 snprintfW(subKey
, 4, InstanceKeyFormat
, HwProfile
);
4668 rc
= RegOpenKeyExW(hHWProfilesKey
,
4674 if (rc
!= ERROR_SUCCESS
)
4679 ret
= hHWProfileKey
;
4682 if (hHWProfilesKey
!= NULL
)
4683 RegCloseKey(hHWProfilesKey
);
4684 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4685 RegCloseKey(hHWProfileKey
);
4690 IsDeviceInfoInDeviceInfoSet(
4691 struct DeviceInfoSet
*deviceInfoSet
,
4692 struct DeviceInfo
*deviceInfo
)
4694 PLIST_ENTRY ListEntry
;
4696 ListEntry
= deviceInfoSet
->ListHead
.Flink
;
4697 while (ListEntry
!= &deviceInfoSet
->ListHead
)
4699 if (deviceInfo
== CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
))
4702 ListEntry
= ListEntry
->Flink
;
4708 /***********************************************************************
4709 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4712 SetupDiDeleteDeviceInfo(
4713 IN HDEVINFO DeviceInfoSet
,
4714 IN PSP_DEVINFO_DATA DeviceInfoData
)
4716 struct DeviceInfoSet
*deviceInfoSet
;
4717 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
;
4720 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
4723 SetLastError(ERROR_INVALID_HANDLE
);
4724 else if ((deviceInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4725 SetLastError(ERROR_INVALID_HANDLE
);
4726 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4727 SetLastError(ERROR_INVALID_USER_BUFFER
);
4728 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet
, deviceInfo
))
4729 SetLastError(ERROR_INVALID_PARAMETER
);
4732 RemoveEntryList(&deviceInfo
->ListEntry
);
4733 DestroyDeviceInfo(deviceInfo
);
4741 /***********************************************************************
4742 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4745 SetupDiOpenDeviceInfoA(
4746 IN HDEVINFO DeviceInfoSet
,
4747 IN PCSTR DeviceInstanceId
,
4748 IN HWND hwndParent OPTIONAL
,
4750 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4752 LPWSTR DeviceInstanceIdW
= NULL
;
4755 TRACE("%s(%p %s %p %lx %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4757 DeviceInstanceIdW
= pSetupMultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4758 if (DeviceInstanceIdW
== NULL
)
4761 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4762 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4764 MyFree(DeviceInstanceIdW
);
4770 /***********************************************************************
4771 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4774 SetupDiOpenDeviceInfoW(
4775 IN HDEVINFO DeviceInfoSet
,
4776 IN PCWSTR DeviceInstanceId
,
4777 IN HWND hwndParent OPTIONAL
,
4779 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4781 struct DeviceInfoSet
*list
;
4782 HKEY hEnumKey
, hKey
= NULL
;
4786 TRACE("%s(%p %s %p %lx %p)\n", __FUNCTION__
,
4787 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
4788 hwndParent
, OpenFlags
, DeviceInfoData
);
4790 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4791 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4794 SetLastError(ERROR_INVALID_HANDLE
);
4795 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4796 SetLastError(ERROR_INVALID_HANDLE
);
4797 else if (!DeviceInstanceId
)
4798 SetLastError(ERROR_INVALID_PARAMETER
);
4799 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4801 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4802 SetLastError(ERROR_INVALID_FLAGS
);
4804 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4805 SetLastError(ERROR_INVALID_USER_BUFFER
);
4808 struct DeviceInfo
*deviceInfo
= NULL
;
4809 /* Search if device already exists in DeviceInfoSet.
4810 * If yes, return the existing element
4811 * If no, create a new element using information in registry
4813 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4814 while (ItemList
!= &list
->ListHead
)
4816 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
4817 if (!wcscmp(deviceInfo
->instanceId
, DeviceInstanceId
))
4820 ItemList
= ItemList
->Flink
;
4825 /* good one found */
4831 WCHAR szClassGuid
[MAX_GUID_STRING_LEN
];
4833 /* Open supposed registry key */
4836 REGSTR_PATH_SYSTEMENUM
,
4840 if (rc
!= ERROR_SUCCESS
)
4851 RegCloseKey(hEnumKey
);
4852 if (rc
!= ERROR_SUCCESS
)
4854 if (rc
== ERROR_FILE_NOT_FOUND
)
4855 rc
= ERROR_NO_SUCH_DEVINST
;
4860 ClassGUID
= GUID_NULL
;
4861 dwSize
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
4863 if (RegQueryValueExW(hKey
,
4864 REGSTR_VAL_CLASSGUID
,
4867 (LPBYTE
)szClassGuid
,
4868 &dwSize
) == ERROR_SUCCESS
)
4870 szClassGuid
[MAX_GUID_STRING_LEN
- 2] = UNICODE_NULL
;
4872 /* Convert a string to a ClassGuid */
4873 UuidFromStringW(&szClassGuid
[1], &ClassGUID
);
4876 if (!CreateDeviceInfo(list
, DeviceInstanceId
, &ClassGUID
, &deviceInfo
))
4879 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4884 if (ret
&& deviceInfo
&& DeviceInfoData
)
4886 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4887 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4888 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4899 /***********************************************************************
4900 * SetupDiGetSelectedDevice (SETUPAPI.@)
4903 SetupDiGetSelectedDevice(
4904 IN HDEVINFO DeviceInfoSet
,
4905 OUT PSP_DEVINFO_DATA DeviceInfoData
)
4907 struct DeviceInfoSet
*list
;
4910 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
4913 SetLastError(ERROR_INVALID_HANDLE
);
4914 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4915 SetLastError(ERROR_INVALID_HANDLE
);
4916 else if (list
->SelectedDevice
== NULL
)
4917 SetLastError(ERROR_NO_DEVICE_SELECTED
);
4918 else if (!DeviceInfoData
)
4919 SetLastError(ERROR_INVALID_PARAMETER
);
4920 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4921 SetLastError(ERROR_INVALID_USER_BUFFER
);
4924 memcpy(&DeviceInfoData
->ClassGuid
,
4925 &list
->SelectedDevice
->ClassGuid
,
4927 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
4928 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
4932 TRACE("Returning %d\n", ret
);
4937 /***********************************************************************
4938 * SetupDiSetSelectedDevice (SETUPAPI.@)
4941 SetupDiSetSelectedDevice(
4942 IN HDEVINFO DeviceInfoSet
,
4943 IN PSP_DEVINFO_DATA DeviceInfoData
)
4945 struct DeviceInfoSet
*list
;
4948 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
4951 SetLastError(ERROR_INVALID_HANDLE
);
4952 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4953 SetLastError(ERROR_INVALID_HANDLE
);
4954 else if (!DeviceInfoData
)
4955 SetLastError(ERROR_INVALID_PARAMETER
);
4956 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4957 SetLastError(ERROR_INVALID_USER_BUFFER
);
4958 else if (DeviceInfoData
->Reserved
== 0)
4959 SetLastError(ERROR_INVALID_USER_BUFFER
);
4962 list
->SelectedDevice
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
4966 TRACE("Returning %d\n", ret
);
4971 /* Return the current hardware profile id, or -1 if error */
4973 SETUPAPI_GetCurrentHwProfile(
4974 IN HDEVINFO DeviceInfoSet
)
4977 DWORD dwRegType
, dwLength
;
4980 DWORD ret
= (DWORD
)-1;
4982 rc
= RegOpenKeyExW(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
4983 REGSTR_PATH_IDCONFIGDB
,
4987 if (rc
!= ERROR_SUCCESS
)
4993 dwLength
= sizeof(DWORD
);
4994 rc
= RegQueryValueExW(hKey
,
4995 REGSTR_VAL_CURRENTCONFIG
,
4998 (LPBYTE
)&hwProfile
, &dwLength
);
4999 if (rc
!= ERROR_SUCCESS
)
5004 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5006 SetLastError(ERROR_GEN_FAILURE
);
5021 IN HDEVINFO DeviceInfoSet
,
5022 IN PSP_DEVINFO_DATA DeviceInfoData
)
5025 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5026 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5029 cr
= CM_Enable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
5030 if (cr
!= CR_SUCCESS
)
5032 SetLastError(GetErrorCodeFromCrCode(cr
));
5038 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5045 IN HDEVINFO DeviceInfoSet
,
5046 IN PSP_DEVINFO_DATA DeviceInfoData
)
5049 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5050 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5053 cr
= CM_Disable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
5054 if (cr
!= CR_SUCCESS
)
5056 SetLastError(GetErrorCodeFromCrCode(cr
));
5062 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5067 /***********************************************************************
5068 * SetupDiChangeState (SETUPAPI.@)
5072 IN HDEVINFO DeviceInfoSet
,
5073 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5075 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5076 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5077 PSP_PROPCHANGE_PARAMS PropChange
;
5078 HKEY hRootKey
= INVALID_HANDLE_VALUE
, hKey
= INVALID_HANDLE_VALUE
;
5079 LPCWSTR RegistryValueName
;
5080 DWORD dwConfigFlags
, dwLength
, dwRegType
;
5084 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
5086 if (!DeviceInfoData
)
5087 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChangeParams
;
5089 PropChange
= ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChangeParams
;
5092 SetLastError(ERROR_INVALID_PARAMETER
);
5096 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
5097 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
5099 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
5101 switch (PropChange
->StateChange
)
5106 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
5107 hRootKey
= set
->HKLM
;
5108 else /* PropChange->Scope == DICS_FLAG_CONFIGSPECIFIC */
5110 hRootKey
= OpenHardwareProfileKey(set
->HKLM
, PropChange
->HwProfile
, KEY_CREATE_SUB_KEY
);
5111 if (hRootKey
== INVALID_HANDLE_VALUE
)
5115 /* Enable/disable device in registry */
5116 hKey
= SETUPDI_OpenDrvKey(hRootKey
, deviceInfo
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5117 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5118 hKey
= SETUPDI_CreateDevKey(hRootKey
, deviceInfo
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5119 if (hKey
== INVALID_HANDLE_VALUE
)
5121 dwLength
= sizeof(DWORD
);
5122 rc
= RegQueryValueExW(
5127 (LPBYTE
)&dwConfigFlags
, &dwLength
);
5128 if (rc
== ERROR_FILE_NOT_FOUND
)
5130 else if (rc
!= ERROR_SUCCESS
)
5135 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5137 SetLastError(ERROR_GEN_FAILURE
);
5140 if (PropChange
->StateChange
== DICS_ENABLE
)
5141 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5143 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5144 rc
= RegSetValueExW(
5149 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
5150 if (rc
!= ERROR_SUCCESS
)
5156 /* Enable/disable device if needed */
5157 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
5158 || PropChange
->HwProfile
== 0
5159 || PropChange
->HwProfile
== SETUPAPI_GetCurrentHwProfile(DeviceInfoSet
))
5161 if (PropChange
->StateChange
== DICS_ENABLE
)
5162 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5164 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
5170 case DICS_PROPCHANGE
:
5172 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5177 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
5178 SetLastError(ERROR_NOT_SUPPORTED
);
5183 if (hRootKey
!= INVALID_HANDLE_VALUE
&& hRootKey
!= set
->HKLM
)
5184 RegCloseKey(hRootKey
);
5186 if (hKey
!= INVALID_HANDLE_VALUE
)
5189 TRACE("Returning %d\n", ret
);
5193 /***********************************************************************
5194 * SetupDiSelectDevice (SETUPAPI.@)
5197 SetupDiSelectDevice(
5198 IN HDEVINFO DeviceInfoSet
,
5199 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5201 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5202 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5207 /***********************************************************************
5208 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5211 SetupDiRegisterCoDeviceInstallers(
5212 IN HDEVINFO DeviceInfoSet
,
5213 IN PSP_DEVINFO_DATA DeviceInfoData
)
5215 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5216 struct DeviceInfo
*deviceInfo
;
5217 BOOL ret
= FALSE
; /* Return value */
5219 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
5222 SetLastError(ERROR_INVALID_PARAMETER
);
5223 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5224 SetLastError(ERROR_INVALID_HANDLE
);
5225 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5226 SetLastError(ERROR_INVALID_HANDLE
);
5227 else if (!DeviceInfoData
)
5228 SetLastError(ERROR_INVALID_PARAMETER
);
5229 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5230 SetLastError(ERROR_INVALID_USER_BUFFER
);
5233 SP_DEVINSTALL_PARAMS_W InstallParams
;
5234 struct DriverInfoElement
*SelectedDriver
;
5237 WCHAR SectionName
[MAX_PATH
];
5238 DWORD SectionNameLength
= 0;
5239 HKEY hKey
= INVALID_HANDLE_VALUE
;
5240 PVOID Context
= NULL
;
5242 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5243 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5247 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.ClassInstallReserved
;
5248 if (SelectedDriver
== NULL
)
5250 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5254 /* Get .CoInstallers section name */
5255 Result
= SetupDiGetActualSectionToInstallW(
5256 SelectedDriver
->InfFileDetails
->hInf
,
5257 SelectedDriver
->Details
.SectionName
,
5258 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5259 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
5261 lstrcatW(SectionName
, DotCoInstallers
);
5263 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5265 /* Open/Create driver key information */
5266 #if _WIN32_WINNT >= 0x502
5267 hKey
= SETUPDI_OpenDrvKey(set
->HKLM
, deviceInfo
, KEY_READ
| KEY_WRITE
);
5269 hKey
= SETUPDI_OpenDrvKey(set
->HKLM
, deviceInfo
, KEY_ALL_ACCESS
);
5271 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5272 #if _WIN32_WINNT >= 0x502
5273 hKey
= SETUPDI_CreateDrvKey(set
->HKLM
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_READ
| KEY_WRITE
);
5275 hKey
= SETUPDI_CreateDrvKey(set
->HKLM
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_ALL_ACCESS
);
5277 if (hKey
== INVALID_HANDLE_VALUE
)
5280 /* Install .CoInstallers section */
5281 DoAction
= SPINST_REGISTRY
;
5282 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5284 DoAction
|= SPINST_FILES
;
5285 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5289 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5290 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5291 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5292 SetupDefaultQueueCallbackW
, Context
,
5293 DeviceInfoSet
, DeviceInfoData
);
5301 SetupTermDefaultQueueCallback(Context
);
5302 if (hKey
!= INVALID_HANDLE_VALUE
)
5306 TRACE("Returning %d\n", ret
);
5311 InfIsFromOEMLocation(
5313 OUT LPBOOL IsOEMLocation
)
5317 last
= strrchrW(FullName
, '\\');
5320 /* No directory specified */
5321 *IsOEMLocation
= FALSE
;
5328 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
5331 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5335 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
5336 if (ret
== 0 || ret
> MAX_PATH
)
5339 SetLastError(ERROR_GEN_FAILURE
);
5342 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
5343 strcatW(Windir
, BackSlash
);
5344 strcatW(Windir
, InfDirectory
);
5346 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
5348 /* The path is %SYSTEMROOT%\Inf */
5349 *IsOEMLocation
= FALSE
;
5353 /* The file is in another place */
5354 *IsOEMLocation
= TRUE
;
5361 /***********************************************************************
5362 * SetupDiInstallDevice (SETUPAPI.@)
5365 SetupDiInstallDevice(
5366 IN HDEVINFO DeviceInfoSet
,
5367 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5369 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5370 struct DeviceInfo
*deviceInfo
;
5371 SP_DEVINSTALL_PARAMS_W InstallParams
;
5372 struct DriverInfoElement
*SelectedDriver
;
5373 SYSTEMTIME DriverDate
;
5374 WCHAR SectionName
[MAX_PATH
];
5376 DWORD SectionNameLength
= 0;
5377 BOOL Result
= FALSE
;
5380 LPWSTR pSectionName
= NULL
;
5381 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5383 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5384 BOOL RebootRequired
= FALSE
;
5385 HKEY hKey
= INVALID_HANDLE_VALUE
;
5386 BOOL NeedtoCopyFile
;
5387 LARGE_INTEGER fullVersion
;
5389 PVOID Context
= NULL
;
5390 BOOL ret
= FALSE
; /* Return value */
5392 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
5395 SetLastError(ERROR_INVALID_PARAMETER
);
5396 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5397 SetLastError(ERROR_INVALID_HANDLE
);
5398 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5399 SetLastError(ERROR_INVALID_HANDLE
);
5400 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5401 SetLastError(ERROR_INVALID_USER_BUFFER
);
5407 /* One parameter is bad */
5411 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5412 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5416 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5418 /* Set FAILEDINSTALL in ConfigFlags registry value */
5419 DWORD ConfigFlags
, regType
;
5420 Result
= SetupDiGetDeviceRegistryPropertyW(
5425 (PBYTE
)&ConfigFlags
,
5426 sizeof(ConfigFlags
),
5428 if (!Result
|| regType
!= REG_DWORD
)
5430 SetLastError(ERROR_GEN_FAILURE
);
5433 ConfigFlags
|= CONFIGFLAG_FAILEDINSTALL
;
5434 Result
= SetupDiSetDeviceRegistryPropertyW(
5438 (PBYTE
)&ConfigFlags
,
5439 sizeof(ConfigFlags
));
5442 SetLastError(ERROR_GEN_FAILURE
);
5450 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.ClassInstallReserved
;
5451 if (SelectedDriver
== NULL
)
5453 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5457 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5459 Result
= SetupDiGetActualSectionToInstallW(
5460 SelectedDriver
->InfFileDetails
->hInf
,
5461 SelectedDriver
->Details
.SectionName
,
5462 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5463 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
5465 pSectionName
= &SectionName
[strlenW(SectionName
)];
5467 /* Get information from [Version] section */
5468 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5470 /* Format ClassGuid to a string */
5471 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5473 RequiredSize
= lstrlenW(lpGuidString
);
5474 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5475 if (!lpFullGuidString
)
5477 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5480 lpFullGuidString
[0] = '{';
5481 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5482 lpFullGuidString
[RequiredSize
+ 1] = '}';
5483 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5485 /* Copy .inf file to Inf\ directory (if needed) */
5486 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
5491 WCHAR NewFileName
[MAX_PATH
];
5492 struct InfFileDetails
*newInfFileDetails
;
5493 Result
= SetupCopyOEMInfW(
5494 SelectedDriver
->Details
.InfFileName
,
5497 SP_COPY_NOOVERWRITE
,
5498 NewFileName
, MAX_PATH
,
5501 if (!Result
&& GetLastError() != ERROR_FILE_EXISTS
)
5503 /* Create a new struct InfFileDetails, and set it to
5504 * SelectedDriver->InfFileDetails, to release use of
5505 * current InfFile */
5506 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
5507 if (!newInfFileDetails
)
5509 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
5510 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
5511 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
5514 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5516 /* Open/Create driver key information */
5517 #if _WIN32_WINNT >= 0x502
5518 hKey
= SETUPDI_OpenDrvKey(set
->HKLM
, deviceInfo
, KEY_READ
| KEY_WRITE
);
5520 hKey
= SETUPDI_OpenDrvKey(set
->HKLM
, deviceInfo
, KEY_ALL_ACCESS
);
5522 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5523 #if _WIN32_WINNT >= 0x502
5524 hKey
= SETUPDI_CreateDrvKey(set
->HKLM
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_READ
| KEY_WRITE
);
5526 hKey
= SETUPDI_CreateDrvKey(set
->HKLM
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_ALL_ACCESS
);
5528 if (hKey
== INVALID_HANDLE_VALUE
)
5531 /* Install main section */
5533 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5534 DoAction
|= SPINST_REGISTRY
;
5535 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5537 DoAction
|= SPINST_FILES
;
5538 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5542 *pSectionName
= '\0';
5543 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5544 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5545 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5546 SetupDefaultQueueCallbackW
, Context
,
5547 DeviceInfoSet
, DeviceInfoData
);
5550 InstallParams
.Flags
|= DI_NOFILECOPY
;
5551 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5553 /* Write information to driver key */
5554 *pSectionName
= UNICODE_NULL
;
5555 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
5556 TRACE("Write information to driver key\n");
5557 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5558 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5559 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5560 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
5561 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
5562 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
5563 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
5564 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
5565 sprintfW(Buffer
, DateFormat
, DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5566 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5567 if (rc
== ERROR_SUCCESS
)
5568 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5569 if (rc
== ERROR_SUCCESS
)
5570 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5571 if (rc
== ERROR_SUCCESS
)
5573 sprintfW(Buffer
, VersionFormat
, fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5574 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5576 if (rc
== ERROR_SUCCESS
)
5577 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
5578 if (rc
== ERROR_SUCCESS
)
5579 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5580 if (rc
== ERROR_SUCCESS
)
5581 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
));
5582 if (rc
== ERROR_SUCCESS
)
5583 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5584 if (rc
== ERROR_SUCCESS
)
5585 rc
= RegSetValueExW(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5586 if (rc
!= ERROR_SUCCESS
)
5592 hKey
= INVALID_HANDLE_VALUE
;
5594 /* FIXME: Process .LogConfigOverride section */
5596 /* Install .Services section */
5597 strcpyW(pSectionName
, DotServices
);
5598 Result
= SetupInstallServicesFromInfSectionExW(
5599 SelectedDriver
->InfFileDetails
->hInf
,
5608 if (GetLastError() != ERROR_SECTION_NOT_FOUND
)
5610 SetLastError(ERROR_SUCCESS
);
5612 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5613 RebootRequired
= TRUE
;
5615 /* Open device registry key */
5616 hKey
= SETUPDI_OpenDevKey(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
, (struct DeviceInfo
*)DeviceInfoData
->Reserved
, KEY_SET_VALUE
);
5617 if (hKey
== INVALID_HANDLE_VALUE
)
5620 /* Install .HW section */
5622 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5623 DoAction
|= SPINST_REGISTRY
;
5624 strcpyW(pSectionName
, DotHW
);
5625 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5626 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5627 DoAction
, hKey
, NULL
, 0,
5629 DeviceInfoSet
, DeviceInfoData
);
5633 /* Write information to enum key */
5634 TRACE("Write information to enum key\n");
5635 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
5636 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
5637 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5638 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
5639 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
5640 if (rc
== ERROR_SUCCESS
)
5641 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5642 if (rc
== ERROR_SUCCESS
)
5643 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5644 if (rc
== ERROR_SUCCESS
)
5645 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5646 if (rc
!= ERROR_SUCCESS
)
5652 /* Start the device */
5653 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5654 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5659 /* End of installation */
5660 if (hKey
!= INVALID_HANDLE_VALUE
)
5663 RpcStringFreeW(&lpGuidString
);
5664 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5666 SetupTermDefaultQueueCallback(Context
);
5667 TRACE("Returning %d\n", ret
);
5671 HKEY
SETUPDI_CreateDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5673 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5676 l
= RegCreateKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_CREATE_SUB_KEY
, NULL
, &enumKey
, NULL
);
5679 l
= RegCreateKeyExW(enumKey
, devInfo
->instanceId
, 0, NULL
, REG_OPTION_NON_VOLATILE
, samDesired
, NULL
, &key
, NULL
);
5680 RegCloseKey(enumKey
);
5687 HKEY
SETUPDI_CreateDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, UUID
*ClassGuid
, REGSAM samDesired
)
5689 HKEY key
= INVALID_HANDLE_VALUE
;
5690 LPWSTR lpGuidString
= NULL
;
5691 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
5692 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
5693 DWORD Index
; /* Index used in the DriverKey name */
5697 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
5698 HKEY hEnumKey
= NULL
;
5699 HKEY hClassKey
= NULL
;
5700 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
5703 /* Open device key, to read Driver value */
5704 hDeviceKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5705 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
5708 rc
= RegOpenKeyExW(RootKey
, REGSTR_PATH_CLASS_NT
, 0, KEY_CREATE_SUB_KEY
, &hClassKey
);
5709 if (rc
!= ERROR_SUCCESS
)
5715 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, NULL
, &dwSize
);
5716 if (rc
!= ERROR_SUCCESS
)
5718 /* Create a new driver key */
5720 if (UuidToStringW(ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5723 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
5724 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
5727 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5732 strcpyW(&DriverKey
[1], lpGuidString
);
5733 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
5734 *pDeviceInstance
++ = '}';
5735 *pDeviceInstance
++ = '\\';
5737 /* Try all values for Index between 0 and 9999 */
5739 while (Index
<= 9999)
5741 sprintfW(pDeviceInstance
, InstanceKeyFormat
, Index
);
5742 rc
= RegCreateKeyExW(hClassKey
,
5746 REG_OPTION_NON_VOLATILE
,
5747 #if _WIN32_WINNT >= 0x502
5748 KEY_READ
| KEY_WRITE
,
5755 if (rc
!= ERROR_SUCCESS
)
5760 if (Disposition
== REG_CREATED_NEW_KEY
)
5769 /* Unable to create more than 9999 devices within the same class */
5770 SetLastError(ERROR_GEN_FAILURE
);
5774 /* Write the new Driver value */
5775 rc
= RegSetValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
5776 if (rc
!= ERROR_SUCCESS
)
5784 /* Open the existing driver key */
5786 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
5789 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5793 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, (LPBYTE
)DriverKey
, &dwSize
);
5794 if (rc
!= ERROR_SUCCESS
)
5800 rc
= RegCreateKeyExW(hClassKey
,
5804 REG_OPTION_NON_VOLATILE
,
5805 #if _WIN32_WINNT >= 0x502
5806 KEY_READ
| KEY_WRITE
,
5813 if (rc
!= ERROR_SUCCESS
)
5824 RpcStringFreeW(&lpGuidString
);
5825 HeapFree(GetProcessHeap(), 0, DriverKey
);
5826 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5827 RegCloseKey(hHWProfileKey
);
5828 if (hEnumKey
!= NULL
)
5829 RegCloseKey(hEnumKey
);
5830 if (hClassKey
!= NULL
)
5831 RegCloseKey(hClassKey
);
5832 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
5833 RegCloseKey(hDeviceKey
);
5834 if (hKey
!= NULL
&& hKey
!= key
)
5837 TRACE("Returning 0x%p\n", hKey
);
5841 HKEY
SETUPDI_OpenDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5843 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5846 l
= RegOpenKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, READ_CONTROL
, &enumKey
);
5849 l
= RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
5850 RegCloseKey(enumKey
);
5857 HKEY
SETUPDI_OpenDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5859 LPWSTR DriverKey
= NULL
;
5863 HKEY hEnumKey
= NULL
;
5865 HKEY key
= INVALID_HANDLE_VALUE
;
5867 hKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
);
5868 if (hKey
== INVALID_HANDLE_VALUE
)
5870 /* Read the 'Driver' key */
5871 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5872 if (rc
!= ERROR_SUCCESS
)
5877 else if (dwRegType
!= REG_SZ
)
5879 SetLastError(ERROR_GEN_FAILURE
);
5882 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5885 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5888 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5889 if (rc
!= ERROR_SUCCESS
)
5896 /* Need to open the driver key */
5899 REGSTR_PATH_CLASS_NT
,
5903 if (rc
!= ERROR_SUCCESS
)
5914 if (rc
!= ERROR_SUCCESS
)
5922 if (hEnumKey
!= NULL
)
5923 RegCloseKey(hEnumKey
);
5924 if (hKey
!= NULL
&& hKey
!= key
)
5927 HeapFree(GetProcessHeap(), 0, DriverKey
);
5931 /***********************************************************************
5932 * SetupDiOpenDevRegKey (SETUPAPI.@)
5934 HKEY WINAPI
SetupDiOpenDevRegKey(
5935 HDEVINFO DeviceInfoSet
,
5936 PSP_DEVINFO_DATA DeviceInfoData
,
5942 struct DeviceInfoSet
*set
= DeviceInfoSet
;
5943 struct DeviceInfo
*devInfo
;
5944 HKEY key
= INVALID_HANDLE_VALUE
;
5947 TRACE("%s(%p %p %d %d %d %x)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
,
5948 Scope
, HwProfile
, KeyType
, samDesired
);
5950 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5952 SetLastError(ERROR_INVALID_HANDLE
);
5953 return INVALID_HANDLE_VALUE
;
5955 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5957 SetLastError(ERROR_INVALID_HANDLE
);
5958 return INVALID_HANDLE_VALUE
;
5960 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5961 || !DeviceInfoData
->Reserved
)
5963 SetLastError(ERROR_INVALID_PARAMETER
);
5964 return INVALID_HANDLE_VALUE
;
5966 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5968 SetLastError(ERROR_INVALID_FLAGS
);
5969 return INVALID_HANDLE_VALUE
;
5971 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
5973 SetLastError(ERROR_INVALID_FLAGS
);
5974 return INVALID_HANDLE_VALUE
;
5976 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5977 if (devInfo
->set
!= set
)
5979 SetLastError(ERROR_INVALID_PARAMETER
);
5980 return INVALID_HANDLE_VALUE
;
5982 if (Scope
!= DICS_FLAG_GLOBAL
)
5984 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5985 if (RootKey
== INVALID_HANDLE_VALUE
)
5986 return INVALID_HANDLE_VALUE
;
5989 RootKey
= set
->HKLM
;
5993 key
= SETUPDI_OpenDevKey(RootKey
, devInfo
, samDesired
);
5994 if (Scope
== DICS_FLAG_GLOBAL
)
5997 HKEY hTempKey
= key
;
5998 rc
= RegOpenKeyExW(hTempKey
,
5999 L
"Device Parameters",
6003 if (rc
== ERROR_SUCCESS
)
6004 RegCloseKey(hTempKey
);
6008 key
= SETUPDI_OpenDrvKey(RootKey
, devInfo
, samDesired
);
6011 WARN("unknown KeyType %d\n", KeyType
);
6013 if (RootKey
!= set
->HKLM
)
6014 RegCloseKey(RootKey
);
6018 static BOOL
SETUPDI_DeleteDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
6024 static BOOL
SETUPDI_DeleteDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
6030 /***********************************************************************
6031 * SetupDiDeleteDevRegKey (SETUPAPI.@)
6033 BOOL WINAPI
SetupDiDeleteDevRegKey(
6034 HDEVINFO DeviceInfoSet
,
6035 PSP_DEVINFO_DATA DeviceInfoData
,
6040 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
6041 struct DeviceInfo
*devInfo
;
6045 TRACE("%s(%p %p %d %d %d)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
6048 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
6050 SetLastError(ERROR_INVALID_HANDLE
);
6053 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
6055 SetLastError(ERROR_INVALID_HANDLE
);
6058 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
6059 || !DeviceInfoData
->Reserved
)
6061 SetLastError(ERROR_INVALID_PARAMETER
);
6064 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
6066 SetLastError(ERROR_INVALID_FLAGS
);
6069 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
&& KeyType
!= DIREG_BOTH
)
6071 SetLastError(ERROR_INVALID_FLAGS
);
6074 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
6075 if (devInfo
->set
!= set
)
6077 SetLastError(ERROR_INVALID_PARAMETER
);
6080 if (Scope
!= DICS_FLAG_GLOBAL
)
6082 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
6083 if (RootKey
== INVALID_HANDLE_VALUE
)
6087 RootKey
= set
->HKLM
;
6091 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
6094 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
6097 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
6099 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
6102 WARN("unknown KeyType %d\n", KeyType
);
6104 if (RootKey
!= set
->HKLM
)
6105 RegCloseKey(RootKey
);
6109 /***********************************************************************
6110 * SetupDiRestartDevices (SETUPAPI.@)
6114 SetupDiRestartDevices(
6115 HDEVINFO DeviceInfoSet
,
6116 PSP_DEVINFO_DATA DeviceInfoData
)
6118 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
6119 struct DeviceInfo
*devInfo
;
6122 TRACE("%s(%p %p)\n", __FUNCTION__
, DeviceInfoSet
, DeviceInfoData
);
6124 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
6126 SetLastError(ERROR_INVALID_HANDLE
);
6129 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
6131 SetLastError(ERROR_INVALID_HANDLE
);
6135 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
6136 || !DeviceInfoData
->Reserved
)
6138 SetLastError(ERROR_INVALID_PARAMETER
);
6142 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
6144 cr
= CM_Enable_DevNode_Ex(devInfo
->dnDevInst
, 0, set
->hMachine
);
6145 if (cr
!= CR_SUCCESS
)
6147 SetLastError(GetErrorCodeFromCrCode(cr
));