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 /* Unicode constants */
24 static const WCHAR BackSlash
[] = {'\\',0};
25 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
26 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
27 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
28 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
30 static const WCHAR INF_MANUFACTURER
[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
31 static const WCHAR INF_PROVIDER
[] = {'P','r','o','v','i','d','e','r',0};
32 static const WCHAR INF_DRIVER_VER
[] = {'D','r','i','v','e','r','V','e','r',0};
35 /***********************************************************************
36 * struct InfFileDetails management
39 ReferenceInfFile(struct InfFileDetails
* infFile
)
41 InterlockedIncrement(&infFile
->References
);
45 DereferenceInfFile(struct InfFileDetails
* infFile
)
47 if (InterlockedDecrement(&infFile
->References
) == 0)
49 SetupCloseInfFile(infFile
->hInf
);
50 HeapFree(GetProcessHeap(), 0, infFile
);
54 struct InfFileDetails
*
56 IN LPCWSTR FullInfFileName
)
58 struct InfFileDetails
*details
;
62 Needed
= FIELD_OFFSET(struct InfFileDetails
, szData
)
63 + strlenW(FullInfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
65 details
= HeapAlloc(GetProcessHeap(), 0, Needed
);
68 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
72 memset(details
, 0, Needed
);
73 strcpyW(details
->szData
, FullInfFileName
);
74 last
= strrchrW(details
->szData
, '\\');
77 details
->DirectoryName
= details
->szData
;
78 details
->FileName
= last
+ 1;
82 details
->FileName
= details
->szData
;
83 ReferenceInfFile(details
);
84 details
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
85 if (details
->hInf
== INVALID_HANDLE_VALUE
)
87 HeapFree(GetProcessHeap(), 0, details
);
94 DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
96 DereferenceInfFile(driverInfo
->InfFileDetails
);
97 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
98 HeapFree(GetProcessHeap(), 0, driverInfo
);
102 /***********************************************************************
103 * Helper functions for SetupDiBuildDriverInfoList
106 AddKnownDriverToList(
107 IN PLIST_ENTRY DriverListHead
,
108 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
110 IN
struct InfFileDetails
*InfFileDetails
,
112 IN LPCWSTR SectionName
,
113 IN LPCWSTR DriverDescription
,
114 IN LPCWSTR ProviderName
,
115 IN LPCWSTR ManufacturerName
,
116 IN LPCWSTR MatchingId
,
117 IN FILETIME DriverDate
,
118 IN DWORDLONG DriverVersion
,
121 struct DriverInfoElement
*driverInfo
= NULL
;
122 HANDLE hFile
= INVALID_HANDLE_VALUE
;
124 PLIST_ENTRY PreviousEntry
;
127 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
130 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
133 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
135 driverInfo
->Params
.cbSize
= sizeof(SP_DRVINSTALL_PARAMS
);
136 driverInfo
->Params
.Reserved
= (ULONG_PTR
)driverInfo
;
138 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
139 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
141 /* Copy InfFileName field */
142 lstrcpynW(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
143 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
145 /* Fill InfDate field */
148 GENERIC_READ
, FILE_SHARE_READ
,
149 NULL
, OPEN_EXISTING
, 0, NULL
);
150 if (hFile
== INVALID_HANDLE_VALUE
)
152 Result
= GetFileTime(hFile
, NULL
, NULL
, &driverInfo
->Details
.InfDate
);
156 /* Fill SectionName field */
157 lstrcpynW(driverInfo
->Details
.SectionName
, SectionName
, LINE_LEN
);
159 /* Fill DrvDescription field */
160 lstrcpynW(driverInfo
->Details
.DrvDescription
, DriverDescription
, LINE_LEN
);
162 /* Copy MatchingId information */
165 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
166 if (!driverInfo
->MatchingId
)
168 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
171 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
174 driverInfo
->MatchingId
= NULL
;
176 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
177 debugstr_w(driverInfo
->Details
.DrvDescription
), debugstr_w(InfFile
),
178 debugstr_w(SectionName
), Rank
);
180 driverInfo
->Params
.Rank
= Rank
;
181 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
182 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
183 driverInfo
->Info
.DriverType
= DriverType
;
184 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
185 lstrcpynW(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
186 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
187 lstrcpynW(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
188 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
191 lstrcpynW(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
192 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
195 driverInfo
->Info
.ProviderName
[0] = '\0';
196 driverInfo
->Info
.DriverDate
= DriverDate
;
197 driverInfo
->Info
.DriverVersion
= DriverVersion
;
198 ReferenceInfFile(InfFileDetails
);
199 driverInfo
->InfFileDetails
= InfFileDetails
;
201 /* Insert current driver in driver list, according to its rank */
202 PreviousEntry
= DriverListHead
->Flink
;
203 while (PreviousEntry
!= DriverListHead
)
205 struct DriverInfoElement
*CurrentDriver
;
206 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
207 if (CurrentDriver
->Params
.Rank
> Rank
||
208 (CurrentDriver
->Params
.Rank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
< driverInfo
->DriverDate
.QuadPart
))
210 /* Insert before the current item */
211 InsertHeadList(PreviousEntry
->Blink
, &driverInfo
->ListEntry
);
214 PreviousEntry
= PreviousEntry
->Flink
;
216 if (PreviousEntry
== DriverListHead
)
218 /* Insert at the end of the list */
219 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
228 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
229 HeapFree(GetProcessHeap(), 0, driverInfo
);
231 if (hFile
!= INVALID_HANDLE_VALUE
)
239 IN PLIST_ENTRY DriverListHead
,
240 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
242 IN INFCONTEXT ContextDevice
,
243 IN
struct InfFileDetails
*InfFileDetails
,
245 IN LPCWSTR ProviderName
,
246 IN LPCWSTR ManufacturerName
,
247 IN LPCWSTR MatchingId
,
248 IN FILETIME DriverDate
,
249 IN DWORDLONG DriverVersion
,
252 LPWSTR SectionName
= NULL
;
253 LPWSTR DriverDescription
= NULL
;
257 /* Read SectionName */
258 SectionName
= MyMalloc(LINE_LEN
);
261 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
264 ZeroMemory(SectionName
, LINE_LEN
);
265 Result
= SetupGetStringFieldW(
274 /* Read DriverDescription */
275 DriverDescription
= MyMalloc(LINE_LEN
);
276 if (!DriverDescription
)
278 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
281 ZeroMemory(DriverDescription
, LINE_LEN
);
282 Result
= SetupGetStringFieldW(
285 DriverDescription
, LINE_LEN
,
288 ret
= AddKnownDriverToList(
305 MyFree(DriverDescription
);
311 GetVersionInformationFromInfFile(
313 OUT LPGUID ClassGuid
,
314 OUT LPWSTR
* pProviderName
,
315 OUT FILETIME
* DriverDate
,
316 OUT DWORDLONG
* DriverVersion
)
319 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
320 LPWSTR DriverVer
= NULL
;
321 LPWSTR ProviderName
= NULL
;
322 LPWSTR pComma
; /* Points into DriverVer */
323 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
324 SYSTEMTIME SystemTime
;
326 BOOL ret
= FALSE
; /* Final result */
329 if (!SetupGetLineTextW(
333 guidW
, sizeof(guidW
),
334 NULL
/* Required size */))
338 guidW
[37] = '\0'; /* Replace the } by a NULL character */
339 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
341 SetLastError(ERROR_GEN_FAILURE
);
345 /* Get provider name */
346 Result
= SetupGetLineTextW(
348 hInf
, Version
, INF_PROVIDER
,
353 /* We know the needed buffer size */
354 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
357 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
360 Result
= SetupGetLineTextW(
362 hInf
, Version
, INF_PROVIDER
,
363 ProviderName
, RequiredSize
,
368 *pProviderName
= ProviderName
;
370 /* Read the "DriverVer" value */
371 Result
= SetupGetLineTextW(
373 hInf
, Version
, INF_DRIVER_VER
,
378 /* We know know the needed buffer size */
379 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
382 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
385 Result
= SetupGetLineTextW(
387 hInf
, Version
, INF_DRIVER_VER
,
388 DriverVer
, RequiredSize
,
393 /* windows sets default date of 00/00/0000 when this directive is missing*/
394 memset(DriverDate
, 0, sizeof(FILETIME
));
399 /* Get driver date and driver version, by analyzing the "DriverVer" value */
400 pComma
= strchrW(DriverVer
, ',');
403 *pComma
= UNICODE_NULL
;
404 pVersion
= pComma
+ 1;
406 /* Get driver date version. Invalid date = 00/00/00 */
407 memset(DriverDate
, 0, sizeof(FILETIME
));
408 if (strlenW(DriverVer
) == 10
409 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
410 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
412 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
413 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
414 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
415 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
416 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
417 SystemTimeToFileTime(&SystemTime
, DriverDate
);
419 /* Get driver version. Invalid version = 0.0.0.0 */
423 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
424 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
425 LARGE_INTEGER fullVersion
;
427 pMinor
= strchrW(pVersion
, '.');
431 pRevision
= strchrW(++pMinor
, '.');
432 Minor
= atoiW(pMinor
);
437 pBuild
= strchrW(++pRevision
, '.');
438 Revision
= atoiW(pRevision
);
444 Build
= atoiW(pBuild
);
446 Major
= atoiW(pVersion
);
447 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
448 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
449 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
457 HeapFree(GetProcessHeap(), 0, ProviderName
);
458 *pProviderName
= NULL
;
460 HeapFree(GetProcessHeap(), 0, DriverVer
);
466 GetHardwareAndCompatibleIDsLists(
467 IN HDEVINFO DeviceInfoSet
,
468 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
469 OUT LPWSTR
*pHardwareIDs OPTIONAL
,
470 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL
,
471 OUT LPWSTR
*pCompatibleIDs OPTIONAL
,
472 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL
)
474 LPWSTR HardwareIDs
= NULL
;
475 LPWSTR CompatibleIDs
= NULL
;
479 /* Get hardware IDs list */
481 RequiredSize
= 512; /* Initial buffer size */
482 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
483 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
486 HardwareIDs
= MyMalloc(RequiredSize
);
489 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
492 Result
= SetupDiGetDeviceRegistryPropertyW(
503 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
505 /* No hardware ID for this device */
514 *pHardwareIDs
= HardwareIDs
;
515 if (pHardwareIDsRequiredSize
)
516 *pHardwareIDsRequiredSize
= RequiredSize
;
518 /* Get compatible IDs list */
520 RequiredSize
= 512; /* Initial buffer size */
521 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
522 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
524 MyFree(CompatibleIDs
);
525 CompatibleIDs
= MyMalloc(RequiredSize
);
528 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
531 Result
= SetupDiGetDeviceRegistryPropertyW(
536 (PBYTE
)CompatibleIDs
,
542 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
544 /* No compatible ID for this device */
545 MyFree(CompatibleIDs
);
546 CompatibleIDs
= NULL
;
553 *pCompatibleIDs
= CompatibleIDs
;
554 if (pCompatibleIDsRequiredSize
)
555 *pCompatibleIDsRequiredSize
= RequiredSize
;
563 MyFree(CompatibleIDs
);
568 #if _WIN32_WINNT < 0x0600
570 * This code has been copied from advapi32/reg/reg.c,
571 * so this dll can be tested as is on Windows XP
574 #define RRF_RT_REG_NONE (1 << 0)
575 #define RRF_RT_REG_SZ (1 << 1)
576 #define RRF_RT_REG_EXPAND_SZ (1 << 2)
577 #define RRF_RT_REG_BINARY (1 << 3)
578 #define RRF_RT_REG_DWORD (1 << 4)
579 #define RRF_RT_REG_MULTI_SZ (1 << 5)
580 #define RRF_RT_REG_QWORD (1 << 6)
581 #define RRF_RT_DWORD (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD)
582 #define RRF_RT_QWORD (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD)
583 #define RRF_NOEXPAND (1 << 28)
584 #define RRF_ZEROONFAILURE (1 << 29)
587 RegpApplyRestrictions( DWORD dwFlags
, DWORD dwType
, DWORD cbData
,
590 /* Check if the type is restricted by the passed flags */
591 if (*ret
== ERROR_SUCCESS
|| *ret
== ERROR_MORE_DATA
)
597 case REG_NONE
: dwMask
= RRF_RT_REG_NONE
; break;
598 case REG_SZ
: dwMask
= RRF_RT_REG_SZ
; break;
599 case REG_EXPAND_SZ
: dwMask
= RRF_RT_REG_EXPAND_SZ
; break;
600 case REG_MULTI_SZ
: dwMask
= RRF_RT_REG_MULTI_SZ
; break;
601 case REG_BINARY
: dwMask
= RRF_RT_REG_BINARY
; break;
602 case REG_DWORD
: dwMask
= RRF_RT_REG_DWORD
; break;
603 case REG_QWORD
: dwMask
= RRF_RT_REG_QWORD
; break;
606 if (dwFlags
& dwMask
)
608 /* Type is not restricted, check for size mismatch */
609 if (dwType
== REG_BINARY
)
613 if ((dwFlags
& RRF_RT_DWORD
) == RRF_RT_DWORD
)
615 else if ((dwFlags
& RRF_RT_QWORD
) == RRF_RT_QWORD
)
618 if (cbExpect
&& cbData
!= cbExpect
)
619 *ret
= ERROR_DATATYPE_MISMATCH
;
622 else *ret
= ERROR_UNSUPPORTED_TYPE
;
627 RegGetValueW( HKEY hKey
, LPCWSTR pszSubKey
, LPCWSTR pszValue
,
628 DWORD dwFlags
, LPDWORD pdwType
, PVOID pvData
,
631 DWORD dwType
, cbData
= pcbData
? *pcbData
: 0;
635 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
636 hKey
, debugstr_w(pszSubKey
), debugstr_w(pszValue
), dwFlags
, pdwType
,
637 pvData
, pcbData
, cbData
);
639 if ((dwFlags
& RRF_RT_REG_EXPAND_SZ
) && !(dwFlags
& RRF_NOEXPAND
))
640 return ERROR_INVALID_PARAMETER
;
642 if (pszSubKey
&& pszSubKey
[0])
644 ret
= RegOpenKeyExW(hKey
, pszSubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
645 if (ret
!= ERROR_SUCCESS
) return ret
;
648 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwType
, pvData
, &cbData
);
650 /* If we are going to expand we need to read in the whole the value even
651 * if the passed buffer was too small as the expanded string might be
652 * smaller than the unexpanded one and could fit into cbData bytes. */
653 if ((ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) &&
654 (dwType
== REG_EXPAND_SZ
&& !(dwFlags
& RRF_NOEXPAND
)))
657 if (pvBuf
) HeapFree(GetProcessHeap(), 0, pvBuf
);
659 pvBuf
= HeapAlloc(GetProcessHeap(), 0, cbData
);
662 ret
= ERROR_NOT_ENOUGH_MEMORY
;
666 if (ret
== ERROR_MORE_DATA
)
667 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
,
668 &dwType
, pvBuf
, &cbData
);
671 /* Even if cbData was large enough we have to copy the
672 * string since ExpandEnvironmentStrings can't handle
673 * overlapping buffers. */
674 CopyMemory(pvBuf
, pvData
, cbData
);
677 /* Both the type or the value itself could have been modified in
678 * between so we have to keep retrying until the buffer is large
679 * enough or we no longer have to expand the value. */
680 } while (dwType
== REG_EXPAND_SZ
&& ret
== ERROR_MORE_DATA
);
682 if (ret
== ERROR_SUCCESS
)
684 if (dwType
== REG_EXPAND_SZ
)
686 cbData
= ExpandEnvironmentStringsW(pvBuf
, pvData
,
687 pcbData
? (*pcbData
)/sizeof(WCHAR
) : 0);
689 if(pcbData
&& cbData
> ((*pcbData
)/sizeof(WCHAR
)))
690 ret
= ERROR_MORE_DATA
;
693 CopyMemory(pvData
, pvBuf
, *pcbData
);
696 if (pvBuf
) HeapFree(GetProcessHeap(), 0, pvBuf
);
699 if (pszSubKey
&& pszSubKey
[0])
702 RegpApplyRestrictions(dwFlags
, dwType
, cbData
, &ret
);
704 if (pcbData
&& ret
!= ERROR_SUCCESS
&& (dwFlags
& RRF_ZEROONFAILURE
))
705 ZeroMemory(pvData
, *pcbData
);
707 if (pdwType
) *pdwType
= dwType
;
708 if (pcbData
) *pcbData
= cbData
;
712 #endif /* End of code copied from advapi32/reg/reg.c */
714 /***********************************************************************
715 * SetupDiBuildDriverInfoList (SETUPAPI.@)
718 SetupDiBuildDriverInfoList(
719 IN HDEVINFO DeviceInfoSet
,
720 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
723 struct DeviceInfoSet
*list
;
724 SP_DEVINSTALL_PARAMS_W InstallParams
;
726 struct InfFileDetails
*currentInfFileDetails
= NULL
;
727 LPWSTR ProviderName
= NULL
;
728 LPWSTR ManufacturerName
= NULL
;
729 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
730 LPWSTR HardwareIDs
= NULL
;
731 LPWSTR CompatibleIDs
= NULL
;
732 LPWSTR FullInfFileName
= NULL
;
733 LPWSTR ExcludeFromSelect
= NULL
;
735 DWORDLONG DriverVersion
= 0;
739 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
742 SetLastError(ERROR_INVALID_HANDLE
);
743 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
744 SetLastError(ERROR_INVALID_HANDLE
);
745 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
746 SetLastError(ERROR_INVALID_HANDLE
);
747 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
748 SetLastError(ERROR_INVALID_PARAMETER
);
749 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
750 SetLastError(ERROR_INVALID_PARAMETER
);
751 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
752 SetLastError(ERROR_INVALID_USER_BUFFER
);
755 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
758 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
759 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
765 struct DeviceInfo
*devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
766 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
767 pDriverListHead
= &devInfo
->DriverListHead
;
770 if (DriverType
== SPDIT_COMPATDRIVER
)
772 /* Get hardware and compatible IDs lists */
773 Result
= GetHardwareAndCompatibleIDsLists(
782 if (!HardwareIDs
&& !CompatibleIDs
)
784 SetLastError(ERROR_FILE_NOT_FOUND
);
789 if (InstallParams
.FlagsEx
& DI_FLAGSEX_INSTALLEDDRIVER
)
792 WCHAR InfFileName
[MAX_PATH
];
793 WCHAR InfFileSection
[MAX_PATH
];
795 struct DeviceInfo
*devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
796 struct InfFileDetails
*infFileDetails
= NULL
;
801 /* Prepend inf directory name to file name */
802 len
= sizeof(InfFileName
) / sizeof(InfFileName
[0]);
803 RequiredSize
= GetSystemWindowsDirectoryW(InfFileName
, len
);
804 if (RequiredSize
== 0 || RequiredSize
>= len
)
806 if (*InfFileName
&& InfFileName
[strlenW(InfFileName
) - 1] != '\\')
807 strcatW(InfFileName
, BackSlash
);
808 strcatW(InfFileName
, InfDirectory
);
810 /* Read some information from registry, before creating the driver structure */
811 hDriverKey
= SETUPDI_OpenDrvKey(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
, devInfo
, KEY_QUERY_VALUE
);
812 if (hDriverKey
== INVALID_HANDLE_VALUE
)
814 RequiredSize
= (len
- strlenW(InfFileName
)) * sizeof(WCHAR
);
821 &InfFileName
[strlenW(InfFileName
)],
823 if (rc
!= ERROR_SUCCESS
)
826 CloseHandle(hDriverKey
);
829 RequiredSize
= sizeof(InfFileSection
);
833 REGSTR_VAL_INFSECTION
,
838 if (rc
!= ERROR_SUCCESS
)
841 CloseHandle(hDriverKey
);
844 TRACE("Current driver in %s/%s\n", debugstr_w(InfFileName
), debugstr_w(InfFileSection
));
845 infFileDetails
= CreateInfFileDetails(InfFileName
);
848 CloseHandle(hDriverKey
);
851 DriverDate
.dwLowDateTime
= DriverDate
.dwHighDateTime
= 0; /* FIXME */
852 CloseHandle(hDriverKey
);
853 ret
= AddKnownDriverToList(
859 InfFileSection
, /* Yes, we don't care of section extension */
860 L
"DriverDescription", /* FIXME */
861 L
"ProviderName", /* FIXME */
862 L
"ManufacturerName", /* FIXME */
863 L
"MatchingId", /* FIXME */
865 0, /* FIXME: DriverVersion */
868 DereferenceInfFile(infFileDetails
);
871 else if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
873 /* InstallParams.DriverPath contains the name of a .inf file */
874 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
875 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
878 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
881 strcpyW(Buffer
, InstallParams
.DriverPath
);
882 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
887 /* Enumerate .inf files */
889 RequiredSize
= 32768; /* Initial buffer size */
890 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
891 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
893 HeapFree(GetProcessHeap(), 0, Buffer
);
894 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
898 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
901 Result
= SetupGetInfFileListW(
902 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
904 Buffer
, RequiredSize
,
907 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
909 /* No .inf file in specified directory. So, we should
910 * success as we created an empty driver info list.
919 LPWSTR pFullFilename
;
921 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
923 /* Only a filename */
924 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
925 if (!FullInfFileName
)
927 pFullFilename
= &FullInfFileName
[0];
929 else if (*InstallParams
.DriverPath
)
931 /* Directory name specified */
933 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
936 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + MAX_PATH
) * sizeof(WCHAR
));
937 if (!FullInfFileName
)
939 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
942 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
943 strcatW(FullInfFileName
, BackSlash
);
944 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
948 /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */
950 len
= GetSystemWindowsDirectoryW(NULL
, 0);
953 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + strlenW(InfDirectory
) + MAX_PATH
) * sizeof(WCHAR
));
954 if (!FullInfFileName
)
956 len
= GetSystemWindowsDirectoryW(FullInfFileName
, len
);
959 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
960 strcatW(FullInfFileName
, BackSlash
);
961 strcatW(FullInfFileName
, InfDirectory
);
962 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
965 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
967 INFCONTEXT ContextManufacturer
, ContextDevice
;
970 strcpyW(pFullFilename
, filename
);
971 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
973 currentInfFileDetails
= CreateInfFileDetails(FullInfFileName
);
974 if (!currentInfFileDetails
)
977 if (!GetVersionInformationFromInfFile(
978 currentInfFileDetails
->hInf
,
984 DereferenceInfFile(currentInfFileDetails
);
985 currentInfFileDetails
= NULL
;
989 if (DriverType
== SPDIT_CLASSDRIVER
)
991 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
992 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
998 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
1000 /* Read ExcludeFromSelect control flags */
1004 FIXME("ExcludeFromSelect list ignored\n");
1006 /* Get the manufacturers list */
1007 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
1010 Result
= SetupGetStringFieldW(
1011 &ContextManufacturer
,
1012 0, /* Field index */
1017 /* We got the needed size for the buffer */
1018 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
1019 if (!ManufacturerName
)
1021 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1024 Result
= SetupGetStringFieldW(
1025 &ContextManufacturer
,
1026 0, /* Field index */
1027 ManufacturerName
, RequiredSize
,
1030 /* Get manufacturer section name */
1031 Result
= SetupGetStringFieldW(
1032 &ContextManufacturer
,
1033 1, /* Field index */
1034 ManufacturerSection
, LINE_LEN
,
1038 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
1039 /* Add (possible) extension to manufacturer section name */
1040 Result
= SetupDiGetActualSectionToInstallW(
1041 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
1044 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
1045 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
1050 if (DriverType
== SPDIT_CLASSDRIVER
)
1052 /* FIXME: Check ExcludeFromSelect list */
1053 if (!AddDriverToList(
1058 currentInfFileDetails
,
1063 DriverDate
, DriverVersion
,
1069 else /* DriverType = SPDIT_COMPATDRIVER */
1071 /* 1. Get all fields */
1072 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
1076 BOOL DriverAlreadyAdded
;
1078 for (i
= 2; i
<= FieldCount
; i
++)
1080 LPWSTR DeviceId
= NULL
;
1082 RequiredSize
= 128; /* Initial buffer size */
1083 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1084 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1086 HeapFree(GetProcessHeap(), 0, DeviceId
);
1087 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
1090 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1093 Result
= SetupGetStringFieldW(
1096 DeviceId
, RequiredSize
,
1101 HeapFree(GetProcessHeap(), 0, DeviceId
);
1104 /* FIXME: Check ExcludeFromSelect list */
1105 DriverAlreadyAdded
= FALSE
;
1108 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
1110 if (strcmpiW(DeviceId
, currentId
) == 0)
1117 currentInfFileDetails
,
1122 DriverDate
, DriverVersion
,
1123 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
1124 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
);