2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
26 /* Unicode constants */
27 static const WCHAR BackSlash
[] = {'\\',0};
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
31 static const WCHAR DotHW
[] = {'.','H','W',0};
32 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
33 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
35 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
36 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
37 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
38 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
39 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
42 (CALLBACK
* CLASS_INSTALL_PROC
) (
43 IN DI_FUNCTION InstallFunction
,
44 IN HDEVINFO DeviceInfoSet
,
45 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
47 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
48 IN HDEVINFO DeviceInfoSet
,
49 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
51 (CALLBACK
* COINSTALLER_PROC
) (
52 IN DI_FUNCTION InstallFunction
,
53 IN HDEVINFO DeviceInfoSet
,
54 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
55 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
57 struct CoInstallerElement
62 COINSTALLER_PROC Function
;
63 BOOL DoPostProcessing
;
67 struct GetSectionCallbackInfo
69 PSP_ALTPLATFORM_INFO PlatformInfo
;
73 WCHAR BestSection
[LINE_LEN
+ 1];
74 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
78 /***********************************************************************
79 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
82 SetupDiCreateDeviceInfoList(
83 IN CONST GUID
*ClassGuid OPTIONAL
,
84 IN HWND hwndParent OPTIONAL
)
86 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
89 /***********************************************************************
90 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
93 SetupDiCreateDeviceInfoListExA(
94 IN CONST GUID
*ClassGuid OPTIONAL
,
95 IN HWND hwndParent OPTIONAL
,
96 IN PCSTR MachineName OPTIONAL
,
99 LPWSTR MachineNameW
= NULL
;
102 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
103 debugstr_a(MachineName
), Reserved
);
107 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
108 if (MachineNameW
== NULL
)
109 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
112 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
113 MachineNameW
, Reserved
);
115 MyFree(MachineNameW
);
121 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
125 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
126 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
127 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
128 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
129 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
130 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
131 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
132 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
133 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
134 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
135 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
136 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
137 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
138 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
139 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
140 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
141 case CR_SUCCESS
: return ERROR_SUCCESS
;
142 default: return ERROR_GEN_FAILURE
;
145 /* Does not happen */
148 /***********************************************************************
149 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
151 * Create an empty DeviceInfoSet list.
154 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
156 * hwndParent [I] hwnd needed for interface related actions.
157 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
158 * local regestry will be used.
159 * Reserved [I] must be NULL
162 * Success: empty list.
163 * Failure: INVALID_HANDLE_VALUE.
166 SetupDiCreateDeviceInfoListExW(
167 IN CONST GUID
*ClassGuid OPTIONAL
,
168 IN HWND hwndParent OPTIONAL
,
169 IN PCWSTR MachineName OPTIONAL
,
172 struct DeviceInfoSet
*list
;
173 LPWSTR UNCServerName
= NULL
;
177 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
179 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
180 debugstr_w(MachineName
), Reserved
);
182 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
184 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
185 list
= MyMalloc(size
);
188 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
191 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
193 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
196 ClassGuid
? ClassGuid
: &GUID_NULL
,
197 sizeof(list
->ClassGuid
));
198 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
199 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
200 list
->InstallParams
.hwndParent
= hwndParent
;
203 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
204 if (rc
!= ERROR_SUCCESS
)
209 UNCServerName
= MyMalloc((strlenW(MachineName
) + 3) * sizeof(WCHAR
));
212 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
216 UNCServerName
[0] = UNCServerName
[1] = '\\';
217 strcpyW(UNCServerName
+ 2, MachineName
);
218 list
->szData
[0] = list
->szData
[1] = '\\';
219 strcpyW(list
->szData
+ 2, MachineName
);
220 list
->MachineName
= list
->szData
;
224 list
->HKLM
= HKEY_LOCAL_MACHINE
;
225 list
->MachineName
= NULL
;
227 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
228 if (cr
!= CR_SUCCESS
)
230 SetLastError(GetErrorCodeFromCrCode(cr
));
233 InitializeListHead(&list
->DriverListHead
);
234 InitializeListHead(&list
->ListHead
);
236 ret
= (HDEVINFO
)list
;
239 if (ret
== INVALID_HANDLE_VALUE
)
243 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
244 RegCloseKey(list
->HKLM
);
248 MyFree(UNCServerName
);
252 /***********************************************************************
253 * SetupDiEnumDeviceInfo (SETUPAPI.@)
256 SetupDiEnumDeviceInfo(
257 IN HDEVINFO DeviceInfoSet
,
258 IN DWORD MemberIndex
,
259 OUT PSP_DEVINFO_DATA DeviceInfoData
)
263 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
265 SetLastError(ERROR_INVALID_PARAMETER
);
266 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
268 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
270 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
271 SetLastError(ERROR_INVALID_HANDLE
);
272 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
273 SetLastError(ERROR_INVALID_USER_BUFFER
);
276 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
277 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
278 ItemList
= ItemList
->Flink
;
279 if (ItemList
== &list
->ListHead
)
280 SetLastError(ERROR_NO_MORE_ITEMS
);
283 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
284 memcpy(&DeviceInfoData
->ClassGuid
,
287 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
288 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
294 SetLastError(ERROR_INVALID_HANDLE
);
298 /***********************************************************************
299 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
302 SetupDiGetActualSectionToInstallA(
304 IN PCSTR InfSectionName
,
305 OUT PSTR InfSectionWithExt OPTIONAL
,
306 IN DWORD InfSectionWithExtSize
,
307 OUT PDWORD RequiredSize OPTIONAL
,
308 OUT PSTR
*Extension OPTIONAL
)
310 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
311 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
315 /***********************************************************************
316 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
319 SetupDiGetActualSectionToInstallW(
321 IN PCWSTR InfSectionName
,
322 OUT PWSTR InfSectionWithExt OPTIONAL
,
323 IN DWORD InfSectionWithExtSize
,
324 OUT PDWORD RequiredSize OPTIONAL
,
325 OUT PWSTR
*Extension OPTIONAL
)
327 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
328 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
332 /***********************************************************************
333 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
336 SetupDiGetActualSectionToInstallExA(
338 IN PCSTR InfSectionName
,
339 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
340 OUT PSTR InfSectionWithExt OPTIONAL
,
341 IN DWORD InfSectionWithExtSize
,
342 OUT PDWORD RequiredSize OPTIONAL
,
343 OUT PSTR
* Extension OPTIONAL
,
346 LPWSTR InfSectionNameW
= NULL
;
347 LPWSTR InfSectionWithExtW
= NULL
;
349 BOOL bResult
= FALSE
;
355 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
356 if (InfSectionNameW
== NULL
)
359 if (InfSectionWithExt
)
361 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
362 if (InfSectionWithExtW
== NULL
)
366 bResult
= SetupDiGetActualSectionToInstallExW(
367 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
368 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
369 InfSectionWithExtSize
,
371 Extension
? &ExtensionW
: NULL
,
374 if (bResult
&& InfSectionWithExt
)
376 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
377 InfSectionWithExtSize
, NULL
, NULL
) != 0;
379 if (bResult
&& Extension
)
381 if (ExtensionW
== NULL
)
384 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
388 MyFree(InfSectionNameW
);
389 MyFree(InfSectionWithExtW
);
394 /* Lower scores are best ones */
397 IN LPCWSTR SectionName
,
398 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
401 OUT PDWORD ScorePlatform
,
402 OUT PDWORD ScoreMajorVersion
,
403 OUT PDWORD ScoreMinorVersion
,
404 OUT PDWORD ScoreProductType
,
405 OUT PDWORD ScoreSuiteMask
)
407 LPWSTR Section
= NULL
;
408 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
413 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
414 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
415 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
417 static const WCHAR ExtensionArchitectureNone
[] = {0};
418 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
419 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
420 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
421 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
422 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
423 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
425 TRACE("%s %p 0x%x 0x%x\n",
426 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
428 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
430 Section
= DuplicateString(SectionName
);
433 TRACE("DuplicateString() failed\n");
437 /* Set various extensions values */
438 switch (PlatformInfo
->Platform
)
440 case VER_PLATFORM_WIN32_WINDOWS
:
441 pExtensionPlatform
= ExtensionPlatformWindows
;
443 case VER_PLATFORM_WIN32_NT
:
444 pExtensionPlatform
= ExtensionPlatformNT
;
447 ERR("Unkown platform 0x%lx\n", PlatformInfo
->Platform
);
448 pExtensionPlatform
= ExtensionPlatformNone
;
451 switch (PlatformInfo
->ProcessorArchitecture
)
453 case PROCESSOR_ARCHITECTURE_ALPHA
:
454 pExtensionArchitecture
= ExtensionArchitecturealpha
;
456 case PROCESSOR_ARCHITECTURE_AMD64
:
457 pExtensionArchitecture
= ExtensionArchitectureamd64
;
459 case PROCESSOR_ARCHITECTURE_IA64
:
460 pExtensionArchitecture
= ExtensionArchitectureia64
;
462 case PROCESSOR_ARCHITECTURE_INTEL
:
463 pExtensionArchitecture
= ExtensionArchitecturex86
;
465 case PROCESSOR_ARCHITECTURE_MIPS
:
466 pExtensionArchitecture
= ExtensionArchitecturemips
;
468 case PROCESSOR_ARCHITECTURE_PPC
:
469 pExtensionArchitecture
= ExtensionArchitectureppc
;
472 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
473 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
474 pExtensionArchitecture
= ExtensionArchitectureNone
;
480 * Field[1] Architecture
481 * Field[2] Major version
482 * Field[3] Minor version
483 * Field[4] Product type
484 * Field[5] Suite mask
485 * Remark: lastests fields may be NULL if the information is not provided
488 if (Fields
[0] == NULL
)
490 TRACE("No extension found\n");
491 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
495 Fields
[1] = Fields
[0] + 1;
496 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
497 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
499 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
503 *(Fields
[i
] - 1) = L
'\0';
506 /* Take care of first 2 fields */
507 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
509 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
511 TRACE("Mismatch on platform field\n");
514 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
516 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
518 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
520 TRACE("Mismatch on platform field\n");
523 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
527 /* No platform specified */
528 *ScorePlatform
|= 0x02;
530 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
532 /* No architecture specified */
533 *ScorePlatform
|= 0x01;
535 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
537 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
538 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
542 /* Check if informations are matching */
543 if (Fields
[2] && *Fields
[2])
545 DWORD MajorVersion
, MinorVersion
= 0;
546 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
547 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
548 (errno
== ERANGE
|| errno
== EINVAL
))
550 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
553 if (Fields
[3] && *Fields
[3])
555 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
556 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
557 (errno
== ERANGE
|| errno
== EINVAL
))
559 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
563 if (PlatformInfo
->MajorVersion
< MajorVersion
||
564 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
566 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
567 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
570 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
571 if (MajorVersion
== PlatformInfo
->MajorVersion
)
572 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
574 *ScoreMinorVersion
= MinorVersion
;
576 else if (Fields
[3] && *Fields
[3])
578 TRACE("Minor version found without major version\n");
583 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
584 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
587 if (Fields
[4] && *Fields
[4])
589 DWORD CurrentProductType
;
590 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
591 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
592 (errno
== ERANGE
|| errno
== EINVAL
))
594 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
597 if (CurrentProductType
!= ProductType
)
599 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
600 CurrentProductType
, ProductType
);
605 *ScoreProductType
= 1;
607 if (Fields
[5] && *Fields
[5])
609 DWORD CurrentSuiteMask
;
610 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
611 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
612 (errno
== ERANGE
|| errno
== EINVAL
))
614 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
617 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
619 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
620 CurrentSuiteMask
, SuiteMask
);
623 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
626 *ScoreSuiteMask
= SuiteMask
;
637 IN LPCWSTR SectionName
,
640 struct GetSectionCallbackInfo
*info
= Context
;
641 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
644 if (SectionName
[info
->PrefixLength
] != '.')
647 ret
= CheckSectionValid(
648 &SectionName
[info
->PrefixLength
],
652 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
655 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
658 if (Score1
> info
->BestScore1
) goto done
;
659 if (Score1
< info
->BestScore1
) goto bettersection
;
660 if (Score2
> info
->BestScore2
) goto done
;
661 if (Score2
< info
->BestScore2
) goto bettersection
;
662 if (Score3
> info
->BestScore3
) goto done
;
663 if (Score3
< info
->BestScore3
) goto bettersection
;
664 if (Score4
> info
->BestScore4
) goto done
;
665 if (Score4
< info
->BestScore4
) goto bettersection
;
666 if (Score5
> info
->BestScore5
) goto done
;
667 if (Score5
< info
->BestScore5
) goto bettersection
;
671 strcpyW(info
->BestSection
, SectionName
);
672 info
->BestScore1
= Score1
;
673 info
->BestScore2
= Score2
;
674 info
->BestScore3
= Score3
;
675 info
->BestScore4
= Score4
;
676 info
->BestScore5
= Score5
;
682 /***********************************************************************
683 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
686 SetupDiGetActualSectionToInstallExW(
688 IN PCWSTR InfSectionName
,
689 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
690 OUT PWSTR InfSectionWithExt OPTIONAL
,
691 IN DWORD InfSectionWithExtSize
,
692 OUT PDWORD RequiredSize OPTIONAL
,
693 OUT PWSTR
* Extension OPTIONAL
,
698 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
699 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
700 RequiredSize
, Extension
, Reserved
);
702 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
703 SetLastError(ERROR_INVALID_HANDLE
);
704 else if (!InfSectionName
)
705 SetLastError(ERROR_INVALID_PARAMETER
);
706 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
707 SetLastError(ERROR_INVALID_USER_BUFFER
);
708 else if (Reserved
!= NULL
)
709 SetLastError(ERROR_INVALID_PARAMETER
);
712 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
713 static BYTE CurrentProductType
= 0;
714 static WORD CurrentSuiteMask
= 0;
715 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
716 struct GetSectionCallbackInfo CallbackInfo
;
721 /* Fill platform info if needed */
722 if (AlternatePlatformInfo
)
724 pPlatformInfo
= AlternatePlatformInfo
;
730 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
732 /* That's the first time we go here. We need to fill in the structure */
733 OSVERSIONINFOEX VersionInfo
;
734 SYSTEM_INFO SystemInfo
;
735 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
736 ret
= GetVersionEx((POSVERSIONINFO
)&VersionInfo
);
739 GetSystemInfo(&SystemInfo
);
740 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
741 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
742 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
743 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
744 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
745 CurrentPlatform
.Reserved
= 0;
746 CurrentProductType
= VersionInfo
.wProductType
;
747 CurrentSuiteMask
= VersionInfo
.wSuiteMask
;
749 ProductType
= CurrentProductType
;
750 SuiteMask
= CurrentSuiteMask
;
753 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
754 CallbackInfo
.ProductType
= ProductType
;
755 CallbackInfo
.SuiteMask
= SuiteMask
;
756 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
757 CallbackInfo
.BestScore1
= ULONG_MAX
;
758 CallbackInfo
.BestScore2
= ULONG_MAX
;
759 CallbackInfo
.BestScore3
= ULONG_MAX
;
760 CallbackInfo
.BestScore4
= ULONG_MAX
;
761 CallbackInfo
.BestScore5
= ULONG_MAX
;
762 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
763 if (!EnumerateSectionsStartingWith(
769 SetLastError(ERROR_GEN_FAILURE
);
773 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
774 if (RequiredSize
!= NULL
)
775 *RequiredSize
= dwFullLength
+ 1;
777 if (InfSectionWithExtSize
> 0)
779 if (InfSectionWithExtSize
< dwFullLength
+ 1)
781 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
784 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
787 DWORD dwLength
= lstrlenW(InfSectionName
);
788 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
796 TRACE("Returning %d\n", ret
);
802 CreateDeviceInfoElement(
803 IN
struct DeviceInfoSet
*list
,
804 IN LPCWSTR InstancePath
,
805 IN LPCGUID pClassGuid
,
806 OUT
struct DeviceInfoElement
**pDeviceInfo
)
810 struct DeviceInfoElement
*deviceInfo
;
814 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
815 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
818 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
821 ZeroMemory(deviceInfo
, size
);
823 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
824 if (cr
!= CR_SUCCESS
)
826 SetLastError(GetErrorCodeFromCrCode(cr
));
830 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
831 strcpyW(deviceInfo
->Data
, InstancePath
);
832 deviceInfo
->DeviceName
= deviceInfo
->Data
;
833 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
834 deviceInfo
->DeviceDescription
= NULL
;
835 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
836 deviceInfo
->CreationFlags
= 0;
837 InitializeListHead(&deviceInfo
->DriverListHead
);
838 InitializeListHead(&deviceInfo
->InterfaceListHead
);
840 *pDeviceInfo
= deviceInfo
;
846 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
848 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
849 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
854 DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
856 PLIST_ENTRY ListEntry
;
857 struct DriverInfoElement
*driverInfo
;
858 struct DeviceInterface
*deviceInterface
;
860 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
862 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
863 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
864 if (!DestroyDriverInfoElement(driverInfo
))
867 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
869 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
870 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
871 if (!DestroyDeviceInterface(deviceInterface
))
874 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
875 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
879 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
881 PLIST_ENTRY ListEntry
;
882 struct DeviceInfoElement
*deviceInfo
;
884 while (!IsListEmpty(&list
->ListHead
))
886 ListEntry
= RemoveHeadList(&list
->ListHead
);
887 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfoElement
, ListEntry
);
888 if (!DestroyDeviceInfoElement(deviceInfo
))
891 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
892 RegCloseKey(list
->HKLM
);
893 CM_Disconnect_Machine(list
->hMachine
);
894 DestroyClassInstallParams(&list
->ClassInstallParams
);
895 return HeapFree(GetProcessHeap(), 0, list
);
898 /***********************************************************************
899 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
902 SetupDiDestroyDeviceInfoList(
903 IN HDEVINFO DeviceInfoSet
)
907 TRACE("%p\n", DeviceInfoSet
);
908 if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
910 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
912 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
913 ret
= DestroyDeviceInfoSet(list
);
915 SetLastError(ERROR_INVALID_HANDLE
);
918 SetLastError(ERROR_INVALID_HANDLE
);
920 TRACE("Returning %d\n", ret
);
924 /***********************************************************************
925 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
928 SetupDiGetDeviceRegistryPropertyA(
929 IN HDEVINFO DeviceInfoSet
,
930 IN PSP_DEVINFO_DATA DeviceInfoData
,
932 OUT PDWORD PropertyRegDataType OPTIONAL
,
933 OUT PBYTE PropertyBuffer OPTIONAL
,
934 IN DWORD PropertyBufferSize
,
935 OUT PDWORD RequiredSize OPTIONAL
)
938 BOOL bIsStringProperty
;
940 DWORD RequiredSizeA
, RequiredSizeW
;
941 DWORD PropertyBufferSizeW
= 0;
942 PBYTE PropertyBufferW
= NULL
;
944 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
945 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
948 if (PropertyBufferSize
!= 0)
950 PropertyBufferSizeW
= PropertyBufferSize
* 2;
951 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
952 if (!PropertyBufferW
)
954 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
959 bResult
= SetupDiGetDeviceRegistryPropertyW(
968 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
970 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
972 if (bIsStringProperty
)
973 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
975 RequiredSizeA
= RequiredSizeW
;
977 *RequiredSize
= RequiredSizeA
;
978 if (PropertyRegDataType
)
979 *PropertyRegDataType
= RegType
;
984 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
988 if (RequiredSizeA
<= PropertyBufferSize
)
990 if (bIsStringProperty
&& PropertyBufferSize
> 0)
992 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
994 /* Last error is already set by WideCharToMultiByte */
999 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
1003 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1007 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
1011 /***********************************************************************
1012 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
1015 SetupDiGetDeviceRegistryPropertyW(
1016 IN HDEVINFO DeviceInfoSet
,
1017 IN PSP_DEVINFO_DATA DeviceInfoData
,
1019 OUT PDWORD PropertyRegDataType OPTIONAL
,
1020 OUT PBYTE PropertyBuffer OPTIONAL
,
1021 IN DWORD PropertyBufferSize
,
1022 OUT PDWORD RequiredSize OPTIONAL
)
1024 HKEY hEnumKey
, hKey
;
1028 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1029 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
1032 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1033 SetLastError(ERROR_INVALID_HANDLE
);
1034 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1035 SetLastError(ERROR_INVALID_HANDLE
);
1036 else if (!DeviceInfoData
)
1037 SetLastError(ERROR_INVALID_PARAMETER
);
1038 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1039 SetLastError(ERROR_INVALID_USER_BUFFER
);
1040 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
1041 SetLastError(ERROR_INVALID_PARAMETER
);
1044 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1045 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
1049 case SPDRP_CAPABILITIES
:
1051 case SPDRP_CLASSGUID
:
1052 case SPDRP_COMPATIBLEIDS
:
1053 case SPDRP_CONFIGFLAGS
:
1054 case SPDRP_DEVICEDESC
:
1056 case SPDRP_FRIENDLYNAME
:
1057 case SPDRP_HARDWAREID
:
1058 case SPDRP_LOCATION_INFORMATION
:
1059 case SPDRP_LOWERFILTERS
:
1061 case SPDRP_SECURITY
:
1063 case SPDRP_UI_NUMBER
:
1064 case SPDRP_UI_NUMBER_DESC_FORMAT
:
1065 case SPDRP_UPPERFILTERS
:
1067 LPCWSTR RegistryPropertyName
;
1072 case SPDRP_CAPABILITIES
:
1073 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
1075 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
1076 case SPDRP_CLASSGUID
:
1077 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
1078 case SPDRP_COMPATIBLEIDS
:
1079 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
1080 case SPDRP_CONFIGFLAGS
:
1081 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
1082 case SPDRP_DEVICEDESC
:
1083 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
1085 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
1086 case SPDRP_FRIENDLYNAME
:
1087 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
1088 case SPDRP_HARDWAREID
:
1089 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
1090 case SPDRP_LOCATION_INFORMATION
:
1091 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
1092 case SPDRP_LOWERFILTERS
:
1093 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
1095 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
1096 case SPDRP_SECURITY
:
1097 RegistryPropertyName
= REGSTR_SECURITY
; break;
1099 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
1100 case SPDRP_UI_NUMBER
:
1101 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
1102 case SPDRP_UI_NUMBER_DESC_FORMAT
:
1103 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
; break;
1104 case SPDRP_UPPERFILTERS
:
1105 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
1107 /* Should not happen */
1108 RegistryPropertyName
= NULL
; break;
1111 /* Open registry key name */
1114 REGSTR_PATH_SYSTEMENUM
,
1118 if (rc
!= ERROR_SUCCESS
)
1129 RegCloseKey(hEnumKey
);
1130 if (rc
!= ERROR_SUCCESS
)
1135 /* Read registry entry */
1136 BufferSize
= PropertyBufferSize
;
1137 rc
= RegQueryValueExW(
1139 RegistryPropertyName
,
1140 NULL
, /* Reserved */
1141 PropertyRegDataType
,
1145 *RequiredSize
= BufferSize
;
1148 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
1151 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1153 case ERROR_MORE_DATA
:
1154 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1163 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
1165 DWORD required
= (strlenW(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
1167 if (PropertyRegDataType
)
1168 *PropertyRegDataType
= REG_SZ
;
1170 *RequiredSize
= required
;
1171 if (PropertyBufferSize
>= required
)
1173 strcpyW((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
1177 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1181 /*case SPDRP_BUSTYPEGUID:
1182 case SPDRP_LEGACYBUSTYPE:
1183 case SPDRP_BUSNUMBER:
1184 case SPDRP_ENUMERATOR_NAME:
1185 case SPDRP_SECURITY_SDS:
1187 case SPDRP_EXCLUSIVE:
1188 case SPDRP_CHARACTERISTICS:
1190 case SPDRP_DEVICE_POWER_DATA:*/
1191 #if (WINVER >= 0x501)
1192 /*case SPDRP_REMOVAL_POLICY:
1193 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
1194 case SPDRP_REMOVAL_POLICY_OVERRIDE:
1195 case SPDRP_INSTALL_STATE:*/
1200 ERR("Property 0x%lx not implemented\n", Property
);
1201 SetLastError(ERROR_NOT_SUPPORTED
);
1206 TRACE("Returning %d\n", ret
);
1210 /***********************************************************************
1211 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
1214 SetupDiSetDeviceRegistryPropertyA(
1215 IN HDEVINFO DeviceInfoSet
,
1216 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
1218 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
1219 IN DWORD PropertyBufferSize
)
1221 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
1222 Property
, PropertyBuffer
, PropertyBufferSize
);
1223 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1227 /***********************************************************************
1228 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
1231 SetupDiSetDeviceRegistryPropertyW(
1232 IN HDEVINFO DeviceInfoSet
,
1233 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
1235 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
1236 IN DWORD PropertyBufferSize
)
1238 struct DeviceInfoSet
*list
;
1241 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
1242 Property
, PropertyBuffer
, PropertyBufferSize
);
1245 SetLastError(ERROR_INVALID_HANDLE
);
1246 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1247 SetLastError(ERROR_INVALID_HANDLE
);
1248 else if (!DeviceInfoData
)
1249 SetLastError(ERROR_INVALID_HANDLE
);
1250 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1251 SetLastError(ERROR_INVALID_USER_BUFFER
);
1256 case SPDRP_COMPATIBLEIDS
:
1257 case SPDRP_CONFIGFLAGS
:
1258 case SPDRP_FRIENDLYNAME
:
1259 case SPDRP_HARDWAREID
:
1260 case SPDRP_LOCATION_INFORMATION
:
1261 case SPDRP_LOWERFILTERS
:
1262 case SPDRP_SECURITY
:
1264 case SPDRP_UI_NUMBER_DESC_FORMAT
:
1265 case SPDRP_UPPERFILTERS
:
1267 LPCWSTR RegistryPropertyName
;
1268 DWORD RegistryDataType
;
1274 case SPDRP_COMPATIBLEIDS
:
1275 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
1276 RegistryDataType
= REG_MULTI_SZ
;
1278 case SPDRP_CONFIGFLAGS
:
1279 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
1280 RegistryDataType
= REG_DWORD
;
1282 case SPDRP_FRIENDLYNAME
:
1283 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
1284 RegistryDataType
= REG_SZ
;
1286 case SPDRP_HARDWAREID
:
1287 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
1288 RegistryDataType
= REG_MULTI_SZ
;
1290 case SPDRP_LOCATION_INFORMATION
:
1291 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
1292 RegistryDataType
= REG_SZ
;
1294 case SPDRP_LOWERFILTERS
:
1295 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
1296 RegistryDataType
= REG_MULTI_SZ
;
1298 case SPDRP_SECURITY
:
1299 RegistryPropertyName
= REGSTR_SECURITY
;
1300 RegistryDataType
= REG_BINARY
;
1303 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
1304 RegistryDataType
= REG_SZ
;
1306 case SPDRP_UI_NUMBER_DESC_FORMAT
:
1307 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
;
1308 RegistryDataType
= REG_SZ
;
1310 case SPDRP_UPPERFILTERS
:
1311 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
1312 RegistryDataType
= REG_MULTI_SZ
;
1315 /* Should not happen */
1316 RegistryPropertyName
= NULL
;
1317 RegistryDataType
= REG_BINARY
;
1320 /* Open device registry key */
1321 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
1322 if (hKey
!= INVALID_HANDLE_VALUE
)
1324 /* Write new data */
1325 rc
= RegSetValueExW(
1327 RegistryPropertyName
,
1331 PropertyBufferSize
);
1332 if (rc
== ERROR_SUCCESS
)
1341 /*case SPDRP_CHARACTERISTICS:
1343 case SPDRP_EXCLUSIVE:*/
1344 #if (WINVER >= 0x501)
1345 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
1347 //case SPDRP_SECURITY_SDS:
1351 ERR("Property 0x%lx not implemented\n", Property
);
1352 SetLastError(ERROR_NOT_SUPPORTED
);
1357 TRACE("Returning %d\n", ret
);
1363 IntSetupDiRegisterDeviceInfo(
1364 IN HDEVINFO DeviceInfoSet
,
1365 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
1367 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
1370 /***********************************************************************
1371 * SetupDiCallClassInstaller (SETUPAPI.@)
1374 SetupDiCallClassInstaller(
1375 IN DI_FUNCTION InstallFunction
,
1376 IN HDEVINFO DeviceInfoSet
,
1377 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
1381 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
1384 SetLastError(ERROR_INVALID_PARAMETER
);
1385 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1386 SetLastError(ERROR_INVALID_HANDLE
);
1387 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1388 SetLastError(ERROR_INVALID_HANDLE
);
1389 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
1390 SetLastError(ERROR_INVALID_HANDLE
);
1391 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1392 SetLastError(ERROR_INVALID_USER_BUFFER
);
1395 SP_DEVINSTALL_PARAMS_W InstallParams
;
1396 #define CLASS_COINSTALLER 0x1
1397 #define DEVICE_COINSTALLER 0x2
1398 #define CLASS_INSTALLER 0x4
1399 UCHAR CanHandle
= 0;
1400 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
1402 switch (InstallFunction
)
1404 case DIF_ADDPROPERTYPAGE_ADVANCED
:
1405 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1407 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
1408 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1410 case DIF_ALLOW_INSTALL
:
1411 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1414 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1416 case DIF_DESTROYPRIVATEDATA
:
1417 CanHandle
= CLASS_INSTALLER
;
1419 case DIF_INSTALLDEVICE
:
1420 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1421 DefaultHandler
= SetupDiInstallDevice
;
1423 case DIF_INSTALLDEVICEFILES
:
1424 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1425 DefaultHandler
= SetupDiInstallDriverFiles
;
1427 case DIF_INSTALLINTERFACES
:
1428 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1429 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
1431 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
1432 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1434 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
1435 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1437 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
1438 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1440 case DIF_NEWDEVICEWIZARD_PRESELECT
:
1441 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1443 case DIF_NEWDEVICEWIZARD_SELECT
:
1444 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1446 case DIF_POWERMESSAGEWAKE
:
1447 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1449 case DIF_PROPERTYCHANGE
:
1450 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1451 DefaultHandler
= SetupDiChangeState
;
1453 case DIF_REGISTER_COINSTALLERS
:
1454 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1455 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
1457 case DIF_REGISTERDEVICE
:
1458 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1459 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
1462 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1463 DefaultHandler
= SetupDiRemoveDevice
;
1465 case DIF_SELECTBESTCOMPATDRV
:
1466 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1467 DefaultHandler
= SetupDiSelectBestCompatDrv
;
1469 case DIF_SELECTDEVICE
:
1470 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1471 DefaultHandler
= SetupDiSelectDevice
;
1473 case DIF_TROUBLESHOOTER
:
1474 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1477 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1478 DefaultHandler
= SetupDiUnremoveDevice
;
1481 ERR("Install function %u not supported\n", InstallFunction
);
1482 SetLastError(ERROR_NOT_SUPPORTED
);
1485 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1486 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1487 /* Don't process this call, as a parameter is invalid */
1492 LIST_ENTRY ClassCoInstallersListHead
;
1493 LIST_ENTRY DeviceCoInstallersListHead
;
1494 HMODULE ClassInstallerLibrary
= NULL
;
1495 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
1496 COINSTALLER_CONTEXT_DATA Context
;
1497 PLIST_ENTRY ListEntry
;
1499 DWORD dwRegType
, dwLength
;
1500 DWORD rc
= NO_ERROR
;
1502 InitializeListHead(&ClassCoInstallersListHead
);
1503 InitializeListHead(&DeviceCoInstallersListHead
);
1505 if (CanHandle
& DEVICE_COINSTALLER
)
1507 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
1508 if (hKey
!= INVALID_HANDLE_VALUE
)
1510 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
1511 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
1513 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
1514 if (KeyBuffer
!= NULL
)
1516 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1517 if (rc
== ERROR_SUCCESS
)
1520 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1522 /* Add coinstaller to DeviceCoInstallersListHead list */
1523 struct CoInstallerElement
*coinstaller
;
1524 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
1525 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
1528 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
1529 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
1530 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
1532 HeapFree(GetProcessHeap(), 0, coinstaller
);
1535 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
1541 if (CanHandle
& CLASS_COINSTALLER
)
1545 REGSTR_PATH_CODEVICEINSTALLERS
,
1549 if (rc
== ERROR_SUCCESS
)
1551 LPWSTR lpGuidString
;
1552 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
1554 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
1555 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
1557 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
1558 if (KeyBuffer
!= NULL
)
1560 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1561 if (rc
== ERROR_SUCCESS
)
1564 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1566 /* Add coinstaller to ClassCoInstallersListHead list */
1567 struct CoInstallerElement
*coinstaller
;
1568 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
1569 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
1572 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
1573 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
1574 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
1576 HeapFree(GetProcessHeap(), 0, coinstaller
);
1579 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
1582 RpcStringFreeW(&lpGuidString
);
1587 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
1589 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
1590 if (hKey
!= INVALID_HANDLE_VALUE
)
1592 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
1593 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
1595 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
1596 if (KeyBuffer
!= NULL
)
1598 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1599 if (rc
== ERROR_SUCCESS
)
1601 /* Get ClassInstaller function pointer */
1602 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
1603 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
1605 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
1606 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1609 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
1616 /* Call Class co-installers */
1617 Context
.PostProcessing
= FALSE
;
1619 ListEntry
= ClassCoInstallersListHead
.Flink
;
1620 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
1622 struct CoInstallerElement
*coinstaller
;
1623 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
1624 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
1625 coinstaller
->PrivateData
= Context
.PrivateData
;
1626 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
1628 coinstaller
->DoPostProcessing
= TRUE
;
1631 ListEntry
= ListEntry
->Flink
;
1634 /* Call Device co-installers */
1635 ListEntry
= DeviceCoInstallersListHead
.Flink
;
1636 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
1638 struct CoInstallerElement
*coinstaller
;
1639 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
1640 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
1641 coinstaller
->PrivateData
= Context
.PrivateData
;
1642 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
1644 coinstaller
->DoPostProcessing
= TRUE
;
1647 ListEntry
= ListEntry
->Flink
;
1650 /* Call Class installer */
1653 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
1654 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
1657 rc
= ERROR_DI_DO_DEFAULT
;
1659 /* Call default handler */
1660 if (rc
== ERROR_DI_DO_DEFAULT
)
1662 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
1664 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
1667 rc
= GetLastError();
1673 /* Call Class co-installers that required postprocessing */
1674 Context
.PostProcessing
= TRUE
;
1675 ListEntry
= ClassCoInstallersListHead
.Flink
;
1676 while (ListEntry
!= &ClassCoInstallersListHead
)
1678 struct CoInstallerElement
*coinstaller
;
1679 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
1680 if (coinstaller
->DoPostProcessing
)
1682 Context
.InstallResult
= rc
;
1683 Context
.PrivateData
= coinstaller
->PrivateData
;
1684 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
1686 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
1687 ListEntry
= ListEntry
->Flink
;
1690 /* Call Device co-installers that required postprocessing */
1691 ListEntry
= DeviceCoInstallersListHead
.Flink
;
1692 while (ListEntry
!= &DeviceCoInstallersListHead
)
1694 struct CoInstallerElement
*coinstaller
;
1695 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
1696 if (coinstaller
->DoPostProcessing
)
1698 Context
.InstallResult
= rc
;
1699 Context
.PrivateData
= coinstaller
->PrivateData
;
1700 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
1702 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
1703 ListEntry
= ListEntry
->Flink
;
1706 /* Free allocated memory */
1707 while (!IsListEmpty(&ClassCoInstallersListHead
))
1709 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
1710 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
1712 while (!IsListEmpty(&DeviceCoInstallersListHead
))
1714 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
1715 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
1718 ret
= (rc
== NO_ERROR
);
1722 TRACE("Returning %d\n", ret
);
1726 /***********************************************************************
1727 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
1730 SetupDiGetDeviceInfoListClass(
1731 IN HDEVINFO DeviceInfoSet
,
1732 OUT LPGUID ClassGuid
)
1734 struct DeviceInfoSet
*list
;
1737 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
1740 SetLastError(ERROR_INVALID_HANDLE
);
1741 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1742 SetLastError(ERROR_INVALID_HANDLE
);
1743 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1744 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
1747 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
1752 TRACE("Returning %d\n", ret
);
1756 /***********************************************************************
1757 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
1760 SetupDiGetDeviceInfoListDetailW(
1761 IN HDEVINFO DeviceInfoSet
,
1762 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
1764 struct DeviceInfoSet
*list
;
1767 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
1770 SetLastError(ERROR_INVALID_HANDLE
);
1771 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1772 SetLastError(ERROR_INVALID_HANDLE
);
1773 else if (!DeviceInfoListDetailData
)
1774 SetLastError(ERROR_INVALID_PARAMETER
);
1775 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
1776 SetLastError(ERROR_INVALID_USER_BUFFER
);
1780 &DeviceInfoListDetailData
->ClassGuid
,
1783 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
1784 if (list
->MachineName
)
1785 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
1787 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
1792 TRACE("Returning %d\n", ret
);
1796 /***********************************************************************
1797 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1800 SetupDiGetDeviceInstallParamsA(
1801 IN HDEVINFO DeviceInfoSet
,
1802 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1803 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
1805 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
1808 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
1810 if (DeviceInstallParams
== NULL
)
1811 SetLastError(ERROR_INVALID_PARAMETER
);
1812 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
1813 SetLastError(ERROR_INVALID_USER_BUFFER
);
1816 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1817 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
1821 /* Do W->A conversion */
1823 DeviceInstallParams
,
1824 &deviceInstallParamsW
,
1825 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
1826 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
1827 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
1829 DeviceInstallParams
->DriverPath
[0] = '\0';
1835 TRACE("Returning %d\n", ret
);
1839 /***********************************************************************
1840 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
1843 SetupDiGetDeviceInstallParamsW(
1844 IN HDEVINFO DeviceInfoSet
,
1845 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1846 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
1848 struct DeviceInfoSet
*list
;
1851 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
1854 SetLastError(ERROR_INVALID_HANDLE
);
1855 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1856 SetLastError(ERROR_INVALID_HANDLE
);
1857 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1858 SetLastError(ERROR_INVALID_USER_BUFFER
);
1859 else if (!DeviceInstallParams
)
1860 SetLastError(ERROR_INVALID_PARAMETER
);
1861 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
1862 SetLastError(ERROR_INVALID_USER_BUFFER
);
1865 PSP_DEVINSTALL_PARAMS_W Source
;
1868 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
1870 Source
= &list
->InstallParams
;
1871 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
1875 TRACE("Returning %d\n", ret
);
1880 CheckDeviceInstallParameters(
1881 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
1883 DWORD SupportedFlags
=
1884 DI_NOVCP
| /* 0x00000008 */
1885 DI_DIDCOMPAT
| /* 0x00000010 */
1886 DI_DIDCLASS
| /* 0x00000020 */
1887 DI_NEEDRESTART
| /* 0x00000080 */
1888 DI_NEEDREBOOT
| /* 0x00000100 */
1889 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
1890 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
1891 DI_ENUMSINGLEINF
| /* 0x00010000 */
1892 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
1893 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
1894 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
1895 DI_QUIETINSTALL
| /* 0x00800000 */
1896 DI_NOFILECOPY
| /* 0x01000000 */
1897 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
1898 DWORD SupportedFlagsEx
=
1899 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
1900 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
1901 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
1902 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
1903 DI_FLAGSEX_NO_DRVREG_MODIFY
| /* 0x00008000 */
1904 DI_FLAGSEX_INSTALLEDDRIVER
; /* 0x04000000 */
1907 /* FIXME: add support for more flags */
1909 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
1910 * It should be checked before accessing to other values
1911 * of the SP_DEVINSTALL_PARAMS structure */
1913 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
1915 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
1916 SetLastError(ERROR_INVALID_FLAGS
);
1918 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
1920 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
1921 SetLastError(ERROR_INVALID_FLAGS
);
1923 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
1924 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
1925 SetLastError(ERROR_INVALID_USER_BUFFER
);
1928 /* FIXME: check Reserved field */
1935 /***********************************************************************
1936 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
1939 SetupDiSetDeviceInstallParamsW(
1940 IN HDEVINFO DeviceInfoSet
,
1941 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1942 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
1944 struct DeviceInfoSet
*list
;
1947 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
1950 SetLastError(ERROR_INVALID_HANDLE
);
1951 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1952 SetLastError(ERROR_INVALID_HANDLE
);
1953 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1954 SetLastError(ERROR_INVALID_USER_BUFFER
);
1955 else if (!DeviceInstallParams
)
1956 SetLastError(ERROR_INVALID_PARAMETER
);
1957 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
1958 SetLastError(ERROR_INVALID_USER_BUFFER
);
1959 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
1961 PSP_DEVINSTALL_PARAMS_W Destination
;
1964 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
1966 Destination
= &list
->InstallParams
;
1967 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
1971 TRACE("Returning %d\n", ret
);
1975 /***********************************************************************
1976 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
1979 SetupDiGetDeviceInstanceIdA(
1980 IN HDEVINFO DeviceInfoSet
,
1981 IN PSP_DEVINFO_DATA DeviceInfoData
,
1982 OUT PSTR DeviceInstanceId OPTIONAL
,
1983 IN DWORD DeviceInstanceIdSize
,
1984 OUT PDWORD RequiredSize OPTIONAL
)
1986 PWSTR DeviceInstanceIdW
= NULL
;
1989 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
1990 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
1992 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1993 SetLastError(ERROR_INVALID_PARAMETER
);
1996 if (DeviceInstanceIdSize
!= 0)
1998 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
1999 if (DeviceInstanceIdW
== NULL
)
2003 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
2004 DeviceInstanceIdW
, DeviceInstanceIdSize
,
2007 if (ret
&& DeviceInstanceIdW
!= NULL
)
2009 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
2010 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
2012 DeviceInstanceId
[0] = '\0';
2018 TRACE("Returning %d\n", ret
);
2022 /***********************************************************************
2023 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
2026 SetupDiGetDeviceInstanceIdW(
2027 IN HDEVINFO DeviceInfoSet
,
2028 IN PSP_DEVINFO_DATA DeviceInfoData
,
2029 OUT PWSTR DeviceInstanceId OPTIONAL
,
2030 IN DWORD DeviceInstanceIdSize
,
2031 OUT PDWORD RequiredSize OPTIONAL
)
2035 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
2036 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
2039 SetLastError(ERROR_INVALID_HANDLE
);
2040 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2041 SetLastError(ERROR_INVALID_HANDLE
);
2042 else if (!DeviceInfoData
)
2043 SetLastError(ERROR_INVALID_PARAMETER
);
2044 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2045 SetLastError(ERROR_INVALID_USER_BUFFER
);
2046 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
2047 SetLastError(ERROR_INVALID_PARAMETER
);
2048 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
2049 SetLastError(ERROR_INVALID_PARAMETER
);
2052 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2055 required
= (strlenW(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
2057 *RequiredSize
= required
;
2059 if (required
<= DeviceInstanceIdSize
)
2061 strcpyW(DeviceInstanceId
, DevInfo
->DeviceName
);
2065 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2068 TRACE("Returning %d\n", ret
);
2073 /***********************************************************************
2074 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
2077 SetupDiCreateDevRegKeyA(
2078 IN HDEVINFO DeviceInfoSet
,
2079 IN PSP_DEVINFO_DATA DeviceInfoData
,
2083 IN HINF InfHandle OPTIONAL
,
2084 IN PCSTR InfSectionName OPTIONAL
)
2086 PCWSTR InfSectionNameW
= NULL
;
2087 HKEY ret
= INVALID_HANDLE_VALUE
;
2091 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
2092 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
2095 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
2103 if (InfSectionNameW
!= NULL
)
2104 MyFree((PVOID
)InfSectionNameW
);
2110 OpenHardwareProfileKey(
2113 IN DWORD samDesired
)
2115 HKEY hHWProfilesKey
= NULL
;
2116 HKEY hHWProfileKey
= NULL
;
2117 HKEY ret
= INVALID_HANDLE_VALUE
;
2120 rc
= RegOpenKeyExW(HKLM
,
2121 REGSTR_PATH_HWPROFILES
,
2125 if (rc
!= ERROR_SUCCESS
)
2142 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
2151 if (rc
!= ERROR_SUCCESS
)
2156 ret
= hHWProfileKey
;
2159 if (hHWProfilesKey
!= NULL
)
2160 RegCloseKey(hHWProfilesKey
);
2161 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
2162 RegCloseKey(hHWProfileKey
);
2166 /***********************************************************************
2167 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
2170 SetupDiCreateDevRegKeyW(
2171 IN HDEVINFO DeviceInfoSet
,
2172 IN PSP_DEVINFO_DATA DeviceInfoData
,
2176 IN HINF InfHandle OPTIONAL
,
2177 IN PCWSTR InfSectionName OPTIONAL
)
2179 struct DeviceInfoSet
*list
;
2180 HKEY ret
= INVALID_HANDLE_VALUE
;
2182 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
2183 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
2186 SetLastError(ERROR_INVALID_HANDLE
);
2187 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2188 SetLastError(ERROR_INVALID_HANDLE
);
2189 else if (!DeviceInfoData
)
2190 SetLastError(ERROR_INVALID_PARAMETER
);
2191 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2192 SetLastError(ERROR_INVALID_USER_BUFFER
);
2193 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
2194 SetLastError(ERROR_INVALID_PARAMETER
);
2195 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
2196 SetLastError(ERROR_INVALID_PARAMETER
);
2197 else if (InfHandle
&& !InfSectionName
)
2198 SetLastError(ERROR_INVALID_PARAMETER
);
2199 else if (!InfHandle
&& InfSectionName
)
2200 SetLastError(ERROR_INVALID_PARAMETER
);
2203 LPWSTR lpGuidString
= NULL
;
2204 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
2205 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
2206 DWORD Index
; /* Index used in the DriverKey name */
2208 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
2209 HKEY hEnumKey
= NULL
;
2210 HKEY hClassKey
= NULL
;
2211 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
2215 if (Scope
== DICS_FLAG_GLOBAL
)
2216 RootKey
= list
->HKLM
;
2217 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
2219 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
2220 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
2222 RootKey
= hHWProfileKey
;
2225 if (KeyType
== DIREG_DEV
)
2227 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2229 rc
= RegCreateKeyExW(
2231 REGSTR_PATH_SYSTEMENUM
,
2234 REG_OPTION_NON_VOLATILE
,
2239 if (rc
!= ERROR_SUCCESS
)
2244 rc
= RegCreateKeyExW(
2246 deviceInfo
->DeviceName
,
2249 REG_OPTION_NON_VOLATILE
,
2250 #if _WIN32_WINNT >= 0x502
2251 KEY_READ
| KEY_WRITE
,
2258 if (rc
!= ERROR_SUCCESS
)
2264 else /* KeyType == DIREG_DRV */
2266 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2268 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
2269 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
2272 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2276 strcpyW(&DriverKey
[1], lpGuidString
);
2277 strcatW(DriverKey
, L
"}\\");
2278 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
2279 rc
= RegOpenKeyExW(RootKey
,
2280 REGSTR_PATH_CLASS_NT
,
2284 if (rc
!= ERROR_SUCCESS
)
2290 /* Try all values for Index between 0 and 9999 */
2292 while (Index
<= 9999)
2295 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
2296 rc
= RegCreateKeyEx(hClassKey
,
2300 REG_OPTION_NON_VOLATILE
,
2301 #if _WIN32_WINNT >= 0x502
2302 KEY_READ
| KEY_WRITE
,
2309 if (rc
!= ERROR_SUCCESS
)
2314 if (Disposition
== REG_CREATED_NEW_KEY
)
2322 /* Unable to create more than 9999 devices within the same class */
2323 SetLastError(ERROR_GEN_FAILURE
);
2327 /* Open device key, to write Driver value */
2328 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
2329 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
2331 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
2332 if (rc
!= ERROR_SUCCESS
)
2339 /* Do installation of the specified section */
2342 FIXME("Need to install section %s in file %p\n",
2343 debugstr_w(InfSectionName
), InfHandle
);
2349 RpcStringFreeW(&lpGuidString
);
2350 HeapFree(GetProcessHeap(), 0, DriverKey
);
2351 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
2352 RegCloseKey(hHWProfileKey
);
2353 if (hEnumKey
!= NULL
)
2354 RegCloseKey(hEnumKey
);
2355 if (hClassKey
!= NULL
)
2356 RegCloseKey(hClassKey
);
2357 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
2358 RegCloseKey(hDeviceKey
);
2359 if (hKey
!= NULL
&& hKey
!= ret
)
2363 TRACE("Returning 0x%p\n", ret
);
2367 /***********************************************************************
2368 * SetupDiOpenDevRegKey (SETUPAPI.@)
2371 SetupDiOpenDevRegKey(
2372 IN HDEVINFO DeviceInfoSet
,
2373 IN PSP_DEVINFO_DATA DeviceInfoData
,
2377 IN REGSAM samDesired
)
2379 struct DeviceInfoSet
*list
;
2380 HKEY ret
= INVALID_HANDLE_VALUE
;
2382 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2383 Scope
, HwProfile
, KeyType
, samDesired
);
2386 SetLastError(ERROR_INVALID_HANDLE
);
2387 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2388 SetLastError(ERROR_INVALID_HANDLE
);
2389 else if (!DeviceInfoData
)
2390 SetLastError(ERROR_INVALID_PARAMETER
);
2391 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2392 SetLastError(ERROR_INVALID_USER_BUFFER
);
2393 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
2394 SetLastError(ERROR_INVALID_PARAMETER
);
2395 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
2396 SetLastError(ERROR_INVALID_PARAMETER
);
2399 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2400 LPWSTR DriverKey
= NULL
;
2404 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
2405 HKEY hEnumKey
= NULL
;
2409 if (Scope
== DICS_FLAG_GLOBAL
)
2410 RootKey
= list
->HKLM
;
2411 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
2413 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
2414 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
2416 RootKey
= hHWProfileKey
;
2421 REGSTR_PATH_SYSTEMENUM
,
2425 if (rc
!= ERROR_SUCCESS
)
2432 deviceInfo
->DeviceName
,
2434 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
2436 RegCloseKey(hEnumKey
);
2438 if (rc
!= ERROR_SUCCESS
)
2443 if (KeyType
== DIREG_DEV
)
2445 /* We're done. Just return the hKey handle */
2449 /* Read the 'Driver' key */
2450 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
2451 if (rc
!= ERROR_SUCCESS
)
2456 else if (dwRegType
!= REG_SZ
)
2458 SetLastError(ERROR_GEN_FAILURE
);
2461 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2464 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2467 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
2468 if (rc
!= ERROR_SUCCESS
)
2475 /* Need to open the driver key */
2478 REGSTR_PATH_CLASS_NT
,
2482 if (rc
!= ERROR_SUCCESS
)
2493 if (rc
!= ERROR_SUCCESS
)
2501 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
2502 RegCloseKey(hHWProfileKey
);
2503 if (hEnumKey
!= NULL
)
2504 RegCloseKey(hEnumKey
);
2505 if (hKey
!= NULL
&& hKey
!= ret
)
2509 TRACE("Returning 0x%p\n", ret
);
2513 /***********************************************************************
2514 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
2517 SetupDiCreateDeviceInfoA(
2518 IN HDEVINFO DeviceInfoSet
,
2519 IN PCSTR DeviceName
,
2520 IN CONST GUID
*ClassGuid
,
2521 IN PCSTR DeviceDescription OPTIONAL
,
2522 IN HWND hwndParent OPTIONAL
,
2523 IN DWORD CreationFlags
,
2524 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2526 LPWSTR DeviceNameW
= NULL
;
2527 LPWSTR DeviceDescriptionW
= NULL
;
2534 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
2535 if (DeviceNameW
== NULL
) return FALSE
;
2537 if (DeviceDescription
)
2539 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
2540 if (DeviceDescriptionW
== NULL
)
2542 if (DeviceNameW
) MyFree(DeviceNameW
);
2547 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
2548 ClassGuid
, DeviceDescriptionW
,
2549 hwndParent
, CreationFlags
,
2552 if (DeviceNameW
) MyFree(DeviceNameW
);
2553 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
2558 /***********************************************************************
2559 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
2562 SetupDiCreateDeviceInfoW(
2563 IN HDEVINFO DeviceInfoSet
,
2564 IN PCWSTR DeviceName
,
2565 IN CONST GUID
*ClassGuid
,
2566 IN PCWSTR DeviceDescription OPTIONAL
,
2567 IN HWND hwndParent OPTIONAL
,
2568 IN DWORD CreationFlags
,
2569 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2571 struct DeviceInfoSet
*list
;
2574 TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
2575 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
2576 hwndParent
, CreationFlags
, DeviceInfoData
);
2579 SetLastError(ERROR_INVALID_HANDLE
);
2580 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2581 SetLastError(ERROR_INVALID_HANDLE
);
2582 else if (!ClassGuid
)
2583 SetLastError(ERROR_INVALID_PARAMETER
);
2584 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
2585 SetLastError(ERROR_CLASS_MISMATCH
);
2586 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
2588 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
2589 SetLastError(ERROR_INVALID_FLAGS
);
2593 SP_DEVINFO_DATA DevInfo
;
2595 if (CreationFlags
& DICD_GENERATE_ID
)
2597 /* Generate a new unique ID for this device */
2598 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2599 FIXME("not implemented\n");
2603 /* Device name is fully qualified. Try to open it */
2606 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
2607 rc
= SetupDiOpenDeviceInfoW(
2610 NULL
, /* hwndParent */
2611 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
2616 /* SetupDiOpenDeviceInfoW has already added
2617 * the device info to the device info set
2619 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
2621 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
2623 struct DeviceInfoElement
*deviceInfo
;
2625 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
2627 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
2629 if (!DeviceInfoData
)
2633 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
2635 SetLastError(ERROR_INVALID_USER_BUFFER
);
2639 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
2640 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
2641 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
2650 TRACE("Returning %d\n", ret
);
2655 /***********************************************************************
2656 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
2659 SetupDiDeleteDeviceInfo(
2660 IN HDEVINFO DeviceInfoSet
,
2661 IN PSP_DEVINFO_DATA DeviceInfoData
)
2663 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2665 FIXME("not implemented\n");
2666 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2671 /***********************************************************************
2672 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
2675 SetupDiOpenDeviceInfoA(
2676 IN HDEVINFO DeviceInfoSet
,
2677 IN PCSTR DeviceInstanceId
,
2678 IN HWND hwndParent OPTIONAL
,
2680 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2682 LPWSTR DeviceInstanceIdW
= NULL
;
2685 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
2687 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
2688 if (DeviceInstanceIdW
== NULL
)
2691 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
2692 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
2694 MyFree(DeviceInstanceIdW
);
2700 /***********************************************************************
2701 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
2704 SetupDiOpenDeviceInfoW(
2705 IN HDEVINFO DeviceInfoSet
,
2706 IN PCWSTR DeviceInstanceId
,
2707 IN HWND hwndParent OPTIONAL
,
2709 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2711 struct DeviceInfoSet
*list
;
2712 HKEY hEnumKey
, hKey
= NULL
;
2716 TRACE("%p %s %p %lx %p\n",
2717 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
2718 hwndParent
, OpenFlags
, DeviceInfoData
);
2720 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
2721 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
2724 SetLastError(ERROR_INVALID_HANDLE
);
2725 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2726 SetLastError(ERROR_INVALID_HANDLE
);
2727 else if (!DeviceInstanceId
)
2728 SetLastError(ERROR_INVALID_PARAMETER
);
2729 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
2731 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
2732 SetLastError(ERROR_INVALID_FLAGS
);
2734 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2735 SetLastError(ERROR_INVALID_USER_BUFFER
);
2738 struct DeviceInfoElement
*deviceInfo
= NULL
;
2739 /* Search if device already exists in DeviceInfoSet.
2740 * If yes, return the existing element
2741 * If no, create a new element using informations in registry
2743 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2744 while (ItemList
!= &list
->ListHead
)
2749 FIXME("not implemented\n");
2750 ItemList
= ItemList
->Flink
;
2755 /* good one found */
2760 /* Open supposed registry key */
2763 REGSTR_PATH_SYSTEMENUM
,
2767 if (rc
!= ERROR_SUCCESS
)
2778 RegCloseKey(hEnumKey
);
2779 if (rc
!= ERROR_SUCCESS
)
2781 if (rc
== ERROR_FILE_NOT_FOUND
)
2782 rc
= ERROR_NO_SUCH_DEVINST
;
2787 /* FIXME: try to get ClassGUID from registry, instead of
2788 * sending GUID_NULL to CreateDeviceInfoElement
2790 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
2792 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
2797 if (ret
&& deviceInfo
&& DeviceInfoData
)
2799 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
2800 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
2801 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
2812 /***********************************************************************
2813 * SetupDiGetSelectedDevice (SETUPAPI.@)
2816 SetupDiGetSelectedDevice(
2817 IN HDEVINFO DeviceInfoSet
,
2818 OUT PSP_DEVINFO_DATA DeviceInfoData
)
2820 struct DeviceInfoSet
*list
;
2823 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2826 SetLastError(ERROR_INVALID_HANDLE
);
2827 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2828 SetLastError(ERROR_INVALID_HANDLE
);
2829 else if (list
->SelectedDevice
== NULL
)
2830 SetLastError(ERROR_NO_DEVICE_SELECTED
);
2831 else if (!DeviceInfoData
)
2832 SetLastError(ERROR_INVALID_PARAMETER
);
2833 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2834 SetLastError(ERROR_INVALID_USER_BUFFER
);
2837 memcpy(&DeviceInfoData
->ClassGuid
,
2838 &list
->SelectedDevice
->ClassGuid
,
2840 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
2841 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
2845 TRACE("Returning %d\n", ret
);
2850 /***********************************************************************
2851 * SetupDiSetSelectedDevice (SETUPAPI.@)
2854 SetupDiSetSelectedDevice(
2855 IN HDEVINFO DeviceInfoSet
,
2856 IN PSP_DEVINFO_DATA DeviceInfoData
)
2858 struct DeviceInfoSet
*list
;
2861 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2864 SetLastError(ERROR_INVALID_HANDLE
);
2865 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2866 SetLastError(ERROR_INVALID_HANDLE
);
2867 else if (!DeviceInfoData
)
2868 SetLastError(ERROR_INVALID_PARAMETER
);
2869 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2870 SetLastError(ERROR_INVALID_USER_BUFFER
);
2871 else if (DeviceInfoData
->Reserved
== 0)
2872 SetLastError(ERROR_INVALID_USER_BUFFER
);
2875 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2879 TRACE("Returning %d\n", ret
);
2884 /* Return the current hardware profile id, or -1 if error */
2886 GetCurrentHwProfile(
2887 IN HDEVINFO DeviceInfoSet
)
2890 DWORD dwRegType
, dwLength
;
2893 DWORD ret
= (DWORD
)-1;
2896 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
2897 REGSTR_PATH_IDCONFIGDB
,
2901 if (rc
!= ERROR_SUCCESS
)
2907 dwLength
= sizeof(DWORD
);
2908 rc
= RegQueryValueExW(
2910 REGSTR_VAL_CURRENTCONFIG
,
2913 (LPBYTE
)&hwProfile
, &dwLength
);
2914 if (rc
!= ERROR_SUCCESS
)
2919 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
2921 SetLastError(ERROR_GEN_FAILURE
);
2936 IN HDEVINFO DeviceInfoSet
,
2937 IN PSP_DEVINFO_DATA DeviceInfoData
)
2940 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
2941 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2944 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2946 /* At the moment, I only know how to start local devices */
2947 SetLastError(ERROR_INVALID_COMPUTERNAME
);
2951 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
2952 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
2953 SetLastError(RtlNtStatusToDosError(Status
));
2954 return NT_SUCCESS(Status
);
2956 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
2961 static BOOL
StopDevice(
2962 IN HDEVINFO DeviceInfoSet
,
2963 IN PSP_DEVINFO_DATA DeviceInfoData
)
2965 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
2969 /***********************************************************************
2970 * SetupDiChangeState (SETUPAPI.@)
2974 IN HDEVINFO DeviceInfoSet
,
2975 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
2977 PSP_PROPCHANGE_PARAMS PropChange
;
2978 HKEY hKey
= INVALID_HANDLE_VALUE
;
2979 LPCWSTR RegistryValueName
;
2980 DWORD dwConfigFlags
, dwLength
, dwRegType
;
2984 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2986 if (!DeviceInfoData
)
2987 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChangeParams
;
2989 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChangeParams
;
2992 SetLastError(ERROR_INVALID_PARAMETER
);
2996 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
2997 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
2999 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
3001 switch (PropChange
->StateChange
)
3006 /* Enable/disable device in registry */
3007 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
3008 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3009 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
3010 if (hKey
== INVALID_HANDLE_VALUE
)
3012 dwLength
= sizeof(DWORD
);
3013 rc
= RegQueryValueExW(
3018 (LPBYTE
)&dwConfigFlags
, &dwLength
);
3019 if (rc
== ERROR_FILE_NOT_FOUND
)
3021 else if (rc
!= ERROR_SUCCESS
)
3026 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
3028 SetLastError(ERROR_GEN_FAILURE
);
3031 if (PropChange
->StateChange
== DICS_ENABLE
)
3032 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
3034 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
3040 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
3041 if (rc
!= ERROR_SUCCESS
)
3047 /* Enable/disable device if needed */
3048 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
3049 || PropChange
->HwProfile
== 0
3050 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
3052 if (PropChange
->StateChange
== DICS_ENABLE
)
3053 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
3055 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
3061 case DICS_PROPCHANGE
:
3063 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
3068 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
3069 SetLastError(ERROR_NOT_SUPPORTED
);
3074 if (hKey
!= INVALID_HANDLE_VALUE
)
3077 TRACE("Returning %d\n", ret
);
3081 /***********************************************************************
3082 * SetupDiSelectDevice (SETUPAPI.@)
3085 SetupDiSelectDevice(
3086 IN HDEVINFO DeviceInfoSet
,
3087 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3089 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3090 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3095 /***********************************************************************
3096 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
3099 SetupDiRegisterCoDeviceInstallers(
3100 IN HDEVINFO DeviceInfoSet
,
3101 IN PSP_DEVINFO_DATA DeviceInfoData
)
3103 BOOL ret
= FALSE
; /* Return value */
3105 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3108 SetLastError(ERROR_INVALID_PARAMETER
);
3109 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3110 SetLastError(ERROR_INVALID_HANDLE
);
3111 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3112 SetLastError(ERROR_INVALID_HANDLE
);
3113 else if (!DeviceInfoData
)
3114 SetLastError(ERROR_INVALID_PARAMETER
);
3115 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3116 SetLastError(ERROR_INVALID_USER_BUFFER
);
3119 SP_DEVINSTALL_PARAMS_W InstallParams
;
3120 struct DriverInfoElement
*SelectedDriver
;
3123 WCHAR SectionName
[MAX_PATH
];
3124 DWORD SectionNameLength
= 0;
3125 HKEY hKey
= INVALID_HANDLE_VALUE
;
3126 PVOID Context
= NULL
;
3128 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3129 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3133 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
3134 if (SelectedDriver
== NULL
)
3136 SetLastError(ERROR_NO_DRIVER_SELECTED
);
3140 /* Get .CoInstallers section name */
3141 Result
= SetupDiGetActualSectionToInstallW(
3142 SelectedDriver
->InfFileDetails
->hInf
,
3143 SelectedDriver
->Details
.SectionName
,
3144 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
3145 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
3147 lstrcatW(SectionName
, DotCoInstallers
);
3149 /* Open/Create driver key information */
3150 #if _WIN32_WINNT >= 0x502
3151 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
3153 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
3155 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3156 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
3157 if (hKey
== INVALID_HANDLE_VALUE
)
3160 /* Install .CoInstallers section */
3161 DoAction
= SPINST_REGISTRY
;
3162 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
3164 DoAction
|= SPINST_FILES
;
3165 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
3169 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
3170 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
3171 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
3172 SetupDefaultQueueCallback
, Context
,
3173 DeviceInfoSet
, DeviceInfoData
);
3181 SetupTermDefaultQueueCallback(Context
);
3182 if (hKey
!= INVALID_HANDLE_VALUE
)
3186 TRACE("Returning %d\n", ret
);
3191 InfIsFromOEMLocation(
3193 OUT LPBOOL IsOEMLocation
)
3197 last
= strrchrW(FullName
, '\\');
3200 /* No directory specified */
3201 *IsOEMLocation
= FALSE
;
3208 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
3211 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3215 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
3216 if (ret
== 0 || ret
> MAX_PATH
)
3219 SetLastError(ERROR_GEN_FAILURE
);
3222 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
3223 strcatW(Windir
, BackSlash
);
3224 strcatW(Windir
, InfDirectory
);
3226 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
3228 /* The path is %SYSTEMROOT%\Inf */
3229 *IsOEMLocation
= FALSE
;
3233 /* The file is in another place */
3234 *IsOEMLocation
= TRUE
;
3241 /***********************************************************************
3242 * SetupDiInstallDevice (SETUPAPI.@)
3245 SetupDiInstallDevice(
3246 IN HDEVINFO DeviceInfoSet
,
3247 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3249 SP_DEVINSTALL_PARAMS_W InstallParams
;
3250 struct DriverInfoElement
*SelectedDriver
;
3251 SYSTEMTIME DriverDate
;
3252 WCHAR SectionName
[MAX_PATH
];
3254 DWORD SectionNameLength
= 0;
3255 BOOL Result
= FALSE
;
3258 LPWSTR pSectionName
= NULL
;
3259 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
3261 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
3262 BOOL RebootRequired
= FALSE
;
3263 HKEY hKey
= INVALID_HANDLE_VALUE
;
3264 BOOL NeedtoCopyFile
;
3265 LARGE_INTEGER fullVersion
;
3267 PVOID Context
= NULL
;
3268 BOOL ret
= FALSE
; /* Return value */
3270 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3273 SetLastError(ERROR_INVALID_PARAMETER
);
3274 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3275 SetLastError(ERROR_INVALID_HANDLE
);
3276 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3277 SetLastError(ERROR_INVALID_HANDLE
);
3278 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3279 SetLastError(ERROR_INVALID_USER_BUFFER
);
3285 /* One parameter is bad */
3289 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3290 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3294 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
3296 /* Set FAILEDINSTALL in ConfigFlags registry value */
3297 DWORD ConfigFlags
, regType
;
3298 Result
= SetupDiGetDeviceRegistryPropertyW(
3303 (PBYTE
)&ConfigFlags
,
3304 sizeof(ConfigFlags
),
3306 if (!Result
|| regType
!= REG_DWORD
)
3308 SetLastError(ERROR_GEN_FAILURE
);
3311 ConfigFlags
|= DNF_DISABLED
;
3312 Result
= SetupDiSetDeviceRegistryPropertyW(
3316 (PBYTE
)&ConfigFlags
,
3317 sizeof(ConfigFlags
));
3320 SetLastError(ERROR_GEN_FAILURE
);
3328 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
3329 if (SelectedDriver
== NULL
)
3331 SetLastError(ERROR_NO_DRIVER_SELECTED
);
3335 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
3337 Result
= SetupDiGetActualSectionToInstallW(
3338 SelectedDriver
->InfFileDetails
->hInf
,
3339 SelectedDriver
->Details
.SectionName
,
3340 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
3341 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
3343 pSectionName
= &SectionName
[strlenW(SectionName
)];
3345 /* Get information from [Version] section */
3346 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
3348 /* Format ClassGuid to a string */
3349 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3351 RequiredSize
= lstrlenW(lpGuidString
);
3352 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
3353 if (!lpFullGuidString
)
3355 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3358 lpFullGuidString
[0] = '{';
3359 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
3360 lpFullGuidString
[RequiredSize
+ 1] = '}';
3361 lpFullGuidString
[RequiredSize
+ 2] = '\0';
3363 /* Copy .inf file to Inf\ directory (if needed) */
3364 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
3369 WCHAR NewFileName
[MAX_PATH
];
3370 struct InfFileDetails
*newInfFileDetails
;
3371 Result
= SetupCopyOEMInfW(
3372 SelectedDriver
->Details
.InfFileName
,
3375 SP_COPY_NOOVERWRITE
,
3376 NewFileName
, MAX_PATH
,
3381 /* Create a new struct InfFileDetails, and set it to
3382 * SelectedDriver->InfFileDetails, to release use of
3383 * current InfFile */
3384 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
3385 if (!newInfFileDetails
)
3387 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
3388 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
3389 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
3392 /* Open/Create driver key information */
3393 #if _WIN32_WINNT >= 0x502
3394 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
3396 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
3398 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3399 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
3400 if (hKey
== INVALID_HANDLE_VALUE
)
3403 /* Install main section */
3405 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
3406 DoAction
|= SPINST_REGISTRY
;
3407 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
3409 DoAction
|= SPINST_FILES
;
3410 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
3414 *pSectionName
= '\0';
3415 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
3416 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
3417 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
3418 SetupDefaultQueueCallback
, Context
,
3419 DeviceInfoSet
, DeviceInfoData
);
3422 InstallParams
.Flags
|= DI_NOFILECOPY
;
3423 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3425 /* Write information to driver key */
3426 *pSectionName
= UNICODE_NULL
;
3427 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
3428 TRACE("Write information to driver key\n");
3429 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
3430 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
3431 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
3432 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
3433 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
3434 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
3435 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
3436 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
3437 sprintfW(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
3438 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
3439 if (rc
== ERROR_SUCCESS
)
3440 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
3441 if (rc
== ERROR_SUCCESS
)
3442 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
3443 if (rc
== ERROR_SUCCESS
)
3445 sprintfW(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
3446 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
3448 if (rc
== ERROR_SUCCESS
)
3449 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
3450 if (rc
== ERROR_SUCCESS
)
3451 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
3452 if (rc
== ERROR_SUCCESS
)
3453 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
));
3454 if (rc
== ERROR_SUCCESS
)
3455 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
3456 if (rc
== ERROR_SUCCESS
)
3457 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
3458 if (rc
!= ERROR_SUCCESS
)
3464 hKey
= INVALID_HANDLE_VALUE
;
3466 /* FIXME: Process .LogConfigOverride section */
3468 /* Install .Services section */
3469 strcpyW(pSectionName
, DotServices
);
3470 Result
= SetupInstallServicesFromInfSectionExW(
3471 SelectedDriver
->InfFileDetails
->hInf
,
3480 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
3481 RebootRequired
= TRUE
;
3483 /* Open device registry key */
3484 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3485 if (hKey
== INVALID_HANDLE_VALUE
)
3488 /* Install .HW section */
3490 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
3491 DoAction
|= SPINST_REGISTRY
;
3492 strcpyW(pSectionName
, DotHW
);
3493 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
3494 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
3495 DoAction
, hKey
, NULL
, 0,
3497 DeviceInfoSet
, DeviceInfoData
);
3501 /* Write information to enum key */
3502 TRACE("Write information to enum key\n");
3503 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
3504 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
3505 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
3506 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
3507 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
3508 if (rc
== ERROR_SUCCESS
)
3509 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
3510 if (rc
== ERROR_SUCCESS
)
3511 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
3512 if (rc
== ERROR_SUCCESS
)
3513 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
3514 if (rc
!= ERROR_SUCCESS
)
3520 /* Start the device */
3521 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
3522 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
3527 /* End of installation */
3528 if (hKey
!= INVALID_HANDLE_VALUE
)
3531 RpcStringFreeW(&lpGuidString
);
3532 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3534 SetupTermDefaultQueueCallback(Context
);
3535 TRACE("Returning %d\n", ret
);