2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "setupapi_private.h"
24 /* Unicode constants */
25 static const WCHAR BackSlash
[] = {'\\',0};
26 static const WCHAR DateFormat
[] = {'%','u','-','%','u','-','%','u',0};
27 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
28 static const WCHAR DotHW
[] = {'.','H','W',0};
29 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
30 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
31 static const WCHAR InstanceKeyFormat
[] = {'%','0','4','l','u',0};
32 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
33 static const WCHAR VersionFormat
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
35 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
36 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
37 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
38 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
39 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
42 (CALLBACK
* CLASS_INSTALL_PROC
) (
43 IN DI_FUNCTION InstallFunction
,
44 IN HDEVINFO DeviceInfoSet
,
45 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
47 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
48 IN HDEVINFO DeviceInfoSet
,
49 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
51 (CALLBACK
* COINSTALLER_PROC
) (
52 IN DI_FUNCTION InstallFunction
,
53 IN HDEVINFO DeviceInfoSet
,
54 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
55 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
57 struct CoInstallerElement
62 COINSTALLER_PROC Function
;
63 BOOL DoPostProcessing
;
67 struct GetSectionCallbackInfo
69 PSP_ALTPLATFORM_INFO PlatformInfo
;
73 WCHAR BestSection
[LINE_LEN
+ 1];
74 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
79 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
81 static const WCHAR fmt
[] = {'{','%','0','8','X','-','%','0','4','X','-',
82 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
83 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
86 sprintfW(guidStr
, fmt
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
87 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
88 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
92 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
96 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
97 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
98 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
99 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
100 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
101 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
102 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
103 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
104 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
105 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
106 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
107 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
108 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
109 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
110 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
111 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
112 case CR_ALREADY_SUCH_DEVINST
: return ERROR_DEVINST_ALREADY_EXISTS
;
113 case CR_SUCCESS
: return ERROR_SUCCESS
;
114 default: return ERROR_GEN_FAILURE
;
117 /* Does not happen */
120 /* Lower scores are best ones */
123 IN LPCWSTR SectionName
,
124 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
127 OUT PDWORD ScorePlatform
,
128 OUT PDWORD ScoreMajorVersion
,
129 OUT PDWORD ScoreMinorVersion
,
130 OUT PDWORD ScoreProductType
,
131 OUT PDWORD ScoreSuiteMask
)
133 LPWSTR Section
= NULL
;
134 //LPCWSTR pExtensionPlatform;
135 LPCWSTR pExtensionArchitecture
;
140 //static const WCHAR ExtensionPlatformNone[] = {'.',0};
141 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
142 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
144 static const WCHAR ExtensionArchitectureNone
[] = {0};
145 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
146 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
147 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
148 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
149 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
150 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
152 TRACE("%s %p 0x%x 0x%x\n",
153 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
155 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
157 Section
= pSetupDuplicateString(SectionName
);
160 TRACE("pSetupDuplicateString() failed\n");
164 /* Set various extensions values */
165 switch (PlatformInfo
->Platform
)
167 case VER_PLATFORM_WIN32_WINDOWS
:
168 //pExtensionPlatform = ExtensionPlatformWindows;
170 case VER_PLATFORM_WIN32_NT
:
171 //pExtensionPlatform = ExtensionPlatformNT;
174 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
175 //pExtensionPlatform = ExtensionPlatformNone;
178 switch (PlatformInfo
->ProcessorArchitecture
)
180 case PROCESSOR_ARCHITECTURE_ALPHA
:
181 pExtensionArchitecture
= ExtensionArchitecturealpha
;
183 case PROCESSOR_ARCHITECTURE_AMD64
:
184 pExtensionArchitecture
= ExtensionArchitectureamd64
;
186 case PROCESSOR_ARCHITECTURE_IA64
:
187 pExtensionArchitecture
= ExtensionArchitectureia64
;
189 case PROCESSOR_ARCHITECTURE_INTEL
:
190 pExtensionArchitecture
= ExtensionArchitecturex86
;
192 case PROCESSOR_ARCHITECTURE_MIPS
:
193 pExtensionArchitecture
= ExtensionArchitecturemips
;
195 case PROCESSOR_ARCHITECTURE_PPC
:
196 pExtensionArchitecture
= ExtensionArchitectureppc
;
199 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
200 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
201 pExtensionArchitecture
= ExtensionArchitectureNone
;
207 * Field[1] Architecture
208 * Field[2] Major version
209 * Field[3] Minor version
210 * Field[4] Product type
211 * Field[5] Suite mask
212 * Remark: these fields may be NULL if the information is not provided
215 if (Fields
[0] == NULL
)
217 TRACE("No extension found\n");
218 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
222 Fields
[1] = Fields
[0] + 1;
223 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
224 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
226 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
230 *(Fields
[i
] - 1) = UNICODE_NULL
;
233 /* Take care of first 2 fields */
234 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
236 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
238 TRACE("Mismatch on platform field\n");
241 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
243 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
245 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
247 TRACE("Mismatch on platform field\n");
250 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
254 /* No platform specified */
255 *ScorePlatform
|= 0x02;
257 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
259 /* No architecture specified */
260 *ScorePlatform
|= 0x01;
262 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
264 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
265 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
269 /* Check if informations are matching */
270 if (Fields
[2] && *Fields
[2])
272 DWORD MajorVersion
, MinorVersion
= 0;
273 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
274 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
275 (errno
== ERANGE
|| errno
== EINVAL
))
277 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
280 if (Fields
[3] && *Fields
[3])
282 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
283 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
284 (errno
== ERANGE
|| errno
== EINVAL
))
286 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
290 if (PlatformInfo
->MajorVersion
< MajorVersion
||
291 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
293 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
294 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
297 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
298 if (MajorVersion
== PlatformInfo
->MajorVersion
)
299 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
301 *ScoreMinorVersion
= MinorVersion
;
303 else if (Fields
[3] && *Fields
[3])
305 TRACE("Minor version found without major version\n");
310 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
311 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
314 if (Fields
[4] && *Fields
[4])
316 DWORD CurrentProductType
;
317 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
318 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
319 (errno
== ERANGE
|| errno
== EINVAL
))
321 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
324 if (CurrentProductType
!= ProductType
)
326 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
327 CurrentProductType
, ProductType
);
332 *ScoreProductType
= 1;
334 if (Fields
[5] && *Fields
[5])
336 DWORD CurrentSuiteMask
;
337 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
338 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
339 (errno
== ERANGE
|| errno
== EINVAL
))
341 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
344 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
346 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
347 CurrentSuiteMask
, SuiteMask
);
350 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
353 *ScoreSuiteMask
= SuiteMask
;
364 IN LPCWSTR SectionName
,
367 struct GetSectionCallbackInfo
*info
= Context
;
368 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
371 if (SectionName
[info
->PrefixLength
] != '.')
374 ret
= CheckSectionValid(
375 &SectionName
[info
->PrefixLength
],
379 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
382 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
385 if (Score1
> info
->BestScore1
) goto done
;
386 if (Score1
< info
->BestScore1
) goto bettersection
;
387 if (Score2
> info
->BestScore2
) goto done
;
388 if (Score2
< info
->BestScore2
) goto bettersection
;
389 if (Score3
> info
->BestScore3
) goto done
;
390 if (Score3
< info
->BestScore3
) goto bettersection
;
391 if (Score4
> info
->BestScore4
) goto done
;
392 if (Score4
< info
->BestScore4
) goto bettersection
;
393 if (Score5
> info
->BestScore5
) goto done
;
394 if (Score5
< info
->BestScore5
) goto bettersection
;
398 strcpyW(info
->BestSection
, SectionName
);
399 info
->BestScore1
= Score1
;
400 info
->BestScore2
= Score2
;
401 info
->BestScore3
= Score3
;
402 info
->BestScore4
= Score4
;
403 info
->BestScore5
= Score5
;
409 /***********************************************************************
410 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
413 SetupDiGetActualSectionToInstallExW(
415 IN PCWSTR InfSectionName
,
416 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
417 OUT PWSTR InfSectionWithExt OPTIONAL
,
418 IN DWORD InfSectionWithExtSize
,
419 OUT PDWORD RequiredSize OPTIONAL
,
420 OUT PWSTR
* Extension OPTIONAL
,
425 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
426 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
427 RequiredSize
, Extension
, Reserved
);
429 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
430 SetLastError(ERROR_INVALID_HANDLE
);
431 else if (!InfSectionName
)
432 SetLastError(ERROR_INVALID_PARAMETER
);
433 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
434 SetLastError(ERROR_INVALID_USER_BUFFER
);
435 else if (Reserved
!= NULL
)
436 SetLastError(ERROR_INVALID_PARAMETER
);
439 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
440 static BYTE CurrentProductType
= 0;
441 static WORD CurrentSuiteMask
= 0;
442 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
443 struct GetSectionCallbackInfo CallbackInfo
;
448 /* Fill platform info if needed */
449 if (AlternatePlatformInfo
)
451 pPlatformInfo
= AlternatePlatformInfo
;
457 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
459 /* That's the first time we go here. We need to fill in the structure */
460 SYSTEM_INFO SystemInfo
;
461 GetSystemInfo(&SystemInfo
);
462 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
463 CurrentPlatform
.Platform
= OsVersionInfo
.dwPlatformId
;
464 CurrentPlatform
.MajorVersion
= OsVersionInfo
.dwMajorVersion
;
465 CurrentPlatform
.MinorVersion
= OsVersionInfo
.dwMinorVersion
;
466 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
467 CurrentPlatform
.Reserved
= 0;
468 CurrentProductType
= OsVersionInfo
.wProductType
;
469 CurrentSuiteMask
= OsVersionInfo
.wSuiteMask
;
471 ProductType
= CurrentProductType
;
472 SuiteMask
= CurrentSuiteMask
;
475 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
476 CallbackInfo
.ProductType
= ProductType
;
477 CallbackInfo
.SuiteMask
= SuiteMask
;
478 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
479 CallbackInfo
.BestScore1
= ULONG_MAX
;
480 CallbackInfo
.BestScore2
= ULONG_MAX
;
481 CallbackInfo
.BestScore3
= ULONG_MAX
;
482 CallbackInfo
.BestScore4
= ULONG_MAX
;
483 CallbackInfo
.BestScore5
= ULONG_MAX
;
484 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
485 TRACE("EnumerateSectionsStartingWith(InfSectionName = %S)\n", InfSectionName
);
486 if (!EnumerateSectionsStartingWith(
492 SetLastError(ERROR_GEN_FAILURE
);
495 TRACE("CallbackInfo.BestSection = %S\n", CallbackInfo
.BestSection
);
497 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
498 if (RequiredSize
!= NULL
)
499 *RequiredSize
= dwFullLength
+ 1;
501 if (InfSectionWithExtSize
> 0)
503 if (InfSectionWithExtSize
< dwFullLength
+ 1)
505 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
508 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
511 DWORD dwLength
= lstrlenW(InfSectionName
);
512 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
520 TRACE("Returning %d\n", ret
);
527 IN
struct DeviceInfoSet
*list
,
528 IN LPCWSTR InstancePath
,
529 IN LPCGUID pClassGuid
,
530 OUT
struct DeviceInfo
**pDeviceInfo
)
534 struct DeviceInfo
*deviceInfo
;
538 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
539 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
542 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
545 ZeroMemory(deviceInfo
, size
);
547 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
548 if (cr
!= CR_SUCCESS
)
550 SetLastError(GetErrorCodeFromCrCode(cr
));
554 deviceInfo
->set
= list
;
555 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
556 strcpyW(deviceInfo
->Data
, InstancePath
);
557 deviceInfo
->instanceId
= deviceInfo
->Data
;
558 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
559 deviceInfo
->DeviceDescription
= NULL
;
560 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
561 deviceInfo
->CreationFlags
= 0;
562 InitializeListHead(&deviceInfo
->DriverListHead
);
563 InitializeListHead(&deviceInfo
->InterfaceListHead
);
565 *pDeviceInfo
= deviceInfo
;
571 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
573 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
574 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
579 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
581 PLIST_ENTRY ListEntry
;
582 struct DriverInfoElement
*driverInfo
;
583 struct DeviceInterface
*deviceInterface
;
585 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
587 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
588 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
589 if (!DestroyDriverInfoElement(driverInfo
))
592 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
594 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
595 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
596 if (!DestroyDeviceInterface(deviceInterface
))
599 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
600 if (deviceInfo
->hmodDevicePropPageProvider
)
601 FreeLibrary(deviceInfo
->hmodDevicePropPageProvider
);
602 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
606 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
608 PLIST_ENTRY ListEntry
;
609 struct DeviceInfo
*deviceInfo
;
611 while (!IsListEmpty(&list
->ListHead
))
613 ListEntry
= RemoveHeadList(&list
->ListHead
);
614 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
);
615 if (!DestroyDeviceInfo(deviceInfo
))
618 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
619 RegCloseKey(list
->HKLM
);
620 CM_Disconnect_Machine(list
->hMachine
);
621 DestroyClassInstallParams(&list
->ClassInstallParams
);
622 if (list
->hmodClassPropPageProvider
)
623 FreeLibrary(list
->hmodClassPropPageProvider
);
624 return HeapFree(GetProcessHeap(), 0, list
);
627 /***********************************************************************
628 * SetupDiBuildClassInfoList (SETUPAPI.@)
630 * Returns a list of setup class GUIDs that identify the classes
631 * that are installed on a local machine.
634 * Flags [I] control exclusion of classes from the list.
635 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
636 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
637 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
643 BOOL WINAPI
SetupDiBuildClassInfoList(
645 LPGUID ClassGuidList
,
646 DWORD ClassGuidListSize
,
650 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
651 ClassGuidListSize
, RequiredSize
,
655 /***********************************************************************
656 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
658 * Returns a list of setup class GUIDs that identify the classes
659 * that are installed on a local or remote machine.
662 * Flags [I] control exclusion of classes from the list.
663 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
664 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
665 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
666 * MachineName [I] name of a remote machine.
667 * Reserved [I] must be NULL.
673 BOOL WINAPI
SetupDiBuildClassInfoListExA(
675 LPGUID ClassGuidList
,
676 DWORD ClassGuidListSize
,
681 LPWSTR MachineNameW
= NULL
;
684 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
685 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
689 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
690 if (MachineNameW
== NULL
) return FALSE
;
693 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
694 ClassGuidListSize
, RequiredSize
,
695 MachineNameW
, Reserved
);
697 MyFree(MachineNameW
);
702 /***********************************************************************
703 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
705 * Returns a list of setup class GUIDs that identify the classes
706 * that are installed on a local or remote machine.
709 * Flags [I] control exclusion of classes from the list.
710 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
711 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
712 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
713 * MachineName [I] name of a remote machine.
714 * Reserved [I] must be NULL.
720 BOOL WINAPI
SetupDiBuildClassInfoListExW(
722 LPGUID ClassGuidList
,
723 DWORD ClassGuidListSize
,
729 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
734 DWORD dwGuidListIndex
= 0;
736 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
737 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
741 SetLastError(ERROR_INVALID_PARAMETER
);
744 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
746 SetLastError(ERROR_INVALID_PARAMETER
);
750 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
751 KEY_ENUMERATE_SUB_KEYS
,
755 if (hClassesKey
== INVALID_HANDLE_VALUE
)
760 for (dwIndex
= 0; ; dwIndex
++)
763 lError
= RegEnumKeyExW(hClassesKey
,
771 TRACE("RegEnumKeyExW() returns %d\n", lError
);
772 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
774 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
776 if (RegOpenKeyExW(hClassesKey
,
782 RegCloseKey(hClassesKey
);
786 if (!RegQueryValueExW(hClassKey
,
787 REGSTR_VAL_NOUSECLASS
,
793 TRACE("'NoUseClass' value found!\n");
794 RegCloseKey(hClassKey
);
798 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
799 (!RegQueryValueExW(hClassKey
,
800 REGSTR_VAL_NOINSTALLCLASS
,
806 TRACE("'NoInstallClass' value found!\n");
807 RegCloseKey(hClassKey
);
811 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
812 (!RegQueryValueExW(hClassKey
,
813 REGSTR_VAL_NODISPLAYCLASS
,
819 TRACE("'NoDisplayClass' value found!\n");
820 RegCloseKey(hClassKey
);
824 RegCloseKey(hClassKey
);
826 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
827 if (dwGuidListIndex
< ClassGuidListSize
)
829 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
833 TRACE("Guid: %p\n", &szKeyName
[1]);
835 UuidFromStringW(&szKeyName
[1],
836 &ClassGuidList
[dwGuidListIndex
]);
842 if (lError
!= ERROR_SUCCESS
)
846 RegCloseKey(hClassesKey
);
848 if (RequiredSize
!= NULL
)
849 *RequiredSize
= dwGuidListIndex
;
851 if (ClassGuidListSize
< dwGuidListIndex
)
853 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
860 /***********************************************************************
861 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
863 BOOL WINAPI
SetupDiClassGuidsFromNameA(
865 LPGUID ClassGuidList
,
866 DWORD ClassGuidListSize
,
869 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
870 ClassGuidListSize
, RequiredSize
,
874 /***********************************************************************
875 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
877 BOOL WINAPI
SetupDiClassGuidsFromNameW(
879 LPGUID ClassGuidList
,
880 DWORD ClassGuidListSize
,
883 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
884 ClassGuidListSize
, RequiredSize
,
888 /***********************************************************************
889 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
891 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
893 LPGUID ClassGuidList
,
894 DWORD ClassGuidListSize
,
899 LPWSTR ClassNameW
= NULL
;
900 LPWSTR MachineNameW
= NULL
;
903 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName
), ClassGuidList
,
904 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
908 SetLastError(ERROR_INVALID_PARAMETER
);
912 ClassNameW
= pSetupMultiByteToUnicode(ClassName
, CP_ACP
);
913 if (ClassNameW
== NULL
)
918 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
919 if (MachineNameW
== NULL
)
926 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
927 ClassGuidListSize
, RequiredSize
,
928 MachineNameW
, Reserved
);
930 MyFree(MachineNameW
);
936 /***********************************************************************
937 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
939 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
941 LPGUID ClassGuidList
,
942 DWORD ClassGuidListSize
,
948 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
954 DWORD dwGuidListIndex
= 0;
956 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
957 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
959 if (!ClassName
|| !RequiredSize
)
961 SetLastError(ERROR_INVALID_PARAMETER
);
964 if (!ClassGuidList
&& ClassGuidListSize
> 0)
966 SetLastError(ERROR_INVALID_PARAMETER
);
971 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
972 KEY_ENUMERATE_SUB_KEYS
,
976 if (hClassesKey
== INVALID_HANDLE_VALUE
)
981 for (dwIndex
= 0; ; dwIndex
++)
984 lError
= RegEnumKeyExW(hClassesKey
,
992 TRACE("RegEnumKeyExW() returns %d\n", lError
);
993 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
995 TRACE("Key name: %p\n", szKeyName
);
997 if (RegOpenKeyExW(hClassesKey
,
1003 RegCloseKey(hClassesKey
);
1007 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
1008 if (!RegQueryValueExW(hClassKey
,
1012 (LPBYTE
)szClassName
,
1015 TRACE("Class name: %p\n", szClassName
);
1017 if (strcmpiW(szClassName
, ClassName
) == 0)
1019 TRACE("Found matching class name\n");
1021 TRACE("Guid: %p\n", szKeyName
);
1022 if (dwGuidListIndex
< ClassGuidListSize
)
1024 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1028 TRACE("Guid: %p\n", &szKeyName
[1]);
1030 UuidFromStringW(&szKeyName
[1],
1031 &ClassGuidList
[dwGuidListIndex
]);
1038 RegCloseKey(hClassKey
);
1041 if (lError
!= ERROR_SUCCESS
)
1045 RegCloseKey(hClassesKey
);
1047 if (RequiredSize
!= NULL
)
1048 *RequiredSize
= dwGuidListIndex
;
1050 if (ClassGuidListSize
< dwGuidListIndex
)
1052 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1059 /***********************************************************************
1060 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1062 BOOL WINAPI
SetupDiClassNameFromGuidA(
1063 const GUID
* ClassGuid
,
1065 DWORD ClassNameSize
,
1066 PDWORD RequiredSize
)
1068 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1069 ClassNameSize
, RequiredSize
,
1073 /***********************************************************************
1074 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1076 BOOL WINAPI
SetupDiClassNameFromGuidW(
1077 const GUID
* ClassGuid
,
1079 DWORD ClassNameSize
,
1080 PDWORD RequiredSize
)
1082 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1083 ClassNameSize
, RequiredSize
,
1087 /***********************************************************************
1088 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1090 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1091 const GUID
* ClassGuid
,
1093 DWORD ClassNameSize
,
1094 PDWORD RequiredSize
,
1098 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1099 LPWSTR MachineNameW
= NULL
;
1103 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1104 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1105 RequiredSize
, MachineNameW
, Reserved
);
1108 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1109 ClassNameSize
, NULL
, NULL
);
1110 if (len
== 0 || len
> ClassNameSize
)
1112 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1116 MyFree(MachineNameW
);
1120 /***********************************************************************
1121 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1123 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1124 const GUID
* ClassGuid
,
1126 DWORD ClassNameSize
,
1127 PDWORD RequiredSize
,
1137 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
1138 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1140 /* Make sure there's a GUID */
1141 if (ClassGuid
== NULL
)
1143 SetLastError(ERROR_INVALID_CLASS
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1147 /* Make sure there's a real buffer when there's a size */
1148 if ((ClassNameSize
> 0) && (ClassName
== NULL
))
1150 SetLastError(ERROR_INVALID_PARAMETER
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1154 /* Open the key for the GUID */
1155 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INSTALLER
, MachineName
, Reserved
);
1157 if (hKey
== INVALID_HANDLE_VALUE
)
1160 /* Retrieve the class name data and close the key */
1161 rc
= QueryRegistryValue(hKey
, REGSTR_VAL_CLASS
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
1164 /* Make sure we got the data */
1165 if (rc
!= ERROR_SUCCESS
)
1171 /* Make sure the data is a string */
1172 if (dwRegType
!= REG_SZ
)
1175 SetLastError(ERROR_GEN_FAILURE
);
1179 /* Determine the length of the class name */
1180 dwLength
/= sizeof(WCHAR
);
1182 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
1183 /* Count the null-terminator */
1186 /* Inform the caller about the class name */
1187 if ((ClassName
!= NULL
) && (dwLength
<= ClassNameSize
))
1189 memcpy(ClassName
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
1190 ClassName
[dwLength
- 1] = UNICODE_NULL
;
1193 /* Inform the caller about the required size */
1194 if (RequiredSize
!= NULL
)
1195 *RequiredSize
= dwLength
;
1197 /* Clean up the buffer */
1200 /* Make sure the buffer was large enough */
1201 if ((ClassName
== NULL
) || (dwLength
> ClassNameSize
))
1203 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1210 /***********************************************************************
1211 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1214 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1217 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1220 /***********************************************************************
1221 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1224 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1229 LPWSTR MachineNameW
= NULL
;
1232 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1233 debugstr_a(MachineName
), Reserved
);
1237 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1238 if (MachineNameW
== NULL
)
1239 return INVALID_HANDLE_VALUE
;
1242 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1243 MachineNameW
, Reserved
);
1245 MyFree(MachineNameW
);
1250 /***********************************************************************
1251 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1253 * Create an empty DeviceInfoSet list.
1256 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1258 * hwndParent [I] hwnd needed for interface related actions.
1259 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1260 * local registry will be used.
1261 * Reserved [I] must be NULL
1264 * Success: empty list.
1265 * Failure: INVALID_HANDLE_VALUE.
1268 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1273 struct DeviceInfoSet
*list
= NULL
;
1274 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1277 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1279 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1280 debugstr_w(MachineName
), Reserved
);
1282 if (MachineName
!= NULL
)
1284 SIZE_T len
= strlenW(MachineName
);
1285 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1287 SetLastError(ERROR_INVALID_MACHINENAME
);
1291 size
+= (len
+ 3) * sizeof(WCHAR
);
1296 if (Reserved
!= NULL
)
1298 SetLastError(ERROR_INVALID_PARAMETER
);
1299 return INVALID_HANDLE_VALUE
;
1302 list
= MyMalloc(size
);
1305 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1306 return INVALID_HANDLE_VALUE
;
1308 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1310 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1311 memcpy(&list
->ClassGuid
,
1312 ClassGuid
? ClassGuid
: &GUID_NULL
,
1313 sizeof(list
->ClassGuid
));
1314 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1315 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1316 list
->InstallParams
.hwndParent
= hwndParent
;
1319 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1320 if (rc
!= ERROR_SUCCESS
)
1322 SetLastError(ERROR_INVALID_MACHINENAME
);
1326 list
->szData
[0] = list
->szData
[1] = '\\';
1327 strcpyW(list
->szData
+ 2, MachineName
);
1328 list
->MachineName
= list
->szData
;
1332 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1333 list
->MachineName
= NULL
;
1335 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1336 if (cr
!= CR_SUCCESS
)
1338 SetLastError(GetErrorCodeFromCrCode(cr
));
1341 InitializeListHead(&list
->DriverListHead
);
1342 InitializeListHead(&list
->ListHead
);
1344 return (HDEVINFO
)list
;
1347 if (ret
== INVALID_HANDLE_VALUE
)
1351 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1352 RegCloseKey(list
->HKLM
);
1359 /***********************************************************************
1360 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1362 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1363 HDEVINFO DeviceInfoSet
,
1364 PSP_DEVINFO_DATA DeviceInfoData
,
1369 PCSTR InfSectionName
)
1371 PWSTR InfSectionNameW
= NULL
;
1374 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1375 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1379 if (!InfSectionName
)
1381 SetLastError(ERROR_INVALID_PARAMETER
);
1382 return INVALID_HANDLE_VALUE
;
1386 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
1387 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1390 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1391 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1392 MyFree(InfSectionNameW
);
1397 OpenHardwareProfileKey(
1400 IN DWORD samDesired
);
1402 /***********************************************************************
1403 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1405 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1406 HDEVINFO DeviceInfoSet
,
1407 PSP_DEVINFO_DATA DeviceInfoData
,
1412 PCWSTR InfSectionName
)
1414 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1415 HKEY key
= INVALID_HANDLE_VALUE
;
1416 LPWSTR lpGuidString
= NULL
;
1417 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
1418 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
1419 DWORD Index
; /* Index used in the DriverKey name */
1423 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1424 HKEY hEnumKey
= NULL
;
1425 HKEY hClassKey
= NULL
;
1426 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
1430 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1431 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1433 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1435 SetLastError(ERROR_INVALID_HANDLE
);
1436 return INVALID_HANDLE_VALUE
;
1438 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1440 SetLastError(ERROR_INVALID_HANDLE
);
1441 return INVALID_HANDLE_VALUE
;
1443 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1444 || !DeviceInfoData
->Reserved
)
1446 SetLastError(ERROR_INVALID_PARAMETER
);
1447 return INVALID_HANDLE_VALUE
;
1449 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1451 SetLastError(ERROR_INVALID_FLAGS
);
1452 return INVALID_HANDLE_VALUE
;
1454 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1456 SetLastError(ERROR_INVALID_FLAGS
);
1457 return INVALID_HANDLE_VALUE
;
1459 if (InfHandle
&& !InfSectionName
)
1461 SetLastError(ERROR_INVALID_PARAMETER
);
1462 return INVALID_HANDLE_VALUE
;
1464 if (!InfHandle
&& InfSectionName
)
1466 SetLastError(ERROR_INVALID_PARAMETER
);
1467 return INVALID_HANDLE_VALUE
;
1470 if (Scope
== DICS_FLAG_GLOBAL
)
1471 RootKey
= set
->HKLM
;
1472 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1474 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1475 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1477 RootKey
= hHWProfileKey
;
1480 if (KeyType
== DIREG_DEV
)
1482 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1484 rc
= RegCreateKeyExW(
1486 REGSTR_PATH_SYSTEMENUM
,
1489 REG_OPTION_NON_VOLATILE
,
1494 if (rc
!= ERROR_SUCCESS
)
1499 rc
= RegCreateKeyExW(
1501 deviceInfo
->instanceId
,
1504 REG_OPTION_NON_VOLATILE
,
1505 #if _WIN32_WINNT >= 0x502
1506 KEY_READ
| KEY_WRITE
,
1513 if (rc
!= ERROR_SUCCESS
)
1519 if (Scope
== DICS_FLAG_GLOBAL
)
1521 HKEY hTempKey
= hKey
;
1523 rc
= RegCreateKeyExW(hTempKey
,
1524 L
"Device Parameters",
1527 REG_OPTION_NON_VOLATILE
,
1528 #if _WIN32_WINNT >= 0x502
1529 KEY_READ
| KEY_WRITE
,
1536 if (rc
== ERROR_SUCCESS
)
1537 RegCloseKey(hTempKey
);
1540 else /* KeyType == DIREG_DRV */
1542 /* Open device key, to read Driver value */
1543 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1544 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
1547 rc
= RegOpenKeyExW(RootKey
, REGSTR_PATH_CLASS_NT
, 0, KEY_CREATE_SUB_KEY
, &hClassKey
);
1548 if (rc
!= ERROR_SUCCESS
)
1554 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, NULL
, &dwSize
);
1555 if (rc
!= ERROR_SUCCESS
)
1557 /* Create a new driver key */
1559 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
1562 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1563 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
1566 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1571 strcpyW(&DriverKey
[1], lpGuidString
);
1572 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
1573 *pDeviceInstance
++ = '}';
1574 *pDeviceInstance
++ = '\\';
1576 /* Try all values for Index between 0 and 9999 */
1578 while (Index
<= 9999)
1580 sprintfW(pDeviceInstance
, InstanceKeyFormat
, Index
);
1581 rc
= RegCreateKeyExW(hClassKey
,
1585 REG_OPTION_NON_VOLATILE
,
1586 #if _WIN32_WINNT >= 0x502
1587 KEY_READ
| KEY_WRITE
,
1594 if (rc
!= ERROR_SUCCESS
)
1599 if (Disposition
== REG_CREATED_NEW_KEY
)
1608 /* Unable to create more than 9999 devices within the same class */
1609 SetLastError(ERROR_GEN_FAILURE
);
1613 /* Write the new Driver value */
1614 rc
= RegSetValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
1615 if (rc
!= ERROR_SUCCESS
)
1624 /* Open the existing driver key */
1626 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
1629 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1633 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, (LPBYTE
)DriverKey
, &dwSize
);
1634 if (rc
!= ERROR_SUCCESS
)
1640 rc
= RegCreateKeyExW(hClassKey
,
1644 REG_OPTION_NON_VOLATILE
,
1645 #if _WIN32_WINNT >= 0x502
1646 KEY_READ
| KEY_WRITE
,
1653 if (rc
!= ERROR_SUCCESS
)
1661 /* Do installation of the specified section */
1664 FIXME("Need to install section %s in file %p\n",
1665 debugstr_w(InfSectionName
), InfHandle
);
1671 RpcStringFreeW(&lpGuidString
);
1672 HeapFree(GetProcessHeap(), 0, DriverKey
);
1673 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1674 RegCloseKey(hHWProfileKey
);
1675 if (hEnumKey
!= NULL
)
1676 RegCloseKey(hEnumKey
);
1677 if (hClassKey
!= NULL
)
1678 RegCloseKey(hClassKey
);
1679 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
1680 RegCloseKey(hDeviceKey
);
1681 if (hKey
!= NULL
&& hKey
!= key
)
1684 TRACE("Returning 0x%p\n", key
);
1688 /***********************************************************************
1689 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1691 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1692 HDEVINFO DeviceInfoSet
,
1694 CONST GUID
*ClassGuid
,
1695 PCSTR DeviceDescription
,
1697 DWORD CreationFlags
,
1698 PSP_DEVINFO_DATA DeviceInfoData
)
1701 LPWSTR DeviceNameW
= NULL
;
1702 LPWSTR DeviceDescriptionW
= NULL
;
1708 DeviceNameW
= pSetupMultiByteToUnicode(DeviceName
, CP_ACP
);
1709 if (DeviceNameW
== NULL
) return FALSE
;
1711 if (DeviceDescription
)
1713 DeviceDescriptionW
= pSetupMultiByteToUnicode(DeviceDescription
, CP_ACP
);
1714 if (DeviceDescriptionW
== NULL
)
1716 MyFree(DeviceNameW
);
1721 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1722 hwndParent
, CreationFlags
, DeviceInfoData
);
1724 MyFree(DeviceNameW
);
1725 MyFree(DeviceDescriptionW
);
1730 /***********************************************************************
1731 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1733 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1734 HDEVINFO DeviceInfoSet
,
1736 CONST GUID
*ClassGuid
,
1737 PCWSTR DeviceDescription
,
1739 DWORD CreationFlags
,
1740 PSP_DEVINFO_DATA DeviceInfoData
)
1742 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1743 struct DeviceInfo
*deviceInfo
= NULL
;
1746 DEVINST RootDevInst
;
1748 WCHAR GenInstanceId
[MAX_DEVICE_ID_LEN
];
1750 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1751 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1752 hwndParent
, CreationFlags
, DeviceInfoData
);
1756 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1759 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1761 SetLastError(ERROR_INVALID_HANDLE
);
1766 SetLastError(ERROR_INVALID_PARAMETER
);
1769 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1771 SetLastError(ERROR_INVALID_HANDLE
);
1774 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1775 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1777 SetLastError(ERROR_CLASS_MISMATCH
);
1780 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1782 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1783 SetLastError(ERROR_INVALID_FLAGS
);
1787 /* Get the root device instance */
1788 cr
= CM_Locate_DevInst_ExW(&RootDevInst
,
1790 CM_LOCATE_DEVINST_NORMAL
,
1792 if (cr
!= CR_SUCCESS
)
1794 SetLastError(ERROR_INVALID_DATA
);
1798 /* Create the new device instance */
1799 cr
= CM_Create_DevInst_ExW(&DevInst
,
1800 (DEVINSTID
)DeviceName
,
1802 (CreationFlags
& DICD_GENERATE_ID
) ?
1803 CM_CREATE_DEVINST_GENERATE_ID
: 0,
1805 if (cr
!= CR_SUCCESS
)
1807 SetLastError(GetErrorCodeFromCrCode(cr
));
1811 if (CreationFlags
& DICD_GENERATE_ID
)
1813 /* Grab the actual instance ID that was created */
1814 cr
= CM_Get_Device_ID_Ex(DevInst
,
1819 if (cr
!= CR_SUCCESS
)
1821 SetLastError(GetErrorCodeFromCrCode(cr
));
1825 DeviceName
= GenInstanceId
;
1826 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName
));
1829 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1831 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1833 if (!DeviceInfoData
)
1837 if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1839 SetLastError(ERROR_INVALID_USER_BUFFER
);
1843 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1844 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1845 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1853 if (deviceInfo
!= NULL
)
1855 /* Remove deviceInfo from List */
1856 RemoveEntryList(&deviceInfo
->ListEntry
);
1858 /* Destroy deviceInfo */
1859 DestroyDeviceInfo(deviceInfo
);
1863 TRACE("Returning %d\n", ret
);
1867 /***********************************************************************
1868 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1870 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1871 HDEVINFO DeviceInfoSet
,
1872 PSP_DEVINFO_DATA DeviceInfoData
,
1874 PSP_DETSIG_CMPPROC CompareProc
,
1875 PVOID CompareContext
,
1876 PSP_DEVINFO_DATA DupDeviceInfoData
)
1878 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1879 WCHAR DevInstId
[MAX_DEVICE_ID_LEN
];
1880 DEVINST ParentDevInst
;
1882 DWORD dwError
= ERROR_SUCCESS
;
1884 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1885 CompareProc
, CompareContext
, DupDeviceInfoData
);
1887 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1889 SetLastError(ERROR_INVALID_HANDLE
);
1892 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1894 SetLastError(ERROR_INVALID_HANDLE
);
1897 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1898 || !DeviceInfoData
->Reserved
)
1900 SetLastError(ERROR_INVALID_PARAMETER
);
1904 if (Flags
& ~SPRDI_FIND_DUPS
)
1906 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~SPRDI_FIND_DUPS
);
1907 SetLastError(ERROR_INVALID_FLAGS
);
1911 if (Flags
& SPRDI_FIND_DUPS
)
1913 FIXME("Unimplemented codepath!\n");
1916 CM_Get_Device_ID_Ex(DeviceInfoData
->DevInst
,
1922 CM_Get_Parent_Ex(&ParentDevInst
,
1923 DeviceInfoData
->DevInst
,
1927 cr
= CM_Create_DevInst_Ex(&DeviceInfoData
->DevInst
,
1930 CM_CREATE_DEVINST_NORMAL
| CM_CREATE_DEVINST_DO_NOT_INSTALL
,
1932 if (cr
!= CR_SUCCESS
&&
1933 cr
!= CR_ALREADY_SUCH_DEVINST
)
1935 dwError
= ERROR_NO_SUCH_DEVINST
;
1938 SetLastError(dwError
);
1940 return (dwError
== ERROR_SUCCESS
);
1943 /***********************************************************************
1944 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1946 BOOL WINAPI
SetupDiEnumDeviceInfo(
1949 PSP_DEVINFO_DATA info
)
1953 TRACE("%p %d %p\n", devinfo
, index
, info
);
1957 SetLastError(ERROR_INVALID_PARAMETER
);
1960 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1962 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1963 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1965 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1966 SetLastError(ERROR_INVALID_USER_BUFFER
);
1969 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1970 while (ItemList
!= &list
->ListHead
&& index
-- > 0)
1971 ItemList
= ItemList
->Flink
;
1972 if (ItemList
== &list
->ListHead
)
1973 SetLastError(ERROR_NO_MORE_ITEMS
);
1976 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1977 memcpy(&info
->ClassGuid
,
1978 &DevInfo
->ClassGuid
,
1980 info
->DevInst
= DevInfo
->dnDevInst
;
1981 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1987 SetLastError(ERROR_INVALID_HANDLE
);
1990 SetLastError(ERROR_INVALID_HANDLE
);
1994 /***********************************************************************
1995 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1997 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1998 HDEVINFO DeviceInfoSet
,
1999 PSP_DEVINFO_DATA DeviceInfoData
,
2000 PSTR DeviceInstanceId
,
2001 DWORD DeviceInstanceIdSize
,
2002 PDWORD RequiredSize
)
2008 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
2009 DeviceInstanceIdSize
, RequiredSize
);
2011 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
2013 SetLastError(ERROR_INVALID_PARAMETER
);
2017 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
2022 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
2024 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
2027 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
2034 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
2036 DeviceInstanceIdSize
, NULL
, NULL
);
2042 if (len
> DeviceInstanceIdSize
)
2044 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2048 *RequiredSize
= len
;
2056 *RequiredSize
= size
;
2057 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2063 /***********************************************************************
2064 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
2066 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
2067 HDEVINFO DeviceInfoSet
,
2068 PSP_DEVINFO_DATA DeviceInfoData
,
2069 PWSTR DeviceInstanceId
,
2070 DWORD DeviceInstanceIdSize
,
2071 PDWORD RequiredSize
)
2073 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2074 struct DeviceInfo
*devInfo
;
2076 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
2077 DeviceInstanceIdSize
, RequiredSize
);
2079 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2081 SetLastError(ERROR_INVALID_HANDLE
);
2084 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2086 SetLastError(ERROR_INVALID_HANDLE
);
2089 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2090 || !DeviceInfoData
->Reserved
)
2092 SetLastError(ERROR_INVALID_PARAMETER
);
2095 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2096 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
2098 SetLastError(ERROR_INVALID_PARAMETER
);
2101 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
2103 SetLastError(ERROR_INVALID_PARAMETER
);
2106 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
2107 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
2109 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2111 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2114 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
2116 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2120 /***********************************************************************
2121 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
2123 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
2125 PCSTR InfSectionName
,
2126 PSTR InfSectionWithExt
,
2127 DWORD InfSectionWithExtSize
,
2128 PDWORD RequiredSize
,
2131 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
2132 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2136 /***********************************************************************
2137 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2139 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
2141 PCWSTR InfSectionName
,
2142 PWSTR InfSectionWithExt
,
2143 DWORD InfSectionWithExtSize
,
2144 PDWORD RequiredSize
,
2147 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
2148 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2152 /***********************************************************************
2153 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2156 SetupDiGetActualSectionToInstallExA(
2158 IN PCSTR InfSectionName
,
2159 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
2160 OUT PSTR InfSectionWithExt OPTIONAL
,
2161 IN DWORD InfSectionWithExtSize
,
2162 OUT PDWORD RequiredSize OPTIONAL
,
2163 OUT PSTR
* Extension OPTIONAL
,
2166 LPWSTR InfSectionNameW
= NULL
;
2167 LPWSTR InfSectionWithExtW
= NULL
;
2169 BOOL bResult
= FALSE
;
2175 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2176 if (InfSectionNameW
== NULL
)
2179 if (InfSectionWithExt
)
2181 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2182 if (InfSectionWithExtW
== NULL
)
2186 bResult
= SetupDiGetActualSectionToInstallExW(
2187 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2188 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2189 InfSectionWithExtSize
,
2191 Extension
? &ExtensionW
: NULL
,
2194 if (bResult
&& InfSectionWithExt
)
2196 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2197 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2199 if (bResult
&& Extension
)
2201 if (ExtensionW
== NULL
)
2204 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2208 MyFree(InfSectionNameW
);
2209 MyFree(InfSectionWithExtW
);
2214 /***********************************************************************
2215 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2217 BOOL WINAPI
SetupDiGetClassDescriptionA(
2218 const GUID
* ClassGuid
,
2219 PSTR ClassDescription
,
2220 DWORD ClassDescriptionSize
,
2221 PDWORD RequiredSize
)
2223 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2224 ClassDescriptionSize
,
2225 RequiredSize
, NULL
, NULL
);
2228 /***********************************************************************
2229 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2231 BOOL WINAPI
SetupDiGetClassDescriptionW(
2232 const GUID
* ClassGuid
,
2233 PWSTR ClassDescription
,
2234 DWORD ClassDescriptionSize
,
2235 PDWORD RequiredSize
)
2237 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2238 ClassDescriptionSize
,
2239 RequiredSize
, NULL
, NULL
);
2242 /***********************************************************************
2243 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2245 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2246 const GUID
* ClassGuid
,
2247 PSTR ClassDescription
,
2248 DWORD ClassDescriptionSize
,
2249 PDWORD RequiredSize
,
2253 PWCHAR ClassDescriptionW
= NULL
;
2254 LPWSTR MachineNameW
= NULL
;
2257 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2258 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2260 if (ClassDescriptionSize
> 0)
2262 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2263 if (!ClassDescriptionW
)
2265 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2272 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
2275 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2280 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2281 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2284 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2285 ClassDescriptionSize
, NULL
, NULL
);
2286 if (len
== 0 || len
> ClassDescriptionSize
)
2288 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2294 MyFree(ClassDescriptionW
);
2295 MyFree(MachineNameW
);
2299 /***********************************************************************
2300 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2302 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2303 const GUID
* ClassGuid
,
2304 PWSTR ClassDescription
,
2305 DWORD ClassDescriptionSize
,
2306 PDWORD RequiredSize
,
2316 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2317 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2319 /* Make sure there's a GUID */
2322 SetLastError(ERROR_INVALID_PARAMETER
);
2326 /* Make sure there's a real buffer when there's a size */
2327 if (!ClassDescription
&& ClassDescriptionSize
> 0)
2329 SetLastError(ERROR_INVALID_PARAMETER
);
2333 /* Open the key for the GUID */
2334 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2339 if (hKey
== INVALID_HANDLE_VALUE
)
2342 /* Retrieve the class description data and close the key */
2343 rc
= QueryRegistryValue(hKey
, NULL
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
2346 /* Make sure we got the data */
2347 if (rc
!= ERROR_SUCCESS
)
2353 /* Make sure the data is a string */
2354 if (dwRegType
!= REG_SZ
)
2357 SetLastError(ERROR_GEN_FAILURE
);
2361 /* Determine the length of the class description */
2362 dwLength
/= sizeof(WCHAR
);
2364 /* Count the null-terminator if none is present */
2365 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
2368 /* Inform the caller about the class description */
2369 if ((ClassDescription
!= NULL
) && (dwLength
<= ClassDescriptionSize
))
2371 memcpy(ClassDescription
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
2372 ClassDescription
[dwLength
- 1] = UNICODE_NULL
;
2375 /* Inform the caller about the required size */
2376 if (RequiredSize
!= NULL
)
2377 *RequiredSize
= dwLength
;
2379 /* Clean up the buffer */
2382 /* Make sure the buffer was large enough */
2383 if ((ClassDescription
== NULL
) || (dwLength
> ClassDescriptionSize
))
2385 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2392 /***********************************************************************
2393 * SetupDiGetClassDevsA (SETUPAPI.@)
2395 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2401 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2402 flags
, NULL
, NULL
, NULL
);
2405 /***********************************************************************
2406 * SetupDiGetClassDevsExA (SETUPAPI.@)
2408 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2418 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2422 enumstrW
= pSetupMultiByteToUnicode(enumstr
, CP_ACP
);
2425 ret
= INVALID_HANDLE_VALUE
;
2431 machineW
= pSetupMultiByteToUnicode(machine
, CP_ACP
);
2435 ret
= INVALID_HANDLE_VALUE
;
2439 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2440 machineW
, reserved
);
2448 /***********************************************************************
2449 * SetupDiGetClassDevsW (SETUPAPI.@)
2451 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2457 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2461 /***********************************************************************
2462 * SetupDiGetClassDevsExW (SETUPAPI.@)
2464 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2473 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2474 struct DeviceInfoSet
*list
;
2475 CONST GUID
*pClassGuid
;
2477 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2479 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2480 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2483 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2485 SetLastError(ERROR_INVALID_PARAMETER
);
2486 return INVALID_HANDLE_VALUE
;
2489 /* Create the deviceset if not set */
2492 list
= (struct DeviceInfoSet
*)deviceset
;
2493 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2495 SetLastError(ERROR_INVALID_HANDLE
);
2498 hDeviceInfo
= deviceset
;
2502 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2503 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2504 NULL
, machine
, NULL
);
2505 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2507 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2510 if (flags
& DIGCF_PROFILE
)
2511 FIXME(": flag DIGCF_PROFILE ignored\n");
2513 if (flags
& DIGCF_DEVICEINTERFACE
)
2517 SetLastError(ERROR_INVALID_PARAMETER
);
2520 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2524 /* Determine which class(es) should be included in the deviceset */
2525 if (flags
& DIGCF_ALLCLASSES
)
2527 /* The caller wants all classes. Check if
2528 * the deviceset limits us to one class */
2529 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2532 pClassGuid
= &list
->ClassGuid
;
2536 /* The caller wants one class. Check if it matches deviceset class */
2537 if (IsEqualIID(&list
->ClassGuid
, class)
2538 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2544 SetLastError(ERROR_INVALID_PARAMETER
);
2548 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2550 /* No class specified. Try to use the one of the deviceset */
2551 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2552 pClassGuid
= &list
->ClassGuid
;
2555 SetLastError(ERROR_INVALID_PARAMETER
);
2561 SetLastError(ERROR_INVALID_PARAMETER
);
2564 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2566 if (rc
!= ERROR_SUCCESS
)
2574 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2575 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2579 /***********************************************************************
2580 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2582 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2583 HDEVINFO DeviceInfoSet
,
2584 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2586 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2588 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2590 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2592 SetLastError(ERROR_INVALID_HANDLE
);
2595 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2597 SetLastError(ERROR_INVALID_HANDLE
);
2601 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2603 SetLastError(ERROR_INVALID_PARAMETER
);
2606 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2607 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2608 if (set
->MachineName
)
2611 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2615 DevInfoData
->RemoteMachineName
[0] = 0;
2620 /***********************************************************************
2621 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2623 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2624 HDEVINFO DeviceInfoSet
,
2625 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2627 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2629 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2631 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2633 SetLastError(ERROR_INVALID_HANDLE
);
2636 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2638 SetLastError(ERROR_INVALID_HANDLE
);
2642 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2644 SetLastError(ERROR_INVALID_PARAMETER
);
2647 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2648 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2649 if (set
->MachineName
)
2650 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2652 DevInfoData
->RemoteMachineName
[0] = 0;
2657 /***********************************************************************
2658 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2660 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2661 HDEVINFO DeviceInfoSet
,
2662 PSP_DEVINFO_DATA DeviceInfoData
,
2663 const GUID
*InterfaceClassGuid
,
2664 PCSTR ReferenceString
,
2665 DWORD CreationFlags
,
2666 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2669 LPWSTR ReferenceStringW
= NULL
;
2671 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2672 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2673 CreationFlags
, DeviceInterfaceData
);
2675 if (ReferenceString
)
2677 ReferenceStringW
= pSetupMultiByteToUnicode(ReferenceString
, CP_ACP
);
2678 if (ReferenceStringW
== NULL
) return FALSE
;
2681 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2682 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2683 DeviceInterfaceData
);
2685 MyFree(ReferenceStringW
);
2690 /***********************************************************************
2691 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2693 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2694 HDEVINFO DeviceInfoSet
,
2695 PSP_DEVINFO_DATA DeviceInfoData
,
2696 const GUID
*InterfaceClassGuid
,
2697 PCWSTR ReferenceString
,
2698 DWORD CreationFlags
,
2699 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2701 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2702 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2703 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2704 CreationFlags
, DeviceInterfaceData
);
2706 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2708 SetLastError(ERROR_INVALID_HANDLE
);
2711 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2713 SetLastError(ERROR_INVALID_HANDLE
);
2716 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2717 || !DeviceInfoData
->Reserved
)
2719 SetLastError(ERROR_INVALID_PARAMETER
);
2722 if (!InterfaceClassGuid
)
2724 SetLastError(ERROR_INVALID_USER_BUFFER
);
2728 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2729 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2730 CreationFlags
, DeviceInterfaceData
);
2731 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2735 /***********************************************************************
2736 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2738 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2739 HDEVINFO DeviceInfoSet
,
2740 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2744 PCSTR InfSectionName
)
2747 PWSTR InfSectionNameW
= NULL
;
2749 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2750 samDesired
, InfHandle
, InfSectionName
);
2753 if (!InfSectionName
)
2755 SetLastError(ERROR_INVALID_PARAMETER
);
2756 return INVALID_HANDLE_VALUE
;
2758 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2759 if (!InfSectionNameW
)
2760 return INVALID_HANDLE_VALUE
;
2762 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2763 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2765 MyFree(InfSectionNameW
);
2769 /***********************************************************************
2770 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2772 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2773 HDEVINFO DeviceInfoSet
,
2774 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2778 PCWSTR InfSectionName
)
2781 LPWSTR SymbolicLink
;
2782 DWORD Length
, Index
;
2784 WCHAR bracedGuidString
[39];
2785 struct DeviceInterface
*DevItf
;
2786 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2788 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2789 samDesired
, InfHandle
, InfSectionName
);
2791 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2792 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2794 SetLastError(ERROR_INVALID_HANDLE
);
2795 return INVALID_HANDLE_VALUE
;
2797 if (!DeviceInterfaceData
||
2798 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2799 !DeviceInterfaceData
->Reserved
)
2801 SetLastError(ERROR_INVALID_PARAMETER
);
2802 return INVALID_HANDLE_VALUE
;
2804 if (InfHandle
&& !InfSectionName
)
2806 SetLastError(ERROR_INVALID_PARAMETER
);
2807 return INVALID_HANDLE_VALUE
;
2810 hKey
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2811 if (hKey
== INVALID_HANDLE_VALUE
)
2813 hKey
= SetupDiOpenClassRegKeyExW(NULL
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2814 if (hKey
== INVALID_HANDLE_VALUE
)
2816 SetLastError(ERROR_INVALID_PARAMETER
);
2817 return INVALID_HANDLE_VALUE
;
2819 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
, bracedGuidString
);
2821 if (RegCreateKeyExW(hKey
, bracedGuidString
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
) != ERROR_SUCCESS
)
2823 SetLastError(ERROR_INVALID_PARAMETER
);
2824 return INVALID_HANDLE_VALUE
;
2830 DevItf
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2832 Length
= (wcslen(DevItf
->SymbolicLink
)+1) * sizeof(WCHAR
);
2833 SymbolicLink
= HeapAlloc(GetProcessHeap(), 0, Length
);
2837 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2838 return INVALID_HANDLE_VALUE
;
2841 wcscpy(SymbolicLink
, DevItf
->SymbolicLink
);
2844 while(SymbolicLink
[Index
])
2846 if (SymbolicLink
[Index
] == L
'\\')
2848 SymbolicLink
[Index
] = L
'#';
2853 rc
= RegCreateKeyExW(hKey
, SymbolicLink
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
);
2856 HeapFree(GetProcessHeap(), 0, SymbolicLink
);
2858 if (rc
== ERROR_SUCCESS
)
2860 if (InfHandle
&& InfSectionName
)
2862 if (!SetupInstallFromInfSection(NULL
/*FIXME */,
2865 SPINST_INIFILES
| SPINST_REGISTRY
| SPINST_INI2REG
| SPINST_FILES
| SPINST_BITREG
| SPINST_REGSVR
| SPINST_UNREGSVR
| SPINST_PROFILEITEMS
| SPINST_COPYINF
,
2869 set
->SelectedDevice
->InstallParams
.InstallMsgHandler
,
2870 set
->SelectedDevice
->InstallParams
.InstallMsgHandlerContext
,
2871 INVALID_HANDLE_VALUE
,
2874 RegCloseKey(hDevKey
);
2875 return INVALID_HANDLE_VALUE
;
2884 /***********************************************************************
2885 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2887 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2888 HDEVINFO DeviceInfoSet
,
2889 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2892 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2895 TRACE("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2897 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2898 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2900 SetLastError(ERROR_INVALID_HANDLE
);
2903 if (!DeviceInterfaceData
||
2904 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2905 !DeviceInterfaceData
->Reserved
)
2907 SetLastError(ERROR_INVALID_PARAMETER
);
2911 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2912 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2916 /***********************************************************************
2917 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2920 * DeviceInfoSet [I] Set of devices from which to enumerate
2922 * DeviceInfoData [I] (Optional) If specified, a specific device
2923 * instance from which to enumerate interfaces.
2924 * If it isn't specified, all interfaces for all
2925 * devices in the set are enumerated.
2926 * InterfaceClassGuid [I] The interface class to enumerate.
2927 * MemberIndex [I] An index of the interface instance to enumerate.
2928 * A caller should start with MemberIndex set to 0,
2929 * and continue until the function fails with
2930 * ERROR_NO_MORE_ITEMS.
2931 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2932 * member must be set to
2933 * sizeof(SP_DEVICE_INTERFACE_DATA).
2936 * Success: non-zero value.
2937 * Failure: FALSE. Call GetLastError() for more info.
2939 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2940 HDEVINFO DeviceInfoSet
,
2941 PSP_DEVINFO_DATA DeviceInfoData
,
2942 CONST GUID
* InterfaceClassGuid
,
2944 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2946 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2949 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet
, DeviceInfoData
,
2950 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2952 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2953 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2955 SetLastError(ERROR_INVALID_HANDLE
);
2958 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2959 !DeviceInfoData
->Reserved
))
2961 SetLastError(ERROR_INVALID_PARAMETER
);
2964 if (!DeviceInterfaceData
||
2965 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2967 SetLastError(ERROR_INVALID_PARAMETER
);
2972 struct DeviceInfo
*devInfo
=
2973 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2975 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2976 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2978 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2979 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2981 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2984 if (MemberIndex
-- == 0)
2986 /* return this item */
2987 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2988 &DevItf
->InterfaceClassGuid
,
2990 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2991 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2995 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2998 SetLastError(ERROR_NO_MORE_ITEMS
);
3003 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
3004 while (ItemList
!= &set
->ListHead
&& !found
)
3006 PLIST_ENTRY InterfaceListEntry
;
3007 struct DeviceInfo
*devInfo
=
3008 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
3009 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
3010 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
3012 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
3013 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
3015 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3018 if (MemberIndex
-- == 0)
3020 /* return this item */
3021 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
3022 &DevItf
->InterfaceClassGuid
,
3024 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
3025 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
3029 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3031 ItemList
= ItemList
->Flink
;
3035 SetLastError(ERROR_NO_MORE_ITEMS
);
3040 /***********************************************************************
3041 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
3043 * Destroy a DeviceInfoList and free all used memory of the list.
3046 * devinfo [I] DeviceInfoList pointer to list to destroy
3049 * Success: non zero value.
3050 * Failure: zero value.
3052 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
3056 TRACE("%p\n", devinfo
);
3057 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
3059 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
3061 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
3063 ret
= DestroyDeviceInfoSet(list
);
3068 SetLastError(ERROR_INVALID_HANDLE
);
3073 /***********************************************************************
3074 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
3076 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
3077 HDEVINFO DeviceInfoSet
,
3078 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3079 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
3080 DWORD DeviceInterfaceDetailDataSize
,
3081 PDWORD RequiredSize
,
3082 PSP_DEVINFO_DATA DeviceInfoData
)
3084 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3085 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
3086 DWORD sizeW
= 0, bytesNeeded
;
3089 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3090 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3091 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3093 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3094 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3096 SetLastError(ERROR_INVALID_HANDLE
);
3099 if (!DeviceInterfaceData
||
3100 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3101 !DeviceInterfaceData
->Reserved
)
3103 SetLastError(ERROR_INVALID_PARAMETER
);
3106 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
3108 SetLastError(ERROR_INVALID_USER_BUFFER
);
3112 if((DeviceInterfaceDetailDataSize
!= 0) &&
3113 (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + sizeof(CHAR
))))
3115 SetLastError(ERROR_INVALID_USER_BUFFER
);
3119 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3121 SetLastError(ERROR_INVALID_USER_BUFFER
);
3126 if (DeviceInterfaceDetailData
!= NULL
)
3128 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
3129 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
3130 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
3131 if (!DeviceInterfaceDetailDataW
)
3133 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3135 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
3137 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
3139 ret
= SetupDiGetDeviceInterfaceDetailW(
3141 DeviceInterfaceData
,
3142 DeviceInterfaceDetailDataW
,
3146 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
3147 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
3149 *RequiredSize
= bytesNeeded
;
3150 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
>= bytesNeeded
)
3152 if (!WideCharToMultiByte(
3154 DeviceInterfaceDetailDataW
->DevicePath
, -1,
3155 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
3162 MyFree(DeviceInterfaceDetailDataW
);
3167 /***********************************************************************
3168 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3170 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
3171 HDEVINFO DeviceInfoSet
,
3172 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3173 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
3174 DWORD DeviceInterfaceDetailDataSize
,
3175 PDWORD RequiredSize
,
3176 PSP_DEVINFO_DATA DeviceInfoData
)
3178 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3181 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3182 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3183 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3185 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3186 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3188 SetLastError(ERROR_INVALID_HANDLE
);
3191 if (!DeviceInterfaceData
||
3192 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3193 !DeviceInterfaceData
->Reserved
)
3195 SetLastError(ERROR_INVALID_PARAMETER
);
3198 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
3200 SetLastError(ERROR_INVALID_USER_BUFFER
);
3203 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3205 SetLastError(ERROR_INVALID_USER_BUFFER
);
3208 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3210 SetLastError(ERROR_INVALID_PARAMETER
);
3213 if ((DeviceInterfaceDetailData
!= NULL
)
3214 && (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) + sizeof(WCHAR
)))
3216 SetLastError(ERROR_INVALID_PARAMETER
);
3221 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
3222 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
3223 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
3224 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
3226 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
3228 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3230 *RequiredSize
= sizeRequired
;
3234 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3235 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3238 memcpy(&DeviceInfoData
->ClassGuid
,
3239 &deviceInterface
->DeviceInfo
->ClassGuid
,
3241 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3242 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3250 struct PropertyMapEntry
3257 static struct PropertyMapEntry PropertyMap
[] = {
3258 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3259 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3260 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3261 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3262 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3263 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3264 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3265 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3266 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3267 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3268 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3269 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3270 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3271 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3272 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3273 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3274 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3275 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3276 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3277 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3278 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3279 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3280 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3281 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3282 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3283 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3284 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3285 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3286 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3287 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3288 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3289 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3290 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3291 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3292 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3295 /***********************************************************************
3296 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3298 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3299 HDEVINFO DeviceInfoSet
,
3300 PSP_DEVINFO_DATA DeviceInfoData
,
3302 PDWORD PropertyRegDataType
,
3303 PBYTE PropertyBuffer
,
3304 DWORD PropertyBufferSize
,
3305 PDWORD RequiredSize
)
3308 BOOL bIsStringProperty
;
3310 DWORD RequiredSizeA
, RequiredSizeW
;
3311 DWORD PropertyBufferSizeW
= 0;
3312 PBYTE PropertyBufferW
= NULL
;
3314 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3315 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3318 if (PropertyBufferSize
!= 0)
3320 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3321 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3322 if (!PropertyBufferW
)
3324 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3329 ret
= SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
3334 PropertyBufferSizeW
,
3337 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3339 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
3341 if (bIsStringProperty
)
3342 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
3344 RequiredSizeA
= RequiredSizeW
;
3346 *RequiredSize
= RequiredSizeA
;
3347 if (PropertyRegDataType
)
3348 *PropertyRegDataType
= RegType
;
3353 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3357 if (RequiredSizeA
<= PropertyBufferSize
)
3359 if (bIsStringProperty
&& PropertyBufferSize
> 0)
3361 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
3363 /* Last error is already set by WideCharToMultiByte */
3368 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
3372 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3376 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3380 /***********************************************************************
3381 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3383 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3384 HDEVINFO DeviceInfoSet
,
3385 PSP_DEVINFO_DATA DeviceInfoData
,
3387 PDWORD PropertyRegDataType
,
3388 PBYTE PropertyBuffer
,
3389 DWORD PropertyBufferSize
,
3390 PDWORD RequiredSize
)
3392 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3393 struct DeviceInfo
*devInfo
;
3395 LONG lError
= ERROR_SUCCESS
;
3398 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3399 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3402 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3404 SetLastError(ERROR_INVALID_HANDLE
);
3407 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3409 SetLastError(ERROR_INVALID_HANDLE
);
3412 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3413 || !DeviceInfoData
->Reserved
)
3415 SetLastError(ERROR_INVALID_PARAMETER
);
3419 if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
3421 SetLastError(ERROR_INVALID_REG_PROPERTY
);
3425 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3427 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3428 && PropertyMap
[Property
].nameW
)
3431 size
= PropertyBufferSize
;
3432 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_QUERY_VALUE
);
3433 if (hKey
== INVALID_HANDLE_VALUE
)
3435 lError
= RegQueryValueExW(hKey
, PropertyMap
[Property
].nameW
,
3436 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3440 *RequiredSize
= size
;
3445 if (PropertyBuffer
== NULL
&& size
!= 0)
3446 lError
= ERROR_INSUFFICIENT_BUFFER
;
3448 case ERROR_MORE_DATA
:
3449 lError
= ERROR_INSUFFICIENT_BUFFER
;
3455 else if (Property
== SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
)
3457 size
= (strlenW(devInfo
->Data
) + 1) * sizeof(WCHAR
);
3459 if (PropertyRegDataType
)
3460 *PropertyRegDataType
= REG_SZ
;
3462 *RequiredSize
= size
;
3463 if (PropertyBufferSize
>= size
)
3465 strcpyW((LPWSTR
)PropertyBuffer
, devInfo
->Data
);
3468 lError
= ERROR_INSUFFICIENT_BUFFER
;
3472 size
= PropertyBufferSize
;
3474 cr
= CM_Get_DevNode_Registry_Property_ExW(devInfo
->dnDevInst
,
3475 Property
+ (CM_DRP_DEVICEDESC
- SPDRP_DEVICEDESC
),
3476 PropertyRegDataType
,
3481 if ((cr
== CR_SUCCESS
) || (cr
== CR_BUFFER_SMALL
))
3484 *RequiredSize
= size
;
3487 if (cr
!= CR_SUCCESS
)
3491 case CR_INVALID_DEVINST
:
3492 lError
= ERROR_NO_SUCH_DEVINST
;
3495 case CR_INVALID_PROPERTY
:
3496 lError
= ERROR_INVALID_REG_PROPERTY
;
3499 case CR_BUFFER_SMALL
:
3500 lError
= ERROR_INSUFFICIENT_BUFFER
;
3504 lError
= ERROR_INVALID_DATA
;
3510 SetLastError(lError
);
3511 return (lError
== ERROR_SUCCESS
);
3514 /***********************************************************************
3515 * Internal for SetupDiSetDeviceRegistryPropertyA/W
3517 BOOL WINAPI
IntSetupDiSetDeviceRegistryPropertyAW(
3518 HDEVINFO DeviceInfoSet
,
3519 PSP_DEVINFO_DATA DeviceInfoData
,
3521 const BYTE
*PropertyBuffer
,
3522 DWORD PropertyBufferSize
,
3526 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3528 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3529 PropertyBuffer
, PropertyBufferSize
);
3531 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3533 SetLastError(ERROR_INVALID_HANDLE
);
3536 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3538 SetLastError(ERROR_INVALID_HANDLE
);
3541 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3542 || !DeviceInfoData
->Reserved
)
3544 SetLastError(ERROR_INVALID_PARAMETER
);
3547 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3548 && PropertyMap
[Property
].nameW
3549 && PropertyMap
[Property
].nameA
)
3553 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3554 if (hKey
== INVALID_HANDLE_VALUE
)
3556 /* Write new data */
3560 hKey
, PropertyMap
[Property
].nameA
, 0,
3561 PropertyMap
[Property
].regType
, PropertyBuffer
,
3562 PropertyBufferSize
);
3567 hKey
, PropertyMap
[Property
].nameW
, 0,
3568 PropertyMap
[Property
].regType
, PropertyBuffer
,
3569 PropertyBufferSize
);
3579 ERR("Property 0x%lx not implemented\n", Property
);
3580 SetLastError(ERROR_NOT_SUPPORTED
);
3583 TRACE("Returning %d\n", ret
);
3586 /***********************************************************************
3587 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3589 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3590 HDEVINFO DeviceInfoSet
,
3591 PSP_DEVINFO_DATA DeviceInfoData
,
3593 const BYTE
*PropertyBuffer
,
3594 DWORD PropertyBufferSize
)
3596 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet
,
3604 /***********************************************************************
3605 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3607 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3608 HDEVINFO DeviceInfoSet
,
3609 PSP_DEVINFO_DATA DeviceInfoData
,
3611 const BYTE
*PropertyBuffer
,
3612 DWORD PropertyBufferSize
)
3614 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet
,
3622 /***********************************************************************
3623 * SetupDiInstallClassA (SETUPAPI.@)
3625 BOOL WINAPI
SetupDiInstallClassA(
3631 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3634 /***********************************************************************
3635 * SetupDiInstallClassExA (SETUPAPI.@)
3638 SetupDiInstallClassExA(
3639 IN HWND hwndParent OPTIONAL
,
3640 IN PCSTR InfFileName OPTIONAL
,
3642 IN HSPFILEQ FileQueue OPTIONAL
,
3643 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3647 PWSTR InfFileNameW
= NULL
;
3652 SetLastError(ERROR_INVALID_PARAMETER
);
3657 InfFileNameW
= pSetupMultiByteToUnicode(InfFileName
, CP_ACP
);
3658 if (InfFileNameW
== NULL
)
3660 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3665 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3666 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3668 MyFree(InfFileNameW
);
3673 HKEY
SETUP_CreateClassKey(HINF hInf
)
3675 WCHAR FullBuffer
[MAX_PATH
];
3676 WCHAR Buffer
[MAX_PATH
];
3681 /* Obtain the Class GUID for this class */
3682 if (!SetupGetLineTextW(NULL
,
3685 REGSTR_VAL_CLASSGUID
,
3687 sizeof(Buffer
) / sizeof(WCHAR
),
3690 return INVALID_HANDLE_VALUE
;
3693 /* Build the corresponding registry key name */
3694 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3695 lstrcatW(FullBuffer
, BackSlash
);
3696 lstrcatW(FullBuffer
, Buffer
);
3698 /* Obtain the Class name for this class */
3699 if (!SetupGetLineTextW(NULL
,
3704 sizeof(Buffer
) / sizeof(WCHAR
),
3707 return INVALID_HANDLE_VALUE
;
3710 /* Try to open or create the registry key */
3711 TRACE("Opening class key %s\n", debugstr_w(FullBuffer
));
3712 #if 0 // I keep this for reference...
3713 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3719 /* Use RegCreateKeyExW */
3722 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3726 REG_OPTION_NON_VOLATILE
,
3732 ERR("RegCreateKeyExW(%s) failed\n", debugstr_w(FullBuffer
));
3733 return INVALID_HANDLE_VALUE
;
3735 if (Disposition
== REG_CREATED_NEW_KEY
)
3736 TRACE("The class key %s was successfully created\n", debugstr_w(FullBuffer
));
3738 TRACE("The class key %s was successfully opened\n", debugstr_w(FullBuffer
));
3740 TRACE( "setting value %s to %s\n", debugstr_w(REGSTR_VAL_CLASS
), debugstr_w(Buffer
) );
3741 if (RegSetValueExW(hClassKey
,
3746 RequiredSize
* sizeof(WCHAR
)))
3748 RegCloseKey(hClassKey
);
3749 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3751 return INVALID_HANDLE_VALUE
;
3757 /***********************************************************************
3758 * SetupDiInstallClassW (SETUPAPI.@)
3760 BOOL WINAPI
SetupDiInstallClassW(
3766 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3770 /***********************************************************************
3771 * SetupDiOpenClassRegKey (SETUPAPI.@)
3773 HKEY WINAPI
SetupDiOpenClassRegKey(
3774 const GUID
* ClassGuid
,
3777 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3778 DIOCR_INSTALLER
, NULL
, NULL
);
3782 /***********************************************************************
3783 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3785 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3786 const GUID
* ClassGuid
,
3792 PWSTR MachineNameW
= NULL
;
3795 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3796 Flags
, debugstr_a(MachineName
), Reserved
);
3800 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
3801 if (MachineNameW
== NULL
)
3802 return INVALID_HANDLE_VALUE
;
3805 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3806 Flags
, MachineNameW
, Reserved
);
3808 MyFree(MachineNameW
);
3814 /***********************************************************************
3815 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3817 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3818 const GUID
* ClassGuid
,
3830 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3831 Flags
, debugstr_w(MachineName
), Reserved
);
3833 if (MachineName
!= NULL
)
3835 l
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3836 if (l
!= ERROR_SUCCESS
)
3839 return INVALID_HANDLE_VALUE
;
3843 HKLM
= HKEY_LOCAL_MACHINE
;
3845 if (Flags
== DIOCR_INSTALLER
)
3847 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3849 else if (Flags
== DIOCR_INTERFACE
)
3851 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3855 ERR("Invalid Flags parameter!\n");
3856 SetLastError(ERROR_INVALID_FLAGS
);
3857 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3858 return INVALID_HANDLE_VALUE
;
3863 if ((l
= RegOpenKeyExW(HKLM
,
3869 SetLastError(ERROR_INVALID_CLASS
);
3870 hClassesKey
= INVALID_HANDLE_VALUE
;
3872 if (MachineName
!= NULL
)
3878 WCHAR bracedGuidString
[39];
3880 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3882 if (!(l
= RegOpenKeyExW(HKLM
,
3888 if (MachineName
!= NULL
)
3891 if ((l
= RegOpenKeyExW(hClassesKey
,
3898 key
= INVALID_HANDLE_VALUE
;
3900 RegCloseKey(hClassesKey
);
3904 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3906 key
= INVALID_HANDLE_VALUE
;
3913 /***********************************************************************
3914 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3916 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3917 HDEVINFO DeviceInfoSet
,
3920 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3922 struct DeviceInfoSet
* list
;
3924 DWORD dwLength
, dwError
, dwIndex
, dwKeyName
, dwSubIndex
;
3926 WCHAR Buffer
[MAX_PATH
+ 1];
3927 WCHAR SymBuffer
[MAX_PATH
+ 1];
3928 WCHAR InstancePath
[MAX_PATH
+ 1];
3929 HKEY hKey
, hDevKey
, hSymKey
;
3930 struct DeviceInfo
* deviceInfo
;
3931 struct DeviceInterface
*deviceInterface
;
3933 PLIST_ENTRY ItemList
;
3934 PLIST_ENTRY InterfaceListEntry
;
3936 TRACE("%p %s %08x %p\n",
3937 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3940 if (DeviceInterfaceData
&& DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
3942 SetLastError(ERROR_INVALID_PARAMETER
);
3946 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3948 SetLastError(ERROR_INVALID_HANDLE
);
3952 list
= (struct DeviceInfoSet
* )DeviceInfoSet
;
3954 dwLength
= wcslen(DevicePath
);
3957 /* path must be at least a guid length + L'\0' */
3958 SetLastError(ERROR_BAD_PATHNAME
);
3962 if (DevicePath
[0] != L
'\\' ||
3963 DevicePath
[1] != L
'\\' ||
3964 (DevicePath
[2] != L
'?' && DevicePath
[2] != L
'.') ||
3965 DevicePath
[3] != L
'\\')
3967 /* invalid formatted path */
3968 SetLastError(ERROR_BAD_PATHNAME
);
3972 /* check for reference strings */
3973 pEnd
= wcschr(&DevicePath
[4], L
'\\');
3976 /* no reference string */
3977 pEnd
= DevicePath
+ dwLength
;
3981 wcscpy(Buffer
, pEnd
- 37);
3984 dwError
= UuidFromStringW(Buffer
, &ClassId
);
3985 if (dwError
!= NOERROR
)
3987 /* invalid formatted path */
3988 SetLastError(ERROR_BAD_PATHNAME
);
3992 hKey
= SetupDiOpenClassRegKeyExW(&ClassId
, KEY_READ
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
3994 if (hKey
== INVALID_HANDLE_VALUE
)
3996 /* invalid device class */
4000 ItemList
= list
->ListHead
.Flink
;
4001 while (ItemList
!= &list
->ListHead
)
4003 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
4004 InterfaceListEntry
= deviceInfo
->InterfaceListHead
.Flink
;
4005 while (InterfaceListEntry
!= &deviceInfo
->InterfaceListHead
)
4007 deviceInterface
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
4008 if (!IsEqualIID(&deviceInterface
->InterfaceClassGuid
, &ClassId
))
4010 InterfaceListEntry
= InterfaceListEntry
->Flink
;
4014 if (!wcsicmp(deviceInterface
->SymbolicLink
, DevicePath
))
4016 if (DeviceInterfaceData
)
4018 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
4019 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
4020 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
4034 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
4035 dwError
= RegEnumKeyExW(hKey
, dwIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
4037 if (dwError
!= ERROR_SUCCESS
)
4040 if (RegOpenKeyExW(hKey
, Buffer
, 0, KEY_READ
, &hDevKey
) != ERROR_SUCCESS
)
4044 InstancePath
[0] = 0;
4045 dwKeyName
= sizeof(InstancePath
);
4047 dwError
= RegQueryValueExW(hDevKey
, L
"DeviceInstance", NULL
, NULL
, (LPBYTE
)InstancePath
, &dwKeyName
);
4052 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
4053 dwError
= RegEnumKeyExW(hDevKey
, dwSubIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
4055 if (dwError
!= ERROR_SUCCESS
)
4058 dwError
= RegOpenKeyExW(hDevKey
, Buffer
, 0, KEY_READ
, &hSymKey
);
4059 if (dwError
!= ERROR_SUCCESS
)
4062 /* query for symbolic link */
4063 dwKeyName
= sizeof(SymBuffer
);
4064 SymBuffer
[0] = L
'\0';
4065 dwError
= RegQueryValueExW(hSymKey
, L
"SymbolicLink", NULL
, NULL
, (LPBYTE
)SymBuffer
, &dwKeyName
);
4067 if (dwError
!= ERROR_SUCCESS
)
4069 RegCloseKey(hSymKey
);
4073 if (!wcsicmp(SymBuffer
, DevicePath
))
4075 Ret
= CreateDeviceInfo(list
, InstancePath
, &ClassId
, &deviceInfo
);
4076 RegCloseKey(hSymKey
);
4077 RegCloseKey(hDevKey
);
4082 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymBuffer
) + 1) * sizeof(WCHAR
));
4083 if (deviceInterface
)
4086 CopyMemory(&deviceInterface
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
4087 deviceInterface
->DeviceInfo
= deviceInfo
;
4088 deviceInterface
->Flags
= SPINT_ACTIVE
; //FIXME
4090 wcscpy(deviceInterface
->SymbolicLink
, SymBuffer
);
4092 InsertTailList(&deviceInfo
->InterfaceListHead
, &deviceInterface
->ListEntry
);
4093 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4096 if (DeviceInterfaceData
)
4098 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
4099 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
4100 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
4105 SetLastError(ERROR_INVALID_USER_BUFFER
);
4111 HeapFree(GetProcessHeap(), 0, deviceInfo
);
4116 RegCloseKey(hSymKey
);
4120 RegCloseKey(hDevKey
);
4128 /***********************************************************************
4129 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
4131 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
4132 HDEVINFO DeviceInfoSet
,
4135 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
4137 LPWSTR DevicePathW
= NULL
;
4140 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
4142 DevicePathW
= pSetupMultiByteToUnicode(DevicePath
, CP_ACP
);
4143 if (DevicePathW
== NULL
)
4146 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
4147 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
4149 MyFree(DevicePathW
);
4154 /***********************************************************************
4155 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
4157 BOOL WINAPI
SetupDiSetClassInstallParamsA(
4158 HDEVINFO DeviceInfoSet
,
4159 PSP_DEVINFO_DATA DeviceInfoData
,
4160 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
4161 DWORD ClassInstallParamsSize
)
4163 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
4164 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
4169 IntSetupDiRegisterDeviceInfo(
4170 IN HDEVINFO DeviceInfoSet
,
4171 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
4173 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
4176 /***********************************************************************
4177 * SetupDiCallClassInstaller (SETUPAPI.@)
4179 BOOL WINAPI
SetupDiCallClassInstaller(
4180 DI_FUNCTION InstallFunction
,
4181 HDEVINFO DeviceInfoSet
,
4182 PSP_DEVINFO_DATA DeviceInfoData
)
4186 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4189 SetLastError(ERROR_INVALID_PARAMETER
);
4190 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4191 SetLastError(ERROR_INVALID_HANDLE
);
4192 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4193 SetLastError(ERROR_INVALID_HANDLE
);
4194 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
4195 SetLastError(ERROR_INVALID_HANDLE
);
4196 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4197 SetLastError(ERROR_INVALID_USER_BUFFER
);
4200 SP_DEVINSTALL_PARAMS_W InstallParams
;
4201 #define CLASS_COINSTALLER 0x1
4202 #define DEVICE_COINSTALLER 0x2
4203 #define CLASS_INSTALLER 0x4
4204 UCHAR CanHandle
= 0;
4205 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
4207 switch (InstallFunction
)
4209 case DIF_ADDPROPERTYPAGE_ADVANCED
:
4210 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4212 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
4213 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4215 case DIF_ALLOW_INSTALL
:
4216 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4219 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4221 case DIF_DESTROYPRIVATEDATA
:
4222 CanHandle
= CLASS_INSTALLER
;
4224 case DIF_INSTALLDEVICE
:
4225 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4226 DefaultHandler
= SetupDiInstallDevice
;
4228 case DIF_INSTALLDEVICEFILES
:
4229 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4230 DefaultHandler
= SetupDiInstallDriverFiles
;
4232 case DIF_INSTALLINTERFACES
:
4233 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4234 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
4236 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
4237 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4239 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
4240 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4242 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
4243 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4245 case DIF_NEWDEVICEWIZARD_PRESELECT
:
4246 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4248 case DIF_NEWDEVICEWIZARD_SELECT
:
4249 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4251 case DIF_POWERMESSAGEWAKE
:
4252 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4254 case DIF_PROPERTYCHANGE
:
4255 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4256 DefaultHandler
= SetupDiChangeState
;
4258 case DIF_REGISTER_COINSTALLERS
:
4259 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4260 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
4262 case DIF_REGISTERDEVICE
:
4263 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4264 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
4267 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4268 DefaultHandler
= SetupDiRemoveDevice
;
4270 case DIF_SELECTBESTCOMPATDRV
:
4271 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4272 DefaultHandler
= SetupDiSelectBestCompatDrv
;
4274 case DIF_SELECTDEVICE
:
4275 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4276 DefaultHandler
= SetupDiSelectDevice
;
4278 case DIF_TROUBLESHOOTER
:
4279 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4282 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4283 DefaultHandler
= SetupDiUnremoveDevice
;
4286 ERR("Install function %u not supported\n", InstallFunction
);
4287 SetLastError(ERROR_NOT_SUPPORTED
);
4290 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4291 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4292 /* Don't process this call, as a parameter is invalid */
4297 LIST_ENTRY ClassCoInstallersListHead
;
4298 LIST_ENTRY DeviceCoInstallersListHead
;
4299 HMODULE ClassInstallerLibrary
= NULL
;
4300 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
4301 COINSTALLER_CONTEXT_DATA Context
;
4302 PLIST_ENTRY ListEntry
;
4304 DWORD dwRegType
, dwLength
;
4305 DWORD rc
= NO_ERROR
;
4307 InitializeListHead(&ClassCoInstallersListHead
);
4308 InitializeListHead(&DeviceCoInstallersListHead
);
4310 if (CanHandle
& DEVICE_COINSTALLER
)
4312 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4313 if (hKey
!= INVALID_HANDLE_VALUE
)
4315 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4316 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4318 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4319 if (KeyBuffer
!= NULL
)
4321 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4322 if (rc
== ERROR_SUCCESS
)
4325 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4327 /* Add coinstaller to DeviceCoInstallersListHead list */
4328 struct CoInstallerElement
*coinstaller
;
4329 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
4330 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4333 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4334 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4335 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
4337 HeapFree(GetProcessHeap(), 0, coinstaller
);
4340 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4346 if (CanHandle
& CLASS_COINSTALLER
)
4350 REGSTR_PATH_CODEVICEINSTALLERS
,
4354 if (rc
== ERROR_SUCCESS
)
4356 WCHAR szGuidString
[40];
4357 if (pSetupStringFromGuid(&DeviceInfoData
->ClassGuid
, szGuidString
, ARRAYSIZE(szGuidString
)) == ERROR_SUCCESS
)
4359 rc
= RegQueryValueExW(hKey
, szGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
4360 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4362 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4363 if (KeyBuffer
!= NULL
)
4365 rc
= RegQueryValueExW(hKey
, szGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4366 if (rc
== ERROR_SUCCESS
)
4369 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4371 /* Add coinstaller to ClassCoInstallersListHead list */
4372 struct CoInstallerElement
*coinstaller
;
4373 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
4374 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4377 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4378 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4379 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
4381 HeapFree(GetProcessHeap(), 0, coinstaller
);
4384 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4391 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4393 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4394 if (hKey
!= INVALID_HANDLE_VALUE
)
4396 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4397 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4399 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4400 if (KeyBuffer
!= NULL
)
4402 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4403 if (rc
== ERROR_SUCCESS
)
4405 /* Get ClassInstaller function pointer */
4406 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4407 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4409 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4410 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4413 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4420 /* Call Class co-installers */
4421 Context
.PostProcessing
= FALSE
;
4423 ListEntry
= ClassCoInstallersListHead
.Flink
;
4424 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4426 struct CoInstallerElement
*coinstaller
;
4427 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4428 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4429 coinstaller
->PrivateData
= Context
.PrivateData
;
4430 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4432 coinstaller
->DoPostProcessing
= TRUE
;
4435 ListEntry
= ListEntry
->Flink
;
4438 /* Call Device co-installers */
4439 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4440 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4442 struct CoInstallerElement
*coinstaller
;
4443 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4444 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4445 coinstaller
->PrivateData
= Context
.PrivateData
;
4446 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4448 coinstaller
->DoPostProcessing
= TRUE
;
4451 ListEntry
= ListEntry
->Flink
;
4454 /* Call Class installer */
4457 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4458 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4461 rc
= ERROR_DI_DO_DEFAULT
;
4463 /* Call default handler */
4464 if (rc
== ERROR_DI_DO_DEFAULT
)
4466 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4468 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4471 rc
= GetLastError();
4477 /* Call Class co-installers that required postprocessing */
4478 Context
.PostProcessing
= TRUE
;
4479 ListEntry
= ClassCoInstallersListHead
.Flink
;
4480 while (ListEntry
!= &ClassCoInstallersListHead
)
4482 struct CoInstallerElement
*coinstaller
;
4483 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4484 if (coinstaller
->DoPostProcessing
)
4486 Context
.InstallResult
= rc
;
4487 Context
.PrivateData
= coinstaller
->PrivateData
;
4488 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4490 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4491 ListEntry
= ListEntry
->Flink
;
4494 /* Call Device co-installers that required postprocessing */
4495 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4496 while (ListEntry
!= &DeviceCoInstallersListHead
)
4498 struct CoInstallerElement
*coinstaller
;
4499 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4500 if (coinstaller
->DoPostProcessing
)
4502 Context
.InstallResult
= rc
;
4503 Context
.PrivateData
= coinstaller
->PrivateData
;
4504 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4506 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4507 ListEntry
= ListEntry
->Flink
;
4510 /* Free allocated memory */
4511 while (!IsListEmpty(&ClassCoInstallersListHead
))
4513 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4514 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4516 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4518 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4519 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4522 ret
= (rc
== NO_ERROR
);
4526 TRACE("Returning %d\n", ret
);
4530 /***********************************************************************
4531 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4533 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4534 HDEVINFO DeviceInfoSet
,
4535 PSP_DEVINFO_DATA DeviceInfoData
,
4536 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4538 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4541 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4543 if (DeviceInstallParams
== NULL
)
4544 SetLastError(ERROR_INVALID_PARAMETER
);
4545 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4546 SetLastError(ERROR_INVALID_USER_BUFFER
);
4549 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4550 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4554 /* Do W->A conversion */
4556 DeviceInstallParams
,
4557 &deviceInstallParamsW
,
4558 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4559 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4560 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4562 DeviceInstallParams
->DriverPath
[0] = '\0';
4568 TRACE("Returning %d\n", ret
);
4572 /***********************************************************************
4573 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4576 SetupDiGetDeviceInfoListClass(
4577 IN HDEVINFO DeviceInfoSet
,
4578 OUT LPGUID ClassGuid
)
4580 struct DeviceInfoSet
*list
;
4583 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4586 SetLastError(ERROR_INVALID_HANDLE
);
4587 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4588 SetLastError(ERROR_INVALID_HANDLE
);
4589 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4590 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4593 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4598 TRACE("Returning %d\n", ret
);
4602 /***********************************************************************
4603 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4606 SetupDiGetDeviceInstallParamsW(
4607 IN HDEVINFO DeviceInfoSet
,
4608 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4609 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4611 struct DeviceInfoSet
*list
;
4614 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4617 SetLastError(ERROR_INVALID_HANDLE
);
4618 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4619 SetLastError(ERROR_INVALID_HANDLE
);
4620 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4621 SetLastError(ERROR_INVALID_USER_BUFFER
);
4622 else if (!DeviceInstallParams
)
4623 SetLastError(ERROR_INVALID_PARAMETER
);
4624 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4625 SetLastError(ERROR_INVALID_USER_BUFFER
);
4628 PSP_DEVINSTALL_PARAMS_W Source
;
4631 Source
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4633 Source
= &list
->InstallParams
;
4639 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4641 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4643 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4649 TRACE("Returning %d\n", ret
);
4654 CheckDeviceInstallParameters(
4655 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4657 DWORD SupportedFlags
=
4658 DI_NOVCP
| /* 0x00000008 */
4659 DI_DIDCOMPAT
| /* 0x00000010 */
4660 DI_DIDCLASS
| /* 0x00000020 */
4661 DI_NEEDRESTART
| /* 0x00000080 */
4662 DI_NEEDREBOOT
| /* 0x00000100 */
4663 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4664 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4665 DI_ENUMSINGLEINF
| /* 0x00010000 */
4666 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
4667 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4668 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4669 DI_QUIETINSTALL
| /* 0x00800000 */
4670 DI_NOFILECOPY
| /* 0x01000000 */
4671 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4672 DWORD SupportedFlagsEx
=
4673 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4674 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4675 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4676 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4677 DI_FLAGSEX_NO_DRVREG_MODIFY
| /* 0x00008000 */
4678 DI_FLAGSEX_INSTALLEDDRIVER
; /* 0x04000000 */
4681 /* FIXME: add support for more flags */
4683 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4684 * It should be checked before accessing to other values
4685 * of the SP_DEVINSTALL_PARAMS structure */
4687 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4689 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4690 SetLastError(ERROR_INVALID_FLAGS
);
4692 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4694 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4695 SetLastError(ERROR_INVALID_FLAGS
);
4697 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4698 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4699 SetLastError(ERROR_INVALID_USER_BUFFER
);
4702 /* FIXME: check Reserved field */
4709 /***********************************************************************
4710 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4713 SetupDiSetDeviceInstallParamsW(
4714 IN HDEVINFO DeviceInfoSet
,
4715 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4716 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4718 struct DeviceInfoSet
*list
;
4721 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4724 SetLastError(ERROR_INVALID_HANDLE
);
4725 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4726 SetLastError(ERROR_INVALID_HANDLE
);
4727 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4728 SetLastError(ERROR_INVALID_USER_BUFFER
);
4729 else if (!DeviceInstallParams
)
4730 SetLastError(ERROR_INVALID_PARAMETER
);
4731 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4732 SetLastError(ERROR_INVALID_USER_BUFFER
);
4733 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4735 PSP_DEVINSTALL_PARAMS_W Destination
;
4738 Destination
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4740 Destination
= &list
->InstallParams
;
4741 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4745 TRACE("Returning %d\n", ret
);
4749 /***********************************************************************
4750 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4753 SetupDiSetDeviceInstallParamsA(
4754 HDEVINFO DeviceInfoSet
,
4755 PSP_DEVINFO_DATA DeviceInfoData
,
4756 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4758 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4762 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4764 if (DeviceInstallParams
== NULL
)
4765 SetLastError(ERROR_INVALID_PARAMETER
);
4766 else if (DeviceInstallParams
->cbSize
< sizeof(SP_DEVINSTALL_PARAMS_A
))
4767 SetLastError(ERROR_INVALID_USER_BUFFER
);
4770 memcpy(&deviceInstallParamsW
, DeviceInstallParams
, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A
, DriverPath
));
4771 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4772 len
= MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, NULL
, 0);
4775 ERR("DrivePath is NULL\n");
4780 MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, deviceInstallParamsW
.DriverPath
, len
);
4781 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4785 TRACE("Returning %d\n", ret
);
4790 OpenHardwareProfileKey(
4793 IN DWORD samDesired
)
4795 HKEY hHWProfilesKey
= NULL
;
4796 HKEY hHWProfileKey
= NULL
;
4797 HKEY ret
= INVALID_HANDLE_VALUE
;
4800 rc
= RegOpenKeyExW(HKLM
,
4801 REGSTR_PATH_HWPROFILES
,
4805 if (rc
!= ERROR_SUCCESS
)
4812 rc
= RegOpenKeyExW(hHWProfilesKey
,
4821 snprintfW(subKey
, 4, InstanceKeyFormat
, HwProfile
);
4823 rc
= RegOpenKeyExW(hHWProfilesKey
,
4829 if (rc
!= ERROR_SUCCESS
)
4834 ret
= hHWProfileKey
;
4837 if (hHWProfilesKey
!= NULL
)
4838 RegCloseKey(hHWProfilesKey
);
4839 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4840 RegCloseKey(hHWProfileKey
);
4845 IsDeviceInfoInDeviceInfoSet(
4846 struct DeviceInfoSet
*deviceInfoSet
,
4847 struct DeviceInfo
*deviceInfo
)
4849 PLIST_ENTRY ListEntry
;
4851 ListEntry
= deviceInfoSet
->ListHead
.Flink
;
4852 while (ListEntry
!= &deviceInfoSet
->ListHead
)
4854 if (deviceInfo
== CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
))
4857 ListEntry
= ListEntry
->Flink
;
4863 /***********************************************************************
4864 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4867 SetupDiDeleteDeviceInfo(
4868 IN HDEVINFO DeviceInfoSet
,
4869 IN PSP_DEVINFO_DATA DeviceInfoData
)
4871 struct DeviceInfoSet
*deviceInfoSet
;
4872 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
;
4875 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4878 SetLastError(ERROR_INVALID_HANDLE
);
4879 else if ((deviceInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4880 SetLastError(ERROR_INVALID_HANDLE
);
4881 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4882 SetLastError(ERROR_INVALID_USER_BUFFER
);
4883 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet
, deviceInfo
))
4884 SetLastError(ERROR_INVALID_PARAMETER
);
4887 RemoveEntryList(&deviceInfo
->ListEntry
);
4888 DestroyDeviceInfo(deviceInfo
);
4896 /***********************************************************************
4897 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4900 SetupDiOpenDeviceInfoA(
4901 IN HDEVINFO DeviceInfoSet
,
4902 IN PCSTR DeviceInstanceId
,
4903 IN HWND hwndParent OPTIONAL
,
4905 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4907 LPWSTR DeviceInstanceIdW
= NULL
;
4910 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4912 DeviceInstanceIdW
= pSetupMultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4913 if (DeviceInstanceIdW
== NULL
)
4916 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4917 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4919 MyFree(DeviceInstanceIdW
);
4925 /***********************************************************************
4926 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4929 SetupDiOpenDeviceInfoW(
4930 IN HDEVINFO DeviceInfoSet
,
4931 IN PCWSTR DeviceInstanceId
,
4932 IN HWND hwndParent OPTIONAL
,
4934 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4936 struct DeviceInfoSet
*list
;
4937 HKEY hEnumKey
, hKey
= NULL
;
4941 TRACE("%p %s %p %lx %p\n",
4942 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
4943 hwndParent
, OpenFlags
, DeviceInfoData
);
4945 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4946 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4949 SetLastError(ERROR_INVALID_HANDLE
);
4950 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4951 SetLastError(ERROR_INVALID_HANDLE
);
4952 else if (!DeviceInstanceId
)
4953 SetLastError(ERROR_INVALID_PARAMETER
);
4954 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4956 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4957 SetLastError(ERROR_INVALID_FLAGS
);
4959 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4960 SetLastError(ERROR_INVALID_USER_BUFFER
);
4963 struct DeviceInfo
*deviceInfo
= NULL
;
4964 /* Search if device already exists in DeviceInfoSet.
4965 * If yes, return the existing element
4966 * If no, create a new element using information in registry
4968 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4969 while (ItemList
!= &list
->ListHead
)
4971 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
4972 if (!wcscmp(deviceInfo
->instanceId
, DeviceInstanceId
))
4975 ItemList
= ItemList
->Flink
;
4980 /* good one found */
4986 WCHAR szClassGuid
[MAX_GUID_STRING_LEN
];
4988 /* Open supposed registry key */
4991 REGSTR_PATH_SYSTEMENUM
,
4995 if (rc
!= ERROR_SUCCESS
)
5006 RegCloseKey(hEnumKey
);
5007 if (rc
!= ERROR_SUCCESS
)
5009 if (rc
== ERROR_FILE_NOT_FOUND
)
5010 rc
= ERROR_NO_SUCH_DEVINST
;
5015 ClassGUID
= GUID_NULL
;
5016 dwSize
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
5018 if (RegQueryValueExW(hKey
,
5019 REGSTR_VAL_CLASSGUID
,
5022 (LPBYTE
)szClassGuid
,
5023 &dwSize
) == ERROR_SUCCESS
)
5025 szClassGuid
[MAX_GUID_STRING_LEN
- 2] = UNICODE_NULL
;
5027 /* Convert a string to a ClassGuid */
5028 UuidFromStringW(&szClassGuid
[1], &ClassGUID
);
5031 if (!CreateDeviceInfo(list
, DeviceInstanceId
, &ClassGUID
, &deviceInfo
))
5034 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5039 if (ret
&& deviceInfo
&& DeviceInfoData
)
5041 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
5042 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5043 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5054 /***********************************************************************
5055 * SetupDiGetSelectedDevice (SETUPAPI.@)
5058 SetupDiGetSelectedDevice(
5059 IN HDEVINFO DeviceInfoSet
,
5060 OUT PSP_DEVINFO_DATA DeviceInfoData
)
5062 struct DeviceInfoSet
*list
;
5065 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5068 SetLastError(ERROR_INVALID_HANDLE
);
5069 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5070 SetLastError(ERROR_INVALID_HANDLE
);
5071 else if (list
->SelectedDevice
== NULL
)
5072 SetLastError(ERROR_NO_DEVICE_SELECTED
);
5073 else if (!DeviceInfoData
)
5074 SetLastError(ERROR_INVALID_PARAMETER
);
5075 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5076 SetLastError(ERROR_INVALID_USER_BUFFER
);
5079 memcpy(&DeviceInfoData
->ClassGuid
,
5080 &list
->SelectedDevice
->ClassGuid
,
5082 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
5083 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
5087 TRACE("Returning %d\n", ret
);
5092 /***********************************************************************
5093 * SetupDiSetSelectedDevice (SETUPAPI.@)
5096 SetupDiSetSelectedDevice(
5097 IN HDEVINFO DeviceInfoSet
,
5098 IN PSP_DEVINFO_DATA DeviceInfoData
)
5100 struct DeviceInfoSet
*list
;
5103 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5106 SetLastError(ERROR_INVALID_HANDLE
);
5107 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5108 SetLastError(ERROR_INVALID_HANDLE
);
5109 else if (!DeviceInfoData
)
5110 SetLastError(ERROR_INVALID_PARAMETER
);
5111 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5112 SetLastError(ERROR_INVALID_USER_BUFFER
);
5113 else if (DeviceInfoData
->Reserved
== 0)
5114 SetLastError(ERROR_INVALID_USER_BUFFER
);
5117 list
->SelectedDevice
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5121 TRACE("Returning %d\n", ret
);
5126 /* Return the current hardware profile id, or -1 if error */
5128 SETUPAPI_GetCurrentHwProfile(
5129 IN HDEVINFO DeviceInfoSet
)
5132 DWORD dwRegType
, dwLength
;
5135 DWORD ret
= (DWORD
)-1;
5137 rc
= RegOpenKeyExW(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
5138 REGSTR_PATH_IDCONFIGDB
,
5142 if (rc
!= ERROR_SUCCESS
)
5148 dwLength
= sizeof(DWORD
);
5149 rc
= RegQueryValueExW(hKey
,
5150 REGSTR_VAL_CURRENTCONFIG
,
5153 (LPBYTE
)&hwProfile
, &dwLength
);
5154 if (rc
!= ERROR_SUCCESS
)
5159 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5161 SetLastError(ERROR_GEN_FAILURE
);
5176 IN HDEVINFO DeviceInfoSet
,
5177 IN PSP_DEVINFO_DATA DeviceInfoData
)
5180 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5181 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5184 cr
= CM_Enable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
5185 if (cr
!= CR_SUCCESS
)
5187 SetLastError(GetErrorCodeFromCrCode(cr
));
5193 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5198 static BOOL
StopDevice(
5199 IN HDEVINFO DeviceInfoSet
,
5200 IN PSP_DEVINFO_DATA DeviceInfoData
)
5202 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5206 /***********************************************************************
5207 * SetupDiChangeState (SETUPAPI.@)
5211 IN HDEVINFO DeviceInfoSet
,
5212 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5214 PSP_PROPCHANGE_PARAMS PropChange
;
5215 HKEY hKey
= INVALID_HANDLE_VALUE
;
5216 LPCWSTR RegistryValueName
;
5217 DWORD dwConfigFlags
, dwLength
, dwRegType
;
5221 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5223 if (!DeviceInfoData
)
5224 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChangeParams
;
5226 PropChange
= ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChangeParams
;
5229 SetLastError(ERROR_INVALID_PARAMETER
);
5233 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
5234 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
5236 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
5238 switch (PropChange
->StateChange
)
5243 /* Enable/disable device in registry */
5244 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5245 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5246 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
5247 if (hKey
== INVALID_HANDLE_VALUE
)
5249 dwLength
= sizeof(DWORD
);
5250 rc
= RegQueryValueExW(
5255 (LPBYTE
)&dwConfigFlags
, &dwLength
);
5256 if (rc
== ERROR_FILE_NOT_FOUND
)
5258 else if (rc
!= ERROR_SUCCESS
)
5263 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5265 SetLastError(ERROR_GEN_FAILURE
);
5268 if (PropChange
->StateChange
== DICS_ENABLE
)
5269 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5271 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5272 rc
= RegSetValueExW(
5277 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
5278 if (rc
!= ERROR_SUCCESS
)
5284 /* Enable/disable device if needed */
5285 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
5286 || PropChange
->HwProfile
== 0
5287 || PropChange
->HwProfile
== SETUPAPI_GetCurrentHwProfile(DeviceInfoSet
))
5289 if (PropChange
->StateChange
== DICS_ENABLE
)
5290 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5292 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
5298 case DICS_PROPCHANGE
:
5300 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5305 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
5306 SetLastError(ERROR_NOT_SUPPORTED
);
5311 if (hKey
!= INVALID_HANDLE_VALUE
)
5314 TRACE("Returning %d\n", ret
);
5318 /***********************************************************************
5319 * SetupDiSelectDevice (SETUPAPI.@)
5322 SetupDiSelectDevice(
5323 IN HDEVINFO DeviceInfoSet
,
5324 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5326 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5327 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5332 /***********************************************************************
5333 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5336 SetupDiRegisterCoDeviceInstallers(
5337 IN HDEVINFO DeviceInfoSet
,
5338 IN PSP_DEVINFO_DATA DeviceInfoData
)
5340 BOOL ret
= FALSE
; /* Return value */
5342 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5345 SetLastError(ERROR_INVALID_PARAMETER
);
5346 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5347 SetLastError(ERROR_INVALID_HANDLE
);
5348 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5349 SetLastError(ERROR_INVALID_HANDLE
);
5350 else if (!DeviceInfoData
)
5351 SetLastError(ERROR_INVALID_PARAMETER
);
5352 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5353 SetLastError(ERROR_INVALID_USER_BUFFER
);
5356 SP_DEVINSTALL_PARAMS_W InstallParams
;
5357 struct DriverInfoElement
*SelectedDriver
;
5360 WCHAR SectionName
[MAX_PATH
];
5361 DWORD SectionNameLength
= 0;
5362 HKEY hKey
= INVALID_HANDLE_VALUE
;
5363 PVOID Context
= NULL
;
5365 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5366 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5370 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5371 if (SelectedDriver
== NULL
)
5373 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5377 /* Get .CoInstallers section name */
5378 Result
= SetupDiGetActualSectionToInstallW(
5379 SelectedDriver
->InfFileDetails
->hInf
,
5380 SelectedDriver
->Details
.SectionName
,
5381 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5382 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
5384 lstrcatW(SectionName
, DotCoInstallers
);
5386 /* Open/Create driver key information */
5387 #if _WIN32_WINNT >= 0x502
5388 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5390 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5392 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5393 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5394 if (hKey
== INVALID_HANDLE_VALUE
)
5397 /* Install .CoInstallers section */
5398 DoAction
= SPINST_REGISTRY
;
5399 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5401 DoAction
|= SPINST_FILES
;
5402 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5406 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5407 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5408 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5409 SetupDefaultQueueCallbackW
, Context
,
5410 DeviceInfoSet
, DeviceInfoData
);
5418 SetupTermDefaultQueueCallback(Context
);
5419 if (hKey
!= INVALID_HANDLE_VALUE
)
5423 TRACE("Returning %d\n", ret
);
5428 InfIsFromOEMLocation(
5430 OUT LPBOOL IsOEMLocation
)
5434 last
= strrchrW(FullName
, '\\');
5437 /* No directory specified */
5438 *IsOEMLocation
= FALSE
;
5445 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
5448 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5452 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
5453 if (ret
== 0 || ret
> MAX_PATH
)
5456 SetLastError(ERROR_GEN_FAILURE
);
5459 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
5460 strcatW(Windir
, BackSlash
);
5461 strcatW(Windir
, InfDirectory
);
5463 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
5465 /* The path is %SYSTEMROOT%\Inf */
5466 *IsOEMLocation
= FALSE
;
5470 /* The file is in another place */
5471 *IsOEMLocation
= TRUE
;
5478 /***********************************************************************
5479 * SetupDiInstallDevice (SETUPAPI.@)
5482 SetupDiInstallDevice(
5483 IN HDEVINFO DeviceInfoSet
,
5484 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5486 SP_DEVINSTALL_PARAMS_W InstallParams
;
5487 struct DriverInfoElement
*SelectedDriver
;
5488 SYSTEMTIME DriverDate
;
5489 WCHAR SectionName
[MAX_PATH
];
5491 DWORD SectionNameLength
= 0;
5492 BOOL Result
= FALSE
;
5495 LPWSTR pSectionName
= NULL
;
5496 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5498 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5499 BOOL RebootRequired
= FALSE
;
5500 HKEY hKey
= INVALID_HANDLE_VALUE
;
5501 BOOL NeedtoCopyFile
;
5502 LARGE_INTEGER fullVersion
;
5504 PVOID Context
= NULL
;
5505 BOOL ret
= FALSE
; /* Return value */
5507 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5510 SetLastError(ERROR_INVALID_PARAMETER
);
5511 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5512 SetLastError(ERROR_INVALID_HANDLE
);
5513 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5514 SetLastError(ERROR_INVALID_HANDLE
);
5515 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5516 SetLastError(ERROR_INVALID_USER_BUFFER
);
5522 /* One parameter is bad */
5526 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5527 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5531 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5533 /* Set FAILEDINSTALL in ConfigFlags registry value */
5534 DWORD ConfigFlags
, regType
;
5535 Result
= SetupDiGetDeviceRegistryPropertyW(
5540 (PBYTE
)&ConfigFlags
,
5541 sizeof(ConfigFlags
),
5543 if (!Result
|| regType
!= REG_DWORD
)
5545 SetLastError(ERROR_GEN_FAILURE
);
5548 ConfigFlags
|= DNF_DISABLED
;
5549 Result
= SetupDiSetDeviceRegistryPropertyW(
5553 (PBYTE
)&ConfigFlags
,
5554 sizeof(ConfigFlags
));
5557 SetLastError(ERROR_GEN_FAILURE
);
5565 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5566 if (SelectedDriver
== NULL
)
5568 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5572 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5574 Result
= SetupDiGetActualSectionToInstallW(
5575 SelectedDriver
->InfFileDetails
->hInf
,
5576 SelectedDriver
->Details
.SectionName
,
5577 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5578 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
5580 pSectionName
= &SectionName
[strlenW(SectionName
)];
5582 /* Get information from [Version] section */
5583 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5585 /* Format ClassGuid to a string */
5586 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5588 RequiredSize
= lstrlenW(lpGuidString
);
5589 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5590 if (!lpFullGuidString
)
5592 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5595 lpFullGuidString
[0] = '{';
5596 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5597 lpFullGuidString
[RequiredSize
+ 1] = '}';
5598 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5600 /* Copy .inf file to Inf\ directory (if needed) */
5601 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
5606 WCHAR NewFileName
[MAX_PATH
];
5607 struct InfFileDetails
*newInfFileDetails
;
5608 Result
= SetupCopyOEMInfW(
5609 SelectedDriver
->Details
.InfFileName
,
5612 SP_COPY_NOOVERWRITE
,
5613 NewFileName
, MAX_PATH
,
5616 if (!Result
&& GetLastError() != ERROR_FILE_EXISTS
)
5618 /* Create a new struct InfFileDetails, and set it to
5619 * SelectedDriver->InfFileDetails, to release use of
5620 * current InfFile */
5621 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
5622 if (!newInfFileDetails
)
5624 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
5625 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
5626 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
5629 /* Open/Create driver key information */
5630 #if _WIN32_WINNT >= 0x502
5631 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5633 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5635 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5636 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5637 if (hKey
== INVALID_HANDLE_VALUE
)
5640 /* Install main section */
5642 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5643 DoAction
|= SPINST_REGISTRY
;
5644 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5646 DoAction
|= SPINST_FILES
;
5647 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5651 *pSectionName
= '\0';
5652 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5653 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5654 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5655 SetupDefaultQueueCallbackW
, Context
,
5656 DeviceInfoSet
, DeviceInfoData
);
5659 InstallParams
.Flags
|= DI_NOFILECOPY
;
5660 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5662 /* Write information to driver key */
5663 *pSectionName
= UNICODE_NULL
;
5664 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
5665 TRACE("Write information to driver key\n");
5666 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5667 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5668 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5669 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
5670 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
5671 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
5672 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
5673 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
5674 sprintfW(Buffer
, DateFormat
, DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5675 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5676 if (rc
== ERROR_SUCCESS
)
5677 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5678 if (rc
== ERROR_SUCCESS
)
5679 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5680 if (rc
== ERROR_SUCCESS
)
5682 sprintfW(Buffer
, VersionFormat
, fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5683 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5685 if (rc
== ERROR_SUCCESS
)
5686 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
5687 if (rc
== ERROR_SUCCESS
)
5688 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5689 if (rc
== ERROR_SUCCESS
)
5690 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
));
5691 if (rc
== ERROR_SUCCESS
)
5692 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5693 if (rc
== ERROR_SUCCESS
)
5694 rc
= RegSetValueExW(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5695 if (rc
!= ERROR_SUCCESS
)
5701 hKey
= INVALID_HANDLE_VALUE
;
5703 /* FIXME: Process .LogConfigOverride section */
5705 /* Install .Services section */
5706 strcpyW(pSectionName
, DotServices
);
5707 Result
= SetupInstallServicesFromInfSectionExW(
5708 SelectedDriver
->InfFileDetails
->hInf
,
5717 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5718 RebootRequired
= TRUE
;
5720 /* Open device registry key */
5721 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5722 if (hKey
== INVALID_HANDLE_VALUE
)
5725 /* Install .HW section */
5727 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5728 DoAction
|= SPINST_REGISTRY
;
5729 strcpyW(pSectionName
, DotHW
);
5730 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5731 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5732 DoAction
, hKey
, NULL
, 0,
5734 DeviceInfoSet
, DeviceInfoData
);
5738 /* Write information to enum key */
5739 TRACE("Write information to enum key\n");
5740 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
5741 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
5742 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5743 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
5744 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
5745 if (rc
== ERROR_SUCCESS
)
5746 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5747 if (rc
== ERROR_SUCCESS
)
5748 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5749 if (rc
== ERROR_SUCCESS
)
5750 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5751 if (rc
!= ERROR_SUCCESS
)
5757 /* Start the device */
5758 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5759 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5764 /* End of installation */
5765 if (hKey
!= INVALID_HANDLE_VALUE
)
5768 RpcStringFreeW(&lpGuidString
);
5769 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5771 SetupTermDefaultQueueCallback(Context
);
5772 TRACE("Returning %d\n", ret
);
5776 static HKEY
SETUPDI_OpenDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5778 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5781 l
= RegOpenKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, READ_CONTROL
, &enumKey
);
5784 l
= RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
5785 RegCloseKey(enumKey
);
5792 static HKEY
SETUPDI_OpenDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5794 LPWSTR DriverKey
= NULL
;
5798 HKEY hEnumKey
= NULL
;
5800 HKEY key
= INVALID_HANDLE_VALUE
;
5802 hKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
);
5803 if (hKey
== INVALID_HANDLE_VALUE
)
5805 /* Read the 'Driver' key */
5806 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5807 if (rc
!= ERROR_SUCCESS
)
5812 else if (dwRegType
!= REG_SZ
)
5814 SetLastError(ERROR_GEN_FAILURE
);
5817 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5820 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5823 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5824 if (rc
!= ERROR_SUCCESS
)
5831 /* Need to open the driver key */
5834 REGSTR_PATH_CLASS_NT
,
5838 if (rc
!= ERROR_SUCCESS
)
5849 if (rc
!= ERROR_SUCCESS
)
5857 if (hEnumKey
!= NULL
)
5858 RegCloseKey(hEnumKey
);
5859 if (hKey
!= NULL
&& hKey
!= key
)
5862 HeapFree(GetProcessHeap(), 0, DriverKey
);
5866 /***********************************************************************
5867 * SetupDiOpenDevRegKey (SETUPAPI.@)
5869 HKEY WINAPI
SetupDiOpenDevRegKey(
5870 HDEVINFO DeviceInfoSet
,
5871 PSP_DEVINFO_DATA DeviceInfoData
,
5877 struct DeviceInfoSet
*set
= DeviceInfoSet
;
5878 struct DeviceInfo
*devInfo
;
5879 HKEY key
= INVALID_HANDLE_VALUE
;
5882 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet
, DeviceInfoData
,
5883 Scope
, HwProfile
, KeyType
, samDesired
);
5885 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5887 SetLastError(ERROR_INVALID_HANDLE
);
5888 return INVALID_HANDLE_VALUE
;
5890 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5892 SetLastError(ERROR_INVALID_HANDLE
);
5893 return INVALID_HANDLE_VALUE
;
5895 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5896 || !DeviceInfoData
->Reserved
)
5898 SetLastError(ERROR_INVALID_PARAMETER
);
5899 return INVALID_HANDLE_VALUE
;
5901 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5903 SetLastError(ERROR_INVALID_FLAGS
);
5904 return INVALID_HANDLE_VALUE
;
5906 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
5908 SetLastError(ERROR_INVALID_FLAGS
);
5909 return INVALID_HANDLE_VALUE
;
5911 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5912 if (devInfo
->set
!= set
)
5914 SetLastError(ERROR_INVALID_PARAMETER
);
5915 return INVALID_HANDLE_VALUE
;
5917 if (Scope
!= DICS_FLAG_GLOBAL
)
5919 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5920 if (RootKey
== INVALID_HANDLE_VALUE
)
5921 return INVALID_HANDLE_VALUE
;
5924 RootKey
= set
->HKLM
;
5928 key
= SETUPDI_OpenDevKey(RootKey
, devInfo
, samDesired
);
5929 if (Scope
== DICS_FLAG_GLOBAL
)
5932 HKEY hTempKey
= key
;
5933 rc
= RegOpenKeyExW(hTempKey
,
5934 L
"Device Parameters",
5938 if (rc
== ERROR_SUCCESS
)
5939 RegCloseKey(hTempKey
);
5943 key
= SETUPDI_OpenDrvKey(RootKey
, devInfo
, samDesired
);
5946 WARN("unknown KeyType %d\n", KeyType
);
5948 if (RootKey
!= set
->HKLM
)
5949 RegCloseKey(RootKey
);
5953 static BOOL
SETUPDI_DeleteDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5959 static BOOL
SETUPDI_DeleteDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5965 /***********************************************************************
5966 * SetupDiDeleteDevRegKey (SETUPAPI.@)
5968 BOOL WINAPI
SetupDiDeleteDevRegKey(
5969 HDEVINFO DeviceInfoSet
,
5970 PSP_DEVINFO_DATA DeviceInfoData
,
5975 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5976 struct DeviceInfo
*devInfo
;
5980 TRACE("%p %p %d %d %d\n", DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
5983 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5985 SetLastError(ERROR_INVALID_HANDLE
);
5988 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5990 SetLastError(ERROR_INVALID_HANDLE
);
5993 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5994 || !DeviceInfoData
->Reserved
)
5996 SetLastError(ERROR_INVALID_PARAMETER
);
5999 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
6001 SetLastError(ERROR_INVALID_FLAGS
);
6004 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
&& KeyType
!= DIREG_BOTH
)
6006 SetLastError(ERROR_INVALID_FLAGS
);
6009 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
6010 if (devInfo
->set
!= set
)
6012 SetLastError(ERROR_INVALID_PARAMETER
);
6015 if (Scope
!= DICS_FLAG_GLOBAL
)
6017 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
6018 if (RootKey
== INVALID_HANDLE_VALUE
)
6022 RootKey
= set
->HKLM
;
6026 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
6029 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
6032 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
6034 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
6037 WARN("unknown KeyType %d\n", KeyType
);
6039 if (RootKey
!= set
->HKLM
)
6040 RegCloseKey(RootKey
);