mirror of
https://github.com/CloudDelphi/Virtual-File-System
synced 2025-12-19 09:53:54 +01:00
Started working on high-level exported mod API. Fixed Delphi bug with wrong stack variables alignment. Fixed bug in IsVfsOn (leave crit section without entering). Now XP normally passes all tests
This commit is contained in:
parent
c4698834c2
commit
ff8192c149
@ -8,8 +8,17 @@ unit VfsControl;
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Windows, SysUtils,
|
Windows, SysUtils,
|
||||||
Utils, WinUtils,
|
Utils, WinUtils, TypeWrappers, DataLib,
|
||||||
VfsBase, VfsUtils, VfsHooks;
|
Files, StrLib,
|
||||||
|
VfsBase, VfsUtils, VfsHooks, DlgMes;
|
||||||
|
|
||||||
|
type
|
||||||
|
(* Import *)
|
||||||
|
TWideString = TypeWrappers.TWideString;
|
||||||
|
|
||||||
|
const
|
||||||
|
(* Flag forces to skip directory names, starting with '#' *)
|
||||||
|
SKIP_HASHTAGGED_MODS = 1;
|
||||||
|
|
||||||
|
|
||||||
(* Runs all VFS subsystems, unless VFS is already running *)
|
(* Runs all VFS subsystems, unless VFS is already running *)
|
||||||
@ -44,4 +53,87 @@ begin
|
|||||||
end; // .with
|
end; // .with
|
||||||
end; // function RunVfs
|
end; // function RunVfs
|
||||||
|
|
||||||
|
function ValidateModName (const ModName: WideString): boolean;
|
||||||
|
const
|
||||||
|
DISALLOWED_CHARS = ['<', '>', '"', '?', '*', '\', '/', '|', ':', #0];
|
||||||
|
|
||||||
|
var
|
||||||
|
StrLen: integer;
|
||||||
|
i: integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
StrLen := Length(ModName);
|
||||||
|
i := 1;
|
||||||
|
|
||||||
|
while (i <= StrLen) and ((ord(ModName[i]) > 255) or not (AnsiChar(ModName[i]) in DISALLOWED_CHARS)) do begin
|
||||||
|
Inc(i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
result := (i > StrLen) and (ModName <> '') and (ModName <> '.') and (ModName <> '..');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function LoadModList (const ModListFilePath: WideString): {O} DataLib.TList {of (O) TWideString};
|
||||||
|
var
|
||||||
|
AbsFilePath: WideString;
|
||||||
|
FileContents: string;
|
||||||
|
Lines: Utils.TArrayOfStr;
|
||||||
|
ModNameUtf8: string;
|
||||||
|
ModName: WideString;
|
||||||
|
i: integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
result := DataLib.NewList(Utils.OWNS_ITEMS);
|
||||||
|
// * * * * * //
|
||||||
|
AbsFilePath := VfsUtils.NormalizePath(ModListFilePath);
|
||||||
|
|
||||||
|
if (AbsFilePath <> '') and (Files.ReadFileContents(AbsFilePath, FileContents)) then begin
|
||||||
|
Lines := StrLib.Explode(FileContents, #10);
|
||||||
|
|
||||||
|
for i := 0 to High(Lines) do begin
|
||||||
|
ModNameUtf8 := Lines[i];
|
||||||
|
ModName := StrLib.Utf8ToWide(ModNameUtf8);
|
||||||
|
|
||||||
|
if ValidateModName(ModName) then begin
|
||||||
|
result.Add(TWideString.Create(ModName));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end; // .function LoadModList
|
||||||
|
|
||||||
|
// function MapModsDir (const RootDir, ModsDir: WideString; Flags: integer = 0);
|
||||||
|
// var
|
||||||
|
// AbsRootDir: WideString;
|
||||||
|
// AbsModsDir: WideString;
|
||||||
|
// FileInfo: VfsUtils.TNativeFileInfo;
|
||||||
|
// ModName: WideString;
|
||||||
|
|
||||||
|
|
||||||
|
// begin
|
||||||
|
// AbsRootDir := VfsUtils.NormalizePath(RootDir);
|
||||||
|
// AbsModsDir := VfsUtils.NormalizePath(ModsDir);
|
||||||
|
// result := (AbsRootDir <> '') and (AbsModsDir <> '') and VfsUtils.GetFileInfo(AbsRootDir, FileInfo);
|
||||||
|
// result := result and Utils.HasFlag(Windows.FILE_ATTRIBUTE_DIRECTORY, FileInfo.Base.FileAttributes);
|
||||||
|
// result := result and VfsUtils.GetFileInfo(AbsModsDir, FileInfo);
|
||||||
|
// result := result and Utils.HasFlag(Windows.FILE_ATTRIBUTE_DIRECTORY, FileInfo.Base.FileAttributes);
|
||||||
|
|
||||||
|
// if result then begin
|
||||||
|
// with VfsUtils.SysScanDir(AbsModsDir, '*') do begin
|
||||||
|
// while IterNext(ModName, @FileInfo.Base) do begin
|
||||||
|
// if (ModName <> '.') and (ModName <> '..') and Utils.HasFlag(Windows.FILE_ATTRIBUTE_DIRECTORY, FileInfo.Base.FileAttributes) then begin
|
||||||
|
|
||||||
|
// end;
|
||||||
|
// end;
|
||||||
|
// end;
|
||||||
|
// end;
|
||||||
|
// end;
|
||||||
|
|
||||||
|
var
|
||||||
|
L: TList;
|
||||||
|
i: integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// L := LoadModList('D:\Heroes 3\Mods\list.txt');
|
||||||
|
// for i := 0 to L.Count- 1 do begin
|
||||||
|
// VarDump([TWideString(L[i]).Value]);
|
||||||
|
// end;
|
||||||
end.
|
end.
|
||||||
@ -61,7 +61,7 @@ end;
|
|||||||
procedure TestIntegrated.TearDown;
|
procedure TestIntegrated.TearDown;
|
||||||
begin
|
begin
|
||||||
VfsBase.ResetVfs();
|
VfsBase.ResetVfs();
|
||||||
VfsDebug.SetLoggingProc(nil);
|
//VfsDebug.SetLoggingProc(nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TestIntegrated.TestGetFileAttributes;
|
procedure TestIntegrated.TestGetFileAttributes;
|
||||||
@ -88,12 +88,14 @@ var
|
|||||||
end; // .function HasValidAttrs
|
end; // .function HasValidAttrs
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
VfsDebug.WriteLog('TestGetFileAttributes', 'Started');
|
||||||
RootDir := VfsTestHelper.GetTestsRootDir;
|
RootDir := VfsTestHelper.GetTestsRootDir;
|
||||||
Check(not HasValidAttrs(VfsUtils.MakePath([RootDir, '\non-existing.non'])), '{1}');
|
Check(not HasValidAttrs(VfsUtils.MakePath([RootDir, 'non-existing.non'])), '{1}');
|
||||||
Check(HasValidAttrs(VfsUtils.MakePath([RootDir, '\Hobbots\mms.cfg']), 0, Windows.FILE_ATTRIBUTE_DIRECTORY), '{2}');
|
Check(HasValidAttrs(VfsUtils.MakePath([RootDir, 'Hobbots\mms.cfg']), 0, Windows.FILE_ATTRIBUTE_DIRECTORY), '{2}');
|
||||||
Check(HasValidAttrs(VfsUtils.MakePath([RootDir, '\503.html']), 0, Windows.FILE_ATTRIBUTE_DIRECTORY), '{3}');
|
Check(HasValidAttrs(VfsUtils.MakePath([RootDir, '503.html']), 0, Windows.FILE_ATTRIBUTE_DIRECTORY), '{3}');
|
||||||
Check(HasValidAttrs(VfsUtils.MakePath([RootDir, '\Hobbots\']), Windows.FILE_ATTRIBUTE_DIRECTORY), '{4}');
|
Check(HasValidAttrs(VfsUtils.MakePath([RootDir, 'Hobbots\']), Windows.FILE_ATTRIBUTE_DIRECTORY), '{4}');
|
||||||
Check(HasValidAttrs(VfsUtils.MakePath([RootDir, '\Mods']), Windows.FILE_ATTRIBUTE_DIRECTORY), '{5}');
|
Check(HasValidAttrs(VfsUtils.MakePath([RootDir, 'Mods']), Windows.FILE_ATTRIBUTE_DIRECTORY), '{5}');
|
||||||
|
VfsDebug.WriteLog('TestGetFileAttributes', 'Ended');
|
||||||
end; // .procedure TestIntegrated.TestGetFileAttributes;
|
end; // .procedure TestIntegrated.TestGetFileAttributes;
|
||||||
|
|
||||||
procedure TestIntegrated.TestGetFileAttributesEx;
|
procedure TestIntegrated.TestGetFileAttributesEx;
|
||||||
@ -113,11 +115,13 @@ var
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
VfsDebug.WriteLog('TestGetFileAttributesEx', 'Started');
|
||||||
RootDir := VfsTestHelper.GetTestsRootDir;
|
RootDir := VfsTestHelper.GetTestsRootDir;
|
||||||
CheckEquals(-1, GetFileSize(VfsUtils.MakePath([RootDir, '\non-existing.non'])), '{1}');
|
CheckEquals(-1, GetFileSize(VfsUtils.MakePath([RootDir, 'non-existing.non'])), '{1}');
|
||||||
CheckEquals(42, GetFileSize(VfsUtils.MakePath([RootDir, '\Hobbots\mms.cfg'])), '{2}');
|
CheckEquals(42, GetFileSize(VfsUtils.MakePath([RootDir, 'Hobbots\mms.cfg'])), '{2}');
|
||||||
CheckEquals(22, GetFileSize(VfsUtils.MakePath([RootDir, '\503.html'])), '{3}');
|
CheckEquals(22, GetFileSize(VfsUtils.MakePath([RootDir, '503.html'])), '{3}');
|
||||||
CheckEquals(318, GetFileSize(VfsUtils.MakePath([RootDir, '\default'])), '{4}');
|
CheckEquals(318, GetFileSize(VfsUtils.MakePath([RootDir, 'default'])), '{4}');
|
||||||
|
VfsDebug.WriteLog('TestGetFileAttributesEx', 'Ended');
|
||||||
end; // .procedure TestIntegrated.TestGetFileAttributesEx;
|
end; // .procedure TestIntegrated.TestGetFileAttributesEx;
|
||||||
|
|
||||||
procedure TestIntegrated.TestFilesOpenClose;
|
procedure TestIntegrated.TestFilesOpenClose;
|
||||||
@ -137,6 +141,7 @@ begin
|
|||||||
RootDir := VfsTestHelper.GetTestsRootDir;
|
RootDir := VfsTestHelper.GetTestsRootDir;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
VfsDebug.WriteLog('TestFilesOpenClose', 'Started');
|
||||||
Check(WinUtils.SetCurrentDirW(RootDir), 'Setting current directory to real path must succeed. Path: ' + RootDir);
|
Check(WinUtils.SetCurrentDirW(RootDir), 'Setting current directory to real path must succeed. Path: ' + RootDir);
|
||||||
|
|
||||||
Check(OpenFile(VfsUtils.MakePath([RootDir, 'non-existing.non'])) <= 0, 'Opening non-existing file must fail');
|
Check(OpenFile(VfsUtils.MakePath([RootDir, 'non-existing.non'])) <= 0, 'Opening non-existing file must fail');
|
||||||
@ -165,6 +170,8 @@ begin
|
|||||||
finally
|
finally
|
||||||
WinUtils.SetCurrentDirW(CurrDir);
|
WinUtils.SetCurrentDirW(CurrDir);
|
||||||
end; // .try
|
end; // .try
|
||||||
|
|
||||||
|
VfsDebug.WriteLog('TestFilesOpenClose', 'Ended');
|
||||||
end; // .procedure TestIntegrated.TestFilesOpenClose;
|
end; // .procedure TestIntegrated.TestFilesOpenClose;
|
||||||
|
|
||||||
procedure TestIntegrated.TestDirectoryListing;
|
procedure TestIntegrated.TestDirectoryListing;
|
||||||
@ -223,6 +230,7 @@ begin
|
|||||||
RootDir := VfsTestHelper.GetTestsRootDir;
|
RootDir := VfsTestHelper.GetTestsRootDir;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
VfsDebug.WriteLog('TestDirectoryListing', 'Started');
|
||||||
FileList := GetDirListing(VfsUtils.MakePath([RootDir, '*']));
|
FileList := GetDirListing(VfsUtils.MakePath([RootDir, '*']));
|
||||||
DirContents := FileList.ToText(#13#10);
|
DirContents := FileList.ToText(#13#10);
|
||||||
CheckEquals(VALID_ROOT_DIR_LISTING, DirContents);
|
CheckEquals(VALID_ROOT_DIR_LISTING, DirContents);
|
||||||
@ -242,6 +250,8 @@ begin
|
|||||||
SysUtils.FreeAndNil(FileList);
|
SysUtils.FreeAndNil(FileList);
|
||||||
SysUtils.FreeAndNil(DirListing);
|
SysUtils.FreeAndNil(DirListing);
|
||||||
end; // .try
|
end; // .try
|
||||||
|
|
||||||
|
VfsDebug.WriteLog('TestDirectoryListing', 'Ended');
|
||||||
end; // .procedure TestIntegrated.TestDirectoryListing;
|
end; // .procedure TestIntegrated.TestDirectoryListing;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|||||||
@ -331,8 +331,11 @@ end;
|
|||||||
function IsVfsActive: boolean;
|
function IsVfsActive: boolean;
|
||||||
begin
|
begin
|
||||||
result := EnterVfs;
|
result := EnterVfs;
|
||||||
|
|
||||||
|
if result then begin
|
||||||
LeaveVfs;
|
LeaveVfs;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
(* Returns real path for vfs item by its absolute virtual path or empty string. Optionally returns file info structure *)
|
(* Returns real path for vfs item by its absolute virtual path or empty string. Optionally returns file info structure *)
|
||||||
function GetVfsItemRealPath (const AbsVirtPath: WideString; {n} FileInfo: PNativeFileInfo = nil): WideString;
|
function GetVfsItemRealPath (const AbsVirtPath: WideString; {n} FileInfo: PNativeFileInfo = nil): WideString;
|
||||||
|
|||||||
@ -87,7 +87,8 @@ var
|
|||||||
RedirectedPath: WideString;
|
RedirectedPath: WideString;
|
||||||
ReplacedObjAttrs: WinNative.TObjectAttributes;
|
ReplacedObjAttrs: WinNative.TObjectAttributes;
|
||||||
FileInfo: TNativeFileInfo;
|
FileInfo: TNativeFileInfo;
|
||||||
HadTrailingDelim: boolean;
|
HadTrailingDelim_: array [0..3] of byte; // Fix Delphi bug: HadTrailingDelim causes stack 4-bytes misalignment
|
||||||
|
HadTrailingDelim: boolean absolute HadTrailingDelim_;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if VfsDebug.LoggingEnabled then begin
|
if VfsDebug.LoggingEnabled then begin
|
||||||
@ -144,7 +145,8 @@ var
|
|||||||
RedirectedPath: WideString;
|
RedirectedPath: WideString;
|
||||||
ReplacedObjAttrs: WinNative.TObjectAttributes;
|
ReplacedObjAttrs: WinNative.TObjectAttributes;
|
||||||
FileInfo: TNativeFileInfo;
|
FileInfo: TNativeFileInfo;
|
||||||
HadTrailingDelim: boolean;
|
HadTrailingDelim_: array [0..3] of byte; // Fix Delphi bug: HadTrailingDelim causes stack 4-bytes misalignment
|
||||||
|
HadTrailingDelim: boolean absolute HadTrailingDelim_;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if VfsDebug.LoggingEnabled then begin
|
if VfsDebug.LoggingEnabled then begin
|
||||||
@ -214,7 +216,8 @@ var
|
|||||||
ExpandedPath: WideString;
|
ExpandedPath: WideString;
|
||||||
RedirectedPath: WideString;
|
RedirectedPath: WideString;
|
||||||
ReplacedObjAttrs: WinNative.TObjectAttributes;
|
ReplacedObjAttrs: WinNative.TObjectAttributes;
|
||||||
HadTrailingDelim: boolean;
|
HadTrailingDelim_: array [0..3] of byte; // Fix Delphi bug: HadTrailingDelim causes stack 4-bytes misalignment
|
||||||
|
HadTrailingDelim: boolean absolute HadTrailingDelim_;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if VfsDebug.LoggingEnabled then begin
|
if VfsDebug.LoggingEnabled then begin
|
||||||
|
|||||||
@ -96,7 +96,7 @@ begin
|
|||||||
ExcludedItems := DataLib.NewDict(not Utils.OWNS_ITEMS, DataLib.CASE_SENSITIVE);
|
ExcludedItems := DataLib.NewDict(not Utils.OWNS_ITEMS, DataLib.CASE_SENSITIVE);
|
||||||
|
|
||||||
if VfsItemFound then begin
|
if VfsItemFound then begin
|
||||||
while DirListing.GetNextItem(DirItem) do begin
|
while Self.DirListing.GetNextItem(DirItem) do begin
|
||||||
ExcludedItems[WideStrToCaselessKey(DirItem.Data.FileName)] := Ptr(1);
|
ExcludedItems[WideStrToCaselessKey(DirItem.Data.FileName)] := Ptr(1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
<DCC_ObjPath>..\Lib\B2;.\Tests</DCC_ObjPath>
|
<DCC_ObjPath>..\Lib\B2;.\Tests</DCC_ObjPath>
|
||||||
<DCC_IncludePath>..\Lib\B2;.\Tests</DCC_IncludePath>
|
<DCC_IncludePath>..\Lib\B2;.\Tests</DCC_IncludePath>
|
||||||
<DCC_MapFile>3</DCC_MapFile>
|
<DCC_MapFile>3</DCC_MapFile>
|
||||||
<DCC_Optimize>False</DCC_Optimize>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<Borland.Personality>Delphi.Personality</Borland.Personality>
|
<Borland.Personality>Delphi.Personality</Borland.Personality>
|
||||||
@ -58,6 +57,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1 +1,10 @@
|
|||||||
UTF-8 Logging
|
UTF-8 Logging
|
||||||
|
|
||||||
|
Editor/Development mode:
|
||||||
|
Separate thread with FindFirstChangeNotificationA/FindNextChangeNotification on mods root dir + WaitForSingleObject
|
||||||
|
+ ResetVfs + BlockVfs + MapDir for each cached mapped directory + RunVfs.
|
||||||
|
We will need some API like RefreshVfs.
|
||||||
|
|
||||||
|
Add ANSI versions of exported API.
|
||||||
|
|
||||||
|
Write VfsImport.pas nad vfs_import.c
|
||||||
Loading…
Reference in New Issue
Block a user