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
;
1114 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
1116 if (strcmpiW(DeviceId
, currentId
) == 0)
1123 currentInfFileDetails
,
1128 DriverDate
, DriverVersion
,
1129 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
1130 DriverAlreadyAdded
= TRUE
;
1136 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
1138 if (strcmpiW(DeviceId
, currentId
) == 0)
1145 currentInfFileDetails
,
1150 DriverDate
, DriverVersion
,
1151 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
1152 DriverAlreadyAdded
= TRUE
;
1156 HeapFree(GetProcessHeap(), 0, DeviceId
);
1159 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
1162 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
1163 ManufacturerName
= NULL
;
1164 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
1169 HeapFree(GetProcessHeap(), 0, ProviderName
);
1170 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
1171 ProviderName
= ExcludeFromSelect
= NULL
;
1173 DereferenceInfFile(currentInfFileDetails
);
1174 currentInfFileDetails
= NULL
;
1185 InstallParams
.Flags
|= DI_DIDCOMPAT
;
1186 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
1190 InstallParams
.Flags
|= DI_DIDCLASS
;
1191 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
1193 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1196 HeapFree(GetProcessHeap(), 0, ProviderName
);
1197 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
1198 MyFree(HardwareIDs
);
1199 MyFree(CompatibleIDs
);
1200 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
1201 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
1202 if (currentInfFileDetails
)
1203 DereferenceInfFile(currentInfFileDetails
);
1204 HeapFree(GetProcessHeap(), 0, Buffer
);
1206 TRACE("Returning %d\n", ret
);
1210 /***********************************************************************
1211 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
1214 SetupDiDestroyDriverInfoList(
1215 IN HDEVINFO DeviceInfoSet
,
1216 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1217 IN DWORD DriverType
)
1219 struct DeviceInfoSet
*list
;
1222 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
1225 SetLastError(ERROR_INVALID_HANDLE
);
1226 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1227 SetLastError(ERROR_INVALID_HANDLE
);
1228 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
1229 SetLastError(ERROR_INVALID_PARAMETER
);
1230 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
1231 SetLastError(ERROR_INVALID_PARAMETER
);
1232 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1233 SetLastError(ERROR_INVALID_USER_BUFFER
);
1236 PLIST_ENTRY ListEntry
;
1237 struct DriverInfoElement
*driverInfo
;
1238 SP_DEVINSTALL_PARAMS_W InstallParams
;
1240 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1241 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1244 if (!DeviceInfoData
)
1245 /* Fall back to destroying class driver list */
1246 DriverType
= SPDIT_CLASSDRIVER
;
1248 if (DriverType
== SPDIT_CLASSDRIVER
)
1250 while (!IsListEmpty(&list
->DriverListHead
))
1252 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
1253 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
1254 DestroyDriverInfoElement(driverInfo
);
1256 InstallParams
.Reserved
= 0;
1257 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
1258 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
1259 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
1263 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
1264 struct DeviceInfo
*deviceInfo
;
1266 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1267 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
1269 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1270 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
1272 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
1273 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
1274 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
1276 InstallParamsSet
.Reserved
= 0;
1277 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
1279 DestroyDriverInfoElement(driverInfo
);
1281 InstallParams
.Reserved
= 0;
1282 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
1283 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
1284 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1289 TRACE("Returning %d\n", ret
);
1293 /***********************************************************************
1294 * SetupDiEnumDriverInfoA (SETUPAPI.@)
1297 SetupDiEnumDriverInfoA(
1298 IN HDEVINFO DeviceInfoSet
,
1299 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1300 IN DWORD DriverType
,
1301 IN DWORD MemberIndex
,
1302 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
1304 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
1307 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1308 DriverType
, MemberIndex
, DriverInfoData
);
1310 if (DriverInfoData
== NULL
)
1311 SetLastError(ERROR_INVALID_PARAMETER
);
1312 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
1313 SetLastError(ERROR_INVALID_USER_BUFFER
);
1316 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1317 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
1318 DriverType
, MemberIndex
, &driverInfoData2W
);
1322 /* Do W->A conversion */
1323 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
1324 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
1325 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
1326 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
1328 DriverInfoData
->Description
[0] = '\0';
1331 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1332 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1334 DriverInfoData
->MfgName
[0] = '\0';
1337 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1338 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1340 DriverInfoData
->ProviderName
[0] = '\0';
1343 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1345 /* Copy more fields */
1346 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1347 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1352 TRACE("Returning %d\n", ret
);
1357 /***********************************************************************
1358 * SetupDiEnumDriverInfoW (SETUPAPI.@)
1361 SetupDiEnumDriverInfoW(
1362 IN HDEVINFO DeviceInfoSet
,
1363 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1364 IN DWORD DriverType
,
1365 IN DWORD MemberIndex
,
1366 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
1368 PLIST_ENTRY ListHead
;
1371 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1372 DriverType
, MemberIndex
, DriverInfoData
);
1374 if (!DeviceInfoSet
|| !DriverInfoData
)
1375 SetLastError(ERROR_INVALID_PARAMETER
);
1376 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1377 SetLastError(ERROR_INVALID_HANDLE
);
1378 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1379 SetLastError(ERROR_INVALID_HANDLE
);
1380 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
1381 SetLastError(ERROR_INVALID_PARAMETER
);
1382 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
1383 SetLastError(ERROR_INVALID_PARAMETER
);
1384 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1385 SetLastError(ERROR_INVALID_USER_BUFFER
);
1388 struct DeviceInfo
*devInfo
= NULL
;
1389 PLIST_ENTRY ItemList
;
1391 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1392 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
1394 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1398 ListHead
= &devInfo
->DriverListHead
;
1401 ItemList
= ListHead
->Flink
;
1402 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
1403 ItemList
= ItemList
->Flink
;
1404 if (ItemList
== ListHead
)
1405 SetLastError(ERROR_NO_MORE_ITEMS
);
1408 struct DriverInfoElement
*DrvInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1411 &DriverInfoData
->DriverType
,
1412 &DrvInfo
->Info
.DriverType
,
1413 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1418 TRACE("Returning %d\n", ret
);
1422 /***********************************************************************
1423 * SetupDiGetSelectedDriverA (SETUPAPI.@)
1426 SetupDiGetSelectedDriverA(
1427 IN HDEVINFO DeviceInfoSet
,
1428 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1429 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
1431 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
1434 if (DriverInfoData
== NULL
)
1435 SetLastError(ERROR_INVALID_PARAMETER
);
1436 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
1437 SetLastError(ERROR_INVALID_USER_BUFFER
);
1440 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1442 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
1448 /* Do W->A conversion */
1449 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
1450 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
1451 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
1452 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
1454 DriverInfoData
->Description
[0] = '\0';
1457 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1458 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1460 DriverInfoData
->MfgName
[0] = '\0';
1463 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1464 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1466 DriverInfoData
->ProviderName
[0] = '\0';
1469 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1471 /* Copy more fields */
1472 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1473 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1481 /***********************************************************************
1482 * SetupDiGetSelectedDriverW (SETUPAPI.@)
1485 SetupDiGetSelectedDriverW(
1486 IN HDEVINFO DeviceInfoSet
,
1487 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1488 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
1492 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
1494 if (!DeviceInfoSet
|| !DriverInfoData
)
1495 SetLastError(ERROR_INVALID_PARAMETER
);
1496 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1497 SetLastError(ERROR_INVALID_HANDLE
);
1498 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1499 SetLastError(ERROR_INVALID_HANDLE
);
1500 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1501 SetLastError(ERROR_INVALID_USER_BUFFER
);
1502 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1503 SetLastError(ERROR_INVALID_USER_BUFFER
);
1506 SP_DEVINSTALL_PARAMS InstallParams
;
1508 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1509 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1511 struct DriverInfoElement
*driverInfo
;
1512 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
1513 if (driverInfo
== NULL
)
1514 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1518 &DriverInfoData
->DriverType
,
1519 &driverInfo
->Info
.DriverType
,
1520 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1526 TRACE("Returning %d\n", ret
);
1530 /***********************************************************************
1531 * SetupDiSetSelectedDriverA (SETUPAPI.@)
1534 SetupDiSetSelectedDriverA(
1535 IN HDEVINFO DeviceInfoSet
,
1536 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1537 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
1539 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
1540 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
1543 if (DriverInfoData
!= NULL
)
1545 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
1546 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
))
1548 SetLastError(ERROR_INVALID_PARAMETER
);
1552 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1553 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1555 if (DriverInfoDataW
.Reserved
== 0)
1557 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1559 /* convert the strings to unicode */
1560 if (!MultiByteToWideChar(CP_ACP
,
1562 DriverInfoData
->Description
,
1564 DriverInfoDataW
.Description
,
1566 !MultiByteToWideChar(CP_ACP
,
1568 DriverInfoData
->ProviderName
,
1570 DriverInfoDataW
.ProviderName
,
1577 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
1580 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
1584 if (ret
&& pDriverInfoDataW
!= NULL
)
1586 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
1592 /***********************************************************************
1593 * SetupDiSetSelectedDriverW (SETUPAPI.@)
1596 SetupDiSetSelectedDriverW(
1597 IN HDEVINFO DeviceInfoSet
,
1598 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1599 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
1603 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
1606 SetLastError(ERROR_INVALID_PARAMETER
);
1607 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1608 SetLastError(ERROR_INVALID_HANDLE
);
1609 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1610 SetLastError(ERROR_INVALID_HANDLE
);
1611 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1612 SetLastError(ERROR_INVALID_USER_BUFFER
);
1613 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
1614 SetLastError(ERROR_INVALID_USER_BUFFER
);
1617 struct DriverInfoElement
**pDriverInfo
;
1618 PLIST_ENTRY ListHead
, ItemList
;
1622 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
1623 ListHead
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->DriverListHead
;
1627 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
1628 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1631 if (!DriverInfoData
)
1633 *pDriverInfo
= NULL
;
1638 /* Search selected driver in list */
1639 ItemList
= ListHead
->Flink
;
1640 while (ItemList
!= ListHead
)
1642 if (DriverInfoData
->Reserved
!= 0)
1644 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
1649 /* The caller wants to compare only DriverType, Description and ProviderName fields */
1650 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1651 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
1652 && strcmpW(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
1653 && strcmpW(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
1658 ItemList
= ItemList
->Flink
;
1660 if (ItemList
== ListHead
)
1661 SetLastError(ERROR_INVALID_PARAMETER
);
1664 *pDriverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1665 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
1667 TRACE("Choosing driver whose rank is 0x%lx\n",
1668 (*pDriverInfo
)->Params
.Rank
);
1670 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
1675 TRACE("Returning %d\n", ret
);
1679 /***********************************************************************
1680 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
1683 SetupDiGetDriverInfoDetailA(
1684 IN HDEVINFO DeviceInfoSet
,
1685 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1686 IN PSP_DRVINFO_DATA_A DriverInfoData
,
1687 IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
1688 IN DWORD DriverInfoDetailDataSize
,
1689 OUT PDWORD RequiredSize OPTIONAL
)
1691 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
1692 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
1694 DWORD HardwareIDLen
= 0;
1697 /* do some sanity checks, the unicode version might do more thorough checks */
1698 if (DriverInfoData
== NULL
||
1699 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
1700 (DriverInfoDetailData
!= NULL
&&
1701 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
1702 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
1704 SetLastError(ERROR_INVALID_PARAMETER
);
1708 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
1709 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
1711 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1713 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1715 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1719 SetLastError(ERROR_INVALID_PARAMETER
);
1722 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1723 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1725 /* convert the strings to unicode */
1726 if (MultiByteToWideChar(CP_ACP
,
1728 DriverInfoData
->Description
,
1730 DriverInfoDataW
.Description
,
1732 MultiByteToWideChar(CP_ACP
,
1734 DriverInfoData
->MfgName
,
1736 DriverInfoDataW
.MfgName
,
1738 MultiByteToWideChar(CP_ACP
,
1740 DriverInfoData
->ProviderName
,
1742 DriverInfoDataW
.ProviderName
,
1745 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
1747 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
1748 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
1751 if (DriverInfoDetailData
!= NULL
)
1753 /* calculate the unicode buffer size from the ansi buffer size */
1754 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
1755 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
1756 (HardwareIDLen
* sizeof(WCHAR
));
1758 DriverInfoDetailDataW
= MyMalloc(BufSize
);
1759 if (DriverInfoDetailDataW
== NULL
)
1761 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1765 /* initialize the buffer */
1766 ZeroMemory(DriverInfoDetailDataW
,
1768 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
1771 /* call the unicode version */
1772 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
1775 DriverInfoDetailDataW
,
1781 if (DriverInfoDetailDataW
!= NULL
)
1783 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
1784 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
1785 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
1786 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
1787 if (WideCharToMultiByte(CP_ACP
,
1789 DriverInfoDetailDataW
->SectionName
,
1791 DriverInfoDetailData
->SectionName
,
1795 WideCharToMultiByte(CP_ACP
,
1797 DriverInfoDetailDataW
->InfFileName
,
1799 DriverInfoDetailData
->InfFileName
,
1803 WideCharToMultiByte(CP_ACP
,
1805 DriverInfoDetailDataW
->DrvDescription
,
1807 DriverInfoDetailData
->DrvDescription
,
1811 WideCharToMultiByte(CP_ACP
,
1813 DriverInfoDetailDataW
->HardwareID
,
1815 DriverInfoDetailData
->HardwareID
,
1821 DWORD hwidlen
= HardwareIDLen
;
1822 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
1824 /* count the strings in the list */
1827 len
= lstrlenA(s
) + 1;
1836 /* looks like the string list wasn't terminated... */
1837 SetLastError(ERROR_INVALID_USER_BUFFER
);
1843 /* make sure CompatIDsOffset points to the second string in the
1847 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
1848 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
1849 DriverInfoDetailData
->CompatIDsOffset
+ 1;
1853 DriverInfoDetailData
->CompatIDsOffset
= 0;
1854 DriverInfoDetailData
->CompatIDsLength
= 0;
1863 if (RequiredSize
!= NULL
)
1865 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
1866 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
1872 if (DriverInfoDetailDataW
!= NULL
)
1874 MyFree(DriverInfoDetailDataW
);
1880 /***********************************************************************
1881 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
1884 SetupDiGetDriverInfoDetailW(
1885 IN HDEVINFO DeviceInfoSet
,
1886 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1887 IN PSP_DRVINFO_DATA_W DriverInfoData
,
1888 IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
1889 IN DWORD DriverInfoDetailDataSize
,
1890 OUT PDWORD RequiredSize OPTIONAL
)
1894 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
1895 DriverInfoData
, DriverInfoDetailData
,
1896 DriverInfoDetailDataSize
, RequiredSize
);
1899 SetLastError(ERROR_INVALID_PARAMETER
);
1900 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1901 SetLastError(ERROR_INVALID_HANDLE
);
1902 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1903 SetLastError(ERROR_INVALID_HANDLE
);
1904 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1905 SetLastError(ERROR_INVALID_USER_BUFFER
);
1906 else if (!DriverInfoData
)
1907 SetLastError(ERROR_INVALID_PARAMETER
);
1908 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
1909 SetLastError(ERROR_INVALID_PARAMETER
);
1910 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
1911 SetLastError(ERROR_INVALID_PARAMETER
);
1912 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
1913 SetLastError(ERROR_INVALID_USER_BUFFER
);
1914 else if (DriverInfoData
->Reserved
== 0)
1915 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1918 struct DriverInfoElement
*driverInfoElement
;
1919 LPWSTR HardwareIDs
= NULL
;
1920 LPWSTR CompatibleIDs
= NULL
;
1921 LPWSTR pBuffer
= NULL
;
1922 LPCWSTR DeviceID
= NULL
;
1923 ULONG HardwareIDsSize
, CompatibleIDsSize
;
1924 ULONG sizeNeeded
, sizeLeft
, size
;
1927 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
1929 /* Get hardware and compatible IDs lists */
1930 Result
= GetHardwareAndCompatibleIDsLists(
1933 &HardwareIDs
, &HardwareIDsSize
,
1934 &CompatibleIDs
, &CompatibleIDsSize
);
1938 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
1939 + HardwareIDsSize
+ CompatibleIDsSize
;
1941 *RequiredSize
= sizeNeeded
;
1943 if (!DriverInfoDetailData
)
1950 DriverInfoDetailData
,
1951 &driverInfoElement
->Details
,
1952 driverInfoElement
->Details
.cbSize
);
1953 DriverInfoDetailData
->CompatIDsOffset
= 0;
1954 DriverInfoDetailData
->CompatIDsLength
= 0;
1956 sizeLeft
= (DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
);
1957 pBuffer
= DriverInfoDetailData
->HardwareID
;
1958 /* Add as many as possible HardwareIDs in the list */
1959 DeviceID
= HardwareIDs
;
1960 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
1962 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
1963 wcscpy(pBuffer
, DeviceID
);
1964 DeviceID
+= size
+ 1;
1965 pBuffer
+= size
+ 1;
1966 sizeLeft
-= size
+ 1;
1967 DriverInfoDetailData
->CompatIDsOffset
+= size
+ 1;
1971 *pBuffer
= UNICODE_NULL
;
1973 DriverInfoDetailData
->CompatIDsOffset
++;
1975 /* Add as many as possible CompatibleIDs in the list */
1976 DeviceID
= CompatibleIDs
;
1977 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
1979 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
1980 wcscpy(pBuffer
, DeviceID
);
1981 DeviceID
+= size
+ 1;
1982 pBuffer
+= size
+ 1;
1983 sizeLeft
-= size
+ 1;
1984 DriverInfoDetailData
->CompatIDsLength
+= size
+ 1;
1988 *pBuffer
= UNICODE_NULL
;
1990 DriverInfoDetailData
->CompatIDsLength
++;
1993 if (sizeNeeded
> DriverInfoDetailDataSize
)
1994 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1999 MyFree(HardwareIDs
);
2000 MyFree(CompatibleIDs
);
2003 TRACE("Returning %d\n", ret
);
2007 /***********************************************************************
2008 * SetupDiGetDriverInstallParamsW (SETUPAPI.@)
2011 SetupDiGetDriverInstallParamsW(
2012 IN HDEVINFO DeviceInfoSet
,
2013 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
2014 IN PSP_DRVINFO_DATA_W DriverInfoData
,
2015 OUT PSP_DRVINSTALL_PARAMS DriverInstallParams
)
2019 TRACE("%p %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
, DriverInstallParams
);
2021 if (!DeviceInfoSet
|| !DriverInfoData
|| !DriverInstallParams
)
2022 SetLastError(ERROR_INVALID_PARAMETER
);
2023 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2024 SetLastError(ERROR_INVALID_HANDLE
);
2025 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2026 SetLastError(ERROR_INVALID_HANDLE
);
2027 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2028 SetLastError(ERROR_INVALID_USER_BUFFER
);
2029 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
2030 SetLastError(ERROR_INVALID_USER_BUFFER
);
2031 else if (DriverInstallParams
->cbSize
!= sizeof(SP_DRVINSTALL_PARAMS
))
2032 SetLastError(ERROR_INVALID_USER_BUFFER
);
2035 SP_DEVINSTALL_PARAMS InstallParams
;
2037 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
2038 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
2040 struct DriverInfoElement
*driverInfo
;
2041 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
2042 if (driverInfo
== NULL
)
2043 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2047 DriverInstallParams
,
2048 &driverInfo
->Params
,
2049 DriverInstallParams
->cbSize
);
2055 TRACE("Returning %d\n", ret
);
2059 /***********************************************************************
2060 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
2063 SetupDiSelectBestCompatDrv(
2064 IN HDEVINFO DeviceInfoSet
,
2065 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2067 SP_DRVINFO_DATA_W drvInfoData
;
2070 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2072 /* Drivers are sorted by rank in the driver list, so
2073 * the first driver in the list is the best one.
2075 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
2076 ret
= SetupDiEnumDriverInfoW(
2080 0, /* Member index */
2085 ret
= SetupDiSetSelectedDriverW(
2091 TRACE("Returning %d\n", ret
);
2095 /***********************************************************************
2096 * SetupDiInstallDriverFiles (SETUPAPI.@)
2099 SetupDiInstallDriverFiles(
2100 IN HDEVINFO DeviceInfoSet
,
2101 IN PSP_DEVINFO_DATA DeviceInfoData
)
2105 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
2108 SetLastError(ERROR_INVALID_PARAMETER
);
2109 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2110 SetLastError(ERROR_INVALID_HANDLE
);
2111 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2112 SetLastError(ERROR_INVALID_HANDLE
);
2113 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2114 SetLastError(ERROR_INVALID_USER_BUFFER
);
2115 else if (DeviceInfoData
&& ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
2116 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2117 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
2118 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2121 SP_DEVINSTALL_PARAMS_W InstallParams
;
2122 struct DriverInfoElement
*SelectedDriver
;
2123 WCHAR SectionName
[MAX_PATH
];
2124 DWORD SectionNameLength
= 0;
2125 PVOID InstallMsgHandler
;
2126 PVOID InstallMsgHandlerContext
;
2127 PVOID Context
= NULL
;
2129 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
2130 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
2134 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
2135 if (!SelectedDriver
)
2137 SetLastError(ERROR_NO_DRIVER_SELECTED
);
2141 ret
= SetupDiGetActualSectionToInstallW(
2142 SelectedDriver
->InfFileDetails
->hInf
,
2143 SelectedDriver
->Details
.SectionName
,
2144 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
2148 if (InstallParams
.InstallMsgHandler
)
2150 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
2151 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
2155 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
2158 InstallMsgHandler
= SetupDefaultQueueCallbackW
;
2159 InstallMsgHandlerContext
= Context
;
2161 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
2162 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
2163 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
2164 InstallMsgHandler
, InstallMsgHandlerContext
,
2165 DeviceInfoSet
, DeviceInfoData
);
2169 /* Install files from .CoInstallers section */
2170 lstrcatW(SectionName
, DotCoInstallers
);
2171 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
2172 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
2173 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
2174 InstallMsgHandler
, InstallMsgHandlerContext
,
2175 DeviceInfoSet
, DeviceInfoData
);
2179 /* Set the DI_NOFILECOPY flag to prevent another
2180 * installation during SetupDiInstallDevice */
2181 InstallParams
.Flags
|= DI_NOFILECOPY
;
2182 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
2186 SetupTermDefaultQueueCallback(Context
);
2190 TRACE("Returning %d\n", ret
);