From 05875a2c6d33f2592f21ce76ddbd2d14f11cdab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Mon, 29 May 2006 13:32:51 +0000 Subject: [PATCH] - Implement SetupCopyOEMInfW - 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 | 95 +++++------ reactos/dll/win32/setupapi/install.c | 158 ++++++++++++++++++ reactos/dll/win32/setupapi/setupapi_private.h | 5 +- reactos/dll/win32/setupapi/stubs.c | 15 -- 4 files changed, 208 insertions(+), 65 deletions(-) diff --git a/reactos/dll/win32/setupapi/devinst.c b/reactos/dll/win32/setupapi/devinst.c index 264144cab49..4870407d432 100644 --- a/reactos/dll/win32/setupapi/devinst.c +++ b/reactos/dll/win32/setupapi/devinst.c @@ -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) diff --git a/reactos/dll/win32/setupapi/install.c b/reactos/dll/win32/setupapi/install.c index 79d0abe77c2..8174f623ce6 100644 --- a/reactos/dll/win32/setupapi/install.c +++ b/reactos/dll/win32/setupapi/install.c @@ -23,6 +23,10 @@ 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; +} diff --git a/reactos/dll/win32/setupapi/setupapi_private.h b/reactos/dll/win32/setupapi/setupapi_private.h index 0e8386cc103..de3c7a931d8 100644 --- a/reactos/dll/win32/setupapi/setupapi_private.h +++ b/reactos/dll/win32/setupapi/setupapi_private.h @@ -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]; }; diff --git a/reactos/dll/win32/setupapi/stubs.c b/reactos/dll/win32/setupapi/stubs.c index e8a4a4b9962..0c22d743e9d 100644 --- a/reactos/dll/win32/setupapi/stubs.c +++ b/reactos/dll/win32/setupapi/stubs.c @@ -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.@) */