Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

567 lines
13 KiB

#include "precomp.h"
#pragma hdrstop
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
restore.c
Abstract:
Routines related to generating the restore diskette(s), and for
logging files to be deleted at next boot.
Author:
Ted Miller (tedm) 6-April-1992
Revision History:
--*/
//
// Defining this symbol causes us to not treat files in the config
// directory specially when it comes to logging files that are copied by
// GUI Setup. We don't do anything special for them because text setup
// copies the registry hives that are relevent for the repair process.
//
#define LOG_CONFIG_DIR_FILES
extern HWND hwndFrame;
extern PSTR LOCAL_SOURCE_DIRECTORY;
PSTR SETUP_LOG_FILE = "\\setup.log";
PSTR SETUP_REPAIR_DIRECTORY = "\\repair";
CHAR _LogFileName[MAX_PATH + 1];
BOOLEAN _LogFileNameInitialized = FALSE;
BOOL _LogStartedByCommand;
BOOL
InsertSpecialBootCode(
IN TCHAR Drive
);
VOID
ValidateAndChecksumFile(
IN PSTR Filename,
OUT PBOOLEAN IsNtImage,
OUT PULONG Checksum,
OUT PBOOLEAN Valid
);
VOID
InitRestoreDiskLogging(
IN BOOL StartedByCommand
)
/*++
Routine Description:
Initialize the restore-diskette generation and file copy logging
module.
Arguments:
StartedByCommand - specifies whether this command was invoked explicitly
from the INF file via an InitRestoreDiskLog command.
Return Value:
None.
--*/
{
//
// We need to know whether the INF file explicitly invoked this command,
// because if it didn't, we'll need to set the S-H-R attributes on setup.log
// ourselves.
//
_LogStartedByCommand = StartedByCommand;
GetWindowsDirectory( _LogFileName, sizeof(_LogFileName) );
strcat( _LogFileName, SETUP_REPAIR_DIRECTORY );
strcat( _LogFileName, SETUP_LOG_FILE );
_LogFileNameInitialized = TRUE;
}
VOID
RestoreDiskLoggingDone(
VOID
)
/*++
Routine Description:
Checks to see if logging was initiated explicitly from the INF file. If it wasn't,
then the S-H-R attributes of the log file (setup.log) are set. Otherwise, we leave
the file alone (we expect the INF file to make a subsequent call to TermRestoreDiskLogging).
Arguments:
None.
Return Value:
None.
--*/
{
if(_LogFileNameInitialized && !_LogStartedByCommand) {
SetFileAttributes(_LogFileName,
FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_READONLY |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_ARCHIVE
);
}
}
VOID
TermRestoreDiskLogging(
VOID
)
/*++
Routine Description:
Terminate the log process, by logging in setup.log the following files:
autoexec.nt and config.nt.
Also change attributes of setup.log in the repair directory.
Arguments:
None.
Return Value:
None.
--*/
{
HANDLE Handle;
WIN32_FIND_DATA FindData;
CHAR SystemDirectory[MAX_PATH];
CHAR SourceFileName[MAX_PATH];
CHAR Buffer[ MAX_PATH ];
BOOLEAN IsValid;
BOOLEAN IsNtImage;
ULONG Checksum;
ULONG i;
PSTR FileList[] = { "autoexec.nt",
"config.nt"
};
Handle = FindFirstFile( _LogFileName,
&FindData );
if( Handle != INVALID_HANDLE_VALUE ) {
FindClose( Handle );
if( !GetSystemDirectory( SystemDirectory, sizeof(SystemDirectory) )) {
return;
}
for(i=0; i < sizeof(FileList)/sizeof(PSTR); i++) {
strcpy( SourceFileName, SystemDirectory );
strcat( SourceFileName, "\\" );
strcat( SourceFileName, FileList[i] );
//
// Log the file in a special section of setup.log
//
ValidateAndChecksumFile( SourceFileName,
&IsNtImage,
&Checksum,
&IsValid );
sprintf( Buffer,
"\"%s\",\"%lx\"",
FileList[i],
Checksum
);
WritePrivateProfileString( "Files.InRepairDirectory",
SourceFileName + 2,
Buffer,
_LogFileName );
}
SetFileAttributes(_LogFileName,
FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_READONLY |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_ARCHIVE
);
}
}
VOID
LogOneFile(
IN PCHAR SrcFullname,
IN PCHAR DstFullname,
IN PCHAR DiskDescription,
IN ULONG Checksum,
IN PCHAR DiskTag,
IN BOOL ThirdPartyFile
)
/*++
Routine Description:
Log a file that was just copied. If the general copy source is a
CD-ROM and the file is from a: or b:, it is marked 'floppy' in the
log. If the file is coming from the network, it is not logged.
If the file is being copied to the boot volume and the boot volume is
different than the NT volume, the file is not logged.
Arguments:
SrcFullname - fully qualified name of the source file.
DstFullname - fully qulaified name of the file as it is called on
the target volume.
DiskDescription - text description of the source diskette/CD containing
the file.
Checksum - checksum of the target file.
Return Value:
None.
--*/
{
static BOOL FoundSymbols = FALSE;
static UINT GeneralSourceDriveType;
static PCHAR GeneralSource;
static CHAR GeneralTarget[MAX_PATH + 3];
#ifndef LOG_CONFIG_DIR_FILES
static ConfigDir;
static ULONG ConfigDirLen;
#endif
#if 0
UINT ThisFileSourceDriveType;
#endif
CHAR temp[4];
CHAR Buffer[256];
ULONG RetryCount;
BOOL Success;
//
// If we haven't already, locate static info, like the general source
// and target directories, etc.
//
if(!FoundSymbols) {
GeneralSource = SzFindSymbolValueInSymTab("!STF_SRCDIR");
GetWindowsDirectory( GeneralTarget, sizeof( GeneralTarget ) / sizeof( CHAR ));
#ifndef LOG_CONFIG_DIR_FILES
ConfigDir = SzFindSymbolValueInSymTab("!STF_CONFIGPATH");
ConfigDirLen = lstrlen(ConfigDir);
#endif
strncpy(temp,GeneralSource,3);
temp[3] = 0;
GeneralSourceDriveType = GetDriveType(temp);
FoundSymbols = TRUE;
}
//
// Determine the full path of the setup log file, if not yet done
//
if( !_LogFileNameInitialized ) {
InitRestoreDiskLogging(FALSE);
}
//
// If the file is being copied from a UNC path, don't log it.
//
if(!strncmp(SrcFullname,"\\\\",2) ||
(GeneralSourceDriveType == DRIVE_REMOTE) ) {
return;
}
//
// If the file is not being copied to the NT volume, don't log it.
//
if(toupper(*DstFullname) != toupper(GeneralTarget[0])) {
return;
}
#ifndef LOG_CONFIG_DIR_FILES
//
// If the file is being copied to the config directory, don't log it.
//
if(!_strnicmp(ConfigDir,DstFullname,ConfigDirLen)) {
return;
}
#endif
//
// Make sure the left hand side of the equals has quotes around it if
// there are spaces in the filename.
//
if(strchr(DstFullname+2,' ')) {
GeneralTarget[0] = '\"';
lstrcpyn(&GeneralTarget[1],DstFullname+2,MAX_PATH);
lstrcat(GeneralTarget,"\"");
} else {
lstrcpyn(GeneralTarget,DstFullname+2,MAX_PATH);
}
//
// Write a line into the log file.
//
if( ThirdPartyFile ) {
CHAR FullSrcName[260];
PCHAR FileName;
PCHAR DirectoryName;
PCHAR p;
//
// This is a third party file
//
sprintf( FullSrcName, "%s", SrcFullname );
CharLowerBuff( FullSrcName, lstrlen( FullSrcName ) );
if( ( FileName = strrchr( FullSrcName, (int)'\\' ) ) == FullSrcName + 2 ) {
DirectoryName = "\\";
} else {
if( FileName ) {
*FileName = '\0';
}
DirectoryName = FullSrcName + 2;
if( (p = strstr( DirectoryName, "drvlib.nic" )) != NULL ) {
//
// We want to convert \...\drvlib.nic\Directory\Subdir
// into \Subdir
//
p += strlen( "drvlib.nic" ) + 1;
p = strchr( p, '\\' );
if( p != NULL ) {
DirectoryName = p;
} else {
DirectoryName = "\\";
}
}
}
sprintf( Buffer,
"\"%s\",\"%lx\",\"%s\",\"%s\",\"%s\"",
FileName + 1,
Checksum,
DirectoryName,
DiskDescription,
(DiskTag)? DiskTag : ""
);
} else {
sprintf( Buffer,
"\"%s\",\"%lx\"",
strrchr( SrcFullname + 2, (int)'\\' ) + 1,
Checksum
);
}
for(RetryCount = 0, Success = FALSE;
!Success && (RetryCount < 2);
RetryCount++)
{
Success = WritePrivateProfileString("Files.WinNt",
GeneralTarget,
Buffer,
_LogFileName
);
if(!(Success || RetryCount)) {
//
// The file is probably has S-H-R attributes, so we'll reset
// these and try again
//
SetFileAttributes(_LogFileName, FILE_ATTRIBUTE_NORMAL);
}
}
}
BOOL
NotifyCB(
IN PCHAR src,
IN PCHAR dst,
IN WORD code
)
{
UNREFERENCED_PARAMETER(src);
UNREFERENCED_PARAMETER(dst);
UNREFERENCED_PARAMETER(code);
return(TRUE);
}
BOOL
AddFileToDeleteList(
IN PCHAR Filename
)
/*++
Routine Description:
Add a file to the list of files to be deleted at next boot.
This involves writing a line to the opened delete log file.
Arguments:
Filename - full pathname of file to delete.
Return Value:
Always true.
--*/
{
return(MoveFileEx(Filename,NULL,MOVEFILE_REPLACE_EXISTING|MOVEFILE_DELAY_UNTIL_REBOOT));
}
//
// Bootcode to be inserted, placed into a C array. See i386\readme.
//
#include "rdskboot.c"
#define DRIVENAME_PREFIX "\\\\.\\"
BOOL
InsertSpecialBootCode(
IN TCHAR Drive
)
{
UCHAR UBuffer[1024];
PUCHAR Buffer = (PUCHAR)(((DWORD_PTR)UBuffer+512) & ~((INT_PTR)511));
HANDLE Handle;
TCHAR DriveName[(sizeof(DRIVENAME_PREFIX)/sizeof(TCHAR)) + 2];
BOOL b;
DWORD BytesXferred;
DWORD Offset;
PUCHAR MsgAddr;
wsprintf(DriveName,"%s%c:",TEXT(DRIVENAME_PREFIX),Drive);
//
// Open the drive DASD
//
Handle = CreateFile(
DriveName,
FILE_READ_DATA | FILE_WRITE_DATA,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if(Handle == INVALID_HANDLE_VALUE) {
return(FALSE);
}
//
// Read and validate the first 512 bytes from the drive.
//
b = ReadFile(Handle,Buffer,512,&BytesXferred,NULL);
if((b == FALSE)
|| (BytesXferred != 512)
|| (Buffer[0] != 0xeb)
|| (Buffer[2] != 0x90)
|| (Buffer[510] != 0x55)
|| (Buffer[511] != 0xaa))
{
CloseHandle(Handle);
return(FALSE);
}
//
// Determine the offset of the bootcode.
//
Offset = Buffer[1] + 2;
if(Offset + REPAIR_DISK_BOOTSECTOR_SIZE > 510) {
CloseHandle(Handle);
return(FALSE);
}
//
// Wipe the boot code clean and reset the signature.
//
ZeroMemory(Buffer+Offset,510-Offset);
//
// Copy the new bootcode into the sector.
//
CopyMemory(
Buffer+Offset,
REPAIR_DISK_BOOTSECTOR,
REPAIR_DISK_BOOTSECTOR_SIZE
);
//
// Calculate the offset of the message within the boot sector.
//
MsgAddr = Buffer+Offset+REPAIR_DISK_BOOTSECTOR_SIZE;
//
// Fetch the boot sector's message from our resources and
// place it into the boot sector.
//
LoadStringA(
MyDllModuleHandle, // was GetModuleHandle(NULL),
IDS_REPAIR_BOOTCODE_MSG,
MsgAddr,
510-Offset-REPAIR_DISK_BOOTSECTOR_SIZE
);
Buffer[509] = 0; // just in case.
//
// The string in the resources will be ANSI text; we want OEM text
// in the boot sector on the floppy.
//
CharToOemA(MsgAddr,MsgAddr);
//
// Seek back to the beginning of the disk and
// write the bootsector back out to disk.
//
if(SetFilePointer(Handle,0,NULL,FILE_BEGIN)) {
CloseHandle(Handle);
return(FALSE);
}
b = WriteFile(Handle,Buffer,512,&BytesXferred,NULL);
CloseHandle(Handle);
return((b == TRUE) && (BytesXferred == 512));
}