2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
26 /* Unicode constants */
27 static const WCHAR BackSlash
[] = {'\\',0};
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR DateFormat
[] = {'%','u','-','%','u','-','%','u',0};
31 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
32 static const WCHAR DotHW
[] = {'.','H','W',0};
33 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
34 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
35 static const WCHAR InstanceKeyFormat
[] = {'%','0','4','l','u',0};
36 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
37 static const WCHAR VersionFormat
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
39 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
40 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
41 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
42 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
43 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
46 (CALLBACK
* CLASS_INSTALL_PROC
) (
47 IN DI_FUNCTION InstallFunction
,
48 IN HDEVINFO DeviceInfoSet
,
49 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
51 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
52 IN HDEVINFO DeviceInfoSet
,
53 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
55 (CALLBACK
* COINSTALLER_PROC
) (
56 IN DI_FUNCTION InstallFunction
,
57 IN HDEVINFO DeviceInfoSet
,
58 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
59 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
61 struct CoInstallerElement
66 COINSTALLER_PROC Function
;
67 BOOL DoPostProcessing
;
71 struct GetSectionCallbackInfo
73 PSP_ALTPLATFORM_INFO PlatformInfo
;
77 WCHAR BestSection
[LINE_LEN
+ 1];
78 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
83 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
85 static const WCHAR fmt
[] = {'{','%','0','8','X','-','%','0','4','X','-',
86 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
87 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
90 sprintfW(guidStr
, fmt
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
91 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
92 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
96 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
100 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
101 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
102 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
103 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
104 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
105 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
106 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
107 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
108 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
109 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
110 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
111 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
112 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
113 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
114 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
115 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
116 case CR_SUCCESS
: return ERROR_SUCCESS
;
117 default: return ERROR_GEN_FAILURE
;
120 /* Does not happen */
123 /* Lower scores are best ones */
126 IN LPCWSTR SectionName
,
127 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
130 OUT PDWORD ScorePlatform
,
131 OUT PDWORD ScoreMajorVersion
,
132 OUT PDWORD ScoreMinorVersion
,
133 OUT PDWORD ScoreProductType
,
134 OUT PDWORD ScoreSuiteMask
)
136 LPWSTR Section
= NULL
;
137 //LPCWSTR pExtensionPlatform;
138 LPCWSTR pExtensionArchitecture
;
143 //static const WCHAR ExtensionPlatformNone[] = {'.',0};
144 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
145 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
147 static const WCHAR ExtensionArchitectureNone
[] = {0};
148 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
149 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
150 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
151 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
152 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
153 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
155 TRACE("%s %p 0x%x 0x%x\n",
156 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
158 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
160 Section
= pSetupDuplicateString(SectionName
);
163 TRACE("pSetupDuplicateString() failed\n");
167 /* Set various extensions values */
168 switch (PlatformInfo
->Platform
)
170 case VER_PLATFORM_WIN32_WINDOWS
:
171 //pExtensionPlatform = ExtensionPlatformWindows;
173 case VER_PLATFORM_WIN32_NT
:
174 //pExtensionPlatform = ExtensionPlatformNT;
177 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
178 //pExtensionPlatform = ExtensionPlatformNone;
181 switch (PlatformInfo
->ProcessorArchitecture
)
183 case PROCESSOR_ARCHITECTURE_ALPHA
:
184 pExtensionArchitecture
= ExtensionArchitecturealpha
;
186 case PROCESSOR_ARCHITECTURE_AMD64
:
187 pExtensionArchitecture
= ExtensionArchitectureamd64
;
189 case PROCESSOR_ARCHITECTURE_IA64
:
190 pExtensionArchitecture
= ExtensionArchitectureia64
;
192 case PROCESSOR_ARCHITECTURE_INTEL
:
193 pExtensionArchitecture
= ExtensionArchitecturex86
;
195 case PROCESSOR_ARCHITECTURE_MIPS
:
196 pExtensionArchitecture
= ExtensionArchitecturemips
;
198 case PROCESSOR_ARCHITECTURE_PPC
:
199 pExtensionArchitecture
= ExtensionArchitectureppc
;
202 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
203 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
204 pExtensionArchitecture
= ExtensionArchitectureNone
;
210 * Field[1] Architecture
211 * Field[2] Major version
212 * Field[3] Minor version
213 * Field[4] Product type
214 * Field[5] Suite mask
215 * Remark: lastests fields may be NULL if the information is not provided
218 if (Fields
[0] == NULL
)
220 TRACE("No extension found\n");
221 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
225 Fields
[1] = Fields
[0] + 1;
226 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
227 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
229 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
233 *(Fields
[i
] - 1) = UNICODE_NULL
;
236 /* Take care of first 2 fields */
237 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
239 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
241 TRACE("Mismatch on platform field\n");
244 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
246 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
248 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
250 TRACE("Mismatch on platform field\n");
253 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
257 /* No platform specified */
258 *ScorePlatform
|= 0x02;
260 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
262 /* No architecture specified */
263 *ScorePlatform
|= 0x01;
265 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
267 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
268 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
272 /* Check if informations are matching */
273 if (Fields
[2] && *Fields
[2])
275 DWORD MajorVersion
, MinorVersion
= 0;
276 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
277 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
278 (errno
== ERANGE
|| errno
== EINVAL
))
280 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
283 if (Fields
[3] && *Fields
[3])
285 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
286 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
287 (errno
== ERANGE
|| errno
== EINVAL
))
289 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
293 if (PlatformInfo
->MajorVersion
< MajorVersion
||
294 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
296 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
297 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
300 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
301 if (MajorVersion
== PlatformInfo
->MajorVersion
)
302 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
304 *ScoreMinorVersion
= MinorVersion
;
306 else if (Fields
[3] && *Fields
[3])
308 TRACE("Minor version found without major version\n");
313 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
314 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
317 if (Fields
[4] && *Fields
[4])
319 DWORD CurrentProductType
;
320 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
321 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
322 (errno
== ERANGE
|| errno
== EINVAL
))
324 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
327 if (CurrentProductType
!= ProductType
)
329 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
330 CurrentProductType
, ProductType
);
335 *ScoreProductType
= 1;
337 if (Fields
[5] && *Fields
[5])
339 DWORD CurrentSuiteMask
;
340 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
341 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
342 (errno
== ERANGE
|| errno
== EINVAL
))
344 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
347 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
349 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
350 CurrentSuiteMask
, SuiteMask
);
353 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
356 *ScoreSuiteMask
= SuiteMask
;
367 IN LPCWSTR SectionName
,
370 struct GetSectionCallbackInfo
*info
= Context
;
371 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
374 if (SectionName
[info
->PrefixLength
] != '.')
377 ret
= CheckSectionValid(
378 &SectionName
[info
->PrefixLength
],
382 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
385 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
388 if (Score1
> info
->BestScore1
) goto done
;
389 if (Score1
< info
->BestScore1
) goto bettersection
;
390 if (Score2
> info
->BestScore2
) goto done
;
391 if (Score2
< info
->BestScore2
) goto bettersection
;
392 if (Score3
> info
->BestScore3
) goto done
;
393 if (Score3
< info
->BestScore3
) goto bettersection
;
394 if (Score4
> info
->BestScore4
) goto done
;
395 if (Score4
< info
->BestScore4
) goto bettersection
;
396 if (Score5
> info
->BestScore5
) goto done
;
397 if (Score5
< info
->BestScore5
) goto bettersection
;
401 strcpyW(info
->BestSection
, SectionName
);
402 info
->BestScore1
= Score1
;
403 info
->BestScore2
= Score2
;
404 info
->BestScore3
= Score3
;
405 info
->BestScore4
= Score4
;
406 info
->BestScore5
= Score5
;
412 /***********************************************************************
413 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
416 SetupDiGetActualSectionToInstallExW(
418 IN PCWSTR InfSectionName
,
419 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
420 OUT PWSTR InfSectionWithExt OPTIONAL
,
421 IN DWORD InfSectionWithExtSize
,
422 OUT PDWORD RequiredSize OPTIONAL
,
423 OUT PWSTR
* Extension OPTIONAL
,
428 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
429 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
430 RequiredSize
, Extension
, Reserved
);
432 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
433 SetLastError(ERROR_INVALID_HANDLE
);
434 else if (!InfSectionName
)
435 SetLastError(ERROR_INVALID_PARAMETER
);
436 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
437 SetLastError(ERROR_INVALID_USER_BUFFER
);
438 else if (Reserved
!= NULL
)
439 SetLastError(ERROR_INVALID_PARAMETER
);
442 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
443 static BYTE CurrentProductType
= 0;
444 static WORD CurrentSuiteMask
= 0;
445 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
446 struct GetSectionCallbackInfo CallbackInfo
;
451 /* Fill platform info if needed */
452 if (AlternatePlatformInfo
)
454 pPlatformInfo
= AlternatePlatformInfo
;
460 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
462 /* That's the first time we go here. We need to fill in the structure */
463 OSVERSIONINFOEX VersionInfo
;
464 SYSTEM_INFO SystemInfo
;
465 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
466 ret
= GetVersionExW((OSVERSIONINFO
*)&VersionInfo
);
469 GetSystemInfo(&SystemInfo
);
470 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
471 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
472 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
473 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
474 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
475 CurrentPlatform
.Reserved
= 0;
476 CurrentProductType
= VersionInfo
.wProductType
;
477 CurrentSuiteMask
= VersionInfo
.wSuiteMask
;
479 ProductType
= CurrentProductType
;
480 SuiteMask
= CurrentSuiteMask
;
483 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
484 CallbackInfo
.ProductType
= ProductType
;
485 CallbackInfo
.SuiteMask
= SuiteMask
;
486 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
487 CallbackInfo
.BestScore1
= ULONG_MAX
;
488 CallbackInfo
.BestScore2
= ULONG_MAX
;
489 CallbackInfo
.BestScore3
= ULONG_MAX
;
490 CallbackInfo
.BestScore4
= ULONG_MAX
;
491 CallbackInfo
.BestScore5
= ULONG_MAX
;
492 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
493 if (!EnumerateSectionsStartingWith(
499 SetLastError(ERROR_GEN_FAILURE
);
503 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
504 if (RequiredSize
!= NULL
)
505 *RequiredSize
= dwFullLength
+ 1;
507 if (InfSectionWithExtSize
> 0)
509 if (InfSectionWithExtSize
< dwFullLength
+ 1)
511 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
514 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
517 DWORD dwLength
= lstrlenW(InfSectionName
);
518 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
526 TRACE("Returning %d\n", ret
);
533 IN
struct DeviceInfoSet
*list
,
534 IN LPCWSTR InstancePath
,
535 IN LPCGUID pClassGuid
,
536 OUT
struct DeviceInfo
**pDeviceInfo
)
540 struct DeviceInfo
*deviceInfo
;
544 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
545 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
548 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
551 ZeroMemory(deviceInfo
, size
);
553 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
554 if (cr
!= CR_SUCCESS
)
556 SetLastError(GetErrorCodeFromCrCode(cr
));
560 deviceInfo
->set
= list
;
561 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
562 strcpyW(deviceInfo
->Data
, InstancePath
);
563 deviceInfo
->instanceId
= deviceInfo
->Data
;
564 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
565 deviceInfo
->DeviceDescription
= NULL
;
566 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
567 deviceInfo
->CreationFlags
= 0;
568 InitializeListHead(&deviceInfo
->DriverListHead
);
569 InitializeListHead(&deviceInfo
->InterfaceListHead
);
571 *pDeviceInfo
= deviceInfo
;
577 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
579 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
580 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
585 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
587 PLIST_ENTRY ListEntry
;
588 struct DriverInfoElement
*driverInfo
;
589 struct DeviceInterface
*deviceInterface
;
591 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
593 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
594 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
595 if (!DestroyDriverInfoElement(driverInfo
))
598 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
600 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
601 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
602 if (!DestroyDeviceInterface(deviceInterface
))
605 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
606 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
610 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
612 PLIST_ENTRY ListEntry
;
613 struct DeviceInfo
*deviceInfo
;
615 while (!IsListEmpty(&list
->ListHead
))
617 ListEntry
= RemoveHeadList(&list
->ListHead
);
618 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
);
619 if (!DestroyDeviceInfo(deviceInfo
))
622 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
623 RegCloseKey(list
->HKLM
);
624 CM_Disconnect_Machine(list
->hMachine
);
625 DestroyClassInstallParams(&list
->ClassInstallParams
);
626 return HeapFree(GetProcessHeap(), 0, list
);
629 /***********************************************************************
630 * SetupDiBuildClassInfoList (SETUPAPI.@)
632 * Returns a list of setup class GUIDs that identify the classes
633 * that are installed on a local machine.
636 * Flags [I] control exclusion of classes from the list.
637 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
638 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
639 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
645 BOOL WINAPI
SetupDiBuildClassInfoList(
647 LPGUID ClassGuidList
,
648 DWORD ClassGuidListSize
,
652 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
653 ClassGuidListSize
, RequiredSize
,
657 /***********************************************************************
658 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
660 * Returns a list of setup class GUIDs that identify the classes
661 * that are installed on a local or remote macine.
664 * Flags [I] control exclusion of classes from the list.
665 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
666 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
667 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
668 * MachineName [I] name of a remote machine.
669 * Reserved [I] must be NULL.
675 BOOL WINAPI
SetupDiBuildClassInfoListExA(
677 LPGUID ClassGuidList
,
678 DWORD ClassGuidListSize
,
683 LPWSTR MachineNameW
= NULL
;
686 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
687 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
691 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
692 if (MachineNameW
== NULL
) return FALSE
;
695 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
696 ClassGuidListSize
, RequiredSize
,
697 MachineNameW
, Reserved
);
699 MyFree(MachineNameW
);
704 /***********************************************************************
705 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
707 * Returns a list of setup class GUIDs that identify the classes
708 * that are installed on a local or remote macine.
711 * Flags [I] control exclusion of classes from the list.
712 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
713 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
714 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
715 * MachineName [I] name of a remote machine.
716 * Reserved [I] must be NULL.
722 BOOL WINAPI
SetupDiBuildClassInfoListExW(
724 LPGUID ClassGuidList
,
725 DWORD ClassGuidListSize
,
731 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
736 DWORD dwGuidListIndex
= 0;
738 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
739 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
743 SetLastError(ERROR_INVALID_PARAMETER
);
746 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
748 SetLastError(ERROR_INVALID_PARAMETER
);
752 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
753 KEY_ENUMERATE_SUB_KEYS
,
757 if (hClassesKey
== INVALID_HANDLE_VALUE
)
762 for (dwIndex
= 0; ; dwIndex
++)
765 lError
= RegEnumKeyExW(hClassesKey
,
773 TRACE("RegEnumKeyExW() returns %d\n", lError
);
774 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
776 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
778 if (RegOpenKeyExW(hClassesKey
,
784 RegCloseKey(hClassesKey
);
788 if (!RegQueryValueExW(hClassKey
,
789 REGSTR_VAL_NOUSECLASS
,
795 TRACE("'NoUseClass' value found!\n");
796 RegCloseKey(hClassKey
);
800 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
801 (!RegQueryValueExW(hClassKey
,
802 REGSTR_VAL_NOINSTALLCLASS
,
808 TRACE("'NoInstallClass' value found!\n");
809 RegCloseKey(hClassKey
);
813 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
814 (!RegQueryValueExW(hClassKey
,
815 REGSTR_VAL_NODISPLAYCLASS
,
821 TRACE("'NoDisplayClass' value found!\n");
822 RegCloseKey(hClassKey
);
826 RegCloseKey(hClassKey
);
828 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
829 if (dwGuidListIndex
< ClassGuidListSize
)
831 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
835 TRACE("Guid: %p\n", &szKeyName
[1]);
837 UuidFromStringW(&szKeyName
[1],
838 &ClassGuidList
[dwGuidListIndex
]);
844 if (lError
!= ERROR_SUCCESS
)
848 RegCloseKey(hClassesKey
);
850 if (RequiredSize
!= NULL
)
851 *RequiredSize
= dwGuidListIndex
;
853 if (ClassGuidListSize
< dwGuidListIndex
)
855 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
862 /***********************************************************************
863 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
865 BOOL WINAPI
SetupDiClassGuidsFromNameA(
867 LPGUID ClassGuidList
,
868 DWORD ClassGuidListSize
,
871 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
872 ClassGuidListSize
, RequiredSize
,
876 /***********************************************************************
877 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
879 BOOL WINAPI
SetupDiClassGuidsFromNameW(
881 LPGUID ClassGuidList
,
882 DWORD ClassGuidListSize
,
885 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
886 ClassGuidListSize
, RequiredSize
,
890 /***********************************************************************
891 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
893 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
895 LPGUID ClassGuidList
,
896 DWORD ClassGuidListSize
,
901 LPWSTR ClassNameW
= NULL
;
902 LPWSTR MachineNameW
= NULL
;
905 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName
), ClassGuidList
,
906 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
910 SetLastError(ERROR_INVALID_PARAMETER
);
914 ClassNameW
= pSetupMultiByteToUnicode(ClassName
, CP_ACP
);
915 if (ClassNameW
== NULL
)
920 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
921 if (MachineNameW
== NULL
)
928 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
929 ClassGuidListSize
, RequiredSize
,
930 MachineNameW
, Reserved
);
932 MyFree(MachineNameW
);
938 /***********************************************************************
939 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
941 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
943 LPGUID ClassGuidList
,
944 DWORD ClassGuidListSize
,
950 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
956 DWORD dwGuidListIndex
= 0;
958 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
959 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
961 if (!ClassName
|| !RequiredSize
)
963 SetLastError(ERROR_INVALID_PARAMETER
);
966 if (!ClassGuidList
&& ClassGuidListSize
> 0)
968 SetLastError(ERROR_INVALID_PARAMETER
);
973 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
974 KEY_ENUMERATE_SUB_KEYS
,
978 if (hClassesKey
== INVALID_HANDLE_VALUE
)
983 for (dwIndex
= 0; ; dwIndex
++)
986 lError
= RegEnumKeyExW(hClassesKey
,
994 TRACE("RegEnumKeyExW() returns %d\n", lError
);
995 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
997 TRACE("Key name: %p\n", szKeyName
);
999 if (RegOpenKeyExW(hClassesKey
,
1005 RegCloseKey(hClassesKey
);
1009 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
1010 if (!RegQueryValueExW(hClassKey
,
1014 (LPBYTE
)szClassName
,
1017 TRACE("Class name: %p\n", szClassName
);
1019 if (strcmpiW(szClassName
, ClassName
) == 0)
1021 TRACE("Found matching class name\n");
1023 TRACE("Guid: %p\n", szKeyName
);
1024 if (dwGuidListIndex
< ClassGuidListSize
)
1026 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1030 TRACE("Guid: %p\n", &szKeyName
[1]);
1032 UuidFromStringW(&szKeyName
[1],
1033 &ClassGuidList
[dwGuidListIndex
]);
1040 RegCloseKey(hClassKey
);
1043 if (lError
!= ERROR_SUCCESS
)
1047 RegCloseKey(hClassesKey
);
1049 if (RequiredSize
!= NULL
)
1050 *RequiredSize
= dwGuidListIndex
;
1052 if (ClassGuidListSize
< dwGuidListIndex
)
1054 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1061 /***********************************************************************
1062 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1064 BOOL WINAPI
SetupDiClassNameFromGuidA(
1065 const GUID
* ClassGuid
,
1067 DWORD ClassNameSize
,
1068 PDWORD RequiredSize
)
1070 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1071 ClassNameSize
, RequiredSize
,
1075 /***********************************************************************
1076 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1078 BOOL WINAPI
SetupDiClassNameFromGuidW(
1079 const GUID
* ClassGuid
,
1081 DWORD ClassNameSize
,
1082 PDWORD RequiredSize
)
1084 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1085 ClassNameSize
, RequiredSize
,
1089 /***********************************************************************
1090 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1092 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1093 const GUID
* ClassGuid
,
1095 DWORD ClassNameSize
,
1096 PDWORD RequiredSize
,
1100 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1101 LPWSTR MachineNameW
= NULL
;
1105 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1106 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1107 RequiredSize
, MachineNameW
, Reserved
);
1110 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1111 ClassNameSize
, NULL
, NULL
);
1112 if (len
== 0 || len
> ClassNameSize
)
1114 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1118 MyFree(MachineNameW
);
1122 /***********************************************************************
1123 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1125 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1126 const GUID
* ClassGuid
,
1128 DWORD ClassNameSize
,
1129 PDWORD RequiredSize
,
1139 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
1140 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1142 /* Make sure there's a GUID */
1143 if (ClassGuid
== NULL
)
1145 SetLastError(ERROR_INVALID_CLASS
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1149 /* Make sure there's a real buffer when there's a size */
1150 if ((ClassNameSize
> 0) && (ClassName
== NULL
))
1152 SetLastError(ERROR_INVALID_PARAMETER
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1156 /* Open the key for the GUID */
1157 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INSTALLER
, MachineName
, Reserved
);
1159 if (hKey
== INVALID_HANDLE_VALUE
)
1162 /* Retrieve the class name data and close the key */
1163 rc
= QueryRegistryValue(hKey
, Class
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
1166 /* Make sure we got the data */
1167 if (rc
!= ERROR_SUCCESS
)
1173 /* Make sure the data is a string */
1174 if (dwRegType
!= REG_SZ
)
1177 SetLastError(ERROR_GEN_FAILURE
);
1181 /* Determine the length of the class name */
1182 dwLength
/= sizeof(WCHAR
);
1184 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
1185 /* Count the null-terminator */
1188 /* Inform the caller about the class name */
1189 if ((ClassName
!= NULL
) && (dwLength
<= ClassNameSize
))
1191 memcpy(ClassName
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
1192 ClassName
[dwLength
- 1] = UNICODE_NULL
;
1195 /* Inform the caller about the required size */
1196 if (RequiredSize
!= NULL
)
1197 *RequiredSize
= dwLength
;
1199 /* Clean up the buffer */
1202 /* Make sure the buffer was large enough */
1203 if ((ClassName
== NULL
) || (dwLength
> ClassNameSize
))
1205 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1212 /***********************************************************************
1213 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1216 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1219 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1222 /***********************************************************************
1223 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1226 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1231 LPWSTR MachineNameW
= NULL
;
1234 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1235 debugstr_a(MachineName
), Reserved
);
1239 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1240 if (MachineNameW
== NULL
)
1241 return INVALID_HANDLE_VALUE
;
1244 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1245 MachineNameW
, Reserved
);
1247 MyFree(MachineNameW
);
1252 /***********************************************************************
1253 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1255 * Create an empty DeviceInfoSet list.
1258 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1260 * hwndParent [I] hwnd needed for interface related actions.
1261 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1262 * local registry will be used.
1263 * Reserved [I] must be NULL
1266 * Success: empty list.
1267 * Failure: INVALID_HANDLE_VALUE.
1270 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1275 struct DeviceInfoSet
*list
= NULL
;
1276 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1279 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1281 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1282 debugstr_w(MachineName
), Reserved
);
1284 if (MachineName
!= NULL
)
1286 SIZE_T len
= strlenW(MachineName
);
1287 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1289 SetLastError(ERROR_INVALID_MACHINENAME
);
1293 size
+= (len
+ 3) * sizeof(WCHAR
);
1298 if (Reserved
!= NULL
)
1300 SetLastError(ERROR_INVALID_PARAMETER
);
1301 return INVALID_HANDLE_VALUE
;
1304 list
= MyMalloc(size
);
1307 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1308 return INVALID_HANDLE_VALUE
;
1310 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1312 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1313 memcpy(&list
->ClassGuid
,
1314 ClassGuid
? ClassGuid
: &GUID_NULL
,
1315 sizeof(list
->ClassGuid
));
1316 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1317 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1318 list
->InstallParams
.hwndParent
= hwndParent
;
1321 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1322 if (rc
!= ERROR_SUCCESS
)
1324 SetLastError(ERROR_INVALID_MACHINENAME
);
1328 list
->szData
[0] = list
->szData
[1] = '\\';
1329 strcpyW(list
->szData
+ 2, MachineName
);
1330 list
->MachineName
= list
->szData
;
1334 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1335 list
->MachineName
= NULL
;
1337 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1338 if (cr
!= CR_SUCCESS
)
1340 SetLastError(GetErrorCodeFromCrCode(cr
));
1343 InitializeListHead(&list
->DriverListHead
);
1344 InitializeListHead(&list
->ListHead
);
1346 return (HDEVINFO
)list
;
1349 if (ret
== INVALID_HANDLE_VALUE
)
1353 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1354 RegCloseKey(list
->HKLM
);
1361 /***********************************************************************
1362 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1364 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1365 HDEVINFO DeviceInfoSet
,
1366 PSP_DEVINFO_DATA DeviceInfoData
,
1371 PCSTR InfSectionName
)
1373 PWSTR InfSectionNameW
= NULL
;
1376 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1377 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1381 if (!InfSectionName
)
1383 SetLastError(ERROR_INVALID_PARAMETER
);
1384 return INVALID_HANDLE_VALUE
;
1388 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
1389 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1392 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1393 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1394 MyFree(InfSectionNameW
);
1399 OpenHardwareProfileKey(
1402 IN DWORD samDesired
);
1404 /***********************************************************************
1405 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1407 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1408 HDEVINFO DeviceInfoSet
,
1409 PSP_DEVINFO_DATA DeviceInfoData
,
1414 PCWSTR InfSectionName
)
1416 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1417 HKEY key
= INVALID_HANDLE_VALUE
;
1418 LPWSTR lpGuidString
= NULL
;
1419 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
1420 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
1421 DWORD Index
; /* Index used in the DriverKey name */
1425 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1426 HKEY hEnumKey
= NULL
;
1427 HKEY hClassKey
= NULL
;
1428 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
1432 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1433 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1435 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1437 SetLastError(ERROR_INVALID_HANDLE
);
1438 return INVALID_HANDLE_VALUE
;
1440 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1442 SetLastError(ERROR_INVALID_HANDLE
);
1443 return INVALID_HANDLE_VALUE
;
1445 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1446 || !DeviceInfoData
->Reserved
)
1448 SetLastError(ERROR_INVALID_PARAMETER
);
1449 return INVALID_HANDLE_VALUE
;
1451 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1453 SetLastError(ERROR_INVALID_FLAGS
);
1454 return INVALID_HANDLE_VALUE
;
1456 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1458 SetLastError(ERROR_INVALID_FLAGS
);
1459 return INVALID_HANDLE_VALUE
;
1461 if (InfHandle
&& !InfSectionName
)
1463 SetLastError(ERROR_INVALID_PARAMETER
);
1464 return INVALID_HANDLE_VALUE
;
1466 if (!InfHandle
&& InfSectionName
)
1468 SetLastError(ERROR_INVALID_PARAMETER
);
1469 return INVALID_HANDLE_VALUE
;
1472 if (Scope
== DICS_FLAG_GLOBAL
)
1473 RootKey
= set
->HKLM
;
1474 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1476 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1477 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1479 RootKey
= hHWProfileKey
;
1482 if (KeyType
== DIREG_DEV
)
1484 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1486 rc
= RegCreateKeyExW(
1488 REGSTR_PATH_SYSTEMENUM
,
1491 REG_OPTION_NON_VOLATILE
,
1496 if (rc
!= ERROR_SUCCESS
)
1501 rc
= RegCreateKeyExW(
1503 deviceInfo
->instanceId
,
1506 REG_OPTION_NON_VOLATILE
,
1507 #if _WIN32_WINNT >= 0x502
1508 KEY_READ
| KEY_WRITE
,
1515 if (rc
!= ERROR_SUCCESS
)
1521 else /* KeyType == DIREG_DRV */
1523 /* Open device key, to read Driver value */
1524 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1525 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
1528 rc
= RegOpenKeyExW(RootKey
, REGSTR_PATH_CLASS_NT
, 0, KEY_CREATE_SUB_KEY
, &hClassKey
);
1529 if (rc
!= ERROR_SUCCESS
)
1535 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, NULL
, &dwSize
);
1536 if (rc
!= ERROR_SUCCESS
)
1538 /* Create a new driver key */
1540 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
1543 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1544 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
1547 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1552 strcpyW(&DriverKey
[1], lpGuidString
);
1553 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
1554 *pDeviceInstance
++ = '}';
1555 *pDeviceInstance
++ = '\\';
1557 /* Try all values for Index between 0 and 9999 */
1559 while (Index
<= 9999)
1561 sprintfW(pDeviceInstance
, InstanceKeyFormat
, Index
);
1562 rc
= RegCreateKeyExW(hClassKey
,
1566 REG_OPTION_NON_VOLATILE
,
1567 #if _WIN32_WINNT >= 0x502
1568 KEY_READ
| KEY_WRITE
,
1575 if (rc
!= ERROR_SUCCESS
)
1580 if (Disposition
== REG_CREATED_NEW_KEY
)
1589 /* Unable to create more than 9999 devices within the same class */
1590 SetLastError(ERROR_GEN_FAILURE
);
1594 /* Write the new Driver value */
1595 rc
= RegSetValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
1596 if (rc
!= ERROR_SUCCESS
)
1605 /* Open the existing driver key */
1607 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
1610 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1614 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, (LPBYTE
)DriverKey
, &dwSize
);
1615 if (rc
!= ERROR_SUCCESS
)
1621 rc
= RegCreateKeyExW(hClassKey
,
1625 REG_OPTION_NON_VOLATILE
,
1626 #if _WIN32_WINNT >= 0x502
1627 KEY_READ
| KEY_WRITE
,
1634 if (rc
!= ERROR_SUCCESS
)
1642 /* Do installation of the specified section */
1645 FIXME("Need to install section %s in file %p\n",
1646 debugstr_w(InfSectionName
), InfHandle
);
1652 RpcStringFreeW(&lpGuidString
);
1653 HeapFree(GetProcessHeap(), 0, DriverKey
);
1654 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1655 RegCloseKey(hHWProfileKey
);
1656 if (hEnumKey
!= NULL
)
1657 RegCloseKey(hEnumKey
);
1658 if (hClassKey
!= NULL
)
1659 RegCloseKey(hClassKey
);
1660 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
1661 RegCloseKey(hDeviceKey
);
1662 if (hKey
!= NULL
&& hKey
!= key
)
1665 TRACE("Returning 0x%p\n", key
);
1669 /***********************************************************************
1670 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1672 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1673 HDEVINFO DeviceInfoSet
,
1675 CONST GUID
*ClassGuid
,
1676 PCSTR DeviceDescription
,
1678 DWORD CreationFlags
,
1679 PSP_DEVINFO_DATA DeviceInfoData
)
1682 LPWSTR DeviceNameW
= NULL
;
1683 LPWSTR DeviceDescriptionW
= NULL
;
1689 DeviceNameW
= pSetupMultiByteToUnicode(DeviceName
, CP_ACP
);
1690 if (DeviceNameW
== NULL
) return FALSE
;
1692 if (DeviceDescription
)
1694 DeviceDescriptionW
= pSetupMultiByteToUnicode(DeviceDescription
, CP_ACP
);
1695 if (DeviceDescriptionW
== NULL
)
1697 MyFree(DeviceNameW
);
1702 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1703 hwndParent
, CreationFlags
, DeviceInfoData
);
1705 MyFree(DeviceNameW
);
1706 MyFree(DeviceDescriptionW
);
1711 /***********************************************************************
1712 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1714 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1715 HDEVINFO DeviceInfoSet
,
1717 CONST GUID
*ClassGuid
,
1718 PCWSTR DeviceDescription
,
1720 DWORD CreationFlags
,
1721 PSP_DEVINFO_DATA DeviceInfoData
)
1723 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1724 struct DeviceInfo
*deviceInfo
= NULL
;
1727 DEVINST RootDevInst
;
1730 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1731 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1732 hwndParent
, CreationFlags
, DeviceInfoData
);
1736 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1739 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1741 SetLastError(ERROR_INVALID_HANDLE
);
1746 SetLastError(ERROR_INVALID_PARAMETER
);
1749 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1751 SetLastError(ERROR_INVALID_HANDLE
);
1754 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1755 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1757 SetLastError(ERROR_CLASS_MISMATCH
);
1760 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1762 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1763 SetLastError(ERROR_INVALID_FLAGS
);
1767 /* Get the root device instance */
1768 cr
= CM_Locate_DevInst_ExW(&RootDevInst
,
1770 CM_LOCATE_DEVINST_NORMAL
,
1772 if (cr
!= CR_SUCCESS
)
1774 SetLastError(ERROR_INVALID_DATA
);
1778 /* Create the new device instance */
1779 cr
= CM_Create_DevInst_ExW(&DevInst
,
1780 (DEVINSTID
)DeviceName
,
1784 if (cr
!= CR_SUCCESS
)
1786 SetLastError(ERROR_INVALID_DATA
);
1790 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1792 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1794 if (!DeviceInfoData
)
1798 if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1800 SetLastError(ERROR_INVALID_USER_BUFFER
);
1804 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1805 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1806 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1814 if (deviceInfo
!= NULL
)
1816 /* Remove deviceInfo from List */
1817 RemoveEntryList(&deviceInfo
->ListEntry
);
1819 /* Destroy deviceInfo */
1820 DestroyDeviceInfo(deviceInfo
);
1824 TRACE("Returning %d\n", ret
);
1828 /***********************************************************************
1829 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1831 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1832 HDEVINFO DeviceInfoSet
,
1833 PSP_DEVINFO_DATA DeviceInfoData
,
1835 PSP_DETSIG_CMPPROC CompareProc
,
1836 PVOID CompareContext
,
1837 PSP_DEVINFO_DATA DupDeviceInfoData
)
1839 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1841 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1842 CompareProc
, CompareContext
, DupDeviceInfoData
);
1844 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1846 SetLastError(ERROR_INVALID_HANDLE
);
1849 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1851 SetLastError(ERROR_INVALID_HANDLE
);
1854 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1855 || !DeviceInfoData
->Reserved
)
1857 SetLastError(ERROR_INVALID_PARAMETER
);
1860 FIXME("Stub %p %p 0x%lx %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1861 CompareProc
, CompareContext
, DupDeviceInfoData
);
1862 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1866 /***********************************************************************
1867 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1869 BOOL WINAPI
SetupDiEnumDeviceInfo(
1872 PSP_DEVINFO_DATA info
)
1876 TRACE("%p %d %p\n", devinfo
, index
, info
);
1880 SetLastError(ERROR_INVALID_PARAMETER
);
1883 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1885 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1886 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1888 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1889 SetLastError(ERROR_INVALID_USER_BUFFER
);
1892 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1893 while (ItemList
!= &list
->ListHead
&& index
-- > 0)
1894 ItemList
= ItemList
->Flink
;
1895 if (ItemList
== &list
->ListHead
)
1896 SetLastError(ERROR_NO_MORE_ITEMS
);
1899 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1900 memcpy(&info
->ClassGuid
,
1901 &DevInfo
->ClassGuid
,
1903 info
->DevInst
= DevInfo
->dnDevInst
;
1904 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1910 SetLastError(ERROR_INVALID_HANDLE
);
1913 SetLastError(ERROR_INVALID_HANDLE
);
1917 /***********************************************************************
1918 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1920 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1921 HDEVINFO DeviceInfoSet
,
1922 PSP_DEVINFO_DATA DeviceInfoData
,
1923 PSTR DeviceInstanceId
,
1924 DWORD DeviceInstanceIdSize
,
1925 PDWORD RequiredSize
)
1931 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1932 DeviceInstanceIdSize
, RequiredSize
);
1934 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1936 SetLastError(ERROR_INVALID_PARAMETER
);
1940 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1945 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1947 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
1950 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1957 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
1959 DeviceInstanceIdSize
, NULL
, NULL
);
1965 if (len
> DeviceInstanceIdSize
)
1967 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1971 *RequiredSize
= len
;
1979 *RequiredSize
= size
;
1980 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1986 /***********************************************************************
1987 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1989 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
1990 HDEVINFO DeviceInfoSet
,
1991 PSP_DEVINFO_DATA DeviceInfoData
,
1992 PWSTR DeviceInstanceId
,
1993 DWORD DeviceInstanceIdSize
,
1994 PDWORD RequiredSize
)
1996 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1997 struct DeviceInfo
*devInfo
;
1999 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
2000 DeviceInstanceIdSize
, RequiredSize
);
2002 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2004 SetLastError(ERROR_INVALID_HANDLE
);
2007 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2009 SetLastError(ERROR_INVALID_HANDLE
);
2012 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2013 || !DeviceInfoData
->Reserved
)
2015 SetLastError(ERROR_INVALID_PARAMETER
);
2018 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2019 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
2021 SetLastError(ERROR_INVALID_PARAMETER
);
2024 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
2026 SetLastError(ERROR_INVALID_PARAMETER
);
2029 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
2030 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
2032 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2034 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2037 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
2039 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2043 /***********************************************************************
2044 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
2046 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
2048 PCSTR InfSectionName
,
2049 PSTR InfSectionWithExt
,
2050 DWORD InfSectionWithExtSize
,
2051 PDWORD RequiredSize
,
2054 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
2055 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2059 /***********************************************************************
2060 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2062 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
2064 PCWSTR InfSectionName
,
2065 PWSTR InfSectionWithExt
,
2066 DWORD InfSectionWithExtSize
,
2067 PDWORD RequiredSize
,
2070 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
2071 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2075 /***********************************************************************
2076 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2079 SetupDiGetActualSectionToInstallExA(
2081 IN PCSTR InfSectionName
,
2082 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
2083 OUT PSTR InfSectionWithExt OPTIONAL
,
2084 IN DWORD InfSectionWithExtSize
,
2085 OUT PDWORD RequiredSize OPTIONAL
,
2086 OUT PSTR
* Extension OPTIONAL
,
2089 LPWSTR InfSectionNameW
= NULL
;
2090 LPWSTR InfSectionWithExtW
= NULL
;
2092 BOOL bResult
= FALSE
;
2098 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2099 if (InfSectionNameW
== NULL
)
2102 if (InfSectionWithExt
)
2104 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2105 if (InfSectionWithExtW
== NULL
)
2109 bResult
= SetupDiGetActualSectionToInstallExW(
2110 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2111 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2112 InfSectionWithExtSize
,
2114 Extension
? &ExtensionW
: NULL
,
2117 if (bResult
&& InfSectionWithExt
)
2119 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2120 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2122 if (bResult
&& Extension
)
2124 if (ExtensionW
== NULL
)
2127 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2131 MyFree(InfSectionNameW
);
2132 MyFree(InfSectionWithExtW
);
2137 /***********************************************************************
2138 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2140 BOOL WINAPI
SetupDiGetClassDescriptionA(
2141 const GUID
* ClassGuid
,
2142 PSTR ClassDescription
,
2143 DWORD ClassDescriptionSize
,
2144 PDWORD RequiredSize
)
2146 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2147 ClassDescriptionSize
,
2148 RequiredSize
, NULL
, NULL
);
2151 /***********************************************************************
2152 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2154 BOOL WINAPI
SetupDiGetClassDescriptionW(
2155 const GUID
* ClassGuid
,
2156 PWSTR ClassDescription
,
2157 DWORD ClassDescriptionSize
,
2158 PDWORD RequiredSize
)
2160 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2161 ClassDescriptionSize
,
2162 RequiredSize
, NULL
, NULL
);
2165 /***********************************************************************
2166 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2168 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2169 const GUID
* ClassGuid
,
2170 PSTR ClassDescription
,
2171 DWORD ClassDescriptionSize
,
2172 PDWORD RequiredSize
,
2176 PWCHAR ClassDescriptionW
= NULL
;
2177 LPWSTR MachineNameW
= NULL
;
2180 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2181 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2183 if (ClassDescriptionSize
> 0)
2185 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2186 if (!ClassDescriptionW
)
2188 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2195 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
2198 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2203 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2204 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2207 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2208 ClassDescriptionSize
, NULL
, NULL
);
2209 if (len
== 0 || len
> ClassDescriptionSize
)
2211 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2217 MyFree(ClassDescriptionW
);
2218 MyFree(MachineNameW
);
2222 /***********************************************************************
2223 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2225 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2226 const GUID
* ClassGuid
,
2227 PWSTR ClassDescription
,
2228 DWORD ClassDescriptionSize
,
2229 PDWORD RequiredSize
,
2239 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2240 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2242 /* Make sure there's a GUID */
2245 SetLastError(ERROR_INVALID_PARAMETER
);
2249 /* Make sure there's a real buffer when there's a size */
2250 if (!ClassDescription
&& ClassDescriptionSize
> 0)
2252 SetLastError(ERROR_INVALID_PARAMETER
);
2256 /* Open the key for the GUID */
2257 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2262 if (hKey
== INVALID_HANDLE_VALUE
)
2265 /* Retrieve the class description data and close the key */
2266 rc
= QueryRegistryValue(hKey
, NULL
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
2269 /* Make sure we got the data */
2270 if (rc
!= ERROR_SUCCESS
)
2276 /* Make sure the data is a string */
2277 if (dwRegType
!= REG_SZ
)
2280 SetLastError(ERROR_GEN_FAILURE
);
2284 /* Determine the length of the class description */
2285 dwLength
/= sizeof(WCHAR
);
2287 /* Count the null-terminator if none is present */
2288 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
2291 /* Inform the caller about the class description */
2292 if ((ClassDescription
!= NULL
) && (dwLength
<= ClassDescriptionSize
))
2294 memcpy(ClassDescription
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
2295 ClassDescription
[dwLength
- 1] = UNICODE_NULL
;
2298 /* Inform the caller about the required size */
2299 if (RequiredSize
!= NULL
)
2300 *RequiredSize
= dwLength
;
2302 /* Clean up the buffer */
2305 /* Make sure the buffer was large enough */
2306 if ((ClassDescription
== NULL
) || (dwLength
> ClassDescriptionSize
))
2308 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2315 /***********************************************************************
2316 * SetupDiGetClassDevsA (SETUPAPI.@)
2318 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2324 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2325 flags
, NULL
, NULL
, NULL
);
2328 /***********************************************************************
2329 * SetupDiGetClassDevsExA (SETUPAPI.@)
2331 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2341 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2345 enumstrW
= pSetupMultiByteToUnicode(enumstr
, CP_ACP
);
2348 ret
= INVALID_HANDLE_VALUE
;
2354 machineW
= pSetupMultiByteToUnicode(machine
, CP_ACP
);
2358 ret
= INVALID_HANDLE_VALUE
;
2362 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2363 machineW
, reserved
);
2371 /***********************************************************************
2372 * SetupDiGetClassDevsW (SETUPAPI.@)
2374 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2380 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2384 /***********************************************************************
2385 * SetupDiGetClassDevsExW (SETUPAPI.@)
2387 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2396 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2397 struct DeviceInfoSet
*list
;
2398 CONST GUID
*pClassGuid
;
2400 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2402 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2403 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2406 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2408 SetLastError(ERROR_INVALID_PARAMETER
);
2409 return INVALID_HANDLE_VALUE
;
2412 /* Create the deviceset if not set */
2415 list
= (struct DeviceInfoSet
*)deviceset
;
2416 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2418 SetLastError(ERROR_INVALID_HANDLE
);
2421 hDeviceInfo
= deviceset
;
2425 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2426 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2427 NULL
, machine
, NULL
);
2428 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2430 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2433 if (flags
& DIGCF_PROFILE
)
2434 FIXME(": flag DIGCF_PROFILE ignored\n");
2436 if (flags
& DIGCF_DEVICEINTERFACE
)
2440 SetLastError(ERROR_INVALID_PARAMETER
);
2443 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2447 /* Determine which class(es) should be included in the deviceset */
2448 if (flags
& DIGCF_ALLCLASSES
)
2450 /* The caller wants all classes. Check if
2451 * the deviceset limits us to one class */
2452 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2455 pClassGuid
= &list
->ClassGuid
;
2459 /* The caller wants one class. Check if it matches deviceset class */
2460 if (IsEqualIID(&list
->ClassGuid
, class)
2461 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2467 SetLastError(ERROR_INVALID_PARAMETER
);
2471 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2473 /* No class specified. Try to use the one of the deviceset */
2474 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2475 pClassGuid
= &list
->ClassGuid
;
2478 SetLastError(ERROR_INVALID_PARAMETER
);
2484 SetLastError(ERROR_INVALID_PARAMETER
);
2487 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2489 if (rc
!= ERROR_SUCCESS
)
2497 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2498 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2502 /***********************************************************************
2503 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2505 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2506 HDEVINFO DeviceInfoSet
,
2507 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2509 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2511 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2513 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2515 SetLastError(ERROR_INVALID_HANDLE
);
2518 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2520 SetLastError(ERROR_INVALID_HANDLE
);
2524 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2526 SetLastError(ERROR_INVALID_PARAMETER
);
2529 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2530 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2531 if (set
->MachineName
)
2534 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2538 DevInfoData
->RemoteMachineName
[0] = 0;
2543 /***********************************************************************
2544 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2546 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2547 HDEVINFO DeviceInfoSet
,
2548 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2550 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2552 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2554 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2556 SetLastError(ERROR_INVALID_HANDLE
);
2559 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2561 SetLastError(ERROR_INVALID_HANDLE
);
2565 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2567 SetLastError(ERROR_INVALID_PARAMETER
);
2570 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2571 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2572 if (set
->MachineName
)
2573 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2575 DevInfoData
->RemoteMachineName
[0] = 0;
2580 /***********************************************************************
2581 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2583 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2584 HDEVINFO DeviceInfoSet
,
2585 PSP_DEVINFO_DATA DeviceInfoData
,
2586 const GUID
*InterfaceClassGuid
,
2587 PCSTR ReferenceString
,
2588 DWORD CreationFlags
,
2589 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2592 LPWSTR ReferenceStringW
= NULL
;
2594 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2595 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2596 CreationFlags
, DeviceInterfaceData
);
2598 if (ReferenceString
)
2600 ReferenceStringW
= pSetupMultiByteToUnicode(ReferenceString
, CP_ACP
);
2601 if (ReferenceStringW
== NULL
) return FALSE
;
2604 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2605 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2606 DeviceInterfaceData
);
2608 MyFree(ReferenceStringW
);
2613 /***********************************************************************
2614 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2616 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2617 HDEVINFO DeviceInfoSet
,
2618 PSP_DEVINFO_DATA DeviceInfoData
,
2619 const GUID
*InterfaceClassGuid
,
2620 PCWSTR ReferenceString
,
2621 DWORD CreationFlags
,
2622 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2624 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2625 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2626 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2627 CreationFlags
, DeviceInterfaceData
);
2629 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2631 SetLastError(ERROR_INVALID_HANDLE
);
2634 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2636 SetLastError(ERROR_INVALID_HANDLE
);
2639 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2640 || !DeviceInfoData
->Reserved
)
2642 SetLastError(ERROR_INVALID_PARAMETER
);
2645 if (!InterfaceClassGuid
)
2647 SetLastError(ERROR_INVALID_USER_BUFFER
);
2651 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2652 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2653 CreationFlags
, DeviceInterfaceData
);
2654 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2658 /***********************************************************************
2659 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2661 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2662 HDEVINFO DeviceInfoSet
,
2663 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2667 PCSTR InfSectionName
)
2670 PWSTR InfSectionNameW
= NULL
;
2672 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2673 samDesired
, InfHandle
, InfSectionName
);
2676 if (!InfSectionName
)
2678 SetLastError(ERROR_INVALID_PARAMETER
);
2679 return INVALID_HANDLE_VALUE
;
2681 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2682 if (!InfSectionNameW
)
2683 return INVALID_HANDLE_VALUE
;
2685 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2686 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2688 MyFree(InfSectionNameW
);
2692 /***********************************************************************
2693 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2695 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2696 HDEVINFO DeviceInfoSet
,
2697 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2701 PCWSTR InfSectionName
)
2704 LPWSTR SymbolicLink
;
2705 DWORD Length
, Index
;
2707 WCHAR bracedGuidString
[39];
2708 struct DeviceInterface
*DevItf
;
2709 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2711 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2712 samDesired
, InfHandle
, InfSectionName
);
2714 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2715 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2717 SetLastError(ERROR_INVALID_HANDLE
);
2718 return INVALID_HANDLE_VALUE
;
2720 if (!DeviceInterfaceData
||
2721 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2722 !DeviceInterfaceData
->Reserved
)
2724 SetLastError(ERROR_INVALID_PARAMETER
);
2725 return INVALID_HANDLE_VALUE
;
2727 if (InfHandle
&& !InfSectionName
)
2729 SetLastError(ERROR_INVALID_PARAMETER
);
2730 return INVALID_HANDLE_VALUE
;
2733 hKey
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2734 if (hKey
== INVALID_HANDLE_VALUE
)
2736 hKey
= SetupDiOpenClassRegKeyExW(NULL
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2737 if (hKey
== INVALID_HANDLE_VALUE
)
2739 SetLastError(ERROR_INVALID_PARAMETER
);
2740 return INVALID_HANDLE_VALUE
;
2742 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
, bracedGuidString
);
2744 if (RegCreateKeyExW(hKey
, bracedGuidString
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
) != ERROR_SUCCESS
)
2746 SetLastError(ERROR_INVALID_PARAMETER
);
2747 return INVALID_HANDLE_VALUE
;
2753 DevItf
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2755 Length
= (wcslen(DevItf
->SymbolicLink
)+1) * sizeof(WCHAR
);
2756 SymbolicLink
= HeapAlloc(GetProcessHeap(), 0, Length
);
2760 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2761 return INVALID_HANDLE_VALUE
;
2764 wcscpy(SymbolicLink
, DevItf
->SymbolicLink
);
2767 while(SymbolicLink
[Index
])
2769 if (SymbolicLink
[Index
] == L
'\\')
2771 SymbolicLink
[Index
] = L
'#';
2776 rc
= RegCreateKeyExW(hKey
, SymbolicLink
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
);
2779 HeapFree(GetProcessHeap(), 0, SymbolicLink
);
2781 if (rc
== ERROR_SUCCESS
)
2783 if (InfHandle
&& InfSectionName
)
2785 if (!SetupInstallFromInfSection(NULL
/*FIXME */,
2788 SPINST_INIFILES
| SPINST_REGISTRY
| SPINST_INI2REG
| SPINST_FILES
| SPINST_BITREG
| SPINST_REGSVR
| SPINST_UNREGSVR
| SPINST_PROFILEITEMS
| SPINST_COPYINF
,
2792 set
->SelectedDevice
->InstallParams
.InstallMsgHandler
,
2793 set
->SelectedDevice
->InstallParams
.InstallMsgHandlerContext
,
2794 INVALID_HANDLE_VALUE
,
2797 RegCloseKey(hDevKey
);
2798 return INVALID_HANDLE_VALUE
;
2807 /***********************************************************************
2808 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2810 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2811 HDEVINFO DeviceInfoSet
,
2812 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2815 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2818 TRACE("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2820 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2821 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2823 SetLastError(ERROR_INVALID_HANDLE
);
2826 if (!DeviceInterfaceData
||
2827 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2828 !DeviceInterfaceData
->Reserved
)
2830 SetLastError(ERROR_INVALID_PARAMETER
);
2834 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2835 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2839 /***********************************************************************
2840 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2843 * DeviceInfoSet [I] Set of devices from which to enumerate
2845 * DeviceInfoData [I] (Optional) If specified, a specific device
2846 * instance from which to enumerate interfaces.
2847 * If it isn't specified, all interfaces for all
2848 * devices in the set are enumerated.
2849 * InterfaceClassGuid [I] The interface class to enumerate.
2850 * MemberIndex [I] An index of the interface instance to enumerate.
2851 * A caller should start with MemberIndex set to 0,
2852 * and continue until the function fails with
2853 * ERROR_NO_MORE_ITEMS.
2854 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2855 * member must be set to
2856 * sizeof(SP_DEVICE_INTERFACE_DATA).
2859 * Success: non-zero value.
2860 * Failure: FALSE. Call GetLastError() for more info.
2862 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2863 HDEVINFO DeviceInfoSet
,
2864 PSP_DEVINFO_DATA DeviceInfoData
,
2865 CONST GUID
* InterfaceClassGuid
,
2867 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2869 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2872 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet
, DeviceInfoData
,
2873 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2875 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2876 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2878 SetLastError(ERROR_INVALID_HANDLE
);
2881 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2882 !DeviceInfoData
->Reserved
))
2884 SetLastError(ERROR_INVALID_PARAMETER
);
2887 if (!DeviceInterfaceData
||
2888 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2890 SetLastError(ERROR_INVALID_PARAMETER
);
2895 struct DeviceInfo
*devInfo
=
2896 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2898 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2899 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2901 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2902 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2904 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2907 if (MemberIndex
-- == 0)
2909 /* return this item */
2910 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2911 &DevItf
->InterfaceClassGuid
,
2913 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2914 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2918 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2921 SetLastError(ERROR_NO_MORE_ITEMS
);
2926 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
2927 while (ItemList
!= &set
->ListHead
&& !found
)
2929 PLIST_ENTRY InterfaceListEntry
;
2930 struct DeviceInfo
*devInfo
=
2931 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
2932 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2933 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2935 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2936 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2938 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2941 if (MemberIndex
-- == 0)
2943 /* return this item */
2944 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2945 &DevItf
->InterfaceClassGuid
,
2947 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2948 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2952 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2954 ItemList
= ItemList
->Flink
;
2958 SetLastError(ERROR_NO_MORE_ITEMS
);
2963 /***********************************************************************
2964 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2966 * Destroy a DeviceInfoList and free all used memory of the list.
2969 * devinfo [I] DeviceInfoList pointer to list to destroy
2972 * Success: non zero value.
2973 * Failure: zero value.
2975 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2979 TRACE("%p\n", devinfo
);
2980 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
2982 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2984 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
2986 ret
= DestroyDeviceInfoSet(list
);
2991 SetLastError(ERROR_INVALID_HANDLE
);
2996 /***********************************************************************
2997 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2999 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
3000 HDEVINFO DeviceInfoSet
,
3001 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3002 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
3003 DWORD DeviceInterfaceDetailDataSize
,
3004 PDWORD RequiredSize
,
3005 PSP_DEVINFO_DATA DeviceInfoData
)
3007 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3008 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
3009 DWORD sizeW
= 0, bytesNeeded
;
3012 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3013 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3014 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3016 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3017 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3019 SetLastError(ERROR_INVALID_HANDLE
);
3022 if (!DeviceInterfaceData
||
3023 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3024 !DeviceInterfaceData
->Reserved
)
3026 SetLastError(ERROR_INVALID_PARAMETER
);
3029 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
3031 SetLastError(ERROR_INVALID_USER_BUFFER
);
3035 if((DeviceInterfaceDetailDataSize
!= 0) &&
3036 (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + sizeof(CHAR
))))
3038 SetLastError(ERROR_INVALID_USER_BUFFER
);
3042 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3044 SetLastError(ERROR_INVALID_USER_BUFFER
);
3049 if (DeviceInterfaceDetailData
!= NULL
)
3051 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
3052 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
3053 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
3054 if (!DeviceInterfaceDetailDataW
)
3056 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3058 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
3060 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
3062 ret
= SetupDiGetDeviceInterfaceDetailW(
3064 DeviceInterfaceData
,
3065 DeviceInterfaceDetailDataW
,
3069 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
3070 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
3072 *RequiredSize
= bytesNeeded
;
3073 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
>= bytesNeeded
)
3075 if (!WideCharToMultiByte(
3077 DeviceInterfaceDetailDataW
->DevicePath
, -1,
3078 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
3085 MyFree(DeviceInterfaceDetailDataW
);
3090 /***********************************************************************
3091 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3093 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
3094 HDEVINFO DeviceInfoSet
,
3095 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3096 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
3097 DWORD DeviceInterfaceDetailDataSize
,
3098 PDWORD RequiredSize
,
3099 PSP_DEVINFO_DATA DeviceInfoData
)
3101 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3104 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3105 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3106 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3108 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3109 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3111 SetLastError(ERROR_INVALID_HANDLE
);
3114 if (!DeviceInterfaceData
||
3115 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3116 !DeviceInterfaceData
->Reserved
)
3118 SetLastError(ERROR_INVALID_PARAMETER
);
3121 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
3123 SetLastError(ERROR_INVALID_USER_BUFFER
);
3126 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3128 SetLastError(ERROR_INVALID_USER_BUFFER
);
3131 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3133 SetLastError(ERROR_INVALID_PARAMETER
);
3136 if ((DeviceInterfaceDetailData
!= NULL
)
3137 && (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) + sizeof(WCHAR
)))
3139 SetLastError(ERROR_INVALID_PARAMETER
);
3144 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
3145 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
3146 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
3147 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
3149 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
3151 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3153 *RequiredSize
= sizeRequired
;
3157 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3158 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3161 memcpy(&DeviceInfoData
->ClassGuid
,
3162 &deviceInterface
->DeviceInfo
->ClassGuid
,
3164 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3165 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3173 struct PropertyMapEntry
3180 static struct PropertyMapEntry PropertyMap
[] = {
3181 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3182 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3183 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3184 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3185 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3186 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3187 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3188 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3189 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3190 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3191 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3192 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3193 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3194 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3195 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3196 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3197 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3198 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3199 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3200 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3201 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3202 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3203 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3204 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3205 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3206 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3207 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3208 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3209 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3210 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3211 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3212 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3213 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3214 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3215 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3218 /***********************************************************************
3219 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3221 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3222 HDEVINFO DeviceInfoSet
,
3223 PSP_DEVINFO_DATA DeviceInfoData
,
3225 PDWORD PropertyRegDataType
,
3226 PBYTE PropertyBuffer
,
3227 DWORD PropertyBufferSize
,
3228 PDWORD RequiredSize
)
3231 BOOL bIsStringProperty
;
3233 DWORD RequiredSizeA
, RequiredSizeW
;
3234 DWORD PropertyBufferSizeW
= 0;
3235 PBYTE PropertyBufferW
= NULL
;
3237 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3238 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3241 if (PropertyBufferSize
!= 0)
3243 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3244 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3245 if (!PropertyBufferW
)
3247 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3252 ret
= SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
3257 PropertyBufferSizeW
,
3260 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3262 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
3264 if (bIsStringProperty
)
3265 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
3267 RequiredSizeA
= RequiredSizeW
;
3269 *RequiredSize
= RequiredSizeA
;
3270 if (PropertyRegDataType
)
3271 *PropertyRegDataType
= RegType
;
3276 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3280 if (RequiredSizeA
<= PropertyBufferSize
)
3282 if (bIsStringProperty
&& PropertyBufferSize
> 0)
3284 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
3286 /* Last error is already set by WideCharToMultiByte */
3291 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
3295 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3299 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3303 /***********************************************************************
3304 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3306 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3307 HDEVINFO DeviceInfoSet
,
3308 PSP_DEVINFO_DATA DeviceInfoData
,
3310 PDWORD PropertyRegDataType
,
3311 PBYTE PropertyBuffer
,
3312 DWORD PropertyBufferSize
,
3313 PDWORD RequiredSize
)
3316 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3317 struct DeviceInfo
*devInfo
;
3319 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3320 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3323 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3325 SetLastError(ERROR_INVALID_HANDLE
);
3328 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3330 SetLastError(ERROR_INVALID_HANDLE
);
3333 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3334 || !DeviceInfoData
->Reserved
)
3336 SetLastError(ERROR_INVALID_PARAMETER
);
3339 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3340 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3341 && PropertyMap
[Property
].nameW
)
3343 DWORD size
= PropertyBufferSize
;
3346 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_QUERY_VALUE
);
3347 if (hKey
== INVALID_HANDLE_VALUE
)
3349 l
= RegQueryValueExW(hKey
, PropertyMap
[Property
].nameW
,
3350 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3354 *RequiredSize
= size
;
3357 if (PropertyBuffer
!= NULL
|| size
== 0)
3360 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3362 case ERROR_MORE_DATA
:
3363 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3369 else if (Property
== SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
)
3371 DWORD required
= (strlenW(devInfo
->Data
) + 1) * sizeof(WCHAR
);
3373 if (PropertyRegDataType
)
3374 *PropertyRegDataType
= REG_SZ
;
3376 *RequiredSize
= required
;
3377 if (PropertyBufferSize
>= required
)
3379 strcpyW((LPWSTR
)PropertyBuffer
, devInfo
->Data
);
3383 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3387 ERR("Property 0x%lx not implemented\n", Property
);
3388 SetLastError(ERROR_NOT_SUPPORTED
);
3393 /***********************************************************************
3394 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3396 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3397 HDEVINFO DeviceInfoSet
,
3398 PSP_DEVINFO_DATA DeviceInfoData
,
3400 const BYTE
*PropertyBuffer
,
3401 DWORD PropertyBufferSize
)
3404 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3406 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3407 PropertyBuffer
, PropertyBufferSize
);
3409 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3411 SetLastError(ERROR_INVALID_HANDLE
);
3414 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3416 SetLastError(ERROR_INVALID_HANDLE
);
3419 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3420 || !DeviceInfoData
->Reserved
)
3422 SetLastError(ERROR_INVALID_PARAMETER
);
3426 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3427 Property
, PropertyBuffer
, PropertyBufferSize
);
3428 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3432 /***********************************************************************
3433 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3435 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3436 HDEVINFO DeviceInfoSet
,
3437 PSP_DEVINFO_DATA DeviceInfoData
,
3439 const BYTE
*PropertyBuffer
,
3440 DWORD PropertyBufferSize
)
3443 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3445 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3446 PropertyBuffer
, PropertyBufferSize
);
3448 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3450 SetLastError(ERROR_INVALID_HANDLE
);
3453 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3455 SetLastError(ERROR_INVALID_HANDLE
);
3458 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3459 || !DeviceInfoData
->Reserved
)
3461 SetLastError(ERROR_INVALID_PARAMETER
);
3464 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3465 && PropertyMap
[Property
].nameW
)
3469 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3470 if (hKey
== INVALID_HANDLE_VALUE
)
3472 /* Write new data */
3474 hKey
, PropertyMap
[Property
].nameW
, 0,
3475 PropertyMap
[Property
].regType
, PropertyBuffer
,
3476 PropertyBufferSize
);
3485 ERR("Property 0x%lx not implemented\n", Property
);
3486 SetLastError(ERROR_NOT_SUPPORTED
);
3489 TRACE("Returning %d\n", ret
);
3493 /***********************************************************************
3494 * SetupDiInstallClassA (SETUPAPI.@)
3496 BOOL WINAPI
SetupDiInstallClassA(
3502 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3505 /***********************************************************************
3506 * SetupDiInstallClassExA (SETUPAPI.@)
3509 SetupDiInstallClassExA(
3510 IN HWND hwndParent OPTIONAL
,
3511 IN PCSTR InfFileName OPTIONAL
,
3513 IN HSPFILEQ FileQueue OPTIONAL
,
3514 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3518 PWSTR InfFileNameW
= NULL
;
3523 SetLastError(ERROR_INVALID_PARAMETER
);
3528 InfFileNameW
= pSetupMultiByteToUnicode(InfFileName
, CP_ACP
);
3529 if (InfFileNameW
== NULL
)
3531 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3536 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3537 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3539 MyFree(InfFileNameW
);
3544 HKEY
SETUP_CreateClassKey(HINF hInf
)
3546 static const WCHAR slash
[] = { '\\',0 };
3547 WCHAR FullBuffer
[MAX_PATH
];
3548 WCHAR Buffer
[MAX_PATH
];
3552 if (!SetupGetLineTextW(NULL
,
3560 return INVALID_HANDLE_VALUE
;
3563 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3564 lstrcatW(FullBuffer
, slash
);
3565 lstrcatW(FullBuffer
, Buffer
);
3567 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3573 if (!SetupGetLineTextW(NULL
,
3581 return INVALID_HANDLE_VALUE
;
3584 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3588 REG_OPTION_NON_VOLATILE
,
3594 return INVALID_HANDLE_VALUE
;
3598 if (RegSetValueExW(hClassKey
,
3603 RequiredSize
* sizeof(WCHAR
)))
3605 RegCloseKey(hClassKey
);
3606 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3608 return INVALID_HANDLE_VALUE
;
3614 /***********************************************************************
3615 * SetupDiInstallClassW (SETUPAPI.@)
3617 BOOL WINAPI
SetupDiInstallClassW(
3623 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3627 /***********************************************************************
3628 * SetupDiOpenClassRegKey (SETUPAPI.@)
3630 HKEY WINAPI
SetupDiOpenClassRegKey(
3631 const GUID
* ClassGuid
,
3634 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3635 DIOCR_INSTALLER
, NULL
, NULL
);
3639 /***********************************************************************
3640 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3642 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3643 const GUID
* ClassGuid
,
3649 PWSTR MachineNameW
= NULL
;
3652 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3653 Flags
, debugstr_a(MachineName
), Reserved
);
3657 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
3658 if (MachineNameW
== NULL
)
3659 return INVALID_HANDLE_VALUE
;
3662 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3663 Flags
, MachineNameW
, Reserved
);
3665 MyFree(MachineNameW
);
3671 /***********************************************************************
3672 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3674 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3675 const GUID
* ClassGuid
,
3687 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3688 Flags
, debugstr_w(MachineName
), Reserved
);
3690 if (MachineName
!= NULL
)
3692 l
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3693 if (l
!= ERROR_SUCCESS
)
3696 return INVALID_HANDLE_VALUE
;
3700 HKLM
= HKEY_LOCAL_MACHINE
;
3702 if (Flags
== DIOCR_INSTALLER
)
3704 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3706 else if (Flags
== DIOCR_INTERFACE
)
3708 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3712 ERR("Invalid Flags parameter!\n");
3713 SetLastError(ERROR_INVALID_FLAGS
);
3714 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3715 return INVALID_HANDLE_VALUE
;
3720 if ((l
= RegOpenKeyExW(HKLM
,
3726 SetLastError(ERROR_INVALID_CLASS
);
3727 hClassesKey
= INVALID_HANDLE_VALUE
;
3729 if (MachineName
!= NULL
)
3735 WCHAR bracedGuidString
[39];
3737 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3739 if (!(l
= RegOpenKeyExW(HKLM
,
3745 if (MachineName
!= NULL
)
3748 if ((l
= RegOpenKeyExW(hClassesKey
,
3755 key
= INVALID_HANDLE_VALUE
;
3757 RegCloseKey(hClassesKey
);
3761 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3763 key
= INVALID_HANDLE_VALUE
;
3770 /***********************************************************************
3771 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3773 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3774 HDEVINFO DeviceInfoSet
,
3777 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3779 struct DeviceInfoSet
* list
;
3781 DWORD dwLength
, dwError
, dwIndex
, dwKeyName
, dwSubIndex
;
3783 WCHAR Buffer
[MAX_PATH
+ 1];
3784 WCHAR SymBuffer
[MAX_PATH
+ 1];
3785 WCHAR InstancePath
[MAX_PATH
+ 1];
3786 HKEY hKey
, hDevKey
, hSymKey
;
3787 struct DeviceInfo
* deviceInfo
;
3788 struct DeviceInterface
*deviceInterface
;
3790 PLIST_ENTRY ItemList
;
3791 PLIST_ENTRY InterfaceListEntry
;
3793 TRACE("%p %s %08x %p\n",
3794 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3797 if (DeviceInterfaceData
&& DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
3799 SetLastError(ERROR_INVALID_PARAMETER
);
3803 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3805 SetLastError(ERROR_INVALID_HANDLE
);
3809 list
= (struct DeviceInfoSet
* )DeviceInfoSet
;
3811 dwLength
= wcslen(DevicePath
);
3814 /* path must be at least a guid length + L'\0' */
3815 SetLastError(ERROR_BAD_PATHNAME
);
3819 if (DevicePath
[0] != L
'\\' ||
3820 DevicePath
[1] != L
'\\' ||
3821 (DevicePath
[2] != L
'?' && DevicePath
[2] != L
'.') ||
3822 DevicePath
[3] != L
'\\')
3824 /* invalid formatted path */
3825 SetLastError(ERROR_BAD_PATHNAME
);
3829 /* check for reference strings */
3830 pEnd
= wcschr(&DevicePath
[4], L
'\\');
3833 /* no reference string */
3834 pEnd
= DevicePath
+ dwLength
;
3838 wcscpy(Buffer
, pEnd
- 37);
3841 dwError
= UuidFromStringW(Buffer
, &ClassId
);
3842 if (dwError
!= NOERROR
)
3844 /* invalid formatted path */
3845 SetLastError(ERROR_BAD_PATHNAME
);
3849 hKey
= SetupDiOpenClassRegKeyExW(&ClassId
, KEY_READ
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
3851 if (hKey
== INVALID_HANDLE_VALUE
)
3853 /* invalid device class */
3857 ItemList
= list
->ListHead
.Flink
;
3858 while (ItemList
!= &list
->ListHead
)
3860 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
3861 InterfaceListEntry
= deviceInfo
->InterfaceListHead
.Flink
;
3862 while (InterfaceListEntry
!= &deviceInfo
->InterfaceListHead
)
3864 deviceInterface
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
3865 if (!IsEqualIID(&deviceInterface
->InterfaceClassGuid
, &ClassId
))
3867 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3871 if (!wcsicmp(deviceInterface
->SymbolicLink
, DevicePath
))
3873 if (DeviceInterfaceData
)
3875 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3876 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3877 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3891 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3892 dwError
= RegEnumKeyExW(hKey
, dwIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3894 if (dwError
!= ERROR_SUCCESS
)
3897 if (RegOpenKeyExW(hKey
, Buffer
, 0, KEY_READ
, &hDevKey
) != ERROR_SUCCESS
)
3901 InstancePath
[0] = 0;
3902 dwKeyName
= sizeof(InstancePath
);
3904 dwError
= RegQueryValueExW(hDevKey
, L
"DeviceInstance", NULL
, NULL
, (LPBYTE
)InstancePath
, &dwKeyName
);
3909 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3910 dwError
= RegEnumKeyExW(hDevKey
, dwSubIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3912 if (dwError
!= ERROR_SUCCESS
)
3915 dwError
= RegOpenKeyExW(hDevKey
, Buffer
, 0, KEY_READ
, &hSymKey
);
3916 if (dwError
!= ERROR_SUCCESS
)
3919 /* query for symbolic link */
3920 dwKeyName
= sizeof(SymBuffer
);
3921 SymBuffer
[0] = L
'\0';
3922 dwError
= RegQueryValueExW(hSymKey
, L
"SymbolicLink", NULL
, NULL
, (LPBYTE
)SymBuffer
, &dwKeyName
);
3924 if (dwError
!= ERROR_SUCCESS
)
3926 RegCloseKey(hSymKey
);
3930 if (!wcsicmp(SymBuffer
, DevicePath
))
3932 Ret
= CreateDeviceInfo(list
, InstancePath
, &ClassId
, &deviceInfo
);
3933 RegCloseKey(hSymKey
);
3934 RegCloseKey(hDevKey
);
3939 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymBuffer
) + 1) * sizeof(WCHAR
));
3940 if (deviceInterface
)
3943 CopyMemory(&deviceInterface
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3944 deviceInterface
->DeviceInfo
= deviceInfo
;
3945 deviceInterface
->Flags
= SPINT_ACTIVE
; //FIXME
3947 wcscpy(deviceInterface
->SymbolicLink
, SymBuffer
);
3949 InsertTailList(&deviceInfo
->InterfaceListHead
, &deviceInterface
->ListEntry
);
3950 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3953 if (DeviceInterfaceData
)
3955 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3956 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3957 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3962 SetLastError(ERROR_INVALID_USER_BUFFER
);
3968 HeapFree(GetProcessHeap(), 0, deviceInfo
);
3973 RegCloseKey(hSymKey
);
3977 RegCloseKey(hDevKey
);
3985 /***********************************************************************
3986 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3988 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3989 HDEVINFO DeviceInfoSet
,
3992 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3994 LPWSTR DevicePathW
= NULL
;
3997 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3999 DevicePathW
= pSetupMultiByteToUnicode(DevicePath
, CP_ACP
);
4000 if (DevicePathW
== NULL
)
4003 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
4004 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
4006 MyFree(DevicePathW
);
4011 /***********************************************************************
4012 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
4014 BOOL WINAPI
SetupDiSetClassInstallParamsA(
4015 HDEVINFO DeviceInfoSet
,
4016 PSP_DEVINFO_DATA DeviceInfoData
,
4017 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
4018 DWORD ClassInstallParamsSize
)
4020 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
4021 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
4026 IntSetupDiRegisterDeviceInfo(
4027 IN HDEVINFO DeviceInfoSet
,
4028 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
4030 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
4033 /***********************************************************************
4034 * SetupDiCallClassInstaller (SETUPAPI.@)
4036 BOOL WINAPI
SetupDiCallClassInstaller(
4037 DI_FUNCTION InstallFunction
,
4038 HDEVINFO DeviceInfoSet
,
4039 PSP_DEVINFO_DATA DeviceInfoData
)
4043 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4046 SetLastError(ERROR_INVALID_PARAMETER
);
4047 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4048 SetLastError(ERROR_INVALID_HANDLE
);
4049 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4050 SetLastError(ERROR_INVALID_HANDLE
);
4051 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
4052 SetLastError(ERROR_INVALID_HANDLE
);
4053 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4054 SetLastError(ERROR_INVALID_USER_BUFFER
);
4057 SP_DEVINSTALL_PARAMS_W InstallParams
;
4058 #define CLASS_COINSTALLER 0x1
4059 #define DEVICE_COINSTALLER 0x2
4060 #define CLASS_INSTALLER 0x4
4061 UCHAR CanHandle
= 0;
4062 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
4064 switch (InstallFunction
)
4066 case DIF_ADDPROPERTYPAGE_ADVANCED
:
4067 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4069 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
4070 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4072 case DIF_ALLOW_INSTALL
:
4073 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4076 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4078 case DIF_DESTROYPRIVATEDATA
:
4079 CanHandle
= CLASS_INSTALLER
;
4081 case DIF_INSTALLDEVICE
:
4082 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4083 DefaultHandler
= SetupDiInstallDevice
;
4085 case DIF_INSTALLDEVICEFILES
:
4086 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4087 DefaultHandler
= SetupDiInstallDriverFiles
;
4089 case DIF_INSTALLINTERFACES
:
4090 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4091 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
4093 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
4094 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4096 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
4097 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4099 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
4100 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4102 case DIF_NEWDEVICEWIZARD_PRESELECT
:
4103 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4105 case DIF_NEWDEVICEWIZARD_SELECT
:
4106 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4108 case DIF_POWERMESSAGEWAKE
:
4109 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4111 case DIF_PROPERTYCHANGE
:
4112 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4113 DefaultHandler
= SetupDiChangeState
;
4115 case DIF_REGISTER_COINSTALLERS
:
4116 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4117 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
4119 case DIF_REGISTERDEVICE
:
4120 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4121 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
4124 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4125 DefaultHandler
= SetupDiRemoveDevice
;
4127 case DIF_SELECTBESTCOMPATDRV
:
4128 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4129 DefaultHandler
= SetupDiSelectBestCompatDrv
;
4131 case DIF_SELECTDEVICE
:
4132 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4133 DefaultHandler
= SetupDiSelectDevice
;
4135 case DIF_TROUBLESHOOTER
:
4136 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4139 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4140 DefaultHandler
= SetupDiUnremoveDevice
;
4143 ERR("Install function %u not supported\n", InstallFunction
);
4144 SetLastError(ERROR_NOT_SUPPORTED
);
4147 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4148 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4149 /* Don't process this call, as a parameter is invalid */
4154 LIST_ENTRY ClassCoInstallersListHead
;
4155 LIST_ENTRY DeviceCoInstallersListHead
;
4156 HMODULE ClassInstallerLibrary
= NULL
;
4157 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
4158 COINSTALLER_CONTEXT_DATA Context
;
4159 PLIST_ENTRY ListEntry
;
4161 DWORD dwRegType
, dwLength
;
4162 DWORD rc
= NO_ERROR
;
4164 InitializeListHead(&ClassCoInstallersListHead
);
4165 InitializeListHead(&DeviceCoInstallersListHead
);
4167 if (CanHandle
& DEVICE_COINSTALLER
)
4169 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4170 if (hKey
!= INVALID_HANDLE_VALUE
)
4172 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4173 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4175 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4176 if (KeyBuffer
!= NULL
)
4178 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4179 if (rc
== ERROR_SUCCESS
)
4182 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4184 /* Add coinstaller to DeviceCoInstallersListHead list */
4185 struct CoInstallerElement
*coinstaller
;
4186 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
4187 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4190 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4191 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4192 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
4194 HeapFree(GetProcessHeap(), 0, coinstaller
);
4197 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4203 if (CanHandle
& CLASS_COINSTALLER
)
4207 REGSTR_PATH_CODEVICEINSTALLERS
,
4211 if (rc
== ERROR_SUCCESS
)
4213 LPWSTR lpGuidString
;
4214 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
4216 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
4217 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4219 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4220 if (KeyBuffer
!= NULL
)
4222 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4223 if (rc
== ERROR_SUCCESS
)
4226 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4228 /* Add coinstaller to ClassCoInstallersListHead list */
4229 struct CoInstallerElement
*coinstaller
;
4230 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
4231 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4234 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4235 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4236 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
4238 HeapFree(GetProcessHeap(), 0, coinstaller
);
4241 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4244 RpcStringFreeW(&lpGuidString
);
4249 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4251 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4252 if (hKey
!= INVALID_HANDLE_VALUE
)
4254 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4255 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4257 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4258 if (KeyBuffer
!= NULL
)
4260 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4261 if (rc
== ERROR_SUCCESS
)
4263 /* Get ClassInstaller function pointer */
4264 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4265 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4267 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4268 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4271 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4278 /* Call Class co-installers */
4279 Context
.PostProcessing
= FALSE
;
4281 ListEntry
= ClassCoInstallersListHead
.Flink
;
4282 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4284 struct CoInstallerElement
*coinstaller
;
4285 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4286 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4287 coinstaller
->PrivateData
= Context
.PrivateData
;
4288 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4290 coinstaller
->DoPostProcessing
= TRUE
;
4293 ListEntry
= ListEntry
->Flink
;
4296 /* Call Device co-installers */
4297 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4298 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4300 struct CoInstallerElement
*coinstaller
;
4301 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4302 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4303 coinstaller
->PrivateData
= Context
.PrivateData
;
4304 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4306 coinstaller
->DoPostProcessing
= TRUE
;
4309 ListEntry
= ListEntry
->Flink
;
4312 /* Call Class installer */
4315 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4316 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4319 rc
= ERROR_DI_DO_DEFAULT
;
4321 /* Call default handler */
4322 if (rc
== ERROR_DI_DO_DEFAULT
)
4324 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4326 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4329 rc
= GetLastError();
4335 /* Call Class co-installers that required postprocessing */
4336 Context
.PostProcessing
= TRUE
;
4337 ListEntry
= ClassCoInstallersListHead
.Flink
;
4338 while (ListEntry
!= &ClassCoInstallersListHead
)
4340 struct CoInstallerElement
*coinstaller
;
4341 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4342 if (coinstaller
->DoPostProcessing
)
4344 Context
.InstallResult
= rc
;
4345 Context
.PrivateData
= coinstaller
->PrivateData
;
4346 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4348 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4349 ListEntry
= ListEntry
->Flink
;
4352 /* Call Device co-installers that required postprocessing */
4353 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4354 while (ListEntry
!= &DeviceCoInstallersListHead
)
4356 struct CoInstallerElement
*coinstaller
;
4357 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4358 if (coinstaller
->DoPostProcessing
)
4360 Context
.InstallResult
= rc
;
4361 Context
.PrivateData
= coinstaller
->PrivateData
;
4362 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4364 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4365 ListEntry
= ListEntry
->Flink
;
4368 /* Free allocated memory */
4369 while (!IsListEmpty(&ClassCoInstallersListHead
))
4371 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4372 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4374 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4376 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4377 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4380 ret
= (rc
== NO_ERROR
);
4384 TRACE("Returning %d\n", ret
);
4388 /***********************************************************************
4389 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4391 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4392 HDEVINFO DeviceInfoSet
,
4393 PSP_DEVINFO_DATA DeviceInfoData
,
4394 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4396 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4399 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4401 if (DeviceInstallParams
== NULL
)
4402 SetLastError(ERROR_INVALID_PARAMETER
);
4403 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4404 SetLastError(ERROR_INVALID_USER_BUFFER
);
4407 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4408 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4412 /* Do W->A conversion */
4414 DeviceInstallParams
,
4415 &deviceInstallParamsW
,
4416 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4417 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4418 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4420 DeviceInstallParams
->DriverPath
[0] = '\0';
4426 TRACE("Returning %d\n", ret
);
4430 /***********************************************************************
4431 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4434 SetupDiGetDeviceInfoListClass(
4435 IN HDEVINFO DeviceInfoSet
,
4436 OUT LPGUID ClassGuid
)
4438 struct DeviceInfoSet
*list
;
4441 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4444 SetLastError(ERROR_INVALID_HANDLE
);
4445 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4446 SetLastError(ERROR_INVALID_HANDLE
);
4447 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4448 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4451 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4456 TRACE("Returning %d\n", ret
);
4460 /***********************************************************************
4461 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4464 SetupDiGetDeviceInstallParamsW(
4465 IN HDEVINFO DeviceInfoSet
,
4466 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4467 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4469 struct DeviceInfoSet
*list
;
4472 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4475 SetLastError(ERROR_INVALID_HANDLE
);
4476 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4477 SetLastError(ERROR_INVALID_HANDLE
);
4478 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4479 SetLastError(ERROR_INVALID_USER_BUFFER
);
4480 else if (!DeviceInstallParams
)
4481 SetLastError(ERROR_INVALID_PARAMETER
);
4482 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4483 SetLastError(ERROR_INVALID_USER_BUFFER
);
4486 PSP_DEVINSTALL_PARAMS_W Source
;
4489 Source
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4491 Source
= &list
->InstallParams
;
4497 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4499 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4501 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4507 TRACE("Returning %d\n", ret
);
4512 CheckDeviceInstallParameters(
4513 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4515 DWORD SupportedFlags
=
4516 DI_NOVCP
| /* 0x00000008 */
4517 DI_DIDCOMPAT
| /* 0x00000010 */
4518 DI_DIDCLASS
| /* 0x00000020 */
4519 DI_NEEDRESTART
| /* 0x00000080 */
4520 DI_NEEDREBOOT
| /* 0x00000100 */
4521 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4522 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4523 DI_ENUMSINGLEINF
| /* 0x00010000 */
4524 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
4525 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4526 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4527 DI_QUIETINSTALL
| /* 0x00800000 */
4528 DI_NOFILECOPY
| /* 0x01000000 */
4529 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4530 DWORD SupportedFlagsEx
=
4531 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4532 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4533 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4534 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4535 DI_FLAGSEX_NO_DRVREG_MODIFY
| /* 0x00008000 */
4536 DI_FLAGSEX_INSTALLEDDRIVER
; /* 0x04000000 */
4539 /* FIXME: add support for more flags */
4541 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4542 * It should be checked before accessing to other values
4543 * of the SP_DEVINSTALL_PARAMS structure */
4545 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4547 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4548 SetLastError(ERROR_INVALID_FLAGS
);
4550 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4552 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4553 SetLastError(ERROR_INVALID_FLAGS
);
4555 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4556 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4557 SetLastError(ERROR_INVALID_USER_BUFFER
);
4560 /* FIXME: check Reserved field */
4567 /***********************************************************************
4568 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4571 SetupDiSetDeviceInstallParamsW(
4572 IN HDEVINFO DeviceInfoSet
,
4573 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4574 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4576 struct DeviceInfoSet
*list
;
4579 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4582 SetLastError(ERROR_INVALID_HANDLE
);
4583 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4584 SetLastError(ERROR_INVALID_HANDLE
);
4585 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4586 SetLastError(ERROR_INVALID_USER_BUFFER
);
4587 else if (!DeviceInstallParams
)
4588 SetLastError(ERROR_INVALID_PARAMETER
);
4589 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4590 SetLastError(ERROR_INVALID_USER_BUFFER
);
4591 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4593 PSP_DEVINSTALL_PARAMS_W Destination
;
4596 Destination
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4598 Destination
= &list
->InstallParams
;
4599 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4603 TRACE("Returning %d\n", ret
);
4607 /***********************************************************************
4608 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4611 SetupDiSetDeviceInstallParamsA(
4612 HDEVINFO DeviceInfoSet
,
4613 PSP_DEVINFO_DATA DeviceInfoData
,
4614 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4616 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4620 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4622 if (DeviceInstallParams
== NULL
)
4623 SetLastError(ERROR_INVALID_PARAMETER
);
4624 else if (DeviceInstallParams
->cbSize
< sizeof(SP_DEVINSTALL_PARAMS_A
))
4625 SetLastError(ERROR_INVALID_USER_BUFFER
);
4628 memcpy(&deviceInstallParamsW
, DeviceInstallParams
, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A
, DriverPath
));
4629 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4630 len
= MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, NULL
, 0);
4633 ERR("DrivePath is NULL\n");
4638 MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, deviceInstallParamsW
.DriverPath
, len
);
4639 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4643 TRACE("Returning %d\n", ret
);
4648 OpenHardwareProfileKey(
4651 IN DWORD samDesired
)
4653 HKEY hHWProfilesKey
= NULL
;
4654 HKEY hHWProfileKey
= NULL
;
4655 HKEY ret
= INVALID_HANDLE_VALUE
;
4658 rc
= RegOpenKeyExW(HKLM
,
4659 REGSTR_PATH_HWPROFILES
,
4663 if (rc
!= ERROR_SUCCESS
)
4670 rc
= RegOpenKeyExW(hHWProfilesKey
,
4679 snprintfW(subKey
, 4, InstanceKeyFormat
, HwProfile
);
4681 rc
= RegOpenKeyExW(hHWProfilesKey
,
4687 if (rc
!= ERROR_SUCCESS
)
4692 ret
= hHWProfileKey
;
4695 if (hHWProfilesKey
!= NULL
)
4696 RegCloseKey(hHWProfilesKey
);
4697 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4698 RegCloseKey(hHWProfileKey
);
4703 IsDeviceInfoInDeviceInfoSet(
4704 struct DeviceInfoSet
*deviceInfoSet
,
4705 struct DeviceInfo
*deviceInfo
)
4707 PLIST_ENTRY ListEntry
;
4709 ListEntry
= deviceInfoSet
->ListHead
.Flink
;
4710 while (ListEntry
!= &deviceInfoSet
->ListHead
)
4712 if (deviceInfo
== CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
))
4715 ListEntry
= ListEntry
->Flink
;
4721 /***********************************************************************
4722 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4725 SetupDiDeleteDeviceInfo(
4726 IN HDEVINFO DeviceInfoSet
,
4727 IN PSP_DEVINFO_DATA DeviceInfoData
)
4729 struct DeviceInfoSet
*deviceInfoSet
;
4730 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
;
4733 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4736 SetLastError(ERROR_INVALID_HANDLE
);
4737 else if ((deviceInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4738 SetLastError(ERROR_INVALID_HANDLE
);
4739 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4740 SetLastError(ERROR_INVALID_USER_BUFFER
);
4741 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet
, deviceInfo
))
4742 SetLastError(ERROR_INVALID_PARAMETER
);
4745 RemoveEntryList(&deviceInfo
->ListEntry
);
4746 DestroyDeviceInfo(deviceInfo
);
4754 /***********************************************************************
4755 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4758 SetupDiOpenDeviceInfoA(
4759 IN HDEVINFO DeviceInfoSet
,
4760 IN PCSTR DeviceInstanceId
,
4761 IN HWND hwndParent OPTIONAL
,
4763 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4765 LPWSTR DeviceInstanceIdW
= NULL
;
4768 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4770 DeviceInstanceIdW
= pSetupMultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4771 if (DeviceInstanceIdW
== NULL
)
4774 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4775 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4777 MyFree(DeviceInstanceIdW
);
4783 /***********************************************************************
4784 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4787 SetupDiOpenDeviceInfoW(
4788 IN HDEVINFO DeviceInfoSet
,
4789 IN PCWSTR DeviceInstanceId
,
4790 IN HWND hwndParent OPTIONAL
,
4792 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4794 struct DeviceInfoSet
*list
;
4795 HKEY hEnumKey
, hKey
= NULL
;
4799 TRACE("%p %s %p %lx %p\n",
4800 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
4801 hwndParent
, OpenFlags
, DeviceInfoData
);
4803 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4804 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4807 SetLastError(ERROR_INVALID_HANDLE
);
4808 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4809 SetLastError(ERROR_INVALID_HANDLE
);
4810 else if (!DeviceInstanceId
)
4811 SetLastError(ERROR_INVALID_PARAMETER
);
4812 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4814 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4815 SetLastError(ERROR_INVALID_FLAGS
);
4817 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4818 SetLastError(ERROR_INVALID_USER_BUFFER
);
4821 struct DeviceInfo
*deviceInfo
= NULL
;
4822 /* Search if device already exists in DeviceInfoSet.
4823 * If yes, return the existing element
4824 * If no, create a new element using information in registry
4826 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4827 while (ItemList
!= &list
->ListHead
)
4832 FIXME("not implemented\n");
4833 ItemList
= ItemList
->Flink
;
4838 /* good one found */
4844 WCHAR szClassGuid
[MAX_GUID_STRING_LEN
];
4846 /* Open supposed registry key */
4849 REGSTR_PATH_SYSTEMENUM
,
4853 if (rc
!= ERROR_SUCCESS
)
4864 RegCloseKey(hEnumKey
);
4865 if (rc
!= ERROR_SUCCESS
)
4867 if (rc
== ERROR_FILE_NOT_FOUND
)
4868 rc
= ERROR_NO_SUCH_DEVINST
;
4873 ClassGUID
= GUID_NULL
;
4874 dwSize
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
4876 if (RegQueryValueExW(hKey
,
4877 REGSTR_VAL_CLASSGUID
,
4880 (LPBYTE
)szClassGuid
,
4881 &dwSize
) == ERROR_SUCCESS
)
4883 szClassGuid
[MAX_GUID_STRING_LEN
- 2] = UNICODE_NULL
;
4885 /* Convert a string to a ClassGuid */
4886 UuidFromStringW(&szClassGuid
[1], &ClassGUID
);
4889 if (!CreateDeviceInfo(list
, DeviceInstanceId
, &ClassGUID
, &deviceInfo
))
4892 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4897 if (ret
&& deviceInfo
&& DeviceInfoData
)
4899 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4900 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4901 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4912 /***********************************************************************
4913 * SetupDiGetSelectedDevice (SETUPAPI.@)
4916 SetupDiGetSelectedDevice(
4917 IN HDEVINFO DeviceInfoSet
,
4918 OUT PSP_DEVINFO_DATA DeviceInfoData
)
4920 struct DeviceInfoSet
*list
;
4923 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4926 SetLastError(ERROR_INVALID_HANDLE
);
4927 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4928 SetLastError(ERROR_INVALID_HANDLE
);
4929 else if (list
->SelectedDevice
== NULL
)
4930 SetLastError(ERROR_NO_DEVICE_SELECTED
);
4931 else if (!DeviceInfoData
)
4932 SetLastError(ERROR_INVALID_PARAMETER
);
4933 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4934 SetLastError(ERROR_INVALID_USER_BUFFER
);
4937 memcpy(&DeviceInfoData
->ClassGuid
,
4938 &list
->SelectedDevice
->ClassGuid
,
4940 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
4941 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
4945 TRACE("Returning %d\n", ret
);
4950 /***********************************************************************
4951 * SetupDiSetSelectedDevice (SETUPAPI.@)
4954 SetupDiSetSelectedDevice(
4955 IN HDEVINFO DeviceInfoSet
,
4956 IN PSP_DEVINFO_DATA DeviceInfoData
)
4958 struct DeviceInfoSet
*list
;
4961 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4964 SetLastError(ERROR_INVALID_HANDLE
);
4965 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4966 SetLastError(ERROR_INVALID_HANDLE
);
4967 else if (!DeviceInfoData
)
4968 SetLastError(ERROR_INVALID_PARAMETER
);
4969 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4970 SetLastError(ERROR_INVALID_USER_BUFFER
);
4971 else if (DeviceInfoData
->Reserved
== 0)
4972 SetLastError(ERROR_INVALID_USER_BUFFER
);
4975 list
->SelectedDevice
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
4979 TRACE("Returning %d\n", ret
);
4984 /* Return the current hardware profile id, or -1 if error */
4986 SETUPAPI_GetCurrentHwProfile(
4987 IN HDEVINFO DeviceInfoSet
)
4990 DWORD dwRegType
, dwLength
;
4993 DWORD ret
= (DWORD
)-1;
4995 rc
= RegOpenKeyExW(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
4996 REGSTR_PATH_IDCONFIGDB
,
5000 if (rc
!= ERROR_SUCCESS
)
5006 dwLength
= sizeof(DWORD
);
5007 rc
= RegQueryValueExW(hKey
,
5008 REGSTR_VAL_CURRENTCONFIG
,
5011 (LPBYTE
)&hwProfile
, &dwLength
);
5012 if (rc
!= ERROR_SUCCESS
)
5017 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5019 SetLastError(ERROR_GEN_FAILURE
);
5034 IN HDEVINFO DeviceInfoSet
,
5035 IN PSP_DEVINFO_DATA DeviceInfoData
)
5038 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5039 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5042 cr
= CM_Enable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
5043 if (cr
!= CR_SUCCESS
)
5045 SetLastError(GetErrorCodeFromCrCode(cr
));
5051 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5056 static BOOL
StopDevice(
5057 IN HDEVINFO DeviceInfoSet
,
5058 IN PSP_DEVINFO_DATA DeviceInfoData
)
5060 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5064 /***********************************************************************
5065 * SetupDiChangeState (SETUPAPI.@)
5069 IN HDEVINFO DeviceInfoSet
,
5070 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5072 PSP_PROPCHANGE_PARAMS PropChange
;
5073 HKEY hKey
= INVALID_HANDLE_VALUE
;
5074 LPCWSTR RegistryValueName
;
5075 DWORD dwConfigFlags
, dwLength
, dwRegType
;
5079 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5081 if (!DeviceInfoData
)
5082 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChangeParams
;
5084 PropChange
= ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChangeParams
;
5087 SetLastError(ERROR_INVALID_PARAMETER
);
5091 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
5092 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
5094 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
5096 switch (PropChange
->StateChange
)
5101 /* Enable/disable device in registry */
5102 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5103 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5104 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
5105 if (hKey
== INVALID_HANDLE_VALUE
)
5107 dwLength
= sizeof(DWORD
);
5108 rc
= RegQueryValueExW(
5113 (LPBYTE
)&dwConfigFlags
, &dwLength
);
5114 if (rc
== ERROR_FILE_NOT_FOUND
)
5116 else if (rc
!= ERROR_SUCCESS
)
5121 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5123 SetLastError(ERROR_GEN_FAILURE
);
5126 if (PropChange
->StateChange
== DICS_ENABLE
)
5127 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5129 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5130 rc
= RegSetValueExW(
5135 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
5136 if (rc
!= ERROR_SUCCESS
)
5142 /* Enable/disable device if needed */
5143 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
5144 || PropChange
->HwProfile
== 0
5145 || PropChange
->HwProfile
== SETUPAPI_GetCurrentHwProfile(DeviceInfoSet
))
5147 if (PropChange
->StateChange
== DICS_ENABLE
)
5148 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5150 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
5156 case DICS_PROPCHANGE
:
5158 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5163 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
5164 SetLastError(ERROR_NOT_SUPPORTED
);
5169 if (hKey
!= INVALID_HANDLE_VALUE
)
5172 TRACE("Returning %d\n", ret
);
5176 /***********************************************************************
5177 * SetupDiSelectDevice (SETUPAPI.@)
5180 SetupDiSelectDevice(
5181 IN HDEVINFO DeviceInfoSet
,
5182 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5184 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5185 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5190 /***********************************************************************
5191 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5194 SetupDiRegisterCoDeviceInstallers(
5195 IN HDEVINFO DeviceInfoSet
,
5196 IN PSP_DEVINFO_DATA DeviceInfoData
)
5198 BOOL ret
= FALSE
; /* Return value */
5200 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5203 SetLastError(ERROR_INVALID_PARAMETER
);
5204 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5205 SetLastError(ERROR_INVALID_HANDLE
);
5206 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5207 SetLastError(ERROR_INVALID_HANDLE
);
5208 else if (!DeviceInfoData
)
5209 SetLastError(ERROR_INVALID_PARAMETER
);
5210 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5211 SetLastError(ERROR_INVALID_USER_BUFFER
);
5214 SP_DEVINSTALL_PARAMS_W InstallParams
;
5215 struct DriverInfoElement
*SelectedDriver
;
5218 WCHAR SectionName
[MAX_PATH
];
5219 DWORD SectionNameLength
= 0;
5220 HKEY hKey
= INVALID_HANDLE_VALUE
;
5221 PVOID Context
= NULL
;
5223 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5224 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5228 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5229 if (SelectedDriver
== NULL
)
5231 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5235 /* Get .CoInstallers section name */
5236 Result
= SetupDiGetActualSectionToInstallW(
5237 SelectedDriver
->InfFileDetails
->hInf
,
5238 SelectedDriver
->Details
.SectionName
,
5239 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5240 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
5242 lstrcatW(SectionName
, DotCoInstallers
);
5244 /* Open/Create driver key information */
5245 #if _WIN32_WINNT >= 0x502
5246 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5248 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5250 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5251 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5252 if (hKey
== INVALID_HANDLE_VALUE
)
5255 /* Install .CoInstallers section */
5256 DoAction
= SPINST_REGISTRY
;
5257 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5259 DoAction
|= SPINST_FILES
;
5260 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5264 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5265 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5266 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5267 SetupDefaultQueueCallbackW
, Context
,
5268 DeviceInfoSet
, DeviceInfoData
);
5276 SetupTermDefaultQueueCallback(Context
);
5277 if (hKey
!= INVALID_HANDLE_VALUE
)
5281 TRACE("Returning %d\n", ret
);
5286 InfIsFromOEMLocation(
5288 OUT LPBOOL IsOEMLocation
)
5292 last
= strrchrW(FullName
, '\\');
5295 /* No directory specified */
5296 *IsOEMLocation
= FALSE
;
5303 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
5306 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5310 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
5311 if (ret
== 0 || ret
> MAX_PATH
)
5314 SetLastError(ERROR_GEN_FAILURE
);
5317 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
5318 strcatW(Windir
, BackSlash
);
5319 strcatW(Windir
, InfDirectory
);
5321 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
5323 /* The path is %SYSTEMROOT%\Inf */
5324 *IsOEMLocation
= FALSE
;
5328 /* The file is in another place */
5329 *IsOEMLocation
= TRUE
;
5336 /***********************************************************************
5337 * SetupDiInstallDevice (SETUPAPI.@)
5340 SetupDiInstallDevice(
5341 IN HDEVINFO DeviceInfoSet
,
5342 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5344 SP_DEVINSTALL_PARAMS_W InstallParams
;
5345 struct DriverInfoElement
*SelectedDriver
;
5346 SYSTEMTIME DriverDate
;
5347 WCHAR SectionName
[MAX_PATH
];
5349 DWORD SectionNameLength
= 0;
5350 BOOL Result
= FALSE
;
5353 LPWSTR pSectionName
= NULL
;
5354 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5356 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5357 BOOL RebootRequired
= FALSE
;
5358 HKEY hKey
= INVALID_HANDLE_VALUE
;
5359 BOOL NeedtoCopyFile
;
5360 LARGE_INTEGER fullVersion
;
5362 PVOID Context
= NULL
;
5363 BOOL ret
= FALSE
; /* Return value */
5365 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5368 SetLastError(ERROR_INVALID_PARAMETER
);
5369 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5370 SetLastError(ERROR_INVALID_HANDLE
);
5371 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5372 SetLastError(ERROR_INVALID_HANDLE
);
5373 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5374 SetLastError(ERROR_INVALID_USER_BUFFER
);
5380 /* One parameter is bad */
5384 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5385 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5389 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5391 /* Set FAILEDINSTALL in ConfigFlags registry value */
5392 DWORD ConfigFlags
, regType
;
5393 Result
= SetupDiGetDeviceRegistryPropertyW(
5398 (PBYTE
)&ConfigFlags
,
5399 sizeof(ConfigFlags
),
5401 if (!Result
|| regType
!= REG_DWORD
)
5403 SetLastError(ERROR_GEN_FAILURE
);
5406 ConfigFlags
|= DNF_DISABLED
;
5407 Result
= SetupDiSetDeviceRegistryPropertyW(
5411 (PBYTE
)&ConfigFlags
,
5412 sizeof(ConfigFlags
));
5415 SetLastError(ERROR_GEN_FAILURE
);
5423 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5424 if (SelectedDriver
== NULL
)
5426 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5430 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5432 Result
= SetupDiGetActualSectionToInstallW(
5433 SelectedDriver
->InfFileDetails
->hInf
,
5434 SelectedDriver
->Details
.SectionName
,
5435 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5436 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
5438 pSectionName
= &SectionName
[strlenW(SectionName
)];
5440 /* Get information from [Version] section */
5441 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5443 /* Format ClassGuid to a string */
5444 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5446 RequiredSize
= lstrlenW(lpGuidString
);
5447 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5448 if (!lpFullGuidString
)
5450 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5453 lpFullGuidString
[0] = '{';
5454 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5455 lpFullGuidString
[RequiredSize
+ 1] = '}';
5456 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5458 /* Copy .inf file to Inf\ directory (if needed) */
5459 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
5464 WCHAR NewFileName
[MAX_PATH
];
5465 struct InfFileDetails
*newInfFileDetails
;
5466 Result
= SetupCopyOEMInfW(
5467 SelectedDriver
->Details
.InfFileName
,
5470 SP_COPY_NOOVERWRITE
,
5471 NewFileName
, MAX_PATH
,
5476 /* Create a new struct InfFileDetails, and set it to
5477 * SelectedDriver->InfFileDetails, to release use of
5478 * current InfFile */
5479 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
5480 if (!newInfFileDetails
)
5482 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
5483 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
5484 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
5487 /* Open/Create driver key information */
5488 #if _WIN32_WINNT >= 0x502
5489 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5491 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5493 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5494 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5495 if (hKey
== INVALID_HANDLE_VALUE
)
5498 /* Install main section */
5500 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5501 DoAction
|= SPINST_REGISTRY
;
5502 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5504 DoAction
|= SPINST_FILES
;
5505 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5509 *pSectionName
= '\0';
5510 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5511 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5512 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5513 SetupDefaultQueueCallbackW
, Context
,
5514 DeviceInfoSet
, DeviceInfoData
);
5517 InstallParams
.Flags
|= DI_NOFILECOPY
;
5518 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5520 /* Write information to driver key */
5521 *pSectionName
= UNICODE_NULL
;
5522 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
5523 TRACE("Write information to driver key\n");
5524 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5525 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5526 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5527 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
5528 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
5529 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
5530 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
5531 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
5532 sprintfW(Buffer
, DateFormat
, DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5533 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5534 if (rc
== ERROR_SUCCESS
)
5535 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5536 if (rc
== ERROR_SUCCESS
)
5537 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5538 if (rc
== ERROR_SUCCESS
)
5540 sprintfW(Buffer
, VersionFormat
, fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5541 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5543 if (rc
== ERROR_SUCCESS
)
5544 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
5545 if (rc
== ERROR_SUCCESS
)
5546 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5547 if (rc
== ERROR_SUCCESS
)
5548 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTIONEXT
, 0, REG_SZ
, (const BYTE
*)&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)], (strlenW(SectionName
) - strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5549 if (rc
== ERROR_SUCCESS
)
5550 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5551 if (rc
== ERROR_SUCCESS
)
5552 rc
= RegSetValueExW(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5553 if (rc
!= ERROR_SUCCESS
)
5559 hKey
= INVALID_HANDLE_VALUE
;
5561 /* FIXME: Process .LogConfigOverride section */
5563 /* Install .Services section */
5564 strcpyW(pSectionName
, DotServices
);
5565 Result
= SetupInstallServicesFromInfSectionExW(
5566 SelectedDriver
->InfFileDetails
->hInf
,
5575 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5576 RebootRequired
= TRUE
;
5578 /* Open device registry key */
5579 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5580 if (hKey
== INVALID_HANDLE_VALUE
)
5583 /* Install .HW section */
5585 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5586 DoAction
|= SPINST_REGISTRY
;
5587 strcpyW(pSectionName
, DotHW
);
5588 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5589 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5590 DoAction
, hKey
, NULL
, 0,
5592 DeviceInfoSet
, DeviceInfoData
);
5596 /* Write information to enum key */
5597 TRACE("Write information to enum key\n");
5598 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
5599 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
5600 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5601 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
5602 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
5603 if (rc
== ERROR_SUCCESS
)
5604 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5605 if (rc
== ERROR_SUCCESS
)
5606 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5607 if (rc
== ERROR_SUCCESS
)
5608 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5609 if (rc
!= ERROR_SUCCESS
)
5615 /* Start the device */
5616 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5617 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5622 /* End of installation */
5623 if (hKey
!= INVALID_HANDLE_VALUE
)
5626 RpcStringFreeW(&lpGuidString
);
5627 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5629 SetupTermDefaultQueueCallback(Context
);
5630 TRACE("Returning %d\n", ret
);
5634 static HKEY
SETUPDI_OpenDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5636 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5639 l
= RegOpenKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, 0, &enumKey
);
5642 l
= RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
5643 RegCloseKey(enumKey
);
5650 static HKEY
SETUPDI_OpenDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5652 LPWSTR DriverKey
= NULL
;
5656 HKEY hEnumKey
= NULL
;
5658 HKEY key
= INVALID_HANDLE_VALUE
;
5660 hKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
);
5661 if (hKey
== INVALID_HANDLE_VALUE
)
5663 /* Read the 'Driver' key */
5664 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5665 if (rc
!= ERROR_SUCCESS
)
5670 else if (dwRegType
!= REG_SZ
)
5672 SetLastError(ERROR_GEN_FAILURE
);
5675 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5678 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5681 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5682 if (rc
!= ERROR_SUCCESS
)
5689 /* Need to open the driver key */
5692 REGSTR_PATH_CLASS_NT
,
5696 if (rc
!= ERROR_SUCCESS
)
5707 if (rc
!= ERROR_SUCCESS
)
5715 if (hEnumKey
!= NULL
)
5716 RegCloseKey(hEnumKey
);
5717 if (hKey
!= NULL
&& hKey
!= key
)
5722 /***********************************************************************
5723 * SetupDiOpenDevRegKey (SETUPAPI.@)
5725 HKEY WINAPI
SetupDiOpenDevRegKey(
5726 HDEVINFO DeviceInfoSet
,
5727 PSP_DEVINFO_DATA DeviceInfoData
,
5733 struct DeviceInfoSet
*set
= DeviceInfoSet
;
5734 struct DeviceInfo
*devInfo
;
5735 HKEY key
= INVALID_HANDLE_VALUE
;
5738 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet
, DeviceInfoData
,
5739 Scope
, HwProfile
, KeyType
, samDesired
);
5741 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5743 SetLastError(ERROR_INVALID_HANDLE
);
5744 return INVALID_HANDLE_VALUE
;
5746 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5748 SetLastError(ERROR_INVALID_HANDLE
);
5749 return INVALID_HANDLE_VALUE
;
5751 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5752 || !DeviceInfoData
->Reserved
)
5754 SetLastError(ERROR_INVALID_PARAMETER
);
5755 return INVALID_HANDLE_VALUE
;
5757 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5759 SetLastError(ERROR_INVALID_FLAGS
);
5760 return INVALID_HANDLE_VALUE
;
5762 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
5764 SetLastError(ERROR_INVALID_FLAGS
);
5765 return INVALID_HANDLE_VALUE
;
5767 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5768 if (devInfo
->set
!= set
)
5770 SetLastError(ERROR_INVALID_PARAMETER
);
5771 return INVALID_HANDLE_VALUE
;
5773 if (Scope
!= DICS_FLAG_GLOBAL
)
5775 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5776 if (RootKey
== INVALID_HANDLE_VALUE
)
5777 return INVALID_HANDLE_VALUE
;
5780 RootKey
= set
->HKLM
;
5784 key
= SETUPDI_OpenDevKey(RootKey
, devInfo
, samDesired
);
5787 key
= SETUPDI_OpenDrvKey(RootKey
, devInfo
, samDesired
);
5790 WARN("unknown KeyType %d\n", KeyType
);
5792 if (RootKey
!= set
->HKLM
)
5793 RegCloseKey(RootKey
);
5797 static BOOL
SETUPDI_DeleteDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5803 static BOOL
SETUPDI_DeleteDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5809 /***********************************************************************
5810 * SetupDiDeleteDevRegKey (SETUPAPI.@)
5812 BOOL WINAPI
SetupDiDeleteDevRegKey(
5813 HDEVINFO DeviceInfoSet
,
5814 PSP_DEVINFO_DATA DeviceInfoData
,
5819 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5820 struct DeviceInfo
*devInfo
;
5824 TRACE("%p %p %d %d %d\n", DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
5827 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5829 SetLastError(ERROR_INVALID_HANDLE
);
5832 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5834 SetLastError(ERROR_INVALID_HANDLE
);
5837 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5838 || !DeviceInfoData
->Reserved
)
5840 SetLastError(ERROR_INVALID_PARAMETER
);
5843 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5845 SetLastError(ERROR_INVALID_FLAGS
);
5848 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
&& KeyType
!= DIREG_BOTH
)
5850 SetLastError(ERROR_INVALID_FLAGS
);
5853 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5854 if (devInfo
->set
!= set
)
5856 SetLastError(ERROR_INVALID_PARAMETER
);
5859 if (Scope
!= DICS_FLAG_GLOBAL
)
5861 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5862 if (RootKey
== INVALID_HANDLE_VALUE
)
5866 RootKey
= set
->HKLM
;
5870 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5873 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5876 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5878 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5881 WARN("unknown KeyType %d\n", KeyType
);
5883 if (RootKey
!= set
->HKLM
)
5884 RegCloseKey(RootKey
);