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(
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;
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)
}
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);
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);
}
else
{
- FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
+ FullInfFileName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
if (!FullInfFileName)
goto done;
pFullFilename = &FullInfFileName[0];
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)
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);
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));
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)
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)
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
{
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;
+}