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