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