Added more high-level exported API. VFS.dll is built

This commit is contained in:
Berserker 2019-05-14 21:58:27 +03:00
parent 745737abdf
commit 081194c185
9 changed files with 446 additions and 171 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
*.dcu *.dcu
*.exe *.exe
*.dll
*.ini *.ini
*.identcache *.identcache
*.map *.map

View File

@ -1,156 +0,0 @@
unit VfsControl;
(*
Facade unit for high-level VFS API.
*)
(***) interface (***)
uses
Windows, SysUtils,
Utils, WinUtils, TypeWrappers, DataLib,
Files, StrLib,
VfsBase, VfsUtils, VfsHooks, DlgMes {FIXME DELETEME};
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 *)
function RunVfs (DirListingOrder: VfsBase.TDirListingSortType): boolean; stdcall;
(***) implementation (***)
function RunVfs (DirListingOrder: VfsBase.TDirListingSortType): boolean; stdcall;
var
CurrDir: WideString;
begin
with VfsBase.VfsCritSection do begin
Enter;
result := VfsBase.RunVfs(DirListingOrder);
if result then begin
VfsHooks.InstallHooks;
// Try to ensure, that current directory handle is tracked by VfsOpenFiles
CurrDir := WinUtils.GetCurrentDirW;
if CurrDir <> '' then begin
WinUtils.SetCurrentDirW(CurrDir);
end;
end;
Leave;
end; // .with
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} var {out} ModList: DataLib.TList {of (O) TWideString}): boolean;
// var
// AbsFilePath: WideString;
// FileHandle: integer;
// FileContents: string;
// Lines: Utils.TArrayOfStr;
// ModNameUtf8: string;
// ModName: WideString;
// i: integer;
// // FIXME ModList is not result
// begin
// result := DataLib.NewList(Utils.OWNS_ITEMS);
// // * * * * * //
// AbsFilePath := VfsUtils.NormalizePath(ModListFilePath);
// FileHandle := Windows.CreateFileW(PWideChar(AbsFilePath), Windows.GENERIC_READ, Windows.FILE_SHARE_READ, nil, Windows.OPEN_EXISTING, 0, nil);
// // Make available UNICODE path
// // Make UTF8 BOM support EF BB BF
// 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.TrimW(StrLib.Utf8ToWide(ModNameUtf8, StrLib.FAIL_ON_ERROR));
// if ValidateModName(ModName) then begin
// result.Add(TWideString.Create(ModName));
// end;
// end;
// end;
// end; // .function LoadModList
function MapModsFromList_ (const RootDir, ModsDir: WideString; ModList: TList {of (O) TWideString}; Flags: integer = 0): boolean;
var
AbsRootDir: WideString;
AbsModsDir: WideString;
FileInfo: VfsUtils.TNativeFileInfo;
ModName: WideString;
ModPathPrefix: WideString;
NumFailedMappings: integer;
i: integer;
begin
{!} Assert(ModList <> nil);
// * * * * * //
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
ModPathPrefix := VfsUtils.AddBackslash(AbsModsDir);
NumFailedMappings := 0;
for i := ModList.Count - 1 downto 0 do begin
ModName := TWideString(ModList[i]).Value;
if not VfsBase.MapDir(AbsRootDir, ModPathPrefix + ModName, not VfsBase.OVERWRITE_EXISTING, Flags) then begin
Inc(NumFailedMappings);
end;
end;
result := (NumFailedMappings = 0) or (NumFailedMappings < ModList.Count);
end; // .if
end; // .function MapModsFromList
function MapModsFromList (const RootDir, ModsDir, ModListFile: WideString; Flags: integer = 0): boolean;
begin
end;
var
L: TList;
i: integer;
begin
end.

View File

@ -3,7 +3,7 @@ library Vfs;
Author: Alexander Shostak aka Berserker aka EtherniDee. Author: Alexander Shostak aka Berserker aka EtherniDee.
*) *)
uses Windows; uses VfsExport;
begin begin
System.IsMultiThread := true; System.IsMultiThread := true;

