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
);
116 MyFree(MachineNameW
);
122 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
126 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
127 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
128 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
129 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
130 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
131 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
132 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
133 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
134 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
135 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
136 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
137 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
138 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
139 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
140 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
141 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
142 case CR_SUCCESS
: return ERROR_SUCCESS
;
143 default: return ERROR_GEN_FAILURE
;
146 /* Does not happen */
149 /***********************************************************************
150 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
153 SetupDiCreateDeviceInfoListExW(
154 IN CONST GUID
*ClassGuid OPTIONAL
,
155 IN HWND hwndParent OPTIONAL
,
156 IN PCWSTR MachineName OPTIONAL
,
159 struct DeviceInfoSet
*list
;
160 LPWSTR UNCServerName
= NULL
;
164 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
166 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
167 debugstr_w(MachineName
), Reserved
);
169 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
171 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
172 list
= HeapAlloc(GetProcessHeap(), 0, size
);
175 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
178 memset(list
, 0, sizeof(struct DeviceInfoSet
));
180 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
183 ClassGuid
? ClassGuid
: &GUID_NULL
,
184 sizeof(list
->ClassGuid
));
185 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
186 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
187 list
->InstallParams
.hwndParent
= hwndParent
;
190 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
191 if (rc
!= ERROR_SUCCESS
)
196 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
199 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
203 strcpyW(UNCServerName
+ 2, MachineName
);
204 list
->szData
[0] = list
->szData
[1] = '\\';
205 strcpyW(list
->szData
+ 2, MachineName
);
206 list
->MachineName
= list
->szData
;
210 DWORD Size
= MAX_PATH
;
211 list
->HKLM
= HKEY_LOCAL_MACHINE
;
212 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
215 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
218 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
220 list
->MachineName
= NULL
;
223 UNCServerName
[0] = UNCServerName
[1] = '\\';
224 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
225 if (cr
!= CR_SUCCESS
)
227 SetLastError(GetErrorCodeFromCrCode(cr
));
231 InitializeListHead(&list
->DriverListHead
);
232 InitializeListHead(&list
->ListHead
);
234 ret
= (HDEVINFO
)list
;
237 if (ret
== INVALID_HANDLE_VALUE
)
241 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
242 RegCloseKey(list
->HKLM
);
244 HeapFree(GetProcessHeap(), 0, list
);
247 HeapFree(GetProcessHeap(), 0, UNCServerName
);
251 /***********************************************************************
252 * SetupDiEnumDeviceInfo (SETUPAPI.@)
255 SetupDiEnumDeviceInfo(
256 IN HDEVINFO DeviceInfoSet
,
257 IN DWORD MemberIndex
,
258 OUT PSP_DEVINFO_DATA DeviceInfoData
)
262 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
264 SetLastError(ERROR_INVALID_PARAMETER
);
265 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
267 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
269 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
270 SetLastError(ERROR_INVALID_HANDLE
);
271 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
272 SetLastError(ERROR_INVALID_USER_BUFFER
);
275 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
276 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
277 ItemList
= ItemList
->Flink
;
278 if (ItemList
== &list
->ListHead
)
279 SetLastError(ERROR_NO_MORE_ITEMS
);
282 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
283 memcpy(&DeviceInfoData
->ClassGuid
,
286 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
287 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
293 SetLastError(ERROR_INVALID_HANDLE
);
297 /***********************************************************************
298 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
301 SetupDiGetActualSectionToInstallA(
303 IN PCSTR InfSectionName
,
304 OUT PSTR InfSectionWithExt OPTIONAL
,
305 IN DWORD InfSectionWithExtSize
,
306 OUT PDWORD RequiredSize OPTIONAL
,
307 OUT PSTR
*Extension OPTIONAL
)
309 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
310 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
314 /***********************************************************************
315 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
318 SetupDiGetActualSectionToInstallW(
320 IN PCWSTR InfSectionName
,
321 OUT PWSTR InfSectionWithExt OPTIONAL
,
322 IN DWORD InfSectionWithExtSize
,
323 OUT PDWORD RequiredSize OPTIONAL
,
324 OUT PWSTR
*Extension OPTIONAL
)
326 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
327 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
331 /***********************************************************************
332 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
335 SetupDiGetActualSectionToInstallExA(
337 IN PCSTR InfSectionName
,
338 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
339 OUT PSTR InfSectionWithExt OPTIONAL
,
340 IN DWORD InfSectionWithExtSize
,
341 OUT PDWORD RequiredSize OPTIONAL
,
342 OUT PSTR
* Extension OPTIONAL
,
345 LPWSTR InfSectionNameW
= NULL
;
346 LPWSTR InfSectionWithExtW
= NULL
;
348 BOOL bResult
= FALSE
;
354 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
355 if (InfSectionNameW
== NULL
)
358 if (InfSectionWithExt
)
360 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
361 if (InfSectionWithExtW
== NULL
)
365 bResult
= SetupDiGetActualSectionToInstallExW(
366 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
367 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
368 InfSectionWithExtSize
,
370 Extension
? &ExtensionW
: NULL
,
373 if (bResult
&& InfSectionWithExt
)
375 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
376 InfSectionWithExtSize
, NULL
, NULL
) != 0;
378 if (bResult
&& Extension
)
380 if (ExtensionW
== NULL
)
383 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
387 MyFree(InfSectionNameW
);
388 MyFree(InfSectionWithExtW
);
393 /* Lower scores are best ones */
396 IN LPCWSTR SectionName
,
397 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
400 OUT PDWORD ScorePlatform
,
401 OUT PDWORD ScoreMajorVersion
,
402 OUT PDWORD ScoreMinorVersion
,
403 OUT PDWORD ScoreProductType
,
404 OUT PDWORD ScoreSuiteMask
)
406 LPWSTR Section
= NULL
;
407 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
412 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
413 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
414 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
416 static const WCHAR ExtensionArchitectureNone
[] = {0};
417 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
418 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
419 static const WCHAR ExtensionArchitectureia64
[] = {'i','a','6','4',0};
420 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
421 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
422 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
424 TRACE("%s %p 0x%x 0x%x\n",
425 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
427 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
429 Section
= DuplicateString(SectionName
);
432 TRACE("DuplicateString() failed\n");
436 /* Set various extensions values */
437 switch (PlatformInfo
->Platform
)
439 case VER_PLATFORM_WIN32_WINDOWS
:
440 pExtensionPlatform
= ExtensionPlatformWindows
;
442 case VER_PLATFORM_WIN32_NT
:
443 pExtensionPlatform
= ExtensionPlatformNT
;
446 ERR("Unkown platform 0x%lx\n", PlatformInfo
->Platform
);
447 pExtensionPlatform
= ExtensionPlatformNone
;
450 switch (PlatformInfo
->ProcessorArchitecture
)
452 case PROCESSOR_ARCHITECTURE_ALPHA
:
453 pExtensionArchitecture
= ExtensionArchitecturealpha
;
455 case PROCESSOR_ARCHITECTURE_AMD64
:
456 pExtensionArchitecture
= ExtensionArchitectureamd64
;
458 case PROCESSOR_ARCHITECTURE_IA64
:
459 pExtensionArchitecture
= ExtensionArchitectureia64
;
461 case PROCESSOR_ARCHITECTURE_INTEL
:
462 pExtensionArchitecture
= ExtensionArchitecturex86
;
464 case PROCESSOR_ARCHITECTURE_MIPS
:
465 pExtensionArchitecture
= ExtensionArchitecturemips
;
467 case PROCESSOR_ARCHITECTURE_PPC
:
468 pExtensionArchitecture
= ExtensionArchitectureppc
;
471 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
472 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
473 pExtensionArchitecture
= ExtensionArchitectureNone
;
479 * Field[1] Architecture
480 * Field[2] Major version
481 * Field[3] Minor version
482 * Field[4] Product type
483 * Field[5] Suite mask
484 * Remark: lastests fields may be NULL if the information is not provided
487 if (Fields
[0] == NULL
)
489 TRACE("No extension found\n");
490 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
494 Fields
[1] = Fields
[0] + 1;
495 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
496 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
498 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
502 *(Fields
[i
] - 1) = L
'\0';
505 /* Take care of first 2 fields */
506 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
508 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
510 TRACE("Mismatch on platform field\n");
513 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
515 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
517 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
519 TRACE("Mismatch on platform field\n");
522 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
526 /* No platform specified */
527 *ScorePlatform
|= 0x02;
529 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
531 /* No architecture specified */
532 *ScorePlatform
|= 0x01;
534 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
536 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
537 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
541 /* Check if informations are matching */
542 if (Fields
[2] && *Fields
[2])
544 DWORD MajorVersion
, MinorVersion
= 0;
545 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
546 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
547 (errno
== ERANGE
|| errno
== EINVAL
))
549 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
552 if (Fields
[3] && *Fields
[3])
554 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
555 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
556 (errno
== ERANGE
|| errno
== EINVAL
))
558 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
562 if (PlatformInfo
->MajorVersion
< MajorVersion
||
563 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
565 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
566 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
569 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
570 if (MajorVersion
== PlatformInfo
->MajorVersion
)
571 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
573 *ScoreMinorVersion
= MinorVersion
;
575 else if (Fields
[3] && *Fields
[3])
577 TRACE("Minor version found without major version\n");
582 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
583 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
586 if (Fields
[4] && *Fields
[4])
588 DWORD CurrentProductType
;
589 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
590 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
591 (errno
== ERANGE
|| errno
== EINVAL
))
593 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
596 if (CurrentProductType
!= ProductType
)
598 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
599 CurrentProductType
, ProductType
);
604 *ScoreProductType
= 1;
606 if (Fields
[5] && *Fields
[5])
608 DWORD CurrentSuiteMask
;
609 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
610 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
611 (errno
== ERANGE
|| errno
== EINVAL
))
613 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
616 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
618 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
619 CurrentSuiteMask
, SuiteMask
);
622 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
625 *ScoreSuiteMask
= SuiteMask
;
636 IN LPCWSTR SectionName
,
639 struct GetSectionCallbackInfo
*info
= Context
;
640 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
643 if (SectionName
[info
->PrefixLength
] != '.')
646 ret
= CheckSectionValid(
647 &SectionName
[info
->PrefixLength
],
651 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
654 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
657 if (Score1
> info
->BestScore1
) goto done
;
658 if (Score1
< info
->BestScore1
) goto bettersection
;
659 if (Score2
> info
->BestScore2
) goto done
;
660 if (Score2
< info
->BestScore2
) goto bettersection
;
661 if (Score3
> info
->BestScore3
) goto done
;
662 if (Score3
< info
->BestScore3
) goto bettersection
;
663 if (Score4
> info
->BestScore4
) goto done
;
664 if (Score4
< info
->BestScore4
) goto bettersection
;
665 if (Score5
> info
->BestScore5
) goto done
;
666 if (Score5
< info
->BestScore5
) goto bettersection
;
670 strcpyW(info
->BestSection
, SectionName
);
671 info
->BestScore1
= Score1
;
672 info
->BestScore2
= Score2
;
673 info
->BestScore3
= Score3
;
674 info
->BestScore4
= Score4
;
675 info
->BestScore5
= Score5
;
681 /***********************************************************************
682 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
685 SetupDiGetActualSectionToInstallExW(
687 IN PCWSTR InfSectionName
,
688 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
689 OUT PWSTR InfSectionWithExt OPTIONAL
,
690 IN DWORD InfSectionWithExtSize
,
691 OUT PDWORD RequiredSize OPTIONAL
,
692 OUT PWSTR
* Extension OPTIONAL
,
697 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
698 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
699 RequiredSize
, Extension
, Reserved
);
701 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
702 SetLastError(ERROR_INVALID_HANDLE
);
703 else if (!InfSectionName
)
704 SetLastError(ERROR_INVALID_PARAMETER
);
705 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
706 SetLastError(ERROR_INVALID_USER_BUFFER
);
707 else if (Reserved
!= NULL
)
708 SetLastError(ERROR_INVALID_PARAMETER
);
711 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
712 static BYTE CurrentProductType
= 0;
713 static WORD CurrentSuiteMask
= 0;
714 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
715 struct GetSectionCallbackInfo CallbackInfo
;
720 /* Fill platform info if needed */
721 if (AlternatePlatformInfo
)
723 pPlatformInfo
= AlternatePlatformInfo
;
729 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
731 /* That's the first time we go here. We need to fill in the structure */
732 OSVERSIONINFOEX VersionInfo
;
733 SYSTEM_INFO SystemInfo
;
734 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
735 ret
= GetVersionEx((POSVERSIONINFO
)&VersionInfo
);
738 GetSystemInfo(&SystemInfo
);
739 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
740 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
741 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
742 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
743 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
744 CurrentPlatform
.Reserved
= 0;
745 CurrentProductType
= VersionInfo
.wProductType
;
746 CurrentSuiteMask
= VersionInfo
.wSuiteMask
;
748 ProductType
= CurrentProductType
;
749 SuiteMask
= CurrentSuiteMask
;
752 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
753 CallbackInfo
.ProductType
= ProductType
;
754 CallbackInfo
.SuiteMask
= SuiteMask
;
755 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
756 CallbackInfo
.BestScore1
= ULONG_MAX
;
757 CallbackInfo
.BestScore2
= ULONG_MAX
;
758 CallbackInfo
.BestScore3
= ULONG_MAX
;
759 CallbackInfo
.BestScore4
= ULONG_MAX
;
760 CallbackInfo
.BestScore5
= ULONG_MAX
;
761 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
762 if (!EnumerateSectionsStartingWith(
768 SetLastError(ERROR_GEN_FAILURE
);
772 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
773 if (RequiredSize
!= NULL
)
774 *RequiredSize
= dwFullLength
+ 1;
776 if (InfSectionWithExtSize
> 0)
778 if (InfSectionWithExtSize
< dwFullLength
+ 1)
780 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
783 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
786 DWORD dwLength
= lstrlenW(InfSectionName
);
787 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
795 TRACE("Returning %d\n", ret
);
801 CreateDeviceInfoElement(
802 IN
struct DeviceInfoSet
*list
,
803 IN LPCWSTR InstancePath
,
804 IN LPCGUID pClassGuid
,
805 OUT
struct DeviceInfoElement
**pDeviceInfo
)
809 struct DeviceInfoElement
*deviceInfo
;
813 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
814 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
817 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
820 memset(deviceInfo
, 0, size
);
822 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
823 if (cr
!= CR_SUCCESS
)
825 SetLastError(GetErrorCodeFromCrCode(cr
));
829 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
830 strcpyW(deviceInfo
->Data
, InstancePath
);
831 deviceInfo
->DeviceName
= deviceInfo
->Data
;
832 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
833 deviceInfo
->DeviceDescription
= NULL
;
834 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
835 deviceInfo
->CreationFlags
= 0;
836 InitializeListHead(&deviceInfo
->DriverListHead
);
837 InitializeListHead(&deviceInfo
->InterfaceListHead
);
839 *pDeviceInfo
= deviceInfo
;
845 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
847 return HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
851 DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
853 PLIST_ENTRY ListEntry
;
854 struct DriverInfoElement
*driverInfo
;
855 struct DeviceInterface
*deviceInterface
;
857 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
859 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
860 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
861 if (!DestroyDriverInfoElement(driverInfo
))
864 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
866 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
867 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
868 if (!DestroyDeviceInterface(deviceInterface
))
871 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
872 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
876 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
878 PLIST_ENTRY ListEntry
;
879 struct DeviceInfoElement
*deviceInfo
;
881 while (!IsListEmpty(&list
->ListHead
))
883 ListEntry
= RemoveHeadList(&list
->ListHead
);
884 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfoElement
, ListEntry
);
885 if (!DestroyDeviceInfoElement(deviceInfo
))
888 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
889 RegCloseKey(list
->HKLM
);
890 CM_Disconnect_Machine(list
->hMachine
);
891 DestroyClassInstallParams(&list
->ClassInstallParams
);
892 return HeapFree(GetProcessHeap(), 0, list
);
895 /***********************************************************************
896 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
899 SetupDiDestroyDeviceInfoList(
900 IN HDEVINFO DeviceInfoSet
)
904 TRACE("%p\n", DeviceInfoSet
);
905 if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
907 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
909 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
910 ret
= DestroyDeviceInfoSet(list
);
912 SetLastError(ERROR_INVALID_HANDLE
);
915 SetLastError(ERROR_INVALID_HANDLE
);
917 TRACE("Returning %d\n", ret
);
921 /***********************************************************************
922 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
925 SetupDiGetDeviceRegistryPropertyA(
926 IN HDEVINFO DeviceInfoSet
,
927 IN PSP_DEVINFO_DATA DeviceInfoData
,
929 OUT PDWORD PropertyRegDataType OPTIONAL
,
930 OUT PBYTE PropertyBuffer OPTIONAL
,
931 IN DWORD PropertyBufferSize
,
932 OUT PDWORD RequiredSize OPTIONAL
)
935 BOOL bIsStringProperty
;
937 DWORD RequiredSizeA
, RequiredSizeW
;
938 DWORD PropertyBufferSizeW
= 0;
939 PBYTE PropertyBufferW
= NULL
;
941 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
942 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
945 if (PropertyBufferSize
!= 0)
947 PropertyBufferSizeW
= PropertyBufferSize
* 2;
948 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
949 if (!PropertyBufferW
)
951 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
956 bResult
= SetupDiGetDeviceRegistryPropertyW(
965 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
967 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
969 if (bIsStringProperty
)
970 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
972 RequiredSizeA
= RequiredSizeW
;
974 *RequiredSize
= RequiredSizeA
;
975 if (PropertyRegDataType
)
976 *PropertyRegDataType
= RegType
;
981 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
985 if (RequiredSizeA
<= PropertyBufferSize
)
987 if (bIsStringProperty
&& PropertyBufferSize
> 0)
989 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
991 /* Last error is already set by WideCharToMultiByte */
996 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
1000 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1004 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
1008 /***********************************************************************
1009 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
1012 SetupDiGetDeviceRegistryPropertyW(
1013 IN HDEVINFO DeviceInfoSet
,
1014 IN PSP_DEVINFO_DATA DeviceInfoData
,
1016 OUT PDWORD PropertyRegDataType OPTIONAL
,
1017 OUT PBYTE PropertyBuffer OPTIONAL
,
1018 IN DWORD PropertyBufferSize
,
1019 OUT PDWORD RequiredSize OPTIONAL
)
1021 HKEY hEnumKey
, hKey
;
1025 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1026 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
1029 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1030 SetLastError(ERROR_INVALID_HANDLE
);
1031 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1032 SetLastError(ERROR_INVALID_HANDLE
);
1033 else if (!DeviceInfoData
)
1034 SetLastError(ERROR_INVALID_PARAMETER
);
1035 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1036 SetLastError(ERROR_INVALID_USER_BUFFER
);
1037 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
1038 SetLastError(ERROR_INVALID_PARAMETER
);
1041 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1042 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
1046 case SPDRP_CAPABILITIES
:
1048 case SPDRP_CLASSGUID
:
1049 case SPDRP_COMPATIBLEIDS
:
1050 case SPDRP_CONFIGFLAGS
:
1051 case SPDRP_DEVICEDESC
:
1053 case SPDRP_FRIENDLYNAME
:
1054 case SPDRP_HARDWAREID
:
1055 case SPDRP_LOCATION_INFORMATION
:
1056 case SPDRP_LOWERFILTERS
:
1058 case SPDRP_SECURITY
:
1060 case SPDRP_UI_NUMBER
:
1061 case SPDRP_UI_NUMBER_DESC_FORMAT
:
1062 case SPDRP_UPPERFILTERS
:
1064 LPCWSTR RegistryPropertyName
;
1069 case SPDRP_CAPABILITIES
:
1070 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
1072 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
1073 case SPDRP_CLASSGUID
:
1074 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
1075 case SPDRP_COMPATIBLEIDS
:
1076 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
1077 case SPDRP_CONFIGFLAGS
:
1078 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
1079 case SPDRP_DEVICEDESC
:
1080 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
1082 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
1083 case SPDRP_FRIENDLYNAME
:
1084 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
1085 case SPDRP_HARDWAREID
:
1086 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
1087 case SPDRP_LOCATION_INFORMATION
:
1088 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
1089 case SPDRP_LOWERFILTERS
:
1090 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
1092 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
1093 case SPDRP_SECURITY
:
1094 RegistryPropertyName
= REGSTR_SECURITY
; break;
1096 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
1097 case SPDRP_UI_NUMBER
:
1098 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
1099 case SPDRP_UI_NUMBER_DESC_FORMAT
:
1100 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
; break;
1101 case SPDRP_UPPERFILTERS
:
1102 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
1104 /* Should not happen */
1105 RegistryPropertyName
= NULL
; break;
1108 /* Open registry key name */
1111 REGSTR_PATH_SYSTEMENUM
,
1115 if (rc
!= ERROR_SUCCESS
)
1126 RegCloseKey(hEnumKey
);
1127 if (rc
!= ERROR_SUCCESS
)
1132 /* Read registry entry */
1133 BufferSize
= PropertyBufferSize
;
1134 rc
= RegQueryValueExW(
1136 RegistryPropertyName
,
1137 NULL
, /* Reserved */
1138 PropertyRegDataType
,
1142 *RequiredSize
= BufferSize
;
1145 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
1148 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1150 case ERROR_MORE_DATA
:
1151 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1160 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
1162 DWORD required
= (strlenW(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
1164 if (PropertyRegDataType
)
1165 *PropertyRegDataType
= REG_SZ
;
1167 *RequiredSize
= required
;
1168 if (PropertyBufferSize
>= required
)
1170 strcpyW((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
1174 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1178 /*case SPDRP_BUSTYPEGUID:
1179 case SPDRP_LEGACYBUSTYPE:
1180 case SPDRP_BUSNUMBER:
1181 case SPDRP_ENUMERATOR_NAME:
1182 case SPDRP_SECURITY_SDS:
1184 case SPDRP_EXCLUSIVE:
1185 case SPDRP_CHARACTERISTICS:
1187 case SPDRP_DEVICE_POWER_DATA:*/
1188 #if (WINVER >= 0x501)
1189 /*case SPDRP_REMOVAL_POLICY:
1190 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
1191 case SPDRP_REMOVAL_POLICY_OVERRIDE:
1192 case SPDRP_INSTALL_STATE:*/
1197 ERR("Property 0x%lx not implemented\n", Property
);
1198 SetLastError(ERROR_NOT_SUPPORTED
);
1203 TRACE("Returning %d\n", ret
);
1207 /***********************************************************************
1208 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
1211 SetupDiSetDeviceRegistryPropertyA(
1212 IN HDEVINFO DeviceInfoSet
,
1213 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
1215 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
1216 IN DWORD PropertyBufferSize
)
1218 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
1219 Property
, PropertyBuffer
, PropertyBufferSize
);
1220 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1224 /***********************************************************************
1225 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
1228 SetupDiSetDeviceRegistryPropertyW(
1229 IN HDEVINFO DeviceInfoSet
,
1230 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
1232 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
1233 IN DWORD PropertyBufferSize
)
1235 struct DeviceInfoSet
*list
;
1238 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
1239 Property
, PropertyBuffer
, PropertyBufferSize
);
1242 SetLastError(ERROR_INVALID_HANDLE
);
1243 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1244 SetLastError(ERROR_INVALID_HANDLE
);
1245 else if (!DeviceInfoData
)
1246 SetLastError(ERROR_INVALID_HANDLE
);
1247 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1248 SetLastError(ERROR_INVALID_USER_BUFFER
);
1253 case SPDRP_COMPATIBLEIDS
:
1254 case SPDRP_CONFIGFLAGS
:
1255 case SPDRP_FRIENDLYNAME
:
1256 case SPDRP_HARDWAREID
:
1257 case SPDRP_LOCATION_INFORMATION
:
1258 case SPDRP_LOWERFILTERS
:
1259 case SPDRP_SECURITY
:
1261 case SPDRP_UI_NUMBER_DESC_FORMAT
:
1262 case SPDRP_UPPERFILTERS
:
1264 LPCWSTR RegistryPropertyName
;
1265 DWORD RegistryDataType
;
1271 case SPDRP_COMPATIBLEIDS
:
1272 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
1273 RegistryDataType
= REG_MULTI_SZ
;
1275 case SPDRP_CONFIGFLAGS
:
1276 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
1277 RegistryDataType
= REG_DWORD
;
1279 case SPDRP_FRIENDLYNAME
:
1280 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
1281 RegistryDataType
= REG_SZ
;
1283 case SPDRP_HARDWAREID
:
1284 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
1285 RegistryDataType
= REG_MULTI_SZ
;
1287 case SPDRP_LOCATION_INFORMATION
:
1288 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
1289 RegistryDataType
= REG_SZ
;
1291 case SPDRP_LOWERFILTERS
:
1292 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
1293 RegistryDataType
= REG_MULTI_SZ
;
1295 case SPDRP_SECURITY
:
1296 RegistryPropertyName
= REGSTR_SECURITY
;
1297 RegistryDataType
= REG_BINARY
;
1300 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
1301 RegistryDataType
= REG_SZ
;
1303 case SPDRP_UI_NUMBER_DESC_FORMAT
:
1304 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
;
1305 RegistryDataType
= REG_SZ
;
1307 case SPDRP_UPPERFILTERS
:
1308 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
1309 RegistryDataType
= REG_MULTI_SZ
;
1312 /* Should not happen */
1313 RegistryPropertyName
= NULL
;
1314 RegistryDataType
= REG_BINARY
;
1317 /* Open device registry key */
1318 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
1319 if (hKey
!= INVALID_HANDLE_VALUE
)
1321 /* Write new data */
1322 rc
= RegSetValueExW(
1324 RegistryPropertyName
,
1328 PropertyBufferSize
);
1329 if (rc
== ERROR_SUCCESS
)
1338 /*case SPDRP_CHARACTERISTICS:
1340 case SPDRP_EXCLUSIVE:*/
1341 #if (WINVER >= 0x501)
1342 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
1344 //case SPDRP_SECURITY_SDS:
1348 ERR("Property 0x%lx not implemented\n", Property
);
1349 SetLastError(ERROR_NOT_SUPPORTED
);
1354 TRACE("Returning %d\n", ret
);
1360 IntSetupDiRegisterDeviceInfo(
1361 IN HDEVINFO DeviceInfoSet
,
1362 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
1364 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
1367 /***********************************************************************
1368 * SetupDiCallClassInstaller (SETUPAPI.@)
1371 SetupDiCallClassInstaller(
1372 IN DI_FUNCTION InstallFunction
,
1373 IN HDEVINFO DeviceInfoSet
,
1374 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
1378 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
1381 SetLastError(ERROR_INVALID_PARAMETER
);
1382 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1383 SetLastError(ERROR_INVALID_HANDLE
);
1384 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1385 SetLastError(ERROR_INVALID_HANDLE
);
1386 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
1387 SetLastError(ERROR_INVALID_HANDLE
);
1388 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1389 SetLastError(ERROR_INVALID_USER_BUFFER
);
1392 SP_DEVINSTALL_PARAMS_W InstallParams
;
1393 #define CLASS_COINSTALLER 0x1
1394 #define DEVICE_COINSTALLER 0x2
1395 #define CLASS_INSTALLER 0x4
1396 UCHAR CanHandle
= 0;
1397 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
1399 switch (InstallFunction
)
1401 case DIF_ADDPROPERTYPAGE_ADVANCED
:
1402 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1404 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
1405 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1407 case DIF_ALLOW_INSTALL
:
1408 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1411 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1413 case DIF_DESTROYPRIVATEDATA
:
1414 CanHandle
= CLASS_INSTALLER
;
1416 case DIF_INSTALLDEVICE
:
1417 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1418 DefaultHandler
= SetupDiInstallDevice
;
1420 case DIF_INSTALLDEVICEFILES
:
1421 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1422 DefaultHandler
= SetupDiInstallDriverFiles
;
1424 case DIF_INSTALLINTERFACES
:
1425 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1426 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
1428 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
1429 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1431 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
1432 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1434 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
1435 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1437 case DIF_NEWDEVICEWIZARD_PRESELECT
:
1438 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1440 case DIF_NEWDEVICEWIZARD_SELECT
:
1441 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1443 case DIF_POWERMESSAGEWAKE
:
1444 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1446 case DIF_PROPERTYCHANGE
:
1447 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1448 DefaultHandler
= SetupDiChangeState
;
1450 case DIF_REGISTER_COINSTALLERS
:
1451 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1452 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
1454 case DIF_REGISTERDEVICE
:
1455 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1456 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
1459 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1460 DefaultHandler
= SetupDiRemoveDevice
;
1462 case DIF_SELECTBESTCOMPATDRV
:
1463 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1464 DefaultHandler
= SetupDiSelectBestCompatDrv
;
1466 case DIF_SELECTDEVICE
:
1467 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
1468 DefaultHandler
= SetupDiSelectDevice
;
1470 case DIF_TROUBLESHOOTER
:
1471 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1474 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
1475 DefaultHandler
= SetupDiUnremoveDevice
;
1478 ERR("Install function %u not supported\n", InstallFunction
);
1479 SetLastError(ERROR_NOT_SUPPORTED
);
1482 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1483 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1484 /* Don't process this call, as a parameter is invalid */
1489 LIST_ENTRY ClassCoInstallersListHead
;
1490 LIST_ENTRY DeviceCoInstallersListHead
;
1491 HMODULE ClassInstallerLibrary
= NULL
;
1492 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
1493 COINSTALLER_CONTEXT_DATA Context
;
1494 PLIST_ENTRY ListEntry
;
1496 DWORD dwRegType
, dwLength
;
1497 DWORD rc
= NO_ERROR
;
1499 InitializeListHead(&ClassCoInstallersListHead
);
1500 InitializeListHead(&DeviceCoInstallersListHead
);
1502 if (CanHandle
& DEVICE_COINSTALLER
)
1504 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
1505 if (hKey
!= INVALID_HANDLE_VALUE
)
1507 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
1508 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
1510 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
1511 if (KeyBuffer
!= NULL
)
1513 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1514 if (rc
== ERROR_SUCCESS
)
1517 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1519 /* Add coinstaller to DeviceCoInstallersListHead list */
1520 struct CoInstallerElement
*coinstaller
;
1521 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
1522 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
1525 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
1526 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
1527 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
1529 HeapFree(GetProcessHeap(), 0, coinstaller
);
1532 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
1538 if (CanHandle
& CLASS_COINSTALLER
)
1542 REGSTR_PATH_CODEVICEINSTALLERS
,
1546 if (rc
== ERROR_SUCCESS
)
1548 LPWSTR lpGuidString
;
1549 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
1551 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
1552 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
1554 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
1555 if (KeyBuffer
!= NULL
)
1557 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1558 if (rc
== ERROR_SUCCESS
)
1561 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1563 /* Add coinstaller to ClassCoInstallersListHead list */
1564 struct CoInstallerElement
*coinstaller
;
1565 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
1566 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
1569 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
1570 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
1571 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
1573 HeapFree(GetProcessHeap(), 0, coinstaller
);
1576 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
1579 RpcStringFreeW(&lpGuidString
);
1584 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
1586 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
1587 if (hKey
!= INVALID_HANDLE_VALUE
)
1589 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
1590 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
1592 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
1593 if (KeyBuffer
!= NULL
)
1595 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1596 if (rc
== ERROR_SUCCESS
)
1598 /* Get ClassInstaller function pointer */
1599 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
1600 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
1602 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
1603 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1606 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
1613 /* Call Class co-installers */
1614 Context
.PostProcessing
= FALSE
;
1616 ListEntry
= ClassCoInstallersListHead
.Flink
;
1617 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
1619 struct CoInstallerElement
*coinstaller
;
1620 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
1621 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
1622 coinstaller
->PrivateData
= Context
.PrivateData
;
1623 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
1625 coinstaller
->DoPostProcessing
= TRUE
;
1628 ListEntry
= ListEntry
->Flink
;
1631 /* Call Device co-installers */
1632 ListEntry
= DeviceCoInstallersListHead
.Flink
;
1633 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
1635 struct CoInstallerElement
*coinstaller
;
1636 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
1637 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
1638 coinstaller
->PrivateData
= Context
.PrivateData
;
1639 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
1641 coinstaller
->DoPostProcessing
= TRUE
;
1644 ListEntry
= ListEntry
->Flink
;
1647 /* Call Class installer */
1650 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
1651 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
1654 rc
= ERROR_DI_DO_DEFAULT
;
1656 /* Call default handler */
1657 if (rc
== ERROR_DI_DO_DEFAULT
)
1659 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
1661 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
1664 rc
= GetLastError();
1670 /* Call Class co-installers that required postprocessing */
1671 Context
.PostProcessing
= TRUE
;
1672 ListEntry
= ClassCoInstallersListHead
.Flink
;
1673 while (ListEntry
!= &ClassCoInstallersListHead
)
1675 struct CoInstallerElement
*coinstaller
;
1676 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
1677 if (coinstaller
->DoPostProcessing
)
1679 Context
.InstallResult
= rc
;
1680 Context
.PrivateData
= coinstaller
->PrivateData
;
1681 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
1683 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
1684 ListEntry
= ListEntry
->Flink
;
1687 /* Call Device co-installers that required postprocessing */
1688 ListEntry
= DeviceCoInstallersListHead
.Flink
;
1689 while (ListEntry
!= &DeviceCoInstallersListHead
)
1691 struct CoInstallerElement
*coinstaller
;
1692 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
1693 if (coinstaller
->DoPostProcessing
)
1695 Context
.InstallResult
= rc
;
1696 Context
.PrivateData
= coinstaller
->PrivateData
;
1697 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
1699 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
1700 ListEntry
= ListEntry
->Flink
;
1703 /* Free allocated memory */
1704 while (!IsListEmpty(&ClassCoInstallersListHead
))
1706 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
1707 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
1709 while (!IsListEmpty(&DeviceCoInstallersListHead
))
1711 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
1712 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
1715 ret
= (rc
== NO_ERROR
);
1719 TRACE("Returning %d\n", ret
);
1723 /***********************************************************************
1724 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
1727 SetupDiGetDeviceInfoListClass(
1728 IN HDEVINFO DeviceInfoSet
,
1729 OUT LPGUID ClassGuid
)
1731 struct DeviceInfoSet
*list
;
1734 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
1737 SetLastError(ERROR_INVALID_HANDLE
);
1738 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1739 SetLastError(ERROR_INVALID_HANDLE
);
1740 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1741 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
1744 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
1749 TRACE("Returning %d\n", ret
);
1753 /***********************************************************************
1754 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
1757 SetupDiGetDeviceInfoListDetailW(
1758 IN HDEVINFO DeviceInfoSet
,
1759 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
1761 struct DeviceInfoSet
*list
;
1764 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
1767 SetLastError(ERROR_INVALID_HANDLE
);
1768 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1769 SetLastError(ERROR_INVALID_HANDLE
);
1770 else if (!DeviceInfoListDetailData
)
1771 SetLastError(ERROR_INVALID_PARAMETER
);
1772 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
1773 SetLastError(ERROR_INVALID_USER_BUFFER
);
1777 &DeviceInfoListDetailData
->ClassGuid
,
1780 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
1781 if (list
->MachineName
)
1782 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
1784 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
1789 TRACE("Returning %d\n", ret
);
1793 /***********************************************************************
1794 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1797 SetupDiGetDeviceInstallParamsA(
1798 IN HDEVINFO DeviceInfoSet
,
1799 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1800 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
1802 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
1805 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
1807 if (DeviceInstallParams
== NULL
)
1808 SetLastError(ERROR_INVALID_PARAMETER
);
1809 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
1810 SetLastError(ERROR_INVALID_USER_BUFFER
);
1813 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1814 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
1818 /* Do W->A conversion */
1820 DeviceInstallParams
,
1821 &deviceInstallParamsW
,
1822 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
1823 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
1824 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
1826 DeviceInstallParams
->DriverPath
[0] = '\0';
1832 TRACE("Returning %d\n", ret
);
1836 /***********************************************************************
1837 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
1840 SetupDiGetDeviceInstallParamsW(
1841 IN HDEVINFO DeviceInfoSet
,
1842 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1843 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
1845 struct DeviceInfoSet
*list
;
1848 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
1851 SetLastError(ERROR_INVALID_HANDLE
);
1852 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1853 SetLastError(ERROR_INVALID_HANDLE
);
1854 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1855 SetLastError(ERROR_INVALID_USER_BUFFER
);
1856 else if (!DeviceInstallParams
)
1857 SetLastError(ERROR_INVALID_PARAMETER
);
1858 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
1859 SetLastError(ERROR_INVALID_USER_BUFFER
);
1862 PSP_DEVINSTALL_PARAMS_W Source
;
1865 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
1867 Source
= &list
->InstallParams
;
1868 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
1872 TRACE("Returning %d\n", ret
);
1877 CheckDeviceInstallParameters(
1878 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
1880 DWORD SupportedFlags
=
1881 DI_NOVCP
| /* 0x00000008 */
1882 DI_DIDCOMPAT
| /* 0x00000010 */
1883 DI_DIDCLASS
| /* 0x00000020 */
1884 DI_NEEDRESTART
| /* 0x00000080 */
1885 DI_NEEDREBOOT
| /* 0x00000100 */
1886 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
1887 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
1888 DI_ENUMSINGLEINF
| /* 0x00010000 */
1889 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
1890 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
1891 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
1892 DI_QUIETINSTALL
| /* 0x00800000 */
1893 DI_NOFILECOPY
| /* 0x01000000 */
1894 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
1895 DWORD SupportedFlagsEx
=
1896 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
1897 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
1898 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
1899 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
1900 DI_FLAGSEX_NO_DRVREG_MODIFY
; /* 0x00008000 */
1903 /* FIXME: add support for more flags */
1905 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
1906 * It should be checked before accessing to other values
1907 * of the SP_DEVINSTALL_PARAMS structure */
1909 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
1911 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
1912 SetLastError(ERROR_INVALID_FLAGS
);
1914 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
1916 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
1917 SetLastError(ERROR_INVALID_FLAGS
);
1919 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
1920 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
1921 SetLastError(ERROR_INVALID_USER_BUFFER
);
1924 /* FIXME: check Reserved field */
1931 /***********************************************************************
1932 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
1935 SetupDiSetDeviceInstallParamsW(
1936 IN HDEVINFO DeviceInfoSet
,
1937 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1938 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
1940 struct DeviceInfoSet
*list
;
1943 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
1946 SetLastError(ERROR_INVALID_HANDLE
);
1947 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1948 SetLastError(ERROR_INVALID_HANDLE
);
1949 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1950 SetLastError(ERROR_INVALID_USER_BUFFER
);
1951 else if (!DeviceInstallParams
)
1952 SetLastError(ERROR_INVALID_PARAMETER
);
1953 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
1954 SetLastError(ERROR_INVALID_USER_BUFFER
);
1955 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
1957 PSP_DEVINSTALL_PARAMS_W Destination
;
1960 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
1962 Destination
= &list
->InstallParams
;
1963 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
1967 TRACE("Returning %d\n", ret
);
1971 /***********************************************************************
1972 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
1975 SetupDiGetDeviceInstanceIdA(
1976 IN HDEVINFO DeviceInfoSet
,
1977 IN PSP_DEVINFO_DATA DeviceInfoData
,
1978 OUT PSTR DeviceInstanceId OPTIONAL
,
1979 IN DWORD DeviceInstanceIdSize
,
1980 OUT PDWORD RequiredSize OPTIONAL
)
1982 PWSTR DeviceInstanceIdW
= NULL
;
1985 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
1986 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
1988 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1989 SetLastError(ERROR_INVALID_PARAMETER
);
1992 if (DeviceInstanceIdSize
!= 0)
1994 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
1995 if (DeviceInstanceIdW
== NULL
)
1999 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
2000 DeviceInstanceIdW
, DeviceInstanceIdSize
,
2003 if (ret
&& DeviceInstanceIdW
!= NULL
)
2005 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
2006 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
2008 DeviceInstanceId
[0] = '\0';
2014 TRACE("Returning %d\n", ret
);
2018 /***********************************************************************
2019 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
2022 SetupDiGetDeviceInstanceIdW(
2023 IN HDEVINFO DeviceInfoSet
,
2024 IN PSP_DEVINFO_DATA DeviceInfoData
,
2025 OUT PWSTR DeviceInstanceId OPTIONAL
,
2026 IN DWORD DeviceInstanceIdSize
,
2027 OUT PDWORD RequiredSize OPTIONAL
)
2031 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
2032 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
2035 SetLastError(ERROR_INVALID_HANDLE
);
2036 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2037 SetLastError(ERROR_INVALID_HANDLE
);
2038 else if (!DeviceInfoData
)
2039 SetLastError(ERROR_INVALID_PARAMETER
);
2040 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2041 SetLastError(ERROR_INVALID_USER_BUFFER
);
2042 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
2043 SetLastError(ERROR_INVALID_PARAMETER
);
2044 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
2045 SetLastError(ERROR_INVALID_PARAMETER
);
2048 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2051 required
= (strlenW(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
2053 *RequiredSize
= required
;
2055 if (required
<= DeviceInstanceIdSize
)
2057 strcpyW(DeviceInstanceId
, DevInfo
->DeviceName
);
2061 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2064 TRACE("Returning %d\n", ret
);
2069 /***********************************************************************
2070 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
2073 SetupDiCreateDevRegKeyA(
2074 IN HDEVINFO DeviceInfoSet
,
2075 IN PSP_DEVINFO_DATA DeviceInfoData
,
2079 IN HINF InfHandle OPTIONAL
,
2080 IN PCSTR InfSectionName OPTIONAL
)
2082 PCWSTR InfSectionNameW
= NULL
;
2083 HKEY ret
= INVALID_HANDLE_VALUE
;
2087 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
2088 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
2091 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
2099 if (InfSectionNameW
!= NULL
)
2100 MyFree((PVOID
)InfSectionNameW
);
2106 OpenHardwareProfileKey(
2109 IN DWORD samDesired
)
2111 HKEY hHWProfilesKey
= NULL
;
2112 HKEY hHWProfileKey
= NULL
;
2113 HKEY ret
= INVALID_HANDLE_VALUE
;
2116 rc
= RegOpenKeyExW(HKLM
,
2117 REGSTR_PATH_HWPROFILES
,
2121 if (rc
!= ERROR_SUCCESS
)
2138 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
2147 if (rc
!= ERROR_SUCCESS
)
2152 ret
= hHWProfileKey
;
2155 if (hHWProfilesKey
!= NULL
)
2156 RegCloseKey(hHWProfilesKey
);
2157 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
2158 RegCloseKey(hHWProfileKey
);
2162 /***********************************************************************
2163 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
2166 SetupDiCreateDevRegKeyW(
2167 IN HDEVINFO DeviceInfoSet
,
2168 IN PSP_DEVINFO_DATA DeviceInfoData
,
2172 IN HINF InfHandle OPTIONAL
,
2173 IN PCWSTR InfSectionName OPTIONAL
)
2175 struct DeviceInfoSet
*list
;
2176 HKEY ret
= INVALID_HANDLE_VALUE
;
2178 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
2179 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
2182 SetLastError(ERROR_INVALID_HANDLE
);
2183 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2184 SetLastError(ERROR_INVALID_HANDLE
);
2185 else if (!DeviceInfoData
)
2186 SetLastError(ERROR_INVALID_PARAMETER
);
2187 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2188 SetLastError(ERROR_INVALID_USER_BUFFER
);
2189 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
2190 SetLastError(ERROR_INVALID_PARAMETER
);
2191 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
2192 SetLastError(ERROR_INVALID_PARAMETER
);
2193 else if (InfHandle
&& !InfSectionName
)
2194 SetLastError(ERROR_INVALID_PARAMETER
);
2195 else if (!InfHandle
&& InfSectionName
)
2196 SetLastError(ERROR_INVALID_PARAMETER
);
2199 LPWSTR lpGuidString
= NULL
;
2200 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
2201 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
2202 DWORD Index
; /* Index used in the DriverKey name */
2204 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
2205 HKEY hEnumKey
= NULL
;
2206 HKEY hClassKey
= NULL
;
2207 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
2211 if (Scope
== DICS_FLAG_GLOBAL
)
2212 RootKey
= list
->HKLM
;
2213 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
2215 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
2216 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
2218 RootKey
= hHWProfileKey
;
2221 if (KeyType
== DIREG_DEV
)
2223 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2225 rc
= RegCreateKeyExW(
2227 REGSTR_PATH_SYSTEMENUM
,
2230 REG_OPTION_NON_VOLATILE
,
2235 if (rc
!= ERROR_SUCCESS
)
2240 rc
= RegCreateKeyExW(
2242 deviceInfo
->DeviceName
,
2245 REG_OPTION_NON_VOLATILE
,
2246 #if _WIN32_WINNT >= 0x502
2247 KEY_READ
| KEY_WRITE
,
2254 if (rc
!= ERROR_SUCCESS
)
2260 else /* KeyType == DIREG_DRV */
2262 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
2264 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
2265 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
2268 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2271 strcpyW(DriverKey
, L
"{");
2272 strcatW(DriverKey
, lpGuidString
);
2273 strcatW(DriverKey
, L
"}\\");
2274 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
2275 rc
= RegOpenKeyExW(RootKey
,
2276 REGSTR_PATH_CLASS_NT
,
2280 if (rc
!= ERROR_SUCCESS
)
2286 /* Try all values for Index between 0 and 9999 */
2288 while (Index
<= 9999)
2291 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
2292 rc
= RegCreateKeyEx(hClassKey
,
2296 REG_OPTION_NON_VOLATILE
,
2297 #if _WIN32_WINNT >= 0x502
2298 KEY_READ
| KEY_WRITE
,
2305 if (rc
!= ERROR_SUCCESS
)
2310 if (Disposition
== REG_CREATED_NEW_KEY
)
2318 /* Unable to create more than 9999 devices within the same class */
2319 SetLastError(ERROR_GEN_FAILURE
);
2323 /* Open device key, to write Driver value */
2324 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
2325 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
2327 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
2328 if (rc
!= ERROR_SUCCESS
)
2335 /* Do installation of the specified section */
2338 FIXME("Need to install section %s in file %p\n",
2339 debugstr_w(InfSectionName
), InfHandle
);
2345 RpcStringFreeW(&lpGuidString
);
2346 HeapFree(GetProcessHeap(), 0, DriverKey
);
2347 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
2348 RegCloseKey(hHWProfileKey
);
2349 if (hEnumKey
!= NULL
)
2350 RegCloseKey(hEnumKey
);
2351 if (hClassKey
!= NULL
)
2352 RegCloseKey(hClassKey
);
2353 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
2354 RegCloseKey(hDeviceKey
);
2355 if (hKey
!= NULL
&& hKey
!= ret
)
2359 TRACE("Returning 0x%p\n", ret
);
2363 /***********************************************************************
2364 * SetupDiOpenDevRegKey (SETUPAPI.@)
2367 SetupDiOpenDevRegKey(
2368 IN HDEVINFO DeviceInfoSet
,
2369 IN PSP_DEVINFO_DATA DeviceInfoData
,
2373 IN REGSAM samDesired
)
2375 struct DeviceInfoSet
*list
;
2376 HKEY ret
= INVALID_HANDLE_VALUE
;
2378 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2379 Scope
, HwProfile
, KeyType
, samDesired
);
2382 SetLastError(ERROR_INVALID_HANDLE
);
2383 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2384 SetLastError(ERROR_INVALID_HANDLE
);
2385 else if (!DeviceInfoData
)
2386 SetLastError(ERROR_INVALID_PARAMETER
);
2387 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2388 SetLastError(ERROR_INVALID_USER_BUFFER
);
2389 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
2390 SetLastError(ERROR_INVALID_PARAMETER
);
2391 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
2392 SetLastError(ERROR_INVALID_PARAMETER
);
2395 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2396 LPWSTR DriverKey
= NULL
;
2400 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
2401 HKEY hEnumKey
= NULL
;
2405 if (Scope
== DICS_FLAG_GLOBAL
)
2406 RootKey
= list
->HKLM
;
2407 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
2409 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
2410 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
2412 RootKey
= hHWProfileKey
;
2417 REGSTR_PATH_SYSTEMENUM
,
2421 if (rc
!= ERROR_SUCCESS
)
2428 deviceInfo
->DeviceName
,
2430 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
2432 RegCloseKey(hEnumKey
);
2434 if (rc
!= ERROR_SUCCESS
)
2439 if (KeyType
== DIREG_DEV
)
2441 /* We're done. Just return the hKey handle */
2445 /* Read the 'Driver' key */
2446 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
2447 if (rc
!= ERROR_SUCCESS
)
2452 else if (dwRegType
!= REG_SZ
)
2454 SetLastError(ERROR_GEN_FAILURE
);
2457 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
2460 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2463 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
2464 if (rc
!= ERROR_SUCCESS
)
2471 /* Need to open the driver key */
2474 REGSTR_PATH_CLASS_NT
,
2478 if (rc
!= ERROR_SUCCESS
)
2489 if (rc
!= ERROR_SUCCESS
)
2497 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
2498 RegCloseKey(hHWProfileKey
);
2499 if (hEnumKey
!= NULL
)
2500 RegCloseKey(hEnumKey
);
2501 if (hKey
!= NULL
&& hKey
!= ret
)
2505 TRACE("Returning 0x%p\n", ret
);
2509 /***********************************************************************
2510 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
2513 SetupDiCreateDeviceInfoA(
2514 IN HDEVINFO DeviceInfoSet
,
2515 IN PCSTR DeviceName
,
2516 IN CONST GUID
*ClassGuid
,
2517 IN PCSTR DeviceDescription OPTIONAL
,
2518 IN HWND hwndParent OPTIONAL
,
2519 IN DWORD CreationFlags
,
2520 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2522 LPWSTR DeviceNameW
= NULL
;
2523 LPWSTR DeviceDescriptionW
= NULL
;
2530 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
2531 if (DeviceNameW
== NULL
) return FALSE
;
2533 if (DeviceDescription
)
2535 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
2536 if (DeviceDescriptionW
== NULL
)
2538 if (DeviceNameW
) MyFree(DeviceNameW
);
2543 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
2544 ClassGuid
, DeviceDescriptionW
,
2545 hwndParent
, CreationFlags
,
2548 if (DeviceNameW
) MyFree(DeviceNameW
);
2549 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
2554 /***********************************************************************
2555 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
2558 SetupDiCreateDeviceInfoW(
2559 IN HDEVINFO DeviceInfoSet
,
2560 IN PCWSTR DeviceName
,
2561 IN CONST GUID
*ClassGuid
,
2562 IN PCWSTR DeviceDescription OPTIONAL
,
2563 IN HWND hwndParent OPTIONAL
,
2564 IN DWORD CreationFlags
,
2565 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2567 struct DeviceInfoSet
*list
;
2570 TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
2571 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
2572 hwndParent
, CreationFlags
, DeviceInfoData
);
2575 SetLastError(ERROR_INVALID_HANDLE
);
2576 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2577 SetLastError(ERROR_INVALID_HANDLE
);
2578 else if (!ClassGuid
)
2579 SetLastError(ERROR_INVALID_PARAMETER
);
2580 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
2581 SetLastError(ERROR_CLASS_MISMATCH
);
2582 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
2584 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
2585 SetLastError(ERROR_INVALID_FLAGS
);
2589 SP_DEVINFO_DATA DevInfo
;
2591 if (CreationFlags
& DICD_GENERATE_ID
)
2593 /* Generate a new unique ID for this device */
2594 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2595 FIXME("not implemented\n");
2599 /* Device name is fully qualified. Try to open it */
2602 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
2603 rc
= SetupDiOpenDeviceInfoW(
2606 NULL
, /* hwndParent */
2607 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
2612 /* SetupDiOpenDeviceInfoW has already added
2613 * the device info to the device info set
2615 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
2617 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
2619 struct DeviceInfoElement
*deviceInfo
;
2621 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
2623 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
2625 if (!DeviceInfoData
)
2629 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
2631 SetLastError(ERROR_INVALID_USER_BUFFER
);
2635 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
2636 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
2637 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
2646 TRACE("Returning %d\n", ret
);
2651 /***********************************************************************
2652 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
2655 SetupDiDeleteDeviceInfo(
2656 IN HDEVINFO DeviceInfoSet
,
2657 IN PSP_DEVINFO_DATA DeviceInfoData
)
2659 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2661 FIXME("not implemented\n");
2662 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2667 /***********************************************************************
2668 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
2671 SetupDiOpenDeviceInfoA(
2672 IN HDEVINFO DeviceInfoSet
,
2673 IN PCSTR DeviceInstanceId
,
2674 IN HWND hwndParent OPTIONAL
,
2676 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2678 LPWSTR DeviceInstanceIdW
= NULL
;
2681 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
2683 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
2684 if (DeviceInstanceIdW
== NULL
)
2687 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
2688 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
2690 MyFree(DeviceInstanceIdW
);
2696 /***********************************************************************
2697 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
2700 SetupDiOpenDeviceInfoW(
2701 IN HDEVINFO DeviceInfoSet
,
2702 IN PCWSTR DeviceInstanceId
,
2703 IN HWND hwndParent OPTIONAL
,
2705 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2707 struct DeviceInfoSet
*list
;
2708 HKEY hEnumKey
, hKey
= NULL
;
2712 TRACE("%p %s %p %lx %p\n",
2713 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
2714 hwndParent
, OpenFlags
, DeviceInfoData
);
2716 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
2717 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
2720 SetLastError(ERROR_INVALID_HANDLE
);
2721 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2722 SetLastError(ERROR_INVALID_HANDLE
);
2723 else if (!DeviceInstanceId
)
2724 SetLastError(ERROR_INVALID_PARAMETER
);
2725 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
2727 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
2728 SetLastError(ERROR_INVALID_FLAGS
);
2730 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2731 SetLastError(ERROR_INVALID_USER_BUFFER
);
2734 struct DeviceInfoElement
*deviceInfo
= NULL
;
2735 /* Search if device already exists in DeviceInfoSet.
2736 * If yes, return the existing element
2737 * If no, create a new element using informations in registry
2739 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2740 while (ItemList
!= &list
->ListHead
)
2745 FIXME("not implemented\n");
2746 ItemList
= ItemList
->Flink
;
2751 /* good one found */
2756 /* Open supposed registry key */
2759 REGSTR_PATH_SYSTEMENUM
,
2763 if (rc
!= ERROR_SUCCESS
)
2774 RegCloseKey(hEnumKey
);
2775 if (rc
!= ERROR_SUCCESS
)
2777 if (rc
== ERROR_FILE_NOT_FOUND
)
2778 rc
= ERROR_NO_SUCH_DEVINST
;
2783 /* FIXME: try to get ClassGUID from registry, instead of
2784 * sending GUID_NULL to CreateDeviceInfoElement
2786 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
2788 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
2793 if (ret
&& deviceInfo
&& DeviceInfoData
)
2795 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
2796 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
2797 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
2808 /***********************************************************************
2809 * SetupDiGetSelectedDevice (SETUPAPI.@)
2812 SetupDiGetSelectedDevice(
2813 IN HDEVINFO DeviceInfoSet
,
2814 OUT PSP_DEVINFO_DATA DeviceInfoData
)
2816 struct DeviceInfoSet
*list
;
2819 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2822 SetLastError(ERROR_INVALID_HANDLE
);
2823 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2824 SetLastError(ERROR_INVALID_HANDLE
);
2825 else if (list
->SelectedDevice
== NULL
)
2826 SetLastError(ERROR_NO_DEVICE_SELECTED
);
2827 else if (!DeviceInfoData
)
2828 SetLastError(ERROR_INVALID_PARAMETER
);
2829 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2830 SetLastError(ERROR_INVALID_USER_BUFFER
);
2833 memcpy(&DeviceInfoData
->ClassGuid
,
2834 &list
->SelectedDevice
->ClassGuid
,
2836 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
2837 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
2841 TRACE("Returning %d\n", ret
);
2846 /***********************************************************************
2847 * SetupDiSetSelectedDevice (SETUPAPI.@)
2850 SetupDiSetSelectedDevice(
2851 IN HDEVINFO DeviceInfoSet
,
2852 IN PSP_DEVINFO_DATA DeviceInfoData
)
2854 struct DeviceInfoSet
*list
;
2857 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2860 SetLastError(ERROR_INVALID_HANDLE
);
2861 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2862 SetLastError(ERROR_INVALID_HANDLE
);
2863 else if (!DeviceInfoData
)
2864 SetLastError(ERROR_INVALID_PARAMETER
);
2865 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2866 SetLastError(ERROR_INVALID_USER_BUFFER
);
2867 else if (DeviceInfoData
->Reserved
== 0)
2868 SetLastError(ERROR_INVALID_USER_BUFFER
);
2871 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2875 TRACE("Returning %d\n", ret
);
2880 /* Return the current hardware profile id, or -1 if error */
2882 GetCurrentHwProfile(
2883 IN HDEVINFO DeviceInfoSet
)
2886 DWORD dwRegType
, dwLength
;
2889 DWORD ret
= (DWORD
)-1;
2892 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
2893 REGSTR_PATH_IDCONFIGDB
,
2897 if (rc
!= ERROR_SUCCESS
)
2903 dwLength
= sizeof(DWORD
);
2904 rc
= RegQueryValueExW(
2906 REGSTR_VAL_CURRENTCONFIG
,
2909 (LPBYTE
)&hwProfile
, &dwLength
);
2910 if (rc
!= ERROR_SUCCESS
)
2915 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
2917 SetLastError(ERROR_GEN_FAILURE
);
2932 IN HDEVINFO DeviceInfoSet
,
2933 IN PSP_DEVINFO_DATA DeviceInfoData
)
2936 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
2937 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2940 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
2942 /* At the moment, I only know how to start local devices */
2943 SetLastError(ERROR_INVALID_COMPUTERNAME
);
2947 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
2948 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
2949 SetLastError(RtlNtStatusToDosError(Status
));
2950 return NT_SUCCESS(Status
);
2952 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
2957 static BOOL
StopDevice(
2958 IN HDEVINFO DeviceInfoSet
,
2959 IN PSP_DEVINFO_DATA DeviceInfoData
)
2961 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
2965 /***********************************************************************
2966 * SetupDiChangeState (SETUPAPI.@)
2970 IN HDEVINFO DeviceInfoSet
,
2971 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
2973 PSP_PROPCHANGE_PARAMS PropChange
;
2974 HKEY hKey
= INVALID_HANDLE_VALUE
;
2975 LPCWSTR RegistryValueName
;
2976 DWORD dwConfigFlags
, dwLength
, dwRegType
;
2980 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2982 if (!DeviceInfoData
)
2983 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
2985 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
2988 SetLastError(ERROR_INVALID_PARAMETER
);
2992 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
2993 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
2995 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
2997 switch (PropChange
->StateChange
)
3002 /* Enable/disable device in registry */
3003 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
3004 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3005 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
3006 if (hKey
== INVALID_HANDLE_VALUE
)
3008 dwLength
= sizeof(DWORD
);
3009 rc
= RegQueryValueExW(
3014 (LPBYTE
)&dwConfigFlags
, &dwLength
);
3015 if (rc
== ERROR_FILE_NOT_FOUND
)
3017 else if (rc
!= ERROR_SUCCESS
)
3022 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
3024 SetLastError(ERROR_GEN_FAILURE
);
3027 if (PropChange
->StateChange
== DICS_ENABLE
)
3028 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
3030 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
3036 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
3037 if (rc
!= ERROR_SUCCESS
)
3043 /* Enable/disable device if needed */
3044 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
3045 || PropChange
->HwProfile
== 0
3046 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
3048 if (PropChange
->StateChange
== DICS_ENABLE
)
3049 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
3051 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
3057 case DICS_PROPCHANGE
:
3059 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
3064 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
3065 SetLastError(ERROR_NOT_SUPPORTED
);
3070 if (hKey
!= INVALID_HANDLE_VALUE
)
3073 TRACE("Returning %d\n", ret
);
3077 /***********************************************************************
3078 * SetupDiSelectDevice (SETUPAPI.@)
3081 SetupDiSelectDevice(
3082 IN HDEVINFO DeviceInfoSet
,
3083 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3085 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3086 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3091 /***********************************************************************
3092 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
3095 SetupDiRegisterCoDeviceInstallers(
3096 IN HDEVINFO DeviceInfoSet
,
3097 IN PSP_DEVINFO_DATA DeviceInfoData
)
3099 BOOL ret
= FALSE
; /* Return value */
3101 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3104 SetLastError(ERROR_INVALID_PARAMETER
);
3105 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3106 SetLastError(ERROR_INVALID_HANDLE
);
3107 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3108 SetLastError(ERROR_INVALID_HANDLE
);
3109 else if (!DeviceInfoData
)
3110 SetLastError(ERROR_INVALID_PARAMETER
);
3111 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3112 SetLastError(ERROR_INVALID_USER_BUFFER
);
3115 SP_DEVINSTALL_PARAMS_W InstallParams
;
3116 struct DriverInfoElement
*SelectedDriver
;
3119 WCHAR SectionName
[MAX_PATH
];
3120 DWORD SectionNameLength
= 0;
3121 HKEY hKey
= INVALID_HANDLE_VALUE
;
3122 PVOID Context
= NULL
;
3124 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3125 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3129 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
3130 if (SelectedDriver
== NULL
)
3132 SetLastError(ERROR_NO_DRIVER_SELECTED
);
3136 /* Get .CoInstallers section name */
3137 Result
= SetupDiGetActualSectionToInstallW(
3138 SelectedDriver
->InfFileDetails
->hInf
,
3139 SelectedDriver
->Details
.SectionName
,
3140 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
3141 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
3143 lstrcatW(SectionName
, DotCoInstallers
);
3145 /* Open/Create driver key information */
3146 #if _WIN32_WINNT >= 0x502
3147 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
3149 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
3151 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3152 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
3153 if (hKey
== INVALID_HANDLE_VALUE
)
3156 /* Install .CoInstallers section */
3157 DoAction
= SPINST_REGISTRY
;
3158 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
3160 DoAction
|= SPINST_FILES
;
3161 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
3165 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
3166 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
3167 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
3168 SetupDefaultQueueCallback
, Context
,
3169 DeviceInfoSet
, DeviceInfoData
);
3177 SetupTermDefaultQueueCallback(Context
);
3178 if (hKey
!= INVALID_HANDLE_VALUE
)
3182 TRACE("Returning %d\n", ret
);
3187 InfIsFromOEMLocation(
3189 OUT LPBOOL IsOEMLocation
)
3193 last
= strrchrW(FullName
, '\\');
3196 /* No directory specified */
3197 *IsOEMLocation
= FALSE
;
3204 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
3207 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3211 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
3212 if (ret
== 0 || ret
> MAX_PATH
)
3215 SetLastError(ERROR_GEN_FAILURE
);
3218 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
3219 strcatW(Windir
, BackSlash
);
3220 strcatW(Windir
, InfDirectory
);
3222 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
3224 /* The path is %SYSTEMROOT%\Inf */
3225 *IsOEMLocation
= FALSE
;
3229 /* The file is in another place */
3230 *IsOEMLocation
= TRUE
;
3237 /***********************************************************************
3238 * SetupDiInstallDevice (SETUPAPI.@)
3241 SetupDiInstallDevice(
3242 IN HDEVINFO DeviceInfoSet
,
3243 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3245 SP_DEVINSTALL_PARAMS_W InstallParams
;
3246 struct DriverInfoElement
*SelectedDriver
;
3247 SYSTEMTIME DriverDate
;
3248 WCHAR SectionName
[MAX_PATH
];
3250 DWORD SectionNameLength
= 0;
3251 BOOL Result
= FALSE
;
3254 LPWSTR pSectionName
= NULL
;
3255 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
3257 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
3258 BOOL RebootRequired
= FALSE
;
3259 HKEY hKey
= INVALID_HANDLE_VALUE
;
3260 BOOL NeedtoCopyFile
;
3261 LARGE_INTEGER fullVersion
;
3263 PVOID Context
= NULL
;
3264 BOOL ret
= FALSE
; /* Return value */
3266 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
3269 SetLastError(ERROR_INVALID_PARAMETER
);
3270 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3271 SetLastError(ERROR_INVALID_HANDLE
);
3272 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3273 SetLastError(ERROR_INVALID_HANDLE
);
3274 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3275 SetLastError(ERROR_INVALID_USER_BUFFER
);
3281 /* One parameter is bad */
3285 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3286 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3290 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
3292 /* Set FAILEDINSTALL in ConfigFlags registry value */
3293 DWORD ConfigFlags
, regType
;
3294 Result
= SetupDiGetDeviceRegistryPropertyW(
3299 (PBYTE
)&ConfigFlags
,
3300 sizeof(ConfigFlags
),
3302 if (!Result
|| regType
!= REG_DWORD
)
3304 SetLastError(ERROR_GEN_FAILURE
);
3307 ConfigFlags
|= DNF_DISABLED
;
3308 Result
= SetupDiSetDeviceRegistryPropertyW(
3312 (PBYTE
)&ConfigFlags
,
3313 sizeof(ConfigFlags
));
3316 SetLastError(ERROR_GEN_FAILURE
);
3324 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
3325 if (SelectedDriver
== NULL
)
3327 SetLastError(ERROR_NO_DRIVER_SELECTED
);
3331 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
3333 Result
= SetupDiGetActualSectionToInstallW(
3334 SelectedDriver
->InfFileDetails
->hInf
,
3335 SelectedDriver
->Details
.SectionName
,
3336 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
3337 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
3339 pSectionName
= &SectionName
[strlenW(SectionName
)];
3341 /* Get information from [Version] section */
3342 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
3344 /* Format ClassGuid to a string */
3345 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3347 RequiredSize
= lstrlenW(lpGuidString
);
3348 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
3349 if (!lpFullGuidString
)
3351 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3354 lpFullGuidString
[0] = '{';
3355 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
3356 lpFullGuidString
[RequiredSize
+ 1] = '}';
3357 lpFullGuidString
[RequiredSize
+ 2] = '\0';
3359 /* Copy .inf file to Inf\ directory (if needed) */
3360 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
3365 WCHAR NewFileName
[MAX_PATH
];
3366 struct InfFileDetails
*newInfFileDetails
;
3367 Result
= SetupCopyOEMInfW(
3368 SelectedDriver
->Details
.InfFileName
,
3371 SP_COPY_NOOVERWRITE
,
3372 NewFileName
, MAX_PATH
,
3377 /* Create a new struct InfFileDetails, and set it to
3378 * SelectedDriver->InfFileDetails, to release use of
3379 * current InfFile */
3380 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
3381 if (!newInfFileDetails
)
3383 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
3384 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
3385 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
3388 /* Open/Create driver key information */
3389 #if _WIN32_WINNT >= 0x502
3390 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
3392 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
3394 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
3395 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
3396 if (hKey
== INVALID_HANDLE_VALUE
)
3399 /* Install main section */
3401 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
3402 DoAction
|= SPINST_REGISTRY
;
3403 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
3405 DoAction
|= SPINST_FILES
;
3406 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
3410 *pSectionName
= '\0';
3411 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
3412 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
3413 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
3414 SetupDefaultQueueCallback
, Context
,
3415 DeviceInfoSet
, DeviceInfoData
);
3418 InstallParams
.Flags
|= DI_NOFILECOPY
;
3419 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3421 /* Write information to driver key */
3422 *pSectionName
= UNICODE_NULL
;
3423 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
3424 TRACE("Write information to driver key\n");
3425 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
3426 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
3427 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
3428 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
3429 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
3430 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
3431 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
3432 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
3433 sprintfW(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
3434 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
3435 if (rc
== ERROR_SUCCESS
)
3436 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
3437 if (rc
== ERROR_SUCCESS
)
3438 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
3439 if (rc
== ERROR_SUCCESS
)
3441 sprintfW(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
3442 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
3444 if (rc
== ERROR_SUCCESS
)
3445 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
3446 if (rc
== ERROR_SUCCESS
)
3447 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
3448 if (rc
== ERROR_SUCCESS
)
3449 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
));
3450 if (rc
== ERROR_SUCCESS
)
3451 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
3452 if (rc
== ERROR_SUCCESS
)
3453 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
3454 if (rc
!= ERROR_SUCCESS
)
3460 hKey
= INVALID_HANDLE_VALUE
;
3462 /* FIXME: Process .LogConfigOverride section */
3464 /* Install .Services section */
3465 strcpyW(pSectionName
, DotServices
);
3466 Result
= SetupInstallServicesFromInfSectionExW(
3467 SelectedDriver
->InfFileDetails
->hInf
,
3476 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
3477 RebootRequired
= TRUE
;
3479 /* Open device registry key */
3480 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3481 if (hKey
== INVALID_HANDLE_VALUE
)
3484 /* Install .HW section */
3486 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
3487 DoAction
|= SPINST_REGISTRY
;
3488 strcpyW(pSectionName
, DotHW
);
3489 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
3490 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
3491 DoAction
, hKey
, NULL
, 0,
3493 DeviceInfoSet
, DeviceInfoData
);
3497 /* Write information to enum key */
3498 TRACE("Write information to enum key\n");
3499 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
3500 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
3501 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
3502 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
3503 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
3504 if (rc
== ERROR_SUCCESS
)
3505 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
3506 if (rc
== ERROR_SUCCESS
)
3507 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
3508 if (rc
== ERROR_SUCCESS
)
3509 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
3510 if (rc
!= ERROR_SUCCESS
)
3516 /* Start the device */
3517 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
3518 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
3523 /* End of installation */
3524 if (hKey
!= INVALID_HANDLE_VALUE
)
3527 RpcStringFreeW(&lpGuidString
);
3528 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3530 SetupTermDefaultQueueCallback(Context
);
3531 TRACE("Returning %d\n", ret
);