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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
26 /* Unicode constants */
27 static const WCHAR AddInterface
[] = {'A','d','d','I','n','t','e','r','f','a','c','e',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 ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR Control
[] = {'C','o','n','t','r','o','l',0};
32 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
33 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
34 static const WCHAR DotHW
[] = {'.','H','W',0};
35 static const WCHAR DotInterfaces
[] = {'.','I','n','t','e','r','f','a','c','e','s',0};
36 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
37 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
38 static const WCHAR Linked
[] = {'L','i','n','k','e','d',0};
39 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
40 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
42 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
43 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
44 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
45 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
46 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};
48 static const WCHAR INF_MANUFACTURER
[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
49 static const WCHAR INF_PROVIDER
[] = {'P','r','o','v','i','d','e','r',0};
50 static const WCHAR INF_DRIVER_VER
[] = {'D','r','i','v','e','r','V','e','r',0};
53 (CALLBACK
* CLASS_INSTALL_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
58 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
59 IN HDEVINFO DeviceInfoSet
,
60 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
62 (CALLBACK
* COINSTALLER_PROC
) (
63 IN DI_FUNCTION InstallFunction
,
64 IN HDEVINFO DeviceInfoSet
,
65 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
66 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
68 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
69 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
70 IN LPFNADDPROPSHEETPAGE fAddFunc
,
73 (*UPDATE_CLASS_PARAM_HANDLER
) (
74 IN HDEVINFO DeviceInfoSet
,
75 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
76 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
77 IN DWORD ClassInstallParamsSize
);
79 struct CoInstallerElement
84 COINSTALLER_PROC Function
;
85 BOOL DoPostProcessing
;
90 PropertyChangeHandler(
91 IN HDEVINFO DeviceInfoSet
,
92 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
93 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
94 IN DWORD ClassInstallParamsSize
);
96 static const UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
97 NULL
, /* DIF_SELECTDEVICE */
98 NULL
, /* DIF_INSTALLDEVICE */
99 NULL
, /* DIF_ASSIGNRESOURCES */
100 NULL
, /* DIF_PROPERTIES */
101 NULL
, /* DIF_REMOVE */
102 NULL
, /* DIF_FIRSTTIMESETUP */
103 NULL
, /* DIF_FOUNDDEVICE */
104 NULL
, /* DIF_SELECTCLASSDRIVERS */
105 NULL
, /* DIF_VALIDATECLASSDRIVERS */
106 NULL
, /* DIF_INSTALLCLASSDRIVERS */
107 NULL
, /* DIF_CALCDISKSPACE */
108 NULL
, /* DIF_DESTROYPRIVATEDATA */
109 NULL
, /* DIF_VALIDATEDRIVER */
110 NULL
, /* DIF_MOVEDEVICE */
111 NULL
, /* DIF_DETECT */
112 NULL
, /* DIF_INSTALLWIZARD */
113 NULL
, /* DIF_DESTROYWIZARDDATA */
114 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
115 NULL
, /* DIF_ENABLECLASS */
116 NULL
, /* DIF_DETECTVERIFY */
117 NULL
, /* DIF_INSTALLDEVICEFILES */
118 NULL
, /* DIF_UNREMOVE */
119 NULL
, /* DIF_SELECTBESTCOMPATDRV */
120 NULL
, /* DIF_ALLOW_INSTALL */
121 NULL
, /* DIF_REGISTERDEVICE */
122 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
123 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
124 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
125 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
126 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
127 NULL
, /* DIF_UNUSED1 */
128 NULL
, /* DIF_INSTALLINTERFACES */
129 NULL
, /* DIF_DETECTCANCEL */
130 NULL
, /* DIF_REGISTER_COINSTALLERS */
131 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
132 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
133 NULL
, /* DIF_RESERVED1 */
134 NULL
, /* DIF_TROUBLESHOOTER */
135 NULL
, /* DIF_POWERMESSAGEWAKE */
136 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
137 NULL
, /* DIF_UPDATEDRIVER_UI */
138 NULL
/* DIF_RESERVED2 */
141 /***********************************************************************
142 * SetupDiBuildClassInfoList (SETUPAPI.@)
145 SetupDiBuildClassInfoList(
147 OUT LPGUID ClassGuidList OPTIONAL
,
148 IN DWORD ClassGuidListSize
,
149 OUT PDWORD RequiredSize
)
152 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
153 ClassGuidListSize
, RequiredSize
,
157 /***********************************************************************
158 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
161 SetupDiBuildClassInfoListExA(
163 OUT LPGUID ClassGuidList OPTIONAL
,
164 IN DWORD ClassGuidListSize
,
165 OUT PDWORD RequiredSize
,
166 IN PCSTR MachineName OPTIONAL
,
169 LPWSTR MachineNameW
= NULL
;
176 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
177 if (MachineNameW
== NULL
) return FALSE
;
180 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
181 ClassGuidListSize
, RequiredSize
,
182 MachineNameW
, Reserved
);
185 MyFree(MachineNameW
);
190 /***********************************************************************
191 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
194 SetupDiBuildClassInfoListExW(
196 OUT LPGUID ClassGuidList OPTIONAL
,
197 IN DWORD ClassGuidListSize
,
198 OUT PDWORD RequiredSize
,
199 IN PCWSTR MachineName OPTIONAL
,
202 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
203 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
204 HKEY hClassKey
= NULL
;
208 DWORD dwGuidListIndex
= 0;
211 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
212 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
214 if (RequiredSize
!= NULL
)
217 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
218 KEY_ENUMERATE_SUB_KEYS
,
222 if (hClassesKey
== INVALID_HANDLE_VALUE
)
225 for (dwIndex
= 0; ; dwIndex
++)
227 dwLength
= MAX_GUID_STRING_LEN
+ 1;
228 lError
= RegEnumKeyExW(hClassesKey
,
236 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
237 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
239 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
241 if (hClassKey
!= NULL
)
242 RegCloseKey(hClassKey
);
243 if (RegOpenKeyExW(hClassesKey
,
247 &hClassKey
) != ERROR_SUCCESS
)
252 if (RegQueryValueExW(hClassKey
,
253 REGSTR_VAL_NOUSECLASS
,
257 NULL
) == ERROR_SUCCESS
)
259 TRACE("'NoUseClass' value found!\n");
263 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
264 (!RegQueryValueExW(hClassKey
,
265 REGSTR_VAL_NOINSTALLCLASS
,
271 TRACE("'NoInstallClass' value found!\n");
275 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
276 (!RegQueryValueExW(hClassKey
,
277 REGSTR_VAL_NODISPLAYCLASS
,
283 TRACE("'NoDisplayClass' value found!\n");
287 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
288 if (dwGuidListIndex
< ClassGuidListSize
)
290 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
292 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
294 UuidFromStringW(&szKeyName
[1],
295 &ClassGuidList
[dwGuidListIndex
]);
301 if (lError
!= ERROR_SUCCESS
)
305 if (RequiredSize
!= NULL
)
306 *RequiredSize
= dwGuidListIndex
;
308 if (ClassGuidListSize
< dwGuidListIndex
)
309 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
314 if (hClassesKey
!= INVALID_HANDLE_VALUE
)
315 RegCloseKey(hClassesKey
);
316 if (hClassKey
!= NULL
)
317 RegCloseKey(hClassKey
);
321 /***********************************************************************
322 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
325 SetupDiClassGuidsFromNameA(
327 OUT LPGUID ClassGuidList
,
328 IN DWORD ClassGuidListSize
,
329 OUT PDWORD RequiredSize
)
331 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
332 ClassGuidListSize
, RequiredSize
,
336 /***********************************************************************
337 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
339 BOOL WINAPI
SetupDiClassGuidsFromNameW(
341 OUT LPGUID ClassGuidList
,
342 IN DWORD ClassGuidListSize
,
343 OUT PDWORD RequiredSize
)
345 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
346 ClassGuidListSize
, RequiredSize
,
350 /***********************************************************************
351 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
354 SetupDiClassGuidsFromNameExA(
356 OUT LPGUID ClassGuidList
,
357 IN DWORD ClassGuidListSize
,
358 OUT PDWORD RequiredSize
,
359 IN PCSTR MachineName OPTIONAL
,
362 LPWSTR ClassNameW
= NULL
;
363 LPWSTR MachineNameW
= NULL
;
368 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
369 if (ClassNameW
== NULL
)
374 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
375 if (MachineNameW
== NULL
)
382 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
383 ClassGuidListSize
, RequiredSize
,
384 MachineNameW
, Reserved
);
387 MyFree(MachineNameW
);
394 /***********************************************************************
395 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
398 SetupDiClassGuidsFromNameExW(
400 OUT LPGUID ClassGuidList
,
401 IN DWORD ClassGuidListSize
,
402 OUT PDWORD RequiredSize
,
403 IN PCWSTR MachineName OPTIONAL
,
406 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
407 WCHAR szClassName
[256];
408 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
409 HKEY hClassKey
= NULL
;
413 DWORD dwGuidListIndex
= 0;
416 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
417 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
419 if (RequiredSize
!= NULL
)
422 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
423 KEY_ENUMERATE_SUB_KEYS
,
427 if (hClassesKey
== INVALID_HANDLE_VALUE
)
430 for (dwIndex
= 0; ; dwIndex
++)
432 dwLength
= MAX_GUID_STRING_LEN
+ 1;
433 lError
= RegEnumKeyExW(hClassesKey
,
441 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
442 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
444 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
446 if (hClassKey
!= NULL
)
447 RegCloseKey(hClassKey
);
448 if (RegOpenKeyExW(hClassesKey
,
452 &hClassKey
) != ERROR_SUCCESS
)
457 dwLength
= 256 * sizeof(WCHAR
);
458 if (RegQueryValueExW(hClassKey
,
463 &dwLength
) == ERROR_SUCCESS
)
465 TRACE("Class name: %s\n", debugstr_w(szClassName
));
467 if (strcmpiW(szClassName
, ClassName
) == 0)
469 TRACE("Found matching class name\n");
471 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
472 if (dwGuidListIndex
< ClassGuidListSize
)
474 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
476 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
478 UuidFromStringW(&szKeyName
[1],
479 &ClassGuidList
[dwGuidListIndex
]);
487 if (lError
!= ERROR_SUCCESS
)
491 if (RequiredSize
!= NULL
)
492 *RequiredSize
= dwGuidListIndex
;
494 if (ClassGuidListSize
< dwGuidListIndex
)
495 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
500 if (hClassesKey
!= INVALID_HANDLE_VALUE
)
501 RegCloseKey(hClassesKey
);
502 if (hClassKey
!= NULL
)
503 RegCloseKey(hClassKey
);
507 /***********************************************************************
508 * SetupDiClassNameFromGuidA (SETUPAPI.@)
511 SetupDiClassNameFromGuidA(
512 IN CONST GUID
* ClassGuid
,
514 IN DWORD ClassNameSize
,
515 OUT PDWORD RequiredSize OPTIONAL
)
517 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
518 ClassNameSize
, RequiredSize
,
522 /***********************************************************************
523 * SetupDiClassNameFromGuidW (SETUPAPI.@)
526 SetupDiClassNameFromGuidW(
527 IN CONST GUID
* ClassGuid
,
529 IN DWORD ClassNameSize
,
530 OUT PDWORD RequiredSize OPTIONAL
)
532 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
533 ClassNameSize
, RequiredSize
,
537 /***********************************************************************
538 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
541 SetupDiClassNameFromGuidExA(
542 IN CONST GUID
* ClassGuid
,
544 IN DWORD ClassNameSize
,
545 OUT PDWORD RequiredSize OPTIONAL
,
546 IN PCSTR MachineName OPTIONAL
,
549 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
550 LPWSTR MachineNameW
= NULL
;
554 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
555 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
556 NULL
, MachineNameW
, Reserved
);
559 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
560 ClassNameSize
, NULL
, NULL
);
562 if (!ClassNameSize
&& RequiredSize
)
565 MyFree(MachineNameW
);
569 /***********************************************************************
570 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
573 SetupDiClassNameFromGuidExW(
574 IN CONST GUID
* ClassGuid
,
576 IN DWORD ClassNameSize
,
577 OUT PDWORD RequiredSize OPTIONAL
,
578 IN PCWSTR MachineName OPTIONAL
,
586 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
587 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
589 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
594 if (hKey
== INVALID_HANDLE_VALUE
)
597 if (RequiredSize
!= NULL
)
600 rc
= RegQueryValueExW(hKey
,
606 if (rc
!= ERROR_SUCCESS
)
612 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
615 dwLength
= ClassNameSize
* sizeof(WCHAR
);
616 rc
= RegQueryValueExW(hKey
,
622 if (rc
!= ERROR_SUCCESS
)
631 if (hKey
!= INVALID_HANDLE_VALUE
)
636 /***********************************************************************
637 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
640 SetupDiCreateDeviceInfoList(
641 IN CONST GUID
*ClassGuid OPTIONAL
,
642 IN HWND hwndParent OPTIONAL
)
644 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
647 /***********************************************************************
648 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
651 SetupDiCreateDeviceInfoListExA(
652 IN CONST GUID
*ClassGuid OPTIONAL
,
653 IN HWND hwndParent OPTIONAL
,
654 IN PCSTR MachineName OPTIONAL
,
657 LPWSTR MachineNameW
= NULL
;
660 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
661 debugstr_a(MachineName
), Reserved
);
665 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
666 if (MachineNameW
== NULL
)
667 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
670 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
671 MachineNameW
, Reserved
);
674 MyFree(MachineNameW
);
680 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
684 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
685 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
686 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
687 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
688 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
689 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
690 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
691 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
692 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
693 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
694 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
695 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
696 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
697 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
698 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
699 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
700 case CR_SUCCESS
: return ERROR_SUCCESS
;
701 default: return ERROR_GEN_FAILURE
;
704 /* Does not happen */
707 /***********************************************************************
708 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
711 SetupDiCreateDeviceInfoListExW(
712 IN CONST GUID
*ClassGuid OPTIONAL
,
713 IN HWND hwndParent OPTIONAL
,
714 IN PCWSTR MachineName OPTIONAL
,
717 struct DeviceInfoSet
*list
;
718 LPWSTR UNCServerName
= NULL
;
722 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
724 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
725 debugstr_w(MachineName
), Reserved
);
727 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
729 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
730 list
= HeapAlloc(GetProcessHeap(), 0, size
);
733 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
736 memset(list
, 0, sizeof(struct DeviceInfoSet
));
738 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
741 ClassGuid
? ClassGuid
: &GUID_NULL
,
742 sizeof(list
->ClassGuid
));
743 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
744 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
745 list
->InstallParams
.hwndParent
= hwndParent
;
748 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
749 if (rc
!= ERROR_SUCCESS
)
754 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
757 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
761 strcpyW(UNCServerName
+ 2, MachineName
);
762 list
->szData
[0] = list
->szData
[1] = '\\';
763 strcpyW(list
->szData
+ 2, MachineName
);
764 list
->MachineName
= list
->szData
;
768 DWORD Size
= MAX_PATH
;
769 list
->HKLM
= HKEY_LOCAL_MACHINE
;
770 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
773 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
776 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
778 list
->MachineName
= NULL
;
781 UNCServerName
[0] = UNCServerName
[1] = '\\';
782 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
783 if (cr
!= CR_SUCCESS
)
785 SetLastError(GetErrorCodeFromCrCode(cr
));
789 InitializeListHead(&list
->DriverListHead
);
790 InitializeListHead(&list
->ListHead
);
792 ret
= (HDEVINFO
)list
;
795 if (ret
== INVALID_HANDLE_VALUE
)
799 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
800 RegCloseKey(list
->HKLM
);
802 HeapFree(GetProcessHeap(), 0, list
);
805 HeapFree(GetProcessHeap(), 0, UNCServerName
);
809 /***********************************************************************
810 * SetupDiEnumDeviceInfo (SETUPAPI.@)
813 SetupDiEnumDeviceInfo(
814 IN HDEVINFO DeviceInfoSet
,
815 IN DWORD MemberIndex
,
816 OUT PSP_DEVINFO_DATA DeviceInfoData
)
820 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
822 SetLastError(ERROR_INVALID_PARAMETER
);
823 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
825 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
827 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
828 SetLastError(ERROR_INVALID_HANDLE
);
829 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
830 SetLastError(ERROR_INVALID_USER_BUFFER
);
833 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
834 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
835 ItemList
= ItemList
->Flink
;
836 if (ItemList
== &list
->ListHead
)
837 SetLastError(ERROR_NO_MORE_ITEMS
);
840 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
841 memcpy(&DeviceInfoData
->ClassGuid
,
844 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
845 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
851 SetLastError(ERROR_INVALID_HANDLE
);
855 /***********************************************************************
856 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
859 SetupDiGetActualSectionToInstallA(
861 IN PCSTR InfSectionName
,
862 OUT PSTR InfSectionWithExt OPTIONAL
,
863 IN DWORD InfSectionWithExtSize
,
864 OUT PDWORD RequiredSize OPTIONAL
,
865 OUT PSTR
*Extension OPTIONAL
)
867 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
868 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
872 /***********************************************************************
873 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
876 SetupDiGetActualSectionToInstallW(
878 IN PCWSTR InfSectionName
,
879 OUT PWSTR InfSectionWithExt OPTIONAL
,
880 IN DWORD InfSectionWithExtSize
,
881 OUT PDWORD RequiredSize OPTIONAL
,
882 OUT PWSTR
*Extension OPTIONAL
)
884 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
885 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
889 /***********************************************************************
890 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
893 SetupDiGetActualSectionToInstallExA(
895 IN PCSTR InfSectionName
,
896 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
897 OUT PSTR InfSectionWithExt OPTIONAL
,
898 IN DWORD InfSectionWithExtSize
,
899 OUT PDWORD RequiredSize OPTIONAL
,
900 OUT PSTR
* Extension OPTIONAL
,
903 LPWSTR InfSectionNameW
= NULL
;
904 LPWSTR InfSectionWithExtW
= NULL
;
906 BOOL bResult
= FALSE
;
912 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
913 if (InfSectionNameW
== NULL
)
916 if (InfSectionWithExt
)
918 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
919 if (InfSectionWithExtW
== NULL
)
923 bResult
= SetupDiGetActualSectionToInstallExW(
924 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
925 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
926 InfSectionWithExtSize
,
928 Extension
? &ExtensionW
: NULL
,
931 if (bResult
&& InfSectionWithExt
)
933 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
934 InfSectionWithExtSize
, NULL
, NULL
) != 0;
936 if (bResult
&& Extension
)
938 if (ExtensionW
== NULL
)
941 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
945 MyFree(InfSectionNameW
);
946 MyFree(InfSectionWithExtW
);
951 /***********************************************************************
952 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
955 SetupDiGetActualSectionToInstallExW(
957 IN PCWSTR InfSectionName
,
958 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
959 OUT PWSTR InfSectionWithExt OPTIONAL
,
960 IN DWORD InfSectionWithExtSize
,
961 OUT PDWORD RequiredSize OPTIONAL
,
962 OUT PWSTR
* Extension OPTIONAL
,
967 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
968 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
969 RequiredSize
, Extension
, Reserved
);
971 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
972 SetLastError(ERROR_INVALID_HANDLE
);
973 else if (!InfSectionName
)
974 SetLastError(ERROR_INVALID_PARAMETER
);
975 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
976 SetLastError(ERROR_INVALID_USER_BUFFER
);
977 else if (Reserved
!= NULL
)
978 SetLastError(ERROR_INVALID_PARAMETER
);
981 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
982 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
983 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
984 WCHAR SectionName
[LINE_LEN
+ 1];
985 LONG lLineCount
= -1;
988 /* Fill platform info if needed */
989 if (AlternatePlatformInfo
)
990 pPlatformInfo
= AlternatePlatformInfo
;
991 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
993 /* That's the first time we go here. We need to fill in the structure */
994 OSVERSIONINFO VersionInfo
;
995 SYSTEM_INFO SystemInfo
;
996 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
997 ret
= GetVersionEx(&VersionInfo
);
1000 GetSystemInfo(&SystemInfo
);
1001 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
1002 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
1003 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
1004 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
1005 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
1006 CurrentPlatform
.Reserved
= 0;
1009 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
1010 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
1011 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
1013 static const WCHAR ExtensionArchitectureNone
[] = {0};
1014 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
1015 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
1016 static const WCHAR ExtensionArchitectureia64
[] = {'i','a','6','4',0};
1017 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
1018 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
1019 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
1021 /* Set various extensions values */
1022 switch (pPlatformInfo
->Platform
)
1024 case VER_PLATFORM_WIN32_WINDOWS
:
1025 pExtensionPlatform
= ExtensionPlatformWindows
;
1027 case VER_PLATFORM_WIN32_NT
:
1028 pExtensionPlatform
= ExtensionPlatformNT
;
1031 ERR("Unkown platform 0x%lx\n", pPlatformInfo
->Platform
);
1032 pExtensionPlatform
= ExtensionPlatformNone
;
1035 switch (pPlatformInfo
->ProcessorArchitecture
)
1037 case PROCESSOR_ARCHITECTURE_ALPHA
:
1038 pExtensionArchitecture
= ExtensionArchitecturealpha
;
1040 case PROCESSOR_ARCHITECTURE_AMD64
:
1041 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1043 case PROCESSOR_ARCHITECTURE_IA64
:
1044 pExtensionArchitecture
= ExtensionArchitectureia64
;
1046 case PROCESSOR_ARCHITECTURE_INTEL
:
1047 pExtensionArchitecture
= ExtensionArchitecturex86
;
1049 case PROCESSOR_ARCHITECTURE_MIPS
:
1050 pExtensionArchitecture
= ExtensionArchitecturemips
;
1052 case PROCESSOR_ARCHITECTURE_PPC
:
1053 pExtensionArchitecture
= ExtensionArchitectureppc
;
1056 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1057 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1058 pExtensionArchitecture
= ExtensionArchitectureNone
;
1062 static const WCHAR FormatPlatformArchitectureMajorMinor
[] = {'%','s','%','s','%','s','.','%','l','u','.','%','l','u',0};
1063 static const WCHAR FormatPlatformMajorMinor
[] = {'%','s','%','s','.','%','l','u','.','%','l','u',0};
1064 static const WCHAR FormatPlatformArchitectureMajor
[] = {'%','s','%','s','%','s','.','%','l','u',0};
1065 static const WCHAR FormatPlatformMajor
[] = {'%','s','%','s','.','%','l','u',0};
1066 static const WCHAR FormatPlatformArchitecture
[] = {'%','s','%','s','%','s',0};
1067 static const WCHAR FormatPlatform
[] = {'%','s','%','s',0};
1068 static const WCHAR FormatNone
[] = {'%','s',0};
1070 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1072 /* Test with platform.architecture.major.minor extension */
1073 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajorMinor
, InfSectionName
,
1074 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1075 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1076 if (lLineCount
!= -1) goto sectionfound
;
1078 /* Test with platform.major.minor extension */
1079 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajorMinor
, InfSectionName
,
1080 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1081 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1082 if (lLineCount
!= -1) goto sectionfound
;
1084 /* Test with platform.architecture.major extension */
1085 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajor
, InfSectionName
,
1086 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1087 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1088 if (lLineCount
!= -1) goto sectionfound
;
1090 /* Test with platform.major extension */
1091 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajor
, InfSectionName
,
1092 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1093 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1094 if (lLineCount
!= -1) goto sectionfound
;
1096 /* Test with platform.architecture extension */
1097 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitecture
, InfSectionName
,
1098 pExtensionPlatform
, pExtensionArchitecture
);
1099 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1100 if (lLineCount
!= -1) goto sectionfound
;
1102 /* Test with platform extension */
1103 snprintfW(SectionName
, LINE_LEN
, FormatPlatform
, InfSectionName
,
1104 pExtensionPlatform
);
1105 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1106 if (lLineCount
!= -1) goto sectionfound
;
1108 /* Test without extension */
1109 snprintfW(SectionName
, LINE_LEN
, FormatNone
, InfSectionName
);
1110 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1111 if (lLineCount
!= -1) goto sectionfound
;
1113 /* No appropriate section found */
1114 SetLastError(ERROR_INVALID_PARAMETER
);
1118 dwFullLength
= lstrlenW(SectionName
);
1119 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1121 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1123 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1127 lstrcpyW(InfSectionWithExt
, SectionName
);
1128 if (Extension
!= NULL
)
1130 DWORD dwLength
= lstrlenW(SectionName
);
1131 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1135 if (RequiredSize
!= NULL
)
1136 *RequiredSize
= dwFullLength
+ 1;
1142 TRACE("Returning %d\n", ret
);
1147 /***********************************************************************
1148 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1151 SetupDiGetClassDescriptionA(
1152 IN CONST GUID
*ClassGuid
,
1153 OUT PSTR ClassDescription
,
1154 IN DWORD ClassDescriptionSize
,
1155 OUT PDWORD RequiredSize OPTIONAL
)
1157 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1158 ClassDescriptionSize
,
1159 RequiredSize
, NULL
, NULL
);
1162 /***********************************************************************
1163 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1166 SetupDiGetClassDescriptionW(
1167 IN CONST GUID
*ClassGuid
,
1168 OUT PWSTR ClassDescription
,
1169 IN DWORD ClassDescriptionSize
,
1170 OUT PDWORD RequiredSize OPTIONAL
)
1172 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1173 ClassDescriptionSize
,
1174 RequiredSize
, NULL
, NULL
);
1177 /***********************************************************************
1178 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1181 SetupDiGetClassDescriptionExA(
1182 IN CONST GUID
*ClassGuid
,
1183 OUT PSTR ClassDescription
,
1184 IN DWORD ClassDescriptionSize
,
1185 OUT PDWORD RequiredSize OPTIONAL
,
1186 IN PCSTR MachineName OPTIONAL
,
1189 PWCHAR ClassDescriptionW
;
1190 LPWSTR MachineNameW
= NULL
;
1194 if (ClassDescriptionSize
> 0)
1196 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1197 if (!ClassDescriptionW
)
1199 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1205 ClassDescriptionW
= NULL
;
1209 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1212 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1218 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1219 NULL
, MachineNameW
, Reserved
);
1222 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1223 ClassDescriptionSize
, NULL
, NULL
);
1225 if (!ClassDescriptionSize
&& RequiredSize
)
1226 *RequiredSize
= len
;
1230 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1231 MyFree(MachineNameW
);
1235 /***********************************************************************
1236 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1239 SetupDiGetClassDescriptionExW(
1240 IN CONST GUID
*ClassGuid
,
1241 OUT PWSTR ClassDescription
,
1242 IN DWORD ClassDescriptionSize
,
1243 OUT PDWORD RequiredSize OPTIONAL
,
1244 IN PCWSTR MachineName OPTIONAL
,
1247 HKEY hKey
= INVALID_HANDLE_VALUE
;
1251 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1252 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1254 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1259 if (hKey
== INVALID_HANDLE_VALUE
)
1261 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1265 if (RequiredSize
!= NULL
)
1268 if (RegQueryValueExW(hKey
,
1273 &dwLength
) != ERROR_SUCCESS
)
1278 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1281 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1282 if (RegQueryValueExW(hKey
,
1286 (LPBYTE
)ClassDescription
,
1287 &dwLength
) != ERROR_SUCCESS
)
1295 if (hKey
!= INVALID_HANDLE_VALUE
)
1301 /***********************************************************************
1302 * SetupDiGetClassDevsA (SETUPAPI.@)
1305 SetupDiGetClassDevsA(
1306 IN CONST GUID
*ClassGuid OPTIONAL
,
1307 IN PCSTR Enumerator OPTIONAL
,
1308 IN HWND hwndParent OPTIONAL
,
1311 return SetupDiGetClassDevsExA(ClassGuid
, Enumerator
, hwndParent
,
1312 Flags
, NULL
, NULL
, NULL
);
1315 /***********************************************************************
1316 * SetupDiGetClassDevsW (SETUPAPI.@)
1319 SetupDiGetClassDevsW(
1320 IN CONST GUID
*ClassGuid OPTIONAL
,
1321 IN PCWSTR Enumerator OPTIONAL
,
1322 IN HWND hwndParent OPTIONAL
,
1325 return SetupDiGetClassDevsExW(ClassGuid
, Enumerator
, hwndParent
,
1326 Flags
, NULL
, NULL
, NULL
);
1329 /***********************************************************************
1330 * SetupDiGetClassDevsExA (SETUPAPI.@)
1333 SetupDiGetClassDevsExA(
1334 IN CONST GUID
*ClassGuid OPTIONAL
,
1335 IN PCSTR Enumerator OPTIONAL
,
1336 IN HWND hwndParent OPTIONAL
,
1338 IN HDEVINFO DeviceInfoSet OPTIONAL
,
1339 IN PCSTR MachineName OPTIONAL
,
1343 LPWSTR enumstrW
= NULL
;
1344 LPWSTR machineW
= NULL
;
1348 int len
= MultiByteToWideChar(CP_ACP
, 0, Enumerator
, -1, NULL
, 0);
1349 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1352 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1355 MultiByteToWideChar(CP_ACP
, 0, Enumerator
, -1, enumstrW
, len
);
1359 int len
= MultiByteToWideChar(CP_ACP
, 0, MachineName
, -1, NULL
, 0);
1360 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1363 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1366 MultiByteToWideChar(CP_ACP
, 0, MachineName
, -1, machineW
, len
);
1368 ret
= SetupDiGetClassDevsExW(ClassGuid
, enumstrW
, hwndParent
, Flags
, DeviceInfoSet
, machineW
, Reserved
);
1371 HeapFree(GetProcessHeap(), 0, enumstrW
);
1372 HeapFree(GetProcessHeap(), 0, machineW
);
1377 CreateDeviceInfoElement(
1378 IN
struct DeviceInfoSet
*list
,
1379 IN LPCWSTR InstancePath
,
1380 IN LPCGUID pClassGuid
,
1381 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1385 struct DeviceInfoElement
*deviceInfo
;
1387 *pDeviceInfo
= NULL
;
1389 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
1390 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1393 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1396 memset(deviceInfo
, 0, size
);
1398 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1399 if (cr
!= CR_SUCCESS
)
1401 SetLastError(GetErrorCodeFromCrCode(cr
));
1405 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1406 strcpyW(deviceInfo
->Data
, InstancePath
);
1407 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1408 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
1409 deviceInfo
->DeviceDescription
= NULL
;
1410 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1411 deviceInfo
->CreationFlags
= 0;
1412 InitializeListHead(&deviceInfo
->DriverListHead
);
1413 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1415 *pDeviceInfo
= deviceInfo
;
1420 CreateDeviceInterface(
1421 IN
struct DeviceInfoElement
* deviceInfo
,
1422 IN LPCWSTR SymbolicLink
,
1423 IN LPCGUID pInterfaceGuid
,
1424 OUT
struct DeviceInterface
**pDeviceInterface
)
1426 struct DeviceInterface
*deviceInterface
;
1428 *pDeviceInterface
= NULL
;
1430 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1431 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (strlenW(SymbolicLink
) + 1) * sizeof(WCHAR
));
1432 if (!deviceInterface
)
1434 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1437 deviceInterface
->DeviceInfo
= deviceInfo
;
1438 strcpyW(deviceInterface
->SymbolicLink
, SymbolicLink
);
1439 deviceInterface
->Flags
= 0; /* Flags will be updated later */
1440 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1442 *pDeviceInterface
= deviceInterface
;
1447 SETUP_CreateDevListFromEnumerator(
1448 struct DeviceInfoSet
*list
,
1449 CONST GUID
*pClassGuid OPTIONAL
,
1451 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1453 HKEY hDeviceIdKey
= NULL
, hInstanceIdKey
;
1454 WCHAR KeyBuffer
[MAX_PATH
];
1455 WCHAR InstancePath
[MAX_PATH
];
1456 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1457 struct DeviceInfoElement
*deviceInfo
;
1459 DWORD dwLength
, dwRegType
;
1462 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1465 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1466 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1467 if (rc
== ERROR_NO_MORE_ITEMS
)
1469 if (rc
!= ERROR_SUCCESS
)
1473 /* Open device id sub key */
1474 if (hDeviceIdKey
!= NULL
)
1475 RegCloseKey(hDeviceIdKey
);
1476 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1477 if (rc
!= ERROR_SUCCESS
)
1479 strcpyW(InstancePath
, Enumerator
);
1480 strcatW(InstancePath
, L
"\\");
1481 strcatW(InstancePath
, KeyBuffer
);
1482 strcatW(InstancePath
, L
"\\");
1483 pEndOfInstancePath
= &InstancePath
[strlenW(InstancePath
)];
1485 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1491 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1492 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1493 if (rc
== ERROR_NO_MORE_ITEMS
)
1495 if (rc
!= ERROR_SUCCESS
)
1499 /* Open instance id sub key */
1500 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1501 if (rc
!= ERROR_SUCCESS
)
1503 *pEndOfInstancePath
= '\0';
1504 strcatW(InstancePath
, KeyBuffer
);
1506 /* Read ClassGUID value */
1507 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1508 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1509 RegCloseKey(hInstanceIdKey
);
1510 if (rc
== ERROR_FILE_NOT_FOUND
)
1513 /* Skip this bad entry as we can't verify it */
1515 /* Set a default GUID for this device */
1516 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1518 else if (rc
!= ERROR_SUCCESS
)
1522 else if (dwRegType
!= REG_SZ
)
1524 rc
= ERROR_GEN_FAILURE
;
1529 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1530 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1531 /* Bad GUID, skip the entry */
1535 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1537 /* Skip this entry as it is not the right device class */
1541 /* Add the entry to the list */
1542 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1544 rc
= GetLastError();
1547 TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath
), list
);
1548 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1555 if (hDeviceIdKey
!= NULL
)
1556 RegCloseKey(hDeviceIdKey
);
1561 SETUP_CreateDevList(
1562 struct DeviceInfoSet
*list
,
1563 PCWSTR MachineName OPTIONAL
,
1564 CONST GUID
*class OPTIONAL
,
1565 PCWSTR Enumerator OPTIONAL
)
1567 HKEY HKLM
= HKEY_LOCAL_MACHINE
;
1568 HKEY hEnumKey
= NULL
;
1569 HKEY hEnumeratorKey
= NULL
;
1570 WCHAR KeyBuffer
[MAX_PATH
];
1575 if (class && IsEqualIID(class, &GUID_NULL
))
1578 /* Open Enum key (if applicable) */
1579 if (MachineName
!= NULL
)
1581 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1582 if (rc
!= ERROR_SUCCESS
)
1588 REGSTR_PATH_SYSTEMENUM
,
1590 KEY_ENUMERATE_SUB_KEYS
,
1592 if (rc
!= ERROR_SUCCESS
)
1595 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1596 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1605 KEY_ENUMERATE_SUB_KEYS
,
1607 if (rc
!= ERROR_SUCCESS
)
1609 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1613 /* Enumerate enumerators */
1617 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1618 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1619 if (rc
== ERROR_NO_MORE_ITEMS
)
1621 else if (rc
!= ERROR_SUCCESS
)
1626 if (hEnumeratorKey
!= NULL
)
1627 RegCloseKey(hEnumeratorKey
);
1628 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1629 if (rc
!= ERROR_SUCCESS
)
1632 /* Call SETUP_CreateDevListFromEnumerator */
1633 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1634 if (rc
!= ERROR_SUCCESS
)
1641 if (HKLM
!= HKEY_LOCAL_MACHINE
)
1643 if (hEnumKey
!= NULL
)
1644 RegCloseKey(hEnumKey
);
1645 if (hEnumeratorKey
!= NULL
)
1646 RegCloseKey(hEnumeratorKey
);
1651 DestroyDeviceInterface(
1652 struct DeviceInterface
* deviceInterface
)
1654 return HeapFree(GetProcessHeap(), 0, deviceInterface
);
1658 SETUP_CreateInterfaceList(
1659 struct DeviceInfoSet
*list
,
1661 CONST GUID
*InterfaceGuid
,
1662 PCWSTR DeviceInstanceW
/* OPTIONAL */,
1663 BOOL OnlyPresentInterfaces
)
1665 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1666 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1667 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1668 HKEY hControlKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
1669 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1670 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1672 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1673 PWSTR pSymbolicLink
= NULL
;
1674 PWSTR InstancePath
= NULL
;
1676 DWORD dwLength
, dwInstancePathLength
;
1680 struct DeviceInfoElement
*deviceInfo
;
1682 hInterfaceKey
= INVALID_HANDLE_VALUE
;
1683 hDeviceInstanceKey
= NULL
;
1684 hReferenceKey
= NULL
;
1686 /* Open registry key related to this interface */
1687 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1688 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1690 rc
= GetLastError();
1694 /* Enumerate sub keys of hInterfaceKey */
1698 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1699 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1700 if (rc
== ERROR_NO_MORE_ITEMS
)
1702 if (rc
!= ERROR_SUCCESS
)
1707 if (hDeviceInstanceKey
!= NULL
)
1708 RegCloseKey(hDeviceInstanceKey
);
1709 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1710 if (rc
!= ERROR_SUCCESS
)
1713 /* Read DeviceInstance */
1714 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1715 if (rc
!= ERROR_SUCCESS
)
1717 if (dwRegType
!= REG_SZ
)
1719 rc
= ERROR_GEN_FAILURE
;
1722 HeapFree(GetProcessHeap(), 0, InstancePath
);
1723 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1726 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1729 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1730 if (rc
!= ERROR_SUCCESS
)
1732 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1733 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1735 if (DeviceInstanceW
)
1737 /* Check if device enumerator is not the right one */
1738 if (strcmpW(DeviceInstanceW
, InstancePath
) != 0)
1742 /* Find class GUID associated to the device instance */
1745 REGSTR_PATH_SYSTEMENUM
,
1749 if (rc
!= ERROR_SUCCESS
)
1757 RegCloseKey(hEnumKey
);
1758 if (rc
!= ERROR_SUCCESS
)
1760 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1761 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1763 if (rc
!= ERROR_SUCCESS
)
1765 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1766 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1767 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1769 rc
= ERROR_GEN_FAILURE
;
1772 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1774 /* If current device doesn't match the list GUID (if any), skip this entry */
1775 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1778 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1782 struct DeviceInterface
*interfaceInfo
;
1784 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1785 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1786 if (rc
== ERROR_NO_MORE_ITEMS
)
1788 if (rc
!= ERROR_SUCCESS
)
1791 if (KeyBuffer
[0] != '#')
1792 /* This entry doesn't represent an interesting entry */
1796 if (hReferenceKey
!= NULL
)
1797 RegCloseKey(hReferenceKey
);
1798 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1799 if (rc
!= ERROR_SUCCESS
)
1802 /* Read SymbolicLink value */
1803 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1804 if (rc
!= ERROR_SUCCESS
)
1806 if (dwRegType
!= REG_SZ
)
1808 rc
= ERROR_GEN_FAILURE
;
1812 /* We have found a device */
1813 /* Step 1. Create a device info element */
1814 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1816 rc
= GetLastError();
1819 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1820 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1822 /* Step 2. Create an interface list for this element */
1823 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1824 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1827 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1830 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1831 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1832 if (rc
!= ERROR_SUCCESS
)
1834 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1836 rc
= GetLastError();
1840 /* Step 3. Update flags */
1841 if (KeyBuffer
[1] == '\0')
1842 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
1843 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
1844 if (rc
!= ERROR_SUCCESS
)
1846 if (OnlyPresentInterfaces
)
1848 DestroyDeviceInterface(interfaceInfo
);
1852 interfaceInfo
->Flags
|= SPINT_REMOVED
;
1856 dwLength
= sizeof(DWORD
);
1857 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
1858 && dwRegType
== REG_DWORD
&& LinkedValue
)
1859 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
1860 RegCloseKey(hControlKey
);
1863 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1864 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1870 if (hReferenceKey
!= NULL
)
1871 RegCloseKey(hReferenceKey
);
1872 if (hDeviceInstanceKey
!= NULL
)
1873 RegCloseKey(hDeviceInstanceKey
);
1874 if (hInterfaceKey
!= INVALID_HANDLE_VALUE
)
1875 RegCloseKey(hInterfaceKey
);
1876 HeapFree(GetProcessHeap(), 0, InstancePath
);
1877 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1881 /***********************************************************************
1882 * SetupDiGetClassDevsExW (SETUPAPI.@)
1885 SetupDiGetClassDevsExW(
1886 IN CONST GUID
*ClassGuid OPTIONAL
,
1887 IN PCWSTR Enumerator OPTIONAL
,
1888 IN HWND hwndParent OPTIONAL
,
1890 IN HDEVINFO DeviceInfoSet OPTIONAL
,
1891 IN PCWSTR MachineName OPTIONAL
,
1894 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1895 struct DeviceInfoSet
*list
;
1896 CONST GUID
*pClassGuid
;
1898 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1900 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(ClassGuid
), debugstr_w(Enumerator
),
1901 hwndParent
, Flags
, DeviceInfoSet
, debugstr_w(MachineName
), Reserved
);
1903 /* Create the deviceset if not set */
1906 list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1907 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1909 SetLastError(ERROR_INVALID_HANDLE
);
1912 hDeviceInfo
= DeviceInfoSet
;
1916 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1917 Flags
& DIGCF_DEVICEINTERFACE
? NULL
: ClassGuid
,
1918 NULL
, MachineName
, NULL
);
1919 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1921 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1924 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1927 pClassGuid
= &list
->ClassGuid
;
1929 if (Flags
& DIGCF_PROFILE
)
1930 FIXME(": flag DIGCF_PROFILE ignored\n");
1932 if (Flags
& DIGCF_ALLCLASSES
)
1934 rc
= SETUP_CreateDevList(list
, MachineName
, pClassGuid
, Enumerator
);
1935 if (rc
!= ERROR_SUCCESS
)
1942 else if (Flags
& DIGCF_DEVICEINTERFACE
)
1944 if (ClassGuid
== NULL
)
1946 SetLastError(ERROR_INVALID_PARAMETER
);
1950 rc
= SETUP_CreateInterfaceList(list
, MachineName
, ClassGuid
, Enumerator
, Flags
& DIGCF_PRESENT
);
1951 if (rc
!= ERROR_SUCCESS
)
1960 rc
= SETUP_CreateDevList(list
, MachineName
, ClassGuid
, Enumerator
);
1961 if (rc
!= ERROR_SUCCESS
)
1970 if (!DeviceInfoSet
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= ret
)
1971 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1975 /***********************************************************************
1976 * SetupDiGetClassImageIndex (SETUPAPI.@)
1982 OUT PINT ImageIndex
)
1984 LPWSTR Buffer
= NULL
;
1985 DWORD dwRegType
, dwLength
;
1989 /* Read icon registry key */
1990 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1991 if (rc
!= ERROR_SUCCESS
)
1995 } else if (dwRegType
!= REG_SZ
)
1997 SetLastError(ERROR_INVALID_INDEX
);
2000 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2003 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2006 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2007 if (rc
!= ERROR_SUCCESS
)
2012 /* make sure the returned buffer is NULL-terminated */
2013 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2015 /* Transform icon value to a INT */
2016 *ImageIndex
= atoiW(Buffer
);
2025 SetupDiGetClassImageIndex(
2026 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2027 IN CONST GUID
*ClassGuid
,
2028 OUT PINT ImageIndex
)
2030 struct ClassImageList
*list
;
2033 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2035 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2036 SetLastError(ERROR_INVALID_PARAMETER
);
2037 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2038 SetLastError(ERROR_INVALID_USER_BUFFER
);
2039 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2040 SetLastError(ERROR_INVALID_USER_BUFFER
);
2041 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2042 SetLastError(ERROR_INVALID_USER_BUFFER
);
2043 else if (!ImageIndex
)
2044 SetLastError(ERROR_INVALID_PARAMETER
);
2047 HKEY hKey
= INVALID_HANDLE_VALUE
;
2050 /* Read Icon registry entry into Buffer */
2051 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2052 if (hKey
== INVALID_HANDLE_VALUE
)
2054 if (!GetIconIndex(hKey
, &iconIndex
))
2059 SetLastError(ERROR_INVALID_INDEX
);
2063 *ImageIndex
= -iconIndex
;
2067 if (hKey
!= INVALID_HANDLE_VALUE
)
2071 TRACE("Returning %d\n", ret
);
2075 /***********************************************************************
2076 * SetupDiGetClassImageList(SETUPAPI.@)
2079 SetupDiGetClassImageList(
2080 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2082 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2085 /***********************************************************************
2086 * SetupDiGetClassImageListExA(SETUPAPI.@)
2089 SetupDiGetClassImageListExA(
2090 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2091 IN PCSTR MachineName OPTIONAL
,
2094 PWSTR MachineNameW
= NULL
;
2099 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2100 if (MachineNameW
== NULL
)
2104 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2107 MyFree(MachineNameW
);
2112 /***********************************************************************
2113 * SetupDiGetClassImageListExW(SETUPAPI.@)
2116 SetupDiGetClassImageListExW(
2117 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2118 IN PCWSTR MachineName OPTIONAL
,
2123 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2125 if (!ClassImageListData
)
2126 SetLastError(ERROR_INVALID_PARAMETER
);
2127 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2128 SetLastError(ERROR_INVALID_USER_BUFFER
);
2130 SetLastError(ERROR_INVALID_PARAMETER
);
2133 struct ClassImageList
*list
= NULL
;
2136 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2138 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
2139 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2142 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2145 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2148 list
->szData
[0] = list
->szData
[1] = '\\';
2149 strcpyW(list
->szData
+ 2, MachineName
);
2150 list
->MachineName
= list
->szData
;
2154 list
->MachineName
= NULL
;
2157 ClassImageListData
->Reserved
= (ULONG_PTR
)list
;
2165 TRACE("Returning %d\n", ret
);
2169 /***********************************************************************
2170 * SetupDiLoadClassIcon(SETUPAPI.@)
2173 SetupDiLoadClassIcon(
2174 IN CONST GUID
*ClassGuid
,
2175 OUT HICON
*LargeIcon OPTIONAL
,
2176 OUT PINT MiniIconIndex OPTIONAL
)
2181 SetLastError(ERROR_INVALID_PARAMETER
);
2184 LPWSTR Buffer
= NULL
;
2187 HKEY hKey
= INVALID_HANDLE_VALUE
;
2189 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2190 if (hKey
== INVALID_HANDLE_VALUE
)
2193 if (!GetIconIndex(hKey
, &iconIndex
))
2198 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2201 DWORD dwRegType
, dwLength
;
2202 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2203 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2205 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2208 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2211 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2212 if (rc
!= ERROR_SUCCESS
)
2217 /* make sure the returned buffer is NULL-terminated */
2218 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2221 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2222 && dwRegType
== REG_SZ
)
2224 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2227 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2230 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2231 if (rc
!= ERROR_SUCCESS
)
2236 /* make sure the returned buffer is NULL-terminated */
2237 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2241 /* Unable to find where to load the icon */
2242 SetLastError(ERROR_FILE_NOT_FOUND
);
2245 Comma
= strchrW(Buffer
, ',');
2248 SetLastError(ERROR_GEN_FAILURE
);
2256 /* Look up icon in setupapi.dll */
2257 DllName
= L
"setupapi.dll";
2258 iconIndex
= -iconIndex
;
2261 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2264 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2266 SetLastError(ERROR_INVALID_INDEX
);
2271 *MiniIconIndex
= iconIndex
;
2275 if (hKey
!= INVALID_HANDLE_VALUE
)
2280 TRACE("Returning %d\n", ret
);
2284 /***********************************************************************
2285 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2288 SetupDiEnumDeviceInterfaces(
2289 IN HDEVINFO DeviceInfoSet
,
2290 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
2291 IN CONST GUID
*InterfaceClassGuid
,
2292 IN DWORD MemberIndex
,
2293 OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2297 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2298 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2300 if (!DeviceInterfaceData
)
2301 SetLastError(ERROR_INVALID_PARAMETER
);
2302 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2303 SetLastError(ERROR_INVALID_USER_BUFFER
);
2304 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2306 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2308 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2310 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2312 while (ItemList
!= &list
->ListHead
&& !Found
)
2314 PLIST_ENTRY InterfaceListEntry
;
2315 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
2316 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2318 /* We are not searching for this element */
2319 ItemList
= ItemList
->Flink
;
2322 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2323 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2325 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2326 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2328 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2331 if (MemberIndex
-- == 0)
2333 /* return this item */
2334 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2335 &DevItf
->InterfaceClassGuid
,
2337 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2338 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2341 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2343 ItemList
= ItemList
->Flink
;
2346 SetLastError(ERROR_NO_MORE_ITEMS
);
2351 SetLastError(ERROR_INVALID_HANDLE
);
2354 SetLastError(ERROR_INVALID_HANDLE
);
2359 ReferenceInfFile(struct InfFileDetails
* infFile
)
2361 InterlockedIncrement(&infFile
->References
);
2365 DereferenceInfFile(struct InfFileDetails
* infFile
)
2367 if (InterlockedDecrement(&infFile
->References
) == 0)
2369 SetupCloseInfFile(infFile
->hInf
);
2370 HeapFree(GetProcessHeap(), 0, infFile
);
2375 DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2377 DereferenceInfFile(driverInfo
->InfFileDetails
);
2378 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2379 HeapFree(GetProcessHeap(), 0, driverInfo
);
2384 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2386 return HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2390 DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2392 PLIST_ENTRY ListEntry
;
2393 struct DriverInfoElement
*driverInfo
;
2394 struct DeviceInterface
*deviceInterface
;
2396 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2398 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2399 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
2400 if (!DestroyDriverInfoElement(driverInfo
))
2403 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2405 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2406 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
2407 if (!DestroyDeviceInterface(deviceInterface
))
2410 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2411 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
2415 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2417 PLIST_ENTRY ListEntry
;
2418 struct DeviceInfoElement
*deviceInfo
;
2420 while (!IsListEmpty(&list
->ListHead
))
2422 ListEntry
= RemoveHeadList(&list
->ListHead
);
2423 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfoElement
, ListEntry
);
2424 if (!DestroyDeviceInfoElement(deviceInfo
))
2427 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2428 RegCloseKey(list
->HKLM
);
2429 CM_Disconnect_Machine(list
->hMachine
);
2430 DestroyClassInstallParams(&list
->ClassInstallParams
);
2431 return HeapFree(GetProcessHeap(), 0, list
);
2434 /***********************************************************************
2435 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2438 SetupDiDestroyDeviceInfoList(
2439 IN HDEVINFO DeviceInfoSet
)
2443 TRACE("%p\n", DeviceInfoSet
);
2444 if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2446 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2448 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2449 ret
= DestroyDeviceInfoSet(list
);
2451 SetLastError(ERROR_INVALID_HANDLE
);
2454 SetLastError(ERROR_INVALID_HANDLE
);
2456 TRACE("Returning %d\n", ret
);
2460 /***********************************************************************
2461 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2464 SetupDiGetDeviceInterfaceDetailA(
2465 IN HDEVINFO DeviceInfoSet
,
2466 IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2467 OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData OPTIONAL
,
2468 IN DWORD DeviceInterfaceDetailDataSize
,
2469 OUT PDWORD RequiredSize OPTIONAL
,
2470 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2472 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2473 DWORD sizeW
= 0, sizeA
;
2476 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2477 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2478 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2480 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2481 SetLastError(ERROR_INVALID_USER_BUFFER
);
2482 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2483 SetLastError(ERROR_INVALID_PARAMETER
);
2484 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2485 SetLastError(ERROR_INVALID_PARAMETER
);
2488 if (DeviceInterfaceDetailData
!= NULL
)
2490 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2491 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2492 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2493 if (!DeviceInterfaceDetailDataW
)
2495 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2498 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2500 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2501 ret
= SetupDiGetDeviceInterfaceDetailW(
2503 DeviceInterfaceData
,
2504 DeviceInterfaceDetailDataW
,
2508 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2509 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2511 *RequiredSize
= sizeA
;
2512 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2514 if (!WideCharToMultiByte(
2516 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2517 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2524 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2527 TRACE("Returning %d\n", ret
);
2531 /***********************************************************************
2532 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2535 SetupDiGetDeviceInterfaceDetailW(
2536 IN HDEVINFO DeviceInfoSet
,
2537 IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2538 OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData OPTIONAL
,
2539 IN DWORD DeviceInterfaceDetailDataSize
,
2540 OUT PDWORD RequiredSize OPTIONAL
,
2541 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2545 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2546 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2547 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2549 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2550 SetLastError(ERROR_INVALID_PARAMETER
);
2551 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2552 SetLastError(ERROR_INVALID_HANDLE
);
2553 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2554 SetLastError(ERROR_INVALID_HANDLE
);
2555 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2556 SetLastError(ERROR_INVALID_USER_BUFFER
);
2557 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2558 SetLastError(ERROR_INVALID_USER_BUFFER
);
2559 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2560 SetLastError(ERROR_INVALID_USER_BUFFER
);
2561 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2562 SetLastError(ERROR_INVALID_PARAMETER
);
2563 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2564 SetLastError(ERROR_INVALID_PARAMETER
);
2567 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2568 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2569 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2570 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2572 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2574 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2576 *RequiredSize
= sizeRequired
;
2580 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
2581 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2584 memcpy(&DeviceInfoData
->ClassGuid
,
2585 &deviceInterface
->DeviceInfo
->ClassGuid
,
2587 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2588 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2594 TRACE("Returning %d\n", ret
);
2598 /***********************************************************************
2599 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2602 SetupDiGetDeviceRegistryPropertyA(
2603 IN HDEVINFO DeviceInfoSet
,
2604 IN PSP_DEVINFO_DATA DeviceInfoData
,
2606 OUT PDWORD PropertyRegDataType OPTIONAL
,
2607 OUT PBYTE PropertyBuffer OPTIONAL
,
2608 IN DWORD PropertyBufferSize
,
2609 OUT PDWORD RequiredSize OPTIONAL
)
2612 BOOL bIsStringProperty
;
2614 DWORD RequiredSizeA
, RequiredSizeW
;
2615 DWORD PropertyBufferSizeW
= 0;
2616 PBYTE PropertyBufferW
= NULL
;
2618 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2619 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2622 if (PropertyBufferSize
!= 0)
2624 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2625 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2626 if (!PropertyBufferW
)
2628 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2633 bResult
= SetupDiGetDeviceRegistryPropertyW(
2639 PropertyBufferSizeW
,
2642 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2644 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2646 if (bIsStringProperty
)
2647 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2649 RequiredSizeA
= RequiredSizeW
;
2651 *RequiredSize
= RequiredSizeA
;
2652 if (PropertyRegDataType
)
2653 *PropertyRegDataType
= RegType
;
2658 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2662 if (RequiredSizeA
<= PropertyBufferSize
)
2664 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2666 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2668 /* Last error is already set by WideCharToMultiByte */
2673 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2677 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2681 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2685 /***********************************************************************
2686 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2689 SetupDiGetDeviceRegistryPropertyW(
2690 IN HDEVINFO DeviceInfoSet
,
2691 IN PSP_DEVINFO_DATA DeviceInfoData
,
2693 OUT PDWORD PropertyRegDataType OPTIONAL
,
2694 OUT PBYTE PropertyBuffer OPTIONAL
,
2695 IN DWORD PropertyBufferSize
,
2696 OUT PDWORD RequiredSize OPTIONAL
)
2698 HKEY hEnumKey
, hKey
;
2702 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2703 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2706 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2707 SetLastError(ERROR_INVALID_HANDLE
);
2708 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2709 SetLastError(ERROR_INVALID_HANDLE
);
2710 else if (!DeviceInfoData
)
2711 SetLastError(ERROR_INVALID_PARAMETER
);
2712 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2713 SetLastError(ERROR_INVALID_USER_BUFFER
);
2714 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2715 SetLastError(ERROR_INVALID_PARAMETER
);
2718 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2719 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2723 case SPDRP_CAPABILITIES
:
2725 case SPDRP_CLASSGUID
:
2726 case SPDRP_COMPATIBLEIDS
:
2727 case SPDRP_CONFIGFLAGS
:
2728 case SPDRP_DEVICEDESC
:
2730 case SPDRP_FRIENDLYNAME
:
2731 case SPDRP_HARDWAREID
:
2732 case SPDRP_LOCATION_INFORMATION
:
2733 case SPDRP_LOWERFILTERS
:
2735 case SPDRP_SECURITY
:
2737 case SPDRP_UI_NUMBER
:
2738 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2739 case SPDRP_UPPERFILTERS
:
2741 LPCWSTR RegistryPropertyName
;
2746 case SPDRP_CAPABILITIES
:
2747 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2749 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2750 case SPDRP_CLASSGUID
:
2751 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2752 case SPDRP_COMPATIBLEIDS
:
2753 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2754 case SPDRP_CONFIGFLAGS
:
2755 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2756 case SPDRP_DEVICEDESC
:
2757 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2759 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2760 case SPDRP_FRIENDLYNAME
:
2761 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2762 case SPDRP_HARDWAREID
:
2763 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2764 case SPDRP_LOCATION_INFORMATION
:
2765 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2766 case SPDRP_LOWERFILTERS
:
2767 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2769 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2770 case SPDRP_SECURITY
:
2771 RegistryPropertyName
= REGSTR_SECURITY
; break;
2773 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2774 case SPDRP_UI_NUMBER
:
2775 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2776 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2777 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
; break;
2778 case SPDRP_UPPERFILTERS
:
2779 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2781 /* Should not happen */
2782 RegistryPropertyName
= NULL
; break;
2785 /* Open registry key name */
2788 REGSTR_PATH_SYSTEMENUM
,
2792 if (rc
!= ERROR_SUCCESS
)
2803 RegCloseKey(hEnumKey
);
2804 if (rc
!= ERROR_SUCCESS
)
2809 /* Read registry entry */
2810 BufferSize
= PropertyBufferSize
;
2811 rc
= RegQueryValueExW(
2813 RegistryPropertyName
,
2814 NULL
, /* Reserved */
2815 PropertyRegDataType
,
2819 *RequiredSize
= BufferSize
;
2822 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2825 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2827 case ERROR_MORE_DATA
:
2828 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2837 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2839 DWORD required
= (strlenW(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2841 if (PropertyRegDataType
)
2842 *PropertyRegDataType
= REG_SZ
;
2844 *RequiredSize
= required
;
2845 if (PropertyBufferSize
>= required
)
2847 strcpyW((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2851 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2855 /*case SPDRP_BUSTYPEGUID:
2856 case SPDRP_LEGACYBUSTYPE:
2857 case SPDRP_BUSNUMBER:
2858 case SPDRP_ENUMERATOR_NAME:
2859 case SPDRP_SECURITY_SDS:
2861 case SPDRP_EXCLUSIVE:
2862 case SPDRP_CHARACTERISTICS:
2864 case SPDRP_DEVICE_POWER_DATA:*/
2865 #if (WINVER >= 0x501)
2866 /*case SPDRP_REMOVAL_POLICY:
2867 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2868 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2869 case SPDRP_INSTALL_STATE:*/
2874 ERR("Property 0x%lx not implemented\n", Property
);
2875 SetLastError(ERROR_NOT_SUPPORTED
);
2880 TRACE("Returning %d\n", ret
);
2884 /***********************************************************************
2885 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2888 SetupDiSetDeviceRegistryPropertyA(
2889 IN HDEVINFO DeviceInfoSet
,
2890 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2892 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
2893 IN DWORD PropertyBufferSize
)
2895 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2896 Property
, PropertyBuffer
, PropertyBufferSize
);
2897 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2901 /***********************************************************************
2902 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2905 SetupDiSetDeviceRegistryPropertyW(
2906 IN HDEVINFO DeviceInfoSet
,
2907 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2909 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
2910 IN DWORD PropertyBufferSize
)
2912 struct DeviceInfoSet
*list
;
2915 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2916 Property
, PropertyBuffer
, PropertyBufferSize
);
2919 SetLastError(ERROR_INVALID_HANDLE
);
2920 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2921 SetLastError(ERROR_INVALID_HANDLE
);
2922 else if (!DeviceInfoData
)
2923 SetLastError(ERROR_INVALID_HANDLE
);
2924 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2925 SetLastError(ERROR_INVALID_USER_BUFFER
);
2930 case SPDRP_COMPATIBLEIDS
:
2931 case SPDRP_CONFIGFLAGS
:
2932 case SPDRP_FRIENDLYNAME
:
2933 case SPDRP_HARDWAREID
:
2934 case SPDRP_LOCATION_INFORMATION
:
2935 case SPDRP_LOWERFILTERS
:
2936 case SPDRP_SECURITY
:
2938 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2939 case SPDRP_UPPERFILTERS
:
2941 LPCWSTR RegistryPropertyName
;
2942 DWORD RegistryDataType
;
2948 case SPDRP_COMPATIBLEIDS
:
2949 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2950 RegistryDataType
= REG_MULTI_SZ
;
2952 case SPDRP_CONFIGFLAGS
:
2953 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2954 RegistryDataType
= REG_DWORD
;
2956 case SPDRP_FRIENDLYNAME
:
2957 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2958 RegistryDataType
= REG_SZ
;
2960 case SPDRP_HARDWAREID
:
2961 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2962 RegistryDataType
= REG_MULTI_SZ
;
2964 case SPDRP_LOCATION_INFORMATION
:
2965 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2966 RegistryDataType
= REG_SZ
;
2968 case SPDRP_LOWERFILTERS
:
2969 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2970 RegistryDataType
= REG_MULTI_SZ
;
2972 case SPDRP_SECURITY
:
2973 RegistryPropertyName
= REGSTR_SECURITY
;
2974 RegistryDataType
= REG_BINARY
;
2977 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2978 RegistryDataType
= REG_SZ
;
2980 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2981 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
;
2982 RegistryDataType
= REG_SZ
;
2984 case SPDRP_UPPERFILTERS
:
2985 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2986 RegistryDataType
= REG_MULTI_SZ
;
2989 /* Should not happen */
2990 RegistryPropertyName
= NULL
;
2991 RegistryDataType
= REG_BINARY
;
2994 /* Open device registry key */
2995 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2996 if (hKey
!= INVALID_HANDLE_VALUE
)
2998 /* Write new data */
2999 rc
= RegSetValueExW(
3001 RegistryPropertyName
,
3005 PropertyBufferSize
);
3006 if (rc
== ERROR_SUCCESS
)
3015 /*case SPDRP_CHARACTERISTICS:
3017 case SPDRP_EXCLUSIVE:*/
3018 #if (WINVER >= 0x501)
3019 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
3021 //case SPDRP_SECURITY_SDS:
3025 ERR("Property 0x%lx not implemented\n", Property
);
3026 SetLastError(ERROR_NOT_SUPPORTED
);
3031 TRACE("Returning %d\n", ret
);
3036 /***********************************************************************
3037 * SetupDiInstallClassA (SETUPAPI.@)
3040 SetupDiInstallClassA(
3041 IN HWND hwndParent OPTIONAL
,
3042 IN PCSTR InfFileName
,
3044 IN HSPFILEQ FileQueue OPTIONAL
)
3046 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3050 /***********************************************************************
3051 * SetupDiInstallClassW (SETUPAPI.@)
3054 SetupDiInstallClassW(
3055 IN HWND hwndParent OPTIONAL
,
3056 IN PCWSTR InfFileName
,
3058 IN HSPFILEQ FileQueue OPTIONAL
)
3060 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3064 /***********************************************************************
3065 * SetupDiInstallClassExA (SETUPAPI.@)
3068 SetupDiInstallClassExA(
3069 IN HWND hwndParent OPTIONAL
,
3070 IN PCSTR InfFileName OPTIONAL
,
3072 IN HSPFILEQ FileQueue OPTIONAL
,
3073 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3077 PWSTR InfFileNameW
= NULL
;
3082 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3083 if (InfFileNameW
== NULL
)
3085 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3090 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3091 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3093 MyFree(InfFileNameW
);
3100 CreateClassKey(HINF hInf
)
3102 WCHAR FullBuffer
[MAX_PATH
];
3103 WCHAR Buffer
[MAX_PATH
];
3105 HKEY hClassKey
= NULL
;
3106 HKEY ret
= INVALID_HANDLE_VALUE
;
3108 FullBuffer
[0] = '\0';
3110 if (!SetupGetLineTextW(NULL
,
3121 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3122 lstrcatW(FullBuffer
, Buffer
);
3124 if (!SetupGetLineTextW(NULL
,
3132 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3136 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3140 REG_OPTION_NON_VOLATILE
,
3149 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3154 RequiredSize
* sizeof(WCHAR
)))
3162 if (hClassKey
!= NULL
&& hClassKey
!= ret
)
3163 RegCloseKey(hClassKey
);
3164 if (ret
== INVALID_HANDLE_VALUE
&& FullBuffer
[0] != '\0')
3165 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3170 /***********************************************************************
3171 * SetupDiInstallClassExW (SETUPAPI.@)
3174 SetupDiInstallClassExW(
3175 IN HWND hwndParent OPTIONAL
,
3176 IN PCWSTR InfFileName OPTIONAL
,
3178 IN HSPFILEQ FileQueue OPTIONAL
,
3179 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3185 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3186 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3190 FIXME("Case not implemented: InfFileName NULL\n");
3191 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3193 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3195 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3196 SetLastError(ERROR_INVALID_FLAGS
);
3198 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3199 SetLastError(ERROR_INVALID_PARAMETER
);
3200 else if (Reserved1
!= NULL
)
3201 SetLastError(ERROR_INVALID_PARAMETER
);
3202 else if (Reserved2
!= NULL
)
3203 SetLastError(ERROR_INVALID_PARAMETER
);
3206 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
3207 SP_DEVINSTALL_PARAMS_W InstallParams
;
3208 WCHAR SectionName
[MAX_PATH
];
3209 HINF hInf
= INVALID_HANDLE_VALUE
;
3210 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3211 PVOID callback_context
= NULL
;
3213 hDeviceInfo
= SetupDiCreateDeviceInfoList(NULL
, NULL
);
3215 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3216 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3218 InstallParams
.Flags
&= ~(DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3219 InstallParams
.Flags
|= Flags
& (DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3220 if (Flags
& DI_NOVCP
)
3221 InstallParams
.FileQueue
= FileQueue
;
3222 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3225 /* Open the .inf file */
3226 hInf
= SetupOpenInfFileW(
3231 if (hInf
== INVALID_HANDLE_VALUE
)
3234 /* Try to append a layout file */
3235 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3239 if (InterfaceClassGuid
)
3241 /* Retrieve the actual section name */
3242 ret
= SetupDiGetActualSectionToInstallW(
3252 /* Open registry key related to this interface */
3253 /* FIXME: What happens if the key doesn't exist? */
3254 hRootKey
= SetupDiOpenClassRegKeyExW(InterfaceClassGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, NULL
, NULL
);
3255 if (hRootKey
== INVALID_HANDLE_VALUE
)
3258 /* SetupDiCreateDeviceInterface??? */
3259 FIXME("Installing an interface is not implemented\n");
3260 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3264 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3265 hRootKey
= CreateClassKey(hInf
);
3266 if (hRootKey
== INVALID_HANDLE_VALUE
)
3269 /* Retrieve the actual section name */
3270 ret
= SetupDiGetActualSectionToInstallW(
3274 MAX_PATH
- strlenW(DotServices
),
3280 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3281 if (!callback_context
)
3284 ret
= SetupInstallFromInfSectionW(
3288 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3290 NULL
, /* SourceRootPath */
3291 !(Flags
& DI_NOVCP
) && (Flags
& DI_FORCECOPY
) ? SP_COPY_FORCE_IN_USE
: 0, /* CopyFlags */
3292 SetupDefaultQueueCallbackW
,
3299 /* Install .Services section */
3300 lstrcatW(SectionName
, DotServices
);
3301 ret
= SetupInstallServicesFromInfSectionExW(
3316 if (hDeviceInfo
!= INVALID_HANDLE_VALUE
)
3317 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
3318 if (hInf
!= INVALID_HANDLE_VALUE
)
3319 SetupCloseInfFile(hInf
);
3320 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3321 RegCloseKey(hRootKey
);
3322 SetupTermDefaultQueueCallback(callback_context
);
3325 TRACE("Returning %d\n", ret
);
3330 /***********************************************************************
3331 * SetupDiOpenClassRegKey (SETUPAPI.@)
3334 SetupDiOpenClassRegKey(
3335 IN CONST GUID
*ClassGuid OPTIONAL
,
3336 IN REGSAM samDesired
)
3338 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3339 DIOCR_INSTALLER
, NULL
, NULL
);
3343 /***********************************************************************
3344 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3347 SetupDiOpenClassRegKeyExA(
3348 IN CONST GUID
*ClassGuid OPTIONAL
,
3349 IN REGSAM samDesired
,
3351 IN PCSTR MachineName OPTIONAL
,
3354 PWSTR MachineNameW
= NULL
;
3361 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3362 if (MachineNameW
== NULL
)
3363 return INVALID_HANDLE_VALUE
;
3366 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3367 Flags
, MachineNameW
, Reserved
);
3370 MyFree(MachineNameW
);
3376 /***********************************************************************
3377 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3380 SetupDiOpenClassRegKeyExW(
3381 IN CONST GUID
* ClassGuid OPTIONAL
,
3382 IN REGSAM samDesired
,
3384 IN PCWSTR MachineName OPTIONAL
,
3387 LPWSTR lpGuidString
= NULL
;
3388 LPWSTR lpFullGuidString
= NULL
;
3391 HKEY hClassesKey
= NULL
;
3392 HKEY hClassKey
= NULL
;
3393 HKEY ret
= INVALID_HANDLE_VALUE
;
3397 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3398 Flags
, debugstr_w(MachineName
), Reserved
);
3400 if (Flags
== DIOCR_INSTALLER
)
3401 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3402 else if (Flags
== DIOCR_INTERFACE
)
3403 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3406 ERR("Invalid Flags parameter!\n");
3407 SetLastError(ERROR_INVALID_FLAGS
);
3411 if (MachineName
!= NULL
)
3413 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3414 if (rc
!= ERROR_SUCCESS
)
3421 HKLM
= HKEY_LOCAL_MACHINE
;
3423 rc
= RegOpenKeyExW(HKLM
,
3426 ClassGuid
? 0 : samDesired
,
3428 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3429 if (rc
!= ERROR_SUCCESS
)
3435 if (ClassGuid
== NULL
)
3437 /* Stop here. We don't need to open a subkey */
3442 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3444 SetLastError(ERROR_GEN_FAILURE
);
3448 dwLength
= lstrlenW(lpGuidString
);
3449 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3450 if (!lpFullGuidString
)
3452 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3455 lpFullGuidString
[0] = '{';
3456 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3457 lpFullGuidString
[dwLength
+ 1] = '}';
3458 lpFullGuidString
[dwLength
+ 2] = '\0';
3460 rc
= RegOpenKeyExW(hClassesKey
,
3465 if (rc
!= ERROR_SUCCESS
)
3473 if (hClassKey
!= NULL
&& hClassKey
!= ret
)
3474 RegCloseKey(hClassKey
);
3475 if (hClassesKey
!= NULL
&& hClassesKey
!= ret
)
3476 RegCloseKey(hClassesKey
);
3478 RpcStringFreeW(&lpGuidString
);
3479 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3484 /***********************************************************************
3485 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3488 SetupDiOpenDeviceInterfaceW(
3489 IN HDEVINFO DeviceInfoSet
,
3490 IN PCWSTR DevicePath
,
3492 OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL
)
3494 FIXME("%p %s %08lx %p\n",
3495 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3499 /***********************************************************************
3500 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3503 SetupDiOpenDeviceInterfaceA(
3504 IN HDEVINFO DeviceInfoSet
,
3505 IN PCSTR DevicePath
,
3507 OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL
)
3509 LPWSTR DevicePathW
= NULL
;
3512 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3514 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3515 if (DevicePathW
== NULL
)
3518 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3519 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3521 MyFree(DevicePathW
);
3526 /***********************************************************************
3527 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3530 SetupDiSetClassInstallParamsA(
3531 IN HDEVINFO DeviceInfoSet
,
3532 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3533 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3534 IN DWORD ClassInstallParamsSize
)
3536 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3537 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3541 /***********************************************************************
3542 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3545 SetupDiSetClassInstallParamsW(
3546 IN HDEVINFO DeviceInfoSet
,
3547 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3548 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3549 IN DWORD ClassInstallParamsSize
)
3551 struct DeviceInfoSet
*list
;
3554 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3555 ClassInstallParams
, ClassInstallParamsSize
);
3558 SetLastError(ERROR_INVALID_PARAMETER
);
3559 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3560 SetLastError(ERROR_INVALID_HANDLE
);
3561 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3562 SetLastError(ERROR_INVALID_HANDLE
);
3563 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3564 SetLastError(ERROR_INVALID_USER_BUFFER
);
3565 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3566 SetLastError(ERROR_INVALID_USER_BUFFER
);
3567 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3568 SetLastError(ERROR_INVALID_PARAMETER
);
3569 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3570 SetLastError(ERROR_INVALID_PARAMETER
);
3573 SP_DEVINSTALL_PARAMS_W InstallParams
;
3576 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3577 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3581 if (ClassInstallParams
)
3583 /* Check parameters in ClassInstallParams */
3584 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3585 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3587 SetLastError(ERROR_INVALID_USER_BUFFER
);
3590 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3592 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3593 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3596 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3599 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3603 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3606 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3610 TRACE("Returning %d\n", ret
);
3615 PropertyChangeHandler(
3616 IN HDEVINFO DeviceInfoSet
,
3617 IN PSP_DEVINFO_DATA DeviceInfoData
,
3618 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3619 IN DWORD ClassInstallParamsSize
)
3621 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3624 if (!DeviceInfoData
)
3625 SetLastError(ERROR_INVALID_PARAMETER
);
3626 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3627 SetLastError(ERROR_INVALID_PARAMETER
);
3628 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3629 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3630 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3631 SetLastError(ERROR_INVALID_FLAGS
);
3632 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3633 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3634 SetLastError(ERROR_INVALID_FLAGS
);
3635 else if (PropChangeParams
3636 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3637 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3638 SetLastError(ERROR_INVALID_USER_BUFFER
);
3641 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3642 if (!DeviceInfoData
)
3644 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3645 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3649 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3650 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3652 if (*CurrentPropChangeParams
)
3654 MyFree(*CurrentPropChangeParams
);
3655 *CurrentPropChangeParams
= NULL
;
3657 if (PropChangeParams
)
3659 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3660 if (!*CurrentPropChangeParams
)
3662 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3665 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3676 IN PWSTR InstallerName
,