View File

@ -16,14 +16,12 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<Version>7.0</Version> <Version>7.0</Version>
<DCC_Define>DEBUG</DCC_Define>
<DCC_IOChecking>False</DCC_IOChecking> <DCC_IOChecking>False</DCC_IOChecking>
<DCC_WriteableConstants>True</DCC_WriteableConstants> <DCC_WriteableConstants>True</DCC_WriteableConstants>
<DCC_Optimize>False</DCC_Optimize> <DCC_UnitSearchPath>..\Lib\B2</DCC_UnitSearchPath>
<DCC_UnitSearchPath>..\Lib\B2;.\Png</DCC_UnitSearchPath> <DCC_ResourcePath>..\Lib\B2</DCC_ResourcePath>
<DCC_ResourcePath>..\Lib\B2;.\Png</DCC_ResourcePath> <DCC_ObjPath>..\Lib\B2</DCC_ObjPath>
<DCC_ObjPath>..\Lib\B2;.\Png</DCC_ObjPath> <DCC_IncludePath>..\Lib\B2</DCC_IncludePath>
<DCC_IncludePath>..\Lib\B2;.\Png</DCC_IncludePath>
<DCC_MapFile>3</DCC_MapFile> <DCC_MapFile>3</DCC_MapFile>
</PropertyGroup> </PropertyGroup>
<ProjectExtensions> <ProjectExtensions>
@ -33,6 +31,10 @@
<BorlandProject><Delphi.Personality><Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</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"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.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">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</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"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.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>
<Excluded_Packages Name="$(BDS)\bin\dcloffice2k100.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages> <Excluded_Packages Name="$(BDS)\bin\dcloffice2k100.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDS)\bin\dclofficexp100.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages> <Excluded_Packages Name="$(BDS)\bin\dclofficexp100.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages></Delphi.Personality></BorlandProject></BorlandProject> </Excluded_Packages></Delphi.Personality></BorlandProject></BorlandProject>

213
Vfs.drc
View File

