621 lines
20 KiB
ObjectPascal
621 lines
20 KiB
ObjectPascal
unit SetupLdrAndSetup.RedirFunc;
|
|
|
|
{
|
|
Inno Setup
|
|
Copyright (C) 1997-2025 Jordan Russell
|
|
Portions by Martijn Laan
|
|
For conditions of distribution and use, see LICENSE.TXT.
|
|
|
|
Functions for dealing with WOW64 file system redirection.
|
|
Used only by the Setup and SetupLdr projects.
|
|
|
|
The *Redir functions are counterparts to common functions that offer
|
|
built-in support for disabling FS redirection.
|
|
}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, SysUtils, Shared.FileClass, Shared.VerInfoFunc;
|
|
|
|
type
|
|
TPreviousFsRedirectionState = record
|
|
DidDisable: Boolean;
|
|
OldValue: Pointer;
|
|
end;
|
|
|
|
function AreFsRedirectionFunctionsAvailable: Boolean;
|
|
function DisableFsRedirectionIf(const Disable: Boolean;
|
|
var PreviousState: TPreviousFsRedirectionState): Boolean;
|
|
procedure RestoreFsRedirection(const PreviousState: TPreviousFsRedirectionState);
|
|
|
|
function CreateFileRedir(const DisableFsRedir: Boolean; const FileName: String;
|
|
const DesiredAccess, ShareMode: DWORD; const SecurityAttributes: PSecurityAttributes;
|
|
const CreationDisposition, FlagsAndAttributes: DWORD; TemplateFile: THandle): THandle;
|
|
function CreateDirectoryRedir(const DisableFsRedir: Boolean; const Filename: String;
|
|
const SecurityAttributes: PSecurityAttributes = nil): BOOL;
|
|
function CreateProcessRedir(const DisableFsRedir: Boolean;
|
|
const lpApplicationName: PChar; const lpCommandLine: PChar;
|
|
const lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
|
|
const bInheritHandles: BOOL; const dwCreationFlags: DWORD;
|
|
const lpEnvironment: Pointer; const lpCurrentDirectory: PChar;
|
|
const lpStartupInfo: TStartupInfo;
|
|
var lpProcessInformation: TProcessInformation): BOOL;
|
|
function CopyFileRedir(const DisableFsRedir: Boolean;
|
|
const ExistingFilename, NewFilename: String; const FailIfExists: BOOL): BOOL;
|
|
function DeleteFileRedir(const DisableFsRedir: Boolean; const Filename: String): BOOL;
|
|
function DirExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
|
|
function FileOrDirExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
|
|
function FindFirstFileRedir(const DisableFsRedir: Boolean; const Filename: String;
|
|
var FindData: TWin32FindData): THandle;
|
|
function GetFileAttributesRedir(const DisableFsRedir: Boolean; const Filename: String): DWORD;
|
|
function GetShortNameRedir(const DisableFsRedir: Boolean; const Filename: String): String;
|
|
function GetVersionNumbersRedir(const DisableFsRedir: Boolean; const Filename: String;
|
|
var VersionNumbers: TFileVersionNumbers): Boolean;
|
|
function IsDirectoryAndNotReparsePointRedir(const DisableFsRedir: Boolean;
|
|
const Name: String): Boolean;
|
|
function MoveFileRedir(const DisableFsRedir: Boolean;
|
|
const ExistingFilename, NewFilename: String): BOOL;
|
|
function MoveFileExRedir(const DisableFsRedir: Boolean;
|
|
const ExistingFilename, NewFilename: String; const Flags: DWORD): BOOL;
|
|
function NewFileExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
|
|
function RemoveDirectoryRedir(const DisableFsRedir: Boolean; const Filename: String): BOOL;
|
|
function SetFileAttributesRedir(const DisableFsRedir: Boolean; const Filename: String;
|
|
const Attrib: DWORD): BOOL;
|
|
function SetNTFSCompressionRedir(const DisableFsRedir: Boolean; const FileOrDir: String; Compress: Boolean): Boolean;
|
|
|
|
type
|
|
TFileRedir = class(TFile)
|
|
private
|
|
FDisableFsRedir: Boolean;
|
|
protected
|
|
function CreateHandle(const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing): THandle; override;
|
|
public
|
|
constructor Create(const DisableFsRedir: Boolean; const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing);
|
|
end;
|
|
|
|
TTextFileReaderRedir = class(TTextFileReader)
|
|
private
|
|
FDisableFsRedir: Boolean;
|
|
protected
|
|
function CreateHandle(const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing): THandle; override;
|
|
public
|
|
constructor Create(const DisableFsRedir: Boolean; const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing);
|
|
end;
|
|
|
|
TTextFileWriterRedir = class(TTextFileWriter)
|
|
private
|
|
FDisableFsRedir: Boolean;
|
|
protected
|
|
function CreateHandle(const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing): THandle; override;
|
|
public
|
|
constructor Create(const DisableFsRedir: Boolean; const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing);
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Shared.CommonFunc, PathFunc;
|
|
|
|
var
|
|
Wow64DisableWow64FsRedirectionFunc: function(var OldValue: Pointer): BOOL; stdcall;
|
|
Wow64RevertWow64FsRedirectionFunc: function(OldValue: Pointer): BOOL; stdcall;
|
|
FsRedirectionFunctionsAvailable: Boolean;
|
|
|
|
function AreFsRedirectionFunctionsAvailable: Boolean;
|
|
begin
|
|
Result := FsRedirectionFunctionsAvailable;
|
|
end;
|
|
|
|
function DisableFsRedirectionIf(const Disable: Boolean;
|
|
var PreviousState: TPreviousFsRedirectionState): Boolean;
|
|
{ If Disable is False, the function does not change the redirection state and
|
|
always returns True.
|
|
If Disable is True, the function attempts to disable WOW64 file system
|
|
redirection, so that c:\windows\system32 goes to the 64-bit System directory
|
|
instead of the 32-bit one.
|
|
Returns True if successful, False if not. For extended error information when
|
|
False is returned, call GetLastError. }
|
|
begin
|
|
PreviousState.DidDisable := False;
|
|
if not Disable then
|
|
Result := True
|
|
else begin
|
|
if FsRedirectionFunctionsAvailable then begin
|
|
{ Note: Disassembling Wow64DisableWow64FsRedirection and the Rtl function
|
|
it calls, it doesn't appear as if it can ever actually fail on 64-bit
|
|
Windows. But it always fails on the 32-bit version of Windows Server
|
|
2003 SP1 (with error code 1 - ERROR_INVALID_FUNCTION). }
|
|
Result := Wow64DisableWow64FsRedirectionFunc(PreviousState.OldValue);
|
|
if Result then
|
|
PreviousState.DidDisable := True;
|
|
end
|
|
else begin
|
|
{ Should never happen }
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
Result := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure RestoreFsRedirection(const PreviousState: TPreviousFsRedirectionState);
|
|
{ Restores the previous WOW64 file system redirection state after a call to
|
|
DisableFsRedirectionIf. There is no indication of failure (which is
|
|
extremely unlikely). }
|
|
begin
|
|
if PreviousState.DidDisable then
|
|
Wow64RevertWow64FsRedirectionFunc(PreviousState.OldValue);
|
|
end;
|
|
|
|
{ *Redir functions }
|
|
|
|
function CreateFileRedir(const DisableFsRedir: Boolean; const FileName: String;
|
|
const DesiredAccess, ShareMode: DWORD; const SecurityAttributes: PSecurityAttributes;
|
|
const CreationDisposition, FlagsAndAttributes: DWORD; TemplateFile: THandle): THandle;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := INVALID_HANDLE_VALUE;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := CreateFile(PChar(Filename), DesiredAccess, ShareMode, SecurityAttributes,
|
|
CreationDisposition, FlagsAndAttributes, TemplateFile);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function CreateDirectoryRedir(const DisableFsRedir: Boolean; const Filename: String;
|
|
const SecurityAttributes: PSecurityAttributes): BOOL;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := CreateDirectory(PChar(Filename), SecurityAttributes);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function CreateProcessRedir(const DisableFsRedir: Boolean;
|
|
const lpApplicationName: PChar; const lpCommandLine: PChar;
|
|
const lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
|
|
const bInheritHandles: BOOL; const dwCreationFlags: DWORD;
|
|
const lpEnvironment: Pointer; const lpCurrentDirectory: PChar;
|
|
const lpStartupInfo: TStartupInfo;
|
|
var lpProcessInformation: TProcessInformation): BOOL;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := CreateProcess(lpApplicationName, lpCommandLine,
|
|
lpProcessAttributes, lpThreadAttributes,
|
|
bInheritHandles, dwCreationFlags, lpEnvironment,
|
|
lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function CopyFileRedir(const DisableFsRedir: Boolean;
|
|
const ExistingFilename, NewFilename: String; const FailIfExists: BOOL): BOOL;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := CopyFile(PChar(ExistingFilename), PChar(NewFilename), FailIfExists);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function DeleteFileRedir(const DisableFsRedir: Boolean; const Filename: String): BOOL;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := Windows.DeleteFile(PChar(Filename));
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function DirExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := DirExists(Filename);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function FileOrDirExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := FileOrDirExists(Filename);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function FindFirstFileRedir(const DisableFsRedir: Boolean; const Filename: String;
|
|
var FindData: TWin32FindData): THandle;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := INVALID_HANDLE_VALUE;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := FindFirstFile(PChar(Filename), FindData);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function GetFileAttributesRedir(const DisableFsRedir: Boolean; const Filename: String): DWORD;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := INVALID_FILE_ATTRIBUTES;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := GetFileAttributes(PChar(Filename));
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function GetShortNameRedir(const DisableFsRedir: Boolean; const Filename: String): String;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := Filename;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := GetShortName(Filename);
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
end;
|
|
|
|
function GetVersionNumbersRedir(const DisableFsRedir: Boolean; const Filename: String;
|
|
var VersionNumbers: TFileVersionNumbers): Boolean;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := GetVersionNumbers(Filename, VersionNumbers);
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
end;
|
|
|
|
function IsDirectoryAndNotReparsePointRedir(const DisableFsRedir: Boolean;
|
|
const Name: String): Boolean;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := IsDirectoryAndNotReparsePoint(Name);
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
end;
|
|
|
|
function MoveFileRedir(const DisableFsRedir: Boolean;
|
|
const ExistingFilename, NewFilename: String): BOOL;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := MoveFile(PChar(ExistingFilename), PChar(NewFilename));
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function MoveFileExRedir(const DisableFsRedir: Boolean;
|
|
const ExistingFilename, NewFilename: String; const Flags: DWORD): BOOL;
|
|
var
|
|
NewFilenameP: PChar;
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if (NewFilename = '') and (Flags and MOVEFILE_DELAY_UNTIL_REBOOT <> 0) then
|
|
NewFilenameP := nil
|
|
else
|
|
NewFilenameP := PChar(NewFilename);
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := MoveFileEx(PChar(ExistingFilename), NewFilenameP, Flags);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function NewFileExistsRedir(const DisableFsRedir: Boolean; const Filename: String): Boolean;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := NewFileExists(Filename);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function RemoveDirectoryRedir(const DisableFsRedir: Boolean; const Filename: String): BOOL;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := RemoveDirectory(PChar(Filename));
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function SetFileAttributesRedir(const DisableFsRedir: Boolean; const Filename: String;
|
|
const Attrib: DWORD): BOOL;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := SetFileAttributes(PChar(Filename), Attrib);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
function SetNTFSCompressionRedir(const DisableFsRedir: Boolean; const FileOrDir: String; Compress: Boolean): Boolean;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(DisableFsRedir, PrevState) then begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := SetNTFSCompression(FileOrDir, Compress);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
{ TFileRedir }
|
|
|
|
constructor TFileRedir.Create(const DisableFsRedir: Boolean; const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing);
|
|
begin
|
|
FDisableFsRedir := DisableFsRedir;
|
|
inherited Create(AFilename, ACreateDisposition, AAccess, ASharing);
|
|
end;
|
|
|
|
function TFileRedir.CreateHandle(const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing): THandle;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(FDisableFsRedir, PrevState) then begin
|
|
Result := INVALID_HANDLE_VALUE;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := inherited CreateHandle(AFilename, ACreateDisposition, AAccess,
|
|
ASharing);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
{ TTextFileReaderRedir }
|
|
|
|
constructor TTextFileReaderRedir.Create(const DisableFsRedir: Boolean; const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing);
|
|
begin
|
|
FDisableFsRedir := DisableFsRedir;
|
|
inherited Create(AFilename, ACreateDisposition, AAccess, ASharing);
|
|
end;
|
|
|
|
function TTextFileReaderRedir.CreateHandle(const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing): THandle;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(FDisableFsRedir, PrevState) then begin
|
|
Result := INVALID_HANDLE_VALUE;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := inherited CreateHandle(AFilename, ACreateDisposition, AAccess,
|
|
ASharing);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
{ TTextFileWriterRedir }
|
|
|
|
constructor TTextFileWriterRedir.Create(const DisableFsRedir: Boolean; const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing);
|
|
begin
|
|
FDisableFsRedir := DisableFsRedir;
|
|
inherited Create(AFilename, ACreateDisposition, AAccess, ASharing);
|
|
end;
|
|
|
|
function TTextFileWriterRedir.CreateHandle(const AFilename: String;
|
|
ACreateDisposition: TFileCreateDisposition; AAccess: TFileAccess;
|
|
ASharing: TFileSharing): THandle;
|
|
var
|
|
PrevState: TPreviousFsRedirectionState;
|
|
ErrorCode: DWORD;
|
|
begin
|
|
if not DisableFsRedirectionIf(FDisableFsRedir, PrevState) then begin
|
|
Result := INVALID_HANDLE_VALUE;
|
|
Exit;
|
|
end;
|
|
try
|
|
Result := inherited CreateHandle(AFilename, ACreateDisposition, AAccess,
|
|
ASharing);
|
|
ErrorCode := GetLastError;
|
|
finally
|
|
RestoreFsRedirection(PrevState);
|
|
end;
|
|
SetLastError(ErrorCode);
|
|
end;
|
|
|
|
initialization
|
|
Wow64DisableWow64FsRedirectionFunc := GetProcAddress(GetModuleHandle(kernel32),
|
|
'Wow64DisableWow64FsRedirection');
|
|
Wow64RevertWow64FsRedirectionFunc := GetProcAddress(GetModuleHandle(kernel32),
|
|
'Wow64RevertWow64FsRedirection');
|
|
FsRedirectionFunctionsAvailable := Assigned(Wow64DisableWow64FsRedirectionFunc) and
|
|
Assigned(Wow64RevertWow64FsRedirectionFunc);
|
|
|
|
{ For GetVersionNumbersRedir: Pre-load shell32.dll since GetFileVersionInfo
|
|
and GetFileVersionInfoSize will try to load it when reading version info
|
|
on 16-bit files. We can't allow the DLL be loaded for the first time while
|
|
FS redirection is disabled. }
|
|
SafeLoadLibrary(AddBackslash(GetSystemDir) + 'shell32.dll', SEM_NOOPENFILEERRORBOX);
|
|
|
|
{ FormatMessage might be called with FS redirection disabled, so ensure
|
|
that all the DLLs FormatMessage searches in for messages (e.g. netmsg.dll,
|
|
ws03res.dll) are pre-loaded by calling it now with a randomly-chosen
|
|
message ID -- one that won't result in a match and cause the function to
|
|
return early.
|
|
(Note: Presently, FormatMessage loads the DLLs as "data files" so it
|
|
actually may not matter whether it gets 32- or 64-bit versions. But let's
|
|
be on the safe side.) }
|
|
Win32ErrorString($4C783AFB);
|
|
end.
|