|
|
/*++
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; }
|