@ -8,3 +8,216 @@
resources were bound to the produced executable. resources were bound to the produced executable.
*/ */
#define RTLConsts_SInvalidPropertyValue 65424
#define RTLConsts_SListCapacityError 65425
#define RTLConsts_SListCountError 65426
#define RTLConsts_SListIndexError 65427
#define RTLConsts_SReadError 65428
#define RTLConsts_SSeekNotImplemented 65429
#define RTLConsts_SSortedListError 65430
#define RTLConsts_SWriteError 65431
#define SysConst_SShortDayNameTue 65440
#define SysConst_SShortDayNameWed 65441
#define SysConst_SShortDayNameThu 65442
#define SysConst_SShortDayNameFri 65443
#define SysConst_SShortDayNameSat 65444
#define SysConst_SLongDayNameSun 65445
#define SysConst_SLongDayNameMon 65446
#define SysConst_SLongDayNameTue 65447
#define SysConst_SLongDayNameWed 65448
#define SysConst_SLongDayNameThu 65449
#define SysConst_SLongDayNameFri 65450
#define SysConst_SLongDayNameSat 65451
#define RTLConsts_SAssignError 65452
#define RTLConsts_SDuplicateString 65453
#define RTLConsts_SFCreateErrorEx 65454
#define RTLConsts_SFOpenErrorEx 65455
#define SysConst_SShortMonthNameNov 65456
#define SysConst_SShortMonthNameDec 65457
#define SysConst_SLongMonthNameJan 65458
#define SysConst_SLongMonthNameFeb 65459
#define SysConst_SLongMonthNameMar 65460
#define SysConst_SLongMonthNameApr 65461
#define SysConst_SLongMonthNameMay 65462
#define SysConst_SLongMonthNameJun 65463
#define SysConst_SLongMonthNameJul 65464
#define SysConst_SLongMonthNameAug 65465
#define SysConst_SLongMonthNameSep 65466
#define SysConst_SLongMonthNameOct 65467
#define SysConst_SLongMonthNameNov 65468
#define SysConst_SLongMonthNameDec 65469
#define SysConst_SShortDayNameSun 65470
#define SysConst_SShortDayNameMon 65471
#define SysConst_SSafecallException 65472
#define SysConst_SAssertError 65473
#define SysConst_SAbstractError 65474
#define SysConst_SModuleAccessViolation 65475
#define SysConst_SOSError 65476
#define SysConst_SUnkOSError 65477
#define SysConst_SShortMonthNameJan 65478
#define SysConst_SShortMonthNameFeb 65479
#define SysConst_SShortMonthNameMar 65480
#define SysConst_SShortMonthNameApr 65481
#define SysConst_SShortMonthNameMay 65482
#define SysConst_SShortMonthNameJun 65483
#define SysConst_SShortMonthNameJul 65484
#define SysConst_SShortMonthNameAug 65485
#define SysConst_SShortMonthNameSep 65486
#define SysConst_SShortMonthNameOct 65487
#define SysConst_SVarArrayCreate 65488
#define SysConst_SVarArrayBounds 65489
#define SysConst_SVarArrayLocked 65490
#define SysConst_SInvalidVarCast 65491
#define SysConst_SInvalidVarOp 65492
#define SysConst_SInvalidVarOpWithHResultWithPrefix 65493
#define SysConst_SVarTypeCouldNotConvert 65494
#define SysConst_SVarTypeConvertOverflow 65495
#define SysConst_SVarOverflow 65496
#define SysConst_SVarInvalid 65497
#define SysConst_SVarBadType 65498
#define SysConst_SVarNotImplemented 65499
#define SysConst_SVarUnexpected 65500
#define SysConst_SExternalException 65501
#define SysConst_SAssertionFailed 65502
#define SysConst_SIntfCastError 65503
#define SysConst_SOverflow 65504
#define SysConst_SUnderflow 65505
#define SysConst_SInvalidPointer 65506
#define SysConst_SInvalidCast 65507
#define SysConst_SAccessViolationArg3 65508
#define SysConst_SAccessViolationNoArg 65509
#define SysConst_SStackOverflow 65510
#define SysConst_SControlC 65511
#define SysConst_SPrivilege 65512
#define SysConst_SException 65513
#define SysConst_SExceptTitle 65514
#define SysConst_SInvalidFormat 65515
#define SysConst_SArgumentMissing 65516
#define SysConst_SDispatchError 65517
#define SysConst_SReadAccess 65518
#define SysConst_SWriteAccess 65519
#define SysConst_STimeEncodeError 65520
#define SysConst_SDateEncodeError 65521
#define SysConst_SOutOfMemory 65522
#define SysConst_SInOutError 65523
#define SysConst_SFileNotFound 65524
#define SysConst_SInvalidFilename 65525
#define SysConst_STooManyOpenFiles 65526
#define SysConst_SAccessDenied 65527
#define SysConst_SEndOfFile 65528
#define SysConst_SDiskFull 65529
#define SysConst_SInvalidInput 65530
#define SysConst_SDivByZero 65531
#define SysConst_SRangeError 65532
#define SysConst_SIntOverflow 65533
#define SysConst_SInvalidOp 65534
#define SysConst_SZeroDivide 65535
STRINGTABLE
BEGIN
RTLConsts_SInvalidPropertyValue, "Invalid property value"
RTLConsts_SListCapacityError, "List capacity out of bounds (%d)"
RTLConsts_SListCountError, "List count out of bounds (%d)"
RTLConsts_SListIndexError, "List index out of bounds (%d)"
RTLConsts_SReadError, "Stream read error"
RTLConsts_SSeekNotImplemented, "%s.Seek not implemented"
RTLConsts_SSortedListError, "Operation not allowed on sorted list"
RTLConsts_SWriteError, "Stream write error"
SysConst_SShortDayNameTue, "Tue"
SysConst_SShortDayNameWed, "Wed"
SysConst_SShortDayNameThu, "Thu"
SysConst_SShortDayNameFri, "Fri"
SysConst_SShortDayNameSat, "Sat"
SysConst_SLongDayNameSun, "Sunday"
SysConst_SLongDayNameMon, "Monday"
SysConst_SLongDayNameTue, "Tuesday"
SysConst_SLongDayNameWed, "Wednesday"
SysConst_SLongDayNameThu, "Thursday"
SysConst_SLongDayNameFri, "Friday"
SysConst_SLongDayNameSat, "Saturday"
RTLConsts_SAssignError, "Cannot assign a %s to a %s"
RTLConsts_SDuplicateString, "String list does not allow duplicates"
RTLConsts_SFCreateErrorEx, "Cannot create file \"%s\". %s"
RTLConsts_SFOpenErrorEx, "Cannot open file \"%s\". %s"
SysConst_SShortMonthNameNov, "Nov"
SysConst_SShortMonthNameDec, "Dec"
SysConst_SLongMonthNameJan, "January"
SysConst_SLongMonthNameFeb, "February"
SysConst_SLongMonthNameMar, "March"
SysConst_SLongMonthNameApr, "April"
SysConst_SLongMonthNameMay, "May"
SysConst_SLongMonthNameJun, "June"
SysConst_SLongMonthNameJul, "July"
SysConst_SLongMonthNameAug, "August"
SysConst_SLongMonthNameSep, "September"
SysConst_SLongMonthNameOct, "October"
SysConst_SLongMonthNameNov, "November"
SysConst_SLongMonthNameDec, "December"
SysConst_SShortDayNameSun, "Sun"
SysConst_SShortDayNameMon, "Mon"
SysConst_SSafecallException, "Exception in safecall method"
SysConst_SAssertError, "%s (%s, line %d)"
SysConst_SAbstractError, "Abstract Error"
SysConst_SModuleAccessViolation, "Access violation at address %p in module '%s'. %s of address %p"
SysConst_SOSError, "System Error. Code: %d.\r\n%s"
SysConst_SUnkOSError, "A call to an OS function failed"
SysConst_SShortMonthNameJan, "Jan"
SysConst_SShortMonthNameFeb, "Feb"
SysConst_SShortMonthNameMar, "Mar"
SysConst_SShortMonthNameApr, "Apr"
SysConst_SShortMonthNameMay, "May"
SysConst_SShortMonthNameJun, "Jun"
SysConst_SShortMonthNameJul, "Jul"
SysConst_SShortMonthNameAug, "Aug"
SysConst_SShortMonthNameSep, "Sep"
SysConst_SShortMonthNameOct, "Oct"
SysConst_SVarArrayCreate, "Error creating variant or safe array"
SysConst_SVarArrayBounds, "Variant or safe array index out of bounds"
SysConst_SVarArrayLocked, "Variant or safe array is locked"
SysConst_SInvalidVarCast, "Invalid variant type conversion"
SysConst_SInvalidVarOp, "Invalid variant operation"
SysConst_SInvalidVarOpWithHResultWithPrefix, "Invalid variant operation (%s%.8x)\n%s"
SysConst_SVarTypeCouldNotConvert, "Could not convert variant of type (%s) into type (%s)"
SysConst_SVarTypeConvertOverflow, "Overflow while converting variant of type (%s) into type (%s)"
SysConst_SVarOverflow, "Variant overflow"
SysConst_SVarInvalid, "Invalid argument"
SysConst_SVarBadType, "Invalid variant type"
SysConst_SVarNotImplemented, "Operation not supported"
SysConst_SVarUnexpected, "Unexpected variant error"
SysConst_SExternalException, "External exception %x"
SysConst_SAssertionFailed, "Assertion failed"
SysConst_SIntfCastError, "Interface not supported"
SysConst_SOverflow, "Floating point overflow"
SysConst_SUnderflow, "Floating point underflow"
SysConst_SInvalidPointer, "Invalid pointer operation"
SysConst_SInvalidCast, "Invalid class typecast"
SysConst_SAccessViolationArg3, "Access violation at address %p. %s of address %p"
SysConst_SAccessViolationNoArg, "Access violation"
SysConst_SStackOverflow, "Stack overflow"
SysConst_SControlC, "Control-C hit"
SysConst_SPrivilege, "Privileged instruction"
SysConst_SException, "Exception %s in module %s at %p.\r\n%s%s\r\n"
SysConst_SExceptTitle, "Application Error"
SysConst_SInvalidFormat, "Format '%s' invalid or incompatible with argument"
SysConst_SArgumentMissing, "No argument for format '%s'"
SysConst_SDispatchError, "Variant method calls not supported"
SysConst_SReadAccess, "Read"
SysConst_SWriteAccess, "Write"
SysConst_STimeEncodeError, "Invalid argument to time encode"
SysConst_SDateEncodeError, "Invalid argument to date encode"
SysConst_SOutOfMemory, "Out of memory"
SysConst_SInOutError, "I/O error %d"
SysConst_SFileNotFound, "File not found"
SysConst_SInvalidFilename, "Invalid filename"
SysConst_STooManyOpenFiles, "Too many open files"
SysConst_SAccessDenied, "File access denied"
SysConst_SEndOfFile, "Read beyond end of file"
SysConst_SDiskFull, "Disk full"
SysConst_SInvalidInput, "Invalid numeric input"
SysConst_SDivByZero, "Division by zero"
SysConst_SRangeError, "Range check error"
SysConst_SIntOverflow, "Integer overflow"
SysConst_SInvalidOp, "Invalid floating point operation"
SysConst_SZeroDivide, "Floating point division by zero"
END
/* D:\Soft\Programming\Delphi\source\SRC\Vfs\Vfs.drf */

