xref: /reactos/dll/win32/setupapi/driver.c (revision 61e35141)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * SetupAPI driver-related functions
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2005-2006 Herv� Poussineau (hpoussin@reactos.org)
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck 
21c2c66affSColin Finck #include "setupapi_private.h"
22c2c66affSColin Finck 
23c2c66affSColin Finck /* Unicode constants */
24c2c66affSColin Finck static const WCHAR BackSlash[] = {'\\',0};
25c2c66affSColin Finck static const WCHAR ClassGUID[]  = {'C','l','a','s','s','G','U','I','D',0};
26c2c66affSColin Finck static const WCHAR DotCoInstallers[]  = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
27c2c66affSColin Finck static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
28c2c66affSColin Finck static const WCHAR Version[]  = {'V','e','r','s','i','o','n',0};
29c2c66affSColin Finck 
30c2c66affSColin Finck static const WCHAR INF_MANUFACTURER[]  = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
31c2c66affSColin Finck static const WCHAR INF_PROVIDER[]  = {'P','r','o','v','i','d','e','r',0};
32c2c66affSColin Finck static const WCHAR INF_DRIVER_VER[]  = {'D','r','i','v','e','r','V','e','r',0};
33c2c66affSColin Finck 
34c2c66affSColin Finck 
35c2c66affSColin Finck /***********************************************************************
36c2c66affSColin Finck  *		struct InfFileDetails management
37c2c66affSColin Finck  */
38c2c66affSColin Finck static VOID
ReferenceInfFile(struct InfFileDetails * infFile)39c2c66affSColin Finck ReferenceInfFile(struct InfFileDetails* infFile)
40c2c66affSColin Finck {
41c2c66affSColin Finck     InterlockedIncrement(&infFile->References);
42c2c66affSColin Finck }
43c2c66affSColin Finck 
44c2c66affSColin Finck VOID
DereferenceInfFile(struct InfFileDetails * infFile)45c2c66affSColin Finck DereferenceInfFile(struct InfFileDetails* infFile)
46c2c66affSColin Finck {
47c2c66affSColin Finck     if (InterlockedDecrement(&infFile->References) == 0)
48c2c66affSColin Finck     {
49c2c66affSColin Finck         SetupCloseInfFile(infFile->hInf);
50c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, infFile);
51c2c66affSColin Finck     }
52c2c66affSColin Finck }
53c2c66affSColin Finck 
54c2c66affSColin Finck struct InfFileDetails *
CreateInfFileDetails(IN LPCWSTR FullInfFileName)55c2c66affSColin Finck CreateInfFileDetails(
56c2c66affSColin Finck     IN LPCWSTR FullInfFileName)
57c2c66affSColin Finck {
58c2c66affSColin Finck     struct InfFileDetails *details;
59c2c66affSColin Finck     PWCHAR last;
60c2c66affSColin Finck     DWORD Needed;
61c2c66affSColin Finck 
62c2c66affSColin Finck     Needed = FIELD_OFFSET(struct InfFileDetails, szData)
63c2c66affSColin Finck         + strlenW(FullInfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
64c2c66affSColin Finck 
65c2c66affSColin Finck     details = HeapAlloc(GetProcessHeap(), 0, Needed);
66c2c66affSColin Finck     if (!details)
67c2c66affSColin Finck     {
68c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
69c2c66affSColin Finck         return NULL;
70c2c66affSColin Finck     }
71c2c66affSColin Finck 
72c2c66affSColin Finck     memset(details, 0, Needed);
73c2c66affSColin Finck     strcpyW(details->szData, FullInfFileName);
74c2c66affSColin Finck     last = strrchrW(details->szData, '\\');
75c2c66affSColin Finck     if (last)
76c2c66affSColin Finck     {
77c2c66affSColin Finck         details->DirectoryName = details->szData;
78c2c66affSColin Finck         details->FileName = last + 1;
79c2c66affSColin Finck         *last = '\0';
80c2c66affSColin Finck     }
81c2c66affSColin Finck     else
82c2c66affSColin Finck         details->FileName = details->szData;
83c2c66affSColin Finck     ReferenceInfFile(details);
84c2c66affSColin Finck     details->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
85c2c66affSColin Finck     if (details->hInf == INVALID_HANDLE_VALUE)
86c2c66affSColin Finck     {
87c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, details);
88c2c66affSColin Finck         return NULL;
89c2c66affSColin Finck     }
90c2c66affSColin Finck     return details;
91c2c66affSColin Finck }
92c2c66affSColin Finck 
93c2c66affSColin Finck BOOL
DestroyDriverInfoElement(struct DriverInfoElement * driverInfo)94c2c66affSColin Finck DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
95c2c66affSColin Finck {
96c2c66affSColin Finck     DereferenceInfFile(driverInfo->InfFileDetails);
97c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
98c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, driverInfo);
99c2c66affSColin Finck     return TRUE;
100c2c66affSColin Finck }
101c2c66affSColin Finck 
102c2c66affSColin Finck /***********************************************************************
103c2c66affSColin Finck  *		Helper functions for SetupDiBuildDriverInfoList
104c2c66affSColin Finck  */
105c2c66affSColin Finck static BOOL
AddKnownDriverToList(IN PLIST_ENTRY DriverListHead,IN DWORD DriverType,IN LPGUID ClassGuid,IN struct InfFileDetails * InfFileDetails,IN LPCWSTR InfFile,IN LPCWSTR SectionName,IN LPCWSTR DriverDescription,IN LPCWSTR ProviderName,IN LPCWSTR ManufacturerName,IN LPCWSTR MatchingId,IN FILETIME DriverDate,IN DWORDLONG DriverVersion,IN DWORD Rank)106c2c66affSColin Finck AddKnownDriverToList(
107c2c66affSColin Finck     IN PLIST_ENTRY DriverListHead,
108c2c66affSColin Finck     IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
109c2c66affSColin Finck     IN LPGUID ClassGuid,
110c2c66affSColin Finck     IN struct InfFileDetails *InfFileDetails,
111c2c66affSColin Finck     IN LPCWSTR InfFile,
112c2c66affSColin Finck     IN LPCWSTR SectionName,
113c2c66affSColin Finck     IN LPCWSTR DriverDescription,
114c2c66affSColin Finck     IN LPCWSTR ProviderName,
115c2c66affSColin Finck     IN LPCWSTR ManufacturerName,
116c2c66affSColin Finck     IN LPCWSTR MatchingId,
117c2c66affSColin Finck     IN FILETIME DriverDate,
118c2c66affSColin Finck     IN DWORDLONG DriverVersion,
119c2c66affSColin Finck     IN DWORD Rank)
120c2c66affSColin Finck {
121c2c66affSColin Finck     struct DriverInfoElement *driverInfo = NULL;
122c2c66affSColin Finck     HANDLE hFile = INVALID_HANDLE_VALUE;
123c2c66affSColin Finck     BOOL Result = FALSE;
124c2c66affSColin Finck     PLIST_ENTRY PreviousEntry;
125c2c66affSColin Finck     BOOL ret = FALSE;
126c2c66affSColin Finck 
127c2c66affSColin Finck     driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
128c2c66affSColin Finck     if (!driverInfo)
129c2c66affSColin Finck     {
130c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
131c2c66affSColin Finck         goto cleanup;
132c2c66affSColin Finck     }
133c2c66affSColin Finck     memset(driverInfo, 0, sizeof(struct DriverInfoElement));
134c2c66affSColin Finck 
135c2c66affSColin Finck     driverInfo->Params.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
136c2c66affSColin Finck     driverInfo->Params.Reserved = (ULONG_PTR)driverInfo;
137c2c66affSColin Finck 
138c2c66affSColin Finck     driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
139c2c66affSColin Finck     driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
140c2c66affSColin Finck 
141c2c66affSColin Finck     /* Copy InfFileName field */
142c2c66affSColin Finck     lstrcpynW(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
143c2c66affSColin Finck     driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
144c2c66affSColin Finck 
145c2c66affSColin Finck     /* Fill InfDate field */
146c2c66affSColin Finck     hFile = CreateFileW(
147c2c66affSColin Finck         InfFile,
148c2c66affSColin Finck         GENERIC_READ, FILE_SHARE_READ,
149c2c66affSColin Finck         NULL, OPEN_EXISTING, 0, NULL);
150c2c66affSColin Finck     if (hFile == INVALID_HANDLE_VALUE)
151c2c66affSColin Finck         goto cleanup;
152c2c66affSColin Finck     Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
153c2c66affSColin Finck     if (!Result)
154c2c66affSColin Finck         goto cleanup;
155c2c66affSColin Finck 
156c2c66affSColin Finck     /* Fill SectionName field */
157c2c66affSColin Finck     lstrcpynW(driverInfo->Details.SectionName, SectionName, LINE_LEN);
158c2c66affSColin Finck 
159c2c66affSColin Finck     /* Fill DrvDescription field */
160c2c66affSColin Finck     lstrcpynW(driverInfo->Details.DrvDescription, DriverDescription, LINE_LEN);
161c2c66affSColin Finck 
162c2c66affSColin Finck     /* Copy MatchingId information */
163c2c66affSColin Finck     if (MatchingId)
164c2c66affSColin Finck     {
165c2c66affSColin Finck         driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId) + 1) * sizeof(WCHAR));
166c2c66affSColin Finck         if (!driverInfo->MatchingId)
167c2c66affSColin Finck         {
168c2c66affSColin Finck             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
169c2c66affSColin Finck             goto cleanup;
170c2c66affSColin Finck         }
171c2c66affSColin Finck         RtlCopyMemory(driverInfo->MatchingId, MatchingId, (strlenW(MatchingId) + 1) * sizeof(WCHAR));
172c2c66affSColin Finck     }
173c2c66affSColin Finck     else
174c2c66affSColin Finck         driverInfo->MatchingId = NULL;
175c2c66affSColin Finck 
176c2c66affSColin Finck     TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
177c2c66affSColin Finck         debugstr_w(driverInfo->Details.DrvDescription), debugstr_w(InfFile),
178c2c66affSColin Finck         debugstr_w(SectionName), Rank);
179c2c66affSColin Finck 
180c2c66affSColin Finck     driverInfo->Params.Rank = Rank;
181c2c66affSColin Finck     memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
182c2c66affSColin Finck     memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
183c2c66affSColin Finck     driverInfo->Info.DriverType = DriverType;
184c2c66affSColin Finck     driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
185c2c66affSColin Finck     lstrcpynW(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
186c2c66affSColin Finck     driverInfo->Info.Description[LINE_LEN - 1] = '\0';
187c2c66affSColin Finck     lstrcpynW(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
188c2c66affSColin Finck     driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
189c2c66affSColin Finck     if (ProviderName)
190c2c66affSColin Finck     {
191c2c66affSColin Finck         lstrcpynW(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
192c2c66affSColin Finck         driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
193c2c66affSColin Finck     }
194c2c66affSColin Finck     else
195c2c66affSColin Finck         driverInfo->Info.ProviderName[0] = '\0';
196c2c66affSColin Finck     driverInfo->Info.DriverDate = DriverDate;
197c2c66affSColin Finck     driverInfo->Info.DriverVersion = DriverVersion;
198c2c66affSColin Finck     ReferenceInfFile(InfFileDetails);
199c2c66affSColin Finck     driverInfo->InfFileDetails = InfFileDetails;
200c2c66affSColin Finck 
201c2c66affSColin Finck     /* Insert current driver in driver list, according to its rank */
202c2c66affSColin Finck     PreviousEntry = DriverListHead->Flink;
203c2c66affSColin Finck     while (PreviousEntry != DriverListHead)
204c2c66affSColin Finck     {
205c2c66affSColin Finck         struct DriverInfoElement *CurrentDriver;
206c2c66affSColin Finck         CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
207c2c66affSColin Finck         if (CurrentDriver->Params.Rank > Rank ||
208c2c66affSColin Finck             (CurrentDriver->Params.Rank == Rank && CurrentDriver->DriverDate.QuadPart < driverInfo->DriverDate.QuadPart))
209c2c66affSColin Finck         {
210c2c66affSColin Finck             /* Insert before the current item */
211c2c66affSColin Finck             InsertHeadList(PreviousEntry->Blink, &driverInfo->ListEntry);
212c2c66affSColin Finck             break;
213c2c66affSColin Finck         }
214c2c66affSColin Finck         PreviousEntry = PreviousEntry->Flink;
215c2c66affSColin Finck     }
216c2c66affSColin Finck     if (PreviousEntry == DriverListHead)
217c2c66affSColin Finck     {
218c2c66affSColin Finck         /* Insert at the end of the list */
219c2c66affSColin Finck         InsertTailList(DriverListHead, &driverInfo->ListEntry);
220c2c66affSColin Finck     }
221c2c66affSColin Finck 
222c2c66affSColin Finck     ret = TRUE;
223c2c66affSColin Finck 
224c2c66affSColin Finck cleanup:
225c2c66affSColin Finck     if (!ret)
226c2c66affSColin Finck     {
227c2c66affSColin Finck         if (driverInfo)
228c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
229c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, driverInfo);
230c2c66affSColin Finck     }
231c2c66affSColin Finck     if (hFile != INVALID_HANDLE_VALUE)
232c2c66affSColin Finck         CloseHandle(hFile);
233c2c66affSColin Finck 
234c2c66affSColin Finck     return ret;
235c2c66affSColin Finck }
236c2c66affSColin Finck 
237c2c66affSColin Finck static BOOL
AddDriverToList(IN PLIST_ENTRY DriverListHead,IN DWORD DriverType,IN LPGUID ClassGuid,IN INFCONTEXT ContextDevice,IN struct InfFileDetails * InfFileDetails,IN LPCWSTR InfFile,IN LPCWSTR ProviderName,IN LPCWSTR ManufacturerName,IN LPCWSTR MatchingId,IN FILETIME DriverDate,IN DWORDLONG DriverVersion,IN DWORD Rank)238c2c66affSColin Finck AddDriverToList(
239c2c66affSColin Finck     IN PLIST_ENTRY DriverListHead,
240c2c66affSColin Finck     IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
241c2c66affSColin Finck     IN LPGUID ClassGuid,
242c2c66affSColin Finck     IN INFCONTEXT ContextDevice,
243c2c66affSColin Finck     IN struct InfFileDetails *InfFileDetails,
244c2c66affSColin Finck     IN LPCWSTR InfFile,
245c2c66affSColin Finck     IN LPCWSTR ProviderName,
246c2c66affSColin Finck     IN LPCWSTR ManufacturerName,
247c2c66affSColin Finck     IN LPCWSTR MatchingId,
248c2c66affSColin Finck     IN FILETIME DriverDate,
249c2c66affSColin Finck     IN DWORDLONG DriverVersion,
250c2c66affSColin Finck     IN DWORD Rank)
251c2c66affSColin Finck {
252c2c66affSColin Finck     LPWSTR SectionName = NULL;
253c2c66affSColin Finck     LPWSTR DriverDescription = NULL;
254c2c66affSColin Finck     BOOL Result;
255c2c66affSColin Finck     BOOL ret = FALSE;
256c2c66affSColin Finck 
257c2c66affSColin Finck     /* Read SectionName */
258c2c66affSColin Finck     SectionName = MyMalloc(LINE_LEN);
259c2c66affSColin Finck     if (!SectionName)
260c2c66affSColin Finck     {
261c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
262c2c66affSColin Finck         goto cleanup;
263c2c66affSColin Finck     }
264c2c66affSColin Finck     ZeroMemory(SectionName, LINE_LEN);
265c2c66affSColin Finck     Result = SetupGetStringFieldW(
266c2c66affSColin Finck         &ContextDevice,
267c2c66affSColin Finck         1,
268c2c66affSColin Finck         SectionName,
269c2c66affSColin Finck         LINE_LEN,
270c2c66affSColin Finck         NULL);
271c2c66affSColin Finck     if (!Result)
272c2c66affSColin Finck         goto cleanup;
273c2c66affSColin Finck 
274c2c66affSColin Finck     /* Read DriverDescription */
275c2c66affSColin Finck     DriverDescription = MyMalloc(LINE_LEN);
276c2c66affSColin Finck     if (!DriverDescription)
277c2c66affSColin Finck     {
278c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
279c2c66affSColin Finck         goto cleanup;
280c2c66affSColin Finck     }
281c2c66affSColin Finck     ZeroMemory(DriverDescription, LINE_LEN);
282c2c66affSColin Finck     Result = SetupGetStringFieldW(
283c2c66affSColin Finck         &ContextDevice,
284c2c66affSColin Finck         0, /* Field index */
285c2c66affSColin Finck         DriverDescription, LINE_LEN,
286c2c66affSColin Finck         NULL);
287c2c66affSColin Finck 
288c2c66affSColin Finck     ret = AddKnownDriverToList(
289c2c66affSColin Finck         DriverListHead,
290c2c66affSColin Finck         DriverType,
291c2c66affSColin Finck         ClassGuid,
292c2c66affSColin Finck         InfFileDetails,
293c2c66affSColin Finck         InfFile,
294c2c66affSColin Finck         SectionName,
295c2c66affSColin Finck         DriverDescription,
296c2c66affSColin Finck         ProviderName,
297c2c66affSColin Finck         ManufacturerName,
298c2c66affSColin Finck         MatchingId,
299c2c66affSColin Finck         DriverDate,
300c2c66affSColin Finck         DriverVersion,
301c2c66affSColin Finck         Rank);
302c2c66affSColin Finck 
303c2c66affSColin Finck cleanup:
304c2c66affSColin Finck     MyFree(SectionName);
305c2c66affSColin Finck     MyFree(DriverDescription);
306c2c66affSColin Finck 
307c2c66affSColin Finck     return ret;
308c2c66affSColin Finck }
309c2c66affSColin Finck 
310c2c66affSColin Finck static BOOL
GetVersionInformationFromInfFile(IN HINF hInf,OUT LPGUID ClassGuid,OUT LPWSTR * pProviderName,OUT FILETIME * DriverDate,OUT DWORDLONG * DriverVersion)311c2c66affSColin Finck GetVersionInformationFromInfFile(
312c2c66affSColin Finck     IN HINF hInf,
313c2c66affSColin Finck     OUT LPGUID ClassGuid,
314c2c66affSColin Finck     OUT LPWSTR* pProviderName,
315c2c66affSColin Finck     OUT FILETIME* DriverDate,
316c2c66affSColin Finck     OUT DWORDLONG* DriverVersion)
317c2c66affSColin Finck {
318c2c66affSColin Finck     DWORD RequiredSize;
319c2c66affSColin Finck     WCHAR guidW[MAX_GUID_STRING_LEN + 1];
320c2c66affSColin Finck     LPWSTR DriverVer = NULL;
321c2c66affSColin Finck     LPWSTR ProviderName = NULL;
322c2c66affSColin Finck     LPWSTR pComma; /* Points into DriverVer */
323c2c66affSColin Finck     LPWSTR pVersion = NULL; /* Points into DriverVer */
324c2c66affSColin Finck     SYSTEMTIME SystemTime;
325c2c66affSColin Finck     BOOL Result;
326c2c66affSColin Finck     BOOL ret = FALSE; /* Final result */
327c2c66affSColin Finck 
328c2c66affSColin Finck     /* Get class Guid */
329c2c66affSColin Finck     if (!SetupGetLineTextW(
330c2c66affSColin Finck         NULL, /* Context */
331c2c66affSColin Finck         hInf,
332c2c66affSColin Finck         Version, ClassGUID,
333c2c66affSColin Finck         guidW, sizeof(guidW),
334c2c66affSColin Finck         NULL /* Required size */))
335c2c66affSColin Finck     {
336c2c66affSColin Finck         goto cleanup;
337c2c66affSColin Finck     }
338c2c66affSColin Finck     guidW[37] = '\0'; /* Replace the } by a NULL character */
339c2c66affSColin Finck     if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
340c2c66affSColin Finck     {
341c2c66affSColin Finck         SetLastError(ERROR_GEN_FAILURE);
342c2c66affSColin Finck         goto cleanup;
343c2c66affSColin Finck     }
344c2c66affSColin Finck 
345c2c66affSColin Finck     /* Get provider name */
346c2c66affSColin Finck     Result = SetupGetLineTextW(
347c2c66affSColin Finck         NULL, /* Context */
348c2c66affSColin Finck         hInf, Version, INF_PROVIDER,
349c2c66affSColin Finck         NULL, 0,
350c2c66affSColin Finck         &RequiredSize);
351c2c66affSColin Finck     if (Result)
352c2c66affSColin Finck     {
353c2c66affSColin Finck         /* We know the needed buffer size */
354c2c66affSColin Finck         ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
355c2c66affSColin Finck         if (!ProviderName)
356c2c66affSColin Finck         {
357c2c66affSColin Finck             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
358c2c66affSColin Finck             goto cleanup;
359c2c66affSColin Finck         }
360c2c66affSColin Finck         Result = SetupGetLineTextW(
361c2c66affSColin Finck             NULL, /* Context */
362c2c66affSColin Finck             hInf, Version, INF_PROVIDER,
363c2c66affSColin Finck             ProviderName, RequiredSize,
364c2c66affSColin Finck             &RequiredSize);
365c2c66affSColin Finck     }
366c2c66affSColin Finck     if (!Result)
367c2c66affSColin Finck         goto cleanup;
368c2c66affSColin Finck     *pProviderName = ProviderName;
369c2c66affSColin Finck 
370c2c66affSColin Finck     /* Read the "DriverVer" value */
371c2c66affSColin Finck     Result = SetupGetLineTextW(
372c2c66affSColin Finck         NULL, /* Context */
373c2c66affSColin Finck         hInf, Version, INF_DRIVER_VER,
374c2c66affSColin Finck         NULL, 0,
375c2c66affSColin Finck         &RequiredSize);
376c2c66affSColin Finck     if (Result)
377c2c66affSColin Finck     {
378c2c66affSColin Finck         /* We know know the needed buffer size */
379c2c66affSColin Finck         DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
380c2c66affSColin Finck         if (!DriverVer)
381c2c66affSColin Finck         {
382c2c66affSColin Finck             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
383c2c66affSColin Finck             goto cleanup;
384c2c66affSColin Finck         }
385c2c66affSColin Finck         Result = SetupGetLineTextW(
386c2c66affSColin Finck             NULL, /* Context */
387c2c66affSColin Finck             hInf, Version, INF_DRIVER_VER,
388c2c66affSColin Finck             DriverVer, RequiredSize,
389c2c66affSColin Finck             &RequiredSize);
390c2c66affSColin Finck     }
391c2c66affSColin Finck     else
392c2c66affSColin Finck     {
393c2c66affSColin Finck         /* windows sets default date of 00/00/0000 when this directive is missing*/
394c2c66affSColin Finck         memset(DriverDate, 0, sizeof(FILETIME));
395c2c66affSColin Finck         *DriverVersion = 0;
396c2c66affSColin Finck         return TRUE;
397c2c66affSColin Finck     }
398c2c66affSColin Finck 
399c2c66affSColin Finck     /* Get driver date and driver version, by analyzing the "DriverVer" value */
400c2c66affSColin Finck     pComma = strchrW(DriverVer, ',');
401c2c66affSColin Finck     if (pComma != NULL)
402c2c66affSColin Finck     {
403c2c66affSColin Finck         *pComma = UNICODE_NULL;
404c2c66affSColin Finck         pVersion = pComma + 1;
405c2c66affSColin Finck     }
406c2c66affSColin Finck     /* Get driver date version. Invalid date = 00/00/00 */
407c2c66affSColin Finck     memset(DriverDate, 0, sizeof(FILETIME));
408c2c66affSColin Finck     if (strlenW(DriverVer) == 10
409c2c66affSColin Finck         && (DriverVer[2] == '-' || DriverVer[2] == '/')
410c2c66affSColin Finck         && (DriverVer[5] == '-' || DriverVer[5] == '/'))
411c2c66affSColin Finck     {
412c2c66affSColin Finck         memset(&SystemTime, 0, sizeof(SYSTEMTIME));
413c2c66affSColin Finck         DriverVer[2] = DriverVer[5] = UNICODE_NULL;
414c2c66affSColin Finck         SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
415c2c66affSColin Finck         SystemTime.wDay  = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
416c2c66affSColin Finck         SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
417c2c66affSColin Finck         SystemTimeToFileTime(&SystemTime, DriverDate);
418c2c66affSColin Finck     }
419c2c66affSColin Finck     /* Get driver version. Invalid version = 0.0.0.0 */
420c2c66affSColin Finck     *DriverVersion = 0;
421c2c66affSColin Finck     if (pVersion)
422c2c66affSColin Finck     {
423c2c66affSColin Finck         WORD Major, Minor = 0, Revision = 0, Build = 0;
424c2c66affSColin Finck         LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL;
425c2c66affSColin Finck         LARGE_INTEGER fullVersion;
426c2c66affSColin Finck 
427c2c66affSColin Finck         pMinor = strchrW(pVersion, '.');
428c2c66affSColin Finck         if (pMinor)
429c2c66affSColin Finck         {
430c2c66affSColin Finck             *pMinor = 0;
431c2c66affSColin Finck             pRevision = strchrW(++pMinor, '.');
432c2c66affSColin Finck             Minor = atoiW(pMinor);
433c2c66affSColin Finck         }
434c2c66affSColin Finck         if (pRevision)
435c2c66affSColin Finck         {
436c2c66affSColin Finck             *pRevision = 0;
437c2c66affSColin Finck             pBuild = strchrW(++pRevision, '.');
438c2c66affSColin Finck             Revision = atoiW(pRevision);
439c2c66affSColin Finck         }
440c2c66affSColin Finck         if (pBuild)
441c2c66affSColin Finck         {
442c2c66affSColin Finck             *pBuild = 0;
443c2c66affSColin Finck             pBuild++;
444c2c66affSColin Finck             Build = atoiW(pBuild);
445c2c66affSColin Finck         }
446c2c66affSColin Finck         Major = atoiW(pVersion);
447c2c66affSColin Finck         fullVersion.u.HighPart = Major << 16 | Minor;
448c2c66affSColin Finck         fullVersion.u.LowPart = Revision << 16 | Build;
449c2c66affSColin Finck         memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER));
450c2c66affSColin Finck     }
451c2c66affSColin Finck 
452c2c66affSColin Finck     ret = TRUE;
453c2c66affSColin Finck 
454c2c66affSColin Finck cleanup:
455c2c66affSColin Finck     if (!ret)
456c2c66affSColin Finck     {
457c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, ProviderName);
458c2c66affSColin Finck         *pProviderName = NULL;
459c2c66affSColin Finck     }
460c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, DriverVer);
461c2c66affSColin Finck 
462c2c66affSColin Finck     return ret;
463c2c66affSColin Finck }
464c2c66affSColin Finck 
465c2c66affSColin Finck static BOOL
GetHardwareAndCompatibleIDsLists(IN HDEVINFO DeviceInfoSet,IN OUT PSP_DEVINFO_DATA DeviceInfoData,OUT LPWSTR * pHardwareIDs OPTIONAL,OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL,OUT LPWSTR * pCompatibleIDs OPTIONAL,OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL)466c2c66affSColin Finck GetHardwareAndCompatibleIDsLists(
467c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
468c2c66affSColin Finck     IN OUT PSP_DEVINFO_DATA DeviceInfoData,
469c2c66affSColin Finck     OUT LPWSTR *pHardwareIDs OPTIONAL,
470c2c66affSColin Finck     OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL,
471c2c66affSColin Finck     OUT LPWSTR *pCompatibleIDs OPTIONAL,
472c2c66affSColin Finck     OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL)
473c2c66affSColin Finck {
474c2c66affSColin Finck     LPWSTR HardwareIDs = NULL;
475c2c66affSColin Finck     LPWSTR CompatibleIDs = NULL;
476c2c66affSColin Finck     DWORD RequiredSize;
477c2c66affSColin Finck     BOOL Result;
478c2c66affSColin Finck 
479c2c66affSColin Finck     /* Get hardware IDs list */
480c2c66affSColin Finck     Result = FALSE;
481c2c66affSColin Finck     RequiredSize = 512; /* Initial buffer size */
482c2c66affSColin Finck     SetLastError(ERROR_INSUFFICIENT_BUFFER);
483c2c66affSColin Finck     while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
484c2c66affSColin Finck     {
485c2c66affSColin Finck         MyFree(HardwareIDs);
486c2c66affSColin Finck         HardwareIDs = MyMalloc(RequiredSize);
487c2c66affSColin Finck         if (!HardwareIDs)
488c2c66affSColin Finck         {
489c2c66affSColin Finck             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
490c2c66affSColin Finck             goto done;
491c2c66affSColin Finck         }
492c2c66affSColin Finck         Result = SetupDiGetDeviceRegistryPropertyW(
493c2c66affSColin Finck             DeviceInfoSet,
494c2c66affSColin Finck             DeviceInfoData,
495c2c66affSColin Finck             SPDRP_HARDWAREID,
496c2c66affSColin Finck             NULL,
497c2c66affSColin Finck             (PBYTE)HardwareIDs,
498c2c66affSColin Finck             RequiredSize,
499c2c66affSColin Finck             &RequiredSize);
500c2c66affSColin Finck     }
501c2c66affSColin Finck     if (!Result)
502c2c66affSColin Finck     {
503c2c66affSColin Finck         if (GetLastError() == ERROR_FILE_NOT_FOUND)
504c2c66affSColin Finck         {
505c2c66affSColin Finck             /* No hardware ID for this device */
506c2c66affSColin Finck             MyFree(HardwareIDs);
507c2c66affSColin Finck             HardwareIDs = NULL;
508c2c66affSColin Finck             RequiredSize = 0;
509c2c66affSColin Finck         }
510c2c66affSColin Finck         else
511c2c66affSColin Finck             goto done;
512c2c66affSColin Finck     }
513c2c66affSColin Finck     if (pHardwareIDs)
514c2c66affSColin Finck         *pHardwareIDs = HardwareIDs;
515c2c66affSColin Finck     if (pHardwareIDsRequiredSize)
516c2c66affSColin Finck         *pHardwareIDsRequiredSize = RequiredSize;
517c2c66affSColin Finck 
518c2c66affSColin Finck     /* Get compatible IDs list */
519c2c66affSColin Finck     Result = FALSE;
520c2c66affSColin Finck     RequiredSize = 512; /* Initial buffer size */
521c2c66affSColin Finck     SetLastError(ERROR_INSUFFICIENT_BUFFER);
522c2c66affSColin Finck     while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
523c2c66affSColin Finck     {
524c2c66affSColin Finck         MyFree(CompatibleIDs);
525c2c66affSColin Finck         CompatibleIDs = MyMalloc(RequiredSize);
526c2c66affSColin Finck         if (!CompatibleIDs)
527c2c66affSColin Finck         {
528c2c66affSColin Finck             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
529c2c66affSColin Finck             goto done;
530c2c66affSColin Finck         }
531c2c66affSColin Finck         Result = SetupDiGetDeviceRegistryPropertyW(
532c2c66affSColin Finck             DeviceInfoSet,
533c2c66affSColin Finck             DeviceInfoData,
534c2c66affSColin Finck             SPDRP_COMPATIBLEIDS,
535c2c66affSColin Finck             NULL,
536c2c66affSColin Finck             (PBYTE)CompatibleIDs,
537c2c66affSColin Finck             RequiredSize,
538c2c66affSColin Finck             &RequiredSize);
539c2c66affSColin Finck     }
540c2c66affSColin Finck     if (!Result)
541c2c66affSColin Finck     {
542c2c66affSColin Finck         if (GetLastError() == ERROR_FILE_NOT_FOUND)
543c2c66affSColin Finck         {
544c2c66affSColin Finck             /* No compatible ID for this device */
545c2c66affSColin Finck             MyFree(CompatibleIDs);
546c2c66affSColin Finck             CompatibleIDs = NULL;
547c2c66affSColin Finck             RequiredSize = 0;
548c2c66affSColin Finck         }
549c2c66affSColin Finck         else
550c2c66affSColin Finck             goto done;
551c2c66affSColin Finck     }
552c2c66affSColin Finck     if (pCompatibleIDs)
553c2c66affSColin Finck         *pCompatibleIDs = CompatibleIDs;
554c2c66affSColin Finck     if (pCompatibleIDsRequiredSize)
555c2c66affSColin Finck         *pCompatibleIDsRequiredSize = RequiredSize;
556c2c66affSColin Finck 
557c2c66affSColin Finck     Result = TRUE;
558c2c66affSColin Finck 
559c2c66affSColin Finck done:
560c2c66affSColin Finck     if (!Result)
561c2c66affSColin Finck     {
562c2c66affSColin Finck         MyFree(HardwareIDs);
563c2c66affSColin Finck         MyFree(CompatibleIDs);
564c2c66affSColin Finck     }
565c2c66affSColin Finck     return Result;
566c2c66affSColin Finck }
567c2c66affSColin Finck 
568067bb2fcSSerge Gautherie #if _WIN32_WINNT < 0x0600
569c2c66affSColin Finck /* WARNING:
570c2c66affSColin Finck  * This code has been copied from advapi32/reg/reg.c,
571c2c66affSColin Finck  * so this dll can be tested as is on Windows XP
572c2c66affSColin Finck  */
573c2c66affSColin Finck 
574c2c66affSColin Finck #define RRF_RT_REG_NONE         (1 << 0)
575c2c66affSColin Finck #define RRF_RT_REG_SZ           (1 << 1)
576c2c66affSColin Finck #define RRF_RT_REG_EXPAND_SZ    (1 << 2)
577c2c66affSColin Finck #define RRF_RT_REG_BINARY       (1 << 3)
578c2c66affSColin Finck #define RRF_RT_REG_DWORD        (1 << 4)
579c2c66affSColin Finck #define RRF_RT_REG_MULTI_SZ     (1 << 5)
580c2c66affSColin Finck #define RRF_RT_REG_QWORD        (1 << 6)
581c2c66affSColin Finck #define RRF_RT_DWORD            (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD)
582c2c66affSColin Finck #define RRF_RT_QWORD            (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD)
583c2c66affSColin Finck #define RRF_NOEXPAND            (1 << 28)
584c2c66affSColin Finck #define RRF_ZEROONFAILURE       (1 << 29)
585c2c66affSColin Finck 
586c2c66affSColin Finck static VOID
RegpApplyRestrictions(DWORD dwFlags,DWORD dwType,DWORD cbData,PLONG ret)587c2c66affSColin Finck RegpApplyRestrictions( DWORD dwFlags, DWORD dwType, DWORD cbData,
588c2c66affSColin Finck                        PLONG ret )
589c2c66affSColin Finck {
590c2c66affSColin Finck     /* Check if the type is restricted by the passed flags */
591c2c66affSColin Finck     if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
592c2c66affSColin Finck     {
593c2c66affSColin Finck         DWORD dwMask = 0;
594c2c66affSColin Finck 
595c2c66affSColin Finck         switch (dwType)
596c2c66affSColin Finck         {
597c2c66affSColin Finck         case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
598c2c66affSColin Finck         case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
599c2c66affSColin Finck         case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
600c2c66affSColin Finck         case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
601c2c66affSColin Finck         case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
602c2c66affSColin Finck         case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
603c2c66affSColin Finck         case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
604c2c66affSColin Finck         }
605c2c66affSColin Finck 
606c2c66affSColin Finck         if (dwFlags & dwMask)
607c2c66affSColin Finck         {
608c2c66affSColin Finck             /* Type is not restricted, check for size mismatch */
609c2c66affSColin Finck             if (dwType == REG_BINARY)
610c2c66affSColin Finck             {
611c2c66affSColin Finck                 DWORD cbExpect = 0;
612c2c66affSColin Finck 
613c2c66affSColin Finck                 if ((dwFlags & RRF_RT_DWORD) == RRF_RT_DWORD)
614c2c66affSColin Finck                     cbExpect = 4;
615c2c66affSColin Finck                 else if ((dwFlags & RRF_RT_QWORD) == RRF_RT_QWORD)
616c2c66affSColin Finck                     cbExpect = 8;
617c2c66affSColin Finck 
618c2c66affSColin Finck                 if (cbExpect && cbData != cbExpect)
619c2c66affSColin Finck                     *ret = ERROR_DATATYPE_MISMATCH;
620c2c66affSColin Finck             }
621c2c66affSColin Finck         }
622c2c66affSColin Finck         else *ret = ERROR_UNSUPPORTED_TYPE;
623c2c66affSColin Finck     }
624c2c66affSColin Finck }
625c2c66affSColin Finck 
626c2c66affSColin Finck static LONG WINAPI
RegGetValueW(HKEY hKey,LPCWSTR pszSubKey,LPCWSTR pszValue,DWORD dwFlags,LPDWORD pdwType,PVOID pvData,LPDWORD pcbData)627c2c66affSColin Finck RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue,
628c2c66affSColin Finck               DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
629c2c66affSColin Finck               LPDWORD pcbData )
630c2c66affSColin Finck {
631c2c66affSColin Finck     DWORD dwType, cbData = pcbData ? *pcbData : 0;
632c2c66affSColin Finck     PVOID pvBuf = NULL;
633c2c66affSColin Finck     LONG ret;
634c2c66affSColin Finck 
635c2c66affSColin Finck     TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
636c2c66affSColin Finck           hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
637c2c66affSColin Finck           pvData, pcbData, cbData);
638c2c66affSColin Finck 
639c2c66affSColin Finck     if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND))
640c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
641c2c66affSColin Finck 
642c2c66affSColin Finck     if (pszSubKey && pszSubKey[0])
643c2c66affSColin Finck     {
644c2c66affSColin Finck         ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
645c2c66affSColin Finck         if (ret != ERROR_SUCCESS) return ret;
646c2c66affSColin Finck     }
647c2c66affSColin Finck 
648c2c66affSColin Finck     ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
649c2c66affSColin Finck 
650c2c66affSColin Finck     /* If we are going to expand we need to read in the whole the value even
651c2c66affSColin Finck      * if the passed buffer was too small as the expanded string might be
652c2c66affSColin Finck      * smaller than the unexpanded one and could fit into cbData bytes. */
653c2c66affSColin Finck     if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
654c2c66affSColin Finck         (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
655c2c66affSColin Finck     {
656c2c66affSColin Finck         do {
657c2c66affSColin Finck             if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
658c2c66affSColin Finck 
659c2c66affSColin Finck             pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
660c2c66affSColin Finck             if (!pvBuf)
661c2c66affSColin Finck             {
662c2c66affSColin Finck                 ret = ERROR_NOT_ENOUGH_MEMORY;
663c2c66affSColin Finck                 break;
664c2c66affSColin Finck             }
665c2c66affSColin Finck 
666c2c66affSColin Finck             if (ret == ERROR_MORE_DATA)
667c2c66affSColin Finck                 ret = RegQueryValueExW(hKey, pszValue, NULL,
668c2c66affSColin Finck                                        &dwType, pvBuf, &cbData);
669c2c66affSColin Finck             else
670c2c66affSColin Finck             {
671c2c66affSColin Finck                 /* Even if cbData was large enough we have to copy the
672c2c66affSColin Finck                  * string since ExpandEnvironmentStrings can't handle
673c2c66affSColin Finck                  * overlapping buffers. */
674c2c66affSColin Finck                 CopyMemory(pvBuf, pvData, cbData);
675c2c66affSColin Finck             }
676c2c66affSColin Finck 
677c2c66affSColin Finck             /* Both the type or the value itself could have been modified in
678c2c66affSColin Finck              * between so we have to keep retrying until the buffer is large
679c2c66affSColin Finck              * enough or we no longer have to expand the value. */
680c2c66affSColin Finck         } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
681c2c66affSColin Finck 
682c2c66affSColin Finck         if (ret == ERROR_SUCCESS)
683c2c66affSColin Finck         {
684c2c66affSColin Finck             if (dwType == REG_EXPAND_SZ)
685c2c66affSColin Finck             {
686c2c66affSColin Finck                 cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
687c2c66affSColin Finck                                                    pcbData ? (*pcbData)/sizeof(WCHAR) : 0);
688c2c66affSColin Finck                 dwType = REG_SZ;
689c2c66affSColin Finck                 if(pcbData && cbData > ((*pcbData)/sizeof(WCHAR)))
690c2c66affSColin Finck                     ret = ERROR_MORE_DATA;
691c2c66affSColin Finck             }
692c2c66affSColin Finck             else if (pcbData)
693c2c66affSColin Finck                 CopyMemory(pvData, pvBuf, *pcbData);
694c2c66affSColin Finck         }
695c2c66affSColin Finck 
696c2c66affSColin Finck         if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
697c2c66affSColin Finck     }
698c2c66affSColin Finck 
699c2c66affSColin Finck     if (pszSubKey && pszSubKey[0])
700c2c66affSColin Finck         RegCloseKey(hKey);
701c2c66affSColin Finck 
702c2c66affSColin Finck     RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
703c2c66affSColin Finck 
704c2c66affSColin Finck     if (pcbData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
705c2c66affSColin Finck         ZeroMemory(pvData, *pcbData);
706c2c66affSColin Finck 
707c2c66affSColin Finck     if (pdwType) *pdwType = dwType;
708c2c66affSColin Finck     if (pcbData) *pcbData = cbData;
709c2c66affSColin Finck 
710c2c66affSColin Finck     return ret;
711c2c66affSColin Finck }
712c2c66affSColin Finck #endif /* End of code copied from advapi32/reg/reg.c */
713c2c66affSColin Finck 
714c2c66affSColin Finck /***********************************************************************
715c2c66affSColin Finck  *		SetupDiBuildDriverInfoList (SETUPAPI.@)
716c2c66affSColin Finck  */
717c2c66affSColin Finck BOOL WINAPI
SetupDiBuildDriverInfoList(IN HDEVINFO DeviceInfoSet,IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN DWORD DriverType)718c2c66affSColin Finck SetupDiBuildDriverInfoList(
719c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
720c2c66affSColin Finck     IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
721c2c66affSColin Finck     IN DWORD DriverType)
722c2c66affSColin Finck {
723c2c66affSColin Finck     struct DeviceInfoSet *list;
724c2c66affSColin Finck     SP_DEVINSTALL_PARAMS_W InstallParams;
725c2c66affSColin Finck     PVOID Buffer = NULL;
726c2c66affSColin Finck     struct InfFileDetails *currentInfFileDetails = NULL;
727c2c66affSColin Finck     LPWSTR ProviderName = NULL;
728c2c66affSColin Finck     LPWSTR ManufacturerName = NULL;
729c2c66affSColin Finck     WCHAR ManufacturerSection[LINE_LEN + 1];
730c2c66affSColin Finck     LPWSTR HardwareIDs = NULL;
731c2c66affSColin Finck     LPWSTR CompatibleIDs = NULL;
732c2c66affSColin Finck     LPWSTR FullInfFileName = NULL;
733c2c66affSColin Finck     LPWSTR ExcludeFromSelect = NULL;
734c2c66affSColin Finck     FILETIME DriverDate;
735c2c66affSColin Finck     DWORDLONG DriverVersion = 0;
736c2c66affSColin Finck     DWORD RequiredSize;
737c2c66affSColin Finck     BOOL ret = FALSE;
738c2c66affSColin Finck 
739c2c66affSColin Finck     TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
740c2c66affSColin Finck 
741c2c66affSColin Finck     if (!DeviceInfoSet)
742c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
743c2c66affSColin Finck     else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
744c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
745c2c66affSColin Finck     else if (list->HKLM != HKEY_LOCAL_MACHINE)
746c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
747c2c66affSColin Finck     else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
748c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
749c2c66affSColin Finck     else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
750c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
751c2c66affSColin Finck     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
752c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
753c2c66affSColin Finck     else
754c2c66affSColin Finck     {
755c2c66affSColin Finck         PLIST_ENTRY pDriverListHead = &list->DriverListHead;
756c2c66affSColin Finck         BOOL Result;
757c2c66affSColin Finck 
758c2c66affSColin Finck         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
759c2c66affSColin Finck         Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
760c2c66affSColin Finck         if (!Result)
761c2c66affSColin Finck             goto done;
762c2c66affSColin Finck 
763c2c66affSColin Finck         if (DeviceInfoData)
764c2c66affSColin Finck         {
765c2c66affSColin Finck             struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
766c2c66affSColin Finck             if (!(devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS))
767c2c66affSColin Finck                 pDriverListHead = &devInfo->DriverListHead;
768c2c66affSColin Finck         }
769c2c66affSColin Finck 
770c2c66affSColin Finck         if (DriverType == SPDIT_COMPATDRIVER)
771c2c66affSColin Finck         {
772c2c66affSColin Finck             /* Get hardware and compatible IDs lists */
773c2c66affSColin Finck             Result = GetHardwareAndCompatibleIDsLists(
774c2c66affSColin Finck                 DeviceInfoSet,
775c2c66affSColin Finck                 DeviceInfoData,
776c2c66affSColin Finck                 &HardwareIDs,
777c2c66affSColin Finck                 NULL,
778c2c66affSColin Finck                 &CompatibleIDs,
779c2c66affSColin Finck                 NULL);
780c2c66affSColin Finck             if (!Result)
781c2c66affSColin Finck                 goto done;
782c2c66affSColin Finck             if (!HardwareIDs && !CompatibleIDs)
783c2c66affSColin Finck             {
784c2c66affSColin Finck                 SetLastError(ERROR_FILE_NOT_FOUND);
785c2c66affSColin Finck                 goto done;
786c2c66affSColin Finck             }
787c2c66affSColin Finck         }
788c2c66affSColin Finck 
789c2c66affSColin Finck          if (InstallParams.FlagsEx & DI_FLAGSEX_INSTALLEDDRIVER)
790c2c66affSColin Finck         {
791c2c66affSColin Finck             HKEY hDriverKey;
792c2c66affSColin Finck             WCHAR InfFileName[MAX_PATH];
793c2c66affSColin Finck             WCHAR InfFileSection[MAX_PATH];
794c2c66affSColin Finck             ULONG RequiredSize;
795c2c66affSColin Finck             struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
796c2c66affSColin Finck             struct InfFileDetails *infFileDetails = NULL;
797c2c66affSColin Finck             FILETIME DriverDate;
798c2c66affSColin Finck             LONG rc;
799c2c66affSColin Finck             DWORD len;
800c2c66affSColin Finck 
801c2c66affSColin Finck             /* Prepend inf directory name to file name */
802c2c66affSColin Finck             len = sizeof(InfFileName) / sizeof(InfFileName[0]);
803c2c66affSColin Finck             RequiredSize = GetSystemWindowsDirectoryW(InfFileName, len);
804c2c66affSColin Finck             if (RequiredSize == 0 || RequiredSize >= len)
805c2c66affSColin Finck                 goto done;
806c2c66affSColin Finck             if (*InfFileName && InfFileName[strlenW(InfFileName) - 1] != '\\')
807c2c66affSColin Finck                 strcatW(InfFileName, BackSlash);
808c2c66affSColin Finck             strcatW(InfFileName, InfDirectory);
809c2c66affSColin Finck 
810c2c66affSColin Finck             /* Read some information from registry, before creating the driver structure */
81160e16653SEric Kohl             hDriverKey = SETUPDI_OpenDrvKey(((struct DeviceInfoSet *)DeviceInfoSet)->HKLM, devInfo, KEY_QUERY_VALUE);
812c2c66affSColin Finck             if (hDriverKey == INVALID_HANDLE_VALUE)
813c2c66affSColin Finck                 goto done;
814c2c66affSColin Finck             RequiredSize = (len - strlenW(InfFileName)) * sizeof(WCHAR);
815c2c66affSColin Finck             rc = RegGetValueW(
816c2c66affSColin Finck                 hDriverKey,
817c2c66affSColin Finck                 NULL,
818c2c66affSColin Finck                 REGSTR_VAL_INFPATH,
819c2c66affSColin Finck                 RRF_RT_REG_SZ,
820c2c66affSColin Finck                 NULL,
821c2c66affSColin Finck                 &InfFileName[strlenW(InfFileName)],
822c2c66affSColin Finck                 &RequiredSize);
823c2c66affSColin Finck             if (rc != ERROR_SUCCESS)
824c2c66affSColin Finck             {
825c2c66affSColin Finck                 SetLastError(rc);
826c2c66affSColin Finck                 CloseHandle(hDriverKey);
827c2c66affSColin Finck                 goto done;
828c2c66affSColin Finck             }
829c2c66affSColin Finck             RequiredSize = sizeof(InfFileSection);
830c2c66affSColin Finck             rc = RegGetValueW(
831c2c66affSColin Finck                 hDriverKey,
832c2c66affSColin Finck                 NULL,
833c2c66affSColin Finck                 REGSTR_VAL_INFSECTION,
834c2c66affSColin Finck                 RRF_RT_REG_SZ,
835c2c66affSColin Finck                 NULL,
836c2c66affSColin Finck                 InfFileSection,
837c2c66affSColin Finck                 &RequiredSize);
838c2c66affSColin Finck             if (rc != ERROR_SUCCESS)
839c2c66affSColin Finck             {
840c2c66affSColin Finck                 SetLastError(rc);
841c2c66affSColin Finck                 CloseHandle(hDriverKey);
842c2c66affSColin Finck                 goto done;
843c2c66affSColin Finck             }
844c2c66affSColin Finck             TRACE("Current driver in %s/%s\n", debugstr_w(InfFileName), debugstr_w(InfFileSection));
845c2c66affSColin Finck             infFileDetails = CreateInfFileDetails(InfFileName);
846c2c66affSColin Finck             if (!infFileDetails)
847c2c66affSColin Finck             {
848c2c66affSColin Finck                 CloseHandle(hDriverKey);
849c2c66affSColin Finck                 goto done;
850c2c66affSColin Finck             }
851c2c66affSColin Finck             DriverDate.dwLowDateTime = DriverDate.dwHighDateTime = 0; /* FIXME */
852c2c66affSColin Finck             CloseHandle(hDriverKey);
853c2c66affSColin Finck             ret = AddKnownDriverToList(
854c2c66affSColin Finck                 pDriverListHead,
855c2c66affSColin Finck                 SPDIT_COMPATDRIVER,
856c2c66affSColin Finck                 &devInfo->ClassGuid,
857c2c66affSColin Finck                 infFileDetails,
858c2c66affSColin Finck                 InfFileName,
859c2c66affSColin Finck                 InfFileSection, /* Yes, we don't care of section extension */
860c2c66affSColin Finck                 L"DriverDescription", /* FIXME */
861c2c66affSColin Finck                 L"ProviderName", /* FIXME */
862c2c66affSColin Finck                 L"ManufacturerName", /* FIXME */
863c2c66affSColin Finck                 L"MatchingId", /* FIXME */
864c2c66affSColin Finck                 DriverDate,
865c2c66affSColin Finck                 0, /* FIXME: DriverVersion */
866c2c66affSColin Finck                 0);
867c2c66affSColin Finck             if (!ret)
868c2c66affSColin Finck                 DereferenceInfFile(infFileDetails);
869c2c66affSColin Finck             Result = FALSE;
870c2c66affSColin Finck         }
871c2c66affSColin Finck         else if (InstallParams.Flags & DI_ENUMSINGLEINF)
872c2c66affSColin Finck         {
873c2c66affSColin Finck             /* InstallParams.DriverPath contains the name of a .inf file */
874c2c66affSColin Finck             RequiredSize = strlenW(InstallParams.DriverPath) + 2;
875c2c66affSColin Finck             Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
876c2c66affSColin Finck             if (!Buffer)
877c2c66affSColin Finck             {
878c2c66affSColin Finck                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
879c2c66affSColin Finck                 goto done;
880c2c66affSColin Finck             }
881c2c66affSColin Finck             strcpyW(Buffer, InstallParams.DriverPath);
882c2c66affSColin Finck             ((LPWSTR)Buffer)[RequiredSize - 1] = 0;
883c2c66affSColin Finck             Result = TRUE;
884c2c66affSColin Finck         }
885c2c66affSColin Finck         else
886c2c66affSColin Finck         {
887c2c66affSColin Finck             /* Enumerate .inf files */
888c2c66affSColin Finck             Result = FALSE;
889c2c66affSColin Finck             RequiredSize = 32768; /* Initial buffer size */
890c2c66affSColin Finck             SetLastError(ERROR_INSUFFICIENT_BUFFER);
891c2c66affSColin Finck             while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
892c2c66affSColin Finck             {
893c2c66affSColin Finck                 HeapFree(GetProcessHeap(), 0, Buffer);
894c2c66affSColin Finck                 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
895c2c66affSColin Finck                 if (!Buffer)
896c2c66affSColin Finck                 {
897c2c66affSColin Finck                     Result = FALSE;
898c2c66affSColin Finck                     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
899c2c66affSColin Finck                     break;
900c2c66affSColin Finck                 }
901c2c66affSColin Finck                 Result = SetupGetInfFileListW(
902c2c66affSColin Finck                     *InstallParams.DriverPath ? InstallParams.DriverPath : NULL,
903c2c66affSColin Finck                     INF_STYLE_WIN4,
904c2c66affSColin Finck                     Buffer, RequiredSize,
905c2c66affSColin Finck                     &RequiredSize);
906c2c66affSColin Finck             }
907c2c66affSColin Finck             if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
908c2c66affSColin Finck             {
909c2c66affSColin Finck                 /* No .inf file in specified directory. So, we should
910c2c66affSColin Finck                  * success as we created an empty driver info list.
911c2c66affSColin Finck                  */
912c2c66affSColin Finck                 ret = TRUE;
913c2c66affSColin Finck                 goto done;
914c2c66affSColin Finck             }
915c2c66affSColin Finck         }
916c2c66affSColin Finck         if (Result)
917c2c66affSColin Finck         {
918c2c66affSColin Finck             LPCWSTR filename;
919c2c66affSColin Finck             LPWSTR pFullFilename;
920c2c66affSColin Finck 
921c2c66affSColin Finck             if (InstallParams.Flags & DI_ENUMSINGLEINF)
922c2c66affSColin Finck             {
923c2c66affSColin Finck                 /* Only a filename */
924c2c66affSColin Finck                 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
925c2c66affSColin Finck                 if (!FullInfFileName)
926c2c66affSColin Finck                     goto done;
927c2c66affSColin Finck                 pFullFilename = &FullInfFileName[0];
928c2c66affSColin Finck             }
929c2c66affSColin Finck             else if (*InstallParams.DriverPath)
930c2c66affSColin Finck             {
931c2c66affSColin Finck                 /* Directory name specified */
932c2c66affSColin Finck                 DWORD len;
933c2c66affSColin Finck                 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
934c2c66affSColin Finck                 if (len == 0)
935c2c66affSColin Finck                     goto done;
936c2c66affSColin Finck                 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + MAX_PATH) * sizeof(WCHAR));
937c2c66affSColin Finck                 if (!FullInfFileName)
938c2c66affSColin Finck                     goto done;
939c2c66affSColin Finck                 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
940c2c66affSColin Finck                 if (len == 0)
941c2c66affSColin Finck                     goto done;
942c2c66affSColin Finck                 if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\')
943c2c66affSColin Finck                     strcatW(FullInfFileName, BackSlash);
944c2c66affSColin Finck                 pFullFilename = &FullInfFileName[strlenW(FullInfFileName)];
945c2c66affSColin Finck             }
946c2c66affSColin Finck             else
947c2c66affSColin Finck             {
948c2c66affSColin Finck                 /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */
949c2c66affSColin Finck                 DWORD len;
950c2c66affSColin Finck                 len = GetSystemWindowsDirectoryW(NULL, 0);
951c2c66affSColin Finck                 if (len == 0)
952c2c66affSColin Finck                     goto done;
953c2c66affSColin Finck                 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + strlenW(InfDirectory) + MAX_PATH) * sizeof(WCHAR));
954c2c66affSColin Finck                 if (!FullInfFileName)
955c2c66affSColin Finck                     goto done;
956c2c66affSColin Finck                 len = GetSystemWindowsDirectoryW(FullInfFileName, len);
957c2c66affSColin Finck                 if (len == 0)
958c2c66affSColin Finck                     goto done;
959c2c66affSColin Finck                 if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\')
960c2c66affSColin Finck                     strcatW(FullInfFileName, BackSlash);
961c2c66affSColin Finck                 strcatW(FullInfFileName, InfDirectory);
962c2c66affSColin Finck                 pFullFilename = &FullInfFileName[strlenW(FullInfFileName)];
963c2c66affSColin Finck             }
964c2c66affSColin Finck 
965c2c66affSColin Finck             for (filename = (LPCWSTR)Buffer; *filename; filename += strlenW(filename) + 1)
966c2c66affSColin Finck             {
967c2c66affSColin Finck                 INFCONTEXT ContextManufacturer, ContextDevice;
968c2c66affSColin Finck                 GUID ClassGuid;
969c2c66affSColin Finck 
970c2c66affSColin Finck                 strcpyW(pFullFilename, filename);
971c2c66affSColin Finck                 TRACE("Opening file %s\n", debugstr_w(FullInfFileName));
972c2c66affSColin Finck 
973c2c66affSColin Finck                 currentInfFileDetails = CreateInfFileDetails(FullInfFileName);
974c2c66affSColin Finck                 if (!currentInfFileDetails)
975c2c66affSColin Finck                     continue;
976c2c66affSColin Finck 
977c2c66affSColin Finck                 if (!GetVersionInformationFromInfFile(
978c2c66affSColin Finck                     currentInfFileDetails->hInf,
979c2c66affSColin Finck                     &ClassGuid,
980c2c66affSColin Finck                     &ProviderName,
981c2c66affSColin Finck                     &DriverDate,
982c2c66affSColin Finck                     &DriverVersion))
983c2c66affSColin Finck                 {
984c2c66affSColin Finck                     DereferenceInfFile(currentInfFileDetails);
985c2c66affSColin Finck                     currentInfFileDetails = NULL;
986c2c66affSColin Finck                     continue;
987c2c66affSColin Finck                 }
988c2c66affSColin Finck 
989c2c66affSColin Finck                 if (DriverType == SPDIT_CLASSDRIVER)
990c2c66affSColin Finck                 {
991c2c66affSColin Finck                     /* Check if the ClassGuid in this .inf file is corresponding with our needs */
992c2c66affSColin Finck                     if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
993c2c66affSColin Finck                     {
994c2c66affSColin Finck                         goto next;
995c2c66affSColin Finck                     }
996c2c66affSColin Finck                 }
997c2c66affSColin Finck 
998c2c66affSColin Finck                 if (InstallParams.FlagsEx & DI_FLAGSEX_ALLOWEXCLUDEDDRVS)
999c2c66affSColin Finck                 {
1000c2c66affSColin Finck                     /* Read ExcludeFromSelect control flags */
1001c2c66affSColin Finck                     /* FIXME */
1002c2c66affSColin Finck                 }
1003c2c66affSColin Finck                 else
1004c2c66affSColin Finck                     FIXME("ExcludeFromSelect list ignored\n");
1005c2c66affSColin Finck 
1006c2c66affSColin Finck                 /* Get the manufacturers list */
1007c2c66affSColin Finck                 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, INF_MANUFACTURER, NULL, &ContextManufacturer);
1008c2c66affSColin Finck                 while (Result)
1009c2c66affSColin Finck                 {
1010c2c66affSColin Finck                     Result = SetupGetStringFieldW(
1011c2c66affSColin Finck                         &ContextManufacturer,
1012c2c66affSColin Finck                         0, /* Field index */
1013c2c66affSColin Finck                         NULL, 0,
1014c2c66affSColin Finck                         &RequiredSize);
1015c2c66affSColin Finck                     if (Result)
1016c2c66affSColin Finck                     {
1017c2c66affSColin Finck                         /* We got the needed size for the buffer */
1018c2c66affSColin Finck                         ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
1019c2c66affSColin Finck                         if (!ManufacturerName)
1020c2c66affSColin Finck                         {
1021c2c66affSColin Finck                             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1022c2c66affSColin Finck                             goto done;
1023c2c66affSColin Finck                         }
1024c2c66affSColin Finck                         Result = SetupGetStringFieldW(
1025c2c66affSColin Finck                             &ContextManufacturer,
1026c2c66affSColin Finck                             0, /* Field index */
1027c2c66affSColin Finck                             ManufacturerName, RequiredSize,
1028c2c66affSColin Finck                             &RequiredSize);
1029c2c66affSColin Finck                     }
1030c2c66affSColin Finck                     /* Get manufacturer section name */
1031c2c66affSColin Finck                     Result = SetupGetStringFieldW(
1032c2c66affSColin Finck                         &ContextManufacturer,
1033c2c66affSColin Finck                         1, /* Field index */
1034c2c66affSColin Finck                         ManufacturerSection, LINE_LEN,
1035c2c66affSColin Finck                         &RequiredSize);
1036c2c66affSColin Finck                     if (Result)
1037c2c66affSColin Finck                     {
1038c2c66affSColin Finck                         ManufacturerSection[RequiredSize] = 0; /* Final NULL char */
1039c2c66affSColin Finck                         /* Add (possible) extension to manufacturer section name */
1040c2c66affSColin Finck                         Result = SetupDiGetActualSectionToInstallW(
1041c2c66affSColin Finck                             currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
1042c2c66affSColin Finck                         if (Result)
1043c2c66affSColin Finck                         {
1044c2c66affSColin Finck                             TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection));
1045c2c66affSColin Finck                             Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
1046c2c66affSColin Finck                         }
1047c2c66affSColin Finck                     }
1048c2c66affSColin Finck                     while (Result)
1049c2c66affSColin Finck                     {
1050c2c66affSColin Finck                         if (DriverType == SPDIT_CLASSDRIVER)
1051c2c66affSColin Finck                         {
1052c2c66affSColin Finck                             /* FIXME: Check ExcludeFromSelect list */
1053c2c66affSColin Finck                             if (!AddDriverToList(
1054c2c66affSColin Finck                                 pDriverListHead,
1055c2c66affSColin Finck                                 DriverType,
1056c2c66affSColin Finck                                 &ClassGuid,
1057c2c66affSColin Finck                                 ContextDevice,
1058c2c66affSColin Finck                                 currentInfFileDetails,
1059c2c66affSColin Finck                                 FullInfFileName,
1060c2c66affSColin Finck                                 ProviderName,
1061c2c66affSColin Finck                                 ManufacturerName,
1062c2c66affSColin Finck                                 NULL,
1063c2c66affSColin Finck                                 DriverDate, DriverVersion,
1064c2c66affSColin Finck                                 0))
1065c2c66affSColin Finck                             {
1066c2c66affSColin Finck                                 break;
1067c2c66affSColin Finck                             }
1068c2c66affSColin Finck                         }
1069c2c66affSColin Finck                         else /* DriverType = SPDIT_COMPATDRIVER */
1070c2c66affSColin Finck                         {
1071c2c66affSColin Finck                             /* 1. Get all fields */
1072c2c66affSColin Finck                             DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
1073c2c66affSColin Finck                             DWORD DriverRank;
1074c2c66affSColin Finck                             DWORD i;
1075c2c66affSColin Finck                             LPCWSTR currentId;
1076c2c66affSColin Finck                             BOOL DriverAlreadyAdded;
1077c2c66affSColin Finck 
1078c2c66affSColin Finck                             for (i = 2; i <= FieldCount; i++)
1079c2c66affSColin Finck                             {
1080c2c66affSColin Finck                                 LPWSTR DeviceId = NULL;
1081c2c66affSColin Finck                                 Result = FALSE;
1082c2c66affSColin Finck                                 RequiredSize = 128; /* Initial buffer size */
1083c2c66affSColin Finck                                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1084c2c66affSColin Finck                                 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1085c2c66affSColin Finck                                 {
1086c2c66affSColin Finck                                     HeapFree(GetProcessHeap(), 0, DeviceId);
1087c2c66affSColin Finck                                     DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
1088c2c66affSColin Finck                                     if (!DeviceId)
1089c2c66affSColin Finck                                     {
1090c2c66affSColin Finck                                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1091c2c66affSColin Finck                                         goto done;
1092c2c66affSColin Finck                                     }
1093c2c66affSColin Finck                                     Result = SetupGetStringFieldW(
1094c2c66affSColin Finck                                         &ContextDevice,
1095c2c66affSColin Finck                                         i,
1096c2c66affSColin Finck                                         DeviceId, RequiredSize,
1097c2c66affSColin Finck                                         &RequiredSize);
1098c2c66affSColin Finck                                 }
1099c2c66affSColin Finck                                 if (!Result)
1100c2c66affSColin Finck                                 {
1101c2c66affSColin Finck                                     HeapFree(GetProcessHeap(), 0, DeviceId);
1102c2c66affSColin Finck                                     goto done;
1103c2c66affSColin Finck                                 }
1104c2c66affSColin Finck                                 /* FIXME: Check ExcludeFromSelect list */
1105c2c66affSColin Finck                                 DriverAlreadyAdded = FALSE;
1106c2c66affSColin Finck                                 if (HardwareIDs)
1107c2c66affSColin Finck                                 {
1108c2c66affSColin Finck                                     for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++)
1109c2c66affSColin Finck                                     {
1110c2c66affSColin Finck                                         if (strcmpiW(DeviceId, currentId) == 0)
1111c2c66affSColin Finck                                         {
1112c2c66affSColin Finck                                             AddDriverToList(
1113c2c66affSColin Finck                                                 pDriverListHead,
1114c2c66affSColin Finck                                                 DriverType,
1115c2c66affSColin Finck                                                 &ClassGuid,
1116c2c66affSColin Finck                                                 ContextDevice,
1117c2c66affSColin Finck                                                 currentInfFileDetails,
1118c2c66affSColin Finck                                                 FullInfFileName,
1119c2c66affSColin Finck                                                 ProviderName,
1120c2c66affSColin Finck                                                 ManufacturerName,
1121c2c66affSColin Finck                                                 currentId,
1122c2c66affSColin Finck                                                 DriverDate, DriverVersion,
1123c2c66affSColin Finck                                                 DriverRank  + (i == 2 ? 0 : 0x1000 + i - 3));
1124c2c66affSColin Finck                                             DriverAlreadyAdded = TRUE;
1125c2c66affSColin Finck                                         }
1126c2c66affSColin Finck                                     }
1127c2c66affSColin Finck                                 }
1128c2c66affSColin Finck                                 if (CompatibleIDs)
1129c2c66affSColin Finck                                 {
1130c2c66affSColin Finck                                     for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++)
1131c2c66affSColin Finck                                     {
1132c2c66affSColin Finck                                         if (strcmpiW(DeviceId, currentId) == 0)
1133c2c66affSColin Finck                                         {
1134c2c66affSColin Finck                                             AddDriverToList(
1135c2c66affSColin Finck                                                 pDriverListHead,
1136c2c66affSColin Finck                                                 DriverType,
1137c2c66affSColin Finck                                                 &ClassGuid,
1138c2c66affSColin Finck                                                 ContextDevice,
1139c2c66affSColin Finck                                                 currentInfFileDetails,
1140c2c66affSColin Finck                                                 FullInfFileName,
1141c2c66affSColin Finck                                                 ProviderName,
1142c2c66affSColin Finck                                                 ManufacturerName,
1143c2c66affSColin Finck                                                 currentId,
1144c2c66affSColin Finck                                                 DriverDate, DriverVersion,
1145c2c66affSColin Finck                                                 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
1146c2c66affSColin Finck                                             DriverAlreadyAdded = TRUE;
1147c2c66affSColin Finck                                         }
1148c2c66affSColin Finck                                     }
1149c2c66affSColin Finck                                 }
1150c2c66affSColin Finck                                 HeapFree(GetProcessHeap(), 0, DeviceId);
1151c2c66affSColin Finck                             }
1152c2c66affSColin Finck                         }
1153c2c66affSColin Finck                         Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
1154c2c66affSColin Finck                     }
1155c2c66affSColin Finck 
1156c2c66affSColin Finck                     HeapFree(GetProcessHeap(), 0, ManufacturerName);
1157c2c66affSColin Finck                     ManufacturerName = NULL;
1158c2c66affSColin Finck                     Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
1159c2c66affSColin Finck                 }
1160c2c66affSColin Finck 
1161c2c66affSColin Finck                 ret = TRUE;
1162c2c66affSColin Finck next:
1163c2c66affSColin Finck                 HeapFree(GetProcessHeap(), 0, ProviderName);
1164c2c66affSColin Finck                 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect);
1165c2c66affSColin Finck                 ProviderName = ExcludeFromSelect = NULL;
1166c2c66affSColin Finck 
1167c2c66affSColin Finck                 DereferenceInfFile(currentInfFileDetails);
1168c2c66affSColin Finck                 currentInfFileDetails = NULL;
1169c2c66affSColin Finck             }
1170c2c66affSColin Finck             ret = TRUE;
1171c2c66affSColin Finck         }
1172c2c66affSColin Finck     }
1173c2c66affSColin Finck 
1174c2c66affSColin Finck done:
1175c2c66affSColin Finck     if (ret)
1176c2c66affSColin Finck     {
1177c2c66affSColin Finck         if (DeviceInfoData)
1178c2c66affSColin Finck         {
1179c2c66affSColin Finck             InstallParams.Flags |= DI_DIDCOMPAT;
1180c2c66affSColin Finck             InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
1181c2c66affSColin Finck         }
1182c2c66affSColin Finck         else
1183c2c66affSColin Finck         {
1184c2c66affSColin Finck             InstallParams.Flags |= DI_DIDCLASS;
1185c2c66affSColin Finck             InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST;
1186c2c66affSColin Finck         }
1187c2c66affSColin Finck         ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
1188c2c66affSColin Finck     }
1189c2c66affSColin Finck 
1190c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, ProviderName);
1191c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, ManufacturerName);
1192c2c66affSColin Finck     MyFree(HardwareIDs);
1193c2c66affSColin Finck     MyFree(CompatibleIDs);
1194c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, FullInfFileName);
1195c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, ExcludeFromSelect);
1196c2c66affSColin Finck     if (currentInfFileDetails)
1197c2c66affSColin Finck         DereferenceInfFile(currentInfFileDetails);
1198c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, Buffer);
1199c2c66affSColin Finck 
1200c2c66affSColin Finck     TRACE("Returning %d\n", ret);
1201c2c66affSColin Finck     return ret;
1202c2c66affSColin Finck }
1203c2c66affSColin Finck 
1204c2c66affSColin Finck /***********************************************************************
1205c2c66affSColin Finck  *		SetupDiDestroyDriverInfoList (SETUPAPI.@)
1206c2c66affSColin Finck  */
1207c2c66affSColin Finck BOOL WINAPI
SetupDiDestroyDriverInfoList(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN DWORD DriverType)1208c2c66affSColin Finck SetupDiDestroyDriverInfoList(
1209c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
1210c2c66affSColin Finck     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1211c2c66affSColin Finck     IN DWORD DriverType)
1212c2c66affSColin Finck {
1213c2c66affSColin Finck     struct DeviceInfoSet *list;
1214c2c66affSColin Finck     BOOL ret = FALSE;
1215c2c66affSColin Finck 
1216c2c66affSColin Finck     TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
1217c2c66affSColin Finck 
1218c2c66affSColin Finck     if (!DeviceInfoSet)
1219c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1220c2c66affSColin Finck     else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1221c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1222c2c66affSColin Finck     else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
1223c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1224c2c66affSColin Finck     else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
1225c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1226c2c66affSColin Finck     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1227c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1228c2c66affSColin Finck     else
1229c2c66affSColin Finck     {
1230c2c66affSColin Finck         PLIST_ENTRY ListEntry;
1231c2c66affSColin Finck         struct DriverInfoElement *driverInfo;
1232c2c66affSColin Finck         SP_DEVINSTALL_PARAMS_W InstallParams;
1233c2c66affSColin Finck 
1234c2c66affSColin Finck         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1235c2c66affSColin Finck         if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
1236c2c66affSColin Finck             goto done;
1237c2c66affSColin Finck 
1238c2c66affSColin Finck         if (!DeviceInfoData)
1239c2c66affSColin Finck             /* Fall back to destroying class driver list */
1240c2c66affSColin Finck             DriverType = SPDIT_CLASSDRIVER;
1241c2c66affSColin Finck 
1242c2c66affSColin Finck         if (DriverType == SPDIT_CLASSDRIVER)
1243c2c66affSColin Finck         {
1244c2c66affSColin Finck             while (!IsListEmpty(&list->DriverListHead))
1245c2c66affSColin Finck             {
1246c2c66affSColin Finck                  ListEntry = RemoveHeadList(&list->DriverListHead);
1247c2c66affSColin Finck                  driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
1248c2c66affSColin Finck                  DestroyDriverInfoElement(driverInfo);
1249c2c66affSColin Finck             }
1250*61e35141STimo Kreuzer             InstallParams.ClassInstallReserved = 0;
1251c2c66affSColin Finck             InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
1252c2c66affSColin Finck             InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST;
1253c2c66affSColin Finck             ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams);
1254c2c66affSColin Finck         }
1255c2c66affSColin Finck         else
1256c2c66affSColin Finck         {
1257c2c66affSColin Finck             SP_DEVINSTALL_PARAMS_W InstallParamsSet;
1258c2c66affSColin Finck             struct DeviceInfo *deviceInfo;
1259c2c66affSColin Finck 
1260c2c66affSColin Finck             InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1261c2c66affSColin Finck             if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet))
1262c2c66affSColin Finck                 goto done;
1263c2c66affSColin Finck             deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1264c2c66affSColin Finck             while (!IsListEmpty(&deviceInfo->DriverListHead))
1265c2c66affSColin Finck             {
1266c2c66affSColin Finck                  ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
1267c2c66affSColin Finck                  driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
1268*61e35141STimo Kreuzer                  if ((PVOID)InstallParamsSet.ClassInstallReserved == driverInfo)
1269c2c66affSColin Finck                  {
1270*61e35141STimo Kreuzer                      InstallParamsSet.ClassInstallReserved = 0;
1271c2c66affSColin Finck                      SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet);
1272c2c66affSColin Finck                  }
1273c2c66affSColin Finck                  DestroyDriverInfoElement(driverInfo);
1274c2c66affSColin Finck             }
1275*61e35141STimo Kreuzer             InstallParams.ClassInstallReserved = 0;
1276c2c66affSColin Finck             InstallParams.Flags &= ~DI_DIDCOMPAT;
1277c2c66affSColin Finck             InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO;
1278c2c66affSColin Finck             ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
1279c2c66affSColin Finck         }
1280c2c66affSColin Finck     }
1281c2c66affSColin Finck 
1282c2c66affSColin Finck done:
1283c2c66affSColin Finck     TRACE("Returning %d\n", ret);
1284c2c66affSColin Finck     return ret;
1285c2c66affSColin Finck }
1286c2c66affSColin Finck 
1287c2c66affSColin Finck /***********************************************************************
1288c2c66affSColin Finck  *		SetupDiEnumDriverInfoA (SETUPAPI.@)
1289c2c66affSColin Finck  */
1290c2c66affSColin Finck BOOL WINAPI
SetupDiEnumDriverInfoA(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN DWORD DriverType,IN DWORD MemberIndex,OUT PSP_DRVINFO_DATA_A DriverInfoData)1291c2c66affSColin Finck SetupDiEnumDriverInfoA(
1292c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
1293c2c66affSColin Finck     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1294c2c66affSColin Finck     IN DWORD DriverType,
1295c2c66affSColin Finck     IN DWORD MemberIndex,
1296c2c66affSColin Finck     OUT PSP_DRVINFO_DATA_A DriverInfoData)
1297c2c66affSColin Finck {
1298c2c66affSColin Finck     SP_DRVINFO_DATA_V2_W driverInfoData2W;
1299c2c66affSColin Finck     BOOL ret = FALSE;
1300c2c66affSColin Finck 
1301c2c66affSColin Finck     TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
1302c2c66affSColin Finck         DriverType, MemberIndex, DriverInfoData);
1303c2c66affSColin Finck 
1304c2c66affSColin Finck     if (DriverInfoData == NULL)
1305c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1306c2c66affSColin Finck     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
1307c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1308c2c66affSColin Finck     else
1309c2c66affSColin Finck     {
1310c2c66affSColin Finck         driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
1311c2c66affSColin Finck         ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
1312c2c66affSColin Finck             DriverType, MemberIndex, &driverInfoData2W);
1313c2c66affSColin Finck 
1314c2c66affSColin Finck         if (ret)
1315c2c66affSColin Finck         {
1316c2c66affSColin Finck             /* Do W->A conversion */
1317c2c66affSColin Finck             DriverInfoData->DriverType = driverInfoData2W.DriverType;
1318c2c66affSColin Finck             DriverInfoData->Reserved = driverInfoData2W.Reserved;
1319c2c66affSColin Finck             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
1320c2c66affSColin Finck                 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
1321c2c66affSColin Finck             {
1322c2c66affSColin Finck                 DriverInfoData->Description[0] = '\0';
1323c2c66affSColin Finck                 ret = FALSE;
1324c2c66affSColin Finck             }
1325c2c66affSColin Finck             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
1326c2c66affSColin Finck                 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
1327c2c66affSColin Finck             {
1328c2c66affSColin Finck                 DriverInfoData->MfgName[0] = '\0';
1329c2c66affSColin Finck                 ret = FALSE;
1330c2c66affSColin Finck             }
1331c2c66affSColin Finck             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
1332c2c66affSColin Finck                 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
1333c2c66affSColin Finck             {
1334c2c66affSColin Finck                 DriverInfoData->ProviderName[0] = '\0';
1335c2c66affSColin Finck                 ret = FALSE;
1336c2c66affSColin Finck             }
1337c2c66affSColin Finck             if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
1338c2c66affSColin Finck             {
1339c2c66affSColin Finck                 /* Copy more fields */
1340c2c66affSColin Finck                 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
1341c2c66affSColin Finck                 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
1342c2c66affSColin Finck             }
1343c2c66affSColin Finck         }
1344c2c66affSColin Finck     }
1345c2c66affSColin Finck 
1346c2c66affSColin Finck     TRACE("Returning %d\n", ret);
1347c2c66affSColin Finck     return ret;
1348c2c66affSColin Finck }
1349c2c66affSColin Finck 
1350c2c66affSColin Finck 
1351c2c66affSColin Finck /***********************************************************************
1352c2c66affSColin Finck  *		SetupDiEnumDriverInfoW (SETUPAPI.@)
1353c2c66affSColin Finck  */
1354c2c66affSColin Finck BOOL WINAPI
SetupDiEnumDriverInfoW(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN DWORD DriverType,IN DWORD MemberIndex,OUT PSP_DRVINFO_DATA_W DriverInfoData)1355c2c66affSColin Finck SetupDiEnumDriverInfoW(
1356c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
1357c2c66affSColin Finck     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1358c2c66affSColin Finck     IN DWORD DriverType,
1359c2c66affSColin Finck     IN DWORD MemberIndex,
1360c2c66affSColin Finck     OUT PSP_DRVINFO_DATA_W DriverInfoData)
1361c2c66affSColin Finck {
1362c2c66affSColin Finck     PLIST_ENTRY ListHead;
1363c2c66affSColin Finck     BOOL ret = FALSE;
1364c2c66affSColin Finck 
1365c2c66affSColin Finck     TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
1366c2c66affSColin Finck         DriverType, MemberIndex, DriverInfoData);
1367c2c66affSColin Finck 
1368c2c66affSColin Finck     if (!DeviceInfoSet || !DriverInfoData)
1369c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1370c2c66affSColin Finck     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1371c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1372c2c66affSColin Finck     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1373c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1374c2c66affSColin Finck     else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
1375c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1376c2c66affSColin Finck     else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
1377c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1378c2c66affSColin Finck     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
1379c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1380c2c66affSColin Finck     else
1381c2c66affSColin Finck     {
1382c2c66affSColin Finck         struct DeviceInfo *devInfo = NULL;
1383c2c66affSColin Finck         PLIST_ENTRY ItemList;
1384c2c66affSColin Finck         if (DeviceInfoData)
1385c2c66affSColin Finck             devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1386c2c66affSColin Finck         if (!devInfo || (devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS))
1387c2c66affSColin Finck         {
1388c2c66affSColin Finck             ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
1389c2c66affSColin Finck         }
1390c2c66affSColin Finck         else
1391c2c66affSColin Finck         {
1392c2c66affSColin Finck             ListHead = &devInfo->DriverListHead;
1393c2c66affSColin Finck         }
1394c2c66affSColin Finck 
1395c2c66affSColin Finck         ItemList = ListHead->Flink;
1396c2c66affSColin Finck         while (ItemList != ListHead && MemberIndex-- > 0)
1397c2c66affSColin Finck             ItemList = ItemList->Flink;
1398c2c66affSColin Finck         if (ItemList == ListHead)
1399c2c66affSColin Finck             SetLastError(ERROR_NO_MORE_ITEMS);
1400c2c66affSColin Finck         else
1401c2c66affSColin Finck         {
1402c2c66affSColin Finck             struct DriverInfoElement *DrvInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
1403c2c66affSColin Finck 
1404c2c66affSColin Finck             memcpy(
1405c2c66affSColin Finck                 &DriverInfoData->DriverType,
1406c2c66affSColin Finck                 &DrvInfo->Info.DriverType,
1407c2c66affSColin Finck                 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
1408c2c66affSColin Finck             ret = TRUE;
1409c2c66affSColin Finck         }
1410c2c66affSColin Finck     }
1411c2c66affSColin Finck 
1412c2c66affSColin Finck     TRACE("Returning %d\n", ret);
1413c2c66affSColin Finck     return ret;
1414c2c66affSColin Finck }
1415c2c66affSColin Finck 
1416c2c66affSColin Finck /***********************************************************************
1417c2c66affSColin Finck  *		SetupDiGetSelectedDriverA (SETUPAPI.@)
1418c2c66affSColin Finck  */
1419c2c66affSColin Finck BOOL WINAPI
SetupDiGetSelectedDriverA(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,OUT PSP_DRVINFO_DATA_A DriverInfoData)1420c2c66affSColin Finck SetupDiGetSelectedDriverA(
1421c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
1422c2c66affSColin Finck     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1423c2c66affSColin Finck     OUT PSP_DRVINFO_DATA_A DriverInfoData)
1424c2c66affSColin Finck {
1425c2c66affSColin Finck     SP_DRVINFO_DATA_V2_W driverInfoData2W;
1426c2c66affSColin Finck     BOOL ret = FALSE;
1427c2c66affSColin Finck 
1428c2c66affSColin Finck     if (DriverInfoData == NULL)
1429c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1430c2c66affSColin Finck     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
1431c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1432c2c66affSColin Finck     else
1433c2c66affSColin Finck     {
1434c2c66affSColin Finck         driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
1435c2c66affSColin Finck 
1436c2c66affSColin Finck         ret = SetupDiGetSelectedDriverW(DeviceInfoSet,
1437c2c66affSColin Finck                                         DeviceInfoData,
1438c2c66affSColin Finck                                         &driverInfoData2W);
1439c2c66affSColin Finck 
1440c2c66affSColin Finck         if (ret)
1441c2c66affSColin Finck         {
1442c2c66affSColin Finck             /* Do W->A conversion */
1443c2c66affSColin Finck             DriverInfoData->DriverType = driverInfoData2W.DriverType;
1444c2c66affSColin Finck             DriverInfoData->Reserved = driverInfoData2W.Reserved;
1445c2c66affSColin Finck             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
1446c2c66affSColin Finck                 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
1447c2c66affSColin Finck             {
1448c2c66affSColin Finck                 DriverInfoData->Description[0] = '\0';
1449c2c66affSColin Finck                 ret = FALSE;
1450c2c66affSColin Finck             }
1451c2c66affSColin Finck             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
1452c2c66affSColin Finck                 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
1453c2c66affSColin Finck             {
1454c2c66affSColin Finck                 DriverInfoData->MfgName[0] = '\0';
1455c2c66affSColin Finck                 ret = FALSE;
1456c2c66affSColin Finck             }
1457c2c66affSColin Finck             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
1458c2c66affSColin Finck                 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
1459c2c66affSColin Finck             {
1460c2c66affSColin Finck                 DriverInfoData->ProviderName[0] = '\0';
1461c2c66affSColin Finck                 ret = FALSE;
1462c2c66affSColin Finck             }
1463c2c66affSColin Finck             if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
1464c2c66affSColin Finck             {
1465c2c66affSColin Finck                 /* Copy more fields */
1466c2c66affSColin Finck                 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
1467c2c66affSColin Finck                 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
1468c2c66affSColin Finck             }
1469c2c66affSColin Finck         }
1470c2c66affSColin Finck     }
1471c2c66affSColin Finck 
1472c2c66affSColin Finck     return ret;
1473c2c66affSColin Finck }
1474c2c66affSColin Finck 
1475c2c66affSColin Finck /***********************************************************************
1476c2c66affSColin Finck  *		SetupDiGetSelectedDriverW (SETUPAPI.@)
1477c2c66affSColin Finck  */
1478c2c66affSColin Finck BOOL WINAPI
SetupDiGetSelectedDriverW(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,OUT PSP_DRVINFO_DATA_W DriverInfoData)1479c2c66affSColin Finck SetupDiGetSelectedDriverW(
1480c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
1481c2c66affSColin Finck     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1482c2c66affSColin Finck     OUT PSP_DRVINFO_DATA_W DriverInfoData)
1483c2c66affSColin Finck {
1484c2c66affSColin Finck     BOOL ret = FALSE;
1485c2c66affSColin Finck 
1486c2c66affSColin Finck     TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
1487c2c66affSColin Finck 
1488c2c66affSColin Finck     if (!DeviceInfoSet || !DriverInfoData)
1489c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1490c2c66affSColin Finck     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1491c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1492c2c66affSColin Finck     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1493c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1494c2c66affSColin Finck     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1495c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1496c2c66affSColin Finck     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
1497c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1498c2c66affSColin Finck     else
1499c2c66affSColin Finck     {
1500c2c66affSColin Finck         SP_DEVINSTALL_PARAMS InstallParams;
1501c2c66affSColin Finck 
1502c2c66affSColin Finck         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1503c2c66affSColin Finck         if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
1504c2c66affSColin Finck         {
1505c2c66affSColin Finck             struct DriverInfoElement *driverInfo;
1506*61e35141STimo Kreuzer             driverInfo = (struct DriverInfoElement *)InstallParams.ClassInstallReserved;
1507c2c66affSColin Finck             if (driverInfo == NULL)
1508c2c66affSColin Finck                 SetLastError(ERROR_NO_DRIVER_SELECTED);
1509c2c66affSColin Finck             else
1510c2c66affSColin Finck             {
1511c2c66affSColin Finck                 memcpy(
1512c2c66affSColin Finck                     &DriverInfoData->DriverType,
1513c2c66affSColin Finck                     &driverInfo->Info.DriverType,
1514c2c66affSColin Finck                     DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
1515c2c66affSColin Finck                 ret = TRUE;
1516c2c66affSColin Finck             }
1517c2c66affSColin Finck         }
1518c2c66affSColin Finck     }
1519c2c66affSColin Finck 
1520c2c66affSColin Finck     TRACE("Returning %d\n", ret);
1521c2c66affSColin Finck     return ret;
1522c2c66affSColin Finck }
1523c2c66affSColin Finck 
1524c2c66affSColin Finck /***********************************************************************
1525c2c66affSColin Finck  *		SetupDiSetSelectedDriverA (SETUPAPI.@)
1526c2c66affSColin Finck  */
1527c2c66affSColin Finck BOOL WINAPI
SetupDiSetSelectedDriverA(IN HDEVINFO DeviceInfoSet,IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)1528c2c66affSColin Finck SetupDiSetSelectedDriverA(
1529c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
1530c2c66affSColin Finck     IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1531c2c66affSColin Finck     IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
1532c2c66affSColin Finck {
1533c2c66affSColin Finck     SP_DRVINFO_DATA_V1_W DriverInfoDataW;
1534c2c66affSColin Finck     PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
1535c2c66affSColin Finck     BOOL ret = FALSE;
1536c2c66affSColin Finck 
1537c2c66affSColin Finck     if (DriverInfoData != NULL)
1538c2c66affSColin Finck     {
1539c2c66affSColin Finck         if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
1540c2c66affSColin Finck             DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A))
1541c2c66affSColin Finck         {
1542c2c66affSColin Finck             SetLastError(ERROR_INVALID_PARAMETER);
1543c2c66affSColin Finck             return FALSE;
1544c2c66affSColin Finck         }
1545c2c66affSColin Finck 
1546c2c66affSColin Finck         DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
1547c2c66affSColin Finck         DriverInfoDataW.Reserved = DriverInfoData->Reserved;
1548c2c66affSColin Finck 
1549c2c66affSColin Finck         if (DriverInfoDataW.Reserved == 0)
1550c2c66affSColin Finck         {
1551c2c66affSColin Finck             DriverInfoDataW.DriverType = DriverInfoData->DriverType;
1552c2c66affSColin Finck 
1553c2c66affSColin Finck             /* convert the strings to unicode */
1554c2c66affSColin Finck             if (!MultiByteToWideChar(CP_ACP,
1555c2c66affSColin Finck                                      0,
1556c2c66affSColin Finck                                      DriverInfoData->Description,
1557c2c66affSColin Finck                                      LINE_LEN,
1558c2c66affSColin Finck                                      DriverInfoDataW.Description,
1559c2c66affSColin Finck                                      LINE_LEN) ||
1560c2c66affSColin Finck                 !MultiByteToWideChar(CP_ACP,
1561c2c66affSColin Finck                                      0,
1562c2c66affSColin Finck                                      DriverInfoData->ProviderName,
1563c2c66affSColin Finck                                      LINE_LEN,
1564c2c66affSColin Finck                                      DriverInfoDataW.ProviderName,
1565c2c66affSColin Finck                                      LINE_LEN))
1566c2c66affSColin Finck             {
1567c2c66affSColin Finck                 return FALSE;
1568c2c66affSColin Finck             }
1569c2c66affSColin Finck         }
1570c2c66affSColin Finck 
1571c2c66affSColin Finck         pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
1572c2c66affSColin Finck     }
1573c2c66affSColin Finck 
1574c2c66affSColin Finck     ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
1575c2c66affSColin Finck                                     DeviceInfoData,
1576c2c66affSColin Finck                                     pDriverInfoDataW);
1577c2c66affSColin Finck 
1578c2c66affSColin Finck     if (ret && pDriverInfoDataW != NULL)
1579c2c66affSColin Finck     {
1580c2c66affSColin Finck         DriverInfoData->Reserved = DriverInfoDataW.Reserved;
1581c2c66affSColin Finck     }
1582c2c66affSColin Finck 
1583c2c66affSColin Finck     return ret;
1584c2c66affSColin Finck }
1585c2c66affSColin Finck 
1586c2c66affSColin Finck /***********************************************************************
1587c2c66affSColin Finck  *		SetupDiSetSelectedDriverW (SETUPAPI.@)
1588c2c66affSColin Finck  */
1589c2c66affSColin Finck BOOL WINAPI
SetupDiSetSelectedDriverW(IN HDEVINFO DeviceInfoSet,IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)1590c2c66affSColin Finck SetupDiSetSelectedDriverW(
1591c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
1592c2c66affSColin Finck     IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1593c2c66affSColin Finck     IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
1594c2c66affSColin Finck {
1595c2c66affSColin Finck     BOOL ret = FALSE;
1596c2c66affSColin Finck 
1597c2c66affSColin Finck     TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
1598c2c66affSColin Finck 
1599c2c66affSColin Finck     if (!DeviceInfoSet)
1600c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1601c2c66affSColin Finck     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1602c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1603c2c66affSColin Finck     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1604c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1605c2c66affSColin Finck     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1606c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1607c2c66affSColin Finck     else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
1608c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1609c2c66affSColin Finck     else
1610c2c66affSColin Finck     {
1611c2c66affSColin Finck         struct DriverInfoElement **pDriverInfo;
1612c2c66affSColin Finck         PLIST_ENTRY ListHead, ItemList;
1613c2c66affSColin Finck 
1614c2c66affSColin Finck         if (DeviceInfoData)
1615c2c66affSColin Finck         {
1616*61e35141STimo Kreuzer             pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams.ClassInstallReserved;
1617c2c66affSColin Finck             ListHead = &((struct DeviceInfo *)DeviceInfoData->Reserved)->DriverListHead;
1618c2c66affSColin Finck         }
1619c2c66affSColin Finck         else
1620c2c66affSColin Finck         {
1621*61e35141STimo Kreuzer             pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.ClassInstallReserved;
1622c2c66affSColin Finck             ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
1623c2c66affSColin Finck         }
1624c2c66affSColin Finck 
1625c2c66affSColin Finck         if (!DriverInfoData)
1626c2c66affSColin Finck         {
1627c2c66affSColin Finck             *pDriverInfo = NULL;
1628c2c66affSColin Finck             ret = TRUE;
1629c2c66affSColin Finck         }
1630c2c66affSColin Finck         else
1631c2c66affSColin Finck         {
1632c2c66affSColin Finck             /* Search selected driver in list */
1633c2c66affSColin Finck             ItemList = ListHead->Flink;
1634c2c66affSColin Finck             while (ItemList != ListHead)
1635c2c66affSColin Finck             {
1636c2c66affSColin Finck                 if (DriverInfoData->Reserved != 0)
1637c2c66affSColin Finck                 {
1638c2c66affSColin Finck                     if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
1639c2c66affSColin Finck                         break;
1640c2c66affSColin Finck                 }
1641c2c66affSColin Finck                 else
1642c2c66affSColin Finck                 {
1643c2c66affSColin Finck                     /* The caller wants to compare only DriverType, Description and ProviderName fields */
1644c2c66affSColin Finck                     struct DriverInfoElement *driverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
1645c2c66affSColin Finck                     if (driverInfo->Info.DriverType == DriverInfoData->DriverType
1646c2c66affSColin Finck                         && strcmpW(driverInfo->Info.Description, DriverInfoData->Description) == 0
1647c2c66affSColin Finck                         && strcmpW(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
1648c2c66affSColin Finck                     {
1649c2c66affSColin Finck                         break;
1650c2c66affSColin Finck                     }
1651c2c66affSColin Finck                 }
1652c2c66affSColin Finck                 ItemList = ItemList->Flink;
1653c2c66affSColin Finck             }
1654c2c66affSColin Finck             if (ItemList == ListHead)
1655c2c66affSColin Finck                 SetLastError(ERROR_INVALID_PARAMETER);
1656c2c66affSColin Finck             else
1657c2c66affSColin Finck             {
1658c2c66affSColin Finck                 *pDriverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
1659c2c66affSColin Finck                 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
1660c2c66affSColin Finck                 ret = TRUE;
1661c2c66affSColin Finck                 TRACE("Choosing driver whose rank is 0x%lx\n",
1662c2c66affSColin Finck                     (*pDriverInfo)->Params.Rank);
1663c2c66affSColin Finck                 if (DeviceInfoData)
1664c2c66affSColin Finck                     memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
1665c2c66affSColin Finck             }
1666c2c66affSColin Finck         }
1667c2c66affSColin Finck     }
1668c2c66affSColin Finck 
1669c2c66affSColin Finck     TRACE("Returning %d\n", ret);
1670c2c66affSColin Finck     return ret;
1671c2c66affSColin Finck }
1672c2c66affSColin Finck 
1673c2c66affSColin Finck /***********************************************************************
1674c2c66affSColin Finck  *		SetupDiGetDriverInfoDetailA (SETUPAPI.@)
1675c2c66affSColin Finck  */
1676c2c66affSColin Finck BOOL WINAPI
SetupDiGetDriverInfoDetailA(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN PSP_DRVINFO_DATA_A DriverInfoData,IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,IN DWORD DriverInfoDetailDataSize,OUT PDWORD RequiredSize OPTIONAL)1677c2c66affSColin Finck SetupDiGetDriverInfoDetailA(
1678c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
1679c2c66affSColin Finck     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1680c2c66affSColin Finck     IN PSP_DRVINFO_DATA_A DriverInfoData,
1681c2c66affSColin Finck     IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
1682c2c66affSColin Finck     IN DWORD DriverInfoDetailDataSize,
1683c2c66affSColin Finck     OUT PDWORD RequiredSize OPTIONAL)
1684c2c66affSColin Finck {
1685c2c66affSColin Finck     SP_DRVINFO_DATA_V2_W DriverInfoDataW;
1686c2c66affSColin Finck     PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL;
1687c2c66affSColin Finck     DWORD BufSize = 0;
1688c2c66affSColin Finck     DWORD HardwareIDLen = 0;
1689c2c66affSColin Finck     BOOL ret = FALSE;
1690c2c66affSColin Finck 
1691c2c66affSColin Finck     /* do some sanity checks, the unicode version might do more thorough checks */
1692c2c66affSColin Finck     if (DriverInfoData == NULL ||
1693c2c66affSColin Finck         (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
1694c2c66affSColin Finck         (DriverInfoDetailData != NULL &&
1695c2c66affSColin Finck          (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) ||
1696c2c66affSColin Finck           DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A))))
1697c2c66affSColin Finck     {
1698c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1699c2c66affSColin Finck         goto Cleanup;
1700c2c66affSColin Finck     }
1701c2c66affSColin Finck 
1702c2c66affSColin Finck     /* make sure we support both versions of the SP_DRVINFO_DATA structure */
1703c2c66affSColin Finck     if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A))
1704c2c66affSColin Finck     {
1705c2c66affSColin Finck         DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
1706c2c66affSColin Finck     }
1707c2c66affSColin Finck     else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
1708c2c66affSColin Finck     {
1709c2c66affSColin Finck         DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
1710c2c66affSColin Finck     }
1711c2c66affSColin Finck     else
1712c2c66affSColin Finck     {
1713c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1714c2c66affSColin Finck         goto Cleanup;
1715c2c66affSColin Finck     }
1716c2c66affSColin Finck     DriverInfoDataW.DriverType = DriverInfoData->DriverType;
1717c2c66affSColin Finck     DriverInfoDataW.Reserved = DriverInfoData->Reserved;
1718c2c66affSColin Finck 
1719c2c66affSColin Finck     /* convert the strings to unicode */
1720c2c66affSColin Finck     if (MultiByteToWideChar(CP_ACP,
1721c2c66affSColin Finck                             0,
1722c2c66affSColin Finck                             DriverInfoData->Description,
1723c2c66affSColin Finck                             LINE_LEN,
1724c2c66affSColin Finck                             DriverInfoDataW.Description,
1725c2c66affSColin Finck                             LINE_LEN) &&
1726c2c66affSColin Finck         MultiByteToWideChar(CP_ACP,
1727c2c66affSColin Finck                             0,
1728c2c66affSColin Finck                             DriverInfoData->MfgName,
1729c2c66affSColin Finck                             LINE_LEN,
1730c2c66affSColin Finck                             DriverInfoDataW.MfgName,
1731c2c66affSColin Finck                             LINE_LEN) &&
1732c2c66affSColin Finck         MultiByteToWideChar(CP_ACP,
1733c2c66affSColin Finck                             0,
1734c2c66affSColin Finck                             DriverInfoData->ProviderName,
1735c2c66affSColin Finck                             LINE_LEN,
1736c2c66affSColin Finck                             DriverInfoDataW.ProviderName,
1737c2c66affSColin Finck                             LINE_LEN))
1738c2c66affSColin Finck     {
1739c2c66affSColin Finck         if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W))
1740c2c66affSColin Finck         {
1741c2c66affSColin Finck             DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate;
1742c2c66affSColin Finck             DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion;
1743c2c66affSColin Finck         }
1744c2c66affSColin Finck 
1745c2c66affSColin Finck         if (DriverInfoDetailData != NULL)
1746c2c66affSColin Finck         {
1747c2c66affSColin Finck             /* calculate the unicode buffer size from the ansi buffer size */
1748c2c66affSColin Finck             HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID);
1749c2c66affSColin Finck             BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) +
1750c2c66affSColin Finck                       (HardwareIDLen * sizeof(WCHAR));
1751c2c66affSColin Finck 
1752c2c66affSColin Finck             DriverInfoDetailDataW = MyMalloc(BufSize);
1753c2c66affSColin Finck             if (DriverInfoDetailDataW == NULL)
1754c2c66affSColin Finck             {
1755c2c66affSColin Finck                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1756c2c66affSColin Finck                 goto Cleanup;
1757c2c66affSColin Finck             }
1758c2c66affSColin Finck 
1759c2c66affSColin Finck             /* initialize the buffer */
1760c2c66affSColin Finck             ZeroMemory(DriverInfoDetailDataW,
1761c2c66affSColin Finck                        BufSize);
1762c2c66affSColin Finck             DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
1763c2c66affSColin Finck         }
1764c2c66affSColin Finck 
1765c2c66affSColin Finck         /* call the unicode version */
1766c2c66affSColin Finck         ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet,
1767c2c66affSColin Finck                                           DeviceInfoData,
1768c2c66affSColin Finck                                           &DriverInfoDataW,
1769c2c66affSColin Finck                                           DriverInfoDetailDataW,
1770c2c66affSColin Finck                                           BufSize,
1771c2c66affSColin Finck                                           RequiredSize);
1772c2c66affSColin Finck 
1773c2c66affSColin Finck         if (ret)
1774c2c66affSColin Finck         {
1775c2c66affSColin Finck             if (DriverInfoDetailDataW != NULL)
1776c2c66affSColin Finck             {
1777c2c66affSColin Finck                 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
1778c2c66affSColin Finck                 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
1779c2c66affSColin Finck                 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate;
1780c2c66affSColin Finck                 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved;
1781c2c66affSColin Finck                 if (WideCharToMultiByte(CP_ACP,
1782c2c66affSColin Finck                                         0,
1783c2c66affSColin Finck                                         DriverInfoDetailDataW->SectionName,
1784c2c66affSColin Finck                                         LINE_LEN,
1785c2c66affSColin Finck                                         DriverInfoDetailData->SectionName,
1786c2c66affSColin Finck                                         LINE_LEN,
1787c2c66affSColin Finck                                         NULL,
1788c2c66affSColin Finck                                         NULL) &&
1789c2c66affSColin Finck                     WideCharToMultiByte(CP_ACP,
1790c2c66affSColin Finck                                         0,
1791c2c66affSColin Finck                                         DriverInfoDetailDataW->InfFileName,
1792c2c66affSColin Finck                                         MAX_PATH,
1793c2c66affSColin Finck                                         DriverInfoDetailData->InfFileName,
1794c2c66affSColin Finck                                         MAX_PATH,
1795c2c66affSColin Finck                                         NULL,
1796c2c66affSColin Finck                                         NULL) &&
1797c2c66affSColin Finck                     WideCharToMultiByte(CP_ACP,
1798c2c66affSColin Finck                                         0,
1799c2c66affSColin Finck                                         DriverInfoDetailDataW->DrvDescription,
1800c2c66affSColin Finck                                         LINE_LEN,
1801c2c66affSColin Finck                                         DriverInfoDetailData->DrvDescription,
1802c2c66affSColin Finck                                         LINE_LEN,
1803c2c66affSColin Finck                                         NULL,
1804c2c66affSColin Finck                                         NULL) &&
1805c2c66affSColin Finck                     WideCharToMultiByte(CP_ACP,
1806c2c66affSColin Finck                                         0,
1807c2c66affSColin Finck                                         DriverInfoDetailDataW->HardwareID,
1808c2c66affSColin Finck                                         HardwareIDLen,
1809c2c66affSColin Finck                                         DriverInfoDetailData->HardwareID,
1810c2c66affSColin Finck                                         HardwareIDLen,
1811c2c66affSColin Finck                                         NULL,
1812c2c66affSColin Finck                                         NULL))
1813c2c66affSColin Finck                 {
1814c2c66affSColin Finck                     DWORD len, cnt = 0;
1815c2c66affSColin Finck                     DWORD hwidlen = HardwareIDLen;
1816c2c66affSColin Finck                     CHAR *s = DriverInfoDetailData->HardwareID;
1817c2c66affSColin Finck 
1818c2c66affSColin Finck                     /* count the strings in the list */
1819c2c66affSColin Finck                     while (*s != '\0')
1820c2c66affSColin Finck                     {
1821c2c66affSColin Finck                         len = lstrlenA(s) + 1;
1822c2c66affSColin Finck                         if (hwidlen > len)
1823c2c66affSColin Finck                         {
1824c2c66affSColin Finck                             cnt++;
1825c2c66affSColin Finck                             s += len;
1826c2c66affSColin Finck                             hwidlen -= len;
1827c2c66affSColin Finck                         }
1828c2c66affSColin Finck                         else
1829c2c66affSColin Finck                         {
1830c2c66affSColin Finck                             /* looks like the string list wasn't terminated... */
1831c2c66affSColin Finck                             SetLastError(ERROR_INVALID_USER_BUFFER);
1832c2c66affSColin Finck                             ret = FALSE;
1833c2c66affSColin Finck                             break;
1834c2c66affSColin Finck                         }
1835c2c66affSColin Finck                     }
1836c2c66affSColin Finck 
1837c2c66affSColin Finck                     /* make sure CompatIDsOffset points to the second string in the
1838c2c66affSColin Finck                        list, if present */
1839c2c66affSColin Finck                     if (cnt > 1)
1840c2c66affSColin Finck                     {
1841c2c66affSColin Finck                         DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1;
1842c2c66affSColin Finck                         DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) -
1843c2c66affSColin Finck                                                                 DriverInfoDetailData->CompatIDsOffset + 1;
1844c2c66affSColin Finck                     }
1845c2c66affSColin Finck                     else
1846c2c66affSColin Finck                     {
1847c2c66affSColin Finck                         DriverInfoDetailData->CompatIDsOffset = 0;
1848c2c66affSColin Finck                         DriverInfoDetailData->CompatIDsLength = 0;
1849c2c66affSColin Finck                     }
1850c2c66affSColin Finck                 }
1851c2c66affSColin Finck                 else
1852c2c66affSColin Finck                 {
1853c2c66affSColin Finck                     ret = FALSE;
1854c2c66affSColin Finck                 }
1855c2c66affSColin Finck             }
1856c2c66affSColin Finck 
1857c2c66affSColin Finck             if (RequiredSize != NULL)
1858c2c66affSColin Finck             {
1859c2c66affSColin Finck                 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
1860c2c66affSColin Finck                                 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
1861c2c66affSColin Finck             }
1862c2c66affSColin Finck         }
1863c2c66affSColin Finck     }
1864c2c66affSColin Finck 
1865c2c66affSColin Finck Cleanup:
1866c2c66affSColin Finck     if (DriverInfoDetailDataW != NULL)
1867c2c66affSColin Finck     {
1868c2c66affSColin Finck         MyFree(DriverInfoDetailDataW);
1869c2c66affSColin Finck     }
1870c2c66affSColin Finck 
1871c2c66affSColin Finck     return ret;
1872c2c66affSColin Finck }
1873c2c66affSColin Finck 
1874c2c66affSColin Finck /***********************************************************************
1875c2c66affSColin Finck  *		SetupDiGetDriverInfoDetailW (SETUPAPI.@)
1876c2c66affSColin Finck  */
1877c2c66affSColin Finck BOOL WINAPI
SetupDiGetDriverInfoDetailW(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN PSP_DRVINFO_DATA_W DriverInfoData,IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,IN DWORD DriverInfoDetailDataSize,OUT PDWORD RequiredSize OPTIONAL)1878c2c66affSColin Finck SetupDiGetDriverInfoDetailW(
1879c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
1880c2c66affSColin Finck     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
1881c2c66affSColin Finck     IN PSP_DRVINFO_DATA_W DriverInfoData,
1882c2c66affSColin Finck     IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
1883c2c66affSColin Finck     IN DWORD DriverInfoDetailDataSize,
1884c2c66affSColin Finck     OUT PDWORD RequiredSize OPTIONAL)
1885c2c66affSColin Finck {
1886c2c66affSColin Finck     BOOL ret = FALSE;
1887c2c66affSColin Finck 
1888c2c66affSColin Finck     TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
1889c2c66affSColin Finck         DriverInfoData, DriverInfoDetailData,
1890c2c66affSColin Finck         DriverInfoDetailDataSize, RequiredSize);
1891c2c66affSColin Finck 
1892c2c66affSColin Finck     if (!DeviceInfoSet)
1893c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1894c2c66affSColin Finck     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1895c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1896c2c66affSColin Finck     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1897c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
1898c2c66affSColin Finck     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1899c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1900c2c66affSColin Finck     else if (!DriverInfoData)
1901c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1902c2c66affSColin Finck     else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0)
1903c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1904c2c66affSColin Finck     else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W))
1905c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
1906c2c66affSColin Finck     else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W))
1907c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
1908c2c66affSColin Finck     else if (DriverInfoData->Reserved == 0)
1909c2c66affSColin Finck         SetLastError(ERROR_NO_DRIVER_SELECTED);
1910c2c66affSColin Finck     else
1911c2c66affSColin Finck     {
1912c2c66affSColin Finck         struct DriverInfoElement *driverInfoElement;
1913c2c66affSColin Finck         LPWSTR HardwareIDs = NULL;
1914c2c66affSColin Finck         LPWSTR CompatibleIDs = NULL;
1915c2c66affSColin Finck         LPWSTR pBuffer = NULL;
1916c2c66affSColin Finck         LPCWSTR DeviceID = NULL;
1917c2c66affSColin Finck         ULONG HardwareIDsSize, CompatibleIDsSize;
1918c2c66affSColin Finck         ULONG sizeNeeded, sizeLeft, size;
1919c2c66affSColin Finck         BOOL Result;
1920c2c66affSColin Finck 
1921c2c66affSColin Finck         driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
1922c2c66affSColin Finck 
1923c2c66affSColin Finck         /* Get hardware and compatible IDs lists */
1924c2c66affSColin Finck         Result = GetHardwareAndCompatibleIDsLists(
1925c2c66affSColin Finck             DeviceInfoSet,
1926c2c66affSColin Finck             DeviceInfoData,
1927c2c66affSColin Finck             &HardwareIDs, &HardwareIDsSize,
1928c2c66affSColin Finck             &CompatibleIDs, &CompatibleIDsSize);
1929c2c66affSColin Finck         if (!Result)
1930c2c66affSColin Finck             goto done;
1931c2c66affSColin Finck 
1932c2c66affSColin Finck         sizeNeeded = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)
1933c2c66affSColin Finck             + HardwareIDsSize + CompatibleIDsSize;
1934c2c66affSColin Finck         if (RequiredSize)
1935c2c66affSColin Finck             *RequiredSize = sizeNeeded;
1936c2c66affSColin Finck 
1937c2c66affSColin Finck         if (!DriverInfoDetailData)
1938c2c66affSColin Finck         {
1939c2c66affSColin Finck             ret = TRUE;
1940c2c66affSColin Finck             goto done;
1941c2c66affSColin Finck         }
1942c2c66affSColin Finck 
1943c2c66affSColin Finck         memcpy(
1944c2c66affSColin Finck             DriverInfoDetailData,
1945c2c66affSColin Finck             &driverInfoElement->Details,
1946c2c66affSColin Finck             driverInfoElement->Details.cbSize);
1947c2c66affSColin Finck         DriverInfoDetailData->CompatIDsOffset = 0;
1948c2c66affSColin Finck         DriverInfoDetailData->CompatIDsLength = 0;
1949c2c66affSColin Finck 
1950c2c66affSColin Finck         sizeLeft = (DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR);
1951c2c66affSColin Finck         pBuffer = DriverInfoDetailData->HardwareID;
1952c2c66affSColin Finck         /* Add as many as possible HardwareIDs in the list */
1953c2c66affSColin Finck         DeviceID = HardwareIDs;
1954c2c66affSColin Finck         while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
1955c2c66affSColin Finck         {
1956c2c66affSColin Finck             TRACE("Adding %s to list\n", debugstr_w(DeviceID));
1957c2c66affSColin Finck             wcscpy(pBuffer, DeviceID);
1958c2c66affSColin Finck             DeviceID += size + 1;
1959c2c66affSColin Finck             pBuffer += size + 1;
1960c2c66affSColin Finck             sizeLeft -= size + 1;
1961c2c66affSColin Finck             DriverInfoDetailData->CompatIDsOffset += size + 1;
1962c2c66affSColin Finck         }
1963c2c66affSColin Finck         if (sizeLeft > 0)
1964c2c66affSColin Finck         {
1965c2c66affSColin Finck             *pBuffer = UNICODE_NULL;
1966c2c66affSColin Finck             sizeLeft--;
1967c2c66affSColin Finck             DriverInfoDetailData->CompatIDsOffset++;
1968c2c66affSColin Finck         }
1969c2c66affSColin Finck         /* Add as many as possible CompatibleIDs in the list */
1970c2c66affSColin Finck         DeviceID = CompatibleIDs;
1971c2c66affSColin Finck         while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
1972c2c66affSColin Finck         {
1973c2c66affSColin Finck             TRACE("Adding %s to list\n", debugstr_w(DeviceID));
1974c2c66affSColin Finck             wcscpy(pBuffer, DeviceID);
1975c2c66affSColin Finck             DeviceID += size + 1;
1976c2c66affSColin Finck             pBuffer += size + 1;
1977c2c66affSColin Finck             sizeLeft -= size + 1;
1978c2c66affSColin Finck             DriverInfoDetailData->CompatIDsLength += size + 1;
1979c2c66affSColin Finck         }
1980c2c66affSColin Finck         if (sizeLeft > 0)
1981c2c66affSColin Finck         {
1982c2c66affSColin Finck             *pBuffer = UNICODE_NULL;
1983c2c66affSColin Finck             sizeLeft--;
1984c2c66affSColin Finck             DriverInfoDetailData->CompatIDsLength++;
1985c2c66affSColin Finck         }
1986c2c66affSColin Finck 
1987c2c66affSColin Finck         if (sizeNeeded > DriverInfoDetailDataSize)
1988c2c66affSColin Finck             SetLastError(ERROR_INSUFFICIENT_BUFFER);
1989c2c66affSColin Finck         else
1990c2c66affSColin Finck             ret = TRUE;
1991c2c66affSColin Finck 
1992c2c66affSColin Finck done:
1993c2c66affSColin Finck         MyFree(HardwareIDs);
1994c2c66affSColin Finck         MyFree(CompatibleIDs);
1995c2c66affSColin Finck     }
1996c2c66affSColin Finck 
1997c2c66affSColin Finck     TRACE("Returning %d\n", ret);
1998c2c66affSColin Finck     return ret;
1999c2c66affSColin Finck }
2000c2c66affSColin Finck 
2001c2c66affSColin Finck /***********************************************************************
2002c2c66affSColin Finck  *		SetupDiGetDriverInstallParamsW (SETUPAPI.@)
2003c2c66affSColin Finck  */
2004c2c66affSColin Finck BOOL WINAPI
SetupDiGetDriverInstallParamsW(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,IN PSP_DRVINFO_DATA_W DriverInfoData,OUT PSP_DRVINSTALL_PARAMS DriverInstallParams)2005c2c66affSColin Finck SetupDiGetDriverInstallParamsW(
2006c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
2007c2c66affSColin Finck     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
2008c2c66affSColin Finck     IN PSP_DRVINFO_DATA_W DriverInfoData,
2009c2c66affSColin Finck     OUT PSP_DRVINSTALL_PARAMS DriverInstallParams)
2010c2c66affSColin Finck {
2011c2c66affSColin Finck     BOOL ret = FALSE;
2012c2c66affSColin Finck 
2013c2c66affSColin Finck     TRACE("%p %p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData, DriverInstallParams);
2014c2c66affSColin Finck 
2015c2c66affSColin Finck     if (!DeviceInfoSet || !DriverInfoData || !DriverInstallParams)
2016c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
2017c2c66affSColin Finck     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2018c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
2019c2c66affSColin Finck     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2020c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
2021c2c66affSColin Finck     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2022c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
2023c2c66affSColin Finck     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
2024c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
2025c2c66affSColin Finck     else if (DriverInstallParams->cbSize != sizeof(SP_DRVINSTALL_PARAMS))
2026c2c66affSColin Finck        SetLastError(ERROR_INVALID_USER_BUFFER);
2027c2c66affSColin Finck     else
2028c2c66affSColin Finck     {
2029c2c66affSColin Finck         SP_DEVINSTALL_PARAMS InstallParams;
2030c2c66affSColin Finck 
2031c2c66affSColin Finck         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
2032c2c66affSColin Finck         if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
2033c2c66affSColin Finck         {
2034c2c66affSColin Finck             struct DriverInfoElement *driverInfo;
2035*61e35141STimo Kreuzer             driverInfo = (struct DriverInfoElement *)InstallParams.ClassInstallReserved;
2036c2c66affSColin Finck             if (driverInfo == NULL)
2037c2c66affSColin Finck                 SetLastError(ERROR_NO_DRIVER_SELECTED);
2038c2c66affSColin Finck             else
2039c2c66affSColin Finck             {
2040c2c66affSColin Finck                 memcpy(
2041c2c66affSColin Finck                     DriverInstallParams,
2042c2c66affSColin Finck                     &driverInfo->Params,
2043c2c66affSColin Finck                     DriverInstallParams->cbSize);
2044c2c66affSColin Finck                 ret = TRUE;
2045c2c66affSColin Finck             }
2046c2c66affSColin Finck         }
2047c2c66affSColin Finck     }
2048c2c66affSColin Finck 
2049c2c66affSColin Finck     TRACE("Returning %d\n", ret);
2050c2c66affSColin Finck     return ret;
2051c2c66affSColin Finck }
2052c2c66affSColin Finck 
2053c2c66affSColin Finck /***********************************************************************
2054c2c66affSColin Finck  *		SetupDiSelectBestCompatDrv (SETUPAPI.@)
2055c2c66affSColin Finck  */
2056c2c66affSColin Finck BOOL WINAPI
SetupDiSelectBestCompatDrv(IN HDEVINFO DeviceInfoSet,IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)2057c2c66affSColin Finck SetupDiSelectBestCompatDrv(
2058c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
2059c2c66affSColin Finck     IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
2060c2c66affSColin Finck {
2061c2c66affSColin Finck     SP_DRVINFO_DATA_W drvInfoData;
2062c2c66affSColin Finck     BOOL ret;
2063c2c66affSColin Finck 
2064c2c66affSColin Finck     TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
2065c2c66affSColin Finck 
2066c2c66affSColin Finck     /* Drivers are sorted by rank in the driver list, so
2067c2c66affSColin Finck      * the first driver in the list is the best one.
2068c2c66affSColin Finck      */
2069c2c66affSColin Finck     drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
2070c2c66affSColin Finck     ret = SetupDiEnumDriverInfoW(
2071c2c66affSColin Finck         DeviceInfoSet,
2072c2c66affSColin Finck         DeviceInfoData,
2073c2c66affSColin Finck         SPDIT_COMPATDRIVER,
2074c2c66affSColin Finck         0, /* Member index */
2075c2c66affSColin Finck         &drvInfoData);
2076c2c66affSColin Finck 
2077c2c66affSColin Finck     if (ret)
2078c2c66affSColin Finck     {
2079c2c66affSColin Finck         ret = SetupDiSetSelectedDriverW(
2080c2c66affSColin Finck             DeviceInfoSet,
2081c2c66affSColin Finck             DeviceInfoData,
2082c2c66affSColin Finck             &drvInfoData);
2083c2c66affSColin Finck     }
2084c2c66affSColin Finck 
2085c2c66affSColin Finck     TRACE("Returning %d\n", ret);
2086c2c66affSColin Finck     return ret;
2087c2c66affSColin Finck }
2088c2c66affSColin Finck 
2089c2c66affSColin Finck /***********************************************************************
2090c2c66affSColin Finck  *		SetupDiInstallDriverFiles (SETUPAPI.@)
2091c2c66affSColin Finck  */
2092c2c66affSColin Finck BOOL WINAPI
SetupDiInstallDriverFiles(IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData)2093c2c66affSColin Finck SetupDiInstallDriverFiles(
2094c2c66affSColin Finck     IN HDEVINFO DeviceInfoSet,
2095c2c66affSColin Finck     IN PSP_DEVINFO_DATA DeviceInfoData)
2096c2c66affSColin Finck {
2097c2c66affSColin Finck     BOOL ret = FALSE;
2098c2c66affSColin Finck 
2099c2c66affSColin Finck     TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
2100c2c66affSColin Finck 
2101c2c66affSColin Finck     if (!DeviceInfoSet)
2102c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
2103c2c66affSColin Finck     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
2104c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
2105c2c66affSColin Finck     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2106c2c66affSColin Finck         SetLastError(ERROR_INVALID_HANDLE);
2107c2c66affSColin Finck     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2108c2c66affSColin Finck         SetLastError(ERROR_INVALID_USER_BUFFER);
2109*61e35141STimo Kreuzer     else if (DeviceInfoData && ((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams.ClassInstallReserved == 0)
2110c2c66affSColin Finck         SetLastError(ERROR_NO_DRIVER_SELECTED);
2111*61e35141STimo Kreuzer     else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.ClassInstallReserved == 0)
2112c2c66affSColin Finck         SetLastError(ERROR_NO_DRIVER_SELECTED);
2113c2c66affSColin Finck     else
2114c2c66affSColin Finck     {
2115c2c66affSColin Finck         SP_DEVINSTALL_PARAMS_W InstallParams;
2116c2c66affSColin Finck         struct DriverInfoElement *SelectedDriver;
2117c2c66affSColin Finck         WCHAR SectionName[MAX_PATH];
2118c2c66affSColin Finck         DWORD SectionNameLength = 0;
2119c2c66affSColin Finck         PVOID InstallMsgHandler;
2120c2c66affSColin Finck         PVOID InstallMsgHandlerContext;
2121c2c66affSColin Finck         PVOID Context = NULL;
2122c2c66affSColin Finck 
2123c2c66affSColin Finck         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
2124c2c66affSColin Finck         ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
2125c2c66affSColin Finck         if (!ret)
2126c2c66affSColin Finck             goto done;
2127c2c66affSColin Finck 
2128*61e35141STimo Kreuzer         SelectedDriver = (struct DriverInfoElement *)InstallParams.ClassInstallReserved;
2129c2c66affSColin Finck         if (!SelectedDriver)
2130c2c66affSColin Finck         {
2131c2c66affSColin Finck             SetLastError(ERROR_NO_DRIVER_SELECTED);
2132c2c66affSColin Finck             goto done;
2133c2c66affSColin Finck         }
2134c2c66affSColin Finck 
2135c2c66affSColin Finck         ret = SetupDiGetActualSectionToInstallW(
2136c2c66affSColin Finck             SelectedDriver->InfFileDetails->hInf,
2137c2c66affSColin Finck             SelectedDriver->Details.SectionName,
2138c2c66affSColin Finck             SectionName, MAX_PATH - strlenW(DotCoInstallers), &SectionNameLength, NULL);
2139c2c66affSColin Finck         if (!ret)
2140c2c66affSColin Finck             goto done;
2141c2c66affSColin Finck 
2142c2c66affSColin Finck         if (InstallParams.InstallMsgHandler)
2143c2c66affSColin Finck         {
2144c2c66affSColin Finck             InstallMsgHandler = InstallParams.InstallMsgHandler;
2145c2c66affSColin Finck             InstallMsgHandlerContext = InstallParams.InstallMsgHandlerContext;
2146c2c66affSColin Finck         }
2147c2c66affSColin Finck         else
2148c2c66affSColin Finck         {
2149c2c66affSColin Finck             Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
2150c2c66affSColin Finck             if (!Context)
2151c2c66affSColin Finck                 goto cleanup;
2152c2c66affSColin Finck             InstallMsgHandler = SetupDefaultQueueCallbackW;
2153c2c66affSColin Finck             InstallMsgHandlerContext = Context;
2154c2c66affSColin Finck         }
2155c2c66affSColin Finck         ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
2156c2c66affSColin Finck             SelectedDriver->InfFileDetails->hInf, SectionName,
2157c2c66affSColin Finck             SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
2158c2c66affSColin Finck             InstallMsgHandler, InstallMsgHandlerContext,
2159c2c66affSColin Finck             DeviceInfoSet, DeviceInfoData);
2160c2c66affSColin Finck         if (!ret)
2161c2c66affSColin Finck             goto done;
2162c2c66affSColin Finck 
2163c2c66affSColin Finck         /* Install files from .CoInstallers section */
2164c2c66affSColin Finck         lstrcatW(SectionName, DotCoInstallers);
2165c2c66affSColin Finck         ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
2166c2c66affSColin Finck             SelectedDriver->InfFileDetails->hInf, SectionName,
2167c2c66affSColin Finck             SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
2168c2c66affSColin Finck             InstallMsgHandler, InstallMsgHandlerContext,
2169c2c66affSColin Finck             DeviceInfoSet, DeviceInfoData);
2170c2c66affSColin Finck         if (!ret)
2171c2c66affSColin Finck             goto done;
2172c2c66affSColin Finck 
2173c2c66affSColin Finck         /* Set the DI_NOFILECOPY flag to prevent another
2174c2c66affSColin Finck          * installation during SetupDiInstallDevice */
2175c2c66affSColin Finck         InstallParams.Flags |= DI_NOFILECOPY;
2176c2c66affSColin Finck         ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
2177c2c66affSColin Finck 
2178c2c66affSColin Finck cleanup:
2179c2c66affSColin Finck        if (Context)
2180c2c66affSColin Finck            SetupTermDefaultQueueCallback(Context);
2181c2c66affSColin Finck     }
2182c2c66affSColin Finck 
2183c2c66affSColin Finck done:
2184c2c66affSColin Finck     TRACE("Returning %d\n", ret);
2185c2c66affSColin Finck     return ret;
2186c2c66affSColin Finck }
2187