Windows-Server-2003/base/tools/instaler/file.c

441 lines
12 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
file.c
Abstract:
This module implements the functions to save references to files for the
INSTALER program. Part of each reference is a handle to a backup copy
of a file if the reference is a write/delete/rename.
Author:
Steve Wood (stevewo) 22-Aug-1994
Revision History:
--*/
#include "instaler.h"
BOOLEAN
CreateFileReference(
PWSTR Name,
BOOLEAN WriteAccess,
PFILE_REFERENCE *ReturnedReference
)
{
PFILE_REFERENCE p;
PWSTR BackupFileName;
WIN32_FIND_DATAW FindFileData;
HANDLE FindFileHandle;
*ReturnedReference = NULL;
p = FindFileReference( Name );
if (p != NULL) {
if (p->WriteAccess) {
*ReturnedReference = p;
return TRUE;
}
}
else {
p = AllocMem( sizeof( *p ) );
if (p == NULL) {
return FALSE;
}
InsertTailList( &FileReferenceListHead, &p->Entry );
NumberOfFileReferences += 1;
p->Name = Name;
}
BackupFileName = L"";
FindFileHandle = NULL;
if ((p->WriteAccess = WriteAccess) &&
(FindFileHandle = FindFirstFileW( p->Name, &FindFileData )) != INVALID_HANDLE_VALUE
) {
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
p->DirectoryFile = TRUE;
}
else {
p->BackupFileAttributes = FindFileData.dwFileAttributes;
p->BackupLastWriteTime = FindFileData.ftLastWriteTime;
p->BackupFileSize.LowPart = FindFileData.nFileSizeLow;
p->BackupFileSize.HighPart = FindFileData.nFileSizeHigh;
BackupFileName = CreateBackupFileName( &p->BackupFileUniqueId );
if (BackupFileName == NULL ||
!CopyFileW( Name, BackupFileName, TRUE )
) {
p->BackupFileUniqueId = 0xFFFF; // Backup failed.
DeclareError( INSTALER_CANT_ACCESS_FILE, GetLastError(), Name );
}
}
}
else {
p->Created = p->WriteAccess;
}
if (FindFileHandle != NULL) {
FindClose( FindFileHandle );
}
*ReturnedReference = p;
return TRUE;
}
BOOLEAN
CompleteFileReference(
PFILE_REFERENCE p,
BOOLEAN CallSuccessful,
BOOLEAN Deleted,
PFILE_REFERENCE RenameReference
)
{
DWORD dwFileAttributes;
if (!CallSuccessful) {
DestroyFileReference( p );
return FALSE;
}
if (RenameReference) {
if (RenameReference->Created) {
LogEvent( INSTALER_EVENT_RENAME_TEMP_FILE,
3,
RenameReference->DirectoryFile ? L"directory" : L"file",
RenameReference->Name,
p->Name
);
RenameReference->Name = p->Name;
DestroyFileReference( p );
return FALSE;
}
RenameReference->Deleted = TRUE;
LogEvent( INSTALER_EVENT_RENAME_FILE,
3,
RenameReference->DirectoryFile ? L"directory" : L"file",
RenameReference->Name,
p->Name
);
}
else
if (Deleted && p->Created) {
LogEvent( INSTALER_EVENT_DELETE_TEMP_FILE,
2,
p->DirectoryFile ? L"directory" : L"file",
p->Name
);
DestroyFileReference( p );
return FALSE;
}
else {
if (wcschr( p->Name, '\\' ) == NULL) {
//
// If no path separator, must be volume open. Treat
// as directory and dont touch file
//
p->DirectoryFile = TRUE;
}
else
if ((dwFileAttributes = GetFileAttributes( p->Name )) != 0xFFFFFFFF) {
p->DirectoryFile = (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
if (Deleted) {
LogEvent( INSTALER_EVENT_DELETE_FILE,
2,
p->DirectoryFile ? L"directory" : L"file",
p->Name
);
}
else
if (p->WriteAccess) {
if (p->Created) {
LogEvent( INSTALER_EVENT_CREATE_FILE,
2,
p->DirectoryFile ? L"directory" : L"file",
p->Name
);
}
else {
LogEvent( INSTALER_EVENT_WRITE_FILE,
2,
p->DirectoryFile ? L"directory" : L"file",
p->Name
);
}
}
else {
LogEvent( INSTALER_EVENT_READ_FILE,
2,
p->DirectoryFile ? L"directory" : L"file",
p->Name
);
}
}
p->Deleted = Deleted;
return TRUE;
}
BOOLEAN
DestroyFileReference(
PFILE_REFERENCE p
)
{
PWSTR BackupFileName;
if (!p->Created &&
(BackupFileName = FormatTempFileName( NULL, &p->BackupFileUniqueId ))
) {
DeleteFileW( BackupFileName );
}
if (p->DateModified || p->AttributesModified) {
return FALSE;
}
RemoveEntryList( &p->Entry );
NumberOfFileReferences -= 1;
FreeMem( &p );
return TRUE;
}
PVOID
MapFileForRead(
PWSTR FileName,
PULONG FileSize
)
{
HANDLE FileHandle, MappingHandle;
PVOID FileData;
ULONG HighFileSize;
FileData = NULL;
FileHandle = CreateFileW( FileName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (FileHandle != INVALID_HANDLE_VALUE) {
*FileSize = GetFileSize( FileHandle, &HighFileSize );
if (*FileSize == 0) {
CloseHandle( FileHandle );
return (PVOID)0xFFFFFFFF;
}
MappingHandle = CreateFileMappingW( FileHandle,
NULL,
PAGE_READONLY,
0,
*FileSize,
NULL
);
CloseHandle( FileHandle );
if (MappingHandle != NULL) {
FileData = MapViewOfFile( MappingHandle,
FILE_MAP_READ,
0,
0,
*FileSize
);
CloseHandle( MappingHandle );
}
}
return FileData;
}
BOOLEAN
AreFileContentsEqual(
PWSTR FileName1,
PWSTR FileName2
)
{
PVOID FileData1, FileData2;
ULONG FileSize1, FileSize2;
BOOLEAN Result;
Result = FALSE;
if (FileData1 = MapFileForRead( FileName1, &FileSize1 )) {
if (FileData2 = MapFileForRead( FileName2, &FileSize2 )) {
if (FileSize1 == FileSize2 &&
RtlCompareMemory( FileData1, FileData2, FileSize1 ) == FileSize1
) {
Result = TRUE;
}
if (FileData2 != (PVOID)0xFFFFFFFF) {
UnmapViewOfFile( FileData2 );
}
}
else {
DeclareError( INSTALER_CANT_ACCESS_FILE, GetLastError(), FileName2 );
}
if (FileData1 != (PVOID)0xFFFFFFFF) {
UnmapViewOfFile( FileData1 );
}
}
else {
DeclareError( INSTALER_CANT_ACCESS_FILE, GetLastError(), FileName1 );
}
return Result;
}
BOOLEAN
IsNewFileSameAsBackup(
PFILE_REFERENCE p
)
{
WIN32_FIND_DATAW FindFileData;
HANDLE FindFileHandle;
PWSTR BackupFileName;
if ((FindFileHandle = FindFirstFileW( p->Name, &FindFileData )) != INVALID_HANDLE_VALUE) {
FindClose( FindFileHandle );
if (p->BackupFileAttributes != FindFileData.dwFileAttributes) {
p->AttributesModified = TRUE;
}
if (p->BackupLastWriteTime.dwLowDateTime != FindFileData.ftLastWriteTime.dwLowDateTime ||
p->BackupLastWriteTime.dwHighDateTime != FindFileData.ftLastWriteTime.dwHighDateTime
) {
p->DateModified = TRUE;
}
if (BackupFileName = FormatTempFileName( NULL, &p->BackupFileUniqueId )) {
if (p->BackupFileSize.LowPart != FindFileData.nFileSizeLow ||
p->BackupFileSize.HighPart != FindFileData.nFileSizeHigh ||
!AreFileContentsEqual( BackupFileName, p->Name )
) {
p->ContentsModified = TRUE;
return FALSE;
}
}
return TRUE;
}
else {
return FALSE;
}
}
PFILE_REFERENCE
FindFileReference(
PWSTR Name
)
{
PFILE_REFERENCE p;
PLIST_ENTRY Head, Next;
Head = &FileReferenceListHead;
Next = Head->Flink;
while (Head != Next) {
p = CONTAINING_RECORD( Next, FILE_REFERENCE, Entry );
if (p->Name == Name) {
return p;
}
Next = Next->Flink;
}
return NULL;
}
VOID
DumpFileReferenceList(
FILE *LogFile
)
{
PFILE_REFERENCE p;
PLIST_ENTRY Head, Next;
Head = &FileReferenceListHead;
Next = Head->Flink;
while (Head != Next) {
p = CONTAINING_RECORD( Next, FILE_REFERENCE, Entry );
if (p->WriteAccess) {
if (!p->Deleted) {
if (p->BackupFileUniqueId == 0) {
if (p->Created) {
ImlAddFileRecord( pImlNew,
CreateNewFile,
p->Name,
NULL,
NULL,
0
);
}
}
else {
if (p->ContentsModified) {
if (ImlAddFileRecord( pImlNew,
ModifyOldFile,
p->Name,
FormatTempFileName( NULL, &p->BackupFileUniqueId ),
NULL,
0
)
) {
DeleteFile( FormatTempFileName( NULL, &p->BackupFileUniqueId ) );
}
}
else
if (p->DateModified) {
ImlAddFileRecord( pImlNew,
ModifyFileDateTime,
p->Name,
NULL,
&p->BackupLastWriteTime,
p->BackupFileAttributes
);
}
else {
ImlAddFileRecord( pImlNew,
ModifyFileAttributes,
p->Name,
NULL,
&p->BackupLastWriteTime,
p->BackupFileAttributes
);
}
}
}
else {
if (ImlAddFileRecord( pImlNew,
DeleteOldFile,
p->Name,
FormatTempFileName( NULL, &p->BackupFileUniqueId ),
NULL,
0
)
) {
DeleteFile( FormatTempFileName( NULL, &p->BackupFileUniqueId ) );
}
}
}
Next = Next->Flink;
}
return;
}