View File

@ -93,14 +93,19 @@ function GetThreadVfsDisabler: TThreadVfsDisabler;
function RunVfs (DirListingOrder: TDirListingSortType): boolean; function RunVfs (DirListingOrder: TDirListingSortType): boolean;
(* Temporarily pauses VFS, but does not reset existing mappings *) (* Temporarily pauses VFS, but does not reset existing mappings *)
function PauseVfs: boolean; stdcall; function PauseVfs: LONGBOOL; stdcall;
(* Stops VFS and clears all mappings *) (* Stops VFS and clears all mappings *)
function ResetVfs: boolean; stdcall; function ResetVfs: LONGBOOL; stdcall;
(* Returns true if VFS is active globally and for current thread *) (* Returns true if VFS is active globally and for current thread *)
function IsVfsActive: boolean; function IsVfsActive: boolean;
function EnterVfs: boolean;
procedure LeaveVfs;
function EnterVfsConfig: boolean;
procedure LeaveVfsConfig;
(* 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;
@ -315,7 +320,7 @@ begin
end; // .if end; // .if
end; // .function RunVfs end; // .function RunVfs
function PauseVfs: boolean; stdcall; function PauseVfs: LONGBOOL; stdcall;
begin begin
result := not DisableVfsForThisThread; result := not DisableVfsForThisThread;
@ -328,7 +333,7 @@ begin
end; end;
end; end;
function ResetVfs: boolean; stdcall; function ResetVfs: LONGBOOL; stdcall;
begin begin
result := not DisableVfsForThisThread; result := not DisableVfsForThisThread;

184
VfsControl.pas Normal file
View File

@ -0,0 +1,184 @@
unit VfsControl;
(*
Facade unit for high-level VFS API.
*)
(***) interface (***)
uses
Windows, SysUtils,
Utils, WinUtils, TypeWrappers, DataLib,
Files, StrLib,
VfsBase, VfsUtils, VfsHooks, DlgMes {FIXME DELETEME};
type
(* Import *)
TWideString = TypeWrappers.TWideString;
(* Runs all VFS subsystems, unless VFS is already running *)
function RunVfs (DirListingOrder: VfsBase.TDirListingSortType): LONGBOOL; stdcall;
(* Loads mod list from file and maps each mod directory to specified root directory.
File with mod list is treated as (BOM or BOM-less) UTF-8 plain text file, where each mod name is separated
from another one via Line Feed (#10) character. Each mod named is trimmed, converted to UCS16 and validated before
adding to list. Invalid or empty mods will be skipped.
Returns true if root and mods directory existed and file with mod list was loaded successfully *)
function MapModsFromList (const RootDir, ModsDir, ModListFile: WideString; Flags: integer = 0): boolean;
(***) implementation (***)
type
TModList = DataLib.TList {of (O) TWideString};
function RunVfs (DirListingOrder: VfsBase.TDirListingSortType): LONGBOOL; stdcall;
var
CurrDir: WideString;
begin
with VfsBase.VfsCritSection do begin
Enter;
result := VfsBase.RunVfs(DirListingOrder);
if result then begin
VfsHooks.InstallHooks;
// Try to ensure, that current directory handle is tracked by VfsOpenFiles
CurrDir := WinUtils.GetCurrentDirW;
if CurrDir <> '' then begin
WinUtils.SetCurrentDirW(CurrDir);
end;
end;
Leave;
end; // .with
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} var {out} ModList: TModList): boolean;
const
UTF8_BOM = #$EF#$BB#$BF;
var
{O} OpenedFile: Files.TFile;
AbsFilePath: WideString;
FileHandle: integer;
FileContents: string;
Lines: Utils.TArrayOfStr;
ModNameUtf8: string;
ModName: WideString;
i: integer;
begin
OpenedFile := Files.TFile.Create;
// * * * * * //
AbsFilePath := VfsUtils.NormalizePath(ModListFilePath);
FileHandle := integer(Windows.INVALID_HANDLE_VALUE);
result := AbsFilePath <> '';
if result then begin
FileHandle := Windows.CreateFileW(PWideChar(AbsFilePath), Windows.GENERIC_READ, Windows.FILE_SHARE_READ, nil, Windows.OPEN_EXISTING, 0, 0);
result := FileHandle <> integer(Windows.INVALID_HANDLE_VALUE);
end;
if result then begin
result := Files.ReadFileContents(FileHandle, FileContents);
if result then begin
SysUtils.FreeAndNil(ModList);
ModList := DataLib.NewList(Utils.OWNS_ITEMS);
if (Length(FileContents) >= 3) and (FileContents[1] = UTF8_BOM[1]) and (FileContents[2] = UTF8_BOM[2]) and (FileContents[3] = UTF8_BOM[3]) then begin
FileContents := Copy(FileContents, Length(UTF8_BOM) + 1);
end;
Lines := StrLib.Explode(FileContents, #10);
for i := 0 to High(Lines) do begin
ModNameUtf8 := Lines[i];
ModName := StrLib.TrimW(StrLib.Utf8ToWide(ModNameUtf8, StrLib.FAIL_ON_ERROR));
if ValidateModName(ModName) then begin
ModList.Add(TWideString.Create(ModName));
end;
end;
end;
Windows.CloseHandle(FileHandle);
end; // .if
// * * * * * //
SysUtils.FreeAndNil(OpenedFile);
end; // .function LoadModList
function MapModsFromList_ (const RootDir, ModsDir: WideString; ModList: TModList; Flags: integer = 0): boolean;
var
AbsRootDir: WideString;
AbsModsDir: WideString;
FileInfo: VfsUtils.TNativeFileInfo;
ModName: WideString;
ModPathPrefix: WideString;
i: integer;
begin
{!} Assert(ModList <> nil);
// * * * * * //
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);
if result then begin
ModPathPrefix := VfsUtils.AddBackslash(AbsModsDir);
for i := ModList.Count - 1 downto 0 do begin
ModName := TWideString(ModList[i]).Value;
VfsBase.MapDir(AbsRootDir, ModPathPrefix + ModName, not VfsBase.OVERWRITE_EXISTING, Flags);
end;
end; // .if
end; // .function MapModsFromList
function MapModsFromList (const RootDir, ModsDir, ModListFile: WideString; Flags: integer = 0): boolean;
var
{O} ModList: TModList;
begin
ModList := nil;
// * * * * * //
result := VfsBase.EnterVfsConfig;
if result then begin
try
result := LoadModList(ModListFile, ModList) and MapModsFromList_(RootDir, ModsDir, ModList, Flags);
finally
VfsBase.LeaveVfsConfig;
end;
end;
// * * * * * //
SysUtils.FreeAndNil(ModList);
end; // .function MapModsFromList
end.

