ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

driver.c
Go to the documentation of this file.
00001 /*
00002  * SetupAPI driver-related functions
00003  *
00004  * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include "setupapi_private.h"
00022 
00023 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
00024 
00025 /* Unicode constants */
00026 static const WCHAR BackSlash[] = {'\\',0};
00027 static const WCHAR ClassGUID[]  = {'C','l','a','s','s','G','U','I','D',0};
00028 static const WCHAR DotCoInstallers[]  = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
00029 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
00030 static const WCHAR Version[]  = {'V','e','r','s','i','o','n',0};
00031 
00032 static const WCHAR INF_MANUFACTURER[]  = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
00033 static const WCHAR INF_PROVIDER[]  = {'P','r','o','v','i','d','e','r',0};
00034 static const WCHAR INF_DRIVER_VER[]  = {'D','r','i','v','e','r','V','e','r',0};
00035 
00036 
00037 /***********************************************************************
00038  *      struct InfFileDetails management
00039  */
00040 static VOID
00041 ReferenceInfFile(struct InfFileDetails* infFile)
00042 {
00043     InterlockedIncrement(&infFile->References);
00044 }
00045 
00046 VOID
00047 DereferenceInfFile(struct InfFileDetails* infFile)
00048 {
00049     if (InterlockedDecrement(&infFile->References) == 0)
00050     {
00051         SetupCloseInfFile(infFile->hInf);
00052         HeapFree(GetProcessHeap(), 0, infFile);
00053     }
00054 }
00055 
00056 struct InfFileDetails *
00057 CreateInfFileDetails(
00058     IN LPCWSTR FullInfFileName)
00059 {
00060     struct InfFileDetails *details;
00061     PWCHAR last;
00062     DWORD Needed;
00063 
00064     Needed = FIELD_OFFSET(struct InfFileDetails, szData)
00065         + strlenW(FullInfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
00066 
00067     details = HeapAlloc(GetProcessHeap(), 0, Needed);
00068     if (!details)
00069     {
00070         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00071         return NULL;
00072     }
00073 
00074     memset(details, 0, Needed);
00075     strcpyW(details->szData, FullInfFileName);
00076     last = strrchrW(details->szData, '\\');
00077     if (last)
00078     {
00079         details->DirectoryName = details->szData;
00080         details->FileName = last + 1;
00081         *last = '\0';
00082     }
00083     else
00084         details->FileName = details->szData;
00085     ReferenceInfFile(details);
00086     details->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
00087     if (details->hInf == INVALID_HANDLE_VALUE)
00088     {
00089         HeapFree(GetProcessHeap(), 0, details);
00090         return NULL;
00091     }
00092     return details;
00093 }
00094 
00095 BOOL
00096 DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
00097 {
00098     DereferenceInfFile(driverInfo->InfFileDetails);
00099     HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
00100     HeapFree(GetProcessHeap(), 0, driverInfo);
00101     return TRUE;
00102 }
00103 
00104 /***********************************************************************
00105  *      Helper functions for SetupDiBuildDriverInfoList
00106  */
00107 static BOOL
00108 AddKnownDriverToList(
00109     IN PLIST_ENTRY DriverListHead,
00110     IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
00111     IN LPGUID ClassGuid,
00112     IN struct InfFileDetails *InfFileDetails,
00113     IN LPCWSTR InfFile,
00114     IN LPCWSTR SectionName,
00115     IN LPCWSTR DriverDescription,
00116     IN LPCWSTR ProviderName,
00117     IN LPCWSTR ManufacturerName,
00118     IN LPCWSTR MatchingId,
00119     IN FILETIME DriverDate,
00120     IN DWORDLONG DriverVersion,
00121     IN DWORD Rank)
00122 {
00123     struct DriverInfoElement *driverInfo = NULL;
00124     HANDLE hFile = INVALID_HANDLE_VALUE;
00125     BOOL Result = FALSE;
00126     PLIST_ENTRY PreviousEntry;
00127     BOOL ret = FALSE;
00128 
00129     driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
00130     if (!driverInfo)
00131     {
00132         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00133         goto cleanup;
00134     }
00135     memset(driverInfo, 0, sizeof(struct DriverInfoElement));
00136 
00137     driverInfo->Params.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
00138     driverInfo->Params.Reserved = (ULONG_PTR)driverInfo;
00139 
00140     driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
00141     driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
00142 
00143     /* Copy InfFileName field */
00144     lstrcpynW(driverInfo->Details.InfFileName, InfFile, MAX_PATH - 1);
00145     driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
00146 
00147     /* Fill InfDate field */
00148     hFile = CreateFileW(
00149         InfFile,
00150         GENERIC_READ, FILE_SHARE_READ,
00151         NULL, OPEN_EXISTING, 0, NULL);
00152     if (hFile == INVALID_HANDLE_VALUE)
00153         goto cleanup;
00154     Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
00155     if (!Result)
00156         goto cleanup;
00157 
00158     /* Fill SectionName field */
00159     lstrcpynW(driverInfo->Details.SectionName, SectionName, LINE_LEN);
00160 
00161     /* Fill DrvDescription field */
00162     lstrcpynW(driverInfo->Details.DrvDescription, DriverDescription, LINE_LEN);
00163 
00164     /* Copy MatchingId information */
00165     if (MatchingId)
00166     {
00167         driverInfo->MatchingId = HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId) + 1) * sizeof(WCHAR));
00168         if (!driverInfo->MatchingId)
00169         {
00170             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00171             goto cleanup;
00172         }
00173         RtlCopyMemory(driverInfo->MatchingId, MatchingId, (strlenW(MatchingId) + 1) * sizeof(WCHAR));
00174     }
00175     else
00176         driverInfo->MatchingId = NULL;
00177 
00178     TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
00179         debugstr_w(driverInfo->Details.DrvDescription), debugstr_w(InfFile),
00180         debugstr_w(SectionName), Rank);
00181 
00182     driverInfo->Params.Rank = Rank;
00183     memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
00184     memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
00185     driverInfo->Info.DriverType = DriverType;
00186     driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
00187     lstrcpynW(driverInfo->Info.Description, driverInfo->Details.DrvDescription, LINE_LEN - 1);
00188     driverInfo->Info.Description[LINE_LEN - 1] = '\0';
00189     lstrcpynW(driverInfo->Info.MfgName, ManufacturerName, LINE_LEN - 1);
00190     driverInfo->Info.MfgName[LINE_LEN - 1] = '\0';
00191     if (ProviderName)
00192     {
00193         lstrcpynW(driverInfo->Info.ProviderName, ProviderName, LINE_LEN - 1);
00194         driverInfo->Info.ProviderName[LINE_LEN - 1] = '\0';
00195     }
00196     else
00197         driverInfo->Info.ProviderName[0] = '\0';
00198     driverInfo->Info.DriverDate = DriverDate;
00199     driverInfo->Info.DriverVersion = DriverVersion;
00200     ReferenceInfFile(InfFileDetails);
00201     driverInfo->InfFileDetails = InfFileDetails;
00202 
00203     /* Insert current driver in driver list, according to its rank */
00204     PreviousEntry = DriverListHead->Flink;
00205     while (PreviousEntry != DriverListHead)
00206     {
00207         struct DriverInfoElement *CurrentDriver;
00208         CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
00209         if (CurrentDriver->Params.Rank > Rank ||
00210             (CurrentDriver->Params.Rank == Rank && CurrentDriver->DriverDate.QuadPart < driverInfo->DriverDate.QuadPart))
00211         {
00212             /* Insert before the current item */
00213             InsertHeadList(PreviousEntry->Blink, &driverInfo->ListEntry);
00214             break;
00215         }
00216         PreviousEntry = PreviousEntry->Flink;
00217     }
00218     if (PreviousEntry == DriverListHead)
00219     {
00220         /* Insert at the end of the list */
00221         InsertTailList(DriverListHead, &driverInfo->ListEntry);
00222     }
00223 
00224     ret = TRUE;
00225 
00226 cleanup:
00227     if (!ret)
00228     {
00229         if (driverInfo)
00230             HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
00231         HeapFree(GetProcessHeap(), 0, driverInfo);
00232     }
00233     if (hFile != INVALID_HANDLE_VALUE)
00234         CloseHandle(hFile);
00235 
00236     return ret;
00237 }
00238 
00239 static BOOL
00240 AddDriverToList(
00241     IN PLIST_ENTRY DriverListHead,
00242     IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
00243     IN LPGUID ClassGuid,
00244     IN INFCONTEXT ContextDevice,
00245     IN struct InfFileDetails *InfFileDetails,
00246     IN LPCWSTR InfFile,
00247     IN LPCWSTR ProviderName,
00248     IN LPCWSTR ManufacturerName,
00249     IN LPCWSTR MatchingId,
00250     IN FILETIME DriverDate,
00251     IN DWORDLONG DriverVersion,
00252     IN DWORD Rank)
00253 {
00254     LPWSTR SectionName = NULL;
00255     LPWSTR DriverDescription = NULL;
00256     BOOL Result;
00257     BOOL ret = FALSE;
00258 
00259     /* Read SectionName */
00260     SectionName = MyMalloc(LINE_LEN);
00261     if (!SectionName)
00262     {
00263         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00264         goto cleanup;
00265     }
00266     ZeroMemory(SectionName, LINE_LEN);
00267     Result = SetupGetStringFieldW(
00268         &ContextDevice,
00269         1,
00270         SectionName,
00271         LINE_LEN,
00272         NULL);
00273     if (!Result)
00274         goto cleanup;
00275 
00276     /* Read DriverDescription */
00277     DriverDescription = MyMalloc(LINE_LEN);
00278     if (!DriverDescription)
00279     {
00280         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00281         goto cleanup;
00282     }
00283     ZeroMemory(DriverDescription, LINE_LEN);
00284     Result = SetupGetStringFieldW(
00285         &ContextDevice,
00286         0, /* Field index */
00287         DriverDescription, LINE_LEN,
00288         NULL);
00289 
00290     ret = AddKnownDriverToList(
00291         DriverListHead,
00292         DriverType,
00293         ClassGuid,
00294         InfFileDetails,
00295         InfFile,
00296         SectionName,
00297         DriverDescription,
00298         ProviderName,
00299         ManufacturerName,
00300         MatchingId,
00301         DriverDate,
00302         DriverVersion,
00303         Rank);
00304 
00305 cleanup:
00306     MyFree(SectionName);
00307     MyFree(DriverDescription);
00308 
00309     return ret;
00310 }
00311 
00312 static BOOL
00313 GetVersionInformationFromInfFile(
00314     IN HINF hInf,
00315     OUT LPGUID ClassGuid,
00316     OUT LPWSTR* pProviderName,
00317     OUT FILETIME* DriverDate,
00318     OUT DWORDLONG* DriverVersion)
00319 {
00320     DWORD RequiredSize;
00321     WCHAR guidW[MAX_GUID_STRING_LEN + 1];
00322     LPWSTR DriverVer = NULL;
00323     LPWSTR ProviderName = NULL;
00324     LPWSTR pComma; /* Points into DriverVer */
00325     LPWSTR pVersion = NULL; /* Points into DriverVer */
00326     SYSTEMTIME SystemTime;
00327     BOOL Result;
00328     BOOL ret = FALSE; /* Final result */
00329 
00330     /* Get class Guid */
00331     if (!SetupGetLineTextW(
00332         NULL, /* Context */
00333         hInf,
00334         Version, ClassGUID,
00335         guidW, sizeof(guidW),
00336         NULL /* Required size */))
00337     {
00338         goto cleanup;
00339     }
00340     guidW[37] = '\0'; /* Replace the } by a NULL character */
00341     if (UuidFromStringW(&guidW[1], ClassGuid) != RPC_S_OK)
00342     {
00343         SetLastError(ERROR_GEN_FAILURE);
00344         goto cleanup;
00345     }
00346 
00347     /* Get provider name */
00348     Result = SetupGetLineTextW(
00349         NULL, /* Context */
00350         hInf, Version, INF_PROVIDER,
00351         NULL, 0,
00352         &RequiredSize);
00353     if (Result)
00354     {
00355         /* We know the needed buffer size */
00356         ProviderName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
00357         if (!ProviderName)
00358         {
00359             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00360             goto cleanup;
00361         }
00362         Result = SetupGetLineTextW(
00363             NULL, /* Context */
00364             hInf, Version, INF_PROVIDER,
00365             ProviderName, RequiredSize,
00366             &RequiredSize);
00367     }
00368     if (!Result)
00369         goto cleanup;
00370     *pProviderName = ProviderName;
00371 
00372     /* Read the "DriverVer" value */
00373     Result = SetupGetLineTextW(
00374         NULL, /* Context */
00375         hInf, Version, INF_DRIVER_VER,
00376         NULL, 0,
00377         &RequiredSize);
00378     if (Result)
00379     {
00380         /* We know know the needed buffer size */
00381         DriverVer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
00382         if (!DriverVer)
00383         {
00384             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00385             goto cleanup;
00386         }
00387         Result = SetupGetLineTextW(
00388             NULL, /* Context */
00389             hInf, Version, INF_DRIVER_VER,
00390             DriverVer, RequiredSize,
00391             &RequiredSize);
00392     }
00393     else
00394     {
00395         /* windows sets default date of 00/00/0000 when this directive is missing*/
00396         memset(DriverDate, 0, sizeof(FILETIME));
00397         *DriverVersion = 0;
00398         return TRUE;
00399     }
00400 
00401     /* Get driver date and driver version, by analyzing the "DriverVer" value */
00402     pComma = strchrW(DriverVer, ',');
00403     if (pComma != NULL)
00404     {
00405         *pComma = UNICODE_NULL;
00406         pVersion = pComma + 1;
00407     }
00408     /* Get driver date version. Invalid date = 00/00/00 */
00409     memset(DriverDate, 0, sizeof(FILETIME));
00410     if (strlenW(DriverVer) == 10
00411         && (DriverVer[2] == '-' || DriverVer[2] == '/')
00412         && (DriverVer[5] == '-' || DriverVer[5] == '/'))
00413     {
00414         memset(&SystemTime, 0, sizeof(SYSTEMTIME));
00415         DriverVer[2] = DriverVer[5] = UNICODE_NULL;
00416         SystemTime.wMonth = ((DriverVer[0] - '0') * 10) + DriverVer[1] - '0';
00417         SystemTime.wDay  = ((DriverVer[3] - '0') * 10) + DriverVer[4] - '0';
00418         SystemTime.wYear = ((DriverVer[6] - '0') * 1000) + ((DriverVer[7] - '0') * 100) + ((DriverVer[8] - '0') * 10) + DriverVer[9] - '0';
00419         SystemTimeToFileTime(&SystemTime, DriverDate);
00420     }
00421     /* Get driver version. Invalid version = 0.0.0.0 */
00422     *DriverVersion = 0;
00423     if (pVersion)
00424     {
00425         WORD Major, Minor = 0, Revision = 0, Build = 0;
00426         LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL;
00427         LARGE_INTEGER fullVersion;
00428 
00429         pMinor = strchrW(pVersion, '.');
00430         if (pMinor)
00431         {
00432             *pMinor = 0;
00433             pRevision = strchrW(++pMinor, '.');
00434             Minor = atoiW(pMinor);
00435         }
00436         if (pRevision)
00437         {
00438             *pRevision = 0;
00439             pBuild = strchrW(++pRevision, '.');
00440             Revision = atoiW(pRevision);
00441         }
00442         if (pBuild)
00443         {
00444             *pBuild = 0;
00445             pBuild++;
00446             Build = atoiW(pBuild);
00447         }
00448         Major = atoiW(pVersion);
00449         fullVersion.u.HighPart = Major << 16 | Minor;
00450         fullVersion.u.LowPart = Revision << 16 | Build;
00451         memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER));
00452     }
00453 
00454     ret = TRUE;
00455 
00456 cleanup:
00457     if (!ret)
00458     {
00459         HeapFree(GetProcessHeap(), 0, ProviderName);
00460         *pProviderName = NULL;
00461     }
00462     HeapFree(GetProcessHeap(), 0, DriverVer);
00463 
00464     return ret;
00465 }
00466 
00467 static BOOL
00468 GetHardwareAndCompatibleIDsLists(
00469     IN HDEVINFO DeviceInfoSet,
00470     IN OUT PSP_DEVINFO_DATA DeviceInfoData,
00471     OUT LPWSTR *pHardwareIDs OPTIONAL,
00472     OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL,
00473     OUT LPWSTR *pCompatibleIDs OPTIONAL,
00474     OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL)
00475 {
00476     LPWSTR HardwareIDs = NULL;
00477     LPWSTR CompatibleIDs = NULL;
00478     DWORD RequiredSize;
00479     BOOL Result;
00480 
00481     /* Get hardware IDs list */
00482     Result = FALSE;
00483     RequiredSize = 512; /* Initial buffer size */
00484     SetLastError(ERROR_INSUFFICIENT_BUFFER);
00485     while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
00486     {
00487         MyFree(HardwareIDs);
00488         HardwareIDs = MyMalloc(RequiredSize);
00489         if (!HardwareIDs)
00490         {
00491             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00492             goto done;
00493         }
00494         Result = SetupDiGetDeviceRegistryPropertyW(
00495             DeviceInfoSet,
00496             DeviceInfoData,
00497             SPDRP_HARDWAREID,
00498             NULL,
00499             (PBYTE)HardwareIDs,
00500             RequiredSize,
00501             &RequiredSize);
00502     }
00503     if (!Result)
00504     {
00505         if (GetLastError() == ERROR_FILE_NOT_FOUND)
00506         {
00507             /* No hardware ID for this device */
00508             MyFree(HardwareIDs);
00509             HardwareIDs = NULL;
00510             RequiredSize = 0;
00511         }
00512         else
00513             goto done;
00514     }
00515     if (pHardwareIDs)
00516         *pHardwareIDs = HardwareIDs;
00517     if (pHardwareIDsRequiredSize)
00518         *pHardwareIDsRequiredSize = RequiredSize;
00519 
00520     /* Get compatible IDs list */
00521     Result = FALSE;
00522     RequiredSize = 512; /* Initial buffer size */
00523     SetLastError(ERROR_INSUFFICIENT_BUFFER);
00524     while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
00525     {
00526         MyFree(CompatibleIDs);
00527         CompatibleIDs = MyMalloc(RequiredSize);
00528         if (!CompatibleIDs)
00529         {
00530             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00531             goto done;
00532         }
00533         Result = SetupDiGetDeviceRegistryPropertyW(
00534             DeviceInfoSet,
00535             DeviceInfoData,
00536             SPDRP_COMPATIBLEIDS,
00537             NULL,
00538             (PBYTE)CompatibleIDs,
00539             RequiredSize,
00540             &RequiredSize);
00541     }
00542     if (!Result)
00543     {
00544         if (GetLastError() == ERROR_FILE_NOT_FOUND)
00545         {
00546             /* No compatible ID for this device */
00547             MyFree(CompatibleIDs);
00548             CompatibleIDs = NULL;
00549             RequiredSize = 0;
00550         }
00551         else
00552             goto done;
00553     }
00554     if (pCompatibleIDs)
00555         *pCompatibleIDs = CompatibleIDs;
00556     if (pCompatibleIDsRequiredSize)
00557         *pCompatibleIDsRequiredSize = RequiredSize;
00558 
00559     Result = TRUE;
00560 
00561 done:
00562     if (!Result)
00563     {
00564         MyFree(HardwareIDs);
00565         MyFree(CompatibleIDs);
00566     }
00567     return Result;
00568 }
00569 
00570 #if WIN32_WINNT < 0x0600
00571 /* WARNING:
00572  * This code has been copied from advapi32/reg/reg.c,
00573  * so this dll can be tested as is on Windows XP
00574  */
00575 
00576 #define RRF_RT_REG_NONE         (1 << 0)
00577 #define RRF_RT_REG_SZ           (1 << 1)
00578 #define RRF_RT_REG_EXPAND_SZ    (1 << 2)
00579 #define RRF_RT_REG_BINARY       (1 << 3)
00580 #define RRF_RT_REG_DWORD        (1 << 4)
00581 #define RRF_RT_REG_MULTI_SZ     (1 << 5)
00582 #define RRF_RT_REG_QWORD        (1 << 6)
00583 #define RRF_RT_DWORD            (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD)
00584 #define RRF_RT_QWORD            (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD)
00585 #define RRF_NOEXPAND            (1 << 28)
00586 #define RRF_ZEROONFAILURE       (1 << 29)
00587 
00588 static VOID
00589 RegpApplyRestrictions( DWORD dwFlags, DWORD dwType, DWORD cbData,
00590                        PLONG ret )
00591 {
00592     /* Check if the type is restricted by the passed flags */
00593     if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
00594     {
00595         DWORD dwMask = 0;
00596 
00597         switch (dwType)
00598         {
00599         case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
00600         case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
00601         case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
00602         case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
00603         case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
00604         case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
00605         case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
00606         }
00607 
00608         if (dwFlags & dwMask)
00609         {
00610             /* Type is not restricted, check for size mismatch */
00611             if (dwType == REG_BINARY)
00612             {
00613                 DWORD cbExpect = 0;
00614 
00615                 if ((dwFlags & RRF_RT_DWORD) == RRF_RT_DWORD)
00616                     cbExpect = 4;
00617                 else if ((dwFlags & RRF_RT_QWORD) == RRF_RT_QWORD)
00618                     cbExpect = 8;
00619 
00620                 if (cbExpect && cbData != cbExpect)
00621                     *ret = ERROR_DATATYPE_MISMATCH;
00622             }
00623         }
00624         else *ret = ERROR_UNSUPPORTED_TYPE;
00625     }
00626 }
00627 
00628 static LONG WINAPI
00629 RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue,
00630               DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
00631               LPDWORD pcbData )
00632 {
00633     DWORD dwType, cbData = pcbData ? *pcbData : 0;
00634     PVOID pvBuf = NULL;
00635     LONG ret;
00636 
00637     TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
00638           hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
00639           pvData, pcbData, cbData);
00640 
00641     if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND))
00642         return ERROR_INVALID_PARAMETER;
00643 
00644     if (pszSubKey && pszSubKey[0])
00645     {
00646         ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
00647         if (ret != ERROR_SUCCESS) return ret;
00648     }
00649 
00650     ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
00651 
00652     /* If we are going to expand we need to read in the whole the value even
00653      * if the passed buffer was too small as the expanded string might be
00654      * smaller than the unexpanded one and could fit into cbData bytes. */
00655     if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
00656         (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
00657     {
00658         do {
00659             if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
00660 
00661             pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
00662             if (!pvBuf)
00663             {
00664                 ret = ERROR_NOT_ENOUGH_MEMORY;
00665                 break;
00666             }
00667 
00668             if (ret == ERROR_MORE_DATA)
00669                 ret = RegQueryValueExW(hKey, pszValue, NULL,
00670                                        &dwType, pvBuf, &cbData);
00671             else
00672             {
00673                 /* Even if cbData was large enough we have to copy the
00674                  * string since ExpandEnvironmentStrings can't handle
00675                  * overlapping buffers. */
00676                 CopyMemory(pvBuf, pvData, cbData);
00677             }
00678 
00679             /* Both the type or the value itself could have been modified in
00680              * between so we have to keep retrying until the buffer is large
00681              * enough or we no longer have to expand the value. */
00682         } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
00683 
00684         if (ret == ERROR_SUCCESS)
00685         {
00686             if (dwType == REG_EXPAND_SZ)
00687             {
00688                 cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
00689                                                    pcbData ? (*pcbData)/sizeof(WCHAR) : 0);
00690                 dwType = REG_SZ;
00691                 if(pcbData && cbData > ((*pcbData)/sizeof(WCHAR)))
00692                     ret = ERROR_MORE_DATA;
00693             }
00694             else if (pcbData)
00695                 CopyMemory(pvData, pvBuf, *pcbData);
00696         }
00697 
00698         if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
00699     }
00700 
00701     if (pszSubKey && pszSubKey[0])
00702         RegCloseKey(hKey);
00703 
00704     RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
00705 
00706     if (pcbData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
00707         ZeroMemory(pvData, *pcbData);
00708 
00709     if (pdwType) *pdwType = dwType;
00710     if (pcbData) *pcbData = cbData;
00711 
00712     return ret;
00713 }
00714 #endif /* End of code copied from advapi32/reg/reg.c */
00715 
00716 /***********************************************************************
00717  *      SetupDiBuildDriverInfoList (SETUPAPI.@)
00718  */
00719 BOOL WINAPI
00720 SetupDiBuildDriverInfoList(
00721     IN HDEVINFO DeviceInfoSet,
00722     IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
00723     IN DWORD DriverType)
00724 {
00725     struct DeviceInfoSet *list;
00726     SP_DEVINSTALL_PARAMS_W InstallParams;
00727     PVOID Buffer = NULL;
00728     struct InfFileDetails *currentInfFileDetails = NULL;
00729     LPWSTR ProviderName = NULL;
00730     LPWSTR ManufacturerName = NULL;
00731     WCHAR ManufacturerSection[LINE_LEN + 1];
00732     LPWSTR HardwareIDs = NULL;
00733     LPWSTR CompatibleIDs = NULL;
00734     LPWSTR FullInfFileName = NULL;
00735     LPWSTR ExcludeFromSelect = NULL;
00736     FILETIME DriverDate;
00737     DWORDLONG DriverVersion = 0;
00738     DWORD RequiredSize;
00739     BOOL ret = FALSE;
00740 
00741     TRACE("%p %p %ld\n", DeviceInfoSet, DeviceInfoData, DriverType);
00742 
00743     if (!DeviceInfoSet)
00744         SetLastError(ERROR_INVALID_HANDLE);
00745     else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
00746         SetLastError(ERROR_INVALID_HANDLE);
00747     else if (list->HKLM != HKEY_LOCAL_MACHINE)
00748         SetLastError(ERROR_INVALID_HANDLE);
00749     else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
00750         SetLastError(ERROR_INVALID_PARAMETER);
00751     else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
00752         SetLastError(ERROR_INVALID_PARAMETER);
00753     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
00754         SetLastError(ERROR_INVALID_USER_BUFFER);
00755     else
00756     {
00757         PLIST_ENTRY pDriverListHead = &list->DriverListHead;
00758         BOOL Result;
00759 
00760         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
00761         Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
00762         if (!Result)
00763             goto done;
00764 
00765         if (DeviceInfoData)
00766         {
00767             struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
00768             if (!(devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS))
00769                 pDriverListHead = &devInfo->DriverListHead;
00770         }
00771 
00772         if (DriverType == SPDIT_COMPATDRIVER)
00773         {
00774             /* Get hardware and compatible IDs lists */
00775             Result = GetHardwareAndCompatibleIDsLists(
00776                 DeviceInfoSet,
00777                 DeviceInfoData,
00778                 &HardwareIDs,
00779                 NULL,
00780                 &CompatibleIDs,
00781                 NULL);
00782             if (!Result)
00783                 goto done;
00784             if (!HardwareIDs && !CompatibleIDs)
00785             {
00786                 SetLastError(ERROR_FILE_NOT_FOUND);
00787                 goto done;
00788             }
00789         }
00790 
00791          if (InstallParams.FlagsEx & DI_FLAGSEX_INSTALLEDDRIVER)
00792         {
00793             HKEY hDriverKey;
00794             WCHAR InfFileName[MAX_PATH];
00795             WCHAR InfFileSection[MAX_PATH];
00796             ULONG RequiredSize;
00797             struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
00798             struct InfFileDetails *infFileDetails = NULL;
00799             FILETIME DriverDate;
00800             LONG rc;
00801             DWORD len;
00802 
00803             /* Prepend inf directory name to file name */
00804             len = sizeof(InfFileName) / sizeof(InfFileName[0]);
00805             RequiredSize = GetSystemWindowsDirectoryW(InfFileName, len);
00806             if (RequiredSize == 0 || RequiredSize >= len)
00807                 goto done;
00808             if (*InfFileName && InfFileName[strlenW(InfFileName) - 1] != '\\')
00809                 strcatW(InfFileName, BackSlash);
00810             strcatW(InfFileName, InfDirectory);
00811 
00812             /* Read some information from registry, before creating the driver structure */
00813             hDriverKey = SetupDiOpenDevRegKey(
00814                 DeviceInfoSet,
00815                 DeviceInfoData,
00816                 DICS_FLAG_GLOBAL,
00817                 0,
00818                 DIREG_DRV,
00819                 KEY_QUERY_VALUE);
00820             if (hDriverKey == INVALID_HANDLE_VALUE)
00821                 goto done;
00822             RequiredSize = (len - strlenW(InfFileName)) * sizeof(WCHAR);
00823             rc = RegGetValueW(
00824                 hDriverKey,
00825                 NULL,
00826                 REGSTR_VAL_INFPATH,
00827                 RRF_RT_REG_SZ,
00828                 NULL,
00829                 &InfFileName[strlenW(InfFileName)],
00830                 &RequiredSize);
00831             if (rc != ERROR_SUCCESS)
00832             {
00833                 SetLastError(rc);
00834                 CloseHandle(hDriverKey);
00835                 goto done;
00836             }
00837             RequiredSize = sizeof(InfFileSection);
00838             rc = RegGetValueW(
00839                 hDriverKey,
00840                 NULL,
00841                 REGSTR_VAL_INFSECTION,
00842                 RRF_RT_REG_SZ,
00843                 NULL,
00844                 InfFileSection,
00845                 &RequiredSize);
00846             if (rc != ERROR_SUCCESS)
00847             {
00848                 SetLastError(rc);
00849                 CloseHandle(hDriverKey);
00850                 goto done;
00851             }
00852             TRACE("Current driver in %s/%s\n", debugstr_w(InfFileName), debugstr_w(InfFileSection));
00853             infFileDetails = CreateInfFileDetails(InfFileName);
00854             if (!infFileDetails)
00855             {
00856                 CloseHandle(hDriverKey);
00857                 goto done;
00858             }
00859             DriverDate.dwLowDateTime = DriverDate.dwHighDateTime = 0; /* FIXME */
00860             CloseHandle(hDriverKey);
00861             ret = AddKnownDriverToList(
00862                 pDriverListHead,
00863                 SPDIT_COMPATDRIVER,
00864                 &devInfo->ClassGuid,
00865                 infFileDetails,
00866                 InfFileName,
00867                 InfFileSection, /* Yes, we don't care of section extension */
00868                 L"DriverDescription", /* FIXME */
00869                 L"ProviderName", /* FIXME */
00870                 L"ManufacturerName", /* FIXME */
00871                 L"MatchingId", /* FIXME */
00872                 DriverDate,
00873                 0, /* FIXME: DriverVersion */
00874                 0);
00875             if (!ret)
00876                 DereferenceInfFile(infFileDetails);
00877             Result = FALSE;
00878         }
00879         else if (InstallParams.Flags & DI_ENUMSINGLEINF)
00880         {
00881             /* InstallParams.DriverPath contains the name of a .inf file */
00882             RequiredSize = strlenW(InstallParams.DriverPath) + 2;
00883             Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
00884             if (!Buffer)
00885             {
00886                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00887                 goto done;
00888             }
00889             strcpyW(Buffer, InstallParams.DriverPath);
00890             ((LPWSTR)Buffer)[RequiredSize - 1] = 0;
00891             Result = TRUE;
00892         }
00893         else
00894         {
00895             /* Enumerate .inf files */
00896             Result = FALSE;
00897             RequiredSize = 32768; /* Initial buffer size */
00898             SetLastError(ERROR_INSUFFICIENT_BUFFER);
00899             while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
00900             {
00901                 HeapFree(GetProcessHeap(), 0, Buffer);
00902                 Buffer = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
00903                 if (!Buffer)
00904                 {
00905                     Result = FALSE;
00906                     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00907                     break;
00908                 }
00909                 Result = SetupGetInfFileListW(
00910                     *InstallParams.DriverPath ? InstallParams.DriverPath : NULL,
00911                     INF_STYLE_WIN4,
00912                     Buffer, RequiredSize,
00913                     &RequiredSize);
00914             }
00915             if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
00916             {
00917                 /* No .inf file in specified directory. So, we should
00918                  * success as we created an empty driver info list.
00919                  */
00920                 ret = TRUE;
00921                 goto done;
00922             }
00923         }
00924         if (Result)
00925         {
00926             LPCWSTR filename;
00927             LPWSTR pFullFilename;
00928 
00929             if (InstallParams.Flags & DI_ENUMSINGLEINF)
00930             {
00931                 /* Only a filename */
00932                 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
00933                 if (!FullInfFileName)
00934                     goto done;
00935                 pFullFilename = &FullInfFileName[0];
00936             }
00937             else if (*InstallParams.DriverPath)
00938             {
00939                 /* Directory name specified */
00940                 DWORD len;
00941                 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
00942                 if (len == 0)
00943                     goto done;
00944                 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + MAX_PATH) * sizeof(WCHAR));
00945                 if (!FullInfFileName)
00946                     goto done;
00947                 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
00948                 if (len == 0)
00949                     goto done;
00950                 if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\')
00951                     strcatW(FullInfFileName, BackSlash);
00952                 pFullFilename = &FullInfFileName[strlenW(FullInfFileName)];
00953             }
00954             else
00955             {
00956                 /* Nothing specified ; need to get the %SYSTEMROOT%\ directory */
00957                 DWORD len;
00958                 len = GetSystemWindowsDirectoryW(NULL, 0);
00959                 if (len == 0)
00960                     goto done;
00961                 FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + strlenW(InfDirectory) + MAX_PATH) * sizeof(WCHAR));
00962                 if (!FullInfFileName)
00963                     goto done;
00964                 len = GetSystemWindowsDirectoryW(FullInfFileName, len);
00965                 if (len == 0)
00966                     goto done;
00967                 if (*FullInfFileName && FullInfFileName[strlenW(FullInfFileName) - 1] != '\\')
00968                     strcatW(FullInfFileName, BackSlash);
00969                 strcatW(FullInfFileName, InfDirectory);
00970                 pFullFilename = &FullInfFileName[strlenW(FullInfFileName)];
00971             }
00972 
00973             for (filename = (LPCWSTR)Buffer; *filename; filename += strlenW(filename) + 1)
00974             {
00975                 INFCONTEXT ContextManufacturer, ContextDevice;
00976                 GUID ClassGuid;
00977 
00978                 strcpyW(pFullFilename, filename);
00979                 TRACE("Opening file %s\n", debugstr_w(FullInfFileName));
00980 
00981                 currentInfFileDetails = CreateInfFileDetails(FullInfFileName);
00982                 if (!currentInfFileDetails)
00983                     continue;
00984 
00985                 if (!GetVersionInformationFromInfFile(
00986                     currentInfFileDetails->hInf,
00987                     &ClassGuid,
00988                     &ProviderName,
00989                     &DriverDate,
00990                     &DriverVersion))
00991                 {
00992                     DereferenceInfFile(currentInfFileDetails);
00993                     currentInfFileDetails = NULL;
00994                     continue;
00995                 }
00996 
00997                 if (DriverType == SPDIT_CLASSDRIVER)
00998                 {
00999                     /* Check if the ClassGuid in this .inf file is corresponding with our needs */
01000                     if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid))
01001                     {
01002                         goto next;
01003                     }
01004                 }
01005 
01006                 if (InstallParams.FlagsEx & DI_FLAGSEX_ALLOWEXCLUDEDDRVS)
01007                 {
01008                     /* Read ExcludeFromSelect control flags */
01009                     /* FIXME */
01010                 }
01011                 else
01012                     FIXME("ExcludeFromSelect list ignored\n");
01013 
01014                 /* Get the manufacturers list */
01015                 Result = SetupFindFirstLineW(currentInfFileDetails->hInf, INF_MANUFACTURER, NULL, &ContextManufacturer);
01016                 while (Result)
01017                 {
01018                     Result = SetupGetStringFieldW(
01019                         &ContextManufacturer,
01020                         0, /* Field index */
01021                         NULL, 0,
01022                         &RequiredSize);
01023                     if (Result)
01024                     {
01025                         /* We got the needed size for the buffer */
01026                         ManufacturerName = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
01027                         if (!ManufacturerName)
01028                         {
01029                             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01030                             goto done;
01031                         }
01032                         Result = SetupGetStringFieldW(
01033                             &ContextManufacturer,
01034                             0, /* Field index */
01035                             ManufacturerName, RequiredSize,
01036                             &RequiredSize);
01037                     }
01038                     /* Get manufacturer section name */
01039                     Result = SetupGetStringFieldW(
01040                         &ContextManufacturer,
01041                         1, /* Field index */
01042                         ManufacturerSection, LINE_LEN,
01043                         &RequiredSize);
01044                     if (Result)
01045                     {
01046                         ManufacturerSection[RequiredSize] = 0; /* Final NULL char */
01047                         /* Add (possible) extension to manufacturer section name */
01048                         Result = SetupDiGetActualSectionToInstallW(
01049                             currentInfFileDetails->hInf, ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
01050                         if (Result)
01051                         {
01052                             TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection));
01053                             Result = SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection, NULL, &ContextDevice);
01054                         }
01055                     }
01056                     while (Result)
01057                     {
01058                         if (DriverType == SPDIT_CLASSDRIVER)
01059                         {
01060                             /* FIXME: Check ExcludeFromSelect list */
01061                             if (!AddDriverToList(
01062                                 pDriverListHead,
01063                                 DriverType,
01064                                 &ClassGuid,
01065                                 ContextDevice,
01066                                 currentInfFileDetails,
01067                                 FullInfFileName,
01068                                 ProviderName,
01069                                 ManufacturerName,
01070                                 NULL,
01071                                 DriverDate, DriverVersion,
01072                                 0))
01073                             {
01074                                 break;
01075                             }
01076                         }
01077                         else /* DriverType = SPDIT_COMPATDRIVER */
01078                         {
01079                             /* 1. Get all fields */
01080                             DWORD FieldCount = SetupGetFieldCount(&ContextDevice);
01081                             DWORD DriverRank;
01082                             DWORD i;
01083                             LPCWSTR currentId;
01084                             BOOL DriverAlreadyAdded;
01085 
01086                             for (i = 2; i <= FieldCount; i++)
01087                             {
01088                                 LPWSTR DeviceId = NULL;
01089                                 Result = FALSE;
01090                                 RequiredSize = 128; /* Initial buffer size */
01091                                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
01092                                 while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
01093                                 {
01094                                     HeapFree(GetProcessHeap(), 0, DeviceId);
01095                                     DeviceId = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
01096                                     if (!DeviceId)
01097                                     {
01098                                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01099                                         goto done;
01100                                     }
01101                                     Result = SetupGetStringFieldW(
01102                                         &ContextDevice,
01103                                         i,
01104                                         DeviceId, RequiredSize,
01105                                         &RequiredSize);
01106                                 }
01107                                 if (!Result)
01108                                 {
01109                                     HeapFree(GetProcessHeap(), 0, DeviceId);
01110                                     goto done;
01111                                 }
01112                                 /* FIXME: Check ExcludeFromSelect list */
01113                                 DriverAlreadyAdded = FALSE;
01114                                 for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++)
01115                                 {
01116                                     if (strcmpiW(DeviceId, currentId) == 0)
01117                                     {
01118                                         AddDriverToList(
01119                                             pDriverListHead,
01120                                             DriverType,
01121                                             &ClassGuid,
01122                                             ContextDevice,
01123                                             currentInfFileDetails,
01124                                             FullInfFileName,
01125                                             ProviderName,
01126                                             ManufacturerName,
01127                                             currentId,
01128                                             DriverDate, DriverVersion,
01129                                             DriverRank  + (i == 2 ? 0 : 0x1000 + i - 3));
01130                                         DriverAlreadyAdded = TRUE;
01131                                     }
01132                                 }
01133                                 if (CompatibleIDs)
01134                                 {
01135                                     for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += strlenW(currentId) + 1, DriverRank++)
01136                                     {
01137                                         if (strcmpiW(DeviceId, currentId) == 0)
01138                                         {
01139                                             AddDriverToList(
01140                                                 pDriverListHead,
01141                                                 DriverType,
01142                                                 &ClassGuid,
01143                                                 ContextDevice,
01144                                                 currentInfFileDetails,
01145                                                 FullInfFileName,
01146                                                 ProviderName,
01147                                                 ManufacturerName,
01148                                                 currentId,
01149                                                 DriverDate, DriverVersion,
01150                                                 DriverRank + (i == 2 ? 0x2000 : 0x3000 + i - 3));
01151                                             DriverAlreadyAdded = TRUE;
01152                                         }
01153                                     }
01154                                 }
01155                                 HeapFree(GetProcessHeap(), 0, DeviceId);
01156                             }
01157                         }
01158                         Result = SetupFindNextLine(&ContextDevice, &ContextDevice);
01159                     }
01160 
01161                     HeapFree(GetProcessHeap(), 0, ManufacturerName);
01162                     ManufacturerName = NULL;
01163                     Result = SetupFindNextLine(&ContextManufacturer, &ContextManufacturer);
01164                 }
01165 
01166                 ret = TRUE;
01167 next:
01168                 HeapFree(GetProcessHeap(), 0, ProviderName);
01169                 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect);
01170                 ProviderName = ExcludeFromSelect = NULL;
01171 
01172                 DereferenceInfFile(currentInfFileDetails);
01173                 currentInfFileDetails = NULL;
01174             }
01175             ret = TRUE;
01176         }
01177     }
01178 
01179 done:
01180     if (ret)
01181     {
01182         if (DeviceInfoData)
01183         {
01184             InstallParams.Flags |= DI_DIDCOMPAT;
01185             InstallParams.FlagsEx |= DI_FLAGSEX_DIDCOMPATINFO;
01186         }
01187         else
01188         {
01189             InstallParams.Flags |= DI_DIDCLASS;
01190             InstallParams.FlagsEx |= DI_FLAGSEX_DIDINFOLIST;
01191         }
01192         ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
01193     }
01194 
01195     HeapFree(GetProcessHeap(), 0, ProviderName);
01196     HeapFree(GetProcessHeap(), 0, ManufacturerName);
01197     MyFree(HardwareIDs);
01198     MyFree(CompatibleIDs);
01199     HeapFree(GetProcessHeap(), 0, FullInfFileName);
01200     HeapFree(GetProcessHeap(), 0, ExcludeFromSelect);
01201     if (currentInfFileDetails)
01202         DereferenceInfFile(currentInfFileDetails);
01203     HeapFree(GetProcessHeap(), 0, Buffer);
01204 
01205     TRACE("Returning %d\n", ret);
01206     return ret;
01207 }
01208 
01209 /***********************************************************************
01210  *      SetupDiDestroyDriverInfoList (SETUPAPI.@)
01211  */
01212 BOOL WINAPI
01213 SetupDiDestroyDriverInfoList(
01214     IN HDEVINFO DeviceInfoSet,
01215     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01216     IN DWORD DriverType)
01217 {
01218     struct DeviceInfoSet *list;
01219     BOOL ret = FALSE;
01220 
01221     TRACE("%p %p 0x%lx\n", DeviceInfoSet, DeviceInfoData, DriverType);
01222 
01223     if (!DeviceInfoSet)
01224         SetLastError(ERROR_INVALID_HANDLE);
01225     else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
01226         SetLastError(ERROR_INVALID_HANDLE);
01227     else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
01228         SetLastError(ERROR_INVALID_PARAMETER);
01229     else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
01230         SetLastError(ERROR_INVALID_PARAMETER);
01231     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
01232         SetLastError(ERROR_INVALID_USER_BUFFER);
01233     else
01234     {
01235         PLIST_ENTRY ListEntry;
01236         struct DriverInfoElement *driverInfo;
01237         SP_DEVINSTALL_PARAMS_W InstallParams;
01238 
01239         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
01240         if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
01241             goto done;
01242 
01243         if (!DeviceInfoData)
01244             /* Fall back to destroying class driver list */
01245             DriverType = SPDIT_CLASSDRIVER;
01246 
01247         if (DriverType == SPDIT_CLASSDRIVER)
01248         {
01249             while (!IsListEmpty(&list->DriverListHead))
01250             {
01251                  ListEntry = RemoveHeadList(&list->DriverListHead);
01252                  driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
01253                  DestroyDriverInfoElement(driverInfo);
01254             }
01255             InstallParams.Reserved = 0;
01256             InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
01257             InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDINFOLIST;
01258             ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParams);
01259         }
01260         else
01261         {
01262             SP_DEVINSTALL_PARAMS_W InstallParamsSet;
01263             struct DeviceInfo *deviceInfo;
01264 
01265             InstallParamsSet.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
01266             if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet))
01267                 goto done;
01268             deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
01269             while (!IsListEmpty(&deviceInfo->DriverListHead))
01270             {
01271                  ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
01272                  driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
01273                  if ((PVOID)InstallParamsSet.Reserved == driverInfo)
01274                  {
01275                      InstallParamsSet.Reserved = 0;
01276                      SetupDiSetDeviceInstallParamsW(DeviceInfoSet, NULL, &InstallParamsSet);
01277                  }
01278                  DestroyDriverInfoElement(driverInfo);
01279             }
01280             InstallParams.Reserved = 0;
01281             InstallParams.Flags &= ~DI_DIDCOMPAT;
01282             InstallParams.FlagsEx &= ~DI_FLAGSEX_DIDCOMPATINFO;
01283             ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
01284         }
01285     }
01286 
01287 done:
01288     TRACE("Returning %d\n", ret);
01289     return ret;
01290 }
01291 
01292 /***********************************************************************
01293  *      SetupDiEnumDriverInfoA (SETUPAPI.@)
01294  */
01295 BOOL WINAPI
01296 SetupDiEnumDriverInfoA(
01297     IN HDEVINFO DeviceInfoSet,
01298     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01299     IN DWORD DriverType,
01300     IN DWORD MemberIndex,
01301     OUT PSP_DRVINFO_DATA_A DriverInfoData)
01302 {
01303     SP_DRVINFO_DATA_V2_W driverInfoData2W;
01304     BOOL ret = FALSE;
01305 
01306     TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
01307         DriverType, MemberIndex, DriverInfoData);
01308 
01309     if (DriverInfoData == NULL)
01310         SetLastError(ERROR_INVALID_PARAMETER);
01311     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
01312         SetLastError(ERROR_INVALID_USER_BUFFER);
01313     else
01314     {
01315         driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
01316         ret = SetupDiEnumDriverInfoW(DeviceInfoSet, DeviceInfoData,
01317             DriverType, MemberIndex, &driverInfoData2W);
01318 
01319         if (ret)
01320         {
01321             /* Do W->A conversion */
01322             DriverInfoData->DriverType = driverInfoData2W.DriverType;
01323             DriverInfoData->Reserved = driverInfoData2W.Reserved;
01324             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
01325                 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
01326             {
01327                 DriverInfoData->Description[0] = '\0';
01328                 ret = FALSE;
01329             }
01330             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
01331                 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
01332             {
01333                 DriverInfoData->MfgName[0] = '\0';
01334                 ret = FALSE;
01335             }
01336             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
01337                 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
01338             {
01339                 DriverInfoData->ProviderName[0] = '\0';
01340                 ret = FALSE;
01341             }
01342             if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
01343             {
01344                 /* Copy more fields */
01345                 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
01346                 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
01347             }
01348         }
01349     }
01350 
01351     TRACE("Returning %d\n", ret);
01352     return ret;
01353 }
01354 
01355 
01356 /***********************************************************************
01357  *      SetupDiEnumDriverInfoW (SETUPAPI.@)
01358  */
01359 BOOL WINAPI
01360 SetupDiEnumDriverInfoW(
01361     IN HDEVINFO DeviceInfoSet,
01362     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01363     IN DWORD DriverType,
01364     IN DWORD MemberIndex,
01365     OUT PSP_DRVINFO_DATA_W DriverInfoData)
01366 {
01367     PLIST_ENTRY ListHead;
01368     BOOL ret = FALSE;
01369 
01370     TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet, DeviceInfoData,
01371         DriverType, MemberIndex, DriverInfoData);
01372 
01373     if (!DeviceInfoSet || !DriverInfoData)
01374         SetLastError(ERROR_INVALID_PARAMETER);
01375     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
01376         SetLastError(ERROR_INVALID_HANDLE);
01377     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
01378         SetLastError(ERROR_INVALID_HANDLE);
01379     else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
01380         SetLastError(ERROR_INVALID_PARAMETER);
01381     else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
01382         SetLastError(ERROR_INVALID_PARAMETER);
01383     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
01384         SetLastError(ERROR_INVALID_USER_BUFFER);
01385     else
01386     {
01387         struct DeviceInfo *devInfo = NULL;
01388         PLIST_ENTRY ItemList;
01389         if (DeviceInfoData)
01390             devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
01391         if (!devInfo || (devInfo->CreationFlags & DICD_INHERIT_CLASSDRVS))
01392         {
01393             ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
01394         }
01395         else
01396         {
01397             ListHead = &devInfo->DriverListHead;
01398         }
01399 
01400         ItemList = ListHead->Flink;
01401         while (ItemList != ListHead && MemberIndex-- > 0)
01402             ItemList = ItemList->Flink;
01403         if (ItemList == ListHead)
01404             SetLastError(ERROR_NO_MORE_ITEMS);
01405         else
01406         {
01407             struct DriverInfoElement *DrvInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
01408 
01409             memcpy(
01410                 &DriverInfoData->DriverType,
01411                 &DrvInfo->Info.DriverType,
01412                 DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
01413             ret = TRUE;
01414         }
01415     }
01416 
01417     TRACE("Returning %d\n", ret);
01418     return ret;
01419 }
01420 
01421 /***********************************************************************
01422  *      SetupDiGetSelectedDriverA (SETUPAPI.@)
01423  */
01424 BOOL WINAPI
01425 SetupDiGetSelectedDriverA(
01426     IN HDEVINFO DeviceInfoSet,
01427     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01428     OUT PSP_DRVINFO_DATA_A DriverInfoData)
01429 {
01430     SP_DRVINFO_DATA_V2_W driverInfoData2W;
01431     BOOL ret = FALSE;
01432 
01433     if (DriverInfoData == NULL)
01434         SetLastError(ERROR_INVALID_PARAMETER);
01435     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A))
01436         SetLastError(ERROR_INVALID_USER_BUFFER);
01437     else
01438     {
01439         driverInfoData2W.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
01440 
01441         ret = SetupDiGetSelectedDriverW(DeviceInfoSet,
01442                                         DeviceInfoData,
01443                                         &driverInfoData2W);
01444 
01445         if (ret)
01446         {
01447             /* Do W->A conversion */
01448             DriverInfoData->DriverType = driverInfoData2W.DriverType;
01449             DriverInfoData->Reserved = driverInfoData2W.Reserved;
01450             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.Description, -1,
01451                 DriverInfoData->Description, LINE_LEN, NULL, NULL) == 0)
01452             {
01453                 DriverInfoData->Description[0] = '\0';
01454                 ret = FALSE;
01455             }
01456             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.MfgName, -1,
01457                 DriverInfoData->MfgName, LINE_LEN, NULL, NULL) == 0)
01458             {
01459                 DriverInfoData->MfgName[0] = '\0';
01460                 ret = FALSE;
01461             }
01462             if (WideCharToMultiByte(CP_ACP, 0, driverInfoData2W.ProviderName, -1,
01463                 DriverInfoData->ProviderName, LINE_LEN, NULL, NULL) == 0)
01464             {
01465                 DriverInfoData->ProviderName[0] = '\0';
01466                 ret = FALSE;
01467             }
01468             if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
01469             {
01470                 /* Copy more fields */
01471                 DriverInfoData->DriverDate = driverInfoData2W.DriverDate;
01472                 DriverInfoData->DriverVersion = driverInfoData2W.DriverVersion;
01473             }
01474         }
01475     }
01476 
01477     return ret;
01478 }
01479 
01480 /***********************************************************************
01481  *      SetupDiGetSelectedDriverW (SETUPAPI.@)
01482  */
01483 BOOL WINAPI
01484 SetupDiGetSelectedDriverW(
01485     IN HDEVINFO DeviceInfoSet,
01486     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01487     OUT PSP_DRVINFO_DATA_W DriverInfoData)
01488 {
01489     BOOL ret = FALSE;
01490 
01491     TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
01492 
01493     if (!DeviceInfoSet || !DriverInfoData)
01494         SetLastError(ERROR_INVALID_PARAMETER);
01495     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
01496         SetLastError(ERROR_INVALID_HANDLE);
01497     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
01498         SetLastError(ERROR_INVALID_HANDLE);
01499     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
01500         SetLastError(ERROR_INVALID_USER_BUFFER);
01501     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
01502         SetLastError(ERROR_INVALID_USER_BUFFER);
01503     else
01504     {
01505         SP_DEVINSTALL_PARAMS InstallParams;
01506 
01507         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
01508         if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
01509         {
01510             struct DriverInfoElement *driverInfo;
01511             driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
01512             if (driverInfo == NULL)
01513                 SetLastError(ERROR_NO_DRIVER_SELECTED);
01514             else
01515             {
01516                 memcpy(
01517                     &DriverInfoData->DriverType,
01518                     &driverInfo->Info.DriverType,
01519                     DriverInfoData->cbSize - FIELD_OFFSET(SP_DRVINFO_DATA_W, DriverType));
01520                 ret = TRUE;
01521             }
01522         }
01523     }
01524 
01525     TRACE("Returning %d\n", ret);
01526     return ret;
01527 }
01528 
01529 /***********************************************************************
01530  *      SetupDiSetSelectedDriverA (SETUPAPI.@)
01531  */
01532 BOOL WINAPI
01533 SetupDiSetSelectedDriverA(
01534     IN HDEVINFO DeviceInfoSet,
01535     IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01536     IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
01537 {
01538     SP_DRVINFO_DATA_V1_W DriverInfoDataW;
01539     PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
01540     BOOL ret = FALSE;
01541 
01542     if (DriverInfoData != NULL)
01543     {
01544         if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
01545             DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A))
01546         {
01547             SetLastError(ERROR_INVALID_PARAMETER);
01548             return FALSE;
01549         }
01550 
01551         DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
01552         DriverInfoDataW.Reserved = DriverInfoData->Reserved;
01553 
01554         if (DriverInfoDataW.Reserved == 0)
01555         {
01556             DriverInfoDataW.DriverType = DriverInfoData->DriverType;
01557 
01558             /* convert the strings to unicode */
01559             if (!MultiByteToWideChar(CP_ACP,
01560                                      0,
01561                                      DriverInfoData->Description,
01562                                      LINE_LEN,
01563                                      DriverInfoDataW.Description,
01564                                      LINE_LEN) ||
01565                 !MultiByteToWideChar(CP_ACP,
01566                                      0,
01567                                      DriverInfoData->ProviderName,
01568                                      LINE_LEN,
01569                                      DriverInfoDataW.ProviderName,
01570                                      LINE_LEN))
01571             {
01572                 return FALSE;
01573             }
01574         }
01575 
01576         pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
01577     }
01578 
01579     ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
01580                                     DeviceInfoData,
01581                                     pDriverInfoDataW);
01582 
01583     if (ret && pDriverInfoDataW != NULL)
01584     {
01585         DriverInfoData->Reserved = DriverInfoDataW.Reserved;
01586     }
01587 
01588     return ret;
01589 }
01590 
01591 /***********************************************************************
01592  *      SetupDiSetSelectedDriverW (SETUPAPI.@)
01593  */
01594 BOOL WINAPI
01595 SetupDiSetSelectedDriverW(
01596     IN HDEVINFO DeviceInfoSet,
01597     IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01598     IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL)
01599 {
01600     BOOL ret = FALSE;
01601 
01602     TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData);
01603 
01604     if (!DeviceInfoSet)
01605         SetLastError(ERROR_INVALID_PARAMETER);
01606     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
01607         SetLastError(ERROR_INVALID_HANDLE);
01608     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
01609         SetLastError(ERROR_INVALID_HANDLE);
01610     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
01611         SetLastError(ERROR_INVALID_USER_BUFFER);
01612     else if (DriverInfoData && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
01613         SetLastError(ERROR_INVALID_USER_BUFFER);
01614     else
01615     {
01616         struct DriverInfoElement **pDriverInfo;
01617         PLIST_ENTRY ListHead, ItemList;
01618 
01619         if (DeviceInfoData)
01620         {
01621             pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams.Reserved;
01622             ListHead = &((struct DeviceInfo *)DeviceInfoData->Reserved)->DriverListHead;
01623         }
01624         else
01625         {
01626             pDriverInfo = (struct DriverInfoElement **)&((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved;
01627             ListHead = &((struct DeviceInfoSet *)DeviceInfoSet)->DriverListHead;
01628         }
01629 
01630         if (!DriverInfoData)
01631         {
01632             *pDriverInfo = NULL;
01633             ret = TRUE;
01634         }
01635         else
01636         {
01637             /* Search selected driver in list */
01638             ItemList = ListHead->Flink;
01639             while (ItemList != ListHead)
01640             {
01641                 if (DriverInfoData->Reserved != 0)
01642                 {
01643                     if (DriverInfoData->Reserved == (ULONG_PTR)ItemList)
01644                         break;
01645                 }
01646                 else
01647                 {
01648                     /* The caller wants to compare only DriverType, Description and ProviderName fields */
01649                     struct DriverInfoElement *driverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
01650                     if (driverInfo->Info.DriverType == DriverInfoData->DriverType
01651                         && strcmpW(driverInfo->Info.Description, DriverInfoData->Description) == 0
01652                         && strcmpW(driverInfo->Info.ProviderName, DriverInfoData->ProviderName) == 0)
01653                     {
01654                         break;
01655                     }
01656                 }
01657                 ItemList = ItemList->Flink;
01658             }
01659             if (ItemList == ListHead)
01660                 SetLastError(ERROR_INVALID_PARAMETER);
01661             else
01662             {
01663                 *pDriverInfo = CONTAINING_RECORD(ItemList, struct DriverInfoElement, ListEntry);
01664                 DriverInfoData->Reserved = (ULONG_PTR)ItemList;
01665                 ret = TRUE;
01666                 TRACE("Choosing driver whose rank is 0x%lx\n",
01667                     (*pDriverInfo)->Params.Rank);
01668                 if (DeviceInfoData)
01669                     memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
01670             }
01671         }
01672     }
01673 
01674     TRACE("Returning %d\n", ret);
01675     return ret;
01676 }
01677 
01678 /***********************************************************************
01679  *      SetupDiGetDriverInfoDetailA (SETUPAPI.@)
01680  */
01681 BOOL WINAPI
01682 SetupDiGetDriverInfoDetailA(
01683     IN HDEVINFO DeviceInfoSet,
01684     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01685     IN PSP_DRVINFO_DATA_A DriverInfoData,
01686     IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL,
01687     IN DWORD DriverInfoDetailDataSize,
01688     OUT PDWORD RequiredSize OPTIONAL)
01689 {
01690     SP_DRVINFO_DATA_V2_W DriverInfoDataW;
01691     PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW = NULL;
01692     DWORD BufSize = 0;
01693     DWORD HardwareIDLen = 0;
01694     BOOL ret = FALSE;
01695 
01696     /* do some sanity checks, the unicode version might do more thorough checks */
01697     if (DriverInfoData == NULL ||
01698         (DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
01699         (DriverInfoDetailData != NULL &&
01700          (DriverInfoDetailDataSize < FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) + sizeof(CHAR) ||
01701           DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_A))))
01702     {
01703         SetLastError(ERROR_INVALID_PARAMETER);
01704         goto Cleanup;
01705     }
01706 
01707     /* make sure we support both versions of the SP_DRVINFO_DATA structure */
01708     if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V1_A))
01709     {
01710         DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
01711     }
01712     else if (DriverInfoData->cbSize == sizeof(SP_DRVINFO_DATA_V2_A))
01713     {
01714         DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V2_W);
01715     }
01716     else
01717     {
01718         SetLastError(ERROR_INVALID_PARAMETER);
01719         goto Cleanup;
01720     }
01721     DriverInfoDataW.DriverType = DriverInfoData->DriverType;
01722     DriverInfoDataW.Reserved = DriverInfoData->Reserved;
01723 
01724     /* convert the strings to unicode */
01725     if (MultiByteToWideChar(CP_ACP,
01726                             0,
01727                             DriverInfoData->Description,
01728                             LINE_LEN,
01729                             DriverInfoDataW.Description,
01730                             LINE_LEN) &&
01731         MultiByteToWideChar(CP_ACP,
01732                             0,
01733                             DriverInfoData->MfgName,
01734                             LINE_LEN,
01735                             DriverInfoDataW.MfgName,
01736                             LINE_LEN) &&
01737         MultiByteToWideChar(CP_ACP,
01738                             0,
01739                             DriverInfoData->ProviderName,
01740                             LINE_LEN,
01741                             DriverInfoDataW.ProviderName,
01742                             LINE_LEN))
01743     {
01744         if (DriverInfoDataW.cbSize == sizeof(SP_DRVINFO_DATA_V2_W))
01745         {
01746             DriverInfoDataW.DriverDate = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverDate;
01747             DriverInfoDataW.DriverVersion = ((PSP_DRVINFO_DATA_V2_A)DriverInfoData)->DriverVersion;
01748         }
01749 
01750         if (DriverInfoDetailData != NULL)
01751         {
01752             /* calculate the unicode buffer size from the ansi buffer size */
01753             HardwareIDLen = DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID);
01754             BufSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID) +
01755                       (HardwareIDLen * sizeof(WCHAR));
01756 
01757             DriverInfoDetailDataW = MyMalloc(BufSize);
01758             if (DriverInfoDetailDataW == NULL)
01759             {
01760                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01761                 goto Cleanup;
01762             }
01763 
01764             /* initialize the buffer */
01765             ZeroMemory(DriverInfoDetailDataW,
01766                        BufSize);
01767             DriverInfoDetailDataW->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
01768         }
01769 
01770         /* call the unicode version */
01771         ret = SetupDiGetDriverInfoDetailW(DeviceInfoSet,
01772                                           DeviceInfoData,
01773                                           &DriverInfoDataW,
01774                                           DriverInfoDetailDataW,
01775                                           BufSize,
01776                                           RequiredSize);
01777 
01778         if (ret)
01779         {
01780             if (DriverInfoDetailDataW != NULL)
01781             {
01782                 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
01783                 DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_A);
01784                 DriverInfoDetailData->InfDate = DriverInfoDetailDataW->InfDate;
01785                 DriverInfoDetailData->Reserved = DriverInfoDetailDataW->Reserved;
01786                 if (WideCharToMultiByte(CP_ACP,
01787                                         0,
01788                                         DriverInfoDetailDataW->SectionName,
01789                                         LINE_LEN,
01790                                         DriverInfoDetailData->SectionName,
01791                                         LINE_LEN,
01792                                         NULL,
01793                                         NULL) &&
01794                     WideCharToMultiByte(CP_ACP,
01795                                         0,
01796                                         DriverInfoDetailDataW->InfFileName,
01797                                         MAX_PATH,
01798                                         DriverInfoDetailData->InfFileName,
01799                                         MAX_PATH,
01800                                         NULL,
01801                                         NULL) &&
01802                     WideCharToMultiByte(CP_ACP,
01803                                         0,
01804                                         DriverInfoDetailDataW->DrvDescription,
01805                                         LINE_LEN,
01806                                         DriverInfoDetailData->DrvDescription,
01807                                         LINE_LEN,
01808                                         NULL,
01809                                         NULL) &&
01810                     WideCharToMultiByte(CP_ACP,
01811                                         0,
01812                                         DriverInfoDetailDataW->HardwareID,
01813                                         HardwareIDLen,
01814                                         DriverInfoDetailData->HardwareID,
01815                                         HardwareIDLen,
01816                                         NULL,
01817                                         NULL))
01818                 {
01819                     DWORD len, cnt = 0;
01820                     DWORD hwidlen = HardwareIDLen;
01821                     CHAR *s = DriverInfoDetailData->HardwareID;
01822 
01823                     /* count the strings in the list */
01824                     while (*s != '\0')
01825                     {
01826                         len = lstrlenA(s) + 1;
01827                         if (hwidlen > len)
01828                         {
01829                             cnt++;
01830                             s += len;
01831                             hwidlen -= len;
01832                         }
01833                         else
01834                         {
01835                             /* looks like the string list wasn't terminated... */
01836                             SetLastError(ERROR_INVALID_USER_BUFFER);
01837                             ret = FALSE;
01838                             break;
01839                         }
01840                     }
01841 
01842                     /* make sure CompatIDsOffset points to the second string in the
01843                        list, if present */
01844                     if (cnt > 1)
01845                     {
01846                         DriverInfoDetailData->CompatIDsOffset = lstrlenA(DriverInfoDetailData->HardwareID) + 1;
01847                         DriverInfoDetailData->CompatIDsLength = (DWORD)(s - DriverInfoDetailData->HardwareID) -
01848                                                                 DriverInfoDetailData->CompatIDsOffset + 1;
01849                     }
01850                     else
01851                     {
01852                         DriverInfoDetailData->CompatIDsOffset = 0;
01853                         DriverInfoDetailData->CompatIDsLength = 0;
01854                     }
01855                 }
01856                 else
01857                 {
01858                     ret = FALSE;
01859                 }
01860             }
01861 
01862             if (RequiredSize != NULL)
01863             {
01864                 *RequiredSize = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A, HardwareID) +
01865                                 (((*RequiredSize) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR));
01866             }
01867         }
01868     }
01869 
01870 Cleanup:
01871     if (DriverInfoDetailDataW != NULL)
01872     {
01873         MyFree(DriverInfoDetailDataW);
01874     }
01875 
01876     return ret;
01877 }
01878 
01879 /***********************************************************************
01880  *      SetupDiGetDriverInfoDetailW (SETUPAPI.@)
01881  */
01882 BOOL WINAPI
01883 SetupDiGetDriverInfoDetailW(
01884     IN HDEVINFO DeviceInfoSet,
01885     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01886     IN PSP_DRVINFO_DATA_W DriverInfoData,
01887     IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL,
01888     IN DWORD DriverInfoDetailDataSize,
01889     OUT PDWORD RequiredSize OPTIONAL)
01890 {
01891     BOOL ret = FALSE;
01892 
01893     TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
01894         DriverInfoData, DriverInfoDetailData,
01895         DriverInfoDetailDataSize, RequiredSize);
01896 
01897     if (!DeviceInfoSet)
01898         SetLastError(ERROR_INVALID_PARAMETER);
01899     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
01900         SetLastError(ERROR_INVALID_HANDLE);
01901     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
01902         SetLastError(ERROR_INVALID_HANDLE);
01903     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
01904         SetLastError(ERROR_INVALID_USER_BUFFER);
01905     else if (!DriverInfoData)
01906         SetLastError(ERROR_INVALID_PARAMETER);
01907     else if (!DriverInfoDetailData && DriverInfoDetailDataSize != 0)
01908         SetLastError(ERROR_INVALID_PARAMETER);
01909     else if (DriverInfoDetailData && DriverInfoDetailDataSize < sizeof(SP_DRVINFO_DETAIL_DATA_W))
01910         SetLastError(ERROR_INVALID_PARAMETER);
01911     else if (DriverInfoDetailData && DriverInfoDetailData->cbSize != sizeof(SP_DRVINFO_DETAIL_DATA_W))
01912         SetLastError(ERROR_INVALID_USER_BUFFER);
01913     else if (DriverInfoData->Reserved == 0)
01914         SetLastError(ERROR_NO_DRIVER_SELECTED);
01915     else
01916     {
01917         struct DriverInfoElement *driverInfoElement;
01918         LPWSTR HardwareIDs = NULL;
01919         LPWSTR CompatibleIDs = NULL;
01920         LPWSTR pBuffer = NULL;
01921         LPCWSTR DeviceID = NULL;
01922         ULONG HardwareIDsSize, CompatibleIDsSize;
01923         ULONG sizeNeeded, sizeLeft, size;
01924         BOOL Result;
01925 
01926         driverInfoElement = (struct DriverInfoElement *)DriverInfoData->Reserved;
01927 
01928         /* Get hardware and compatible IDs lists */
01929         Result = GetHardwareAndCompatibleIDsLists(
01930             DeviceInfoSet,
01931             DeviceInfoData,
01932             &HardwareIDs, &HardwareIDsSize,
01933             &CompatibleIDs, &CompatibleIDsSize);
01934         if (!Result)
01935             goto done;
01936 
01937         sizeNeeded = FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)
01938             + HardwareIDsSize + CompatibleIDsSize;
01939         if (RequiredSize)
01940             *RequiredSize = sizeNeeded;
01941 
01942         if (!DriverInfoDetailData)
01943         {
01944             ret = TRUE;
01945             goto done;
01946         }
01947 
01948         memcpy(
01949             DriverInfoDetailData,
01950             &driverInfoElement->Details,
01951             driverInfoElement->Details.cbSize);
01952         DriverInfoDetailData->CompatIDsOffset = 0;
01953         DriverInfoDetailData->CompatIDsLength = 0;
01954 
01955         sizeLeft = (DriverInfoDetailDataSize - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W, HardwareID)) / sizeof(WCHAR);
01956         pBuffer = DriverInfoDetailData->HardwareID;
01957         /* Add as many as possible HardwareIDs in the list */
01958         DeviceID = HardwareIDs;
01959         while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
01960         {
01961             TRACE("Adding %s to list\n", debugstr_w(DeviceID));
01962             wcscpy(pBuffer, DeviceID);
01963             DeviceID += size + 1;
01964             pBuffer += size + 1;
01965             sizeLeft -= size + 1;
01966             DriverInfoDetailData->CompatIDsOffset += size + 1;
01967         }
01968         if (sizeLeft > 0)
01969         {
01970             *pBuffer = UNICODE_NULL;
01971             sizeLeft--;
01972             DriverInfoDetailData->CompatIDsOffset++;
01973         }
01974         /* Add as many as possible CompatibleIDs in the list */
01975         DeviceID = CompatibleIDs;
01976         while (DeviceID && *DeviceID && (size = wcslen(DeviceID)) + 1 < sizeLeft)
01977         {
01978             TRACE("Adding %s to list\n", debugstr_w(DeviceID));
01979             wcscpy(pBuffer, DeviceID);
01980             DeviceID += size + 1;
01981             pBuffer += size + 1;
01982             sizeLeft -= size + 1;
01983             DriverInfoDetailData->CompatIDsLength += size + 1;
01984         }
01985         if (sizeLeft > 0)
01986         {
01987             *pBuffer = UNICODE_NULL;
01988             sizeLeft--;
01989             DriverInfoDetailData->CompatIDsLength++;
01990         }
01991 
01992         if (sizeNeeded > DriverInfoDetailDataSize)
01993             SetLastError(ERROR_INSUFFICIENT_BUFFER);
01994         else
01995             ret = TRUE;
01996 
01997 done:
01998         MyFree(HardwareIDs);
01999         MyFree(CompatibleIDs);
02000     }
02001 
02002     TRACE("Returning %d\n", ret);
02003     return ret;
02004 }
02005 
02006 /***********************************************************************
02007  *      SetupDiGetDriverInstallParamsW (SETUPAPI.@)
02008  */
02009 BOOL WINAPI
02010 SetupDiGetDriverInstallParamsW(
02011     IN HDEVINFO DeviceInfoSet,
02012     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
02013     IN PSP_DRVINFO_DATA_W DriverInfoData,
02014     OUT PSP_DRVINSTALL_PARAMS DriverInstallParams)
02015 {
02016     BOOL ret = FALSE;
02017 
02018     TRACE("%p %p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData, DriverInstallParams);
02019 
02020     if (!DeviceInfoSet || !DriverInfoData || !DriverInstallParams)
02021         SetLastError(ERROR_INVALID_PARAMETER);
02022     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
02023         SetLastError(ERROR_INVALID_HANDLE);
02024     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
02025         SetLastError(ERROR_INVALID_HANDLE);
02026     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
02027         SetLastError(ERROR_INVALID_USER_BUFFER);
02028     else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
02029         SetLastError(ERROR_INVALID_USER_BUFFER);
02030     else if (DriverInstallParams->cbSize != sizeof(SP_DRVINSTALL_PARAMS))
02031        SetLastError(ERROR_INVALID_USER_BUFFER);
02032     else
02033     {
02034         SP_DEVINSTALL_PARAMS InstallParams;
02035 
02036         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
02037         if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
02038         {
02039             struct DriverInfoElement *driverInfo;
02040             driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
02041             if (driverInfo == NULL)
02042                 SetLastError(ERROR_NO_DRIVER_SELECTED);
02043             else
02044             {
02045                 memcpy(
02046                     DriverInstallParams,
02047                     &driverInfo->Params,
02048                     DriverInstallParams->cbSize);
02049                 ret = TRUE;
02050             }
02051         }
02052     }
02053 
02054     TRACE("Returning %d\n", ret);
02055     return ret;
02056 }
02057 
02058 /***********************************************************************
02059  *      SetupDiSelectBestCompatDrv (SETUPAPI.@)
02060  */
02061 BOOL WINAPI
02062 SetupDiSelectBestCompatDrv(
02063     IN HDEVINFO DeviceInfoSet,
02064     IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
02065 {
02066     SP_DRVINFO_DATA_W drvInfoData;
02067     BOOL ret;
02068 
02069     TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
02070 
02071     /* Drivers are sorted by rank in the driver list, so
02072      * the first driver in the list is the best one.
02073      */
02074     drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
02075     ret = SetupDiEnumDriverInfoW(
02076         DeviceInfoSet,
02077         DeviceInfoData,
02078         SPDIT_COMPATDRIVER,
02079         0, /* Member index */
02080         &drvInfoData);
02081 
02082     if (ret)
02083     {
02084         ret = SetupDiSetSelectedDriverW(
02085             DeviceInfoSet,
02086             DeviceInfoData,
02087             &drvInfoData);
02088     }
02089 
02090     TRACE("Returning %d\n", ret);
02091     return ret;
02092 }
02093 
02094 /***********************************************************************
02095  *      SetupDiInstallDriverFiles (SETUPAPI.@)
02096  */
02097 BOOL WINAPI
02098 SetupDiInstallDriverFiles(
02099     IN HDEVINFO DeviceInfoSet,
02100     IN PSP_DEVINFO_DATA DeviceInfoData)
02101 {
02102     BOOL ret = FALSE;
02103 
02104     TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
02105 
02106     if (!DeviceInfoSet)
02107         SetLastError(ERROR_INVALID_PARAMETER);
02108     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
02109         SetLastError(ERROR_INVALID_HANDLE);
02110     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
02111         SetLastError(ERROR_INVALID_HANDLE);
02112     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
02113         SetLastError(ERROR_INVALID_USER_BUFFER);
02114     else if (DeviceInfoData && ((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams.Reserved == 0)
02115         SetLastError(ERROR_NO_DRIVER_SELECTED);
02116     else if (!DeviceInfoData && ((struct DeviceInfoSet *)DeviceInfoSet)->InstallParams.Reserved == 0)
02117         SetLastError(ERROR_NO_DRIVER_SELECTED);
02118     else
02119     {
02120         SP_DEVINSTALL_PARAMS_W InstallParams;
02121         struct DriverInfoElement *SelectedDriver;
02122         WCHAR SectionName[MAX_PATH];
02123         DWORD SectionNameLength = 0;
02124         PVOID InstallMsgHandler;
02125         PVOID InstallMsgHandlerContext;
02126         PVOID Context = NULL;
02127 
02128         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
02129         ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
02130         if (!ret)
02131             goto done;
02132 
02133         SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
02134         if (!SelectedDriver)
02135         {
02136             SetLastError(ERROR_NO_DRIVER_SELECTED);
02137             goto done;
02138         }
02139 
02140         ret = SetupDiGetActualSectionToInstallW(
02141             SelectedDriver->InfFileDetails->hInf,
02142             SelectedDriver->Details.SectionName,
02143             SectionName, MAX_PATH - strlenW(DotCoInstallers), &SectionNameLength, NULL);
02144         if (!ret)
02145             goto done;
02146 
02147         if (InstallParams.InstallMsgHandler)
02148         {
02149             InstallMsgHandler = InstallParams.InstallMsgHandler;
02150             InstallMsgHandlerContext = InstallParams.InstallMsgHandlerContext;
02151         }
02152         else
02153         {
02154             Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
02155             if (!Context)
02156                 goto cleanup;
02157             InstallMsgHandler = SetupDefaultQueueCallbackW;
02158             InstallMsgHandlerContext = Context;
02159         }
02160         ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
02161             SelectedDriver->InfFileDetails->hInf, SectionName,
02162             SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
02163             InstallMsgHandler, InstallMsgHandlerContext,
02164             DeviceInfoSet, DeviceInfoData);
02165         if (!ret)
02166             goto done;
02167 
02168         /* Install files from .CoInstallers section */
02169         lstrcatW(SectionName, DotCoInstallers);
02170         ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
02171             SelectedDriver->InfFileDetails->hInf, SectionName,
02172             SPINST_FILES, NULL, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
02173             InstallMsgHandler, InstallMsgHandlerContext,
02174             DeviceInfoSet, DeviceInfoData);
02175         if (!ret)
02176             goto done;
02177 
02178         /* Set the DI_NOFILECOPY flag to prevent another
02179          * installation during SetupDiInstallDevice */
02180         InstallParams.Flags |= DI_NOFILECOPY;
02181         ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
02182 
02183 cleanup:
02184        if (Context)
02185            SetupTermDefaultQueueCallback(Context);
02186     }
02187 
02188 done:
02189     TRACE("Returning %d\n", ret);
02190     return ret;
02191 }

Generated on Sun May 27 2012 04:18:51 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.