- Implement SetupCopyOEMInfW
authorHervé Poussineau <hpoussin@reactos.org>
Mon, 29 May 2006 13:32:51 +0000 (13:32 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Mon, 29 May 2006 13:32:51 +0000 (13:32 +0000)
- Correctly sort drivers by rank and by date
- Fix memory corruption if %SYSTEMROOT% was longer than 128 chars

svn path=/trunk/; revision=22109

reactos/dll/win32/setupapi/devinst.c
reactos/dll/win32/setupapi/install.c
reactos/dll/win32/setupapi/setupapi_private.h
reactos/dll/win32/setupapi/stubs.c

index 264144c..4870407 100644 (file)
@@ -5486,14 +5486,15 @@ AddDriverToList(
     driverInfo->Details.InfFileName[MAX_PATH - 1] = '\0';
 
     /* Fill InfDate field */
-    /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
+    hFile = CreateFile(
+        InfFile,
         GENERIC_READ, FILE_SHARE_READ,
         NULL, OPEN_EXISTING, 0, NULL);
     if (hFile == INVALID_HANDLE_VALUE)
         goto cleanup;
     Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
     if (!Result)
-        goto cleanup;*/
+        goto cleanup;
 
     /* Fill SectionName field */
     Result = SetupGetStringFieldW(
@@ -5576,10 +5577,10 @@ AddDriverToList(
         struct DriverInfoElement *CurrentDriver;
         CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
         if (CurrentDriver->DriverRank > Rank ||
-            (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart > driverInfo->DriverDate.QuadPart))
+            (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart < driverInfo->DriverDate.QuadPart))
         {
             /* Insert before the current item */
-            InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
+            InsertHeadList(PreviousEntry->Blink, &driverInfo->ListEntry);
             break;
         }
         PreviousEntry = PreviousEntry->Flink;
@@ -5858,17 +5859,14 @@ done:
 
 static struct InfFileDetails *
 CreateInfFileDetails(
-    IN LPCWSTR InfFileName)
+    IN LPCWSTR FullInfFileName)
 {
     struct InfFileDetails *details;
     PWCHAR last;
     DWORD Needed;
 
-    last = strrchrW(InfFileName, '\\');
     Needed = FIELD_OFFSET(struct InfFileDetails, szData)
-        + strlenW(InfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
-    if (last != NULL)
-    Needed += (last - InfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
+        + strlenW(FullInfFileName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
 
     details = HeapAlloc(GetProcessHeap(), 0, Needed);
     if (!details)
@@ -5878,17 +5876,18 @@ CreateInfFileDetails(
     }
 
     memset(details, 0, Needed);
+    strcpyW(details->szData, FullInfFileName);
+    last = strrchrW(details->szData, '\\');
     if (last)
     {
         details->DirectoryName = details->szData;
-        details->FullInfFileName = &details->szData[last - InfFileName + 1];
-        strncpyW(details->DirectoryName, InfFileName, last - InfFileName);
+        details->FileName = last + 1;
+        *last = '\0';
     }
     else
-        details->FullInfFileName = details->szData;
-    strcpyW(details->FullInfFileName, InfFileName);
+        details->FileName = details->szData;
     ReferenceInfFile(details);
-    details->hInf = SetupOpenInfFileW(InfFileName, NULL, INF_STYLE_WIN4, NULL);
+    details->hInf = SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
     if (details->hInf == INVALID_HANDLE_VALUE)
     {
         HeapFree(GetProcessHeap(), 0, details);
@@ -6022,20 +6021,13 @@ SetupDiBuildDriverInfoList(
             LPCWSTR filename;
             LPWSTR pFullFilename;
 
-            if (InstallParams.Flags & DI_ENUMSINGLEINF)
-            {
-                FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
-                if (!FullInfFileName)
-                    goto done;
-                pFullFilename = &FullInfFileName[0];
-            }
-            else if (*InstallParams.DriverPath)
+            if (!(InstallParams.Flags & DI_ENUMSINGLEINF) && *InstallParams.DriverPath)
             {
                 DWORD len;
                 len = GetFullPathNameW(InstallParams.DriverPath, 0, NULL, NULL);
                 if (len == 0)
                     goto done;
-                FullInfFileName = HeapAlloc(GetProcessHeap(), 0, len + MAX_PATH);
+                FullInfFileName = HeapAlloc(GetProcessHeap(), 0, (len + 1 + MAX_PATH) * sizeof(WCHAR));
                 if (!FullInfFileName)
                     goto done;
                 len = GetFullPathNameW(InstallParams.DriverPath, len, FullInfFileName, NULL);
@@ -6047,7 +6039,7 @@ SetupDiBuildDriverInfoList(
             }
             else
             {
-                FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
+                FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
                 if (!FullInfFileName)
                     goto done;
                 pFullFilename = &FullInfFileName[0];
@@ -8048,7 +8040,7 @@ SetupDiInstallDevice(
     pSectionName = &SectionName[strlenW(SectionName)];
 
     /* Get information from [Version] section */
-    if (!SetupDiGetINFClassW(SelectedDriver->InfFileDetails->FullInfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
+    if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
         goto cleanup;
     /* Format ClassGuid to a string */
     if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
@@ -8065,6 +8057,35 @@ SetupDiInstallDevice(
     lpFullGuidString[RequiredSize + 1] = '}';
     lpFullGuidString[RequiredSize + 2] = '\0';
 
+    /* Copy .inf file to Inf\ directory (if needed) */
+    Result = InfIsFromOEMLocation(SelectedDriver->Details.InfFileName, &NeedtoCopyFile);
+    if (!Result)
+        goto cleanup;
+    if (NeedtoCopyFile)
+    {
+        WCHAR NewFileName[MAX_PATH];
+        struct InfFileDetails *newInfFileDetails;
+        Result = SetupCopyOEMInfW(
+            SelectedDriver->Details.InfFileName,
+            NULL,
+            SPOST_NONE,
+            SP_COPY_NOOVERWRITE,
+            NewFileName, MAX_PATH,
+            NULL,
+            NULL);
+        if (!Result)
+            goto cleanup;
+        /* Create a new struct InfFileDetails, and set it to
+         * SelectedDriver->InfFileDetails, to release use of
+         * current InfFile */
+        newInfFileDetails = CreateInfFileDetails(NewFileName);
+        if (!newInfFileDetails)
+            goto cleanup;
+        DereferenceInfFile(SelectedDriver->InfFileDetails);
+        SelectedDriver->InfFileDetails = newInfFileDetails;
+        strcpyW(SelectedDriver->Details.InfFileName, NewFileName);
+    }
+
     /* Open/Create driver key information */
 #if _WIN32_WINNT >= 0x502
     hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
@@ -8105,7 +8126,7 @@ SetupDiInstallDevice(
     TRACE("DriverDate      : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
     TRACE("DriverDesc      : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
     TRACE("DriverVersion   : '%u.%u.%u.%u'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
-    TRACE("InfPath         : '%s'\n", debugstr_w(SelectedDriver->Details.InfFileName));
+    TRACE("InfPath         : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName));
     TRACE("InfSection      : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName));
     TRACE("InfSectionExt   : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)]));
     TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId));
@@ -8122,7 +8143,7 @@ SetupDiInstallDevice(
         rc = RegSetValueEx(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
     }
     if (rc == ERROR_SUCCESS)
-        rc = RegSetValueEx(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.InfFileName, (strlenW(SelectedDriver->Details.InfFileName) + 1) * sizeof(WCHAR));
+        rc = RegSetValueEx(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->InfFileDetails->FileName, (strlenW(SelectedDriver->InfFileDetails->FileName) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
         rc = RegSetValueEx(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
     if (rc == ERROR_SUCCESS)
@@ -8156,26 +8177,6 @@ SetupDiInstallDevice(
     if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
         RebootRequired = TRUE;
 
-    /* Copy .inf file to Inf\ directory (if needed) */
-    Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
-    if (!Result)
-        goto cleanup;
-    if (NeedtoCopyFile)
-    {
-        Result = SetupCopyOEMInfW(
-            SelectedDriver->InfFileDetails->FullInfFileName,
-            NULL,
-            SPOST_NONE,
-            SP_COPY_NOOVERWRITE,
-            NULL, 0,
-            NULL,
-            NULL);
-        if (!Result)
-            goto cleanup;
-        /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
-         * to release use of current InfFile */
-    }
-
     /* Open device registry key */
     hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
     if (hKey == INVALID_HANDLE_VALUE)
index 79d0abe..8174f62 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
 
+/* Unicode constants */
+static const WCHAR BackSlash[] = {'\\',0};
+static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
+
 /* info passed to callback functions dealing with files */
 struct files_callback_info
 {
@@ -1661,3 +1665,157 @@ cleanup:
     TRACE("Returning %d\n", ret);
     return ret;
 }
+
+/***********************************************************************
+ *             SetupCopyOEMInfW  (SETUPAPI.@)
+ */
+BOOL WINAPI SetupCopyOEMInfW(
+        IN PCWSTR SourceInfFileName,
+        IN PCWSTR OEMSourceMediaLocation,
+        IN DWORD OEMSourceMediaType,
+        IN DWORD CopyStyle,
+        OUT PWSTR DestinationInfFileName OPTIONAL,
+        IN DWORD DestinationInfFileNameSize,
+        OUT PDWORD RequiredSize OPTIONAL,
+        OUT PWSTR* DestinationInfFileNameComponent OPTIONAL)
+{
+    BOOL ret = FALSE;
+
+    TRACE("%s %s 0x%lx 0x%lx %p 0%lu %p %p\n",
+        debugstr_w(SourceInfFileName), debugstr_w(OEMSourceMediaLocation), OEMSourceMediaType,
+        CopyStyle, DestinationInfFileName, DestinationInfFileNameSize,
+        RequiredSize, DestinationInfFileNameComponent);
+
+    if (!SourceInfFileName)
+        SetLastError(ERROR_INVALID_PARAMETER);
+    else if (OEMSourceMediaType != SPOST_NONE && OEMSourceMediaType != SPOST_PATH && OEMSourceMediaType != SPOST_URL)
+        SetLastError(ERROR_INVALID_PARAMETER);
+    else if (CopyStyle & ~(SP_COPY_DELETESOURCE | SP_COPY_REPLACEONLY | SP_COPY_NOOVERWRITE | SP_COPY_OEMINF_CATALOG_ONLY))
+    {
+        TRACE("Unknown flags: 0x%08lx\n", CopyStyle & ~(SP_COPY_DELETESOURCE | SP_COPY_REPLACEONLY | SP_COPY_NOOVERWRITE | SP_COPY_OEMINF_CATALOG_ONLY));
+        SetLastError(ERROR_INVALID_FLAGS);
+    }
+    else if (!DestinationInfFileName && DestinationInfFileNameSize > 0)
+        SetLastError(ERROR_INVALID_PARAMETER);
+    else if (CopyStyle & SP_COPY_OEMINF_CATALOG_ONLY)
+    {
+        FIXME("CopyStyle 0x%lx not supported\n", SP_COPY_OEMINF_CATALOG_ONLY);
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    }
+    else
+    {
+        HANDLE hSearch = INVALID_HANDLE_VALUE;
+        WIN32_FIND_DATAW FindFileData;
+        BOOL AlreadyExists;
+        DWORD NextFreeNumber = 0;
+        SIZE_T len;
+        LPWSTR pFullFileName = NULL;
+        LPWSTR pFileName; /* Pointer into pFullFileName buffer */
+
+        if (OEMSourceMediaType == SPOST_PATH || OEMSourceMediaType == SPOST_URL)
+            FIXME("OEMSourceMediaType 0x%lx ignored\n", OEMSourceMediaType);
+
+        /* Search if the specified .inf file already exists in %WINDIR%\Inf */
+        AlreadyExists = FALSE; /* FIXME */
+
+        if (!AlreadyExists && CopyStyle & SP_COPY_REPLACEONLY)
+        {
+            /* FIXME: set DestinationInfFileName, RequiredSize, DestinationInfFileNameComponent */
+            SetLastError(ERROR_FILE_NOT_FOUND);
+            goto cleanup;
+        }
+        else if (AlreadyExists && (CopyStyle & SP_COPY_NOOVERWRITE))
+        {
+            //SetLastError(ERROR_FILE_EXISTS);
+            /* FIXME: set return fields */
+            SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+            FIXME("File already exists. Need to return its name!\n");
+            goto cleanup;
+        }
+
+        /* Search the number to give to OEM??.INF */
+        len = MAX_PATH + 1 + strlenW(InfDirectory) + 13;
+        pFullFileName = MyMalloc(len * sizeof(WCHAR));
+        if (!pFullFileName)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto cleanup;
+        }
+        len = GetSystemWindowsDirectoryW(pFullFileName, MAX_PATH);
+        if (len == 0 || len > MAX_PATH)
+            goto cleanup;
+        if (pFullFileName[strlenW(pFullFileName) - 1] != '\\')
+            strcatW(pFullFileName, BackSlash);
+        strcatW(pFullFileName, InfDirectory);
+        pFileName = &pFullFileName[strlenW(pFullFileName)];
+        sprintfW(pFileName, L"oem*.inf", NextFreeNumber);
+        hSearch = FindFirstFileW(pFullFileName, &FindFileData);
+        if (hSearch == INVALID_HANDLE_VALUE)
+        {
+            if (GetLastError() != ERROR_FILE_NOT_FOUND)
+                goto cleanup;
+        }
+        else
+        {
+            do
+            {
+                DWORD CurrentNumber;
+                if (swscanf(FindFileData.cFileName, L"oem%lu.inf", &CurrentNumber) == 1
+                    && CurrentNumber <= 99999)
+                {
+                    NextFreeNumber = CurrentNumber + 1;
+                }
+            } while (FindNextFile(hSearch, &FindFileData));
+        }
+
+        if (NextFreeNumber > 99999)
+        {
+            ERR("Too much custom .inf files\n");
+            SetLastError(ERROR_GEN_FAILURE);
+            goto cleanup;
+        }
+
+        /* Create the full path: %WINDIR%\Inf\OEM{XXXXX}.inf */
+        sprintfW(pFileName, L"oem%lu.inf", NextFreeNumber);
+        TRACE("Next available file is %s\n", debugstr_w(pFileName));
+
+        if (RequiredSize)
+            *RequiredSize = len;
+        if (DestinationInfFileName)
+        {
+            if (DestinationInfFileNameSize < len)
+            {
+                SetLastError(ERROR_INSUFFICIENT_BUFFER);
+                goto cleanup;
+            }
+            strcpyW(DestinationInfFileName, pFullFileName);
+            if (DestinationInfFileNameComponent)
+                *DestinationInfFileNameComponent = &DestinationInfFileName[pFileName - pFullFileName];
+        }
+
+        if (!CopyFileW(SourceInfFileName, pFullFileName, TRUE))
+        {
+            TRACE("CopyFileW() failed with error 0x%lx\n", GetLastError());
+            goto cleanup;
+        }
+
+        if (CopyStyle & SP_COPY_DELETESOURCE)
+        {
+            if (!DeleteFileW(SourceInfFileName))
+            {
+                TRACE("DeleteFileW() failed with error 0x%lx\n", GetLastError());
+                goto cleanup;
+            }
+        }
+
+        ret = TRUE;
+
+cleanup:
+        if (hSearch != INVALID_HANDLE_VALUE)
+            FindClose(hSearch);
+        MyFree(pFullFileName);
+    }
+
+    TRACE("Returning %d\n", ret);
+    return ret;
+}
index 0e8386c..de3c7a9 100644 (file)
@@ -78,10 +78,9 @@ struct InfFileDetails
      * be NULL if the file is already in %SYSTEMROOT%\Inf.
      * Points into szData at then end of the structure */
     PCWSTR DirectoryName;
-    /* Contains the full file name of the .inf file. However, the directory
-     * part may be missing if the file is already in %SYSTEMROOT%\Inf.
+    /* Contains the .inf file name (without directory name).
      * Points into szData at then end of the structure */
-    PCWSTR FullInfFileName;
+    PCWSTR FileName;
 
     WCHAR szData[ANYSIZE_ARRAY];
 };
index e8a4a4b..0c22d74 100644 (file)
@@ -50,21 +50,6 @@ BOOL WINAPI SetupDiGetDeviceInfoListDetailA(HDEVINFO devinfo, PSP_DEVINFO_LIST_D
   return FALSE;
 }
 
-/***********************************************************************
- *      SetupCopyOEMInfW  (SETUPAPI.@)
- */
-BOOL WINAPI SetupCopyOEMInfW(PCWSTR sourceinffile, PCWSTR sourcemedialoc,
-                DWORD mediatype, DWORD copystyle, PWSTR destinfname,
-                DWORD destnamesize, PDWORD required,
-                PWSTR *destinfnamecomponent)
-{
-  FIXME("%s %s 0x%lx 0x%lx\n", debugstr_w(sourceinffile), debugstr_w(sourcemedialoc), mediatype, copystyle);
-  FIXME("stub: source %s location %s ...\n", debugstr_w(sourceinffile),
-        debugstr_w(sourcemedialoc));
-  //return FALSE;
-  return TRUE;
-}
-
 /***********************************************************************
  *             SetupInitializeFileLogW(SETUPAPI.@)
  */