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
= SetupDiOpenDevRegKey(
818 if (hDriverKey
== INVALID_HANDLE_VALUE
)
820 RequiredSize
= (len
- strlenW(InfFileName
)) * sizeof(WCHAR
);
827 &InfFileName
[strlenW(InfFileName
)],
829 if (rc
!= ERROR_SUCCESS
)
832 CloseHandle(hDriverKey
);
835 RequiredSize
= sizeof(InfFileSection
);
839 REGSTR_VAL_INFSECTION
,
844 if (rc
!= ERROR_SUCCESS
)
847 CloseHandle(hDriverKey
);
850 TRACE("Current driver in %s/%s\n", debugstr_w(InfFileName
), debugstr_w(InfFileSection
));
851 infFileDetails
= CreateInfFileDetails(InfFileName
);
854 CloseHandle(hDriverKey
);
857 DriverDate
.dwLowDateTime
= DriverDate
.dwHighDateTime
= 0; /* FIXME */
858 CloseHandle(hDriverKey
);
859 ret
= AddKnownDriverToList(
865 InfFileSection
, /* Yes, we don't care of section extension */
866 L
"DriverDescription", /* FIXME */
867 L
"ProviderName", /* FIXME */
868 L
"ManufacturerName", /* FIXME */
869 L
"MatchingId", /* FIXME */
871 0, /* FIXME: DriverVersion */
874 DereferenceInfFile(infFileDetails
);
877 else if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
879 /* InstallParams.DriverPath contains the name of a .inf file */
880 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
881 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
884 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
887 strcpyW(Buffer
, InstallParams
.DriverPath
);
888 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
893 /* Enumerate .inf files */
895 RequiredSize
= 32768; /* Initial buffer size */
896 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
897 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
899 HeapFree(GetProcessHeap(), 0, Buffer
);
900 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
904 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
907 Result
= SetupGetInfFileListW(
908 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
910 Buffer
, RequiredSize
,
913 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
915 /* No .inf file in specified directory. So, we should
916 * success as we created an empty driver info list.
925 LPWSTR pFullFilename
;
927 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
929 /* Only a filename */
930 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
931 if (!FullInfFileName
)
933 pFullFilename
= &FullInfFileName
[0];
935 else if (*InstallParams
.DriverPath
)
937 /* Directory name specified */
939 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
942 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + MAX_PATH
) * sizeof(WCHAR
));
943 if (!FullInfFileName
)
945 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
948 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
949 strcatW(FullInfFileName
, BackSlash
);
950 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
954 /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */
956 len
= GetSystemWindowsDirectoryW(NULL
, 0);
959 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + strlenW(InfDirectory
) + MAX_PATH
) * sizeof(WCHAR
));
960 if (!FullInfFileName
)
962 len
= GetSystemWindowsDirectoryW(FullInfFileName
, len
);
965 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
966 strcatW(FullInfFileName
, BackSlash
);
967 strcatW(FullInfFileName
, InfDirectory
);
968 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
971 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
973 INFCONTEXT ContextManufacturer
, ContextDevice
;
976 strcpyW(pFullFilename
, filename
);
977 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
979 currentInfFileDetails
= CreateInfFileDetails(FullInfFileName
);
980 if (!currentInfFileDetails
)
983 if (!GetVersionInformationFromInfFile(
984 currentInfFileDetails
->hInf
,
990 DereferenceInfFile(currentInfFileDetails
);
991 currentInfFileDetails
= NULL
;
995 if (DriverType
== SPDIT_CLASSDRIVER
)
997 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
998 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1004 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
1006 /* Read ExcludeFromSelect control flags */
1010 FIXME("ExcludeFromSelect list ignored\n");
1012 /* Get the manufacturers list */
1013 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
1016 Result
= SetupGetStringFieldW(
1017 &ContextManufacturer
,
1018 0, /* Field index */
1023 /* We got the needed size for the buffer */
1024 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
1025 if (!ManufacturerName
)
1027 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1030 Result
= SetupGetStringFieldW(
1031 &ContextManufacturer
,
1032 0, /* Field index */
1033 ManufacturerName
, RequiredSize
,
1036 /* Get manufacturer section name */
1037 Result
= SetupGetStringFieldW(
1038 &ContextManufacturer
,
1039 1, /* Field index */
1040 ManufacturerSection
, LINE_LEN
,
1044 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
1045 /* Add (possible) extension to manufacturer section name */
1046 Result
= SetupDiGetActualSectionToInstallW(
1047 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
1050 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
1051 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
1056 if (DriverType
== SPDIT_CLASSDRIVER
)
1058 /* FIXME: Check ExcludeFromSelect list */
1059 if (!AddDriverToList(
1064 currentInfFileDetails
,
1069 DriverDate
, DriverVersion
,
1075 else /* DriverType = SPDIT_COMPATDRIVER */
1077 /* 1. Get all fields */
1078 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
1082 BOOL DriverAlreadyAdded
;
1084 for (i
= 2; i
<= FieldCount
; i
++)
1086 LPWSTR DeviceId
= NULL
;
1088 RequiredSize
= 128; /* Initial buffer size */
1089 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1090 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1092 HeapFree(GetProcessHeap(), 0, DeviceId
);
1093 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
1096 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1099 Result
= SetupGetStringFieldW(
1102 DeviceId
, RequiredSize
,
1107 HeapFree(GetProcessHeap(), 0, DeviceId
);
1110 /* FIXME: Check ExcludeFromSelect list */
1111 DriverAlreadyAdded
= FALSE
;
1112 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
1114 if (strcmpiW(DeviceId
, currentId
) == 0)
1121 currentInfFileDetails
,
1126 DriverDate
, DriverVersion
,
1127 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
1128 DriverAlreadyAdded
= TRUE
;
1133 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
1135 if (strcmpiW(DeviceId
, currentId
) == 0)
1142 currentInfFileDetails
,
1147 DriverDate
, DriverVersion
,
1148 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
1149 DriverAlreadyAdded
= TRUE
;
1153 HeapFree(GetProcessHeap(), 0, DeviceId
);
1156 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
1159 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
1160 ManufacturerName
= NULL
;
1161 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
1166 HeapFree(GetProcessHeap(), 0, ProviderName
);
1167 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
1168 ProviderName
= ExcludeFromSelect
= NULL
;
1170 DereferenceInfFile(currentInfFileDetails
);
1171 currentInfFileDetails
= NULL
;
1182 InstallParams
.Flags
|= DI_DIDCOMPAT
;
1183 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
1187 InstallParams
.Flags
|= DI_DIDCLASS
;
1188 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
1190 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1193 HeapFree(GetProcessHeap(), 0, ProviderName
);
1194 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
1195 MyFree(HardwareIDs
);
1196 MyFree(CompatibleIDs
);
1197 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
1198 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
1199 if (currentInfFileDetails
)
1200 DereferenceInfFile(currentInfFileDetails
);
1201 HeapFree(GetProcessHeap(), 0, Buffer
);
1203 TRACE("Returning %d\n", ret
);
1207 /***********************************************************************
1208 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
1211 SetupDiDestroyDriverInfoList(
1212 IN HDEVINFO DeviceInfoSet
,
1213 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1214 IN DWORD DriverType
)
1216 struct DeviceInfoSet
*list
;
1219 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
1222 SetLastError(ERROR_INVALID_HANDLE
);
1223 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1224 SetLastError(ERROR_INVALID_HANDLE
);
1225 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
1226 SetLastError(ERROR_INVALID_PARAMETER
);
1227 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
1228 SetLastError(ERROR_INVALID_PARAMETER
);
1229 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1230 SetLastError(ERROR_INVALID_USER_BUFFER
);
1233 PLIST_ENTRY ListEntry
;
1234 struct DriverInfoElement
*driverInfo
;
1235 SP_DEVINSTALL_PARAMS_W InstallParams
;
1237 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1238 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1241 if (!DeviceInfoData
)
1242 /* Fall back to destroying class driver list */
1243 DriverType
= SPDIT_CLASSDRIVER
;
1245 if (DriverType
== SPDIT_CLASSDRIVER
)
1247 while (!IsListEmpty(&list
->DriverListHead
))
1249 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
1250 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
1251 DestroyDriverInfoElement(driverInfo
);
1253 InstallParams
.Reserved
= 0;
1254 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
1255 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
1256 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
1260 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
1261 struct DeviceInfo
*deviceInfo
;
1263 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1264 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
1266 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1267 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
1269 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
1270 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
1271 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
1273 InstallParamsSet
.Reserved
= 0;
1274 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
1276 DestroyDriverInfoElement(driverInfo
);
1278 InstallParams
.Reserved
= 0;
1279 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
1280 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
1281 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1286 TRACE("Returning %d\n", ret
);
1290 /***********************************************************************
1291 * SetupDiEnumDriverInfoA (SETUPAPI.@)
1294 SetupDiEnumDriverInfoA(
1295 IN HDEVINFO DeviceInfoSet
,
1296 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1297 IN DWORD DriverType
,
1298 IN DWORD MemberIndex
,
1299 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
1301 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
1304 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1305 DriverType
, MemberIndex
, DriverInfoData
);
1307 if (DriverInfoData
== NULL
)
1308 SetLastError(ERROR_INVALID_PARAMETER
);
1309 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
1310 SetLastError(ERROR_INVALID_USER_BUFFER
);
1313 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1314 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
1315 DriverType
, MemberIndex
, &driverInfoData2W
);
1319 /* Do W->A conversion */
1320 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
1321 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
1322 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
1323 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
1325 DriverInfoData
->Description
[0] = '\0';
1328 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1329 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1331 DriverInfoData
->MfgName
[0] = '\0';
1334 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1335 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1337 DriverInfoData
->ProviderName
[0] = '\0';
1340 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1342 /* Copy more fields */
1343 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1344 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1349 TRACE("Returning %d\n", ret
);
1354 /***********************************************************************
1355 * SetupDiEnumDriverInfoW (SETUPAPI.@)
1358 SetupDiEnumDriverInfoW(
1359 IN HDEVINFO DeviceInfoSet
,
1360 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1361 IN DWORD DriverType
,
1362 IN DWORD MemberIndex
,
1363 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
1365 PLIST_ENTRY ListHead
;
1368 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1369 DriverType
, MemberIndex
, DriverInfoData
);
1371 if (!DeviceInfoSet
|| !DriverInfoData
)
1372 SetLastError(ERROR_INVALID_PARAMETER
);
1373 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1374 SetLastError(ERROR_INVALID_HANDLE
);
1375 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1376 SetLastError(ERROR_INVALID_HANDLE
);
1377 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
1378 SetLastError(ERROR_INVALID_PARAMETER
);
1379 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
1380 SetLastError(ERROR_INVALID_PARAMETER
);
1381 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1382 SetLastError(ERROR_INVALID_USER_BUFFER
);
1385 struct DeviceInfo
*devInfo
= NULL
;
1386 PLIST_ENTRY ItemList
;
1388 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1389 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
1391 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1395 ListHead
= &devInfo
->DriverListHead
;
1398 ItemList
= ListHead
->Flink
;
1399 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
1400 ItemList
= ItemList
->Flink
;
1401 if (ItemList
== ListHead
)
1402 SetLastError(ERROR_NO_MORE_ITEMS
);
1405 struct DriverInfoElement
*DrvInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1408 &DriverInfoData
->DriverType
,
1409 &DrvInfo
->Info
.DriverType
,
1410 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1415 TRACE("Returning %d\n", ret
);
1419 /***********************************************************************
1420 * SetupDiGetSelectedDriverA (SETUPAPI.@)
1423 SetupDiGetSelectedDriverA(
1424 IN HDEVINFO DeviceInfoSet
,
1425 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1426 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
1428 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
1431 if (DriverInfoData
== NULL
)
1432 SetLastError(ERROR_INVALID_PARAMETER
);
1433 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
1434 SetLastError(ERROR_INVALID_USER_BUFFER
);
1437 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1439 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
1445 /* Do W->A conversion */
1446 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
1447 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
1448 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
1449 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
1451 DriverInfoData
->Description
[0] = '\0';
1454 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1455 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1457 DriverInfoData
->MfgName
[0] = '\0';
1460 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1461 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1463 DriverInfoData
->ProviderName
[0] = '\0';
1466 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1468 /* Copy more fields */
1469 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1470 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1478 /***********************************************************************
1479 * SetupDiGetSelectedDriverW (SETUPAPI.@)
1482 SetupDiGetSelectedDriverW(
1483 IN HDEVINFO DeviceInfoSet
,
1484 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1485 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
1489 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
1491 if (!DeviceInfoSet
|| !DriverInfoData
)
1492 SetLastError(ERROR_INVALID_PARAMETER
);
1493 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1494 SetLastError(ERROR_INVALID_HANDLE
);
1495 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1496 SetLastError(ERROR_INVALID_HANDLE
);
1497 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1498 SetLastError(ERROR_INVALID_USER_BUFFER
);
1499 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1500 SetLastError(ERROR_INVALID_USER_BUFFER
);
1503 SP_DEVINSTALL_PARAMS InstallParams
;
1505 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1506 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1508 struct DriverInfoElement
*driverInfo
;
1509 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
1510 if (driverInfo
== NULL
)
1511 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1515 &DriverInfoData
->DriverType
,
1516 &driverInfo
->Info
.DriverType
,
1517 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1523 TRACE("Returning %d\n", ret
);
1527 /***********************************************************************
1528 * SetupDiSetSelectedDriverA (SETUPAPI.@)
1531 SetupDiSetSelectedDriverA(
1532 IN HDEVINFO DeviceInfoSet
,
1533 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1534 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
1536 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
1537 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
1540 if (DriverInfoData
!= NULL
)
1542 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
1543 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
))
1545 SetLastError(ERROR_INVALID_PARAMETER
);
1549 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1550 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1552 if (DriverInfoDataW
.Reserved
== 0)
1554 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1556 /* convert the strings to unicode */
1557 if (!MultiByteToWideChar(CP_ACP
,
1559 DriverInfoData
->Description
,
1561 DriverInfoDataW
.Description
,
1563 !MultiByteToWideChar(CP_ACP
,
1565 DriverInfoData
->ProviderName
,
1567 DriverInfoDataW
.ProviderName
,
1574 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
1577 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
1581 if (ret
&& pDriverInfoDataW
!= NULL
)
1583 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
1589 /***********************************************************************
1590 * SetupDiSetSelectedDriverW (SETUPAPI.@)
1593 SetupDiSetSelectedDriverW(
1594 IN HDEVINFO DeviceInfoSet
,
1595 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1596 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
1600 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
1603 SetLastError(ERROR_INVALID_PARAMETER
);
1604 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1605 SetLastError(ERROR_INVALID_HANDLE
);
1606 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1607 SetLastError(ERROR_INVALID_HANDLE
);
1608 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1609 SetLastError(ERROR_INVALID_USER_BUFFER
);
1610 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1611 SetLastError(ERROR_INVALID_USER_BUFFER
);
1614 struct DriverInfoElement
**pDriverInfo
;
1615 PLIST_ENTRY ListHead
, ItemList
;
1619 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
1620 ListHead
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->DriverListHead
;
1624 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
1625 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1628 if (!DriverInfoData
)
1630 *pDriverInfo
= NULL
;
1635 /* Search selected driver in list */
1636 ItemList
= ListHead
->Flink
;
1637 while (ItemList
!= ListHead
)
1639 if (DriverInfoData
->Reserved
!= 0)
1641 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
1646 /* The caller wants to compare only DriverType, Description and ProviderName fields */
1647 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1648 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
1649 && strcmpW(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
1650 && strcmpW(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
1655 ItemList
= ItemList
->Flink
;
1657 if (ItemList
== ListHead
)
1658 SetLastError(ERROR_INVALID_PARAMETER
);
1661 *pDriverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1662 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
1664 TRACE("Choosing driver whose rank is 0x%lx\n",
1665 (*pDriverInfo
)->Params
.Rank
);
1667 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
1672 TRACE("Returning %d\n", ret
);
1676 /***********************************************************************
1677 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
1680 SetupDiGetDriverInfoDetailA(
1681 IN HDEVINFO DeviceInfoSet
,
1682 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1683 IN PSP_DRVINFO_DATA_A DriverInfoData
,
1684 IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
1685 IN DWORD DriverInfoDetailDataSize
,
1686 OUT PDWORD RequiredSize OPTIONAL
)
1688 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
1689 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
1691 DWORD HardwareIDLen
= 0;
1694 /* do some sanity checks, the unicode version might do more thorough checks */
1695 if (DriverInfoData
== NULL
||
1696 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
1697 (DriverInfoDetailData
!= NULL
&&
1698 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
1699 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
1701 SetLastError(ERROR_INVALID_PARAMETER
);
1705 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
1706 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
1708 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1710 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1712 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1716 SetLastError(ERROR_INVALID_PARAMETER
);
1719 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1720 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1722 /* convert the strings to unicode */
1723 if (MultiByteToWideChar(CP_ACP
,
1725 DriverInfoData
->Description
,
1727 DriverInfoDataW
.Description
,
1729 MultiByteToWideChar(CP_ACP
,
1731 DriverInfoData
->MfgName
,
1733 DriverInfoDataW
.MfgName
,
1735 MultiByteToWideChar(CP_ACP
,
1737 DriverInfoData
->ProviderName
,
1739 DriverInfoDataW
.ProviderName
,
1742 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
1744 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
1745 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
1748 if (DriverInfoDetailData
!= NULL
)
1750 /* calculate the unicode buffer size from the ansi buffer size */
1751 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
1752 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
1753 (HardwareIDLen
* sizeof(WCHAR
));
1755 DriverInfoDetailDataW
= MyMalloc(BufSize
);
1756 if (DriverInfoDetailDataW
== NULL
)
1758 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1762 /* initialize the buffer */
1763 ZeroMemory(DriverInfoDetailDataW
,
1765 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
1768 /* call the unicode version */
1769 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
1772 DriverInfoDetailDataW
,
1778 if (DriverInfoDetailDataW
!= NULL
)
1780 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
1781 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
1782 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
1783 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
1784 if (WideCharToMultiByte(CP_ACP
,
1786 DriverInfoDetailDataW
->SectionName
,
1788 DriverInfoDetailData
->SectionName
,
1792 WideCharToMultiByte(CP_ACP
,
1794 DriverInfoDetailDataW
->InfFileName
,
1796 DriverInfoDetailData
->InfFileName
,
1800 WideCharToMultiByte(CP_ACP
,
1802 DriverInfoDetailDataW
->DrvDescription
,
1804 DriverInfoDetailData
->DrvDescription
,
1808 WideCharToMultiByte(CP_ACP
,
1810 DriverInfoDetailDataW
->HardwareID
,
1812 DriverInfoDetailData
->HardwareID
,
1818 DWORD hwidlen
= HardwareIDLen
;
1819 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
1821 /* count the strings in the list */
1824 len
= lstrlenA(s
) + 1;
1833 /* looks like the string list wasn't terminated... */
1834 SetLastError(ERROR_INVALID_USER_BUFFER
);
1840 /* make sure CompatIDsOffset points to the second string in the
1844 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
1845 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
1846 DriverInfoDetailData
->CompatIDsOffset
+ 1;
1850 DriverInfoDetailData
->CompatIDsOffset
= 0;
1851 DriverInfoDetailData
->CompatIDsLength
= 0;
1860 if (RequiredSize
!= NULL
)
1862 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
1863 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
1869 if (DriverInfoDetailDataW
!= NULL
)
1871 MyFree(DriverInfoDetailDataW
);
1877 /***********************************************************************
1878 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
1881 SetupDiGetDriverInfoDetailW(
1882 IN HDEVINFO DeviceInfoSet
,
1883 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1884 IN PSP_DRVINFO_DATA_W DriverInfoData
,
1885 IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
1886 IN DWORD DriverInfoDetailDataSize
,
1887 OUT PDWORD RequiredSize OPTIONAL
)
1891 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
1892 DriverInfoData
, DriverInfoDetailData
,
1893 DriverInfoDetailDataSize
, RequiredSize
);
1896 SetLastError(ERROR_INVALID_PARAMETER
);
1897 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1898 SetLastError(ERROR_INVALID_HANDLE
);
1899 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1900 SetLastError(ERROR_INVALID_HANDLE
);
1901 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1902 SetLastError(ERROR_INVALID_USER_BUFFER
);
1903 else if (!DriverInfoData
)
1904 SetLastError(ERROR_INVALID_PARAMETER
);
1905 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
1906 SetLastError(ERROR_INVALID_PARAMETER
);
1907 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
1908 SetLastError(ERROR_INVALID_PARAMETER
);
1909 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
1910 SetLastError(ERROR_INVALID_USER_BUFFER
);
1911 else if (DriverInfoData
->Reserved
== 0)
1912 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1915 struct DriverInfoElement
*driverInfoElement
;
1916 LPWSTR HardwareIDs
= NULL
;
1917 LPWSTR CompatibleIDs
= NULL
;
1918 LPWSTR pBuffer
= NULL
;
1919 LPCWSTR DeviceID
= NULL
;
1920 ULONG HardwareIDsSize
, CompatibleIDsSize
;
1921 ULONG sizeNeeded
, sizeLeft
, size
;
1924 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
1926 /* Get hardware and compatible IDs lists */
1927 Result
= GetHardwareAndCompatibleIDsLists(
1930 &HardwareIDs
, &HardwareIDsSize
,
1931 &CompatibleIDs
, &CompatibleIDsSize
);
1935 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
1936 + HardwareIDsSize
+ CompatibleIDsSize
;
1938 *RequiredSize
= sizeNeeded
;
1940 if (!DriverInfoDetailData
)
1947 DriverInfoDetailData
,
1948 &driverInfoElement
->Details
,
1949 driverInfoElement
->Details
.cbSize
);
1950 DriverInfoDetailData
->CompatIDsOffset
= 0;
1951 DriverInfoDetailData
->CompatIDsLength
= 0;
1953 sizeLeft
= (DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
);
1954 pBuffer
= DriverInfoDetailData
->HardwareID
;
1955 /* Add as many as possible HardwareIDs in the list */
1956 DeviceID
= HardwareIDs
;
1957 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
1959 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
1960 wcscpy(pBuffer
, DeviceID
);
1961 DeviceID
+= size
+ 1;
1962 pBuffer
+= size
+ 1;
1963 sizeLeft
-= size
+ 1;
1964 DriverInfoDetailData
->CompatIDsOffset
+= size
+ 1;
1968 *pBuffer
= UNICODE_NULL
;
1970 DriverInfoDetailData
->CompatIDsOffset
++;
1972 /* Add as many as possible CompatibleIDs in the list */
1973 DeviceID
= CompatibleIDs
;
1974 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
1976 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
1977 wcscpy(pBuffer
, DeviceID
);
1978 DeviceID
+= size
+ 1;
1979 pBuffer
+= size
+ 1;
1980 sizeLeft
-= size
+ 1;
1981 DriverInfoDetailData
->CompatIDsLength
+= size
+ 1;
1985 *pBuffer
= UNICODE_NULL
;
1987 DriverInfoDetailData
->CompatIDsLength
++;
1990 if (sizeNeeded
> DriverInfoDetailDataSize
)
1991 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1996 MyFree(HardwareIDs
);
1997 MyFree(CompatibleIDs
);
2000 TRACE("Returning %d\n", ret
);
2004 /***********************************************************************
2005 * SetupDiGetDriverInstallParamsW (SETUPAPI.@)
2008 SetupDiGetDriverInstallParamsW(
2009 IN HDEVINFO DeviceInfoSet
,
2010 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
2011 IN PSP_DRVINFO_DATA_W DriverInfoData
,
2012 OUT PSP_DRVINSTALL_PARAMS DriverInstallParams
)
2016 TRACE("%p %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
, DriverInstallParams
);
2018 if (!DeviceInfoSet
|| !DriverInfoData
|| !DriverInstallParams
)
2019 SetLastError(ERROR_INVALID_PARAMETER
);
2020 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2021 SetLastError(ERROR_INVALID_HANDLE
);
2022 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2023 SetLastError(ERROR_INVALID_HANDLE
);
2024 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2025 SetLastError(ERROR_INVALID_USER_BUFFER
);
2026 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
2027 SetLastError(ERROR_INVALID_USER_BUFFER
);
2028 else if (DriverInstallParams
->cbSize
!= sizeof(SP_DRVINSTALL_PARAMS
))
2029 SetLastError(ERROR_INVALID_USER_BUFFER
);
2032 SP_DEVINSTALL_PARAMS InstallParams
;
2034 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
2035 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
2037 struct DriverInfoElement
*driverInfo
;
2038 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
2039 if (driverInfo
== NULL
)
2040 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2044 DriverInstallParams
,
2045 &driverInfo
->Params
,
2046 DriverInstallParams
->cbSize
);
2052 TRACE("Returning %d\n", ret
);
2056 /***********************************************************************
2057 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
2060 SetupDiSelectBestCompatDrv(
2061 IN HDEVINFO DeviceInfoSet
,
2062 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2064 SP_DRVINFO_DATA_W drvInfoData
;
2067 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2069 /* Drivers are sorted by rank in the driver list, so
2070 * the first driver in the list is the best one.
2072 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
2073 ret
= SetupDiEnumDriverInfoW(
2077 0, /* Member index */
2082 ret
= SetupDiSetSelectedDriverW(
2088 TRACE("Returning %d\n", ret
);
2092 /***********************************************************************
2093 * SetupDiInstallDriverFiles (SETUPAPI.@)
2096 SetupDiInstallDriverFiles(
2097 IN HDEVINFO DeviceInfoSet
,
2098 IN PSP_DEVINFO_DATA DeviceInfoData
)
2102 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2105 SetLastError(ERROR_INVALID_PARAMETER
);
2106 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2107 SetLastError(ERROR_INVALID_HANDLE
);
2108 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2109 SetLastError(ERROR_INVALID_HANDLE
);
2110 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2111 SetLastError(ERROR_INVALID_USER_BUFFER
);
2112 else if (DeviceInfoData
&& ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
2113 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2114 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
2115 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2118 SP_DEVINSTALL_PARAMS_W InstallParams
;
2119 struct DriverInfoElement
*SelectedDriver
;
2120 WCHAR SectionName
[MAX_PATH
];
2121 DWORD SectionNameLength
= 0;
2122 PVOID InstallMsgHandler
;
2123 PVOID InstallMsgHandlerContext
;
2124 PVOID Context
= NULL
;
2126 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
2127 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
2131 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
2132 if (!SelectedDriver
)
2134 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2138 ret
= SetupDiGetActualSectionToInstallW(
2139 SelectedDriver
->InfFileDetails
->hInf
,
2140 SelectedDriver
->Details
.SectionName
,
2141 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
2145 if (InstallParams
.InstallMsgHandler
)
2147 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
2148 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
2152 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
2155 InstallMsgHandler
= SetupDefaultQueueCallbackW
;
2156 InstallMsgHandlerContext
= Context
;
2158 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
2159 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
2160 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
2161 InstallMsgHandler
, InstallMsgHandlerContext
,
2162 DeviceInfoSet
, DeviceInfoData
);
2166 /* Install files from .CoInstallers section */
2167 lstrcatW(SectionName
, DotCoInstallers
);
2168 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
2169 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
2170 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
2171 InstallMsgHandler
, InstallMsgHandlerContext
,
2172 DeviceInfoSet
, DeviceInfoData
);
2176 /* Set the DI_NOFILECOPY flag to prevent another
2177 * installation during SetupDiInstallDevice */
2178 InstallParams
.Flags
|= DI_NOFILECOPY
;
2179 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
2183 SetupTermDefaultQueueCallback(Context
);
2187 TRACE("Returning %d\n", ret
);