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 if (InstancePath
!= NULL
)
1723 HeapFree(GetProcessHeap(), 0, InstancePath
);
1724 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1727 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1730 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1731 if (rc
!= ERROR_SUCCESS
)
1733 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1734 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1736 if (DeviceInstanceW
)
1738 /* Check if device enumerator is not the right one */
1739 if (strcmpW(DeviceInstanceW
, InstancePath
) != 0)
1743 /* Find class GUID associated to the device instance */
1746 REGSTR_PATH_SYSTEMENUM
,
1750 if (rc
!= ERROR_SUCCESS
)
1758 RegCloseKey(hEnumKey
);
1759 if (rc
!= ERROR_SUCCESS
)
1761 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1762 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1764 if (rc
!= ERROR_SUCCESS
)
1766 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1767 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1768 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1770 rc
= ERROR_GEN_FAILURE
;
1773 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1775 /* If current device doesn't match the list GUID (if any), skip this entry */
1776 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1779 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1783 struct DeviceInterface
*interfaceInfo
;
1785 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1786 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1787 if (rc
== ERROR_NO_MORE_ITEMS
)
1789 if (rc
!= ERROR_SUCCESS
)
1792 if (KeyBuffer
[0] != '#')
1793 /* This entry doesn't represent an interesting entry */
1797 if (hReferenceKey
!= NULL
)
1798 RegCloseKey(hReferenceKey
);
1799 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1800 if (rc
!= ERROR_SUCCESS
)
1803 /* Read SymbolicLink value */
1804 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1805 if (rc
!= ERROR_SUCCESS
)
1807 if (dwRegType
!= REG_SZ
)
1809 rc
= ERROR_GEN_FAILURE
;
1813 /* We have found a device */
1814 /* Step 1. Create a device info element */
1815 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1817 rc
= GetLastError();
1820 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1821 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1823 /* Step 2. Create an interface list for this element */
1824 if (pSymbolicLink
!= NULL
)
1825 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1826 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1829 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1832 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1833 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1834 if (rc
!= ERROR_SUCCESS
)
1836 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1838 rc
= GetLastError();
1842 /* Step 3. Update flags */
1843 if (KeyBuffer
[1] == '\0')
1844 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
1845 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
1846 if (rc
!= ERROR_SUCCESS
)
1848 if (OnlyPresentInterfaces
)
1850 DestroyDeviceInterface(interfaceInfo
);
1854 interfaceInfo
->Flags
|= SPINT_REMOVED
;
1858 dwLength
= sizeof(DWORD
);
1859 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
1860 && dwRegType
== REG_DWORD
&& LinkedValue
)
1861 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
1862 RegCloseKey(hControlKey
);
1865 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1866 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1872 if (hReferenceKey
!= NULL
)
1873 RegCloseKey(hReferenceKey
);
1874 if (hDeviceInstanceKey
!= NULL
)
1875 RegCloseKey(hDeviceInstanceKey
);
1876 if (hInterfaceKey
!= INVALID_HANDLE_VALUE
)
1877 RegCloseKey(hInterfaceKey
);
1878 if (InstancePath
!= NULL
)
1879 HeapFree(GetProcessHeap(), 0, InstancePath
);
1880 if (pSymbolicLink
!= NULL
)
1881 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1885 /***********************************************************************
1886 * SetupDiGetClassDevsExW (SETUPAPI.@)
1889 SetupDiGetClassDevsExW(
1890 IN CONST GUID
*ClassGuid OPTIONAL
,
1891 IN PCWSTR Enumerator OPTIONAL
,
1892 IN HWND hwndParent OPTIONAL
,
1894 IN HDEVINFO DeviceInfoSet OPTIONAL
,
1895 IN PCWSTR MachineName OPTIONAL
,
1898 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1899 struct DeviceInfoSet
*list
;
1900 CONST GUID
*pClassGuid
;
1902 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1904 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(ClassGuid
), debugstr_w(Enumerator
),
1905 hwndParent
, Flags
, DeviceInfoSet
, debugstr_w(MachineName
), Reserved
);
1907 /* Create the deviceset if not set */
1910 list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1911 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1913 SetLastError(ERROR_INVALID_HANDLE
);
1916 hDeviceInfo
= DeviceInfoSet
;
1920 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1921 Flags
& DIGCF_DEVICEINTERFACE
? NULL
: ClassGuid
,
1922 NULL
, MachineName
, NULL
);
1923 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1925 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1928 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1931 pClassGuid
= &list
->ClassGuid
;
1933 if (Flags
& DIGCF_PROFILE
)
1934 FIXME(": flag DIGCF_PROFILE ignored\n");
1936 if (Flags
& DIGCF_ALLCLASSES
)
1938 rc
= SETUP_CreateDevList(list
, MachineName
, pClassGuid
, Enumerator
);
1939 if (rc
!= ERROR_SUCCESS
)
1946 else if (Flags
& DIGCF_DEVICEINTERFACE
)
1948 if (ClassGuid
== NULL
)
1950 SetLastError(ERROR_INVALID_PARAMETER
);
1954 rc
= SETUP_CreateInterfaceList(list
, MachineName
, ClassGuid
, Enumerator
, Flags
& DIGCF_PRESENT
);
1955 if (rc
!= ERROR_SUCCESS
)
1964 rc
= SETUP_CreateDevList(list
, MachineName
, ClassGuid
, Enumerator
);
1965 if (rc
!= ERROR_SUCCESS
)
1974 if (!DeviceInfoSet
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= ret
)
1975 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1979 /***********************************************************************
1980 * SetupDiGetClassImageIndex (SETUPAPI.@)
1986 OUT PINT ImageIndex
)
1988 LPWSTR Buffer
= NULL
;
1989 DWORD dwRegType
, dwLength
;
1993 /* Read icon registry key */
1994 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1995 if (rc
!= ERROR_SUCCESS
)
1999 } else if (dwRegType
!= REG_SZ
)
2001 SetLastError(ERROR_INVALID_INDEX
);
2004 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2007 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2010 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2011 if (rc
!= ERROR_SUCCESS
)
2016 /* make sure the returned buffer is NULL-terminated */
2017 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2019 /* Transform icon value to a INT */
2020 *ImageIndex
= atoiW(Buffer
);
2029 SetupDiGetClassImageIndex(
2030 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2031 IN CONST GUID
*ClassGuid
,
2032 OUT PINT ImageIndex
)
2034 struct ClassImageList
*list
;
2037 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2039 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2040 SetLastError(ERROR_INVALID_PARAMETER
);
2041 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2042 SetLastError(ERROR_INVALID_USER_BUFFER
);
2043 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2044 SetLastError(ERROR_INVALID_USER_BUFFER
);
2045 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2046 SetLastError(ERROR_INVALID_USER_BUFFER
);
2047 else if (!ImageIndex
)
2048 SetLastError(ERROR_INVALID_PARAMETER
);
2051 HKEY hKey
= INVALID_HANDLE_VALUE
;
2054 /* Read Icon registry entry into Buffer */
2055 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2056 if (hKey
== INVALID_HANDLE_VALUE
)
2058 if (!GetIconIndex(hKey
, &iconIndex
))
2063 SetLastError(ERROR_INVALID_INDEX
);
2067 *ImageIndex
= -iconIndex
;
2071 if (hKey
!= INVALID_HANDLE_VALUE
)
2075 TRACE("Returning %d\n", ret
);
2079 /***********************************************************************
2080 * SetupDiGetClassImageList(SETUPAPI.@)
2083 SetupDiGetClassImageList(
2084 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2086 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2089 /***********************************************************************
2090 * SetupDiGetClassImageListExA(SETUPAPI.@)
2093 SetupDiGetClassImageListExA(
2094 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2095 IN PCSTR MachineName OPTIONAL
,
2098 PWSTR MachineNameW
= NULL
;
2103 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2104 if (MachineNameW
== NULL
)
2108 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2111 MyFree(MachineNameW
);
2116 /***********************************************************************
2117 * SetupDiGetClassImageListExW(SETUPAPI.@)
2120 SetupDiGetClassImageListExW(
2121 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2122 IN PCWSTR MachineName OPTIONAL
,
2127 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2129 if (!ClassImageListData
)
2130 SetLastError(ERROR_INVALID_PARAMETER
);
2131 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2132 SetLastError(ERROR_INVALID_USER_BUFFER
);
2134 SetLastError(ERROR_INVALID_PARAMETER
);
2137 struct ClassImageList
*list
= NULL
;
2140 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2142 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
2143 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2146 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2149 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2152 list
->szData
[0] = list
->szData
[1] = '\\';
2153 strcpyW(list
->szData
+ 2, MachineName
);
2154 list
->MachineName
= list
->szData
;
2158 list
->MachineName
= NULL
;
2161 ClassImageListData
->Reserved
= (ULONG_PTR
)list
;
2169 TRACE("Returning %d\n", ret
);
2173 /***********************************************************************
2174 * SetupDiLoadClassIcon(SETUPAPI.@)
2177 SetupDiLoadClassIcon(
2178 IN CONST GUID
*ClassGuid
,
2179 OUT HICON
*LargeIcon OPTIONAL
,
2180 OUT PINT MiniIconIndex OPTIONAL
)
2185 SetLastError(ERROR_INVALID_PARAMETER
);
2188 LPWSTR Buffer
= NULL
;
2191 HKEY hKey
= INVALID_HANDLE_VALUE
;
2193 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2194 if (hKey
== INVALID_HANDLE_VALUE
)
2197 if (!GetIconIndex(hKey
, &iconIndex
))
2202 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2205 DWORD dwRegType
, dwLength
;
2206 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2207 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2209 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2212 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2215 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2216 if (rc
!= ERROR_SUCCESS
)
2221 /* make sure the returned buffer is NULL-terminated */
2222 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2225 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2226 && dwRegType
== REG_SZ
)
2228 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2231 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2234 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2235 if (rc
!= ERROR_SUCCESS
)
2240 /* make sure the returned buffer is NULL-terminated */
2241 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2245 /* Unable to find where to load the icon */
2246 SetLastError(ERROR_FILE_NOT_FOUND
);
2249 Comma
= strchrW(Buffer
, ',');
2252 SetLastError(ERROR_GEN_FAILURE
);
2260 /* Look up icon in setupapi.dll */
2261 DllName
= L
"setupapi.dll";
2262 iconIndex
= -iconIndex
;
2265 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2268 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2270 SetLastError(ERROR_INVALID_INDEX
);
2275 *MiniIconIndex
= iconIndex
;
2279 if (hKey
!= INVALID_HANDLE_VALUE
)
2284 TRACE("Returning %d\n", ret
);
2288 /***********************************************************************
2289 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2292 SetupDiEnumDeviceInterfaces(
2293 IN HDEVINFO DeviceInfoSet
,
2294 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
2295 IN CONST GUID
*InterfaceClassGuid
,
2296 IN DWORD MemberIndex
,
2297 OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2301 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2302 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2304 if (!DeviceInterfaceData
)
2305 SetLastError(ERROR_INVALID_PARAMETER
);
2306 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2307 SetLastError(ERROR_INVALID_USER_BUFFER
);
2308 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2310 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2312 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2314 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2316 while (ItemList
!= &list
->ListHead
&& !Found
)
2318 PLIST_ENTRY InterfaceListEntry
;
2319 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
2320 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2322 /* We are not searching for this element */
2323 ItemList
= ItemList
->Flink
;
2326 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2327 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2329 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2330 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2332 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2335 if (MemberIndex
-- == 0)
2337 /* return this item */
2338 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2339 &DevItf
->InterfaceClassGuid
,
2341 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2342 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2345 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2347 ItemList
= ItemList
->Flink
;
2350 SetLastError(ERROR_NO_MORE_ITEMS
);
2355 SetLastError(ERROR_INVALID_HANDLE
);
2358 SetLastError(ERROR_INVALID_HANDLE
);
2363 ReferenceInfFile(struct InfFileDetails
* infFile
)
2365 InterlockedIncrement(&infFile
->References
);
2369 DereferenceInfFile(struct InfFileDetails
* infFile
)
2371 if (InterlockedDecrement(&infFile
->References
) == 0)
2373 SetupCloseInfFile(infFile
->hInf
);
2374 HeapFree(GetProcessHeap(), 0, infFile
);
2379 DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2381 DereferenceInfFile(driverInfo
->InfFileDetails
);
2382 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2383 HeapFree(GetProcessHeap(), 0, driverInfo
);
2388 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2390 return HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2394 DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2396 PLIST_ENTRY ListEntry
;
2397 struct DriverInfoElement
*driverInfo
;
2398 struct DeviceInterface
*deviceInterface
;
2400 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2402 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2403 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
2404 if (!DestroyDriverInfoElement(driverInfo
))
2407 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2409 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2410 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
2411 if (!DestroyDeviceInterface(deviceInterface
))
2414 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2415 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
2419 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2421 PLIST_ENTRY ListEntry
;
2422 struct DeviceInfoElement
*deviceInfo
;
2424 while (!IsListEmpty(&list
->ListHead
))
2426 ListEntry
= RemoveHeadList(&list
->ListHead
);
2427 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfoElement
, ListEntry
);
2428 if (!DestroyDeviceInfoElement(deviceInfo
))
2431 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2432 RegCloseKey(list
->HKLM
);
2433 CM_Disconnect_Machine(list
->hMachine
);
2434 DestroyClassInstallParams(&list
->ClassInstallParams
);
2435 return HeapFree(GetProcessHeap(), 0, list
);
2438 /***********************************************************************
2439 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2442 SetupDiDestroyDeviceInfoList(
2443 IN HDEVINFO DeviceInfoSet
)
2447 TRACE("%p\n", DeviceInfoSet
);
2448 if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2450 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2452 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2453 ret
= DestroyDeviceInfoSet(list
);
2455 SetLastError(ERROR_INVALID_HANDLE
);
2458 SetLastError(ERROR_INVALID_HANDLE
);
2460 TRACE("Returning %d\n", ret
);
2464 /***********************************************************************
2465 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2468 SetupDiGetDeviceInterfaceDetailA(
2469 IN HDEVINFO DeviceInfoSet
,
2470 IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2471 OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData OPTIONAL
,
2472 IN DWORD DeviceInterfaceDetailDataSize
,
2473 OUT PDWORD RequiredSize OPTIONAL
,
2474 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2476 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2477 DWORD sizeW
= 0, sizeA
;
2480 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2481 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2482 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2484 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2485 SetLastError(ERROR_INVALID_USER_BUFFER
);
2486 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2487 SetLastError(ERROR_INVALID_PARAMETER
);
2488 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2489 SetLastError(ERROR_INVALID_PARAMETER
);
2492 if (DeviceInterfaceDetailData
!= NULL
)
2494 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2495 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2496 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2497 if (!DeviceInterfaceDetailDataW
)
2499 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2502 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2504 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2505 ret
= SetupDiGetDeviceInterfaceDetailW(
2507 DeviceInterfaceData
,
2508 DeviceInterfaceDetailDataW
,
2512 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2513 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2515 *RequiredSize
= sizeA
;
2516 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2518 if (!WideCharToMultiByte(
2520 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2521 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2528 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2531 TRACE("Returning %d\n", ret
);
2535 /***********************************************************************
2536 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2539 SetupDiGetDeviceInterfaceDetailW(
2540 IN HDEVINFO DeviceInfoSet
,
2541 IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2542 OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData OPTIONAL
,
2543 IN DWORD DeviceInterfaceDetailDataSize
,
2544 OUT PDWORD RequiredSize OPTIONAL
,
2545 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2549 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2550 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2551 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2553 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2554 SetLastError(ERROR_INVALID_PARAMETER
);
2555 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2556 SetLastError(ERROR_INVALID_HANDLE
);
2557 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2558 SetLastError(ERROR_INVALID_HANDLE
);
2559 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2560 SetLastError(ERROR_INVALID_USER_BUFFER
);
2561 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2562 SetLastError(ERROR_INVALID_USER_BUFFER
);
2563 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2564 SetLastError(ERROR_INVALID_USER_BUFFER
);
2565 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2566 SetLastError(ERROR_INVALID_PARAMETER
);
2567 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2568 SetLastError(ERROR_INVALID_PARAMETER
);
2571 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2572 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2573 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2574 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2576 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2578 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2580 *RequiredSize
= sizeRequired
;
2584 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
2585 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2588 memcpy(&DeviceInfoData
->ClassGuid
,
2589 &deviceInterface
->DeviceInfo
->ClassGuid
,
2591 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2592 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2598 TRACE("Returning %d\n", ret
);
2602 /***********************************************************************
2603 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2606 SetupDiGetDeviceRegistryPropertyA(
2607 IN HDEVINFO DeviceInfoSet
,
2608 IN PSP_DEVINFO_DATA DeviceInfoData
,
2610 OUT PDWORD PropertyRegDataType OPTIONAL
,
2611 OUT PBYTE PropertyBuffer OPTIONAL
,
2612 IN DWORD PropertyBufferSize
,
2613 OUT PDWORD RequiredSize OPTIONAL
)
2616 BOOL bIsStringProperty
;
2618 DWORD RequiredSizeA
, RequiredSizeW
;
2619 DWORD PropertyBufferSizeW
= 0;
2620 PBYTE PropertyBufferW
= NULL
;
2622 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2623 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2626 if (PropertyBufferSize
!= 0)
2628 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2629 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2630 if (!PropertyBufferW
)
2632 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2637 bResult
= SetupDiGetDeviceRegistryPropertyW(
2643 PropertyBufferSizeW
,
2646 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2648 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2650 if (bIsStringProperty
)
2651 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2653 RequiredSizeA
= RequiredSizeW
;
2655 *RequiredSize
= RequiredSizeA
;
2656 if (PropertyRegDataType
)
2657 *PropertyRegDataType
= RegType
;
2662 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2666 if (RequiredSizeA
<= PropertyBufferSize
)
2668 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2670 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2672 /* Last error is already set by WideCharToMultiByte */
2677 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2681 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2685 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2689 /***********************************************************************
2690 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2693 SetupDiGetDeviceRegistryPropertyW(
2694 IN HDEVINFO DeviceInfoSet
,
2695 IN PSP_DEVINFO_DATA DeviceInfoData
,
2697 OUT PDWORD PropertyRegDataType OPTIONAL
,
2698 OUT PBYTE PropertyBuffer OPTIONAL
,
2699 IN DWORD PropertyBufferSize
,
2700 OUT PDWORD RequiredSize OPTIONAL
)
2702 HKEY hEnumKey
, hKey
;
2706 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2707 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2710 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2711 SetLastError(ERROR_INVALID_HANDLE
);
2712 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2713 SetLastError(ERROR_INVALID_HANDLE
);
2714 else if (!DeviceInfoData
)
2715 SetLastError(ERROR_INVALID_PARAMETER
);
2716 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2717 SetLastError(ERROR_INVALID_USER_BUFFER
);
2718 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2719 SetLastError(ERROR_INVALID_PARAMETER
);
2722 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2723 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2727 case SPDRP_CAPABILITIES
:
2729 case SPDRP_CLASSGUID
:
2730 case SPDRP_COMPATIBLEIDS
:
2731 case SPDRP_CONFIGFLAGS
:
2732 case SPDRP_DEVICEDESC
:
2734 case SPDRP_FRIENDLYNAME
:
2735 case SPDRP_HARDWAREID
:
2736 case SPDRP_LOCATION_INFORMATION
:
2737 case SPDRP_LOWERFILTERS
:
2739 case SPDRP_SECURITY
:
2741 case SPDRP_UI_NUMBER
:
2742 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2743 case SPDRP_UPPERFILTERS
:
2745 LPCWSTR RegistryPropertyName
;
2750 case SPDRP_CAPABILITIES
:
2751 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2753 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2754 case SPDRP_CLASSGUID
:
2755 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2756 case SPDRP_COMPATIBLEIDS
:
2757 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2758 case SPDRP_CONFIGFLAGS
:
2759 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2760 case SPDRP_DEVICEDESC
:
2761 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2763 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2764 case SPDRP_FRIENDLYNAME
:
2765 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2766 case SPDRP_HARDWAREID
:
2767 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2768 case SPDRP_LOCATION_INFORMATION
:
2769 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2770 case SPDRP_LOWERFILTERS
:
2771 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2773 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2774 case SPDRP_SECURITY
:
2775 RegistryPropertyName
= REGSTR_SECURITY
; break;
2777 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2778 case SPDRP_UI_NUMBER
:
2779 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2780 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2781 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
; break;
2782 case SPDRP_UPPERFILTERS
:
2783 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2785 /* Should not happen */
2786 RegistryPropertyName
= NULL
; break;
2789 /* Open registry key name */
2792 REGSTR_PATH_SYSTEMENUM
,
2796 if (rc
!= ERROR_SUCCESS
)
2807 RegCloseKey(hEnumKey
);
2808 if (rc
!= ERROR_SUCCESS
)
2813 /* Read registry entry */
2814 BufferSize
= PropertyBufferSize
;
2815 rc
= RegQueryValueExW(
2817 RegistryPropertyName
,
2818 NULL
, /* Reserved */
2819 PropertyRegDataType
,
2823 *RequiredSize
= BufferSize
;
2826 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2829 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2831 case ERROR_MORE_DATA
:
2832 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2841 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2843 DWORD required
= (strlenW(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2845 if (PropertyRegDataType
)
2846 *PropertyRegDataType
= REG_SZ
;
2848 *RequiredSize
= required
;
2849 if (PropertyBufferSize
>= required
)
2851 strcpyW((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2855 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2859 /*case SPDRP_BUSTYPEGUID:
2860 case SPDRP_LEGACYBUSTYPE:
2861 case SPDRP_BUSNUMBER:
2862 case SPDRP_ENUMERATOR_NAME:
2863 case SPDRP_SECURITY_SDS:
2865 case SPDRP_EXCLUSIVE:
2866 case SPDRP_CHARACTERISTICS:
2868 case SPDRP_DEVICE_POWER_DATA:*/
2869 #if (WINVER >= 0x501)
2870 /*case SPDRP_REMOVAL_POLICY:
2871 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2872 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2873 case SPDRP_INSTALL_STATE:*/
2878 ERR("Property 0x%lx not implemented\n", Property
);
2879 SetLastError(ERROR_NOT_SUPPORTED
);
2884 TRACE("Returning %d\n", ret
);
2888 /***********************************************************************
2889 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2892 SetupDiSetDeviceRegistryPropertyA(
2893 IN HDEVINFO DeviceInfoSet
,
2894 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2896 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
2897 IN DWORD PropertyBufferSize
)
2899 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2900 Property
, PropertyBuffer
, PropertyBufferSize
);
2901 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2905 /***********************************************************************
2906 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2909 SetupDiSetDeviceRegistryPropertyW(
2910 IN HDEVINFO DeviceInfoSet
,
2911 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2913 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
2914 IN DWORD PropertyBufferSize
)
2916 struct DeviceInfoSet
*list
;
2919 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2920 Property
, PropertyBuffer
, PropertyBufferSize
);
2923 SetLastError(ERROR_INVALID_HANDLE
);
2924 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2925 SetLastError(ERROR_INVALID_HANDLE
);
2926 else if (!DeviceInfoData
)
2927 SetLastError(ERROR_INVALID_HANDLE
);
2928 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2929 SetLastError(ERROR_INVALID_USER_BUFFER
);
2934 case SPDRP_COMPATIBLEIDS
:
2935 case SPDRP_CONFIGFLAGS
:
2936 case SPDRP_FRIENDLYNAME
:
2937 case SPDRP_HARDWAREID
:
2938 case SPDRP_LOCATION_INFORMATION
:
2939 case SPDRP_LOWERFILTERS
:
2940 case SPDRP_SECURITY
:
2942 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2943 case SPDRP_UPPERFILTERS
:
2945 LPCWSTR RegistryPropertyName
;
2946 DWORD RegistryDataType
;
2952 case SPDRP_COMPATIBLEIDS
:
2953 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2954 RegistryDataType
= REG_MULTI_SZ
;
2956 case SPDRP_CONFIGFLAGS
:
2957 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2958 RegistryDataType
= REG_DWORD
;
2960 case SPDRP_FRIENDLYNAME
:
2961 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2962 RegistryDataType
= REG_SZ
;
2964 case SPDRP_HARDWAREID
:
2965 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2966 RegistryDataType
= REG_MULTI_SZ
;
2968 case SPDRP_LOCATION_INFORMATION
:
2969 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2970 RegistryDataType
= REG_SZ
;
2972 case SPDRP_LOWERFILTERS
:
2973 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2974 RegistryDataType
= REG_MULTI_SZ
;
2976 case SPDRP_SECURITY
:
2977 RegistryPropertyName
= REGSTR_SECURITY
;
2978 RegistryDataType
= REG_BINARY
;
2981 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2982 RegistryDataType
= REG_SZ
;
2984 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2985 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
;
2986 RegistryDataType
= REG_SZ
;
2988 case SPDRP_UPPERFILTERS
:
2989 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2990 RegistryDataType
= REG_MULTI_SZ
;
2993 /* Should not happen */
2994 RegistryPropertyName
= NULL
;
2995 RegistryDataType
= REG_BINARY
;
2998 /* Open device registry key */
2999 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3000 if (hKey
!= INVALID_HANDLE_VALUE
)
3002 /* Write new data */
3003 rc
= RegSetValueExW(
3005 RegistryPropertyName
,
3009 PropertyBufferSize
);
3010 if (rc
== ERROR_SUCCESS
)
3019 /*case SPDRP_CHARACTERISTICS:
3021 case SPDRP_EXCLUSIVE:*/
3022 #if (WINVER >= 0x501)
3023 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
3025 //case SPDRP_SECURITY_SDS:
3029 ERR("Property 0x%lx not implemented\n", Property
);
3030 SetLastError(ERROR_NOT_SUPPORTED
);
3035 TRACE("Returning %d\n", ret
);
3040 /***********************************************************************
3041 * SetupDiInstallClassA (SETUPAPI.@)
3044 SetupDiInstallClassA(
3045 IN HWND hwndParent OPTIONAL
,
3046 IN PCSTR InfFileName
,
3048 IN HSPFILEQ FileQueue OPTIONAL
)
3050 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3054 /***********************************************************************
3055 * SetupDiInstallClassW (SETUPAPI.@)
3058 SetupDiInstallClassW(
3059 IN HWND hwndParent OPTIONAL
,
3060 IN PCWSTR InfFileName
,
3062 IN HSPFILEQ FileQueue OPTIONAL
)
3064 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3068 /***********************************************************************
3069 * SetupDiInstallClassExA (SETUPAPI.@)
3072 SetupDiInstallClassExA(
3073 IN HWND hwndParent OPTIONAL
,
3074 IN PCSTR InfFileName OPTIONAL
,
3076 IN HSPFILEQ FileQueue OPTIONAL
,
3077 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3081 PWSTR InfFileNameW
= NULL
;
3086 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3087 if (InfFileNameW
== NULL
)
3089 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3094 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3095 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3097 MyFree(InfFileNameW
);
3104 CreateClassKey(HINF hInf
)
3106 WCHAR FullBuffer
[MAX_PATH
];
3107 WCHAR Buffer
[MAX_PATH
];
3109 HKEY hClassKey
= NULL
;
3110 HKEY ret
= INVALID_HANDLE_VALUE
;
3112 FullBuffer
[0] = '\0';
3114 if (!SetupGetLineTextW(NULL
,
3125 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3126 lstrcatW(FullBuffer
, Buffer
);
3128 if (!SetupGetLineTextW(NULL
,
3136 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3140 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3144 REG_OPTION_NON_VOLATILE
,
3153 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3158 RequiredSize
* sizeof(WCHAR
)))
3166 if (hClassKey
!= NULL
&& hClassKey
!= ret
)
3167 RegCloseKey(hClassKey
);
3168 if (ret
== INVALID_HANDLE_VALUE
&& FullBuffer
[0] != '\0')
3169 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3174 /***********************************************************************
3175 * SetupDiInstallClassExW (SETUPAPI.@)
3178 SetupDiInstallClassExW(
3179 IN HWND hwndParent OPTIONAL
,
3180 IN PCWSTR InfFileName OPTIONAL
,
3182 IN HSPFILEQ FileQueue OPTIONAL
,
3183 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3189 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3190 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3194 FIXME("Case not implemented: InfFileName NULL\n");
3195 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3197 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3199 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3200 SetLastError(ERROR_INVALID_FLAGS
);
3202 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3203 SetLastError(ERROR_INVALID_PARAMETER
);
3204 else if (Reserved1
!= NULL
)
3205 SetLastError(ERROR_INVALID_PARAMETER
);
3206 else if (Reserved2
!= NULL
)
3207 SetLastError(ERROR_INVALID_PARAMETER
);
3210 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
3211 SP_DEVINSTALL_PARAMS_W InstallParams
;
3212 WCHAR SectionName
[MAX_PATH
];
3213 HINF hInf
= INVALID_HANDLE_VALUE
;
3214 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3215 PVOID callback_context
= NULL
;
3217 hDeviceInfo
= SetupDiCreateDeviceInfoList(NULL
, NULL
);
3219 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3220 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3222 InstallParams
.Flags
&= ~(DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3223 InstallParams
.Flags
|= Flags
& (DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3224 if (Flags
& DI_NOVCP
)
3225 InstallParams
.FileQueue
= FileQueue
;
3226 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3229 /* Open the .inf file */
3230 hInf
= SetupOpenInfFileW(
3235 if (hInf
== INVALID_HANDLE_VALUE
)
3238 /* Try to append a layout file */
3239 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3243 if (InterfaceClassGuid
)
3245 /* Retrieve the actual section name */
3246 ret
= SetupDiGetActualSectionToInstallW(
3256 /* Open registry key related to this interface */
3257 /* FIXME: What happens if the key doesn't exist? */
3258 hRootKey
= SetupDiOpenClassRegKeyExW(InterfaceClassGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, NULL
, NULL
);
3259 if (hRootKey
== INVALID_HANDLE_VALUE
)
3262 /* SetupDiCreateDeviceInterface??? */
3263 FIXME("Installing an interface is not implemented\n");
3264 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3268 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3269 hRootKey
= CreateClassKey(hInf
);
3270 if (hRootKey
== INVALID_HANDLE_VALUE
)
3273 /* Retrieve the actual section name */
3274 ret
= SetupDiGetActualSectionToInstallW(
3278 MAX_PATH
- strlenW(DotServices
),
3284 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3285 if (!callback_context
)
3288 ret
= SetupInstallFromInfSectionW(
3292 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3294 NULL
, /* SourceRootPath */
3295 !(Flags
& DI_NOVCP
) && (Flags
& DI_FORCECOPY
) ? SP_COPY_FORCE_IN_USE
: 0, /* CopyFlags */
3296 SetupDefaultQueueCallbackW
,
3303 /* Install .Services section */
3304 lstrcatW(SectionName
, DotServices
);
3305 ret
= SetupInstallServicesFromInfSectionExW(
3320 if (hDeviceInfo
!= INVALID_HANDLE_VALUE
)
3321 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
3322 if (hInf
!= INVALID_HANDLE_VALUE
)
3323 SetupCloseInfFile(hInf
);
3324 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3325 RegCloseKey(hRootKey
);
3326 SetupTermDefaultQueueCallback(callback_context
);
3329 TRACE("Returning %d\n", ret
);
3334 /***********************************************************************
3335 * SetupDiOpenClassRegKey (SETUPAPI.@)
3338 SetupDiOpenClassRegKey(
3339 IN CONST GUID
*ClassGuid OPTIONAL
,
3340 IN REGSAM samDesired
)
3342 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3343 DIOCR_INSTALLER
, NULL
, NULL
);
3347 /***********************************************************************
3348 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3351 SetupDiOpenClassRegKeyExA(
3352 IN CONST GUID
*ClassGuid OPTIONAL
,
3353 IN REGSAM samDesired
,
3355 IN PCSTR MachineName OPTIONAL
,
3358 PWSTR MachineNameW
= NULL
;
3365 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3366 if (MachineNameW
== NULL
)
3367 return INVALID_HANDLE_VALUE
;
3370 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3371 Flags
, MachineNameW
, Reserved
);
3374 MyFree(MachineNameW
);
3380 /***********************************************************************
3381 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3384 SetupDiOpenClassRegKeyExW(
3385 IN CONST GUID
* ClassGuid OPTIONAL
,
3386 IN REGSAM samDesired
,
3388 IN PCWSTR MachineName OPTIONAL
,
3391 LPWSTR lpGuidString
= NULL
;
3392 LPWSTR lpFullGuidString
= NULL
;
3395 HKEY hClassesKey
= NULL
;
3396 HKEY hClassKey
= NULL
;
3397 HKEY ret
= INVALID_HANDLE_VALUE
;
3401 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3402 Flags
, debugstr_w(MachineName
), Reserved
);
3404 if (Flags
== DIOCR_INSTALLER
)
3405 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3406 else if (Flags
== DIOCR_INTERFACE
)
3407 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3410 ERR("Invalid Flags parameter!\n");
3411 SetLastError(ERROR_INVALID_FLAGS
);
3415 if (MachineName
!= NULL
)
3417 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3418 if (rc
!= ERROR_SUCCESS
)
3425 HKLM
= HKEY_LOCAL_MACHINE
;
3427 rc
= RegOpenKeyExW(HKLM
,
3430 ClassGuid
? 0 : samDesired
,
3432 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3433 if (rc
!= ERROR_SUCCESS
)
3439 if (ClassGuid
== NULL
)
3441 /* Stop here. We don't need to open a subkey */
3446 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3448 SetLastError(ERROR_GEN_FAILURE
);
3452 dwLength
= lstrlenW(lpGuidString
);
3453 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3454 if (!lpFullGuidString
)
3456 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3459 lpFullGuidString
[0] = '{';
3460 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3461 lpFullGuidString
[dwLength
+ 1] = '}';
3462 lpFullGuidString
[dwLength
+ 2] = '\0';
3464 rc
= RegOpenKeyExW(hClassesKey
,
3469 if (rc
!= ERROR_SUCCESS
)
3477 if (hClassKey
!= NULL
&& hClassKey
!= ret
)
3478 RegCloseKey(hClassKey
);
3479 if (hClassesKey
!= NULL
&& hClassesKey
!= ret
)
3480 RegCloseKey(hClassesKey
);
3482 RpcStringFreeW(&lpGuidString
);
3483 if (lpFullGuidString
)
3484 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3489 /***********************************************************************
3490 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3493 SetupDiOpenDeviceInterfaceW(
3494 IN HDEVINFO DeviceInfoSet
,
3495 IN PCWSTR DevicePath
,
3497 OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL
)
3499 FIXME("%p %s %08lx %p\n",
3500 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3504 /***********************************************************************
3505 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3508 SetupDiOpenDeviceInterfaceA(
3509 IN HDEVINFO DeviceInfoSet
,
3510 IN PCSTR DevicePath
,
3512 OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL
)
3514 LPWSTR DevicePathW
= NULL
;
3517 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3519 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3520 if (DevicePathW
== NULL
)
3523 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3524 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3526 MyFree(DevicePathW
);
3531 /***********************************************************************
3532 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3535 SetupDiSetClassInstallParamsA(
3536 IN HDEVINFO DeviceInfoSet
,
3537 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3538 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3539 IN DWORD ClassInstallParamsSize
)
3541 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3542 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3546 /***********************************************************************
3547 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3550 SetupDiSetClassInstallParamsW(
3551 IN HDEVINFO DeviceInfoSet
,
3552 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3553 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3554 IN DWORD ClassInstallParamsSize
)
3556 struct DeviceInfoSet
*list
;
3559 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3560 ClassInstallParams
, ClassInstallParamsSize
);
3563 SetLastError(ERROR_INVALID_PARAMETER
);
3564 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3565 SetLastError(ERROR_INVALID_HANDLE
);
3566 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3567 SetLastError(ERROR_INVALID_HANDLE
);
3568 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3569 SetLastError(ERROR_INVALID_USER_BUFFER
);
3570 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3571 SetLastError(ERROR_INVALID_USER_BUFFER
);
3572 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3573 SetLastError(ERROR_INVALID_PARAMETER
);
3574 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3575 SetLastError(ERROR_INVALID_PARAMETER
);
3578 SP_DEVINSTALL_PARAMS_W InstallParams
;
3581 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3582 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3586 if (ClassInstallParams
)
3588 /* Check parameters in ClassInstallParams */
3589 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3590 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3592 SetLastError(ERROR_INVALID_USER_BUFFER
);
3595 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3597 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3598 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3601 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3604 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3608 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3611 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3615 TRACE("Returning %d\n", ret
);
3620 PropertyChangeHandler(
3621 IN HDEVINFO DeviceInfoSet
,
3622 IN PSP_DEVINFO_DATA DeviceInfoData
,
3623 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3624 IN DWORD ClassInstallParamsSize
)
3626 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3629 if (!DeviceInfoData
)
3630 SetLastError(ERROR_INVALID_PARAMETER
);
3631 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3632 SetLastError(ERROR_INVALID_PARAMETER
);
3633 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3634 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3635 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3636 SetLastError(ERROR_INVALID_FLAGS
);
3637 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3638 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3639 SetLastError(ERROR_INVALID_FLAGS
);
3640 else if (PropChangeParams
3641 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3642 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3643 SetLastError(ERROR_INVALID_USER_BUFFER
);
3646 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3647 if (!DeviceInfoData
)
3649 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3650 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3654 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3655 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3657 if (*CurrentPropChangeParams
)
3659 MyFree(*CurrentPropChangeParams
);
3660 *CurrentPropChangeParams
= NULL
;
3662 if (PropChangeParams
)
3664 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3665 if (!*CurrentPropChangeParams
)
3667 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3670 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3681 IN PWSTR InstallerName
,
3682 OUT HMODULE
* ModulePointer
,
3683 OUT PVOID
* FunctionPointer
)
3685 HMODULE hModule
= NULL
;
3686 LPSTR FunctionNameA
= NULL
;
3690 *ModulePointer
= NULL
;
3691 *FunctionPointer
= NULL
;
3693 Comma
= strchrW(InstallerName
, ',');
3696 rc
= ERROR_INVALID_PARAMETER
;
3702 hModule
= LoadLibraryW(InstallerName
);
3706 rc
= GetLastError();
3710 /* Skip comma spaces */
3711 while (*Comma
== ',' || isspaceW(*Comma
))
3714 /* W->A conversion for function name */
3715 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3718 rc
= GetLastError();
3722 /* Search function */
3723 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3724 if (!*FunctionPointer
)
3726 rc
= GetLastError();
3730 *ModulePointer
= hModule
;
3734 if (rc
!= ERROR_SUCCESS
&& hModule
)
3735 FreeLibrary(hModule
);
3736 MyFree(FunctionNameA
);
3741 FreeFunctionPointer(
3742 IN HMODULE ModulePointer
,
3743 IN PVOID FunctionPointer
)
3745 if (ModulePointer
== NULL
)
3746 return ERROR_SUCCESS
;
3747 if (FreeLibrary(ModulePointer
))
3748 return ERROR_SUCCESS
;
3750 return GetLastError();
3754 IntSetupDiRegisterDeviceInfo(
3755 IN HDEVINFO DeviceInfoSet
,
3756 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3758 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
3761 /***********************************************************************
3762 * SetupDiCallClassInstaller (SETUPAPI.@)
3765 SetupDiCallClassInstaller(
3766 IN DI_FUNCTION InstallFunction
,
3767 IN HDEVINFO DeviceInfoSet
,
3768 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3772 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3775 SetLastError(ERROR_INVALID_PARAMETER
);
3776 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3777 SetLastError(ERROR_INVALID_HANDLE
);
3778 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3779 SetLastError(ERROR_INVALID_HANDLE
);
3780 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3781 SetLastError(ERROR_INVALID_HANDLE
);
3782 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3783 SetLastError(ERROR_INVALID_USER_BUFFER
);
3786 SP_DEVINSTALL_PARAMS_W InstallParams
;
3787 #define CLASS_COINSTALLER 0x1
3788 #define DEVICE_COINSTALLER 0x2
3789 #define CLASS_INSTALLER 0x4
3790 UCHAR CanHandle
= 0;
3791 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3793 switch (InstallFunction
)
3795 case DIF_ADDPROPERTYPAGE_ADVANCED
:
3796 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3798 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
3799 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3801 case DIF_ALLOW_INSTALL
:
3802 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3805 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3807 case DIF_DESTROYPRIVATEDATA
:
3808 CanHandle
= CLASS_INSTALLER
;
3810 case DIF_INSTALLDEVICE
:
3811 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3812 DefaultHandler
= SetupDiInstallDevice
;
3814 case DIF_INSTALLDEVICEFILES
:
3815 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3816 DefaultHandler
= SetupDiInstallDriverFiles
;
3818 case DIF_INSTALLINTERFACES
:
3819 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3820 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3822 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3823 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3825 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3826 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3828 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3829 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3831 case DIF_NEWDEVICEWIZARD_PRESELECT
:
3832 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3834 case DIF_NEWDEVICEWIZARD_SELECT
:
3835 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3837 case DIF_POWERMESSAGEWAKE
:
3838 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3840 case DIF_PROPERTYCHANGE
:
3841 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3842 DefaultHandler
= SetupDiChangeState
;
3844 case DIF_REGISTER_COINSTALLERS
:
3845 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3846 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3848 case DIF_REGISTERDEVICE
:
3849 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3850 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
3853 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3854 DefaultHandler
= SetupDiRemoveDevice
;
3856 case DIF_SELECTBESTCOMPATDRV
:
3857 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3858 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3860 case DIF_SELECTDEVICE
:
3861 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3862 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3864 case DIF_TROUBLESHOOTER
:
3865 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3868 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3869 DefaultHandler
= SetupDiUnremoveDevice
;
3872 ERR("Install function %u not supported\n", InstallFunction
);
3873 SetLastError(ERROR_NOT_SUPPORTED
);
3876 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3877 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3878 /* Don't process this call, as a parameter is invalid */
3883 LIST_ENTRY ClassCoInstallersListHead
;
3884 LIST_ENTRY DeviceCoInstallersListHead
;
3885 HMODULE ClassInstallerLibrary
= NULL
;
3886 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3887 COINSTALLER_CONTEXT_DATA Context
;
3888 PLIST_ENTRY ListEntry
;
3890 DWORD dwRegType
, dwLength
;
3891 DWORD rc
= NO_ERROR
;
3893 InitializeListHead(&ClassCoInstallersListHead
);
3894 InitializeListHead(&DeviceCoInstallersListHead
);
3896 if (CanHandle
& DEVICE_COINSTALLER
)
3898 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3899 if (hKey
!= INVALID_HANDLE_VALUE
)
3901 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3902 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3904 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3905 if (KeyBuffer
!= NULL
)
3907 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3908 if (rc
== ERROR_SUCCESS
)
3911 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3913 /* Add coinstaller to DeviceCoInstallersListHead list */
3914 struct CoInstallerElement
*coinstaller
;
3915 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3916 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3919 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3920 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3921 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3923 HeapFree(GetProcessHeap(), 0, coinstaller
);
3926 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3932 if (CanHandle
& CLASS_COINSTALLER
)
3936 REGSTR_PATH_CODEVICEINSTALLERS
,
3940 if (rc
== ERROR_SUCCESS
)
3942 LPWSTR lpGuidString
;
3943 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3945 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3946 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3948 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3949 if (KeyBuffer
!= NULL
)
3951 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3952 if (rc
== ERROR_SUCCESS
)
3955 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3957 /* Add coinstaller to ClassCoInstallersListHead list */
3958 struct CoInstallerElement
*coinstaller
;
3959 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3960 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3963 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3964 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3965 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3967 HeapFree(GetProcessHeap(), 0, coinstaller
);
3970 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3973 RpcStringFreeW(&lpGuidString
);
3978 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3980 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3981 if (hKey
!= INVALID_HANDLE_VALUE
)
3983 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3984 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3986 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3987 if (KeyBuffer
!= NULL
)
3989 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3990 if (rc
== ERROR_SUCCESS
)
3992 /* Get ClassInstaller function pointer */
3993 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3994 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3996 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3997 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4000 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4007 /* Call Class co-installers */
4008 Context
.PostProcessing
= FALSE
;
4010 ListEntry
= ClassCoInstallersListHead
.Flink
;
4011 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4013 struct CoInstallerElement
*coinstaller
;
4014 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4015 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4016 coinstaller
->PrivateData
= Context
.PrivateData
;
4017 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4019 coinstaller
->DoPostProcessing
= TRUE
;
4022 ListEntry
= ListEntry
->Flink
;
4025 /* Call Device co-installers */
4026 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4027 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4029 struct CoInstallerElement
*coinstaller
;
4030 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4031 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4032 coinstaller
->PrivateData
= Context
.PrivateData
;
4033 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4035 coinstaller
->DoPostProcessing
= TRUE
;
4038 ListEntry
= ListEntry
->Flink
;
4041 /* Call Class installer */
4044 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4045 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4048 rc
= ERROR_DI_DO_DEFAULT
;
4050 /* Call default handler */
4051 if (rc
== ERROR_DI_DO_DEFAULT
)
4053 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4055 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4058 rc
= GetLastError();
4064 /* Call Class co-installers that required postprocessing */
4065 Context
.PostProcessing
= TRUE
;
4066 ListEntry
= ClassCoInstallersListHead
.Flink
;
4067 while (ListEntry
!= &ClassCoInstallersListHead
)
4069 struct CoInstallerElement
*coinstaller
;
4070 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4071 if (coinstaller
->DoPostProcessing
)
4073 Context
.InstallResult
= rc
;
4074 Context
.PrivateData
= coinstaller
->PrivateData
;
4075 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4077 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4078 ListEntry
= ListEntry
->Flink
;
4081 /* Call Device co-installers that required postprocessing */
4082 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4083 while (ListEntry
!= &DeviceCoInstallersListHead
)
4085 struct CoInstallerElement
*coinstaller
;
4086 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4087 if (coinstaller
->DoPostProcessing
)
4089 Context
.InstallResult
= rc
;
4090 Context
.PrivateData
= coinstaller
->PrivateData
;
4091 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4093 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4094 ListEntry
= ListEntry
->Flink
;
4097 /* Free allocated memory */
4098 while (!IsListEmpty(&ClassCoInstallersListHead
))
4100 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4101 HeapFree(GetProcessHeap(), 0, ListEntry
);
4103 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4105 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4106 HeapFree(GetProcessHeap(), 0, ListEntry
);
4109 ret
= (rc
== NO_ERROR
);
4113 TRACE("Returning %d\n", ret
);
4117 /***********************************************************************
4118 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4121 SetupDiGetDeviceInfoListClass(
4122 IN HDEVINFO DeviceInfoSet
,
4123 OUT LPGUID ClassGuid
)
4125 struct DeviceInfoSet
*list
;
4128 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4131 SetLastError(ERROR_INVALID_HANDLE
);
4132 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4133 SetLastError(ERROR_INVALID_HANDLE
);
4134 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4135 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4138 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4143 TRACE("Returning %d\n", ret
);
4147 /***********************************************************************
4148 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4151 SetupDiGetDeviceInfoListDetailW(
4152 IN HDEVINFO DeviceInfoSet
,
4153 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4155 struct DeviceInfoSet
*list
;
4158 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4161 SetLastError(ERROR_INVALID_HANDLE
);
4162 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4163 SetLastError(ERROR_INVALID_HANDLE
);
4164 else if (!DeviceInfoListDetailData
)
4165 SetLastError(ERROR_INVALID_PARAMETER
);
4166 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4167 SetLastError(ERROR_INVALID_USER_BUFFER
);
4171 &DeviceInfoListDetailData
->ClassGuid
,
4174 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4175 if (list
->MachineName
)
4176 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4178 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4183 TRACE("Returning %d\n", ret
);
4187 /***********************************************************************
4188 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4191 SetupDiGetDeviceInstallParamsA(
4192 IN HDEVINFO DeviceInfoSet
,
4193 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4194 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4196 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4199 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4201 if (DeviceInstallParams
== NULL
)
4202 SetLastError(ERROR_INVALID_PARAMETER
);
4203 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4204 SetLastError(ERROR_INVALID_USER_BUFFER
);
4207 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4208 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4212 /* Do W->A conversion */
4214 DeviceInstallParams
,
4215 &deviceInstallParamsW
,
4216 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4217 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4218 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4220 DeviceInstallParams
->DriverPath
[0] = '\0';
4226 TRACE("Returning %d\n", ret
);
4230 /***********************************************************************
4231 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4234 SetupDiGetDeviceInstallParamsW(
4235 IN HDEVINFO DeviceInfoSet
,
4236 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4237 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4239 struct DeviceInfoSet
*list
;
4242 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4245 SetLastError(ERROR_INVALID_HANDLE
);
4246 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4247 SetLastError(ERROR_INVALID_HANDLE
);
4248 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4249 SetLastError(ERROR_INVALID_USER_BUFFER
);
4250 else if (!DeviceInstallParams
)
4251 SetLastError(ERROR_INVALID_PARAMETER
);
4252 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4253 SetLastError(ERROR_INVALID_USER_BUFFER
);
4256 PSP_DEVINSTALL_PARAMS_W Source
;
4259 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4261 Source
= &list
->InstallParams
;
4262 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4266 TRACE("Returning %d\n", ret
);
4271 CheckDeviceInstallParameters(
4272 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4274 DWORD SupportedFlags
=
4275 DI_NOVCP
| /* 0x00000008 */
4276 DI_DIDCOMPAT
| /* 0x00000010 */
4277 DI_DIDCLASS
| /* 0x00000020 */
4278 DI_NEEDRESTART
| /* 0x00000080 */
4279 DI_NEEDREBOOT
| /* 0x00000100 */
4280 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4281 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4282 DI_ENUMSINGLEINF
| /* 0x00010000 */
4283 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4284 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4285 DI_QUIETINSTALL
| /* 0x00800000 */
4286 DI_NOFILECOPY
| /* 0x01000000 */
4287 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4288 DWORD SupportedFlagsEx
=
4289 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4290 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4291 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4292 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4293 DI_FLAGSEX_NO_DRVREG_MODIFY
; /* 0x00008000 */
4296 /* FIXME: add support for more flags */
4298 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4299 * It should be checked before accessing to other values
4300 * of the SP_DEVINSTALL_PARAMS structure */
4302 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4304 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4305 SetLastError(ERROR_INVALID_FLAGS
);
4307 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4309 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4310 SetLastError(ERROR_INVALID_FLAGS
);
4312 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4313 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4314 SetLastError(ERROR_INVALID_USER_BUFFER
);
4317 /* FIXME: check Reserved field */
4324 /***********************************************************************
4325 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4328 SetupDiSetDeviceInstallParamsW(
4329 IN HDEVINFO DeviceInfoSet
,
4330 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4331 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4333 struct DeviceInfoSet
*list
;
4336 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4339 SetLastError(ERROR_INVALID_HANDLE
);
4340 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4341 SetLastError(ERROR_INVALID_HANDLE
);
4342 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4343 SetLastError(ERROR_INVALID_USER_BUFFER
);
4344 else if (!DeviceInstallParams
)
4345 SetLastError(ERROR_INVALID_PARAMETER
);
4346 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4347 SetLastError(ERROR_INVALID_USER_BUFFER
);
4348 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4350 PSP_DEVINSTALL_PARAMS_W Destination
;
4353 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4355 Destination
= &list
->InstallParams
;
4356 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4360 TRACE("Returning %d\n", ret
);
4364 /***********************************************************************
4365 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4368 SetupDiGetDeviceInstanceIdA(
4369 IN HDEVINFO DeviceInfoSet
,
4370 IN PSP_DEVINFO_DATA DeviceInfoData
,
4371 OUT PSTR DeviceInstanceId OPTIONAL
,
4372 IN DWORD DeviceInstanceIdSize
,
4373 OUT PDWORD RequiredSize OPTIONAL
)
4375 PWSTR DeviceInstanceIdW
= NULL
;
4378 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4379 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4381 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4382 SetLastError(ERROR_INVALID_PARAMETER
);
4385 if (DeviceInstanceIdSize
!= 0)
4387 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4388 if (DeviceInstanceIdW
== NULL
)
4392 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4393 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4396 if (ret
&& DeviceInstanceIdW
!= NULL
)
4398 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4399 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4401 DeviceInstanceId
[0] = '\0';
4407 TRACE("Returning %d\n", ret
);
4411 /***********************************************************************
4412 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4415 SetupDiGetDeviceInstanceIdW(
4416 IN HDEVINFO DeviceInfoSet
,
4417 IN PSP_DEVINFO_DATA DeviceInfoData
,
4418 OUT PWSTR DeviceInstanceId OPTIONAL
,
4419 IN DWORD DeviceInstanceIdSize
,
4420 OUT PDWORD RequiredSize OPTIONAL
)
4424 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4425 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4428 SetLastError(ERROR_INVALID_HANDLE
);
4429 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4430 SetLastError(ERROR_INVALID_HANDLE
);
4431 else if (!DeviceInfoData
)
4432 SetLastError(ERROR_INVALID_PARAMETER
);
4433 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4434 SetLastError(ERROR_INVALID_USER_BUFFER
);
4435 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4436 SetLastError(ERROR_INVALID_PARAMETER
);
4437 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4438 SetLastError(ERROR_INVALID_PARAMETER
);
4441 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4444 required
= (strlenW(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4446 *RequiredSize
= required
;
4448 if (required
<= DeviceInstanceIdSize
)
4450 strcpyW(DeviceInstanceId
, DevInfo
->DeviceName
);
4454 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4457 TRACE("Returning %d\n", ret
);
4461 /***********************************************************************
4462 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4465 SetupDiGetClassDevPropertySheetsA(
4466 IN HDEVINFO DeviceInfoSet
,
4467 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4468 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4469 IN DWORD PropertySheetHeaderPageListSize
,
4470 OUT PDWORD RequiredSize OPTIONAL
,
4471 IN DWORD PropertySheetType
)
4473 PROPSHEETHEADERW psh
;
4476 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4477 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4478 RequiredSize
, PropertySheetType
);
4480 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4481 psh
.phpage
= PropertySheetHeader
->phpage
;
4482 psh
.nPages
= PropertySheetHeader
->nPages
;
4484 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4485 PropertySheetHeaderPageListSize
, RequiredSize
,
4489 PropertySheetHeader
->nPages
= psh
.nPages
;
4492 TRACE("Returning %d\n", ret
);
4496 struct ClassDevPropertySheetsData
4498 HPROPSHEETPAGE
*PropertySheetPages
;
4499 DWORD MaximumNumberOfPages
;
4500 DWORD NumberOfPages
;
4504 GetClassDevPropertySheetsCallback(
4505 IN HPROPSHEETPAGE hPropSheetPage
,
4506 IN OUT LPARAM lParam
)
4508 struct ClassDevPropertySheetsData
*PropPageData
;
4510 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4512 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4514 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4515 PropPageData
->PropertySheetPages
++;
4518 PropPageData
->NumberOfPages
++;
4522 /***********************************************************************
4523 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4526 SetupDiGetClassDevPropertySheetsW(
4527 IN HDEVINFO DeviceInfoSet
,
4528 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4529 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4530 IN DWORD PropertySheetHeaderPageListSize
,
4531 OUT PDWORD RequiredSize OPTIONAL
,
4532 IN DWORD PropertySheetType
)
4534 struct DeviceInfoSet
*list
;
4537 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4538 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4539 RequiredSize
, PropertySheetType
);
4542 SetLastError(ERROR_INVALID_HANDLE
);
4543 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4544 SetLastError(ERROR_INVALID_HANDLE
);
4545 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4546 SetLastError(ERROR_INVALID_HANDLE
);
4547 else if (!PropertySheetHeader
)
4548 SetLastError(ERROR_INVALID_PARAMETER
);
4549 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4550 SetLastError(ERROR_INVALID_FLAGS
);
4551 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4552 SetLastError(ERROR_INVALID_USER_BUFFER
);
4553 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4554 SetLastError(ERROR_INVALID_PARAMETER
);
4555 else if (!PropertySheetHeader
)
4556 SetLastError(ERROR_INVALID_PARAMETER
);
4557 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4558 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4559 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4560 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4561 SetLastError(ERROR_INVALID_PARAMETER
);
4564 HKEY hKey
= INVALID_HANDLE_VALUE
;
4565 SP_PROPSHEETPAGE_REQUEST Request
;
4566 LPWSTR PropPageProvider
= NULL
;
4567 HMODULE hModule
= NULL
;
4568 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4569 struct ClassDevPropertySheetsData PropPageData
;
4570 DWORD dwLength
, dwRegType
;
4574 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4577 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4578 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4580 if (hKey
== INVALID_HANDLE_VALUE
)
4583 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4584 if (rc
== ERROR_FILE_NOT_FOUND
)
4586 /* No registry key. As it is optional, don't say it's a bad error */
4592 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4598 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4599 if (!PropPageProvider
)
4601 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4604 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4605 if (rc
!= ERROR_SUCCESS
)
4610 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4612 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4613 if (rc
!= ERROR_SUCCESS
)
4615 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4619 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4620 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4621 Request
.DeviceInfoSet
= DeviceInfoSet
;
4622 Request
.DeviceInfoData
= DeviceInfoData
;
4623 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4624 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4625 PropPageData
.NumberOfPages
= 0;
4626 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4631 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4632 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4634 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4639 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4640 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4644 if (hKey
!= INVALID_HANDLE_VALUE
)
4646 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4647 FreeFunctionPointer(hModule
, pPropPageProvider
);
4650 TRACE("Returning %d\n", ret
);
4654 /***********************************************************************
4655 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4658 SetupDiCreateDevRegKeyA(
4659 IN HDEVINFO DeviceInfoSet
,
4660 IN PSP_DEVINFO_DATA DeviceInfoData
,
4664 IN HINF InfHandle OPTIONAL
,
4665 IN PCSTR InfSectionName OPTIONAL
)
4667 PCWSTR InfSectionNameW
= NULL
;
4668 HKEY ret
= INVALID_HANDLE_VALUE
;
4672 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4673 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4676 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4684 if (InfSectionNameW
!= NULL
)
4685 MyFree((PVOID
)InfSectionNameW
);
4691 OpenHardwareProfileKey(
4694 IN DWORD samDesired
)
4696 HKEY hHWProfilesKey
= NULL
;
4697 HKEY hHWProfileKey
= NULL
;
4698 HKEY ret
= INVALID_HANDLE_VALUE
;
4701 rc
= RegOpenKeyExW(HKLM
,
4702 REGSTR_PATH_HWPROFILES
,
4706 if (rc
!= ERROR_SUCCESS
)
4723 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4732 if (rc
!= ERROR_SUCCESS
)
4737 ret
= hHWProfileKey
;
4740 if (hHWProfilesKey
!= NULL
)
4741 RegCloseKey(hHWProfilesKey
);
4742 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4743 RegCloseKey(hHWProfileKey
);
4747 /***********************************************************************
4748 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4751 SetupDiCreateDevRegKeyW(
4752 IN HDEVINFO DeviceInfoSet
,
4753 IN PSP_DEVINFO_DATA DeviceInfoData
,
4757 IN HINF InfHandle OPTIONAL
,
4758 IN PCWSTR InfSectionName OPTIONAL
)
4760 struct DeviceInfoSet
*list
;
4761 HKEY ret
= INVALID_HANDLE_VALUE
;
4763 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4764 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4767 SetLastError(ERROR_INVALID_HANDLE
);
4768 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4769 SetLastError(ERROR_INVALID_HANDLE
);
4770 else if (!DeviceInfoData
)
4771 SetLastError(ERROR_INVALID_PARAMETER
);
4772 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4773 SetLastError(ERROR_INVALID_USER_BUFFER
);
4774 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4775 SetLastError(ERROR_INVALID_PARAMETER
);
4776 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4777 SetLastError(ERROR_INVALID_PARAMETER
);
4778 else if (InfHandle
&& !InfSectionName
)
4779 SetLastError(ERROR_INVALID_PARAMETER
);
4780 else if (!InfHandle
&& InfSectionName
)
4781 SetLastError(ERROR_INVALID_PARAMETER
);
4784 LPWSTR lpGuidString
= NULL
;
4785 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4786 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4787 DWORD Index
; /* Index used in the DriverKey name */
4789 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4790 HKEY hEnumKey
= NULL
;
4791 HKEY hClassKey
= NULL
;
4792 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4796 if (Scope
== DICS_FLAG_GLOBAL
)
4797 RootKey
= list
->HKLM
;
4798 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4800 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4801 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4803 RootKey
= hHWProfileKey
;
4806 if (KeyType
== DIREG_DEV
)
4808 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4810 rc
= RegCreateKeyExW(
4812 REGSTR_PATH_SYSTEMENUM
,
4815 REG_OPTION_NON_VOLATILE
,
4820 if (rc
!= ERROR_SUCCESS
)
4825 rc
= RegCreateKeyExW(
4827 deviceInfo
->DeviceName
,
4830 REG_OPTION_NON_VOLATILE
,
4831 #if _WIN32_WINNT >= 0x502
4832 KEY_READ
| KEY_WRITE
,
4839 if (rc
!= ERROR_SUCCESS
)
4845 else /* KeyType == DIREG_DRV */
4847 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4849 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4850 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4853 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4856 strcpyW(DriverKey
, L
"{");
4857 strcatW(DriverKey
, lpGuidString
);
4858 strcatW(DriverKey
, L
"}\\");
4859 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
4860 rc
= RegOpenKeyExW(RootKey
,
4861 REGSTR_PATH_CLASS_NT
,
4865 if (rc
!= ERROR_SUCCESS
)
4871 /* Try all values for Index between 0 and 9999 */
4873 while (Index
<= 9999)
4876 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4877 rc
= RegCreateKeyEx(hClassKey
,
4881 REG_OPTION_NON_VOLATILE
,
4882 #if _WIN32_WINNT >= 0x502
4883 KEY_READ
| KEY_WRITE
,
4890 if (rc
!= ERROR_SUCCESS
)
4895 if (Disposition
== REG_CREATED_NEW_KEY
)
4903 /* Unable to create more than 9999 devices within the same class */
4904 SetLastError(ERROR_GEN_FAILURE
);
4908 /* Open device key, to write Driver value */
4909 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4910 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4912 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
4913 if (rc
!= ERROR_SUCCESS
)
4920 /* Do installation of the specified section */
4923 FIXME("Need to install section %s in file %p\n",
4924 debugstr_w(InfSectionName
), InfHandle
);
4930 RpcStringFreeW(&lpGuidString
);
4931 HeapFree(GetProcessHeap(), 0, DriverKey
);
4932 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4933 RegCloseKey(hHWProfileKey
);
4934 if (hEnumKey
!= NULL
)
4935 RegCloseKey(hEnumKey
);
4936 if (hClassKey
!= NULL
)
4937 RegCloseKey(hClassKey
);
4938 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4939 RegCloseKey(hDeviceKey
);
4940 if (hKey
!= NULL
&& hKey
!= ret
)
4944 TRACE("Returning 0x%p\n", ret
);
4948 /***********************************************************************
4949 * SetupDiOpenDevRegKey (SETUPAPI.@)
4952 SetupDiOpenDevRegKey(
4953 IN HDEVINFO DeviceInfoSet
,
4954 IN PSP_DEVINFO_DATA DeviceInfoData
,
4958 IN REGSAM samDesired
)
4960 struct DeviceInfoSet
*list
;
4961 HKEY ret
= INVALID_HANDLE_VALUE
;
4963 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4964 Scope
, HwProfile
, KeyType
, samDesired
);
4967 SetLastError(ERROR_INVALID_HANDLE
);
4968 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4969 SetLastError(ERROR_INVALID_HANDLE
);
4970 else if (!DeviceInfoData
)
4971 SetLastError(ERROR_INVALID_PARAMETER
);
4972 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4973 SetLastError(ERROR_INVALID_USER_BUFFER
);
4974 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4975 SetLastError(ERROR_INVALID_PARAMETER
);
4976 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4977 SetLastError(ERROR_INVALID_PARAMETER
);
4980 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4981 LPWSTR DriverKey
= NULL
;
4985 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4986 HKEY hEnumKey
= NULL
;
4990 if (Scope
== DICS_FLAG_GLOBAL
)
4991 RootKey
= list
->HKLM
;
4992 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4994 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4995 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4997 RootKey
= hHWProfileKey
;
5002 REGSTR_PATH_SYSTEMENUM
,
5006 if (rc
!= ERROR_SUCCESS
)
5013 deviceInfo
->DeviceName
,
5015 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
5017 RegCloseKey(hEnumKey
);
5019 if (rc
!= ERROR_SUCCESS
)
5024 if (KeyType
== DIREG_DEV
)
5026 /* We're done. Just return the hKey handle */
5030 /* Read the 'Driver' key */
5031 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5032 if (rc
!= ERROR_SUCCESS
)
5037 else if (dwRegType
!= REG_SZ
)
5039 SetLastError(ERROR_GEN_FAILURE
);
5042 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5045 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5048 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5049 if (rc
!= ERROR_SUCCESS
)
5056 /* Need to open the driver key */
5059 REGSTR_PATH_CLASS_NT
,
5063 if (rc
!= ERROR_SUCCESS
)
5074 if (rc
!= ERROR_SUCCESS
)
5082 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5083 RegCloseKey(hHWProfileKey
);
5084 if (hEnumKey
!= NULL
)
5085 RegCloseKey(hEnumKey
);
5086 if (hKey
!= NULL
&& hKey
!= ret
)
5090 TRACE("Returning 0x%p\n", ret
);
5094 /***********************************************************************
5095 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
5098 SetupDiCreateDeviceInfoA(
5099 IN HDEVINFO DeviceInfoSet
,
5100 IN PCSTR DeviceName
,
5101 IN CONST GUID
*ClassGuid
,
5102 IN PCSTR DeviceDescription OPTIONAL
,
5103 IN HWND hwndParent OPTIONAL
,
5104 IN DWORD CreationFlags
,
5105 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5107 LPWSTR DeviceNameW
= NULL
;
5108 LPWSTR DeviceDescriptionW
= NULL
;
5115 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
5116 if (DeviceNameW
== NULL
) return FALSE
;
5118 if (DeviceDescription
)
5120 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
5121 if (DeviceDescriptionW
== NULL
)
5123 if (DeviceNameW
) MyFree(DeviceNameW
);
5128 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
5129 ClassGuid
, DeviceDescriptionW
,
5130 hwndParent
, CreationFlags
,
5133 if (DeviceNameW
) MyFree(DeviceNameW
);
5134 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
5139 /***********************************************************************
5140 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5143 SetupDiCreateDeviceInfoW(
5144 IN HDEVINFO DeviceInfoSet
,
5145 IN PCWSTR DeviceName
,
5146 IN CONST GUID
*ClassGuid
,
5147 IN PCWSTR DeviceDescription OPTIONAL
,
5148 IN HWND hwndParent OPTIONAL
,
5149 IN DWORD CreationFlags
,
5150 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5152 struct DeviceInfoSet
*list
;
5155 TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
5156 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
5157 hwndParent
, CreationFlags
, DeviceInfoData
);
5160 SetLastError(ERROR_INVALID_HANDLE
);
5161 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5162 SetLastError(ERROR_INVALID_HANDLE
);
5163 else if (!ClassGuid
)
5164 SetLastError(ERROR_INVALID_PARAMETER
);
5165 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5166 SetLastError(ERROR_CLASS_MISMATCH
);
5167 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5169 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5170 SetLastError(ERROR_INVALID_FLAGS
);
5174 SP_DEVINFO_DATA DevInfo
;
5176 if (CreationFlags
& DICD_GENERATE_ID
)
5178 /* Generate a new unique ID for this device */
5179 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5180 FIXME("not implemented\n");
5184 /* Device name is fully qualified. Try to open it */
5187 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5188 rc
= SetupDiOpenDeviceInfoW(
5191 NULL
, /* hwndParent */
5192 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5197 /* SetupDiOpenDeviceInfoW has already added
5198 * the device info to the device info set
5200 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5202 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5204 struct DeviceInfoElement
*deviceInfo
;
5206 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5208 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5210 if (!DeviceInfoData
)
5214 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5216 SetLastError(ERROR_INVALID_USER_BUFFER
);
5220 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5221 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5222 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5231 TRACE("Returning %d\n", ret
);
5235 /***********************************************************************
5236 * Helper functions for SetupDiBuildDriverInfoList
5240 IN PLIST_ENTRY DriverListHead
,
5241 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5242 IN LPGUID ClassGuid
,
5243 IN INFCONTEXT ContextDevice
,
5244 IN
struct InfFileDetails
*InfFileDetails
,
5246 IN LPCWSTR ProviderName
,
5247 IN LPCWSTR ManufacturerName
,
5248 IN LPCWSTR MatchingId
,
5249 FILETIME DriverDate
,
5250 DWORDLONG DriverVersion
,
5253 struct DriverInfoElement
*driverInfo
= NULL
;
5254 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5255 DWORD RequiredSize
= 128; /* Initial buffer size */
5256 BOOL Result
= FALSE
;
5257 PLIST_ENTRY PreviousEntry
;
5258 LPWSTR InfInstallSection
= NULL
;
5261 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5264 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5267 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5269 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5270 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5272 /* Copy InfFileName field */
5273 strncpyW(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5274 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5276 /* Fill InfDate field */
5277 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5278 GENERIC_READ, FILE_SHARE_READ,
5279 NULL, OPEN_EXISTING, 0, NULL);
5280 if (hFile == INVALID_HANDLE_VALUE)
5282 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5286 /* Fill SectionName field */
5287 Result
= SetupGetStringFieldW(
5290 driverInfo
->Details
.SectionName
, LINE_LEN
,
5295 /* Fill DrvDescription field */
5296 Result
= SetupGetStringFieldW(
5298 0, /* Field index */
5299 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5302 /* Copy MatchingId information */
5305 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5306 if (!driverInfo
->MatchingId
)
5308 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5311 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5314 driverInfo
->MatchingId
= NULL
;
5316 /* Get inf install section */
5318 RequiredSize
= 128; /* Initial buffer size */
5319 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5320 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5322 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5323 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5324 if (!InfInstallSection
)
5326 Result
= SetupGetStringFieldW(
5328 1, /* Field index */
5329 InfInstallSection
, RequiredSize
,
5335 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
5336 debugstr_w(driverInfo
->Details
.DrvDescription
), debugstr_w(InfFile
),
5337 debugstr_w(InfInstallSection
), Rank
);
5339 driverInfo
->DriverRank
= Rank
;
5340 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5341 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5342 driverInfo
->Info
.DriverType
= DriverType
;
5343 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5344 strncpyW(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5345 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5346 strncpyW(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5347 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5350 strncpyW(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5351 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5354 driverInfo
->Info
.ProviderName
[0] = '\0';
5355 driverInfo
->Info
.DriverDate
= DriverDate
;
5356 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5357 ReferenceInfFile(InfFileDetails
);
5358 driverInfo
->InfFileDetails
= InfFileDetails
;
5360 /* Insert current driver in driver list, according to its rank */
5361 PreviousEntry
= DriverListHead
->Flink
;
5362 while (PreviousEntry
!= DriverListHead
)
5364 struct DriverInfoElement
*CurrentDriver
;
5365 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5366 if (CurrentDriver
->DriverRank
> Rank
||
5367 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5369 /* Insert before the current item */
5370 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5373 PreviousEntry
= PreviousEntry
->Flink
;
5375 if (PreviousEntry
== DriverListHead
)
5377 /* Insert at the end of the list */
5378 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5387 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5388 HeapFree(GetProcessHeap(), 0, driverInfo
);
5390 if (hFile
!= INVALID_HANDLE_VALUE
)
5392 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5398 GetVersionInformationFromInfFile(
5400 OUT LPGUID ClassGuid
,
5401 OUT LPWSTR
* pProviderName
,
5402 OUT FILETIME
* DriverDate
,
5403 OUT DWORDLONG
* DriverVersion
)
5406 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5407 LPWSTR DriverVer
= NULL
;
5408 LPWSTR ProviderName
= NULL
;
5409 LPWSTR pComma
; /* Points into DriverVer */
5410 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5411 SYSTEMTIME SystemTime
;
5413 BOOL ret
= FALSE
; /* Final result */
5415 /* Get class Guid */
5416 if (!SetupGetLineTextW(
5420 guidW
, sizeof(guidW
),
5421 NULL
/* Required size */))
5425 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5426 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5428 SetLastError(ERROR_GEN_FAILURE
);
5432 /* Get provider name */
5433 Result
= SetupGetLineTextW(
5435 hInf
, Version
, INF_PROVIDER
,
5440 /* We know know the needed buffer size */
5441 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5444 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5447 Result
= SetupGetLineTextW(
5449 hInf
, Version
, INF_PROVIDER
,
5450 ProviderName
, RequiredSize
,
5455 *pProviderName
= ProviderName
;
5457 /* Read the "DriverVer" value */
5458 Result
= SetupGetLineTextW(
5460 hInf
, Version
, INF_DRIVER_VER
,
5465 /* We know know the needed buffer size */
5466 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5469 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5472 Result
= SetupGetLineTextW(
5474 hInf
, Version
, INF_DRIVER_VER
,
5475 DriverVer
, RequiredSize
,
5481 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5482 pComma
= strchrW(DriverVer
, ',');
5485 *pComma
= UNICODE_NULL
;
5486 pVersion
= pComma
+ 1;
5488 /* Get driver date version. Invalid date = 00/00/00 */
5489 memset(DriverDate
, 0, sizeof(FILETIME
));
5490 if (strlenW(DriverVer
) == 10
5491 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5492 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5494 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5495 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5496 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5497 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5498 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5499 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5501 /* Get driver version. Invalid version = 0.0.0.0 */
5505 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5506 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5507 LARGE_INTEGER fullVersion
;
5509 pMinor
= strchrW(pVersion
, '.');
5513 pRevision
= strchrW(++pMinor
, '.');
5514 Minor
= atoiW(pMinor
);
5519 pBuild
= strchrW(++pRevision
, '.');
5520 Revision
= atoiW(pRevision
);
5526 Build
= atoiW(pBuild
);
5528 Major
= atoiW(pVersion
);
5529 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5530 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5531 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5538 HeapFree(GetProcessHeap(), 0, ProviderName
);
5539 HeapFree(GetProcessHeap(), 0, DriverVer
);
5545 GetHardwareAndCompatibleIDsLists(
5546 IN HDEVINFO DeviceInfoSet
,
5547 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
5548 OUT LPWSTR
*pHardwareIDs OPTIONAL
,
5549 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL
,
5550 OUT LPWSTR
*pCompatibleIDs OPTIONAL
,
5551 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL
)
5553 LPWSTR HardwareIDs
= NULL
;
5554 LPWSTR CompatibleIDs
= NULL
;
5558 /* Get hardware IDs list */
5560 RequiredSize
= 512; /* Initial buffer size */
5561 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5562 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5564 MyFree(HardwareIDs
);
5565 HardwareIDs
= MyMalloc(RequiredSize
);
5568 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5571 Result
= SetupDiGetDeviceRegistryPropertyW(
5582 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5584 /* No hardware ID for this device */
5585 MyFree(HardwareIDs
);
5593 *pHardwareIDs
= HardwareIDs
;
5594 if (pHardwareIDsRequiredSize
)
5595 *pHardwareIDsRequiredSize
= RequiredSize
;
5597 /* Get compatible IDs list */
5599 RequiredSize
= 512; /* Initial buffer size */
5600 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5601 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5603 MyFree(CompatibleIDs
);
5604 CompatibleIDs
= MyMalloc(RequiredSize
);
5607 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5610 Result
= SetupDiGetDeviceRegistryPropertyW(
5613 SPDRP_COMPATIBLEIDS
,
5615 (PBYTE
)CompatibleIDs
,
5621 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5623 /* No compatible ID for this device */
5624 MyFree(CompatibleIDs
);
5625 CompatibleIDs
= NULL
;
5632 *pCompatibleIDs
= CompatibleIDs
;
5633 if (pCompatibleIDsRequiredSize
)
5634 *pCompatibleIDsRequiredSize
= RequiredSize
;
5641 MyFree(HardwareIDs
);
5642 MyFree(CompatibleIDs
);
5647 /***********************************************************************
5648 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5651 SetupDiBuildDriverInfoList(
5652 IN HDEVINFO DeviceInfoSet
,
5653 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5654 IN DWORD DriverType
)
5656 struct DeviceInfoSet
*list
;
5657 SP_DEVINSTALL_PARAMS_W InstallParams
;
5658 PVOID Buffer
= NULL
;
5659 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5660 LPWSTR ProviderName
= NULL
;
5661 LPWSTR ManufacturerName
= NULL
;
5662 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5663 LPWSTR HardwareIDs
= NULL
;
5664 LPWSTR CompatibleIDs
= NULL
;
5665 LPWSTR FullInfFileName
= NULL
;
5666 LPWSTR ExcludeFromSelect
= NULL
;
5667 FILETIME DriverDate
;
5668 DWORDLONG DriverVersion
= 0;
5672 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5675 SetLastError(ERROR_INVALID_HANDLE
);
5676 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5677 SetLastError(ERROR_INVALID_HANDLE
);
5678 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5679 SetLastError(ERROR_INVALID_HANDLE
);
5680 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5681 SetLastError(ERROR_INVALID_PARAMETER
);
5682 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5683 SetLastError(ERROR_INVALID_PARAMETER
);
5684 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5685 SetLastError(ERROR_INVALID_USER_BUFFER
);
5688 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
5691 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5692 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5698 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5699 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
5700 pDriverListHead
= &devInfo
->DriverListHead
;
5703 if (DriverType
== SPDIT_COMPATDRIVER
)
5705 /* Get hardware and compatible IDs lists */
5706 Result
= GetHardwareAndCompatibleIDsLists(
5715 if (!HardwareIDs
&& !CompatibleIDs
)
5717 SetLastError(ERROR_FILE_NOT_FOUND
);
5722 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5724 /* InstallParams.DriverPath contains the name of a .inf file */
5725 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
5726 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5729 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5732 strcpyW(Buffer
, InstallParams
.DriverPath
);
5733 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5738 /* Enumerate .inf files */
5740 RequiredSize
= 32768; /* Initial buffer size */
5741 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5742 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5744 HeapFree(GetProcessHeap(), 0, Buffer
);
5745 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5749 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5752 Result
= SetupGetInfFileListW(
5753 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5755 Buffer
, RequiredSize
,
5758 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5760 /* No .inf file in specified directory. So, we should
5761 * success as we created an empty driver info list.
5770 LPWSTR pFullFilename
;
5772 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5774 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5775 if (!FullInfFileName
)
5777 pFullFilename
= &FullInfFileName
[0];
5779 else if (*InstallParams
.DriverPath
)
5782 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5785 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5786 if (!FullInfFileName
)
5788 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5791 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
5792 strcatW(FullInfFileName
, L
"\\");
5793 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
5797 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5798 if (!FullInfFileName
)
5800 pFullFilename
= &FullInfFileName
[0];
5803 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
5805 INFCONTEXT ContextManufacturer
, ContextDevice
;
5808 strcpyW(pFullFilename
, filename
);
5809 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
5811 currentInfFileDetails
= HeapAlloc(
5814 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + strlenW(FullInfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
5815 if (!currentInfFileDetails
)
5817 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5818 strcpyW(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5820 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5821 ReferenceInfFile(currentInfFileDetails
);
5822 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5824 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5825 currentInfFileDetails
= NULL
;
5829 if (!GetVersionInformationFromInfFile(
5830 currentInfFileDetails
->hInf
,
5836 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5837 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5838 currentInfFileDetails
= NULL
;
5842 if (DriverType
== SPDIT_CLASSDRIVER
)
5844 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5845 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5851 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
5853 /* Read ExcludeFromSelect control flags */
5857 FIXME("ExcludeFromSelect list ignored\n");
5859 /* Get the manufacturers list */
5860 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
5863 Result
= SetupGetStringFieldW(
5864 &ContextManufacturer
,
5865 0, /* Field index */
5870 /* We got the needed size for the buffer */
5871 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5872 if (!ManufacturerName
)
5874 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5877 Result
= SetupGetStringFieldW(
5878 &ContextManufacturer
,
5879 0, /* Field index */
5880 ManufacturerName
, RequiredSize
,
5883 /* Get manufacturer section name */
5884 Result
= SetupGetStringFieldW(
5885 &ContextManufacturer
,
5886 1, /* Field index */
5887 ManufacturerSection
, LINE_LEN
,
5891 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5892 /* Add (possible) extension to manufacturer section name */
5893 Result
= SetupDiGetActualSectionToInstallW(
5894 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5897 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
5898 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5903 if (DriverType
== SPDIT_CLASSDRIVER
)
5905 /* FIXME: Check ExcludeFromSelect list */
5906 if (!AddDriverToList(
5911 currentInfFileDetails
,
5916 DriverDate
, DriverVersion
,
5922 else /* DriverType = SPDIT_COMPATDRIVER */
5924 /* 1. Get all fields */
5925 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5929 BOOL DriverAlreadyAdded
;
5931 for (i
= 2; i
<= FieldCount
; i
++)
5933 LPWSTR DeviceId
= NULL
;
5935 RequiredSize
= 128; /* Initial buffer size */
5936 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5937 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5939 HeapFree(GetProcessHeap(), 0, DeviceId
);
5940 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5943 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5946 Result
= SetupGetStringFieldW(
5949 DeviceId
, RequiredSize
,
5954 HeapFree(GetProcessHeap(), 0, DeviceId
);
5957 /* FIXME: Check ExcludeFromSelect list */
5958 DriverAlreadyAdded
= FALSE
;
5959 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
5961 if (wcsicmp(DeviceId
, currentId
) == 0)
5968 currentInfFileDetails
,
5973 DriverDate
, DriverVersion
,
5974 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5975 DriverAlreadyAdded
= TRUE
;
5980 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
5982 if (wcsicmp(DeviceId
, currentId
) == 0)
5989 currentInfFileDetails
,
5994 DriverDate
, DriverVersion
,
5995 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5996 DriverAlreadyAdded
= TRUE
;
6000 HeapFree(GetProcessHeap(), 0, DeviceId
);
6003 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
6006 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
6007 ManufacturerName
= NULL
;
6008 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
6013 HeapFree(GetProcessHeap(), 0, ProviderName
);
6014 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
6015 ProviderName
= ExcludeFromSelect
= NULL
;
6017 DereferenceInfFile(currentInfFileDetails
);
6018 currentInfFileDetails
= NULL
;
6029 InstallParams
.Flags
|= DI_DIDCOMPAT
;
6030 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
6034 InstallParams
.Flags
|= DI_DIDCLASS
;
6035 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
6037 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6040 HeapFree(GetProcessHeap(), 0, ProviderName
);
6041 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
6042 MyFree(HardwareIDs
);
6043 MyFree(CompatibleIDs
);
6044 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
6045 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
6046 if (currentInfFileDetails
)
6047 DereferenceInfFile(currentInfFileDetails
);
6048 HeapFree(GetProcessHeap(), 0, Buffer
);
6050 TRACE("Returning %d\n", ret
);
6054 /***********************************************************************
6055 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
6058 SetupDiDeleteDeviceInfo(
6059 IN HDEVINFO DeviceInfoSet
,
6060 IN PSP_DEVINFO_DATA DeviceInfoData
)
6062 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6064 FIXME("not implemented\n");
6065 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
6070 /***********************************************************************
6071 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
6074 SetupDiDestroyDriverInfoList(
6075 IN HDEVINFO DeviceInfoSet
,
6076 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6077 IN DWORD DriverType
)
6079 struct DeviceInfoSet
*list
;
6082 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
6085 SetLastError(ERROR_INVALID_HANDLE
);
6086 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6087 SetLastError(ERROR_INVALID_HANDLE
);
6088 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6089 SetLastError(ERROR_INVALID_PARAMETER
);
6090 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6091 SetLastError(ERROR_INVALID_PARAMETER
);
6092 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6093 SetLastError(ERROR_INVALID_USER_BUFFER
);
6096 PLIST_ENTRY ListEntry
;
6097 struct DriverInfoElement
*driverInfo
;
6098 SP_DEVINSTALL_PARAMS_W InstallParams
;
6100 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6101 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6104 if (!DeviceInfoData
)
6105 /* Fall back to destroying class driver list */
6106 DriverType
= SPDIT_CLASSDRIVER
;
6108 if (DriverType
== SPDIT_CLASSDRIVER
)
6110 while (!IsListEmpty(&list
->DriverListHead
))
6112 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
6113 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
6114 DestroyDriverInfoElement(driverInfo
);
6116 InstallParams
.Reserved
= 0;
6117 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
6118 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
6119 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
6123 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
6124 struct DeviceInfoElement
*deviceInfo
;
6126 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6127 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
6129 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6130 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
6132 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
6133 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
6134 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
6136 InstallParamsSet
.Reserved
= 0;
6137 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
6139 DestroyDriverInfoElement(driverInfo
);
6141 InstallParams
.Reserved
= 0;
6142 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
6143 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
6144 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6149 TRACE("Returning %d\n", ret
);
6154 /***********************************************************************
6155 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
6158 SetupDiOpenDeviceInfoA(
6159 IN HDEVINFO DeviceInfoSet
,
6160 IN PCSTR DeviceInstanceId
,
6161 IN HWND hwndParent OPTIONAL
,
6163 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6165 LPWSTR DeviceInstanceIdW
= NULL
;
6168 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
6170 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
6171 if (DeviceInstanceIdW
== NULL
)
6174 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
6175 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
6177 MyFree(DeviceInstanceIdW
);
6183 /***********************************************************************
6184 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
6187 SetupDiOpenDeviceInfoW(
6188 IN HDEVINFO DeviceInfoSet
,
6189 IN PCWSTR DeviceInstanceId
,
6190 IN HWND hwndParent OPTIONAL
,
6192 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6194 struct DeviceInfoSet
*list
;
6195 HKEY hEnumKey
, hKey
= NULL
;
6199 TRACE("%p %s %p %lx %p\n",
6200 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
6201 hwndParent
, OpenFlags
, DeviceInfoData
);
6203 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
6204 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6207 SetLastError(ERROR_INVALID_HANDLE
);
6208 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6209 SetLastError(ERROR_INVALID_HANDLE
);
6210 else if (!DeviceInstanceId
)
6211 SetLastError(ERROR_INVALID_PARAMETER
);
6212 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
6214 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
6215 SetLastError(ERROR_INVALID_FLAGS
);
6217 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6218 SetLastError(ERROR_INVALID_USER_BUFFER
);
6221 struct DeviceInfoElement
*deviceInfo
= NULL
;
6222 /* Search if device already exists in DeviceInfoSet.
6223 * If yes, return the existing element
6224 * If no, create a new element using informations in registry
6226 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
6227 while (ItemList
!= &list
->ListHead
)
6232 FIXME("not implemented\n");
6233 ItemList
= ItemList
->Flink
;
6238 /* good one found */
6243 /* Open supposed registry key */
6246 REGSTR_PATH_SYSTEMENUM
,
6250 if (rc
!= ERROR_SUCCESS
)
6261 RegCloseKey(hEnumKey
);
6262 if (rc
!= ERROR_SUCCESS
)
6264 if (rc
== ERROR_FILE_NOT_FOUND
)
6265 rc
= ERROR_NO_SUCH_DEVINST
;
6270 /* FIXME: try to get ClassGUID from registry, instead of
6271 * sending GUID_NULL to CreateDeviceInfoElement
6273 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6275 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6280 if (ret
&& deviceInfo
&& DeviceInfoData
)
6282 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6283 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6284 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6295 /***********************************************************************
6296 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6299 SetupDiEnumDriverInfoA(
6300 IN HDEVINFO DeviceInfoSet
,
6301 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6302 IN DWORD DriverType
,
6303 IN DWORD MemberIndex
,
6304 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6306 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6309 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6310 DriverType
, MemberIndex
, DriverInfoData
);
6312 if (DriverInfoData
== NULL
)
6313 SetLastError(ERROR_INVALID_PARAMETER
);
6314 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6315 SetLastError(ERROR_INVALID_USER_BUFFER
);
6318 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6319 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6320 DriverType
, MemberIndex
, &driverInfoData2W
);
6324 /* Do W->A conversion */
6325 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6326 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6327 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6328 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6330 DriverInfoData
->Description
[0] = '\0';
6333 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6334 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6336 DriverInfoData
->MfgName
[0] = '\0';
6339 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6340 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6342 DriverInfoData
->ProviderName
[0] = '\0';
6345 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6347 /* Copy more fields */
6348 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6349 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6354 TRACE("Returning %d\n", ret
);
6359 /***********************************************************************
6360 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6363 SetupDiEnumDriverInfoW(
6364 IN HDEVINFO DeviceInfoSet
,
6365 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6366 IN DWORD DriverType
,
6367 IN DWORD MemberIndex
,
6368 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6370 PLIST_ENTRY ListHead
;
6373 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6374 DriverType
, MemberIndex
, DriverInfoData
);
6376 if (!DeviceInfoSet
|| !DriverInfoData
)
6377 SetLastError(ERROR_INVALID_PARAMETER
);
6378 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6379 SetLastError(ERROR_INVALID_HANDLE
);
6380 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6381 SetLastError(ERROR_INVALID_HANDLE
);
6382 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6383 SetLastError(ERROR_INVALID_PARAMETER
);
6384 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6385 SetLastError(ERROR_INVALID_PARAMETER
);
6386 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6387 SetLastError(ERROR_INVALID_USER_BUFFER
);
6390 struct DeviceInfoElement
*devInfo
= NULL
;
6391 PLIST_ENTRY ItemList
;
6393 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6394 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
6396 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6400 ListHead
= &devInfo
->DriverListHead
;
6403 ItemList
= ListHead
->Flink
;
6404 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6405 ItemList
= ItemList
->Flink
;
6406 if (ItemList
== ListHead
)
6407 SetLastError(ERROR_NO_MORE_ITEMS
);
6410 struct DriverInfoElement
*DrvInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6413 &DriverInfoData
->DriverType
,
6414 &DrvInfo
->Info
.DriverType
,
6415 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6420 TRACE("Returning %d\n", ret
);
6425 /***********************************************************************
6426 * SetupDiGetSelectedDevice (SETUPAPI.@)
6429 SetupDiGetSelectedDevice(
6430 IN HDEVINFO DeviceInfoSet
,
6431 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6433 struct DeviceInfoSet
*list
;
6436 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6439 SetLastError(ERROR_INVALID_HANDLE
);
6440 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6441 SetLastError(ERROR_INVALID_HANDLE
);
6442 else if (list
->SelectedDevice
== NULL
)
6443 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6444 else if (!DeviceInfoData
)
6445 SetLastError(ERROR_INVALID_PARAMETER
);
6446 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6447 SetLastError(ERROR_INVALID_USER_BUFFER
);
6450 memcpy(&DeviceInfoData
->ClassGuid
,
6451 &list
->SelectedDevice
->ClassGuid
,
6453 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6454 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6458 TRACE("Returning %d\n", ret
);
6463 /***********************************************************************
6464 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6467 SetupDiGetSelectedDriverA(
6468 IN HDEVINFO DeviceInfoSet
,
6469 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6470 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6472 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6475 if (DriverInfoData
== NULL
)
6476 SetLastError(ERROR_INVALID_PARAMETER
);
6477 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6478 SetLastError(ERROR_INVALID_USER_BUFFER
);
6481 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6483 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6489 /* Do W->A conversion */
6490 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6491 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6492 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6493 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6495 DriverInfoData
->Description
[0] = '\0';
6498 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6499 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6501 DriverInfoData
->MfgName
[0] = '\0';
6504 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6505 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6507 DriverInfoData
->ProviderName
[0] = '\0';
6510 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6512 /* Copy more fields */
6513 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6514 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6523 /***********************************************************************
6524 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6527 SetupDiGetSelectedDriverW(
6528 IN HDEVINFO DeviceInfoSet
,
6529 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6530 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6534 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6536 if (!DeviceInfoSet
|| !DriverInfoData
)
6537 SetLastError(ERROR_INVALID_PARAMETER
);
6538 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6539 SetLastError(ERROR_INVALID_HANDLE
);
6540 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6541 SetLastError(ERROR_INVALID_HANDLE
);
6542 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6543 SetLastError(ERROR_INVALID_USER_BUFFER
);
6544 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6545 SetLastError(ERROR_INVALID_USER_BUFFER
);
6548 SP_DEVINSTALL_PARAMS InstallParams
;
6550 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6551 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6553 struct DriverInfoElement
*driverInfo
;
6554 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6555 if (driverInfo
== NULL
)
6556 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6560 &DriverInfoData
->DriverType
,
6561 &driverInfo
->Info
.DriverType
,
6562 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6568 TRACE("Returning %d\n", ret
);
6573 /***********************************************************************
6574 * SetupDiSetSelectedDevice (SETUPAPI.@)
6577 SetupDiSetSelectedDevice(
6578 IN HDEVINFO DeviceInfoSet
,
6579 IN PSP_DEVINFO_DATA DeviceInfoData
)
6581 struct DeviceInfoSet
*list
;
6584 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6587 SetLastError(ERROR_INVALID_HANDLE
);
6588 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6589 SetLastError(ERROR_INVALID_HANDLE
);
6590 else if (!DeviceInfoData
)
6591 SetLastError(ERROR_INVALID_PARAMETER
);
6592 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6593 SetLastError(ERROR_INVALID_USER_BUFFER
);
6594 else if (DeviceInfoData
->Reserved
== 0)
6595 SetLastError(ERROR_INVALID_USER_BUFFER
);
6598 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6602 TRACE("Returning %d\n", ret
);
6607 /***********************************************************************
6608 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6611 SetupDiSetSelectedDriverA(
6612 IN HDEVINFO DeviceInfoSet
,
6613 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6614 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6616 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6617 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6620 if (DriverInfoData
!= NULL
)
6622 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6623 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6625 SetLastError(ERROR_INVALID_PARAMETER
);
6629 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6630 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6632 if (DriverInfoDataW
.Reserved
== 0)
6634 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6636 /* convert the strings to unicode */
6637 if (!MultiByteToWideChar(CP_ACP
,
6639 DriverInfoData
->Description
,
6641 DriverInfoDataW
.Description
,
6643 !MultiByteToWideChar(CP_ACP
,
6645 DriverInfoData
->ProviderName
,
6647 DriverInfoDataW
.ProviderName
,
6654 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6657 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6661 if (ret
&& pDriverInfoDataW
!= NULL
)
6663 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6670 /***********************************************************************
6671 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6674 SetupDiSetSelectedDriverW(
6675 IN HDEVINFO DeviceInfoSet
,
6676 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6677 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6681 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6684 SetLastError(ERROR_INVALID_PARAMETER
);
6685 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6686 SetLastError(ERROR_INVALID_HANDLE
);
6687 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6688 SetLastError(ERROR_INVALID_HANDLE
);
6689 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6690 SetLastError(ERROR_INVALID_USER_BUFFER
);
6691 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6692 SetLastError(ERROR_INVALID_USER_BUFFER
);
6695 struct DriverInfoElement
**pDriverInfo
;
6696 PLIST_ENTRY ListHead
, ItemList
;
6700 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6701 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6705 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6706 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6709 if (!DriverInfoData
)
6711 *pDriverInfo
= NULL
;
6716 /* Search selected driver in list */
6717 ItemList
= ListHead
->Flink
;
6718 while (ItemList
!= ListHead
)
6720 if (DriverInfoData
->Reserved
!= 0)
6722 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6727 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6728 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6729 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6730 && strcmpW(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6731 && strcmpW(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6736 ItemList
= ItemList
->Flink
;
6738 if (ItemList
== ListHead
)
6739 SetLastError(ERROR_INVALID_PARAMETER
);
6742 *pDriverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6743 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6745 TRACE("Choosing driver whose rank is 0x%lx\n",
6746 (*pDriverInfo
)->DriverRank
);
6748 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6753 TRACE("Returning %d\n", ret
);
6757 /***********************************************************************
6758 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6761 SetupDiGetDriverInfoDetailA(
6762 IN HDEVINFO DeviceInfoSet
,
6763 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6764 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6765 IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6766 IN DWORD DriverInfoDetailDataSize
,
6767 OUT PDWORD RequiredSize OPTIONAL
)
6769 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6770 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6772 DWORD HardwareIDLen
= 0;
6775 /* do some sanity checks, the unicode version might do more thorough checks */
6776 if (DriverInfoData
== NULL
||
6777 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6778 (DriverInfoDetailData
!= NULL
&&
6779 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6780 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6782 SetLastError(ERROR_INVALID_PARAMETER
);
6786 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6787 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6789 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6791 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6793 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6797 SetLastError(ERROR_INVALID_PARAMETER
);
6800 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6801 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6803 /* convert the strings to unicode */
6804 if (MultiByteToWideChar(CP_ACP
,
6806 DriverInfoData
->Description
,
6808 DriverInfoDataW
.Description
,
6810 MultiByteToWideChar(CP_ACP
,
6812 DriverInfoData
->MfgName
,
6814 DriverInfoDataW
.MfgName
,
6816 MultiByteToWideChar(CP_ACP
,
6818 DriverInfoData
->ProviderName
,
6820 DriverInfoDataW
.ProviderName
,
6823 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6825 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6826 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6829 if (DriverInfoDetailData
!= NULL
)
6831 /* calculate the unicode buffer size from the ansi buffer size */
6832 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6833 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6834 (HardwareIDLen
* sizeof(WCHAR
));
6836 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6837 if (DriverInfoDetailDataW
== NULL
)
6839 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6843 /* initialize the buffer */
6844 ZeroMemory(DriverInfoDetailDataW
,
6846 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6849 /* call the unicode version */
6850 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6853 DriverInfoDetailDataW
,
6859 if (DriverInfoDetailDataW
!= NULL
)
6861 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6862 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6863 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6864 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6865 if (WideCharToMultiByte(CP_ACP
,
6867 DriverInfoDetailDataW
->SectionName
,
6869 DriverInfoDetailData
->SectionName
,
6873 WideCharToMultiByte(CP_ACP
,
6875 DriverInfoDetailDataW
->InfFileName
,
6877 DriverInfoDetailData
->InfFileName
,
6881 WideCharToMultiByte(CP_ACP
,
6883 DriverInfoDetailDataW
->DrvDescription
,
6885 DriverInfoDetailData
->DrvDescription
,
6889 WideCharToMultiByte(CP_ACP
,
6891 DriverInfoDetailDataW
->HardwareID
,
6893 DriverInfoDetailData
->HardwareID
,
6899 DWORD hwidlen
= HardwareIDLen
;
6900 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6902 /* count the strings in the list */
6905 len
= lstrlenA(s
) + 1;
6914 /* looks like the string list wasn't terminated... */
6915 SetLastError(ERROR_INVALID_USER_BUFFER
);
6921 /* make sure CompatIDsOffset points to the second string in the
6925 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6926 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6927 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6931 DriverInfoDetailData
->CompatIDsOffset
= 0;
6932 DriverInfoDetailData
->CompatIDsLength
= 0;
6941 if (RequiredSize
!= NULL
)
6943 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6944 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6950 if (DriverInfoDetailDataW
!= NULL
)
6952 MyFree(DriverInfoDetailDataW
);
6958 /***********************************************************************
6959 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6962 SetupDiGetDriverInfoDetailW(
6963 IN HDEVINFO DeviceInfoSet
,
6964 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6965 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6966 IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6967 IN DWORD DriverInfoDetailDataSize
,
6968 OUT PDWORD RequiredSize OPTIONAL
)
6972 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6973 DriverInfoData
, DriverInfoDetailData
,
6974 DriverInfoDetailDataSize
, RequiredSize
);
6977 SetLastError(ERROR_INVALID_PARAMETER
);
6978 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6979 SetLastError(ERROR_INVALID_HANDLE
);
6980 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6981 SetLastError(ERROR_INVALID_HANDLE
);
6982 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6983 SetLastError(ERROR_INVALID_USER_BUFFER
);
6984 else if (!DriverInfoData
)
6985 SetLastError(ERROR_INVALID_PARAMETER
);
6986 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6987 SetLastError(ERROR_INVALID_PARAMETER
);
6988 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6989 SetLastError(ERROR_INVALID_PARAMETER
);
6990 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6991 SetLastError(ERROR_INVALID_USER_BUFFER
);
6992 else if (DriverInfoData
->Reserved
== 0)
6993 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6996 struct DriverInfoElement
*driverInfoElement
;
6997 LPWSTR HardwareIDs
= NULL
;
6998 LPWSTR CompatibleIDs
= NULL
;
6999 LPWSTR pBuffer
= NULL
;
7000 LPCWSTR DeviceID
= NULL
;
7001 ULONG HardwareIDsSize
, CompatibleIDsSize
;
7002 ULONG sizeNeeded
, sizeLeft
, size
;
7005 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
7007 /* Get hardware and compatible IDs lists */
7008 Result
= GetHardwareAndCompatibleIDsLists(
7011 &HardwareIDs
, &HardwareIDsSize
,
7012 &CompatibleIDs
, &CompatibleIDsSize
);
7016 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
7017 + HardwareIDsSize
+ CompatibleIDsSize
;
7019 *RequiredSize
= sizeNeeded
;
7021 if (!DriverInfoDetailData
)
7028 DriverInfoDetailData
,
7029 &driverInfoElement
->Details
,
7030 driverInfoElement
->Details
.cbSize
);
7031 DriverInfoDetailData
->CompatIDsOffset
= 0;
7032 DriverInfoDetailData
->CompatIDsLength
= 0;
7034 sizeLeft
= (DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
);
7035 pBuffer
= DriverInfoDetailData
->HardwareID
;
7036 /* Add as many as possible HardwareIDs in the list */
7037 DeviceID
= HardwareIDs
;
7038 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
7040 TRACE("Adding %S to list\n", DeviceID
);
7041 wcscpy(pBuffer
, DeviceID
);
7042 DeviceID
+= size
+ 1;
7043 pBuffer
+= size
+ 1;
7044 sizeLeft
-= size
+ 1;
7045 DriverInfoDetailData
->CompatIDsOffset
+= size
+ 1;
7049 *pBuffer
= UNICODE_NULL
;
7051 DriverInfoDetailData
->CompatIDsOffset
++;
7053 /* Add as many as possible CompatibleIDs in the list */
7054 DeviceID
= CompatibleIDs
;
7055 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
7057 TRACE("Adding %S to list\n", DeviceID
);
7058 wcscpy(pBuffer
, DeviceID
);
7059 DeviceID
+= size
+ 1;
7060 pBuffer
+= size
+ 1;
7061 sizeLeft
-= size
+ 1;
7062 DriverInfoDetailData
->CompatIDsLength
+= size
+ 1;
7066 *pBuffer
= UNICODE_NULL
;
7068 DriverInfoDetailData
->CompatIDsLength
++;
7071 if (sizeNeeded
> DriverInfoDetailDataSize
)
7072 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
7077 MyFree(HardwareIDs
);
7078 MyFree(CompatibleIDs
);
7081 TRACE("Returning %d\n", ret
);
7085 /* Return the current hardware profile id, or -1 if error */
7087 GetCurrentHwProfile(
7088 IN HDEVINFO DeviceInfoSet
)
7091 DWORD dwRegType
, dwLength
;
7094 DWORD ret
= (DWORD
)-1;
7097 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
7098 REGSTR_PATH_IDCONFIGDB
,
7102 if (rc
!= ERROR_SUCCESS
)
7108 dwLength
= sizeof(DWORD
);
7109 rc
= RegQueryValueExW(
7111 REGSTR_VAL_CURRENTCONFIG
,
7114 (LPBYTE
)&hwProfile
, &dwLength
);
7115 if (rc
!= ERROR_SUCCESS
)
7120 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7122 SetLastError(ERROR_GEN_FAILURE
);
7137 IN HDEVINFO DeviceInfoSet
,
7138 IN PSP_DEVINFO_DATA DeviceInfoData
)
7141 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
7142 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
7145 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
7147 /* At the moment, I only know how to start local devices */
7148 SetLastError(ERROR_INVALID_COMPUTERNAME
);
7152 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
7153 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
7154 SetLastError(RtlNtStatusToDosError(Status
));
7155 return NT_SUCCESS(Status
);
7157 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7162 static BOOL
StopDevice(
7163 IN HDEVINFO DeviceInfoSet
,
7164 IN PSP_DEVINFO_DATA DeviceInfoData
)
7166 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7170 /***********************************************************************
7171 * SetupDiChangeState (SETUPAPI.@)
7175 IN HDEVINFO DeviceInfoSet
,
7176 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
7178 PSP_PROPCHANGE_PARAMS PropChange
;
7179 HKEY hKey
= INVALID_HANDLE_VALUE
;
7180 LPCWSTR RegistryValueName
;
7181 DWORD dwConfigFlags
, dwLength
, dwRegType
;
7185 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7187 if (!DeviceInfoData
)
7188 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
7190 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
7193 SetLastError(ERROR_INVALID_PARAMETER
);
7197 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
7198 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
7200 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
7202 switch (PropChange
->StateChange
)
7207 /* Enable/disable device in registry */
7208 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
7209 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7210 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
7211 if (hKey
== INVALID_HANDLE_VALUE
)
7213 dwLength
= sizeof(DWORD
);
7214 rc
= RegQueryValueExW(
7219 (LPBYTE
)&dwConfigFlags
, &dwLength
);
7220 if (rc
== ERROR_FILE_NOT_FOUND
)
7222 else if (rc
!= ERROR_SUCCESS
)
7227 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7229 SetLastError(ERROR_GEN_FAILURE
);
7232 if (PropChange
->StateChange
== DICS_ENABLE
)
7233 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7235 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7241 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
7242 if (rc
!= ERROR_SUCCESS
)
7248 /* Enable/disable device if needed */
7249 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
7250 || PropChange
->HwProfile
== 0
7251 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
7253 if (PropChange
->StateChange
== DICS_ENABLE
)
7254 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7256 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
7262 case DICS_PROPCHANGE
:
7264 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7269 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
7270 SetLastError(ERROR_NOT_SUPPORTED
);
7275 if (hKey
!= INVALID_HANDLE_VALUE
)
7278 TRACE("Returning %d\n", ret
);
7282 /***********************************************************************
7283 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
7286 SetupDiSelectBestCompatDrv(
7287 IN HDEVINFO DeviceInfoSet
,
7288 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7290 SP_DRVINFO_DATA_W drvInfoData
;
7293 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7295 /* Drivers are sorted by rank in the driver list, so
7296 * the first driver in the list is the best one.
7298 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
7299 ret
= SetupDiEnumDriverInfoW(
7303 0, /* Member index */
7308 ret
= SetupDiSetSelectedDriverW(
7314 TRACE("Returning %d\n", ret
);
7318 /***********************************************************************
7319 * SetupDiInstallDriverFiles (SETUPAPI.@)
7322 SetupDiInstallDriverFiles(
7323 IN HDEVINFO DeviceInfoSet
,
7324 IN PSP_DEVINFO_DATA DeviceInfoData
)
7328 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7331 SetLastError(ERROR_INVALID_PARAMETER
);
7332 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7333 SetLastError(ERROR_INVALID_HANDLE
);
7334 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7335 SetLastError(ERROR_INVALID_HANDLE
);
7336 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7337 SetLastError(ERROR_INVALID_USER_BUFFER
);
7338 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7339 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7340 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7341 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7344 SP_DEVINSTALL_PARAMS_W InstallParams
;
7345 struct DriverInfoElement
*SelectedDriver
;
7346 WCHAR SectionName
[MAX_PATH
];
7347 DWORD SectionNameLength
= 0;
7348 PVOID InstallMsgHandler
;
7349 PVOID InstallMsgHandlerContext
;
7350 PVOID Context
= NULL
;
7352 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7353 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7357 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7358 if (!SelectedDriver
)
7360 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7364 ret
= SetupDiGetActualSectionToInstallW(
7365 SelectedDriver
->InfFileDetails
->hInf
,
7366 SelectedDriver
->Details
.SectionName
,
7367 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
7371 if (InstallParams
.InstallMsgHandler
)
7373 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
7374 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
7378 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7381 InstallMsgHandler
= SetupDefaultQueueCallback
;
7382 InstallMsgHandlerContext
= Context
;
7384 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7385 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7386 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7387 InstallMsgHandler
, InstallMsgHandlerContext
,
7388 DeviceInfoSet
, DeviceInfoData
);
7392 /* Install files from .CoInstallers section */
7393 lstrcatW(SectionName
, DotCoInstallers
);
7394 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7395 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7396 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7397 InstallMsgHandler
, InstallMsgHandlerContext
,
7398 DeviceInfoSet
, DeviceInfoData
);
7402 /* Set the DI_NOFILECOPY flag to prevent another
7403 * installation during SetupDiInstallDevice */
7404 InstallParams
.Flags
|= DI_NOFILECOPY
;
7405 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7409 SetupTermDefaultQueueCallback(Context
);
7413 TRACE("Returning %d\n", ret
);
7417 /***********************************************************************
7418 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7421 SetupDiRegisterCoDeviceInstallers(
7422 IN HDEVINFO DeviceInfoSet
,
7423 IN PSP_DEVINFO_DATA DeviceInfoData
)
7425 BOOL ret
= FALSE
; /* Return value */
7427 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7430 SetLastError(ERROR_INVALID_PARAMETER
);
7431 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7432 SetLastError(ERROR_INVALID_HANDLE
);
7433 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7434 SetLastError(ERROR_INVALID_HANDLE
);
7435 else if (!DeviceInfoData
)
7436 SetLastError(ERROR_INVALID_PARAMETER
);
7437 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7438 SetLastError(ERROR_INVALID_USER_BUFFER
);
7441 SP_DEVINSTALL_PARAMS_W InstallParams
;
7442 struct DriverInfoElement
*SelectedDriver
;
7445 WCHAR SectionName
[MAX_PATH
];
7446 DWORD SectionNameLength
= 0;
7447 HKEY hKey
= INVALID_HANDLE_VALUE
;
7448 PVOID Context
= NULL
;
7450 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7451 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7455 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7456 if (SelectedDriver
== NULL
)
7458 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7462 /* Get .CoInstallers section name */
7463 Result
= SetupDiGetActualSectionToInstallW(
7464 SelectedDriver
->InfFileDetails
->hInf
,
7465 SelectedDriver
->Details
.SectionName
,
7466 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7467 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
7469 lstrcatW(SectionName
, DotCoInstallers
);
7471 /* Open/Create driver key information */
7472 #if _WIN32_WINNT >= 0x502
7473 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7475 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7477 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7478 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7479 if (hKey
== INVALID_HANDLE_VALUE
)
7482 /* Install .CoInstallers section */
7483 DoAction
= SPINST_REGISTRY
;
7484 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7486 DoAction
|= SPINST_FILES
;
7487 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7491 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7492 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7493 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7494 SetupDefaultQueueCallback
, Context
,
7495 DeviceInfoSet
, DeviceInfoData
);
7503 SetupTermDefaultQueueCallback(Context
);
7504 if (hKey
!= INVALID_HANDLE_VALUE
)
7508 TRACE("Returning %d\n", ret
);
7513 InstallOneInterface(
7514 IN LPGUID InterfaceGuid
,
7515 IN LPCWSTR ReferenceString
,
7516 IN LPCWSTR InterfaceSection
,
7517 IN UINT InterfaceFlags
)
7519 if (InterfaceFlags
!= 0)
7521 SetLastError(ERROR_INVALID_PARAMETER
);
7525 FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid
),
7526 debugstr_w(ReferenceString
), debugstr_w(InterfaceSection
), InterfaceFlags
);
7530 /***********************************************************************
7531 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7534 SetupDiInstallDeviceInterfaces(
7535 IN HDEVINFO DeviceInfoSet
,
7536 IN PSP_DEVINFO_DATA DeviceInfoData
)
7538 struct DeviceInfoSet
*list
= NULL
;
7541 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7544 SetLastError(ERROR_INVALID_PARAMETER
);
7545 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7546 SetLastError(ERROR_INVALID_HANDLE
);
7547 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7548 SetLastError(ERROR_INVALID_HANDLE
);
7549 else if (!DeviceInfoData
)
7550 SetLastError(ERROR_INVALID_PARAMETER
);
7551 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7552 SetLastError(ERROR_INVALID_USER_BUFFER
);
7555 struct DriverInfoElement
*SelectedDriver
;
7556 SP_DEVINSTALL_PARAMS_W InstallParams
;
7557 WCHAR SectionName
[MAX_PATH
];
7558 DWORD SectionNameLength
= 0;
7559 INFCONTEXT ContextInterface
;
7560 LPWSTR InterfaceGuidString
= NULL
;
7561 LPWSTR ReferenceString
= NULL
;
7562 LPWSTR InterfaceSection
= NULL
;
7567 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7568 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7572 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7573 if (SelectedDriver
== NULL
)
7575 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7580 /* Get .Interfaces section name */
7581 Result
= SetupDiGetActualSectionToInstallW(
7582 SelectedDriver
->InfFileDetails
->hInf
,
7583 SelectedDriver
->Details
.SectionName
,
7584 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7585 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotInterfaces
) - 1)
7587 strcatW(SectionName
, DotInterfaces
);
7590 Result
= SetupFindFirstLineW(
7591 SelectedDriver
->InfFileDetails
->hInf
,
7595 while (ret
&& Result
)
7597 ret
= GetStringField(&ContextInterface
, 1, &InterfaceGuidString
);
7600 else if (strlenW(InterfaceGuidString
) != MAX_GUID_STRING_LEN
- 1)
7602 SetLastError(ERROR_INVALID_PARAMETER
);
7607 InterfaceGuidString
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
7608 if (UuidFromStringW(&InterfaceGuidString
[1], &InterfaceGuid
) != RPC_S_OK
)
7610 /* Bad GUID, skip the entry */
7611 SetLastError(ERROR_INVALID_PARAMETER
);
7616 ret
= GetStringField(&ContextInterface
, 2, &ReferenceString
);
7620 ret
= GetStringField(&ContextInterface
, 3, &InterfaceSection
);
7624 ret
= SetupGetIntField(
7626 4, /* Field index */
7630 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7632 /* The field may be empty. Ignore the error */
7640 /* Install Interface */
7641 ret
= InstallOneInterface(&InterfaceGuid
, ReferenceString
, InterfaceSection
, InterfaceFlags
);
7644 MyFree(InterfaceGuidString
);
7645 MyFree(ReferenceString
);
7646 MyFree(InterfaceSection
);
7647 InterfaceGuidString
= ReferenceString
= InterfaceSection
= NULL
;
7648 Result
= SetupFindNextMatchLineW(&ContextInterface
, AddInterface
, &ContextInterface
);
7652 TRACE("Returning %d\n", ret
);
7657 InfIsFromOEMLocation(
7659 OUT LPBOOL IsOEMLocation
)
7663 last
= strrchrW(FullName
, '\\');
7666 /* No directory specified */
7667 *IsOEMLocation
= FALSE
;
7671 WCHAR Windir
[MAX_PATH
];
7674 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7675 if (ret
== 0 || ret
>= MAX_PATH
)
7677 SetLastError(ERROR_GEN_FAILURE
);
7681 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7683 /* The path is %WINDIR%\Inf */
7684 *IsOEMLocation
= FALSE
;
7688 /* The file is in another place */
7689 *IsOEMLocation
= TRUE
;
7695 /***********************************************************************
7696 * SetupDiInstallDevice (SETUPAPI.@)
7699 SetupDiInstallDevice(
7700 IN HDEVINFO DeviceInfoSet
,
7701 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
7703 SP_DEVINSTALL_PARAMS_W InstallParams
;
7704 struct DriverInfoElement
*SelectedDriver
;
7705 SYSTEMTIME DriverDate
;
7706 WCHAR SectionName
[MAX_PATH
];
7708 DWORD SectionNameLength
= 0;
7709 BOOL Result
= FALSE
;
7712 LPWSTR pSectionName
= NULL
;
7713 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7715 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7716 BOOL RebootRequired
= FALSE
;
7717 HKEY hKey
= INVALID_HANDLE_VALUE
;
7718 BOOL NeedtoCopyFile
;
7719 LARGE_INTEGER fullVersion
;
7721 PVOID Context
= NULL
;
7722 BOOL ret
= FALSE
; /* Return value */
7724 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7727 SetLastError(ERROR_INVALID_PARAMETER
);
7728 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7729 SetLastError(ERROR_INVALID_HANDLE
);
7730 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7731 SetLastError(ERROR_INVALID_HANDLE
);
7732 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7733 SetLastError(ERROR_INVALID_USER_BUFFER
);
7739 /* One parameter is bad */
7743 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7744 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7748 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7750 /* Set FAILEDINSTALL in ConfigFlags registry value */
7751 DWORD ConfigFlags
, regType
;
7752 Result
= SetupDiGetDeviceRegistryPropertyW(
7757 (PBYTE
)&ConfigFlags
,
7758 sizeof(ConfigFlags
),
7760 if (!Result
|| regType
!= REG_DWORD
)
7762 SetLastError(ERROR_GEN_FAILURE
);
7765 ConfigFlags
|= DNF_DISABLED
;
7766 Result
= SetupDiSetDeviceRegistryPropertyW(
7770 (PBYTE
)&ConfigFlags
,
7771 sizeof(ConfigFlags
));
7774 SetLastError(ERROR_GEN_FAILURE
);
7782 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7783 if (SelectedDriver
== NULL
)
7785 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7789 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7791 Result
= SetupDiGetActualSectionToInstallW(
7792 SelectedDriver
->InfFileDetails
->hInf
,
7793 SelectedDriver
->Details
.SectionName
,
7794 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7795 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
7797 pSectionName
= &SectionName
[strlenW(SectionName
)];
7799 /* Get information from [Version] section */
7800 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7802 /* Format ClassGuid to a string */
7803 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7805 RequiredSize
= lstrlenW(lpGuidString
);
7806 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7807 if (!lpFullGuidString
)
7809 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7812 lpFullGuidString
[0] = '{';
7813 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7814 lpFullGuidString
[RequiredSize
+ 1] = '}';
7815 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7817 /* Open/Create driver key information */
7818 #if _WIN32_WINNT >= 0x502
7819 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7821 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7823 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7824 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7825 if (hKey
== INVALID_HANDLE_VALUE
)
7828 /* Install main section */
7830 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7831 DoAction
|= SPINST_REGISTRY
;
7832 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7834 DoAction
|= SPINST_FILES
;
7835 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7839 *pSectionName
= '\0';
7840 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7841 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7842 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7843 SetupDefaultQueueCallback
, Context
,
7844 DeviceInfoSet
, DeviceInfoData
);
7847 InstallParams
.Flags
|= DI_NOFILECOPY
;
7848 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7850 /* Write information to driver key */
7851 *pSectionName
= UNICODE_NULL
;
7852 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7853 TRACE("Write information to driver key\n");
7854 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7855 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
7856 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7857 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->Details
.InfFileName
));
7858 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
7859 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
7860 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
7861 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
7862 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7863 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
7864 if (rc
== ERROR_SUCCESS
)
7865 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7866 if (rc
== ERROR_SUCCESS
)
7867 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7868 if (rc
== ERROR_SUCCESS
)
7870 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7871 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
7873 if (rc
== ERROR_SUCCESS
)
7874 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (strlenW(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7875 if (rc
== ERROR_SUCCESS
)
7876 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7877 if (rc
== ERROR_SUCCESS
)
7878 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTIONEXT
, 0, REG_SZ
, (const BYTE
*)&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)], (strlenW(SectionName
) - strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7879 if (rc
== ERROR_SUCCESS
)
7880 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7881 if (rc
== ERROR_SUCCESS
)
7882 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7883 if (rc
!= ERROR_SUCCESS
)
7889 hKey
= INVALID_HANDLE_VALUE
;
7891 /* FIXME: Process .LogConfigOverride section */
7893 /* Install .Services section */
7894 strcpyW(pSectionName
, DotServices
);
7895 Result
= SetupInstallServicesFromInfSectionExW(
7896 SelectedDriver
->InfFileDetails
->hInf
,
7905 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7906 RebootRequired
= TRUE
;
7908 /* Copy .inf file to Inf\ directory (if needed) */
7909 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7914 Result
= SetupCopyOEMInfW(
7915 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7918 SP_COPY_NOOVERWRITE
,
7924 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7925 * to release use of current InfFile */
7928 /* Open device registry key */
7929 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7930 if (hKey
== INVALID_HANDLE_VALUE
)
7933 /* Install .HW section */
7935 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7936 DoAction
|= SPINST_REGISTRY
;
7937 strcpyW(pSectionName
, DotHW
);
7938 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7939 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7940 DoAction
, hKey
, NULL
, 0,
7942 DeviceInfoSet
, DeviceInfoData
);
7946 /* Write information to enum key */
7947 TRACE("Write information to enum key\n");
7948 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
7949 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
7950 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
7951 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
7952 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
7953 if (rc
== ERROR_SUCCESS
)
7954 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7955 if (rc
== ERROR_SUCCESS
)
7956 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7957 if (rc
== ERROR_SUCCESS
)
7958 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7959 if (rc
!= ERROR_SUCCESS
)
7965 /* Start the device */
7966 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7967 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7972 /* End of installation */
7973 if (hKey
!= INVALID_HANDLE_VALUE
)
7976 RpcStringFreeW(&lpGuidString
);
7977 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7979 SetupTermDefaultQueueCallback(Context
);
7980 TRACE("Returning %d\n", ret
);