2 * SetupAPI driver-related functions
4 * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "setupapi_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
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};
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};
37 /***********************************************************************
38 * struct InfFileDetails management
41 ReferenceInfFile(struct InfFileDetails
* infFile
)
43 InterlockedIncrement(&infFile
->References
);
47 DereferenceInfFile(struct InfFileDetails
* infFile
)
49 if (InterlockedDecrement(&infFile
->References
) == 0)
51 SetupCloseInfFile(infFile
->hInf
);
52 HeapFree(GetProcessHeap(), 0, infFile
);
56 struct InfFileDetails
*
58 IN LPCWSTR FullInfFileName
)
60 struct InfFileDetails
*details
;
64 Needed
= FIELD_OFFSET(struct InfFileDetails
, szData
)
65 + strlenW(FullInfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
67 details
= HeapAlloc(GetProcessHeap(), 0, Needed
);
70 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
74 memset(details
, 0, Needed
);
75 strcpyW(details
->szData
, FullInfFileName
);
76 last
= strrchrW(details
->szData
, '\\');
79 details
->DirectoryName
= details
->szData
;
80 details
->FileName
= last
+ 1;
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
)
89 HeapFree(GetProcessHeap(), 0, details
);
96 DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
98 DereferenceInfFile(driverInfo
->InfFileDetails
);
99 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
100 HeapFree(GetProcessHeap(), 0, driverInfo
);
104 /***********************************************************************
105 * Helper functions for SetupDiBuildDriverInfoList
109 IN PLIST_ENTRY DriverListHead
,
110 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
112 IN INFCONTEXT ContextDevice
,
113 IN
struct InfFileDetails
*InfFileDetails
,
115 IN LPCWSTR ProviderName
,
116 IN LPCWSTR ManufacturerName
,
117 IN LPCWSTR MatchingId
,
119 DWORDLONG DriverVersion
,
122 struct DriverInfoElement
*driverInfo
= NULL
;
123 HANDLE hFile
= INVALID_HANDLE_VALUE
;
124 DWORD RequiredSize
= 128; /* Initial buffer size */
126 PLIST_ENTRY PreviousEntry
;
127 LPWSTR InfInstallSection
= NULL
;
130 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
133 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
136 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
138 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
139 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
141 /* Copy InfFileName field */
142 strncpyW(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
143 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
145 /* Fill InfDate field */
148 GENERIC_READ
, FILE_SHARE_READ
,
149 NULL
, OPEN_EXISTING
, 0, NULL
);
150 if (hFile
== INVALID_HANDLE_VALUE
)
152 Result
= GetFileTime(hFile
, NULL
, NULL
, &driverInfo
->Details
.InfDate
);
156 /* Fill SectionName field */
157 Result
= SetupGetStringFieldW(
160 driverInfo
->Details
.SectionName
, LINE_LEN
,
165 /* Fill DrvDescription field */
166 Result
= SetupGetStringFieldW(
169 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
172 /* Copy MatchingId information */
175 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
176 if (!driverInfo
->MatchingId
)
178 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
181 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
184 driverInfo
->MatchingId
= NULL
;
186 /* Get inf install section */
188 RequiredSize
= 128; /* Initial buffer size */
189 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
190 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
192 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
193 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
194 if (!InfInstallSection
)
196 Result
= SetupGetStringFieldW(
199 InfInstallSection
, RequiredSize
,
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
);
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';
220 strncpyW(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
221 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
224 driverInfo
->Info
.ProviderName
[0] = '\0';
225 driverInfo
->Info
.DriverDate
= DriverDate
;
226 driverInfo
->Info
.DriverVersion
= DriverVersion
;
227 ReferenceInfFile(InfFileDetails
);
228 driverInfo
->InfFileDetails
= InfFileDetails
;
230 /* Insert current driver in driver list, according to its rank */
231 PreviousEntry
= DriverListHead
->Flink
;
232 while (PreviousEntry
!= DriverListHead
)
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
))
239 /* Insert before the current item */
240 InsertHeadList(PreviousEntry
->Blink
, &driverInfo
->ListEntry
);
243 PreviousEntry
= PreviousEntry
->Flink
;
245 if (PreviousEntry
== DriverListHead
)
247 /* Insert at the end of the list */
248 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
257 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
258 HeapFree(GetProcessHeap(), 0, driverInfo
);
260 if (hFile
!= INVALID_HANDLE_VALUE
)
262 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
268 GetVersionInformationFromInfFile(
270 OUT LPGUID ClassGuid
,
271 OUT LPWSTR
* pProviderName
,
272 OUT FILETIME
* DriverDate
,
273 OUT DWORDLONG
* DriverVersion
)
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
;
283 BOOL ret
= FALSE
; /* Final result */
286 if (!SetupGetLineTextW(
290 guidW
, sizeof(guidW
),
291 NULL
/* Required size */))
295 guidW
[37] = '\0'; /* Replace the } by a NULL character */
296 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
298 SetLastError(ERROR_GEN_FAILURE
);
302 /* Get provider name */
303 Result
= SetupGetLineTextW(
305 hInf
, Version
, INF_PROVIDER
,
310 /* We know know the needed buffer size */
311 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
314 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
317 Result
= SetupGetLineTextW(
319 hInf
, Version
, INF_PROVIDER
,
320 ProviderName
, RequiredSize
,
325 *pProviderName
= ProviderName
;
327 /* Read the "DriverVer" value */
328 Result
= SetupGetLineTextW(
330 hInf
, Version
, INF_DRIVER_VER
,
335 /* We know know the needed buffer size */
336 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
339 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
342 Result
= SetupGetLineTextW(
344 hInf
, Version
, INF_DRIVER_VER
,
345 DriverVer
, RequiredSize
,
351 /* Get driver date and driver version, by analyzing the "DriverVer" value */
352 pComma
= strchrW(DriverVer
, ',');
355 *pComma
= UNICODE_NULL
;
356 pVersion
= pComma
+ 1;
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] == '/'))
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
);
371 /* Get driver version. Invalid version = 0.0.0.0 */
375 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
376 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
377 LARGE_INTEGER fullVersion
;
379 pMinor
= strchrW(pVersion
, '.');
383 pRevision
= strchrW(++pMinor
, '.');
384 Minor
= atoiW(pMinor
);
389 pBuild
= strchrW(++pRevision
, '.');
390 Revision
= atoiW(pRevision
);
396 Build
= atoiW(pBuild
);
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
));
408 HeapFree(GetProcessHeap(), 0, ProviderName
);
409 HeapFree(GetProcessHeap(), 0, DriverVer
);
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
)
423 LPWSTR HardwareIDs
= NULL
;
424 LPWSTR CompatibleIDs
= NULL
;
428 /* Get hardware IDs list */
430 RequiredSize
= 512; /* Initial buffer size */
431 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
432 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
435 HardwareIDs
= MyMalloc(RequiredSize
);
438 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
441 Result
= SetupDiGetDeviceRegistryPropertyW(
452 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
454 /* No hardware ID for this device */
463 *pHardwareIDs
= HardwareIDs
;
464 if (pHardwareIDsRequiredSize
)
465 *pHardwareIDsRequiredSize
= RequiredSize
;
467 /* Get compatible IDs list */
469 RequiredSize
= 512; /* Initial buffer size */
470 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
471 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
473 MyFree(CompatibleIDs
);
474 CompatibleIDs
= MyMalloc(RequiredSize
);
477 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
480 Result
= SetupDiGetDeviceRegistryPropertyW(
485 (PBYTE
)CompatibleIDs
,
491 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
493 /* No compatible ID for this device */
494 MyFree(CompatibleIDs
);
495 CompatibleIDs
= NULL
;
502 *pCompatibleIDs
= CompatibleIDs
;
503 if (pCompatibleIDsRequiredSize
)
504 *pCompatibleIDsRequiredSize
= RequiredSize
;
512 MyFree(CompatibleIDs
);
517 /***********************************************************************
518 * SetupDiBuildDriverInfoList (SETUPAPI.@)
521 SetupDiBuildDriverInfoList(
522 IN HDEVINFO DeviceInfoSet
,
523 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
526 struct DeviceInfoSet
*list
;
527 SP_DEVINSTALL_PARAMS_W InstallParams
;
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
;
538 DWORDLONG DriverVersion
= 0;
542 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
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
);
558 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
561 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
562 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
568 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
569 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
570 pDriverListHead
= &devInfo
->DriverListHead
;
573 if (DriverType
== SPDIT_COMPATDRIVER
)
575 /* Get hardware and compatible IDs lists */
576 Result
= GetHardwareAndCompatibleIDsLists(
585 if (!HardwareIDs
&& !CompatibleIDs
)
587 SetLastError(ERROR_FILE_NOT_FOUND
);
592 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
594 /* InstallParams.DriverPath contains the name of a .inf file */
595 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
596 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
599 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
602 strcpyW(Buffer
, InstallParams
.DriverPath
);
603 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
608 /* Enumerate .inf files */
610 RequiredSize
= 32768; /* Initial buffer size */
611 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
612 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
614 HeapFree(GetProcessHeap(), 0, Buffer
);
615 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
619 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
622 Result
= SetupGetInfFileListW(
623 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
625 Buffer
, RequiredSize
,
628 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
630 /* No .inf file in specified directory. So, we should
631 * success as we created an empty driver info list.
640 LPWSTR pFullFilename
;
642 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
644 /* Only a filename */
645 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
646 if (!FullInfFileName
)
648 pFullFilename
= &FullInfFileName
[0];
650 else if (*InstallParams
.DriverPath
)
652 /* Directory name specified */
654 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
657 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + MAX_PATH
) * sizeof(WCHAR
));
658 if (!FullInfFileName
)
660 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
663 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
664 strcatW(FullInfFileName
, BackSlash
);
665 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
669 /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */
671 len
= GetSystemWindowsDirectoryW(NULL
, 0);
674 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1 + strlenW(InfDirectory
) + MAX_PATH
) * sizeof(WCHAR
));
675 if (!FullInfFileName
)
677 len
= GetSystemWindowsDirectoryW(FullInfFileName
, len
);
680 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
681 strcatW(FullInfFileName
, BackSlash
);
682 strcatW(FullInfFileName
, InfDirectory
);
683 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
686 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
688 INFCONTEXT ContextManufacturer
, ContextDevice
;
691 strcpyW(pFullFilename
, filename
);
692 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
694 currentInfFileDetails
= CreateInfFileDetails(FullInfFileName
);
695 if (!currentInfFileDetails
)
698 if (!GetVersionInformationFromInfFile(
699 currentInfFileDetails
->hInf
,
705 DereferenceInfFile(currentInfFileDetails
);
706 currentInfFileDetails
= NULL
;
710 if (DriverType
== SPDIT_CLASSDRIVER
)
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
))
719 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
721 /* Read ExcludeFromSelect control flags */
725 FIXME("ExcludeFromSelect list ignored\n");
727 /* Get the manufacturers list */
728 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
731 Result
= SetupGetStringFieldW(
732 &ContextManufacturer
,
738 /* We got the needed size for the buffer */
739 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
740 if (!ManufacturerName
)
742 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
745 Result
= SetupGetStringFieldW(
746 &ContextManufacturer
,
748 ManufacturerName
, RequiredSize
,
751 /* Get manufacturer section name */
752 Result
= SetupGetStringFieldW(
753 &ContextManufacturer
,
755 ManufacturerSection
, LINE_LEN
,
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
);
765 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
766 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
771 if (DriverType
== SPDIT_CLASSDRIVER
)
773 /* FIXME: Check ExcludeFromSelect list */
774 if (!AddDriverToList(
779 currentInfFileDetails
,
784 DriverDate
, DriverVersion
,
790 else /* DriverType = SPDIT_COMPATDRIVER */
792 /* 1. Get all fields */
793 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
797 BOOL DriverAlreadyAdded
;
799 for (i
= 2; i
<= FieldCount
; i
++)
801 LPWSTR DeviceId
= NULL
;
803 RequiredSize
= 128; /* Initial buffer size */
804 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
805 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
807 HeapFree(GetProcessHeap(), 0, DeviceId
);
808 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
811 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
814 Result
= SetupGetStringFieldW(
817 DeviceId
, RequiredSize
,
822 HeapFree(GetProcessHeap(), 0, DeviceId
);
825 /* FIXME: Check ExcludeFromSelect list */
826 DriverAlreadyAdded
= FALSE
;
827 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
829 if (strcmpiW(DeviceId
, currentId
) == 0)
836 currentInfFileDetails
,
841 DriverDate
, DriverVersion
,
842 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
843 DriverAlreadyAdded
= TRUE
;
848 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
850 if (strcmpiW(DeviceId
, currentId
) == 0)
857 currentInfFileDetails
,
862 DriverDate
, DriverVersion
,
863 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
864 DriverAlreadyAdded
= TRUE
;
868 HeapFree(GetProcessHeap(), 0, DeviceId
);
871 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
874 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
875 ManufacturerName
= NULL
;
876 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
881 HeapFree(GetProcessHeap(), 0, ProviderName
);
882 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
883 ProviderName
= ExcludeFromSelect
= NULL
;
885 DereferenceInfFile(currentInfFileDetails
);
886 currentInfFileDetails
= NULL
;
897 InstallParams
.Flags
|= DI_DIDCOMPAT
;
898 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
902 InstallParams
.Flags
|= DI_DIDCLASS
;
903 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
905 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
908 HeapFree(GetProcessHeap(), 0, ProviderName
);
909 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
911 MyFree(CompatibleIDs
);
912 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
913 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
914 if (currentInfFileDetails
)
915 DereferenceInfFile(currentInfFileDetails
);
916 HeapFree(GetProcessHeap(), 0, Buffer
);
918 TRACE("Returning %d\n", ret
);
922 /***********************************************************************
923 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
926 SetupDiDestroyDriverInfoList(
927 IN HDEVINFO DeviceInfoSet
,
928 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
931 struct DeviceInfoSet
*list
;
934 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
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
);
948 PLIST_ENTRY ListEntry
;
949 struct DriverInfoElement
*driverInfo
;
950 SP_DEVINSTALL_PARAMS_W InstallParams
;
952 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
953 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
957 /* Fall back to destroying class driver list */
958 DriverType
= SPDIT_CLASSDRIVER
;
960 if (DriverType
== SPDIT_CLASSDRIVER
)
962 while (!IsListEmpty(&list
->DriverListHead
))
964 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
965 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
966 DestroyDriverInfoElement(driverInfo
);
968 InstallParams
.Reserved
= 0;
969 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
970 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
971 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
975 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
976 struct DeviceInfoElement
*deviceInfo
;
978 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
979 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
981 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
982 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
984 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
985 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
986 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
988 InstallParamsSet
.Reserved
= 0;
989 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
991 DestroyDriverInfoElement(driverInfo
);
993 InstallParams
.Reserved
= 0;
994 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
995 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
996 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1001 TRACE("Returning %d\n", ret
);
1005 /***********************************************************************
1006 * SetupDiEnumDriverInfoA (SETUPAPI.@)
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
)
1016 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
1019 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1020 DriverType
, MemberIndex
, DriverInfoData
);
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
);
1028 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1029 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
1030 DriverType
, MemberIndex
, &driverInfoData2W
);
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)
1040 DriverInfoData
->Description
[0] = '\0';
1043 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1044 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1046 DriverInfoData
->MfgName
[0] = '\0';
1049 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1050 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1052 DriverInfoData
->ProviderName
[0] = '\0';
1055 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1057 /* Copy more fields */
1058 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1059 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1064 TRACE("Returning %d\n", ret
);
1069 /***********************************************************************
1070 * SetupDiEnumDriverInfoW (SETUPAPI.@)
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
)
1080 PLIST_ENTRY ListHead
;
1083 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
1084 DriverType
, MemberIndex
, DriverInfoData
);
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
);
1100 struct DeviceInfoElement
*devInfo
= NULL
;
1101 PLIST_ENTRY ItemList
;
1103 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
1104 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
1106 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1110 ListHead
= &devInfo
->DriverListHead
;
1113 ItemList
= ListHead
->Flink
;
1114 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
1115 ItemList
= ItemList
->Flink
;
1116 if (ItemList
== ListHead
)
1117 SetLastError(ERROR_NO_MORE_ITEMS
);
1120 struct DriverInfoElement
*DrvInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1123 &DriverInfoData
->DriverType
,
1124 &DrvInfo
->Info
.DriverType
,
1125 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1130 TRACE("Returning %d\n", ret
);
1134 /***********************************************************************
1135 * SetupDiGetSelectedDriverA (SETUPAPI.@)
1138 SetupDiGetSelectedDriverA(
1139 IN HDEVINFO DeviceInfoSet
,
1140 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1141 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
1143 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
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
);
1152 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1154 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
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)
1166 DriverInfoData
->Description
[0] = '\0';
1169 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
1170 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
1172 DriverInfoData
->MfgName
[0] = '\0';
1175 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
1176 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
1178 DriverInfoData
->ProviderName
[0] = '\0';
1181 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1183 /* Copy more fields */
1184 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
1185 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
1193 /***********************************************************************
1194 * SetupDiGetSelectedDriverW (SETUPAPI.@)
1197 SetupDiGetSelectedDriverW(
1198 IN HDEVINFO DeviceInfoSet
,
1199 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1200 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
1204 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
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
);
1218 SP_DEVINSTALL_PARAMS InstallParams
;
1220 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1221 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
1223 struct DriverInfoElement
*driverInfo
;
1224 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
1225 if (driverInfo
== NULL
)
1226 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1230 &DriverInfoData
->DriverType
,
1231 &driverInfo
->Info
.DriverType
,
1232 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
1238 TRACE("Returning %d\n", ret
);
1242 /***********************************************************************
1243 * SetupDiSetSelectedDriverA (SETUPAPI.@)
1246 SetupDiSetSelectedDriverA(
1247 IN HDEVINFO DeviceInfoSet
,
1248 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1249 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
1251 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
1252 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
1255 if (DriverInfoData
!= NULL
)
1257 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
1258 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
1260 SetLastError(ERROR_INVALID_PARAMETER
);
1264 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1265 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1267 if (DriverInfoDataW
.Reserved
== 0)
1269 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1271 /* convert the strings to unicode */
1272 if (!MultiByteToWideChar(CP_ACP
,
1274 DriverInfoData
->Description
,
1276 DriverInfoDataW
.Description
,
1278 !MultiByteToWideChar(CP_ACP
,
1280 DriverInfoData
->ProviderName
,
1282 DriverInfoDataW
.ProviderName
,
1289 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
1292 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
1296 if (ret
&& pDriverInfoDataW
!= NULL
)
1298 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
1304 /***********************************************************************
1305 * SetupDiSetSelectedDriverW (SETUPAPI.@)
1308 SetupDiSetSelectedDriverW(
1309 IN HDEVINFO DeviceInfoSet
,
1310 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1311 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
1315 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
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
);
1329 struct DriverInfoElement
**pDriverInfo
;
1330 PLIST_ENTRY ListHead
, ItemList
;
1334 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
1335 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
1339 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
1340 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
1343 if (!DriverInfoData
)
1345 *pDriverInfo
= NULL
;
1350 /* Search selected driver in list */
1351 ItemList
= ListHead
->Flink
;
1352 while (ItemList
!= ListHead
)
1354 if (DriverInfoData
->Reserved
!= 0)
1356 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
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)
1370 ItemList
= ItemList
->Flink
;
1372 if (ItemList
== ListHead
)
1373 SetLastError(ERROR_INVALID_PARAMETER
);
1376 *pDriverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
1377 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
1379 TRACE("Choosing driver whose rank is 0x%lx\n",
1380 (*pDriverInfo
)->DriverRank
);
1382 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
1387 TRACE("Returning %d\n", ret
);
1391 /***********************************************************************
1392 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
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
)
1403 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
1404 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
1406 DWORD HardwareIDLen
= 0;
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
))))
1416 SetLastError(ERROR_INVALID_PARAMETER
);
1420 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
1421 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
1423 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
1425 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
1427 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
1431 SetLastError(ERROR_INVALID_PARAMETER
);
1434 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
1435 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
1437 /* convert the strings to unicode */
1438 if (MultiByteToWideChar(CP_ACP
,
1440 DriverInfoData
->Description
,
1442 DriverInfoDataW
.Description
,
1444 MultiByteToWideChar(CP_ACP
,
1446 DriverInfoData
->MfgName
,
1448 DriverInfoDataW
.MfgName
,
1450 MultiByteToWideChar(CP_ACP
,
1452 DriverInfoData
->ProviderName
,
1454 DriverInfoDataW
.ProviderName
,
1457 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
1459 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
1460 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
1463 if (DriverInfoDetailData
!= NULL
)
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
));
1470 DriverInfoDetailDataW
= MyMalloc(BufSize
);
1471 if (DriverInfoDetailDataW
== NULL
)
1473 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1477 /* initialize the buffer */
1478 ZeroMemory(DriverInfoDetailDataW
,
1480 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
1483 /* call the unicode version */
1484 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
1487 DriverInfoDetailDataW
,
1493 if (DriverInfoDetailDataW
!= NULL
)
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
,
1501 DriverInfoDetailDataW
->SectionName
,
1503 DriverInfoDetailData
->SectionName
,
1507 WideCharToMultiByte(CP_ACP
,
1509 DriverInfoDetailDataW
->InfFileName
,
1511 DriverInfoDetailData
->InfFileName
,
1515 WideCharToMultiByte(CP_ACP
,
1517 DriverInfoDetailDataW
->DrvDescription
,
1519 DriverInfoDetailData
->DrvDescription
,
1523 WideCharToMultiByte(CP_ACP
,
1525 DriverInfoDetailDataW
->HardwareID
,
1527 DriverInfoDetailData
->HardwareID
,
1533 DWORD hwidlen
= HardwareIDLen
;
1534 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
1536 /* count the strings in the list */
1539 len
= lstrlenA(s
) + 1;
1548 /* looks like the string list wasn't terminated... */
1549 SetLastError(ERROR_INVALID_USER_BUFFER
);
1555 /* make sure CompatIDsOffset points to the second string in the
1559 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
1560 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
1561 DriverInfoDetailData
->CompatIDsOffset
+ 1;
1565 DriverInfoDetailData
->CompatIDsOffset
= 0;
1566 DriverInfoDetailData
->CompatIDsLength
= 0;
1575 if (RequiredSize
!= NULL
)
1577 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
1578 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
1584 if (DriverInfoDetailDataW
!= NULL
)
1586 MyFree(DriverInfoDetailDataW
);
1592 /***********************************************************************
1593 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
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
)
1606 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
1607 DriverInfoData
, DriverInfoDetailData
,
1608 DriverInfoDetailDataSize
, RequiredSize
);
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
);
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
;
1639 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
1641 /* Get hardware and compatible IDs lists */
1642 Result
= GetHardwareAndCompatibleIDsLists(
1645 &HardwareIDs
, &HardwareIDsSize
,
1646 &CompatibleIDs
, &CompatibleIDsSize
);
1650 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
1651 + HardwareIDsSize
+ CompatibleIDsSize
;
1653 *RequiredSize
= sizeNeeded
;
1655 if (!DriverInfoDetailData
)
1662 DriverInfoDetailData
,
1663 &driverInfoElement
->Details
,
1664 driverInfoElement
->Details
.cbSize
);
1665 DriverInfoDetailData
->CompatIDsOffset
= 0;
1666 DriverInfoDetailData
->CompatIDsLength
= 0;
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
)
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;
1683 *pBuffer
= UNICODE_NULL
;
1685 DriverInfoDetailData
->CompatIDsOffset
++;
1687 /* Add as many as possible CompatibleIDs in the list */
1688 DeviceID
= CompatibleIDs
;
1689 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
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;
1700 *pBuffer
= UNICODE_NULL
;
1702 DriverInfoDetailData
->CompatIDsLength
++;
1705 if (sizeNeeded
> DriverInfoDetailDataSize
)
1706 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1711 MyFree(HardwareIDs
);
1712 MyFree(CompatibleIDs
);
1715 TRACE("Returning %d\n", ret
);
1719 /***********************************************************************
1720 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
1723 SetupDiSelectBestCompatDrv(
1724 IN HDEVINFO DeviceInfoSet
,
1725 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
1727 SP_DRVINFO_DATA_W drvInfoData
;
1730 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
1732 /* Drivers are sorted by rank in the driver list, so
1733 * the first driver in the list is the best one.
1735 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
1736 ret
= SetupDiEnumDriverInfoW(
1740 0, /* Member index */
1745 ret
= SetupDiSetSelectedDriverW(
1751 TRACE("Returning %d\n", ret
);
1755 /***********************************************************************
1756 * SetupDiInstallDriverFiles (SETUPAPI.@)
1759 SetupDiInstallDriverFiles(
1760 IN HDEVINFO DeviceInfoSet
,
1761 IN PSP_DEVINFO_DATA DeviceInfoData
)
1765 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
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
);
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
;
1789 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1790 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1794 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
1795 if (!SelectedDriver
)
1797 SetLastError(ERROR_NO_DRIVER_SELECTED
);
1801 ret
= SetupDiGetActualSectionToInstallW(
1802 SelectedDriver
->InfFileDetails
->hInf
,
1803 SelectedDriver
->Details
.SectionName
,
1804 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
1808 if (InstallParams
.InstallMsgHandler
)
1810 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
1811 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
1815 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
1818 InstallMsgHandler
= SetupDefaultQueueCallback
;
1819 InstallMsgHandlerContext
= Context
;
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
);
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
);
1839 /* Set the DI_NOFILECOPY flag to prevent another
1840 * installation during SetupDiInstallDevice */
1841 InstallParams
.Flags
|= DI_NOFILECOPY
;
1842 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1846 SetupTermDefaultQueueCallback(Context
);
1850 TRACE("Returning %d\n", ret
);