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