Leaked source code of windows server 2003
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

/*++
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()