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
,
396 /* Get driver date and driver version, by analyzing the "DriverVer" value */
397 pComma
= strchrW(DriverVer
, ',');
400 *pComma
= UNICODE_NULL
;
401 pVersion
= pComma
+ 1;
403 /* Get driver date version. Invalid date = 00/00/00 */
404 memset(DriverDate
, 0, sizeof(FILETIME
));
405 if (strlenW(DriverVer
) == 10
406 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
407 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
409 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
410 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
411 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
412 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
413 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
414 SystemTimeToFileTime(&SystemTime
, DriverDate
);
416 /* Get driver version. Invalid version = 0.0.0.0 */
420 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
421 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
422 LARGE_INTEGER fullVersion
;
424 pMinor
= strchrW(pVersion
, '.');
428 pRevision
= strchrW(++pMinor
, '.');
429 Minor
= atoiW(pMinor
);
434 pBuild
= strchrW(++pRevision
, '.');
435 Revision
= atoiW(pRevision
);
441 Build
= atoiW(pBuild
);
443 Major
= atoiW(pVersion
);
444 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
445 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
446 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
454 HeapFree(GetProcessHeap(), 0, ProviderName
);
455 *pProviderName
= NULL
;
457 HeapFree(GetProcessHeap(), 0, DriverVer
);
463 GetHardwareAndCompatibleIDsLists(
464 IN HDEVINFO DeviceInfoSet
,
465 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
466 OUT LPWSTR
*pHardwareIDs OPTIONAL
,
467 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL
,
468 OUT LPWSTR
*pCompatibleIDs OPTIONAL
,
469 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL
)
471 LPWSTR HardwareIDs
= NULL
;
472 LPWSTR CompatibleIDs
= NULL
;
476 /* Get hardware IDs list */
478 RequiredSize
= 512; /* Initial buffer size */
479 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
480 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
483 HardwareIDs
= MyMalloc(RequiredSize
);
486 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
489 Result
= SetupDiGetDeviceRegistryPropertyW(
500 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
502 /* No hardware ID for this device */
511 *pHardwareIDs
= HardwareIDs
;
512 if (pHardwareIDsRequiredSize
)
513 *pHardwareIDsRequiredSize
= RequiredSize
;
515 /* Get compatible IDs list */
517 RequiredSize
= 512; /* Initial buffer size */
518 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
519 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
521 MyFree(CompatibleIDs
);
522 CompatibleIDs
= MyMalloc(RequiredSize
);
525 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
528 Result
= SetupDiGetDeviceRegistryPropertyW(
533 (PBYTE
)CompatibleIDs
,
539 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
541 /* No compatible ID for this device */
542 MyFree(CompatibleIDs
);
543 CompatibleIDs
= NULL
;
550 *pCompatibleIDs
= CompatibleIDs
;
551 if (pCompatibleIDsRequiredSize
)
552 *pCompatibleIDsRequiredSize
= RequiredSize
;
560 MyFree(CompatibleIDs
);
565 #if WIN32_WINNT < 0x0600
567 * This code has been copied from advapi32/reg/reg.c,
568 * so this dll can be tested as is on Windows XP
571 #define RRF_RT_REG_NONE (1 << 0)
572 #define RRF_RT_REG_SZ (1 << 1)
573 #define RRF_RT_REG_EXPAND_SZ (1 << 2)
574 #define RRF_RT_REG_BINARY (1 << 3)
575 #define RRF_RT_REG_DWORD (1 << 4)
576 #define RRF_RT_REG_MULTI_SZ (1 << 5)
577 #define RRF_RT_REG_QWORD (1 << 6)
578 #define RRF_RT_DWORD (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD)
579 #define RRF_RT_QWORD (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD)
580 #define RRF_NOEXPAND (1 << 28)
581 #define RRF_ZEROONFAILURE (1 << 29)
584 RegpApplyRestrictions( DWORD dwFlags
, DWORD dwType
, DWORD cbData
,
587 /* Check if the type is restricted by the passed flags */
588 if (*ret
== ERROR_SUCCESS
|| *ret
== ERROR_MORE_DATA
)
594 case REG_NONE
: dwMask
= RRF_RT_REG_NONE
; break;
595 case REG_SZ
: dwMask
= RRF_RT_REG_SZ
; break;
596 case REG_EXPAND_SZ
: dwMask
= RRF_RT_REG_EXPAND_SZ
; break;
597 case REG_MULTI_SZ
: dwMask
= RRF_RT_REG_MULTI_SZ
; break;
598 case REG_BINARY
: dwMask
= RRF_RT_REG_BINARY
; break;
599 case REG_DWORD
: dwMask
= RRF_RT_REG_DWORD
; break;
600 case REG_QWORD
: dwMask
= RRF_RT_REG_QWORD
; break;
603 if (dwFlags
& dwMask
)
605 /* Type is not restricted, check for size mismatch */
606 if (dwType
== REG_BINARY
)
610 if ((dwFlags
& RRF_RT_DWORD
) == RRF_RT_DWORD
)
612 else if ((dwFlags
& RRF_RT_DWORD
) == RRF_RT_QWORD
)
615 if (cbExpect
&& cbData
!= cbExpect
)
616 *ret
= ERROR_DATATYPE_MISMATCH
;
619 else *ret
= ERROR_UNSUPPORTED_TYPE
;
624 RegGetValueW( HKEY hKey
, LPCWSTR pszSubKey
, LPCWSTR pszValue
,
625 DWORD dwFlags
, LPDWORD pdwType
, PVOID pvData
,
628 DWORD dwType
, cbData
= pcbData
? *pcbData
: 0;
632 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
633 hKey
, debugstr_w(pszSubKey
), debugstr_w(pszValue
), dwFlags
, pdwType
,
634 pvData
, pcbData
, cbData
);
636 if ((dwFlags
& RRF_RT_REG_EXPAND_SZ
) && !(dwFlags
& RRF_NOEXPAND
))
637 return ERROR_INVALID_PARAMETER
;
639 if (pszSubKey
&& pszSubKey
[0])
641 ret
= RegOpenKeyExW(hKey
, pszSubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
642 if (ret
!= ERROR_SUCCESS
) return ret
;
645 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwType
, pvData
, &cbData
);
647 /* If we are going to expand we need to read in the whole the value even
648 * if the passed buffer was too small as the expanded string might be
649 * smaller than the unexpanded one and could fit into cbData bytes. */
650 if ((ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) &&
651 (dwType
== REG_EXPAND_SZ
&& !(dwFlags
& RRF_NOEXPAND
)))
654 if (pvBuf
) HeapFree(GetProcessHeap(), 0, pvBuf
);
656 pvBuf
= HeapAlloc(GetProcessHeap(), 0, cbData
);
659 ret
= ERROR_NOT_ENOUGH_MEMORY
;
663 if (ret
== ERROR_MORE_DATA
)
664 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
,
665 &dwType
, pvBuf
, &cbData
);
668 /* Even if cbData was large enough we have to copy the
669 * string since ExpandEnvironmentStrings can't handle
670 * overlapping buffers. */
671 CopyMemory(pvBuf
, pvData
, cbData
);
674 /* Both the type or the value itself could have been modified in
675 * between so we have to keep retrying until the buffer is large
676 * enough or we no longer have to expand the value. */
677 } while (dwType
== REG_EXPAND_SZ
&& ret
== ERROR_MORE_DATA
);
679 if (ret
== ERROR_SUCCESS
)
681 if (dwType
== REG_EXPAND_SZ
)
683 cbData
= ExpandEnvironmentStringsW(pvBuf
, pvData
,
684 pcbData
? *pcbData
: 0);
686 if(pcbData
&& cbData
> *pcbData
)
687 ret
= ERROR_MORE_DATA
;
690 CopyMemory(pvData
, pvBuf
, *pcbData
);
693 if (pvBuf
) HeapFree(GetProcessHeap(), 0, pvBuf
);
696 if (pszSubKey
&& pszSubKey
[0])
699 RegpApplyRestrictions(dwFlags
, dwType
, cbData
, &ret
);
701 if (pcbData
&& ret
!= ERROR_SUCCESS
&& (dwFlags
& RRF_ZEROONFAILURE
))
702 ZeroMemory(pvData
, *pcbData
);
704 if (pdwType
) *pdwType
= dwType
;
705 if (pcbData
) *pcbData
= cbData
;
709 #endif /* End of code copied from advapi32/reg/reg.c */
711 /***********************************************************************
712 * SetupDiBuildDriverInfoList (SETUPAPI.@)
715 SetupDiBuildDriverInfoList(
716 IN HDEVINFO DeviceInfoSet
,
717 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
720 struct DeviceInfoSet
*list
;
721 SP_DEVINSTALL_PARAMS_W InstallParams
;
723 struct InfFileDetails
*currentInfFileDetails
= NULL
;
724 LPWSTR ProviderName
= NULL
;
725 LPWSTR ManufacturerName
= NULL
;
726 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
727 LPWSTR HardwareIDs
= NULL
;
728 LPWSTR CompatibleIDs
= NULL
;
729 LPWSTR FullInfFileName
= NULL
;
730 LPWSTR ExcludeFromSelect
= NULL
;
732 DWORDLONG DriverVersion
= 0;
736 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
739 SetLastError(ERROR_INVALID_HANDLE
);
740 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
741 SetLastError(ERROR_INVALID_HANDLE
);
742 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
743 SetLastError(ERROR_INVALID_HANDLE
);
744 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
745 SetLastError(ERROR_INVALID_PARAMETER
);
746 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
747 SetLastError(ERROR_INVALID_PARAMETER
);
748 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
749 SetLastError(ERROR_INVALID_USER_BUFFER
);
752 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
755 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
756 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
762 struct DeviceInfo
*devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
763 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
764 pDriverListHead
= &devInfo
->DriverListHead
;
767 if (DriverType
== SPDIT_COMPATDRIVER
)
769 /* Get hardware and compatible IDs lists */
770 Result
= GetHardwareAndCompatibleIDsLists(
779 if (!HardwareIDs
&& !CompatibleIDs
)
781 SetLastError(ERROR_FILE_NOT_FOUND
);
786 if (InstallParams
.FlagsEx
& DI_FLAGSEX_INSTALLEDDRIVER
)
789 WCHAR InfFileName
[MAX_PATH
];
790 WCHAR InfFileSection
[MAX_PATH
];
792 struct DeviceInfo
*devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
793 struct InfFileDetails
*infFileDetails
= NULL
;
798 /* Prepend inf directory name to file name */
799 len
= sizeof(InfFileName
) / sizeof(InfFileName
[0]);
800 RequiredSize
= GetSystemWindowsDirectoryW(InfFileName
, len
);
801 if (RequiredSize
== 0 || RequiredSize
>= len
)
803 if (*InfFileName
&& InfFileName
[strlenW(InfFileName
) - 1] != '\\')
804 strcatW(InfFileName
, BackSlash
);
805 strcatW(InfFileName
, InfDirectory
);
807 /* Read some information from registry, before creating the driver structure */
808 hDriverKey
= SetupDiOpenDevRegKey(
815 if (hDriverKey
== INVALID_HANDLE_VALUE
)
817 RequiredSize
= len
- strlenW(InfFileName
);
824 &InfFileName
[strlenW(InfFileName
)],
826 if (rc
!= ERROR_SUCCESS
)
829 CloseHandle(hDriverKey
);
832 RequiredSize
= sizeof(InfFileSection
);
836 REGSTR_VAL_INFSECTION
,
841 if (rc
!= ERROR_SUCCESS
)
844 CloseHandle(hDriverKey
);
847 TRACE("Current driver in %s/%s\n", debugstr_w(InfFileName
), debugstr_w(InfFileSection
));
848 infFileDetails
= CreateInfFileDetails(InfFileName
);
851 CloseHandle(hDriverKey
);
854 DriverDate
.dwLowDateTime
= DriverDate
.dwHighDateTime
= 0; /* FIXME */
855 CloseHandle(hDriverKey
);
856 ret
= AddKnownDriverToList(
862 InfFileSection
, /* Yes, we don't care of section extension */
863 L
"DriverDescription", /* FIXME */
864 L
"ProviderName", /* FIXME */
865 L
"ManufacturerName", /* FIXME */
866 L
"MatchingId", /* FIXME */
868 0, /* FIXME: DriverVersion */
871 DereferenceInfFile(infFileDetails
);
874 else if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
876 /* InstallParams.DriverPath contains the name of a .inf file */
877 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
878 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
881 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
884 strcpyW(Buffer
, InstallParams
.DriverPath
);
885 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
890 /* Enumerate .inf files */
892 RequiredSize
= 32768; /* Initial buffer size */
893 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
894 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
896 HeapFree(GetProcessHeap(), 0, Buffer
);
897 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
901 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
904 Result
= SetupGetInfFileListW(
905 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
907 Buffer
, RequiredSize
,
910 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
912 /* No .inf file in specified directory. So, we should
913 * success as we created an empty driver info list.
922 LPWSTR pFullFilename
;
924 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
926 /* Only a filename */
927 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
928 if (!FullInfFileName
)
930 pFullFilename
= &FullInfFileName
[0];
932 else if (*InstallParams
.DriverPath
)
934 /* Directory name specified */
936 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
939 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + MAX_PATH
) * sizeof(WCHAR
));
940 if (!FullInfFileName
)
942 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
945 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
946 strcatW(FullInfFileName
, BackSlash
);
947 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
951 /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */
953 len
= GetSystemWindowsDirectoryW(NULL
, 0);
956 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + strlenW(InfDirectory
) + MAX_PATH
) * sizeof(WCHAR
));
957 if (!FullInfFileName
)
959 len
= GetSystemWindowsDirectoryW(FullInfFileName
, len
);
962 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
963 strcatW(FullInfFileName
, BackSlash
);
964 strcatW(FullInfFileName
, InfDirectory
);
965 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
968 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
970 INFCONTEXT ContextManufacturer
, ContextDevice
;
973 strcpyW(pFullFilename
, filename
);
974 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
976 currentInfFileDetails
= CreateInfFileDetails(FullInfFileName
);
977 if (!currentInfFileDetails
)
980 if (!GetVersionInformationFromInfFile(
981 currentInfFileDetails
->hInf
,
987 DereferenceInfFile(currentInfFileDetails
);
988 currentInfFileDetails
= NULL
;
992 if (DriverType
== SPDIT_CLASSDRIVER
)
994 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
995 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1001 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
1003 /* Read ExcludeFromSelect control flags */
1007 FIXME("ExcludeFromSelect list ignored\n");
1009 /* Get the manufacturers list */
1010 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
1013 Result
= SetupGetStringFieldW(
1014 &ContextManufacturer
,
1015 0, /* Field index */
1020 /* We got the needed size for the buffer */
1021 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
1022 if (!ManufacturerName
)
1024 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1027 Result
= SetupGetStringFieldW(
1028 &ContextManufacturer
,
1029 0, /* Field index */
1030 ManufacturerName
, RequiredSize
,
1033 /* Get manufacturer section name */
1034 Result
= SetupGetStringFieldW(
1035 &ContextManufacturer
,
1036 1, /* Field index */
1037 ManufacturerSection
, LINE_LEN
,
1041 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
1042 /* Add (possible) extension to manufacturer section name */
1043 Result
= SetupDiGetActualSectionToInstallW(
1044 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
1047 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
1048 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
1053 if (DriverType
== SPDIT_CLASSDRIVER
)
1055 /* FIXME: Check ExcludeFromSelect list */
1056 if (!AddDriverToList(
1061 currentInfFileDetails
,
1066 DriverDate
, DriverVersion
,
1072 else /* DriverType = SPDIT_COMPATDRIVER */
1074 /* 1. Get all fields */
1075 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
1079 BOOL DriverAlreadyAdded
;
1081 for (i
= 2; i
<= FieldCount
; i
++)
1083 LPWSTR DeviceId
= NULL
;
1085 RequiredSize
= 128; /* Initial buffer size */
1086 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1087 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1089 HeapFree(GetProcessHeap(), 0, DeviceId
);
1090 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
1093 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1096 Result
= SetupGetStringFieldW(
1099 DeviceId
, RequiredSize
,
1104 HeapFree(GetProcessHeap(), 0, DeviceId
);
1107 /* FIXME: Check ExcludeFromSelect list */
1108 DriverAlreadyAdded
= FALSE
;
1109 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
1111 if (strcmpiW(DeviceId
, currentId
) == 0)
1118 currentInfFileDetails
,
1123 DriverDate
, DriverVersion
,
1124 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
1125 DriverAlreadyAdded
= TRUE
;
1130 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
1132 if (strcmpiW(DeviceId
, currentId
) == 0)
1139 currentInfFileDetails
,
1144 DriverDate
, DriverVersion
,
1145 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
1146 DriverAlreadyAdded
= TRUE
;
1150 HeapFree(GetProcessHeap(), 0, DeviceId
);
1153 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
1156 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
1157 ManufacturerName
= NULL
;
1158 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
1163 HeapFree(GetProcessHeap(), 0, ProviderName
);
1164 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
1165 ProviderName
= ExcludeFromSelect
= NULL
;
1167 DereferenceInfFile(currentInfFileDetails
);
1168 currentInfFileDetails
= NULL
;
1179 InstallParams
.Flags
|= DI_DIDCOMPAT
;
1180 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
1184 InstallParams
.Flags
|= DI_DIDCLASS
;
1185 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
1187 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1190 HeapFree(GetProcessHeap(), 0, ProviderName
);
1191 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
1192 MyFree(HardwareIDs
);
1193 MyFree(CompatibleIDs
);
1194 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
1195 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
1196 if (currentInfFileDetails
)
1197 DereferenceInfFile(currentInfFileDetails
);
1198 HeapFree(GetProcessHeap(), 0, Buffer
);
1200 TRACE("Returning %d\n", ret
);
1204 /***********************************************************************
1205 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
1208 SetupDiDestroyDriverInfoList(
1209 IN HDEVINFO DeviceInfoSet
,
1210 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1211 IN DWORD DriverType
)
1213 struct DeviceInfoSet
*list
;
1216 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
1219 SetLastError(ERROR_INVALID_HANDLE
);
1220 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1221 SetLastError(ERROR_INVALID_HANDLE
);
1222 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
1223 SetLastError(ERROR_INVALID_PARAMETER
);
1224 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
1225 SetLastError(ERROR_INVALID_PARAMETER
);
1226 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1227 SetLastError(ERROR_INVALID_USER_BUFFER
);
1230 PLIST_ENTRY ListEntry
;
1231 struct DriverInfoElement
*driverInfo
;
1232 SP_DEVINSTALL_PARAMS_W InstallParams
;
1234 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1235 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1238 if (!DeviceInfoData
)
1239 /* Fall back to destroying class driver list */
1240 DriverType
= SPDIT_CLASSDRIVER
;
1242 if (DriverType
== SPDIT_CLASSDRIVER
)
1244 while (!IsListEmpty(&list
->DriverListHead
))
1246 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
1247 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
1248 DestroyDriverInfoElement(driverInfo
);
1250 InstallParams
.Reserved
= 0;
1251 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
1252 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
1253 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
1257 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
1258 struct DeviceInfo
*deviceInfo
;
1260 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1261 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
1263 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1264 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
1266 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
1267 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
1268 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
1270 InstallParamsSet
.Reserved
= 0;
1271 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
1273 DestroyDriverInfoElement(driverInfo
);
1275 InstallParams
.Reserved
= 0;
1276 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
1277 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
1278 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1283 TRACE("Returning %d\n", ret
);
1287 /***********************************************************************
1288 * SetupDiEnumDriverInfoA (SETUPAPI.@)
1291 SetupDiEnumDriverInfoA(
1292 IN HDEVINFO DeviceInfoSet
,
1293 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1294 IN DWORD DriverType
,
1295 IN DWORD MemberIndex
,
1296 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
1298 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
1301 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1302 DriverType
, MemberIndex
, DriverInfoData
);
1304 if (DriverInfoData
== NULL
)
1305 SetLastError(ERROR_INVALID_PARAMETER
);
1306 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
1307 SetLastError(ERROR_INVALID_USER_BUFFER
);
1310 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1311 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
1312 DriverType
, MemberIndex
, &driverInfoData2W
);
1316 /* Do W->A conversion */
1317 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
1318 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
1319 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
1320 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
1322 DriverInfoData
->Description
[0] = '\0';
1325 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1326 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1328 DriverInfoData
->MfgName
[0] = '\0';
1331 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1332 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1334 DriverInfoData
->ProviderName
[0] = '\0';
1337 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1339 /* Copy more fields */
1340 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1341 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1346 TRACE("Returning %d\n", ret
);
1351 /***********************************************************************
1352 * SetupDiEnumDriverInfoW (SETUPAPI.@)
1355 SetupDiEnumDriverInfoW(
1356 IN HDEVINFO DeviceInfoSet
,
1357 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1358 IN DWORD DriverType
,
1359 IN DWORD MemberIndex
,
1360 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
1362 PLIST_ENTRY ListHead
;
1365 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1366 DriverType
, MemberIndex
, DriverInfoData
);
1368 if (!DeviceInfoSet
|| !DriverInfoData
)
1369 SetLastError(ERROR_INVALID_PARAMETER
);
1370 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1371 SetLastError(ERROR_INVALID_HANDLE
);
1372 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1373 SetLastError(ERROR_INVALID_HANDLE
);
1374 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
1375 SetLastError(ERROR_INVALID_PARAMETER
);
1376 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
1377 SetLastError(ERROR_INVALID_PARAMETER
);
1378 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1379 SetLastError(ERROR_INVALID_USER_BUFFER
);
1382 struct DeviceInfo
*devInfo
= NULL
;
1383 PLIST_ENTRY ItemList
;
1385 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1386 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
1388 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1392 ListHead
= &devInfo
->DriverListHead
;
1395 ItemList
= ListHead
->Flink
;
1396 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
1397 ItemList
= ItemList
->Flink
;
1398 if (ItemList
== ListHead
)
1399 SetLastError(ERROR_NO_MORE_ITEMS
);
1402 struct DriverInfoElement
*DrvInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1405 &DriverInfoData
->DriverType
,
1406 &DrvInfo
->Info
.DriverType
,
1407 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1412 TRACE("Returning %d\n", ret
);
1416 /***********************************************************************
1417 * SetupDiGetSelectedDriverA (SETUPAPI.@)
1420 SetupDiGetSelectedDriverA(
1421 IN HDEVINFO DeviceInfoSet
,
1422 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1423 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
1425 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
1428 if (DriverInfoData
== NULL
)
1429 SetLastError(ERROR_INVALID_PARAMETER
);
1430 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
1431 SetLastError(ERROR_INVALID_USER_BUFFER
);
1434 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1436 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
1442 /* Do W->A conversion */
1443 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
1444 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
1445 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
1446 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
1448 DriverInfoData
->Description
[0] = '\0';
1451 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1452 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1454 DriverInfoData
->MfgName
[0] = '\0';
1457 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1458 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1460 DriverInfoData
->ProviderName
[0] = '\0';
1463 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1465 /* Copy more fields */
1466 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1467 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1475 /***********************************************************************
1476 * SetupDiGetSelectedDriverW (SETUPAPI.@)
1479 SetupDiGetSelectedDriverW(
1480 IN HDEVINFO DeviceInfoSet
,
1481 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1482 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
1486 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
1488 if (!DeviceInfoSet
|| !DriverInfoData
)
1489 SetLastError(ERROR_INVALID_PARAMETER
);
1490 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1491 SetLastError(ERROR_INVALID_HANDLE
);
1492 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1493 SetLastError(ERROR_INVALID_HANDLE
);
1494 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1495 SetLastError(ERROR_INVALID_USER_BUFFER
);
1496 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1497 SetLastError(ERROR_INVALID_USER_BUFFER
);
1500 SP_DEVINSTALL_PARAMS InstallParams
;
1502 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1503 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1505 struct DriverInfoElement
*driverInfo
;
1506 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
1507 if (driverInfo
== NULL
)
1508 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1512 &DriverInfoData
->DriverType
,
1513 &driverInfo
->Info
.DriverType
,
1514 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1520 TRACE("Returning %d\n", ret
);
1524 /***********************************************************************
1525 * SetupDiSetSelectedDriverA (SETUPAPI.@)
1528 SetupDiSetSelectedDriverA(
1529 IN HDEVINFO DeviceInfoSet
,
1530 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1531 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
1533 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
1534 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
1537 if (DriverInfoData
!= NULL
)
1539 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
1540 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
))
1542 SetLastError(ERROR_INVALID_PARAMETER
);
1546 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1547 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1549 if (DriverInfoDataW
.Reserved
== 0)
1551 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1553 /* convert the strings to unicode */
1554 if (!MultiByteToWideChar(CP_ACP
,
1556 DriverInfoData
->Description
,
1558 DriverInfoDataW
.Description
,
1560 !MultiByteToWideChar(CP_ACP
,
1562 DriverInfoData
->ProviderName
,
1564 DriverInfoDataW
.ProviderName
,
1571 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
1574 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
1578 if (ret
&& pDriverInfoDataW
!= NULL
)
1580 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
1586 /***********************************************************************
1587 * SetupDiSetSelectedDriverW (SETUPAPI.@)
1590 SetupDiSetSelectedDriverW(
1591 IN HDEVINFO DeviceInfoSet
,
1592 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1593 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
1597 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
1600 SetLastError(ERROR_INVALID_PARAMETER
);
1601 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1602 SetLastError(ERROR_INVALID_HANDLE
);
1603 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1604 SetLastError(ERROR_INVALID_HANDLE
);
1605 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1606 SetLastError(ERROR_INVALID_USER_BUFFER
);
1607 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1608 SetLastError(ERROR_INVALID_USER_BUFFER
);
1611 struct DriverInfoElement
**pDriverInfo
;
1612 PLIST_ENTRY ListHead
, ItemList
;
1616 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
1617 ListHead
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->DriverListHead
;
1621 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
1622 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1625 if (!DriverInfoData
)
1627 *pDriverInfo
= NULL
;
1632 /* Search selected driver in list */
1633 ItemList
= ListHead
->Flink
;
1634 while (ItemList
!= ListHead
)
1636 if (DriverInfoData
->Reserved
!= 0)
1638 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
1643 /* The caller wants to compare only DriverType, Description and ProviderName fields */
1644 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1645 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
1646 && strcmpW(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
1647 && strcmpW(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
1652 ItemList
= ItemList
->Flink
;
1654 if (ItemList
== ListHead
)
1655 SetLastError(ERROR_INVALID_PARAMETER
);
1658 *pDriverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1659 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
1661 TRACE("Choosing driver whose rank is 0x%lx\n",
1662 (*pDriverInfo
)->Params
.Rank
);
1664 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
1669 TRACE("Returning %d\n", ret
);
1673 /***********************************************************************
1674 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
1677 SetupDiGetDriverInfoDetailA(
1678 IN HDEVINFO DeviceInfoSet
,
1679 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1680 IN PSP_DRVINFO_DATA_A DriverInfoData
,
1681 IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
1682 IN DWORD DriverInfoDetailDataSize
,
1683 OUT PDWORD RequiredSize OPTIONAL
)
1685 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
1686 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
1688 DWORD HardwareIDLen
= 0;
1691 /* do some sanity checks, the unicode version might do more thorough checks */
1692 if (DriverInfoData
== NULL
||
1693 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
1694 (DriverInfoDetailData
!= NULL
&&
1695 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
1696 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
1698 SetLastError(ERROR_INVALID_PARAMETER
);
1702 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
1703 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
1705 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1707 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1709 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1713 SetLastError(ERROR_INVALID_PARAMETER
);
1716 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1717 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1719 /* convert the strings to unicode */
1720 if (MultiByteToWideChar(CP_ACP
,
1722 DriverInfoData
->Description
,
1724 DriverInfoDataW
.Description
,
1726 MultiByteToWideChar(CP_ACP
,
1728 DriverInfoData
->MfgName
,
1730 DriverInfoDataW
.MfgName
,
1732 MultiByteToWideChar(CP_ACP
,
1734 DriverInfoData
->ProviderName
,
1736 DriverInfoDataW
.ProviderName
,
1739 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
1741 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
1742 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
1745 if (DriverInfoDetailData
!= NULL
)
1747 /* calculate the unicode buffer size from the ansi buffer size */
1748 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
1749 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
1750 (HardwareIDLen
* sizeof(WCHAR
));
1752 DriverInfoDetailDataW
= MyMalloc(BufSize
);
1753 if (DriverInfoDetailDataW
== NULL
)
1755 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1759 /* initialize the buffer */
1760 ZeroMemory(DriverInfoDetailDataW
,
1762 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
1765 /* call the unicode version */
1766 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
1769 DriverInfoDetailDataW
,
1775 if (DriverInfoDetailDataW
!= NULL
)
1777 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
1778 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
1779 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
1780 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
1781 if (WideCharToMultiByte(CP_ACP
,
1783 DriverInfoDetailDataW
->SectionName
,
1785 DriverInfoDetailData
->SectionName
,
1789 WideCharToMultiByte(CP_ACP
,
1791 DriverInfoDetailDataW
->InfFileName
,
1793 DriverInfoDetailData
->InfFileName
,
1797 WideCharToMultiByte(CP_ACP
,
1799 DriverInfoDetailDataW
->DrvDescription
,
1801 DriverInfoDetailData
->DrvDescription
,
1805 WideCharToMultiByte(CP_ACP
,
1807 DriverInfoDetailDataW
->HardwareID
,
1809 DriverInfoDetailData
->HardwareID
,
1815 DWORD hwidlen
= HardwareIDLen
;
1816 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
1818 /* count the strings in the list */
1821 len
= lstrlenA(s
) + 1;
1830 /* looks like the string list wasn't terminated... */
1831 SetLastError(ERROR_INVALID_USER_BUFFER
);
1837 /* make sure CompatIDsOffset points to the second string in the
1841 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
1842 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
1843 DriverInfoDetailData
->CompatIDsOffset
+ 1;
1847 DriverInfoDetailData
->CompatIDsOffset
= 0;
1848 DriverInfoDetailData
->CompatIDsLength
= 0;
1857 if (RequiredSize
!= NULL
)
1859 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
1860 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
1866 if (DriverInfoDetailDataW
!= NULL
)
1868 MyFree(DriverInfoDetailDataW
);
1874 /***********************************************************************
1875 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
1878 SetupDiGetDriverInfoDetailW(
1879 IN HDEVINFO DeviceInfoSet
,
1880 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1881 IN PSP_DRVINFO_DATA_W DriverInfoData
,
1882 IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
1883 IN DWORD DriverInfoDetailDataSize
,
1884 OUT PDWORD RequiredSize OPTIONAL
)
1888 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
1889 DriverInfoData
, DriverInfoDetailData
,
1890 DriverInfoDetailDataSize
, RequiredSize
);
1893 SetLastError(ERROR_INVALID_PARAMETER
);
1894 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1895 SetLastError(ERROR_INVALID_HANDLE
);
1896 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1897 SetLastError(ERROR_INVALID_HANDLE
);
1898 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1899 SetLastError(ERROR_INVALID_USER_BUFFER
);
1900 else if (!DriverInfoData
)
1901 SetLastError(ERROR_INVALID_PARAMETER
);
1902 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
1903 SetLastError(ERROR_INVALID_PARAMETER
);
1904 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
1905 SetLastError(ERROR_INVALID_PARAMETER
);
1906 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
1907 SetLastError(ERROR_INVALID_USER_BUFFER
);
1908 else if (DriverInfoData
->Reserved
== 0)
1909 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1912 struct DriverInfoElement
*driverInfoElement
;
1913 LPWSTR HardwareIDs
= NULL
;
1914 LPWSTR CompatibleIDs
= NULL
;
1915 LPWSTR pBuffer
= NULL
;
1916 LPCWSTR DeviceID
= NULL
;
1917 ULONG HardwareIDsSize
, CompatibleIDsSize
;
1918 ULONG sizeNeeded
, sizeLeft
, size
;
1921 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
1923 /* Get hardware and compatible IDs lists */
1924 Result
= GetHardwareAndCompatibleIDsLists(
1927 &HardwareIDs
, &HardwareIDsSize
,
1928 &CompatibleIDs
, &CompatibleIDsSize
);
1932 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
1933 + HardwareIDsSize
+ CompatibleIDsSize
;
1935 *RequiredSize
= sizeNeeded
;
1937 if (!DriverInfoDetailData
)
1944 DriverInfoDetailData
,
1945 &driverInfoElement
->Details
,
1946 driverInfoElement
->Details
.cbSize
);
1947 DriverInfoDetailData
->CompatIDsOffset
= 0;
1948 DriverInfoDetailData
->CompatIDsLength
= 0;
1950 sizeLeft
= (DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
);
1951 pBuffer
= DriverInfoDetailData
->HardwareID
;
1952 /* Add as many as possible HardwareIDs in the list */
1953 DeviceID
= HardwareIDs
;
1954 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
1956 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
1957 wcscpy(pBuffer
, DeviceID
);
1958 DeviceID
+= size
+ 1;
1959 pBuffer
+= size
+ 1;
1960 sizeLeft
-= size
+ 1;
1961 DriverInfoDetailData
->CompatIDsOffset
+= size
+ 1;
1965 *pBuffer
= UNICODE_NULL
;
1967 DriverInfoDetailData
->CompatIDsOffset
++;
1969 /* Add as many as possible CompatibleIDs in the list */
1970 DeviceID
= CompatibleIDs
;
1971 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
1973 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
1974 wcscpy(pBuffer
, DeviceID
);
1975 DeviceID
+= size
+ 1;
1976 pBuffer
+= size
+ 1;
1977 sizeLeft
-= size
+ 1;
1978 DriverInfoDetailData
->CompatIDsLength
+= size
+ 1;
1982 *pBuffer
= UNICODE_NULL
;
1984 DriverInfoDetailData
->CompatIDsLength
++;
1987 if (sizeNeeded
> DriverInfoDetailDataSize
)
1988 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1993 MyFree(HardwareIDs
);
1994 MyFree(CompatibleIDs
);
1997 TRACE("Returning %d\n", ret
);
2001 /***********************************************************************
2002 * SetupDiGetDriverInstallParamsW (SETUPAPI.@)
2005 SetupDiGetDriverInstallParamsW(
2006 IN HDEVINFO DeviceInfoSet
,
2007 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
2008 IN PSP_DRVINFO_DATA_W DriverInfoData
,
2009 OUT PSP_DRVINSTALL_PARAMS DriverInstallParams
)
2013 TRACE("%p %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
, DriverInstallParams
);
2015 if (!DeviceInfoSet
|| !DriverInfoData
|| !DriverInstallParams
)
2016 SetLastError(ERROR_INVALID_PARAMETER
);
2017 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2018 SetLastError(ERROR_INVALID_HANDLE
);
2019 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2020 SetLastError(ERROR_INVALID_HANDLE
);
2021 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2022 SetLastError(ERROR_INVALID_USER_BUFFER
);
2023 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
2024 SetLastError(ERROR_INVALID_USER_BUFFER
);
2025 else if (DriverInstallParams
->cbSize
!= sizeof(SP_DRVINSTALL_PARAMS
))
2026 SetLastError(ERROR_INVALID_USER_BUFFER
);
2029 SP_DEVINSTALL_PARAMS InstallParams
;
2031 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
2032 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
2034 struct DriverInfoElement
*driverInfo
;
2035 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
2036 if (driverInfo
== NULL
)
2037 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2041 DriverInstallParams
,
2042 &driverInfo
->Params
,
2043 DriverInstallParams
->cbSize
);
2049 TRACE("Returning %d\n", ret
);
2053 /***********************************************************************
2054 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
2057 SetupDiSelectBestCompatDrv(
2058 IN HDEVINFO DeviceInfoSet
,
2059 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2061 SP_DRVINFO_DATA_W drvInfoData
;
2064 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2066 /* Drivers are sorted by rank in the driver list, so
2067 * the first driver in the list is the best one.
2069 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
2070 ret
= SetupDiEnumDriverInfoW(
2074 0, /* Member index */
2079 ret
= SetupDiSetSelectedDriverW(
2085 TRACE("Returning %d\n", ret
);
2089 /***********************************************************************
2090 * SetupDiInstallDriverFiles (SETUPAPI.@)
2093 SetupDiInstallDriverFiles(
2094 IN HDEVINFO DeviceInfoSet
,
2095 IN PSP_DEVINFO_DATA DeviceInfoData
)
2099 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2102 SetLastError(ERROR_INVALID_PARAMETER
);
2103 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2104 SetLastError(ERROR_INVALID_HANDLE
);
2105 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2106 SetLastError(ERROR_INVALID_HANDLE
);
2107 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2108 SetLastError(ERROR_INVALID_USER_BUFFER
);
2109 else if (DeviceInfoData
&& ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
2110 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2111 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
2112 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2115 SP_DEVINSTALL_PARAMS_W InstallParams
;
2116 struct DriverInfoElement
*SelectedDriver
;
2117 WCHAR SectionName
[MAX_PATH
];
2118 DWORD SectionNameLength
= 0;
2119 PVOID InstallMsgHandler
;
2120 PVOID InstallMsgHandlerContext
;
2121 PVOID Context
= NULL
;
2123 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
2124 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
2128 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
2129 if (!SelectedDriver
)
2131 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2135 ret
= SetupDiGetActualSectionToInstallW(
2136 SelectedDriver
->InfFileDetails
->hInf
,
2137 SelectedDriver
->Details
.SectionName
,
2138 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
2142 if (InstallParams
.InstallMsgHandler
)
2144 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
2145 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
2149 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
2152 InstallMsgHandler
= SetupDefaultQueueCallbackW
;
2153 InstallMsgHandlerContext
= Context
;
2155 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
2156 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
2157 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
2158 InstallMsgHandler
, InstallMsgHandlerContext
,
2159 DeviceInfoSet
, DeviceInfoData
);
2163 /* Install files from .CoInstallers section */
2164 lstrcatW(SectionName
, DotCoInstallers
);
2165 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
2166 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
2167 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
2168 InstallMsgHandler
, InstallMsgHandlerContext
,
2169 DeviceInfoSet
, DeviceInfoData
);
2173 /* Set the DI_NOFILECOPY flag to prevent another
2174 * installation during SetupDiInstallDevice */
2175 InstallParams
.Flags
|= DI_NOFILECOPY
;
2176 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
2180 SetupTermDefaultQueueCallback(Context
);
2184 TRACE("Returning %d\n", ret
);