mirror of
https://github.com/CloudDelphi/Virtual-File-System
synced 2025-12-19 18:03:49 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85d4fed65f | ||
|
|
420ddd7c15 | ||
|
|
c605df838c | ||
|
|
4d304d2483 | ||
|
|
a73db6fc47 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,5 +4,6 @@
|
||||
*.ini
|
||||
*.identcache
|
||||
*.map
|
||||
*.res
|
||||
_LOG_.txt
|
||||
__history/
|
||||
@ -1,2 +1,9 @@
|
||||
# VFS (Virtual File System)
|
||||
Add Virtual File System support to your project. Implement Mods directory support in 2 lines of code
|
||||
Add Virtual File System support to your project. Implement Mods directory support in 2 lines of code.
|
||||
Virtually copies contents of any directory into any directory. Copied contents is available in read-only mode.
|
||||
|
||||
## Example:
|
||||
```delphi
|
||||
VfsImport.MapModsFromListA('D:\Game', 'D:\Game\Mods', 'D:\Game\Mods\list.txt');
|
||||
VfsImport.RunVfs(VfsImport.SORT_FIFO);
|
||||
```
|
||||
|
||||
@ -30,7 +30,11 @@
|
||||
<Borland.Personality>Delphi.Personality</Borland.Personality>
|
||||
<Borland.ProjectType>VCLApplication</Borland.ProjectType>
|
||||
<BorlandProject>
|
||||
<BorlandProject><Delphi.Personality><Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><VersionInfo><VersionInfo Name="IncludeVerInfo">True</VersionInfo><VersionInfo Name="AutoIncBuild">True</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">2</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1049</VersionInfo><VersionInfo Name="CodePage">1251</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName">Alexander Shostak (aka EtherniDee)</VersionInfoKeys><VersionInfoKeys Name="FileDescription">Virtual File System</VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.2.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Source><Source Name="MainSource">Vfs.dpr</Source></Source><Excluded_Packages>
|
||||
<BorlandProject><Delphi.Personality><Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><VersionInfo><VersionInfo Name="IncludeVerInfo">True</VersionInfo><VersionInfo Name="AutoIncBuild">True</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">4</VersionInfo><VersionInfo Name="Build">1</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1049</VersionInfo><VersionInfo Name="CodePage">1251</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName">Alexander Shostak (aka EtherniDee)</VersionInfoKeys><VersionInfoKeys Name="FileDescription">Virtual File System</VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.4.1</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Source><Source Name="MainSource">Vfs.dpr</Source></Source><Excluded_Packages>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -577,7 +577,7 @@ begin
|
||||
|
||||
with SysScanDir(AbsRealPath, '*') do begin
|
||||
while IterNext(FileInfo.FileName, @FileInfo.Base) do begin
|
||||
if Utils.HasFlag(Windows.FILE_ATTRIBUTE_DIRECTORY, FileInfo.Base.FileAttributes) then begin
|
||||
if Utils.Flags(FileInfo.Base.FileAttributes).Have(Windows.FILE_ATTRIBUTE_DIRECTORY) then begin
|
||||
if (FileInfo.FileName <> '.') and (FileInfo.FileName <> '..') then begin
|
||||
Subdirs.Add(TFileInfo.Create(@FileInfo));
|
||||
end;
|
||||
|
||||
@ -149,8 +149,8 @@ begin
|
||||
AbsRootDir := VfsUtils.NormalizePath(RootDir);
|
||||
AbsModsDir := VfsUtils.NormalizePath(ModsDir);
|
||||
result := (AbsRootDir <> '') and (AbsModsDir <> '') and
|
||||
VfsUtils.GetFileInfo(AbsRootDir, FileInfo) and Utils.HasFlag(Windows.FILE_ATTRIBUTE_DIRECTORY, FileInfo.Base.FileAttributes) and
|
||||
VfsUtils.GetFileInfo(AbsModsDir, FileInfo) and Utils.HasFlag(Windows.FILE_ATTRIBUTE_DIRECTORY, FileInfo.Base.FileAttributes);
|
||||
VfsUtils.GetFileInfo(AbsRootDir, FileInfo) and Utils.Flags(FileInfo.Base.FileAttributes).Have(Windows.FILE_ATTRIBUTE_DIRECTORY) and
|
||||
VfsUtils.GetFileInfo(AbsModsDir, FileInfo) and Utils.Flags(FileInfo.Base.FileAttributes).Have(Windows.FILE_ATTRIBUTE_DIRECTORY);
|
||||
|
||||
if result then begin
|
||||
ModPathPrefix := VfsUtils.AddBackslash(AbsModsDir);
|
||||
|
||||
@ -26,22 +26,14 @@ exports
|
||||
|
||||
function Externalize (const Str: AnsiString): {O} pointer; overload;
|
||||
begin
|
||||
result := nil;
|
||||
|
||||
if Str <> '' then begin
|
||||
GetMem(result, Length(Str) + 1);
|
||||
Utils.CopyMem(Length(Str) + 1, pointer(Str), result);
|
||||
end;
|
||||
Utils.CopyMem(Length(Str) + 1, pchar(Str), result);
|
||||
end;
|
||||
|
||||
function Externalize (const Str: WideString): {O} pointer; overload;
|
||||
begin
|
||||
result := nil;
|
||||
|
||||
if Str <> '' then begin
|
||||
GetMem(result, (Length(Str) + 1) * sizeof(WideChar));
|
||||
Utils.CopyMem((Length(Str) + 1) * sizeof(WideChar), pointer(Str), result);
|
||||
end;
|
||||
Utils.CopyMem((Length(Str) + 1) * sizeof(WideChar), PWideChar(Str), result);
|
||||
end;
|
||||
|
||||
function MapDir (const VirtPath, RealPath: PWideChar; OverwriteExisting: boolean; Flags: integer = 0): LONGBOOL; stdcall;
|
||||
|
||||
37
VfsHooks.pas
37
VfsHooks.pas
@ -31,6 +31,8 @@ var
|
||||
NativeNtCreateFile: WinNative.TNtCreateFile;
|
||||
NativeNtClose: WinNative.TNtClose;
|
||||
NativeNtQueryDirectoryFile: WinNative.TNtQueryDirectoryFile;
|
||||
NativeNtQueryDirectoryFileEx: WinNative.TNtQueryDirectoryFileEx;
|
||||
|
||||
|
||||
NtQueryAttributesFilePatch: VfsPatching.TAppliedPatch;
|
||||
NtQueryFullAttributesFilePatch: VfsPatching.TAppliedPatch;
|
||||
@ -38,6 +40,7 @@ var
|
||||
NtCreateFilePatch: VfsPatching.TAppliedPatch;
|
||||
NtClosePatch: VfsPatching.TAppliedPatch;
|
||||
NtQueryDirectoryFilePatch: VfsPatching.TAppliedPatch;
|
||||
NtQueryDirectoryFileExPatch: VfsPatching.TAppliedPatch;
|
||||
|
||||
|
||||
(* There is no 100% portable and reliable way to get file path by handle, unless file creation/opening
|
||||
@ -111,7 +114,7 @@ begin
|
||||
|
||||
// Return cached VFS file info
|
||||
if RedirectedPath <> '' then begin
|
||||
if not HadTrailingDelim or Utils.HasFlag(FILE_ATTRIBUTE_DIRECTORY, FileInfo.Base.FileAttributes) then begin
|
||||
if not HadTrailingDelim or Utils.Flags(FileInfo.Base.FileAttributes).Have(FILE_ATTRIBUTE_DIRECTORY) then begin
|
||||
FileInformation.CreationTime := FileInfo.Base.CreationTime;
|
||||
FileInformation.LastAccessTime := FileInfo.Base.LastAccessTime;
|
||||
FileInformation.LastWriteTime := FileInfo.Base.LastWriteTime;
|
||||
@ -171,7 +174,7 @@ begin
|
||||
|
||||
// Return cached VFS file info
|
||||
if RedirectedPath <> '' then begin
|
||||
if not HadTrailingDelim or Utils.HasFlag(FILE_ATTRIBUTE_DIRECTORY, FileInfo.Base.FileAttributes) then begin
|
||||
if not HadTrailingDelim or Utils.Flags(FileInfo.Base.FileAttributes).Have(FILE_ATTRIBUTE_DIRECTORY) then begin
|
||||
FileInformation.CreationTime := FileInfo.Base.CreationTime;
|
||||
FileInformation.LastAccessTime := FileInfo.Base.LastAccessTime;
|
||||
FileInformation.LastWriteTime := FileInfo.Base.LastWriteTime;
|
||||
@ -543,11 +546,28 @@ begin
|
||||
end;
|
||||
end; // .function Hook_NtQueryDirectoryFile
|
||||
|
||||
function Hook_NtQueryDirectoryFileEx (OrigFunc: WinNative.TNtQueryDirectoryFileEx; FileHandle: HANDLE; Event: HANDLE; ApcRoutine: pointer; ApcContext: PVOID; Io: PIO_STATUS_BLOCK;
|
||||
Buffer: PVOID; BufLength: ULONG; InfoClass: integer (* FILE_INFORMATION_CLASS *); QueryFlags: integer; Mask: PUNICODE_STRING): NTSTATUS; stdcall;
|
||||
var
|
||||
SingleEntry: LONGBOOL;
|
||||
RestartScan: LONGBOOL;
|
||||
|
||||
begin
|
||||
if VfsDebug.LoggingEnabled then begin
|
||||
WriteLog('NtQueryDirectoryFileEx', Format('Handle: %x. QueryFlags: %x', [FileHandle, QueryFlags]));
|
||||
end;
|
||||
|
||||
RestartScan := Utils.Flags(QueryFlags).Have(WinNative.SL_RESTART_SCAN);
|
||||
SingleEntry := Utils.Flags(QueryFlags).Have(WinNative.SL_RETURN_SINGLE_ENTRY);
|
||||
result := WinNative.NtQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext, Io, Buffer, BufLength, InfoClass, SingleEntry, Mask, RestartScan);
|
||||
end;
|
||||
|
||||
procedure InstallHooks;
|
||||
var
|
||||
SetProcessDEPPolicy: function (dwFlags: integer): LONGBOOL; stdcall;
|
||||
hDll: Windows.THandle;
|
||||
NtdllHandle: integer;
|
||||
NtQueryDirectoryFileExAddr: WinNative.TNtQueryDirectoryFileEx;
|
||||
|
||||
begin
|
||||
with HooksCritSection do begin
|
||||
@ -622,6 +642,18 @@ begin
|
||||
@Hook_NtQueryDirectoryFile,
|
||||
@NtQueryDirectoryFilePatch
|
||||
);
|
||||
|
||||
NtQueryDirectoryFileExAddr := VfsApiDigger.GetRealProcAddress(NtdllHandle, 'NtQueryDirectoryFileEx');
|
||||
|
||||
if @NtQueryDirectoryFileExAddr <> nil then begin
|
||||
WriteLog('InstallHook', 'Installing NtQueryDirectoryFileEx hook');
|
||||
NativeNtQueryDirectoryFileEx := VfsPatching.SpliceWinApi
|
||||
(
|
||||
@NtQueryDirectoryFileExAddr,
|
||||
@Hook_NtQueryDirectoryFileEx,
|
||||
@NtQueryDirectoryFileExPatch
|
||||
);
|
||||
end;
|
||||
end; // .if
|
||||
|
||||
Leave;
|
||||
@ -639,6 +671,7 @@ begin
|
||||
NtCreateFilePatch.Rollback;
|
||||
NtClosePatch.Rollback;
|
||||
NtQueryDirectoryFilePatch.Rollback;
|
||||
NtQueryDirectoryFileExPatch.Rollback;
|
||||
|
||||
Leave;
|
||||
end;
|
||||
|
||||
@ -159,6 +159,7 @@ begin
|
||||
// Create and apply hook at target function start
|
||||
p.Clear();
|
||||
p.Jump(PatchForge.JMP, SpliceBridge);
|
||||
p.Nop(OverwrittenCodeSize - p.Pos);
|
||||
|
||||
if AppliedPatch <> nil then begin
|
||||
AppliedPatch.Addr := OrigFunc;
|
||||
|
||||
@ -506,7 +506,7 @@ var
|
||||
FileAttrs: integer;
|
||||
|
||||
begin
|
||||
result := GetFileAttrs(Path, FileAttrs) and Utils.HasFlag(Windows.FILE_ATTRIBUTE_DIRECTORY, FileAttrs);
|
||||
result := GetFileAttrs(Path, FileAttrs) and Utils.Flags(FileAttrs).Have(Windows.FILE_ATTRIBUTE_DIRECTORY);
|
||||
end;
|
||||
|
||||
function SysOpenFile (const NtAbsPath: WideString; {OUT} var Res: Windows.THandle; const OpenMode: TSysOpenFileMode = OPEN_AS_ANY; const AccessMode: ACCESS_MASK = FILE_GENERIC_READ): boolean;
|
||||
|
||||
@ -4,7 +4,7 @@ cls
|
||||
set h3dir=D:\Heroes 3
|
||||
copy /Y Vfs.dll "%h3dir%\vfs.dll"
|
||||
copy /Y Vfs.map "%h3dir%\Vfs.map"
|
||||
php "%h3dir%\Tools\ExeMapCompiler\compile.phc" "vfs.map" "./DebugMaps"
|
||||
php "%h3dir%\Tools\ExeMapCompiler\compile.phc" "vfs.map" "%h3dir%/DebugMaps"
|
||||
echo.
|
||||
echo.
|
||||
echo %date% %time%
|
||||
|
||||
Loading…
Reference in New Issue
Block a user