View File

@ -7,7 +7,8 @@ unit VfsExport;
(***) interface (***) (***) interface (***)
uses uses
VfsDebug, VfsBase, VfsControl; Windows,
VfsDebug, VfsBase, VfsControl, DlgMes, Files, FilesEx;
exports exports
VfsDebug.SetLoggingProc, VfsDebug.SetLoggingProc,
@ -21,12 +22,36 @@ exports
(***) implementation (***) (***) implementation (***)
function MapDir (const VirtPath, RealPath: PWideChar; OverwriteExisting: boolean; Flags: integer = 0): boolean; stdcall; function MapDir (const VirtPath, RealPath: PWideChar; OverwriteExisting: boolean; Flags: integer = 0): LONGBOOL; stdcall;
begin begin
result := VfsBase.MapDir(WideString(VirtPath), WideString(RealPath), OverwriteExisting, Flags); result := VfsBase.MapDir(WideString(VirtPath), WideString(RealPath), OverwriteExisting, Flags);
end; end;
exports function MapDirA (const VirtPath, RealPath: PAnsiChar; OverwriteExisting: boolean; Flags: integer = 0): LONGBOOL; stdcall;
MapDir; begin
result := VfsBase.MapDir(WideString(VirtPath), WideString(RealPath), OverwriteExisting, Flags);
end;
function MapModsFromList (const RootDir, ModsDir, ModListFile: PWideChar; Flags: integer = 0): LONGBOOL; stdcall;
begin
result := VfsControl.MapModsFromList(WideString(RootDir), WideString(ModsDir), WideString(ModListFile), Flags);
end;
function MapModsFromListA (const RootDir, ModsDir, ModListFile: PAnsiChar; Flags: integer = 0): LONGBOOL; stdcall;
begin
result := VfsControl.MapModsFromList(WideString(RootDir), WideString(ModsDir), WideString(ModListFile), Flags);
end;
exports
MapDir,
MapDirA,
MapModsFromList,
MapModsFromListA;
// var s: string;
// begin
// assert(MapModsFromListA('D:\Heroes 3', 'D:\Heroes 3\Mods', 'D:\Heroes 3\Mods\list.txt'));
// VfsControl.RunVfs(SORT_FIFO);
// ReadFileContents('D:\Heroes 3\Data\s\pHoenix.erm', s);
// VarDump([GetFileList('D:\Heroes 3\Data\s\*', FILES_AND_DIRS).ToText(#13#10)]);
end. end.

View File

@ -633,6 +633,7 @@ begin
end; end;
initialization initialization
System.IsMultiThread := true;
HooksCritSection.Init; HooksCritSection.Init;
finalization finalization
with VfsBase.VfsCritSection do begin with VfsBase.VfsCritSection do begin