2 * SetupAPI driver-related functions
4 * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "setupapi_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
25 /* Unicode constants */
26 static const WCHAR BackSlash
[] = {'\\',0};
27 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
28 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
29 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
30 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
32 static const WCHAR INF_MANUFACTURER
[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
33 static const WCHAR INF_PROVIDER
[] = {'P','r','o','v','i','d','e','r',0};
34 static const WCHAR INF_DRIVER_VER
[] = {'D','r','i','v','e','r','V','e','r',0};
37 /***********************************************************************
38 * struct InfFileDetails management
41 ReferenceInfFile(struct InfFileDetails
* infFile
)
43 InterlockedIncrement(&infFile
->References
);
47 DereferenceInfFile(struct InfFileDetails
* infFile
)
49 if (InterlockedDecrement(&infFile
->References
) == 0)
51 SetupCloseInfFile(infFile
->hInf
);
52 HeapFree(GetProcessHeap(), 0, infFile
);
56 struct InfFileDetails
*
58 IN LPCWSTR FullInfFileName
)
60 struct InfFileDetails
*details
;
64 Needed
= FIELD_OFFSET(struct InfFileDetails
, szData
)
65 + strlenW(FullInfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
67 details
= HeapAlloc(GetProcessHeap(), 0, Needed
);
70 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
74 memset(details
, 0, Needed
);
75 strcpyW(details
->szData
, FullInfFileName
);
76 last
= strrchrW(details
->szData
, '\\');
79 details
->DirectoryName
= details
->szData
;
80 details
->FileName
= last
+ 1;
84 details
->FileName
= details
->szData
;
85 ReferenceInfFile(details
);
86 details
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
87 if (details
->hInf
== INVALID_HANDLE_VALUE
)
89 HeapFree(GetProcessHeap(), 0, details
);
96 DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
98 DereferenceInfFile(driverInfo
->InfFileDetails
);
99 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
100 HeapFree(GetProcessHeap(), 0, driverInfo
);
104 /***********************************************************************
105 * Helper functions for SetupDiBuildDriverInfoList
108 AddKnownDriverToList(
109 IN PLIST_ENTRY DriverListHead
,
110 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
112 IN
struct InfFileDetails
*InfFileDetails
,
114 IN LPCWSTR SectionName
,
115 IN LPCWSTR DriverDescription
,
116 IN LPCWSTR ProviderName
,
117 IN LPCWSTR ManufacturerName
,
118 IN LPCWSTR MatchingId
,
119 IN FILETIME DriverDate
,
120 IN DWORDLONG DriverVersion
,
123 struct DriverInfoElement
*driverInfo
= NULL
;
124 HANDLE hFile
= INVALID_HANDLE_VALUE
;
126 PLIST_ENTRY PreviousEntry
;
129 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
132 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
135 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
137 driverInfo
->Params
.cbSize
= sizeof(SP_DRVINSTALL_PARAMS
);
138 driverInfo
->Params
.Reserved
= (ULONG_PTR
)driverInfo
;
140 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
141 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
143 /* Copy InfFileName field */
144 lstrcpynW(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
145 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
147 /* Fill InfDate field */
150 GENERIC_READ
, FILE_SHARE_READ
,
151 NULL
, OPEN_EXISTING
, 0, NULL
);
152 if (hFile
== INVALID_HANDLE_VALUE
)
154 Result
= GetFileTime(hFile
, NULL
, NULL
, &driverInfo
->Details
.InfDate
);
158 /* Fill SectionName field */
159 lstrcpynW(driverInfo
->Details
.SectionName
, SectionName
, LINE_LEN
);
161 /* Fill DrvDescription field */
162 lstrcpynW(driverInfo
->Details
.DrvDescription
, DriverDescription
, LINE_LEN
);
164 /* Copy MatchingId information */
167 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
168 if (!driverInfo
->MatchingId
)
170 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
173 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
176 driverInfo
->MatchingId
= NULL
;
178 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
179 debugstr_w(driverInfo
->Details
.DrvDescription
), debugstr_w(InfFile
),
180 debugstr_w(SectionName
), Rank
);
182 driverInfo
->Params
.Rank
= Rank
;
183 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
184 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
185 driverInfo
->Info
.DriverType
= DriverType
;
186 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
187 lstrcpynW(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
188 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
189 lstrcpynW(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
190 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
193 lstrcpynW(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
194 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
197 driverInfo
->Info
.ProviderName
[0] = '\0';
198 driverInfo
->Info
.DriverDate
= DriverDate
;
199 driverInfo
->Info
.DriverVersion
= DriverVersion
;
200 ReferenceInfFile(InfFileDetails
);
201 driverInfo
->InfFileDetails
= InfFileDetails
;
203 /* Insert current driver in driver list, according to its rank */
204 PreviousEntry
= DriverListHead
->Flink
;
205 while (PreviousEntry
!= DriverListHead
)
207 struct DriverInfoElement
*CurrentDriver
;
208 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
209 if (CurrentDriver
->Params
.Rank
> Rank
||
210 (CurrentDriver
->Params
.Rank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
< driverInfo
->DriverDate
.QuadPart
))
212 /* Insert before the current item */
213 InsertHeadList(PreviousEntry
->Blink
, &driverInfo
->ListEntry
);
216 PreviousEntry
= PreviousEntry
->Flink
;
218 if (PreviousEntry
== DriverListHead
)
220 /* Insert at the end of the list */
221 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
230 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
231 HeapFree(GetProcessHeap(), 0, driverInfo
);
233 if (hFile
!= INVALID_HANDLE_VALUE
)
241 IN PLIST_ENTRY DriverListHead
,
242 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
244 IN INFCONTEXT ContextDevice
,
245 IN
struct InfFileDetails
*InfFileDetails
,
247 IN LPCWSTR ProviderName
,
248 IN LPCWSTR ManufacturerName
,
249 IN LPCWSTR MatchingId
,
250 IN FILETIME DriverDate
,
251 IN DWORDLONG DriverVersion
,
254 LPWSTR SectionName
= NULL
;
255 LPWSTR DriverDescription
= NULL
;
259 /* Read SectionName */
260 SectionName
= MyMalloc(LINE_LEN
);
263 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
266 ZeroMemory(SectionName
, LINE_LEN
);
267 Result
= SetupGetStringFieldW(
276 /* Read DriverDescription */
277 DriverDescription
= MyMalloc(LINE_LEN
);
278 if (!DriverDescription
)
280 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
283 ZeroMemory(DriverDescription
, LINE_LEN
);
284 Result
= SetupGetStringFieldW(
287 DriverDescription
, LINE_LEN
,
290 ret
= AddKnownDriverToList(
307 MyFree(DriverDescription
);
313 GetVersionInformationFromInfFile(
315 OUT LPGUID ClassGuid
,
316 OUT LPWSTR
* pProviderName
,
317 OUT FILETIME
* DriverDate
,
318 OUT DWORDLONG
* DriverVersion
)
321 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
322 LPWSTR DriverVer
= NULL
;
323 LPWSTR ProviderName
= NULL
;
324 LPWSTR pComma
; /* Points into DriverVer */
325 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
326 SYSTEMTIME SystemTime
;
328 BOOL ret
= FALSE
; /* Final result */
331 if (!SetupGetLineTextW(
335 guidW
, sizeof(guidW
),
336 NULL
/* Required size */))
340 guidW
[37] = '\0'; /* Replace the } by a NULL character */
341 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
343 SetLastError(ERROR_GEN_FAILURE
);
347 /* Get provider name */
348 Result
= SetupGetLineTextW(
350 hInf
, Version
, INF_PROVIDER
,
355 /* We know the needed buffer size */
356 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
359 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
362 Result
= SetupGetLineTextW(
364 hInf
, Version
, INF_PROVIDER
,
365 ProviderName
, RequiredSize
,
370 *pProviderName
= ProviderName
;
372 /* Read the "DriverVer" value */
373 Result
= SetupGetLineTextW(
375 hInf
, Version
, INF_DRIVER_VER
,
380 /* We know know the needed buffer size */
381 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
384 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
387 Result
= SetupGetLineTextW(
389 hInf
, Version
, INF_DRIVER_VER
,
390 DriverVer
, RequiredSize
,
395 /* windows sets default date of 00/00/0000 when this directive is missing*/
396 memset(DriverDate
, 0, sizeof(FILETIME
));
401 /* Get driver date and driver version, by analyzing the "DriverVer" value */
402 pComma
= strchrW(DriverVer
, ',');
405 *pComma
= UNICODE_NULL
;
406 pVersion
= pComma
+ 1;
408 /* Get driver date version. Invalid date = 00/00/00 */
409 memset(DriverDate
, 0, sizeof(FILETIME
));
410 if (strlenW(DriverVer
) == 10
411 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
412 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
414 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
415 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
416 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
417 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
418 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
419 SystemTimeToFileTime(&SystemTime
, DriverDate
);
421 /* Get driver version. Invalid version = 0.0.0.0 */
425 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
426 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
427 LARGE_INTEGER fullVersion
;
429 pMinor
= strchrW(pVersion
, '.');
433 pRevision
= strchrW(++pMinor
, '.');
434 Minor
= atoiW(pMinor
);
439 pBuild
= strchrW(++pRevision
, '.');
440 Revision
= atoiW(pRevision
);
446 Build
= atoiW(pBuild
);
448 Major
= atoiW(pVersion
);
449 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
450 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
451 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
459 HeapFree(GetProcessHeap(), 0, ProviderName
);
460 *pProviderName
= NULL
;
462 HeapFree(GetProcessHeap(), 0, DriverVer
);
468 GetHardwareAndCompatibleIDsLists(
469 IN HDEVINFO DeviceInfoSet
,
470 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
471 OUT LPWSTR
*pHardwareIDs OPTIONAL
,
472 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL
,
473 OUT LPWSTR
*pCompatibleIDs OPTIONAL
,
474 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL
)
476 LPWSTR HardwareIDs
= NULL
;
477 LPWSTR CompatibleIDs
= NULL
;
481 /* Get hardware IDs list */
483 RequiredSize
= 512; /* Initial buffer size */
484 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
485 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
488 HardwareIDs
= MyMalloc(RequiredSize
);
491 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
494 Result
= SetupDiGetDeviceRegistryPropertyW(
505 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
507 /* No hardware ID for this device */
516 *pHardwareIDs
= HardwareIDs
;
517 if (pHardwareIDsRequiredSize
)
518 *pHardwareIDsRequiredSize
= RequiredSize
;
520 /* Get compatible IDs list */
522 RequiredSize
= 512; /* Initial buffer size */
523 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
524 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
526 MyFree(CompatibleIDs
);
527 CompatibleIDs
= MyMalloc(RequiredSize
);
530 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
533 Result
= SetupDiGetDeviceRegistryPropertyW(
538 (PBYTE
)CompatibleIDs
,
544 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
546 /* No compatible ID for this device */
547 MyFree(CompatibleIDs
);
548 CompatibleIDs
= NULL
;
555 *pCompatibleIDs
= CompatibleIDs
;
556 if (pCompatibleIDsRequiredSize
)
557 *pCompatibleIDsRequiredSize
= RequiredSize
;
565 MyFree(CompatibleIDs
);
570 #if WIN32_WINNT < 0x0600
572 * This code has been copied from advapi32/reg/reg.c,
573 * so this dll can be tested as is on Windows XP
576 #define RRF_RT_REG_NONE (1 << 0)
577 #define RRF_RT_REG_SZ (1 << 1)
578 #define RRF_RT_REG_EXPAND_SZ (1 << 2)
579 #define RRF_RT_REG_BINARY (1 << 3)
580 #define RRF_RT_REG_DWORD (1 << 4)
581 #define RRF_RT_REG_MULTI_SZ (1 << 5)
582 #define RRF_RT_REG_QWORD (1 << 6)
583 #define RRF_RT_DWORD (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD)
584 #define RRF_RT_QWORD (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD)
585 #define RRF_NOEXPAND (1 << 28)
586 #define RRF_ZEROONFAILURE (1 << 29)
589 RegpApplyRestrictions( DWORD dwFlags
, DWORD dwType
, DWORD cbData
,
592 /* Check if the type is restricted by the passed flags */
593 if (*ret
== ERROR_SUCCESS
|| *ret
== ERROR_MORE_DATA
)
599 case REG_NONE
: dwMask
= RRF_RT_REG_NONE
; break;
600 case REG_SZ
: dwMask
= RRF_RT_REG_SZ
; break;
601 case REG_EXPAND_SZ
: dwMask
= RRF_RT_REG_EXPAND_SZ
; break;
602 case REG_MULTI_SZ
: dwMask
= RRF_RT_REG_MULTI_SZ
; break;
603 case REG_BINARY
: dwMask
= RRF_RT_REG_BINARY
; break;
604 case REG_DWORD
: dwMask
= RRF_RT_REG_DWORD
; break;
605 case REG_QWORD
: dwMask
= RRF_RT_REG_QWORD
; break;
608 if (dwFlags
& dwMask
)
610 /* Type is not restricted, check for size mismatch */
611 if (dwType
== REG_BINARY
)
615 if ((dwFlags
& RRF_RT_DWORD
) == RRF_RT_DWORD
)
617 else if ((dwFlags
& RRF_RT_QWORD
) == RRF_RT_QWORD
)
620 if (cbExpect
&& cbData
!= cbExpect
)
621 *ret
= ERROR_DATATYPE_MISMATCH
;
624 else *ret
= ERROR_UNSUPPORTED_TYPE
;
629 RegGetValueW( HKEY hKey
, LPCWSTR pszSubKey
, LPCWSTR pszValue
,
630 DWORD dwFlags
, LPDWORD pdwType
, PVOID pvData
,
633 DWORD dwType
, cbData
= pcbData
? *pcbData
: 0;
637 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
638 hKey
, debugstr_w(pszSubKey
), debugstr_w(pszValue
), dwFlags
, pdwType
,
639 pvData
, pcbData
, cbData
);
641 if ((dwFlags
& RRF_RT_REG_EXPAND_SZ
) && !(dwFlags
& RRF_NOEXPAND
))
642 return ERROR_INVALID_PARAMETER
;
644 if (pszSubKey
&& pszSubKey
[0])
646 ret
= RegOpenKeyExW(hKey
, pszSubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
647 if (ret
!= ERROR_SUCCESS
) return ret
;
650 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwType
, pvData
, &cbData
);
652 /* If we are going to expand we need to read in the whole the value even
653 * if the passed buffer was too small as the expanded string might be
654 * smaller than the unexpanded one and could fit into cbData bytes. */
655 if ((ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) &&
656 (dwType
== REG_EXPAND_SZ
&& !(dwFlags
& RRF_NOEXPAND
)))
659 if (pvBuf
) HeapFree(GetProcessHeap(), 0, pvBuf
);
661 pvBuf
= HeapAlloc(GetProcessHeap(), 0, cbData
);
664 ret
= ERROR_NOT_ENOUGH_MEMORY
;
668 if (ret
== ERROR_MORE_DATA
)
669 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
,
670 &dwType
, pvBuf
, &cbData
);
673 /* Even if cbData was large enough we have to copy the
674 * string since ExpandEnvironmentStrings can't handle
675 * overlapping buffers. */
676 CopyMemory(pvBuf
, pvData
, cbData
);
679 /* Both the type or the value itself could have been modified in
680 * between so we have to keep retrying until the buffer is large
681 * enough or we no longer have to expand the value. */
682 } while (dwType
== REG_EXPAND_SZ
&& ret
== ERROR_MORE_DATA
);
684 if (ret
== ERROR_SUCCESS
)
686 if (dwType
== REG_EXPAND_SZ
)
688 cbData
= ExpandEnvironmentStringsW(pvBuf
, pvData
,
689 pcbData
? (*pcbData
)/sizeof(WCHAR
) : 0);
691 if(pcbData
&& cbData
> ((*pcbData
)/sizeof(WCHAR
)))
692 ret
= ERROR_MORE_DATA
;
695 CopyMemory(pvData
, pvBuf
, *pcbData
);
698 if (pvBuf
) HeapFree(GetProcessHeap(), 0, pvBuf
);
701 if (pszSubKey
&& pszSubKey
[0])
704 RegpApplyRestrictions(dwFlags
, dwType
, cbData
, &ret
);
706 if (pcbData
&& ret
!= ERROR_SUCCESS
&& (dwFlags
& RRF_ZEROONFAILURE
))
707 ZeroMemory(pvData
, *pcbData
);
709 if (pdwType
) *pdwType
= dwType
;
710 if (pcbData
) *pcbData
= cbData
;
714 #endif /* End of code copied from advapi32/reg/reg.c */
716 /***********************************************************************
717 * SetupDiBuildDriverInfoList (SETUPAPI.@)
720 SetupDiBuildDriverInfoList(
721 IN HDEVINFO DeviceInfoSet
,
722 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
725 struct DeviceInfoSet
*list
;
726 SP_DEVINSTALL_PARAMS_W InstallParams
;
728 struct InfFileDetails
*currentInfFileDetails
= NULL
;
729 LPWSTR ProviderName
= NULL
;
730 LPWSTR ManufacturerName
= NULL
;
731 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
732 LPWSTR HardwareIDs
= NULL
;
733 LPWSTR CompatibleIDs
= NULL
;
734 LPWSTR FullInfFileName
= NULL
;
735 LPWSTR ExcludeFromSelect
= NULL
;
737 DWORDLONG DriverVersion
= 0;
741 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
744 SetLastError(ERROR_INVALID_HANDLE
);
745 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
746 SetLastError(ERROR_INVALID_HANDLE
);
747 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
748 SetLastError(ERROR_INVALID_HANDLE
);
749 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
750 SetLastError(ERROR_INVALID_PARAMETER
);
751 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
752 SetLastError(ERROR_INVALID_PARAMETER
);
753 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
754 SetLastError(ERROR_INVALID_USER_BUFFER
);
757 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
760 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
761 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
767 struct DeviceInfo
*devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
768 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
769 pDriverListHead
= &devInfo
->DriverListHead
;
772 if (DriverType
== SPDIT_COMPATDRIVER
)
774 /* Get hardware and compatible IDs lists */
775 Result
= GetHardwareAndCompatibleIDsLists(
784 if (!HardwareIDs
&& !CompatibleIDs
)
786 SetLastError(ERROR_FILE_NOT_FOUND
);
791 if (InstallParams
.FlagsEx
& DI_FLAGSEX_INSTALLEDDRIVER
)
794 WCHAR InfFileName
[MAX_PATH
];
795 WCHAR InfFileSection
[MAX_PATH
];
797 struct DeviceInfo
*devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
798 struct InfFileDetails
*infFileDetails
= NULL
;
803 /* Prepend inf directory name to file name */
804 len
= sizeof(InfFileName
) / sizeof(InfFileName
[0]);
805 RequiredSize
= GetSystemWindowsDirectoryW(InfFileName
, len
);
806 if (RequiredSize
== 0 || RequiredSize
>= len
)
808 if (*InfFileName
&& InfFileName
[strlenW(InfFileName
) - 1] != '\\')
809 strcatW(InfFileName
, BackSlash
);
810 strcatW(InfFileName
, InfDirectory
);
812 /* Read some information from registry, before creating the driver structure */
813 hDriverKey
= SetupDiOpenDevRegKey(
820 if (hDriverKey
== INVALID_HANDLE_VALUE
)
822 RequiredSize
= (len
- strlenW(InfFileName
)) * sizeof(WCHAR
);
829 &InfFileName
[strlenW(InfFileName
)],
831 if (rc
!= ERROR_SUCCESS
)
834 CloseHandle(hDriverKey
);
837 RequiredSize
= sizeof(InfFileSection
);
841 REGSTR_VAL_INFSECTION
,
846 if (rc
!= ERROR_SUCCESS
)
849 CloseHandle(hDriverKey
);
852 TRACE("Current driver in %s/%s\n", debugstr_w(InfFileName
), debugstr_w(InfFileSection
));
853 infFileDetails
= CreateInfFileDetails(InfFileName
);
856 CloseHandle(hDriverKey
);
859 DriverDate
.dwLowDateTime
= DriverDate
.dwHighDateTime
= 0; /* FIXME */
860 CloseHandle(hDriverKey
);
861 ret
= AddKnownDriverToList(
867 InfFileSection
, /* Yes, we don't care of section extension */
868 L
"DriverDescription", /* FIXME */
869 L
"ProviderName", /* FIXME */
870 L
"ManufacturerName", /* FIXME */
871 L
"MatchingId", /* FIXME */
873 0, /* FIXME: DriverVersion */
876 DereferenceInfFile(infFileDetails
);
879 else if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
881 /* InstallParams.DriverPath contains the name of a .inf file */
882 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
883 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
886 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
889 strcpyW(Buffer
, InstallParams
.DriverPath
);
890 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
895 /* Enumerate .inf files */
897 RequiredSize
= 32768; /* Initial buffer size */
898 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
899 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
901 HeapFree(GetProcessHeap(), 0, Buffer
);
902 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
906 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
909 Result
= SetupGetInfFileListW(
910 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
912 Buffer
, RequiredSize
,
915 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
917 /* No .inf file in specified directory. So, we should
918 * success as we created an empty driver info list.
927 LPWSTR pFullFilename
;
929 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
931 /* Only a filename */
932 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
933 if (!FullInfFileName
)
935 pFullFilename
= &FullInfFileName
[0];
937 else if (*InstallParams
.DriverPath
)
939 /* Directory name specified */
941 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
944 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + MAX_PATH
) * sizeof(WCHAR
));
945 if (!FullInfFileName
)
947 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
950 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
951 strcatW(FullInfFileName
, BackSlash
);
952 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
956 /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */
958 len
= GetSystemWindowsDirectoryW(NULL
, 0);
961 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + strlenW(InfDirectory
) + MAX_PATH
) * sizeof(WCHAR
));
962 if (!FullInfFileName
)
964 len
= GetSystemWindowsDirectoryW(FullInfFileName
, len
);
967 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
968 strcatW(FullInfFileName
, BackSlash
);
969 strcatW(FullInfFileName
, InfDirectory
);
970 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
973 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
975 INFCONTEXT ContextManufacturer
, ContextDevice
;
978 strcpyW(pFullFilename
, filename
);
979 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
981 currentInfFileDetails
= CreateInfFileDetails(FullInfFileName
);
982 if (!currentInfFileDetails
)
985 if (!GetVersionInformationFromInfFile(
986 currentInfFileDetails
->hInf
,
992 DereferenceInfFile(currentInfFileDetails
);
993 currentInfFileDetails
= NULL
;
997 if (DriverType
== SPDIT_CLASSDRIVER
)
999 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
1000 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1006 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
1008 /* Read ExcludeFromSelect control flags */
1012 FIXME("ExcludeFromSelect list ignored\n");
1014 /* Get the manufacturers list */
1015 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
1018 Result
= SetupGetStringFieldW(
1019 &ContextManufacturer
,
1020 0, /* Field index */
1025 /* We got the needed size for the buffer */
1026 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
1027 if (!ManufacturerName
)
1029 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1032 Result
= SetupGetStringFieldW(
1033 &ContextManufacturer
,
1034 0, /* Field index */
1035 ManufacturerName
, RequiredSize
,
1038 /* Get manufacturer section name */
1039 Result
= SetupGetStringFieldW(
1040 &ContextManufacturer
,
1041 1, /* Field index */
1042 ManufacturerSection
, LINE_LEN
,
1046 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
1047 /* Add (possible) extension to manufacturer section name */
1048 Result
= SetupDiGetActualSectionToInstallW(
1049 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
1052 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
1053 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
1058 if (DriverType
== SPDIT_CLASSDRIVER
)
1060 /* FIXME: Check ExcludeFromSelect list */
1061 if (!AddDriverToList(
1066 currentInfFileDetails
,
1071 DriverDate
, DriverVersion
,
1077 else /* DriverType = SPDIT_COMPATDRIVER */
1079 /* 1. Get all fields */
1080 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
1084 BOOL DriverAlreadyAdded
;
1086 for (i
= 2; i
<= FieldCount
; i
++)
1088 LPWSTR DeviceId
= NULL
;
1090 RequiredSize
= 128; /* Initial buffer size */
1091 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1092 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1094 HeapFree(GetProcessHeap(), 0, DeviceId
);
1095 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
1098 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1101 Result
= SetupGetStringFieldW(
1104 DeviceId
, RequiredSize
,
1109 HeapFree(GetProcessHeap(), 0, DeviceId
);
1112 /* FIXME: Check ExcludeFromSelect list */
1113 DriverAlreadyAdded
= FALSE
;
1114 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
1116 if (strcmpiW(DeviceId
, currentId
) == 0)
1123 currentInfFileDetails
,
1128 DriverDate
, DriverVersion
,
1129 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
1130 DriverAlreadyAdded
= TRUE
;
1135 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
1137 if (strcmpiW(DeviceId
, currentId
) == 0)
1144 currentInfFileDetails
,
1149 DriverDate
, DriverVersion
,
1150 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
1151 DriverAlreadyAdded
= TRUE
;
1155 HeapFree(GetProcessHeap(), 0, DeviceId
);
1158 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
1161 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
1162 ManufacturerName
= NULL
;
1163 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
1168 HeapFree(GetProcessHeap(), 0, ProviderName
);
1169 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
1170 ProviderName
= ExcludeFromSelect
= NULL
;
1172 DereferenceInfFile(currentInfFileDetails
);
1173 currentInfFileDetails
= NULL
;
1184 InstallParams
.Flags
|= DI_DIDCOMPAT
;
1185 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
1189 InstallParams
.Flags
|= DI_DIDCLASS
;
1190 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
1192 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1195 HeapFree(GetProcessHeap(), 0, ProviderName
);
1196 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
1197 MyFree(HardwareIDs
);
1198 MyFree(CompatibleIDs
);
1199 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
1200 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
1201 if (currentInfFileDetails
)
1202 DereferenceInfFile(currentInfFileDetails
);
1203 HeapFree(GetProcessHeap(), 0, Buffer
);
1205 TRACE("Returning %d\n", ret
);
1209 /***********************************************************************
1210 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
1213 SetupDiDestroyDriverInfoList(
1214 IN HDEVINFO DeviceInfoSet
,
1215 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1216 IN DWORD DriverType
)
1218 struct DeviceInfoSet
*list
;
1221 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
1224 SetLastError(ERROR_INVALID_HANDLE
);
1225 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1226 SetLastError(ERROR_INVALID_HANDLE
);
1227 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
1228 SetLastError(ERROR_INVALID_PARAMETER
);
1229 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
1230 SetLastError(ERROR_INVALID_PARAMETER
);
1231 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1232 SetLastError(ERROR_INVALID_USER_BUFFER
);
1235 PLIST_ENTRY ListEntry
;
1236 struct DriverInfoElement
*driverInfo
;
1237 SP_DEVINSTALL_PARAMS_W InstallParams
;
1239 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1240 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1243 if (!DeviceInfoData
)
1244 /* Fall back to destroying class driver list */
1245 DriverType
= SPDIT_CLASSDRIVER
;
1247 if (DriverType
== SPDIT_CLASSDRIVER
)
1249 while (!IsListEmpty(&list
->DriverListHead
))
1251 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
1252 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
1253 DestroyDriverInfoElement(driverInfo
);
1255 InstallParams
.Reserved
= 0;
1256 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
1257 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
1258 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
1262 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
1263 struct DeviceInfo
*deviceInfo
;
1265 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1266 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
1268 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1269 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
1271 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
1272 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
1273 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
1275 InstallParamsSet
.Reserved
= 0;
1276 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
1278 DestroyDriverInfoElement(driverInfo
);
1280 InstallParams
.Reserved
= 0;
1281 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
1282 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
1283 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1288 TRACE("Returning %d\n", ret
);
1292 /***********************************************************************
1293 * SetupDiEnumDriverInfoA (SETUPAPI.@)
1296 SetupDiEnumDriverInfoA(
1297 IN HDEVINFO DeviceInfoSet
,
1298 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1299 IN DWORD DriverType
,
1300 IN DWORD MemberIndex
,
1301 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
1303 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
1306 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1307 DriverType
, MemberIndex
, DriverInfoData
);
1309 if (DriverInfoData
== NULL
)
1310 SetLastError(ERROR_INVALID_PARAMETER
);
1311 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
1312 SetLastError(ERROR_INVALID_USER_BUFFER
);
1315 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1316 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
1317 DriverType
, MemberIndex
, &driverInfoData2W
);
1321 /* Do W->A conversion */
1322 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
1323 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
1324 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
1325 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
1327 DriverInfoData
->Description
[0] = '\0';
1330 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1331 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1333 DriverInfoData
->MfgName
[0] = '\0';
1336 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1337 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1339 DriverInfoData
->ProviderName
[0] = '\0';
1342 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1344 /* Copy more fields */
1345 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1346 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1351 TRACE("Returning %d\n", ret
);
1356 /***********************************************************************
1357 * SetupDiEnumDriverInfoW (SETUPAPI.@)
1360 SetupDiEnumDriverInfoW(
1361 IN HDEVINFO DeviceInfoSet
,
1362 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1363 IN DWORD DriverType
,
1364 IN DWORD MemberIndex
,
1365 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
1367 PLIST_ENTRY ListHead
;
1370 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1371 DriverType
, MemberIndex
, DriverInfoData
);
1373 if (!DeviceInfoSet
|| !DriverInfoData
)
1374 SetLastError(ERROR_INVALID_PARAMETER
);
1375 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1376 SetLastError(ERROR_INVALID_HANDLE
);
1377 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1378 SetLastError(ERROR_INVALID_HANDLE
);
1379 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
1380 SetLastError(ERROR_INVALID_PARAMETER
);
1381 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
1382 SetLastError(ERROR_INVALID_PARAMETER
);
1383 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1384 SetLastError(ERROR_INVALID_USER_BUFFER
);
1387 struct DeviceInfo
*devInfo
= NULL
;
1388 PLIST_ENTRY ItemList
;
1390 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1391 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
1393 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1397 ListHead
= &devInfo
->DriverListHead
;
1400 ItemList
= ListHead
->Flink
;
1401 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
1402 ItemList
= ItemList
->Flink
;
1403 if (ItemList
== ListHead
)
1404 SetLastError(ERROR_NO_MORE_ITEMS
);
1407 struct DriverInfoElement
*DrvInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1410 &DriverInfoData
->DriverType
,
1411 &DrvInfo
->Info
.DriverType
,
1412 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1417 TRACE("Returning %d\n", ret
);
1421 /***********************************************************************
1422 * SetupDiGetSelectedDriverA (SETUPAPI.@)
1425 SetupDiGetSelectedDriverA(
1426 IN HDEVINFO DeviceInfoSet
,
1427 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1428 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
1430 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
1433 if (DriverInfoData
== NULL
)
1434 SetLastError(ERROR_INVALID_PARAMETER
);
1435 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
1436 SetLastError(ERROR_INVALID_USER_BUFFER
);
1439 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1441 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
1447 /* Do W->A conversion */
1448 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
1449 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
1450 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
1451 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
1453 DriverInfoData
->Description
[0] = '\0';
1456 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1457 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1459 DriverInfoData
->MfgName
[0] = '\0';
1462 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1463 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1465 DriverInfoData
->ProviderName
[0] = '\0';
1468 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1470 /* Copy more fields */
1471 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1472 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1480 /***********************************************************************
1481 * SetupDiGetSelectedDriverW (SETUPAPI.@)
1484 SetupDiGetSelectedDriverW(
1485 IN HDEVINFO DeviceInfoSet
,
1486 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1487 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
1491 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
1493 if (!DeviceInfoSet
|| !DriverInfoData
)
1494 SetLastError(ERROR_INVALID_PARAMETER
);
1495 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1496 SetLastError(ERROR_INVALID_HANDLE
);
1497 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1498 SetLastError(ERROR_INVALID_HANDLE
);
1499 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1500 SetLastError(ERROR_INVALID_USER_BUFFER
);
1501 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1502 SetLastError(ERROR_INVALID_USER_BUFFER
);
1505 SP_DEVINSTALL_PARAMS InstallParams
;
1507 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1508 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1510 struct DriverInfoElement
*driverInfo
;
1511 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
1512 if (driverInfo
== NULL
)
1513 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1517 &DriverInfoData
->DriverType
,
1518 &driverInfo
->Info
.DriverType
,
1519 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1525 TRACE("Returning %d\n", ret
);
1529 /***********************************************************************
1530 * SetupDiSetSelectedDriverA (SETUPAPI.@)
1533 SetupDiSetSelectedDriverA(
1534 IN HDEVINFO DeviceInfoSet
,
1535 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1536 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
1538 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
1539 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
1542 if (DriverInfoData
!= NULL
)
1544 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
1545 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
))
1547 SetLastError(ERROR_INVALID_PARAMETER
);
1551 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1552 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1554 if (DriverInfoDataW
.Reserved
== 0)
1556 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1558 /* convert the strings to unicode */
1559 if (!MultiByteToWideChar(CP_ACP
,
1561 DriverInfoData
->Description
,
1563 DriverInfoDataW
.Description
,
1565 !MultiByteToWideChar(CP_ACP
,
1567 DriverInfoData
->ProviderName
,
1569 DriverInfoDataW
.ProviderName
,
1576 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
1579 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
1583 if (ret
&& pDriverInfoDataW
!= NULL
)
1585 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
1591 /***********************************************************************
1592 * SetupDiSetSelectedDriverW (SETUPAPI.@)
1595 SetupDiSetSelectedDriverW(
1596 IN HDEVINFO DeviceInfoSet
,
1597 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1598 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
1602 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
1605 SetLastError(ERROR_INVALID_PARAMETER
);
1606 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1607 SetLastError(ERROR_INVALID_HANDLE
);
1608 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1609 SetLastError(ERROR_INVALID_HANDLE
);
1610 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1611 SetLastError(ERROR_INVALID_USER_BUFFER
);
1612 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1613 SetLastError(ERROR_INVALID_USER_BUFFER
);
1616 struct DriverInfoElement
**pDriverInfo
;
1617 PLIST_ENTRY ListHead
, ItemList
;
1621 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
1622 ListHead
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->DriverListHead
;
1626 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
1627 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1630 if (!DriverInfoData
)
1632 *pDriverInfo
= NULL
;
1637 /* Search selected driver in list */
1638 ItemList
= ListHead
->Flink
;
1639 while (ItemList
!= ListHead
)
1641 if (DriverInfoData
->Reserved
!= 0)
1643 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
1648 /* The caller wants to compare only DriverType, Description and ProviderName fields */
1649 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1650 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
1651 && strcmpW(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
1652 && strcmpW(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
1657 ItemList
= ItemList
->Flink
;
1659 if (ItemList
== ListHead
)
1660 SetLastError(ERROR_INVALID_PARAMETER
);
1663 *pDriverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1664 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
1666 TRACE("Choosing driver whose rank is 0x%lx\n",
1667 (*pDriverInfo
)->Params
.Rank
);
1669 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
1674 TRACE("Returning %d\n", ret
);
1678 /***********************************************************************
1679 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
1682 SetupDiGetDriverInfoDetailA(
1683 IN HDEVINFO DeviceInfoSet
,
1684 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1685 IN PSP_DRVINFO_DATA_A DriverInfoData
,
1686 IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
1687 IN DWORD DriverInfoDetailDataSize
,
1688 OUT PDWORD RequiredSize OPTIONAL
)
1690 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
1691 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
1693 DWORD HardwareIDLen
= 0;
1696 /* do some sanity checks, the unicode version might do more thorough checks */
1697 if (DriverInfoData
== NULL
||
1698 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
1699 (DriverInfoDetailData
!= NULL
&&
1700 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
1701 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
1703 SetLastError(ERROR_INVALID_PARAMETER
);
1707 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
1708 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
1710 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1712 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1714 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1718 SetLastError(ERROR_INVALID_PARAMETER
);
1721 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1722 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1724 /* convert the strings to unicode */
1725 if (MultiByteToWideChar(CP_ACP
,
1727 DriverInfoData
->Description
,
1729 DriverInfoDataW
.Description
,
1731 MultiByteToWideChar(CP_ACP
,
1733 DriverInfoData
->MfgName
,
1735 DriverInfoDataW
.MfgName
,
1737 MultiByteToWideChar(CP_ACP
,
1739 DriverInfoData
->ProviderName
,
1741 DriverInfoDataW
.ProviderName
,
1744 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
1746 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
1747 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
1750 if (DriverInfoDetailData
!= NULL
)
1752 /* calculate the unicode buffer size from the ansi buffer size */
1753 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
1754 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
1755 (HardwareIDLen
* sizeof(WCHAR
));
1757 DriverInfoDetailDataW
= MyMalloc(BufSize
);
1758 if (DriverInfoDetailDataW
== NULL
)
1760 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1764 /* initialize the buffer */
1765 ZeroMemory(DriverInfoDetailDataW
,
1767 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
1770 /* call the unicode version */
1771 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
1774 DriverInfoDetailDataW
,
1780 if (DriverInfoDetailDataW
!= NULL
)
1782 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
1783 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
1784 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
1785 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
1786 if (WideCharToMultiByte(CP_ACP
,
1788 DriverInfoDetailDataW
->SectionName
,
1790 DriverInfoDetailData
->SectionName
,
1794 WideCharToMultiByte(CP_ACP
,
1796 DriverInfoDetailDataW
->InfFileName
,
1798 DriverInfoDetailData
->InfFileName
,
1802 WideCharToMultiByte(CP_ACP
,
1804 DriverInfoDetailDataW
->DrvDescription
,
1806 DriverInfoDetailData
->DrvDescription
,
1810 WideCharToMultiByte(CP_ACP
,
1812 DriverInfoDetailDataW
->HardwareID
,
1814 DriverInfoDetailData
->HardwareID
,
1820 DWORD hwidlen
= HardwareIDLen
;
1821 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
1823 /* count the strings in the list */
1826 len
= lstrlenA(s
) + 1;
1835 /* looks like the string list wasn't terminated... */
1836 SetLastError(ERROR_INVALID_USER_BUFFER
);
1842 /* make sure CompatIDsOffset points to the second string in the
1846 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
1847 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
1848 DriverInfoDetailData
->CompatIDsOffset
+ 1;
1852 DriverInfoDetailData
->CompatIDsOffset
= 0;
1853 DriverInfoDetailData
->CompatIDsLength
= 0;
1862 if (RequiredSize
!= NULL
)
1864 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
1865 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
1871 if (DriverInfoDetailDataW
!= NULL
)
1873 MyFree(DriverInfoDetailDataW
);
1879 /***********************************************************************
1880 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
1883 SetupDiGetDriverInfoDetailW(
1884 IN HDEVINFO DeviceInfoSet
,
1885 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1886 IN PSP_DRVINFO_DATA_W DriverInfoData
,
1887 IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
1888 IN DWORD DriverInfoDetailDataSize
,
1889 OUT PDWORD RequiredSize OPTIONAL
)
1893 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
1894 DriverInfoData
, DriverInfoDetailData
,
1895 DriverInfoDetailDataSize
, RequiredSize
);
1898 SetLastError(ERROR_INVALID_PARAMETER
);
1899 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1900 SetLastError(ERROR_INVALID_HANDLE
);
1901 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1902 SetLastError(ERROR_INVALID_HANDLE
);
1903 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1904 SetLastError(ERROR_INVALID_USER_BUFFER
);
1905 else if (!DriverInfoData
)
1906 SetLastError(ERROR_INVALID_PARAMETER
);
1907 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
1908 SetLastError(ERROR_INVALID_PARAMETER
);
1909 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
1910 SetLastError(ERROR_INVALID_PARAMETER
);
1911 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
1912 SetLastError(ERROR_INVALID_USER_BUFFER
);
1913 else if (DriverInfoData
->Reserved
== 0)
1914 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1917 struct DriverInfoElement
*driverInfoElement
;
1918 LPWSTR HardwareIDs
= NULL
;
1919 LPWSTR CompatibleIDs
= NULL
;
1920 LPWSTR pBuffer
= NULL
;
1921 LPCWSTR DeviceID
= NULL
;
1922 ULONG HardwareIDsSize
, CompatibleIDsSize
;
1923 ULONG sizeNeeded
, sizeLeft
, size
;
1926 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
1928 /* Get hardware and compatible IDs lists */
1929 Result
= GetHardwareAndCompatibleIDsLists(
1932 &HardwareIDs
, &HardwareIDsSize
,
1933 &CompatibleIDs
, &CompatibleIDsSize
);
1937 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
1938 + HardwareIDsSize
+ CompatibleIDsSize
;
1940 *RequiredSize
= sizeNeeded
;
1942 if (!DriverInfoDetailData
)
1949 DriverInfoDetailData
,
1950 &driverInfoElement
->Details
,
1951 driverInfoElement
->Details
.cbSize
);
1952 DriverInfoDetailData
->CompatIDsOffset
= 0;
1953 DriverInfoDetailData
->CompatIDsLength
= 0;
1955 sizeLeft
= (DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
);
1956 pBuffer
= DriverInfoDetailData
->HardwareID
;
1957 /* Add as many as possible HardwareIDs in the list */
1958 DeviceID
= HardwareIDs
;
1959 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
1961 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
1962 wcscpy(pBuffer
, DeviceID
);
1963 DeviceID
+= size
+ 1;
1964 pBuffer
+= size
+ 1;
1965 sizeLeft
-= size
+ 1;
1966 DriverInfoDetailData
->CompatIDsOffset
+= size
+ 1;
1970 *pBuffer
= UNICODE_NULL
;
1972 DriverInfoDetailData
->CompatIDsOffset
++;
1974 /* Add as many as possible CompatibleIDs in the list */
1975 DeviceID
= CompatibleIDs
;
1976 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
1978 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
1979 wcscpy(pBuffer
, DeviceID
);
1980 DeviceID
+= size
+ 1;
1981 pBuffer
+= size
+ 1;
1982 sizeLeft
-= size
+ 1;
1983 DriverInfoDetailData
->CompatIDsLength
+= size
+ 1;
1987 *pBuffer
= UNICODE_NULL
;
1989 DriverInfoDetailData
->CompatIDsLength
++;
1992 if (sizeNeeded
> DriverInfoDetailDataSize
)
1993 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1998 MyFree(HardwareIDs
);
1999 MyFree(CompatibleIDs
);
2002 TRACE("Returning %d\n", ret
);
2006 /***********************************************************************
2007 * SetupDiGetDriverInstallParamsW (SETUPAPI.@)
2010 SetupDiGetDriverInstallParamsW(
2011 IN HDEVINFO DeviceInfoSet
,
2012 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
2013 IN PSP_DRVINFO_DATA_W DriverInfoData
,
2014 OUT PSP_DRVINSTALL_PARAMS DriverInstallParams
)
2018 TRACE("%p %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
, DriverInstallParams
);
2020 if (!DeviceInfoSet
|| !DriverInfoData
|| !DriverInstallParams
)
2021 SetLastError(ERROR_INVALID_PARAMETER
);
2022 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2023 SetLastError(ERROR_INVALID_HANDLE
);
2024 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2025 SetLastError(ERROR_INVALID_HANDLE
);
2026 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2027 SetLastError(ERROR_INVALID_USER_BUFFER
);
2028 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
2029 SetLastError(ERROR_INVALID_USER_BUFFER
);
2030 else if (DriverInstallParams
->cbSize
!= sizeof(SP_DRVINSTALL_PARAMS
))
2031 SetLastError(ERROR_INVALID_USER_BUFFER
);
2034 SP_DEVINSTALL_PARAMS InstallParams
;
2036 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
2037 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
2039 struct DriverInfoElement
*driverInfo
;
2040 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
2041 if (driverInfo
== NULL
)
2042 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2046 DriverInstallParams
,
2047 &driverInfo
->Params
,
2048 DriverInstallParams
->cbSize
);
2054 TRACE("Returning %d\n", ret
);
2058 /***********************************************************************
2059 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
2062 SetupDiSelectBestCompatDrv(
2063 IN HDEVINFO DeviceInfoSet
,
2064 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2066 SP_DRVINFO_DATA_W drvInfoData
;
2069 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2071 /* Drivers are sorted by rank in the driver list, so
2072 * the first driver in the list is the best one.
2074 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
2075 ret
= SetupDiEnumDriverInfoW(
2079 0, /* Member index */
2084 ret
= SetupDiSetSelectedDriverW(
2090 TRACE("Returning %d\n", ret
);
2094 /***********************************************************************
2095 * SetupDiInstallDriverFiles (SETUPAPI.@)
2098 SetupDiInstallDriverFiles(
2099 IN HDEVINFO DeviceInfoSet
,
2100 IN PSP_DEVINFO_DATA DeviceInfoData
)
2104 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2107 SetLastError(ERROR_INVALID_PARAMETER
);
2108 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2109 SetLastError(ERROR_INVALID_HANDLE
);
2110 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2111 SetLastError(ERROR_INVALID_HANDLE
);
2112 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2113 SetLastError(ERROR_INVALID_USER_BUFFER
);
2114 else if (DeviceInfoData
&& ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
2115 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2116 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
2117 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2120 SP_DEVINSTALL_PARAMS_W InstallParams
;
2121 struct DriverInfoElement
*SelectedDriver
;
2122 WCHAR SectionName
[MAX_PATH
];
2123 DWORD SectionNameLength
= 0;
2124 PVOID InstallMsgHandler
;
2125 PVOID InstallMsgHandlerContext
;
2126 PVOID Context
= NULL
;
2128 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
2129 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
2133 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
2134 if (!SelectedDriver
)
2136 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2140 ret
= SetupDiGetActualSectionToInstallW(
2141 SelectedDriver
->InfFileDetails
->hInf
,
2142 SelectedDriver
->Details
.SectionName
,
2143 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
2147 if (InstallParams
.InstallMsgHandler
)
2149 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
2150 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
2154 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
2157 InstallMsgHandler
= SetupDefaultQueueCallbackW
;
2158 InstallMsgHandlerContext
= Context
;
2160 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
2161 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
2162 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
2163 InstallMsgHandler
, InstallMsgHandlerContext
,
2164 DeviceInfoSet
, DeviceInfoData
);
2168 /* Install files from .CoInstallers section */
2169 lstrcatW(SectionName
, DotCoInstallers
);
2170 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
2171 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
2172 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
2173 InstallMsgHandler
, InstallMsgHandlerContext
,
2174 DeviceInfoSet
, DeviceInfoData
);
2178 /* Set the DI_NOFILECOPY flag to prevent another
2179 * installation during SetupDiInstallDevice */
2180 InstallParams
.Flags
|= DI_NOFILECOPY
;
2181 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
2185 SetupTermDefaultQueueCallback(Context
);
2189 TRACE("Returning %d\n", ret
);