- 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
This commit is contained in:
Hervé Poussineau 2006-05-29 13:32:51 +00:00
parent d599ad5c78
commit 05875a2c6d
4 changed files with 208 additions and 65 deletions

View 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)

View file

@ -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;
}

View 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];
};

View 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.@)
*/