You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
721 lines
18 KiB
721 lines
18 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
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 %s, ")
|
|
TEXT("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], ")
|
|
TEXT("error=0x%08lx\n"),
|
|
WINNT_DEVICEINSTANCES, GetLastError()));
|
|
}
|
|
|
|
//
|
|
// Free the allocated buffer.
|
|
//
|
|
LocalFree(buffer);
|
|
buffer = NULL;
|
|
|
|
} else {
|
|
DBGTRACE((DBGF_ERRORS,
|
|
TEXT("AsrCreatePnpStateFile: MigrateDeviceInstanceData failed, ")
|
|
TEXT("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], ")
|
|
TEXT("error=0x%08lx\n"),
|
|
WINNT_CLASSKEYS, GetLastError()));
|
|
}
|
|
|
|
//
|
|
// Free the allocated buffer.
|
|
//
|
|
LocalFree(buffer);
|
|
buffer = NULL;
|
|
} else {
|
|
DBGTRACE((DBGF_ERRORS,
|
|
TEXT("AsrCreatePnpStateFile: MigrateClassKeys failed, ")
|
|
TEXT("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], ")
|
|
TEXT("error=0x%08lx\n"),
|
|
WINNT_DEVICEHASHVALUES, GetLastError()));
|
|
}
|
|
|
|
//
|
|
// Free the allocated buffer.
|
|
//
|
|
LocalFree(buffer);
|
|
buffer = NULL;
|
|
} else {
|
|
DBGTRACE((DBGF_ERRORS,
|
|
TEXT("AsrCreatePnpStateFile: MigrateHashValues failed, ")
|
|
TEXT("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.
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD Err = NO_ERROR;
|
|
SID_IDENTIFIER_AUTHORITY sidNtAuthority = SECURITY_NT_AUTHORITY;
|
|
PSID psidAdministrators = NULL;
|
|
PSID psidBackupOperators = NULL;
|
|
PSID psidLocalSystem = NULL;
|
|
PACL pDacl = NULL;
|
|
ULONG ulAclSize;
|
|
SECURITY_ATTRIBUTES sa;
|
|
SECURITY_DESCRIPTOR sd;
|
|
HANDLE sifhandle = NULL;
|
|
|
|
|
|
//
|
|
// Validate arguments.
|
|
//
|
|
if (!ARGUMENT_PRESENT(lpFilePath) ||
|
|
(wcslen(lpFilePath) > MAX_PATH) ||
|
|
!ARGUMENT_PRESENT(lpSifHandle)) {
|
|
Err = ERROR_INVALID_PARAMETER;
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Initialize output paramaters.
|
|
//
|
|
*lpSifHandle = NULL;
|
|
|
|
//
|
|
// Construct the security attributes for the sif file.
|
|
// Allow access for Administrators, BackupOperators, and LocalSystem.
|
|
//
|
|
if (!AllocateAndInitializeSid(
|
|
&sidNtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&psidAdministrators)) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
ASSERT(IsValidSid(psidAdministrators));
|
|
|
|
if (!AllocateAndInitializeSid(
|
|
&sidNtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_BACKUP_OPS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&psidBackupOperators)) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
ASSERT(IsValidSid(psidBackupOperators));
|
|
|
|
if (!AllocateAndInitializeSid(
|
|
&sidNtAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&psidLocalSystem)) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
ASSERT(IsValidSid(psidLocalSystem));
|
|
|
|
//
|
|
// Determine the size required for the DACL
|
|
//
|
|
ulAclSize = sizeof(ACL);
|
|
ulAclSize += sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdministrators) - sizeof(DWORD);
|
|
ulAclSize += sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidBackupOperators) - sizeof(DWORD);
|
|
ulAclSize += sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidLocalSystem) - sizeof(DWORD);
|
|
|
|
//
|
|
// Allocate and initialize the DACL
|
|
//
|
|
pDacl =(PACL)LocalAlloc(0, ulAclSize);
|
|
|
|
if (pDacl == NULL) {
|
|
Err = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Clean0;
|
|
}
|
|
|
|
if (!InitializeAcl(pDacl, ulAclSize, ACL_REVISION)) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Add an ACE to the DACL for Administrators FILE_ALL_ACCESS
|
|
//
|
|
if (!AddAccessAllowedAceEx(
|
|
pDacl,
|
|
ACL_REVISION,
|
|
0,
|
|
FILE_ALL_ACCESS,
|
|
psidAdministrators)) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Add an ACE to the DACL for BackupOperators FILE_ALL_ACCESS
|
|
//
|
|
if (!AddAccessAllowedAceEx(
|
|
pDacl,
|
|
ACL_REVISION,
|
|
0,
|
|
FILE_ALL_ACCESS,
|
|
psidBackupOperators)) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Add an ACE to the DACL for LocalSystem FILE_ALL_ACCESS
|
|
//
|
|
if (!AddAccessAllowedAceEx(
|
|
pDacl,
|
|
ACL_REVISION,
|
|
0,
|
|
FILE_ALL_ACCESS,
|
|
psidLocalSystem)) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
ASSERT(IsValidAcl(pDacl));
|
|
|
|
//
|
|
// Initialize the security descriptor
|
|
//
|
|
if (!InitializeSecurityDescriptor(
|
|
&sd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
//
|
|
// Set the new DACL in the security descriptor
|
|
//
|
|
if (!SetSecurityDescriptorDacl(
|
|
&sd, TRUE, pDacl, FALSE)) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
ASSERT(IsValidSecurityDescriptor(&sd));
|
|
|
|
//
|
|
// Add the security descriptor to the security attributes
|
|
//
|
|
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
|
|
sa.nLength = sizeof(sa);
|
|
sa.lpSecurityDescriptor = &sd;
|
|
sa.bInheritHandle = TRUE;
|
|
|
|
//
|
|
// 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,
|
|
&sa,
|
|
bCreateNew ? CREATE_ALWAYS : OPEN_EXISTING,
|
|
FILE_FLAG_BACKUP_SEMANTICS,
|
|
NULL);
|
|
|
|
if (sifhandle == INVALID_HANDLE_VALUE) {
|
|
Err = GetLastError();
|
|
goto Clean0;
|
|
}
|
|
|
|
ASSERT(sifhandle != NULL);
|
|
|
|
//
|
|
// Return the sif handle to the caller only if successful.
|
|
//
|
|
*lpSifHandle = sifhandle;
|
|
|
|
Clean0:
|
|
|
|
if (pDacl != NULL) {
|
|
LocalFree(pDacl);
|
|
}
|
|
|
|
if (psidLocalSystem != NULL) {
|
|
FreeSid(psidLocalSystem);
|
|
}
|
|
|
|
if (psidBackupOperators != NULL) {
|
|
FreeSid(psidBackupOperators);
|
|
}
|
|
|
|
if (psidAdministrators != NULL) {
|
|
FreeSid(psidAdministrators);
|
|
}
|
|
|
|
SetLastError(Err);
|
|
return(Err == NO_ERROR);
|
|
|
|
} // 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;
|
|
HRESULT hr;
|
|
|
|
|
|
//
|
|
// 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
|
|
hr = StringCbPrintfExA((LPSTR)buffer,
|
|
sizeof(buffer),
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE,
|
|
(LPCSTR)"[%ls]\r\n",
|
|
SectionName);
|
|
#else // ANSI
|
|
hr = StringCbPrintfExA((LPSTR)buffer,
|
|
sizeof(buffer),
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE,
|
|
(LPCSTR)"[%s]\r\n",
|
|
SectionName);
|
|
#endif // UNICODE/ANSI
|
|
|
|
//
|
|
// If unable to write the section name to the sif file, we can't write
|
|
// the section at all.
|
|
//
|
|
if (FAILED(hr)) {
|
|
SetLastError(ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
dwSize = (DWORD)strlen((PSTR)buffer);
|
|
} else {
|
|
//
|
|
// Write Unicode strings to the sif file
|
|
//
|
|
#if UNICODE
|
|
hr = StringCbPrintfExW((LPWSTR)buffer,
|
|
sizeof(buffer),
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE,
|
|
(LPCWSTR)L"[%ws]\r\n",
|
|
SectionName);
|
|
#else // ANSI
|
|
hr = StringCbPrintfExW((LPWSTR)buffer,
|
|
sizeof(buffer),
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE,
|
|
(LPCWSTR)L"[%S]\r\n",
|
|
SectionName);
|
|
#endif // UNICODE/ANSI
|
|
|
|
//
|
|
// If unable to write the section name to the sif file, we can't write
|
|
// the section at all.
|
|
//
|
|
if (FAILED(hr)) {
|
|
SetLastError(ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
dwSize = (DWORD)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.
|
|
//
|
|
for (p = SectionData; *p != TEXT('\0'); p += lstrlen(p) + 1) {
|
|
|
|
if (Ansi) {
|
|
//
|
|
// Write ANSI strings to the sif file
|
|
//
|
|
#if UNICODE
|
|
hr = StringCbPrintfExA((LPSTR)buffer,
|
|
sizeof(buffer),
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE,
|
|
(LPCSTR)"%ls\r\n",
|
|
p);
|
|
#else // ANSI
|
|
hr = StringCbPrintfExA((LPSTR)buffer,
|
|
sizeof(buffer),
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE,
|
|
(LPCSTR)"%s\r\n",
|
|
p);
|
|
#endif // UNICODE/ANSI
|
|
|
|
//
|
|
// If unable to write this string to the sif file, skip to the next.
|
|
//
|
|
if (FAILED(hr)) {
|
|
continue;
|
|
}
|
|
|
|
dwSize = (DWORD)strlen((PSTR)buffer);
|
|
} else {
|
|
//
|
|
// Write Unicode strings to the sif file
|
|
//
|
|
#if UNICODE
|
|
hr = StringCbPrintfExW((LPWSTR)buffer,
|
|
sizeof(buffer),
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE,
|
|
(LPCWSTR)L"%ws\r\n",
|
|
p);
|
|
#else // ANSI
|
|
hr = StringCbPrintfExW((LPWSTR)buffer,
|
|
sizeof(buffer),
|
|
NULL, NULL,
|
|
STRSAFE_NULL_ON_FAILURE,
|
|
(LPCWSTR)L"%S\r\n",
|
|
p);
|
|
#endif // UNICODE/ANSI
|
|
|
|
//
|
|
// If unable to write this string to the sif file, skip to the next.
|
|
//
|
|
if (FAILED(hr)) {
|
|
continue;
|
|
}
|
|
|
|
dwSize = (DWORD)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));
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} // WriteSifSection()
|
|
|
|
|
|
|