484 lines
10 KiB
C
484 lines
10 KiB
C
/*++
|
||
|
||
Copyright (c) 1998-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
sif.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the following routines for manipulating the sif file in
|
||
which Plug and Play migration data will be stored:
|
||
|
||
AsrCreatePnpStateFileW
|
||
AsrCreatePnpStateFileA
|
||
|
||
Author:
|
||
|
||
Jim Cavalaris (jamesca) 07-Mar-2000
|
||
|
||
Environment:
|
||
|
||
User-mode only.
|
||
|
||
Revision History:
|
||
|
||
07-March-2000 jamesca
|
||
|
||
Creation and initial implementation.
|
||
|
||
--*/
|
||
|
||
|
||
//
|
||
// includes
|
||
//
|
||
#include "precomp.h"
|
||
#include "debug.h"
|
||
#include "pnpsif.h"
|
||
|
||
#include <pnpmgr.h>
|
||
#include <setupbat.h>
|
||
|
||
|
||
//
|
||
// definitions
|
||
//
|
||
|
||
// Maximum length of a line in the sif file
|
||
#define MAX_SIF_LINE 4096
|
||
|
||
|
||
//
|
||
// private prototypes
|
||
//
|
||
|
||
BOOL
|
||
CreateSifFileW(
|
||
IN PCWSTR FilePath,
|
||
IN BOOL CreateNew,
|
||
OUT LPHANDLE SifHandle
|
||
);
|
||
|
||
BOOL
|
||
WriteSifSection(
|
||
IN CONST HANDLE SifHandle,
|
||
IN PCTSTR SectionName,
|
||
IN PCTSTR SectionData,
|
||
IN BOOL Ansi
|
||
);
|
||
|
||
|
||
//
|
||
// routines
|
||
//
|
||
|
||
|
||
BOOL
|
||
AsrCreatePnpStateFileW(
|
||
IN PCWSTR lpFilePath
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates the ASR PNP state file (asrpnp.sif) at the specified file-path
|
||
during an ASR backup operation. This sif file is retrieved from the ASR
|
||
floppy disk during the setupldr phase of a clean install, and in used during
|
||
text mode setup.
|
||
|
||
Arguments:
|
||
|
||
lpFilePath - Specifies the path to the file where the state file is to be
|
||
created.
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE otherwise. Upon failure, additional information
|
||
can be retrieved by calling GetLastError().
|
||
|
||
--*/
|
||
{
|
||
BOOL result = TRUE;
|
||
BOOL bAnsiSif = TRUE; // always write ANSI sif files.
|
||
LPTSTR buffer = NULL;
|
||
HANDLE sifHandle = NULL;
|
||
|
||
//
|
||
// Create an empty sif file using the supplied path name.
|
||
//
|
||
result = CreateSifFileW(lpFilePath,
|
||
TRUE, // create a new asrpnp.sif file
|
||
&sifHandle);
|
||
if (!result) {
|
||
//
|
||
// LastError already set by CreateSifFile.
|
||
//
|
||
DBGTRACE( DBGF_ERRORS,
|
||
(TEXT("AsrCreatePnpStateFile: CreateSifFileW failed for file %ws, error=0x%08lx\n"),
|
||
lpFilePath, GetLastError()));
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Do the device instance migration stuff...
|
||
//
|
||
if (MigrateDeviceInstanceData(&buffer)) {
|
||
|
||
//
|
||
// Write the device instance section to the sif file.
|
||
//
|
||
result = WriteSifSection(sifHandle,
|
||
WINNT_DEVICEINSTANCES,
|
||
buffer,
|
||
bAnsiSif); // Write sif section as ANSI
|
||
if (!result) {
|
||
DBGTRACE( DBGF_ERRORS,
|
||
(TEXT("AsrCreatePnpStateFile: WriteSifSection failed for [%s], error=0x%08lx\n"),
|
||
WINNT_DEVICEINSTANCES, GetLastError()));
|
||
}
|
||
|
||
//
|
||
// Free the allocated buffer.
|
||
//
|
||
LocalFree(buffer);
|
||
buffer = NULL;
|
||
|
||
} else {
|
||
DBGTRACE( DBGF_ERRORS,
|
||
(TEXT("AsrCreatePnpStateFile: MigrateDeviceInstanceData failed, error=0x%08lx\n"),
|
||
GetLastError()));
|
||
}
|
||
|
||
//
|
||
// Do the class key migration stuff...
|
||
//
|
||
if (MigrateClassKeys(&buffer)) {
|
||
|
||
//
|
||
// Write the class key section to the sif file.
|
||
//
|
||
result = WriteSifSection(sifHandle,
|
||
WINNT_CLASSKEYS,
|
||
buffer,
|
||
bAnsiSif); // Write sif section as ANSI
|
||
|
||
if (!result) {
|
||
DBGTRACE( DBGF_ERRORS,
|
||
(TEXT("AsrCreatePnpStateFile: WriteSifSection failed for [%s], error=0x%08lx\n"),
|
||
WINNT_CLASSKEYS, GetLastError()));
|
||
}
|
||
|
||
//
|
||
// Free the allocated buffer.
|
||
//
|
||
LocalFree(buffer);
|
||
buffer = NULL;
|
||
} else {
|
||
DBGTRACE( DBGF_ERRORS,
|
||
(TEXT("AsrCreatePnpStateFile: MigrateClassKeys failed, error=0x%08lx\n"),
|
||
GetLastError()));
|
||
}
|
||
|
||
|
||
//
|
||
// Do the hash value migration stuff...
|
||
//
|
||
if (MigrateHashValues(&buffer)) {
|
||
|
||
//
|
||
// Write the hash value section to the sif file.
|
||
//
|
||
result = WriteSifSection(sifHandle,
|
||
WINNT_DEVICEHASHVALUES,
|
||
buffer,
|
||
bAnsiSif); // Write sif section as ANSI?
|
||
if (!result) {
|
||
DBGTRACE( DBGF_ERRORS,
|
||
(TEXT("AsrCreatePnpStateFile: WriteSifSection failed for [%s], error=0x%08lx\n"),
|
||
WINNT_DEVICEHASHVALUES, GetLastError()));
|
||
}
|
||
|
||
//
|
||
// Free the allocated buffer.
|
||
//
|
||
LocalFree(buffer);
|
||
buffer = NULL;
|
||
} else {
|
||
DBGTRACE( DBGF_ERRORS,
|
||
(TEXT("AsrCreatePnpStateFile: MigrateHashValues failed, error=0x%08lx\n"),
|
||
GetLastError()));
|
||
}
|
||
|
||
//
|
||
// Close the sif file.
|
||
//
|
||
if (sifHandle) {
|
||
CloseHandle(sifHandle);
|
||
}
|
||
|
||
//
|
||
// Reset the last error as successful in case we encountered a non-fatal
|
||
// error along the way.
|
||
//
|
||
SetLastError(ERROR_SUCCESS);
|
||
return TRUE;
|
||
|
||
} // AsrCreatePnpStateFile()
|
||
|
||
|
||
|
||
BOOL
|
||
AsrCreatePnpStateFileA(
|
||
IN PCSTR lpFilePath
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
None.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
|
||
--*/
|
||
{
|
||
WCHAR wszFilePath[MAX_PATH + 1];
|
||
|
||
|
||
//
|
||
// Validate arguments.
|
||
//
|
||
if (!ARGUMENT_PRESENT(lpFilePath) ||
|
||
strlen(lpFilePath) > MAX_PATH) {
|
||
SetLastError(ERROR_INVALID_PARAMETER);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Convert the file path to a wide string.
|
||
//
|
||
memset(wszFilePath, 0, MAX_PATH + 1);
|
||
|
||
if (!(MultiByteToWideChar(CP_ACP,
|
||
0,
|
||
lpFilePath,
|
||
-1,
|
||
wszFilePath,
|
||
MAX_PATH + 1))) {
|
||
SetLastError(ERROR_INVALID_PARAMETER);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Return the result of calling the wide char version
|
||
//
|
||
return AsrCreatePnpStateFileW(wszFilePath);
|
||
|
||
} // AsrCreatePnpStateFileA()
|
||
|
||
|
||
|
||
BOOL
|
||
CreateSifFileW(
|
||
IN PCWSTR lpFilePath,
|
||
IN BOOL bCreateNew,
|
||
OUT LPHANDLE lpSifHandle
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
None.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
|
||
--*/
|
||
{
|
||
HANDLE sifhandle = NULL;
|
||
|
||
|
||
//
|
||
// Validate arguments.
|
||
//
|
||
if (!ARGUMENT_PRESENT(lpFilePath) ||
|
||
(wcslen(lpFilePath) > MAX_PATH) ||
|
||
!ARGUMENT_PRESENT(lpSifHandle)) {
|
||
SetLastError(ERROR_INVALID_PARAMETER);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Initialize output paramaters.
|
||
//
|
||
*lpSifHandle = NULL;
|
||
|
||
//
|
||
// Create the file. The handle will be closed by the caller, once they are
|
||
// finished with it.
|
||
//
|
||
sifhandle = CreateFileW(lpFilePath,
|
||
GENERIC_WRITE | GENERIC_READ,
|
||
FILE_SHARE_READ,
|
||
NULL,
|
||
bCreateNew ? CREATE_ALWAYS : OPEN_EXISTING,
|
||
FILE_FLAG_BACKUP_SEMANTICS,
|
||
NULL);
|
||
|
||
if ((sifhandle == NULL) ||
|
||
(sifhandle == INVALID_HANDLE_VALUE)) {
|
||
//
|
||
// LastError already set by CreateFile.
|
||
//
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Return the sif handle to the caller only if successful.
|
||
//
|
||
*lpSifHandle = sifhandle;
|
||
return TRUE;
|
||
|
||
} // CreateSifFileW()
|
||
|
||
|
||
|
||
BOOL
|
||
WriteSifSection(
|
||
IN CONST HANDLE SifHandle,
|
||
IN PCTSTR SectionName,
|
||
IN PCTSTR SectionData,
|
||
IN BOOL Ansi
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
None.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
|
||
--*/
|
||
{
|
||
BYTE buffer[(MAX_SIF_LINE+1)*sizeof(WCHAR)];
|
||
DWORD dwSize, dwTempSize;
|
||
PCTSTR p;
|
||
|
||
|
||
//
|
||
// Validate the arguments
|
||
//
|
||
if (!ARGUMENT_PRESENT(SifHandle) ||
|
||
!ARGUMENT_PRESENT(SectionName) ||
|
||
!ARGUMENT_PRESENT(SectionData)) {
|
||
SetLastError(ERROR_INVALID_PARAMETER);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Write the section name to the sif file.
|
||
//
|
||
if (Ansi) {
|
||
//
|
||
// Write ANSI strings to the sif file
|
||
//
|
||
#if UNICODE
|
||
wsprintfA((LPSTR)buffer, (LPCSTR)"[%ls]\r\n", SectionName);
|
||
#else // ANSI
|
||
wsprintfA((LPSTR)buffer, (LPCSTR)"[%s]\r\n", SectionName);
|
||
#endif // UNICODE/ANSI
|
||
dwSize = strlen((PSTR)buffer);
|
||
} else {
|
||
//
|
||
// Write Unicode strings to the sif file
|
||
//
|
||
#if UNICODE
|
||
wsprintfW((LPWSTR)buffer, (LPCWSTR)L"[%ws]\r\n", SectionName);
|
||
#else // ANSI
|
||
wsprintfW((LPWSTR)buffer, (LPCWSTR)L"[%S]\r\n", SectionName);
|
||
#endif // UNICODE/ANSI
|
||
dwSize = wcslen((PWSTR)buffer) * sizeof(WCHAR);
|
||
}
|
||
|
||
if (!WriteFile(SifHandle, buffer, dwSize, &dwTempSize, NULL)) {
|
||
//
|
||
// LastError already set by WriteFile
|
||
//
|
||
return FALSE;
|
||
}
|
||
|
||
DBGTRACE( DBGF_INFO,
|
||
(TEXT("[%s]\n"), SectionName));
|
||
|
||
|
||
//
|
||
// Write the multi-sz section data to the file.
|
||
//
|
||
p = SectionData;
|
||
while (*p) {
|
||
if (Ansi) {
|
||
//
|
||
// Write ANSI strings to the sif file
|
||
//
|
||
#if UNICODE
|
||
wsprintfA((LPSTR)buffer, (LPCSTR)"%ls\r\n", p);
|
||
#else // ANSI
|
||
wsprintfA((LPSTR)buffer, (LPCSTR)"%s\r\n", p);
|
||
#endif // UNICODE/ANSI
|
||
dwSize = strlen((PSTR)buffer);
|
||
} else {
|
||
//
|
||
// Write Unicode strings to the sif file
|
||
//
|
||
#if UNICODE
|
||
wsprintfW((LPWSTR)buffer, (LPCWSTR)L"%ws\r\n", p);
|
||
#else // ANSI
|
||
wsprintfW((LPWSTR)buffer, (LPCWSTR)L"%S\r\n", p);
|
||
#endif // UNICODE/ANSI
|
||
dwSize = wcslen((PWSTR)buffer) * sizeof(WCHAR);
|
||
}
|
||
|
||
if (!WriteFile(SifHandle, buffer, dwSize, &dwTempSize, NULL)) {
|
||
//
|
||
// LastError already set by WriteFile
|
||
//
|
||
return FALSE;
|
||
}
|
||
|
||
DBGTRACE( DBGF_INFO,
|
||
(TEXT("%s\n"), p));
|
||
|
||
//
|
||
// Find the next string in the multi-sz
|
||
//
|
||
p += lstrlen(p) + 1;
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
} // WriteSifSection()
|
||
|
||
|
||
|