2999 lines
90 KiB
Plaintext
2999 lines
90 KiB
Plaintext
{$X+,B-,V-} {essential compiler directives}
|
|
|
|
Unit nwFile;
|
|
|
|
{ nwFile unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R. Spronk }
|
|
|
|
INTERFACE
|
|
{ Primary Functions Interrupt: comments:
|
|
|
|
Volume Management (Volume Tables)
|
|
---------------------------------
|
|
|
|
* ClearObjectVolRestriction (F216/22) (3) [aka ClearVolumeRestrictions/RemoveObjectDiskRestrictions]
|
|
* GetObjectVolRestriction (F216/29) (3) [aka GetObjDiskRestrictions/GetObjectDiskUsageAndRestrictions]
|
|
* GetVolumeName (F216/06)
|
|
* GetVolumeNameWithHandle (F216/15) [aka GetVolumeInfoWithHandle]
|
|
* GetVolumeNumber (F216/05)
|
|
* GetVolumeUsage (F216/2C) (3) [aka GetExtendedVolumeInformation]
|
|
* IsVolumeRemovable (F212) [aka GetVolumeInfoWithNumber]
|
|
* ScanVolForRestrictions (F216/20) (3)
|
|
* SetObjectVolRestriction (F216/21) (3) [aka SetVolumeRestrictions/SetObjectVolSpaceLimit
|
|
/AddUserDiskspaceRestriction]
|
|
|
|
Directory Handles (Directory Handle Table/Drive tables)
|
|
-------------------------------------------------------
|
|
|
|
* AllocPermanentDirHandle (F216/12)
|
|
* AllocTemporaryDirHandle (F216/13)
|
|
* DeallocateDirHandle (F216/14)
|
|
* DeleteFakeRootDirectory (E906)
|
|
* GetDirectoryHandle (E900)
|
|
* GetDriveConnectionId (EF02)
|
|
* GetDirectoryPath (F216/01)
|
|
* GetDriveFlag (EF01) (6)
|
|
* GetDriveHandle (EF00) (6)
|
|
* GetRelativeDriveDepth (E907)
|
|
* GetSearchDriveVector (E901)
|
|
* MapFakeRootDirectory (E905)
|
|
* SetDirectoryHandle (F216/00)
|
|
* SetDriveConnectionId (EF02)
|
|
* SetDriveFlag (EF01)
|
|
* SetDriveHandle (EF00)
|
|
* SetSearchDriveVector (E902)
|
|
|
|
Secondary Functions
|
|
|
|
* DeleteConnectionsDriveMappings
|
|
* DeleteDriveMapping
|
|
* GetEnvPath (BA..)
|
|
* IsSearchDrive (BA..)
|
|
* IsNetworkDrive (4409)
|
|
* MapDrive
|
|
* MapPermanentDrive
|
|
* MapSearchDrive
|
|
* SetEnvPath (BA..)
|
|
|
|
Entries (directory/file management)
|
|
-----------------------------------
|
|
|
|
* ChangeDirectory (3B..) (DOS)
|
|
* ConvertPathToDirEntryId (F217/F4)
|
|
* CreateDirectory (F216/0A)
|
|
* DeleteDirectory (F216/0B)
|
|
* EraseFiles (F244)
|
|
. FileServerFileCopy (F3..)
|
|
GetDirectoryInfo (F216/2D) (3)
|
|
* GetDirectoryEntry (F216/1F) (3)
|
|
. GetExtendedFileAttributes (B600) =F24E ???
|
|
. GetFileAttributes (4300) (DOS)
|
|
* GetTrueEntryName (60..) (DOS)
|
|
* MapDirentryIdToPath (F217/F3)
|
|
MoveEntry (F216/2E) (3) dir and files
|
|
* PurgeSalvagableFile (F216/1D) (3)
|
|
* RecoverSalvagebleFile (F216/1C) (3)
|
|
* RenameDirectory (F216/0F)
|
|
* ScanDirectoryInformation (F216/02)
|
|
* ScanDirectoryEntry (F216/1E) (3)
|
|
* ScanFileInformation (F217/0F)
|
|
ScanFilePhysical (F216/28) (3)
|
|
* ScanSalvagableFiles (F216/1B) (3)
|
|
* SetEntry (F216/25) (3) dir and files
|
|
. SetExtendedFileAttributes (B601) =F24F
|
|
. SetFileAttributes (F246) [4301]
|
|
* SetFileInformation (F217/10)
|
|
|
|
* ScanDirRestrictions (F216/23) (3)
|
|
* SetDirRestriction (F216/24) (3)
|
|
|
|
Secondary functions:
|
|
|
|
DeleteFile
|
|
GetFileHandle
|
|
IsFileShareable
|
|
FlagFileShareable
|
|
PurgeFiles (by dirHandle,fileMask)
|
|
SalvageFiles (by dirHandle,fileMask)
|
|
PurgeAllErasedFiles
|
|
|
|
|
|
Trustees/Max. Rights Mask
|
|
-------------------------
|
|
|
|
* DeleteTrustee (F216/2B) (3)
|
|
* GetEffectiveRights (F216/2A) (3)
|
|
. ModifyMaximumRightsMask (F216/04)
|
|
. ScanBinderyObjectTrusteePaths (F217/47)
|
|
* ScanEntryForTrustees (F216/26) (3)
|
|
* SetTrustee (F216/27) (3)
|
|
|
|
|
|
Not Implemented:
|
|
----------------
|
|
|
|
- AddTrusteeToDirectory (F216/0D) (10)
|
|
- AllocSpecialDirHandle (F216/16) (2)
|
|
- DeleteTrusteeFromDirectory (F216/0E) (10)
|
|
- FileServerFileCopy (E6..) (8)
|
|
- GetEffectiveDirectoryRights (F216/03) (10)
|
|
- GetPathFromDirEntryID (F216/1A) (12)
|
|
- GetVolumeInformation (F217/E9) (1)
|
|
- GetVolumeInfoWithHandle (F216/15) (5)
|
|
- GetVolumeInfoWithNumber (F212) (4) [DA..]
|
|
- PurgeErasedFiles (F216/10) (8)
|
|
- PurgeAllErasedFiles (F217/CE) (8)
|
|
- RestoreDirectoryHandle (F216/18) (2)
|
|
- RestoreErasedFile (F216/11) (8)
|
|
- SaveDirectoryHandle (F216/17) (2)
|
|
- ScanDirectoryForTrustees (F216/0C) (9)
|
|
- SetDirectoryInformation (F216/19) (11)
|
|
- SetFileAttributes (E4..) (7)
|
|
- UpdateFileSize (E5..) (7)
|
|
|
|
|
|
Notes: (1) GetVolumeInformation. This call is NOT available in all 3.x versions.
|
|
(only with Nw 2.1 & 3.1x and CLIB.NLM dated before 11-11-92 )
|
|
This call is not implemented here. Replaced by GetVolumeUsage.
|
|
(2) not available in (all versions of) NW 3.x.
|
|
(3) NW 3.x (and upwards) only.
|
|
(4) Replaced by GetVolumeUsage and IsVolumeRemovable.
|
|
(5) Replaced by GetVolumeUsage and GetVolumeNameWithHandle.
|
|
(6) Information can also be obtained by calling GetDirectoryHandle.
|
|
(DOS) 'Normal' DOS call, extended by NetWare shell.
|
|
(7) Not supported by Adv.NW 3.x. Not implemented here.
|
|
These are functions using FCB's. If another function with the same
|
|
name is listed here, that function performs the same action.
|
|
(8) Not supported by Adv.NW 3.x. Not implemented here.
|
|
These functions have been replaced with calls marked (3)
|
|
(9) Replaced by a newer version: ScanEntryForTrustees.
|
|
(10) Replaced by DeleteTrustee, GetEffectiveRights and SetTrustee.
|
|
(11) Replaced by SetEntry
|
|
(12) Replaced by MapDirEntryIDtoPath
|
|
|
|
}
|
|
|
|
Uses nwIntr,nwMisc,nwBindry,nwConn;
|
|
|
|
Var Result:Word;
|
|
|
|
Type TsearchDriveVector=array [1..17] of byte;
|
|
|
|
|
|
CONST
|
|
DRIVE_UNUSED = $00;
|
|
DRIVE_PERMANENT = $01; { Drive permanently assigned to fileserver directory }
|
|
DRIVE_TEMPORARY = $02; { Drive temporary assigned to FS dir. Released by EOJ }
|
|
DRIVE_NETWORK = $03; { Normal drive mapping }
|
|
DRIVE_LOCAL = $80; { Drive is local. ! By ORing with one of the above bits,
|
|
it can be reassigned to a FS directory.}
|
|
|
|
{Name Space Type constants}
|
|
NS_DOS =0;
|
|
NS_MAC =1;
|
|
NS_NFS =2;
|
|
NS_FTAM =3;
|
|
NS_HPFS =4;
|
|
|
|
{ Attributes / Netware directory & file attributes }
|
|
A_NORMAL = $00; {file}
|
|
A_READ_ONLY = $01; {file}
|
|
A_HIDDEN = $02; {file/dir}
|
|
A_SYSTEM = $04; {file/dir}
|
|
A_EXECUTE_ONLY = $08; {file}
|
|
A_DIRECTORY = $10; {file}
|
|
A_NEEDS_ARCHIVED = $20; {file}
|
|
A_undocumented = $40;
|
|
A_SHAREABLE = $80; {file}
|
|
|
|
A_LO_SEARCH = $0100; {file}
|
|
A_MID_SEARCH = $0200; {file}
|
|
A_HI_SEARCH = $0400; {file}
|
|
A_RESERVED = $0800; {file/dir}
|
|
A_TRANSACTIONAL = $1000; {file}
|
|
A_INDEXED = $2000; {file}
|
|
A_READ_AUDIT = $4000; {file}
|
|
A_WRITE_AUDIT = $8000; {file}
|
|
|
|
A_PURGE = $010000; {file/dir}
|
|
A_RENAME_INHIBIT = $020000; {file/dir}
|
|
A_DELETE_INHIBIT = $040000; {file/dir}
|
|
A_COPY_INHIBIT = $080000; {file}
|
|
|
|
{ Trustee Attributes / directory access rights }
|
|
TA_NONE = $00;
|
|
TA_READ = $01; {R open/read}
|
|
TA_WRITE = $02; {W open/write}
|
|
TA_RESERVED = $04; { reserved, set to 0 }
|
|
TA_CREATE = $08; {C create files or dirs}
|
|
TA_DELETE = $10; {E delete files/dirs}
|
|
TA_ACCESS = $20; {A set /delete trustees}
|
|
TA_SEARCH = $40; {F directory can be searched/file is visible}
|
|
TA_MODIFY = $80; {M modify dir/file attributes}
|
|
TA_SUPERVISOR =$100; {S supervisor rights to file or directory }
|
|
|
|
{ Entry Modify flags / see SetEntry }
|
|
|
|
EM_ENTRYNAME = $00000001;
|
|
EM_ATTRIBUTES = $00000002;
|
|
EM_CREATIONTIME = $0000000C; { date = $04, time = $08 }
|
|
EM_OWNERID = $00000010;
|
|
EM_ARCHIVETIME = $00000060; { date = $20, time = $40 }
|
|
EM_ARCHIVERID = $00000080;
|
|
EM_MODIFYTIME = $00000300; { date = $0100, time =$0200 }
|
|
EM_MODIFIERID = $00000400;
|
|
EM_LASTACCESSTIME = $00000800; { date = $0800 }
|
|
EM_RIGHTSMASK = $00001000;
|
|
EM_MAXDISKSPACE = $00002000;
|
|
|
|
Type TvolUsage=record
|
|
totalBlocks, {static info}
|
|
freeBlocks, {dynamic}
|
|
purgableBlocks, {dynamic}
|
|
notYetPurgableBlocks, {dynamic}
|
|
totalDirEntries, {static}
|
|
availDirEntries, {dynamic}
|
|
Flags :LongInt; {dynamic}
|
|
SectorsPerBlock :byte; {static/number of 512 byte sectors per block}
|
|
volumeName :string[16];{static}
|
|
end;
|
|
|
|
{ used By ScanVolForRestrictions }
|
|
TobjVolRestr=array[1..64] of record
|
|
objId :LongInt;
|
|
MaxAllowedBlocks:LongInt;
|
|
end;
|
|
|
|
|
|
Type Tentry=record
|
|
EntryName :String[16];
|
|
|
|
NSType :byte; {namespace number}
|
|
DataForkSize :Longint; { =FileSize when NStype=0 (dos) }
|
|
{ResourceForkSize:Longint; (Mac data) =0 when NStype=0 (dos) }
|
|
FileSize :Longint; {FileSize=Resource+Data forksize }
|
|
|
|
Attributes :Longint;
|
|
RightsMask :word; {(4)}
|
|
|
|
CreationTime,
|
|
ArchiveTime,
|
|
ModifyTime,
|
|
LastAccessTime,
|
|
DeleteTime :TnovTime; {salvagable file only}
|
|
|
|
OwnerId,
|
|
ArchiverId,
|
|
ModifierId,
|
|
DeletorId :Longint; {salvagable file only}
|
|
|
|
end;
|
|
{ Note: (4) When used with ScanDirectoryInfo, this field
|
|
contains the MaximumRightsMask.
|
|
Otherwise, the InheritedRightsMask }
|
|
|
|
Type TdirRestrList=array[1..56] of record
|
|
Level:Byte;
|
|
MaxBlocks,
|
|
AvailableBlocks:Longint;
|
|
end;
|
|
{when MaxBlocks and Availableblocks are set to to $7FFFFFFF,
|
|
no restrictions are enforced -at this level-}
|
|
|
|
Type TtrusteeInformation=record
|
|
NumberOfTrustees:Byte;
|
|
TrusteeID :array[1..20] of Longint;
|
|
TrusteeRights:array[1..20] of Word;
|
|
end;
|
|
|
|
{-------------------- Volumes----------------------- }
|
|
{F216/05 [2.15c+]}
|
|
Function GetVolumeNumber( volumeName:String; Var volumeNumber:Byte ):boolean;
|
|
{ Returns the volume number of a given volume name }
|
|
|
|
{F216/06 [2.15c+]}
|
|
Function GetVolumeName( volumeNumber:Byte; Var volumeName:String ):boolean;
|
|
{ Returns the volume name of a give volume number [0..31].
|
|
If the volume is not mounted at the time of this call, a null-string is returned. }
|
|
|
|
{F216/2C [2.15c+]}
|
|
Function GetVolumeUsage(volumeNumber:byte; Var VolUsage: TvolUsage):boolean;
|
|
|
|
{F212 [2.15c+]}
|
|
Function IsVolumeRemovable( volumeNumber:Byte;
|
|
Var volIsRemoveable:Boolean):boolean;
|
|
|
|
{F216/15 [2.15c+]}
|
|
Function GetVolumeNameWithHandle( dirHandle:Byte;
|
|
Var volumeName:String ):boolean;
|
|
{F216/29 [3.x]}
|
|
Function GetObjectVolRestriction(VolumeNumber:byte; objId:LongInt;
|
|
Var MaxAllowedBlocks,BlocksInUse:LongInt):boolean;
|
|
|
|
{F216/21 [3.x]}
|
|
Function SetObjectVolRestriction(VolumeNumber:byte; objId,
|
|
MaxAllowedBlocks:LongInt):boolean;
|
|
{F216/22 [3.x]}
|
|
Function ClearObjectVolRestriction(VolumeNumber:byte; objId:LongInt):boolean;
|
|
|
|
|
|
{F216/20 [3.x]}
|
|
Function ScanVolForRestrictions(VolumeNumber:byte;
|
|
{i/o} Var sequenceNbr:LongInt;
|
|
{out} Var NbrOfObjects:byte;
|
|
Var ResultBuffer:TobjVolRestr):boolean;
|
|
{ 1st call: sequenceNbr=0,
|
|
after last call: sequenceNbr=0 again. }
|
|
|
|
{-------------------- Directory Handles/ Drives -------------}
|
|
|
|
{F216/01}
|
|
Function GetDirectoryPath(DirHandle:byte; Var PathName:string):boolean;
|
|
|
|
{EF00 [2.0/2.1/3.x]}
|
|
Function GetDriveHandle( DriveNumber:Byte; Var DirHandle:Byte ):boolean;
|
|
{ The call returns a pointer to the shell's Drive Handle Table. (32 bytes)
|
|
(Drives A..Z and temporary drives [\]^_' )
|
|
If a drive has been assigned a directory handle on the file server,
|
|
the handle can be found in the DHT at the position corresponding with the drive letter.}
|
|
|
|
{EF00 [2.0/2.1/3.x]}
|
|
Function SetDriveHandle( DriveNumber:Byte; DirHandle:Byte ):boolean;
|
|
|
|
{E900 [2.0/2.1/3.x]}
|
|
Function GetDirectoryHandle( DriveNumber:Byte; Var dirHandle,status:byte):Boolean;
|
|
{ Returns directory handle and status flags for a drive. }
|
|
{ Drivenumber = 0..31 (A..Z = 0..25) and temp drives (26..31) }
|
|
|
|
{EF01 [2.0/2.1/3.x]}
|
|
Function GetDriveFlag( DriveNumber:Byte; Var DriveStatus:Byte ):Boolean;
|
|
{ This call returns a pointer to the shell's Drive Flag Table (32 Bytes)
|
|
Each entry indicates a drive's status (permanent,temporary,local,unassigned)
|
|
For further explanation see the DRIVE_xxx constants.}
|
|
|
|
{EF01 [2.0/2.1/3.x]}
|
|
Function SetDriveFlag( DriveNumber:Byte; DriveStatus:Byte ):Boolean;
|
|
|
|
{F216/14 [2.15c+]}
|
|
function DeallocateDirHandle(DirHandle : Byte) : Boolean;
|
|
{ This function deletes a directory handle }
|
|
|
|
|
|
{EF02 [2.0/2.1/3.x]}
|
|
Function GetDriveConnectionID( DriveNumber:Byte; Var connID:Byte):boolean;
|
|
{ returns the servernumber (1..8) associated with a drive. }
|
|
|
|
{EF02 [2.0/2.1/3.x]}
|
|
Function SetDriveConnectionID( DriveNumber:Byte; connID:Byte):boolean;
|
|
|
|
{F216/00 [2.15c+]}
|
|
Function SetDirectoryHandle( sourceDirHandle:Byte; sourceDirPath:String;
|
|
targetDirHandle:Byte ):boolean;
|
|
{ make handle 'targetHandle' point to the directory provided by
|
|
sourceHandle and/or sourceDirPath. }
|
|
|
|
{F216/12 [2.15c+]}
|
|
FUNCTION AllocPermanentDirHandle( DriveNumber:Byte;
|
|
DirHandle : byte; DirPath : string ;
|
|
var NewDirHandle, EffectiveRights: byte ) :boolean;
|
|
|
|
{F216/13 [2.15c+]}
|
|
function AllocTemporaryDirHandle( DriveNumber:byte;
|
|
DirHandle : Byte; DirPath : String;
|
|
var NewDirHandle,EffectiveRights : Byte) : Boolean;
|
|
{ Allocates a temporary directory handle, deleted automatically by EOJ. }
|
|
|
|
{E901}
|
|
Function GetSearchDriveVector(Var vector:TsearchDriveVector):boolean;
|
|
|
|
{E902 }
|
|
Function SetSearchDriveVector(vector:TsearchDriveVector):boolean;
|
|
|
|
{E905 (shell 3.01+)}
|
|
Function MapFakeRootDirectory(DriveNumber:byte; DirPath:string):boolean;
|
|
|
|
{E906 (shell 3.01+)}
|
|
Function DeleteFakeRootDirectory(DriveNumber:byte):boolean;
|
|
|
|
{E907 (shell 3.01+)}
|
|
Function GetRelativeDriveDepth(DriveNumber:byte; Var depth:byte):boolean;
|
|
|
|
{BA.. }
|
|
Function GetEnvPath(Var EnvPath:string):boolean;
|
|
|
|
{BA.. }
|
|
Function SetEnvPath(EnvPath:string):boolean;
|
|
|
|
|
|
{secondary }
|
|
FUNCTION MapDrive(DriveNumber:byte; DirectoryPath:string;
|
|
Root, Permanent:boolean):boolean;
|
|
|
|
{secondary }
|
|
FUNCTION MapPermanentDrive(DriveNumber:byte; DirectoryPath:string;
|
|
Root:boolean):boolean;
|
|
|
|
{secondary}
|
|
Function MapSearchDrive(DriveNumber:byte; DirPath:string;
|
|
PathPosition:byte;
|
|
Insert,Root,Permanent:Boolean):boolean;
|
|
|
|
{secondary}
|
|
Function DeleteDriveMapping(DriveNumber:Byte):boolean;
|
|
|
|
{secondary}
|
|
Function DeleteConnectionsDriveMappings(ConnId:Byte):Boolean;
|
|
|
|
{secondary}
|
|
Function IsSearchDrive(DriveNumber:byte):boolean;
|
|
|
|
{4409 }
|
|
Function IsNetworkDrive(driveNumber:Byte):boolean;
|
|
{ isNetworkDrive is set to TRUE if the drive is a) a network drive, and
|
|
b) a legal drive letter was used. }
|
|
|
|
|
|
{------------------------- entries -----------------------------------------}
|
|
|
|
{F217/0F [2.15c+]}
|
|
Function ScanFileInformation(DirHandle:Byte; FilePath:string;
|
|
SearchAttrib:Byte;
|
|
{i/o} VAR SequenceNbr:Integer;
|
|
{out} VAR fileInfo:Tentry):Boolean;
|
|
|
|
{F217/F4 [3.0+]}
|
|
Function ConvertPathToDirEntryId(dirHandle:Byte; dirPath:string;
|
|
Var VolNbr :byte;
|
|
Var dirEntryID:LongInt):boolean;
|
|
{ aka ConvertPathToDirEntry / requires console rights }
|
|
|
|
{F216/02}
|
|
Function ScanDirectoryInformation(dirHandle:byte; searchDirPath:string;
|
|
{i/o} Var sequenceNumber:word;
|
|
{out:} Var dirInfo:Tentry ):boolean;
|
|
|
|
{F216/1F [2.15c+]}
|
|
Function GetDirectoryEntry(DirHandle:byte;
|
|
Var dirEntry:Tentry):boolean;
|
|
|
|
{F216/1E [2.15c+]}
|
|
Function ScanDirectoryEntry(DirHandle:Byte; EntryName:string; SearchFlags:Longint;
|
|
{i/o} Var EntryId:Longint;
|
|
{out} Var Entry:Tentry ):boolean;
|
|
|
|
{F217/F3 [3.0+]}
|
|
Function MapDirEntryIdToPath(VolNbr:byte;DirEntryId:Longint; NStype:byte;
|
|
Var ExtPath:string):boolean;
|
|
|
|
{F216/25 [2.15c+] }
|
|
Function SetEntry(DirHandle:Byte;EntryId:Longint;SearchFlags:Byte;
|
|
ModFlags:Longint; Entry:Tentry ):boolean;
|
|
|
|
{F217/10 [2.15c+]}
|
|
Function SetFileInformation(DirHandle:Byte; FilePath:string;
|
|
SearchAttrib:Byte;
|
|
fileInfo:TEntry):boolean;
|
|
|
|
{F216/1B [2.15c+]}
|
|
Function ScanSalvagableFiles(DirHandle:Byte;
|
|
{i/o} Var EntryId:Longint;
|
|
{out} Var Entry:Tentry ):boolean;
|
|
|
|
{F216/1D [3.0+]}
|
|
Function PurgeSalvagableFile(DirHandle:Byte;
|
|
EntryId:Longint; FileName:string):boolean;
|
|
|
|
{F216/1C [3.0+] }
|
|
Function RecoverSalvagableFile(dirHandle:Byte; EntryId:Longint;
|
|
OldName,NewName:string):boolean;
|
|
|
|
{F244 [2.1x/3.x]}
|
|
Function EraseFiles(dirHandle, searchAttrib:Byte; filePath:string ):boolean;
|
|
|
|
{60.. (extended DOS call)}
|
|
Function GetTrueEntryName(DirPath:string; Var CanonicalPath:string):boolean;
|
|
|
|
|
|
{F216/0F [2.0/2.1/3.x]}
|
|
Function RenameDirectory( dirHandle:Byte; dirPath, newDirName :String):Boolean;
|
|
|
|
{F216/0B [2.15c+]}
|
|
Function DeleteDirectory(DirHandle:Byte; DirPath:string):boolean;
|
|
|
|
{F216/0A [2.15+]}
|
|
Function CreateDirectory(DirHandle:Byte; DirPath:string; MaxRightsMask:byte):boolean;
|
|
|
|
{3B.. }
|
|
Function ChangeDirectory(DirPath:string):boolean;
|
|
|
|
|
|
{F216/24 [3.0+]}
|
|
Function SetDirRestriction(DirHandle:Byte; DiskSpaceLimit:Longint):boolean;
|
|
|
|
{F216/23 [3.0+]}
|
|
Function ScanDirRestrictions(DirHandle:Byte;
|
|
Var NumberOfEntries:Byte;
|
|
Var RestrInfo:TdirRestrList):boolean;
|
|
|
|
{--------------------------- Rights/trustees ---------------------------}
|
|
|
|
{F216/27 [3.0+]}
|
|
Function SetTrustee(DirHandle:Byte;DirPath:string;
|
|
TrusteeObjectID:Longint;
|
|
RightsMask:Word ):boolean;
|
|
|
|
{F216/2B [3.0+]}
|
|
Function DeleteTrustee(DirHandle:Byte;DirPath:String;
|
|
TrusteeObjectId:Longint):boolean;
|
|
|
|
{F216/2A [3.0+]}
|
|
function GetEffectiveRights(DirHandle:Byte;DirPath:String;
|
|
var Rights:Word) : Boolean;
|
|
|
|
{F216/04 [2.15c+]}
|
|
Function ModifyMaximumRightsMask(DirHandle:Byte;DirPath:string;
|
|
RevokeRightsMask,GrantRightsMask:Word):boolean;
|
|
|
|
|
|
{F217/47 [2.15c+]}
|
|
Function ScanBinderyObjectTrusteePaths(TrusteeObjectId:Longint;
|
|
VolumeNumber:Byte;
|
|
{i/o} Var SequenceNumber:word;
|
|
{out} Var AccessMask:Word;
|
|
Var Path:string ):boolean;
|
|
|
|
{F216/26 [3.0+]}
|
|
Function ScanEntryForTrustees(DirHandle:Byte;DirPath:String;
|
|
{i/o} Var SequenceNumber:Byte;
|
|
{out} Var TrusteeInfo: TtrusteeInformation):boolean;
|
|
|
|
IMPLEMENTATION{============================================================}
|
|
|
|
{$IFDEF MSDOS}
|
|
uses dos; { file handles / 'normal' file attributes }
|
|
{$ENDIF}
|
|
|
|
Type TintEntry=record { Unit internal Entry type }
|
|
{ 0} _res1 :Longint; { low word = Dir Id of parent Dir }
|
|
{ 4} _attrib :Longint;
|
|
{ 8} _res2 :word;
|
|
{ 10} _NStype :Byte;
|
|
{ 11} _name :string[12];
|
|
{ 24} _creationTime :Longint;
|
|
{ 28} _OwnerId :Longint; { hi-lo}
|
|
{ 32} _ArchiveTime :Longint;
|
|
{ 36} _ArchiverId :Longint; { hi-lo}
|
|
{ 40} _modifyTime :Longint;
|
|
|
|
{ 44} _ModifierId :Longint; { files only }
|
|
{ 48} _ForkSize :Longint; { files only }
|
|
{ 52} _res3 :array[1..44] of byte; { Trustee obj IDs and Tr. rights }
|
|
{ 96} _FileRightsMask:word; { files only }
|
|
{ 98} _AccessDate :word; { files only }
|
|
|
|
{100} _DirRightsMask :word; { directories only }
|
|
{102} _res4 :word; {Unique Dir ID, hi-lo} { directories only }
|
|
{104} _DeleteTime :Longint; { salvageable files only }
|
|
{108} _DeletorID :LongInt; { salvageable files only }
|
|
{112} _res5 :array[1..16] of byte;
|
|
{128} end;
|
|
|
|
Procedure Convert2ExtEntry(Var Ie:TintEntry;Var Oe:Tentry);
|
|
begin
|
|
FillChar(Oe,Sizeof(Tentry),#$0);
|
|
with Ie,Oe
|
|
do begin
|
|
Attributes:=_Attrib;
|
|
NStype:=_NStype;
|
|
Entryname:=_name;
|
|
DosTime2NovTime(_CreationTime,CreationTime);
|
|
OwnerId:=Lswap(_OwnerId); {force lo-hi}
|
|
DosTime2NovTime(_ArchiveTime,ArchiveTime);
|
|
ArchiverId:=Lswap(_ArchiverID); {force lo-hi}
|
|
DosTime2NovTime(_ModifyTime,ModifyTime);
|
|
if (_attrib and $10)>0 { is entry a directory ? }
|
|
then begin
|
|
RightsMask:=_DirRightsMask;
|
|
end
|
|
else begin
|
|
ModifierId:=LSwap(_ModifierId); {force lo-hi}
|
|
DataForksize:=_Forksize;
|
|
if _NSType=0
|
|
then FileSize:=_ForkSize;
|
|
RightsMask:=_FileRightsMask;
|
|
DosTime2NovTime(MakeLong(_accessDate,0),LastAccessTime);
|
|
DosTime2NovTime(_DeleteTime,DeleteTime);
|
|
DeletorId:=Lswap(_DeletorID); {force lo-hi}
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Procedure Convert2IntEntry(Var Oe:TEntry;Var Ie:TIntEntry);
|
|
Var TempTime:Longint;
|
|
begin
|
|
FillChar(Ie,Sizeof(Tentry),#$0);
|
|
with Ie,Oe
|
|
do begin
|
|
_Attrib:=Attributes;
|
|
_NStype:=NStype;
|
|
_Name:=EntryName;
|
|
NovTime2DosTime(CreationTime,_CreationTime);
|
|
_OwnerId:=Lswap(OwnerId); {force hi-lo}
|
|
NovTime2DosTime(ArchiveTime,_ArchiveTime);
|
|
_ArchiverId:=Lswap(ArchiverId); {force hi-lo}
|
|
NovTime2DosTime(ModifyTime,_ModifyTime);
|
|
if (Attributes and $10)>0 { is entry a directory ? }
|
|
then begin
|
|
_DirRightsMask:=RightsMask;
|
|
end
|
|
else begin
|
|
_ModifierId:=Lswap(ModifierId); { force hi-lo }
|
|
_ForkSize:=DataForkSize;
|
|
_FileRightsMask:=RightsMask;
|
|
NovTime2DosTime(LastAccessTime,TempTime);
|
|
_AccessDate:=HiLong(TempTime);
|
|
NovTime2DosTime(DeleteTime,_DeleteTime);
|
|
_DeletorID:=Lswap(DeletorId); { force hi-lo }
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Procedure ConvertPathToVolFormat(Var path:string);
|
|
{ reformat \\server\vol\path to VOL:PATH
|
|
server/vol:path to VOL:PATH }
|
|
Var pcolon,pslash:byte;
|
|
begin
|
|
if (Path[0]>#1) and (Path[1]='\') and (Path[2]='\')
|
|
then begin
|
|
delete(Path,1,2);
|
|
Path:=Path+'\';
|
|
pslash:=pos('\',Path);
|
|
if pslash>0
|
|
then begin
|
|
delete(Path,1,pslash); { remove servername from path }
|
|
pslash:=pos('\',Path);
|
|
if pslash>0
|
|
then Path:=copy(Path,1,pslash-1)+':'+copy(Path,pslash+1,255);
|
|
end;
|
|
while Path[ord(Path[0])]='\' do dec(Path[0]);
|
|
end
|
|
else begin
|
|
pcolon:=pos(':',path);
|
|
if (path[0]>#3) and (pcolon>3)
|
|
then begin
|
|
pslash:=pos('/',path);
|
|
if (pslash=0) or (pslash>pcolon)
|
|
then pslash:=pos('\',path);
|
|
if (pslash>0) and (pslash<pcolon)
|
|
then delete(path,1,pslash); { remove 'server/' }
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
{------------------ Volume Management --------------------------------------}
|
|
|
|
|
|
{F216/2C [2.15c+]}
|
|
Function GetVolumeUsage(VolumeNumber:byte; Var VolUsage: TvolUsage):boolean;
|
|
Type Treq=record
|
|
len:word;
|
|
subf:byte;
|
|
volNbr:byte;
|
|
end;
|
|
Trep=TvolUsage;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
begin
|
|
with TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subf:=$2C;
|
|
volNbr:=VolumeNumber;
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
|
|
VolUsage:=TPrep(GlobalReplyBuf)^;
|
|
IF (Volusage.totalBlocks=0)
|
|
or (volusage.volumename='')
|
|
then result:=$98;
|
|
GetVolumeUsage:=(result=0);
|
|
{resultcodes:
|
|
00 success; 98h Volume doesn't exist / not mounted }
|
|
end;
|
|
|
|
|
|
{F216/06 [2.15c+]}
|
|
Function GetVolumeName(volumeNumber:Byte; Var volumeName:String ):boolean;
|
|
{ Returns the volume name of a give volume number [0..31].
|
|
If the volume name doesn't exist, or the volume is not mounted
|
|
at the time of this call, an error $98 results and volName is set to '' }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
volNbr :Byte;
|
|
end;
|
|
Trep=record
|
|
_volName:String[16];
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$06;
|
|
volNbr:=volumeNumber
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
|
|
volumeName:=TPrep(GlobalReplyBuf)^._volName;
|
|
if volumeName=''
|
|
then result:=$98;
|
|
GetVolumeName:=(result=0)
|
|
{resultcodes:
|
|
00 success; 98h Volume doesn't exist / not mounted }
|
|
end;
|
|
|
|
|
|
|
|
{F216/05 [2.15c+]}
|
|
Function GetVolumeNumber( volumeName:String; Var volumeNumber:Byte ):boolean;
|
|
{ Returns the volume number [0..31] of a given volume name.
|
|
The volumename can have a maximum of 16 characters. Wildcards are
|
|
allowed, the volume number of the first match will be returned.
|
|
The name of the volume may be supplied with ('SYS:') or without
|
|
the colon ('SYS'). }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
volName :String[16];
|
|
end;
|
|
Trep=record
|
|
volNbr :Byte;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$05;
|
|
if volumeName[0]>#16
|
|
then volumeName[0]:=#16;
|
|
volName:=volumeName;
|
|
if volname[ord(volName[0])]=':'
|
|
then dec(volName[0]);
|
|
len:=2+ord(volName[0]);
|
|
F2SystemCall($16,len+2,SizeOf(Trep),result);
|
|
end;
|
|
volumenumber:=TPrep(GlobalReplyBuf)^.volNbr;
|
|
getVolumeNumber:=(result=0)
|
|
{resultcodes:
|
|
00 success; 98h volume doesn't exist }
|
|
end;
|
|
|
|
|
|
{F216/15 [2.15c+]}
|
|
Function GetVolumeNameWithHandle( dirHandle:Byte;
|
|
Var volumeName:String ):boolean;
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_dirHandle :Byte;
|
|
end;
|
|
Trep=record
|
|
_sectPerBlock :Word; {hi-lo}
|
|
_TotalBlocks :Word; {hi-lo}
|
|
_availBlocks :Word; {hi-lo} { Use GetVolumeUsage for the other fields }
|
|
_TotalDirSlots:Word; {hi-lo}
|
|
_availDirSlots:Word; {hi-lo}
|
|
_volName :array[1..16] of byte;
|
|
_volRemoveable:Word; {hi-lo}
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$15;
|
|
_dirHandle:=dirHandle;
|
|
end;
|
|
F2SystemCall($16,Sizeof(Treq),SizeOf(Trep),result);
|
|
ZStrCopy(volumeName,TPrep(GlobalReplyBuf)^._volName,16);
|
|
if volumeName=''
|
|
then result:=$9B; { Invalid directory handle }
|
|
getVolumeNameWithHandle:=(result=0)
|
|
{ resultcodes: 00 success; $9B invalid directory handle }
|
|
end;
|
|
|
|
|
|
{F212 [2.15c+]}
|
|
Function IsVolumeRemovable( volumeNumber:Byte;
|
|
Var volIsRemoveable:Boolean):boolean;
|
|
{ stripped down version of the GetVolumeInfoWithNumber call }
|
|
Type Treq=Byte;
|
|
Trep=record
|
|
_sectPerBlock :Word; {hi-lo}
|
|
_TotalBlocks :Word; {hi-lo}
|
|
_availBlocks :Word; {hi-lo}
|
|
_TotalDirSlots :Word; {hi-lo}
|
|
_availDirSlots :Word; {hi-lo}
|
|
_volName :array[1..16] of byte;
|
|
_volRemoveable :Word; {hi-lo}
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
TPreq(GlobalReqBuf)^:=volumeNumber;
|
|
F2SystemCall($12,SizeOf(Treq),SizeOf(Trep),result);
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
volIsRemoveable:=(_volRemoveable>0);
|
|
if _volName[1]=0
|
|
then result:=$98;
|
|
end;
|
|
IsVolumeRemovable:=(result=0);
|
|
{ resultcodes: 00 success; 98h Invalid volume number / volume not mounted }
|
|
end;
|
|
|
|
{F216/22 [3.x]}
|
|
Function ClearObjectVolRestriction(VolumeNumber:byte; objId:LongInt):boolean;
|
|
{ If the objId doesn't exist, no error is returned. }
|
|
Type Treq=record
|
|
len:word;
|
|
subFunc:byte;
|
|
_volNbr:byte;
|
|
_objId:LongInt; { hi-lo }
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$22;
|
|
_volNbr:=VolumeNumber;
|
|
_objId:=Lswap(objId); { force hi-lo }
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),0,result);
|
|
ClearObjectVolRestriction:=(result=0)
|
|
{ $8C No supervisor rights }
|
|
end;
|
|
|
|
{F216/29 [3.x]}
|
|
Function GetObjectVolRestriction(VolumeNumber:byte; objId:LongInt;
|
|
Var MaxAllowedBlocks,BlocksInUse:LongInt):boolean;
|
|
{ If MaxAllowedBlocks is equal to $40000000 on return, there are no
|
|
disk restrictions for the object on this volume. }
|
|
{ You need not be logged in to use this call. }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc:byte;
|
|
_volNbr:byte;
|
|
_objId :Longint; {hi-lo}
|
|
end;
|
|
Trep=record
|
|
_MaxAllowedBlocks,
|
|
_BlocksInUse :Longint;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Var objName:string;
|
|
objType:word;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len :=SizeOf(Treq)-2;
|
|
subFunc:=$29;
|
|
_volNbr:=VolumeNumber;
|
|
_objId :=Lswap(objId); {force hi-lo}
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
MaxAllowedBlocks:=_MaxAllowedBlocks;
|
|
BlocksInUse:=_BlocksInUse;
|
|
If BlocksInUse=0
|
|
then if NOT nwBindry.GetBinderyObjectName(objId,objName,objType)
|
|
then result:=$FF;
|
|
end;
|
|
GetObjectVolRestriction:=(result=0)
|
|
{resultcodes: 00 success; $FF Invalid objectId }
|
|
end;
|
|
|
|
{F216/20 [3.x]}
|
|
Function ScanVolForRestrictions(VolumeNumber:byte;
|
|
{i/o} Var sequenceNbr:LongInt;
|
|
{out} Var NbrOfObjects:byte;
|
|
Var ResultBuffer:TobjVolRestr):boolean;
|
|
{ 1st call: sequenceNbr=0,
|
|
// n-th call: sequenceNbr(n):=sequenceNbr(n-1)+NbrOfObjects
|
|
// (addition done by function itself)
|
|
|
|
after last call: sequenceNbr=0 again. }
|
|
Type Treq=record
|
|
len:word;
|
|
subFunc:byte;
|
|
_volNbr:byte;
|
|
_seqNbr:LongInt; { lo-hi !}
|
|
end;
|
|
Trep=record
|
|
_NbrOfObjects:byte;
|
|
_buff :TobjVolRestr;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Var t:byte;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$20;
|
|
_volNbr:=VolumeNumber;
|
|
_seqNbr:=sequenceNbr;
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
|
|
if result=0
|
|
then begin
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
NbrOfObjects:=_NbrOfObjects;
|
|
ResultBuffer:=_buff;
|
|
For t:=1 to NbrOfObjects
|
|
do ResultBuffer[t].objId:=Lswap(_buff[t].ObjId);
|
|
if _NbrOfObjects=0
|
|
then result:=$FF
|
|
else sequenceNbr:=sequenceNbr+_NbrOfObjects;
|
|
end
|
|
end
|
|
else NbrOfObjects:=0;
|
|
ScanVolForRestrictions:=(result=0)
|
|
{ $98 VolumeNumber doesn't exist;
|
|
$FF No New restriction data (end of iteration) }
|
|
end;
|
|
|
|
{F216/21 [3.x]}
|
|
Function SetObjectVolRestriction(VolumeNumber:byte; objId,MaxAllowedBlocks:LongInt):boolean;
|
|
{ If the objId doesn't exist, no error is returned. }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc:byte;
|
|
_volNbr:byte;
|
|
_objId :Longint; {hi-lo}
|
|
_maxBlocks:LongInt; {lo-hi !!}
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalreqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$21;
|
|
_volNbr:=VolumeNumber;
|
|
_objId:=Lswap(objId); { force hi-lo }
|
|
_maxBlocks:=MaxAllowedBlocks;
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),0,result);
|
|
SetObjectVolRestriction:=(result=0)
|
|
{ $8C No supervisor Rights }
|
|
end;
|
|
|
|
|
|
{--------------Dir handles/ drive mappings----------------------------------}
|
|
|
|
|
|
{BA.. }
|
|
Function GetEnvPath(Var EnvPath:string):boolean; {#d}
|
|
Type Tarr=array[1..2048] of byte;
|
|
Var regs:TTregisters;
|
|
penv:^Tarr;
|
|
i,envSize:word;
|
|
state:byte;
|
|
begin
|
|
regs.ah:=$BA;
|
|
RealModeIntr($21,regs);
|
|
envSize:=byte(nwPtr(regs.dx-1,3)^) SHL 4;
|
|
penv:=nwPtr(regs.dx,0);
|
|
i:=1;
|
|
state:=0;
|
|
while (i<envSize) and (state<5)
|
|
do begin
|
|
CASE state of
|
|
4:if penv^[i]=ord('=')
|
|
then state:=5
|
|
else state:=0;
|
|
3:if penv^[i]=ord('H')
|
|
then state:=4
|
|
else state:=0;
|
|
2:if penv^[i]=ord('T')
|
|
then state:=3
|
|
else state:=0;
|
|
1:if penv^[i]=ord('A')
|
|
then state:=2
|
|
else state:=0;
|
|
0:if penv^[i]=ord('P')
|
|
then state:=1;
|
|
end; {case}
|
|
inc(i);
|
|
end;
|
|
|
|
if state<5
|
|
then begin
|
|
result:=$300;
|
|
GetEnvPath:=false;
|
|
exit;
|
|
end;
|
|
EnvPath:='';
|
|
while (i<=envSize) and (penv^[i]<>0)
|
|
do begin
|
|
EnvPath:=EnvPath+chr(penv^[i]);
|
|
inc(i);
|
|
end;
|
|
if i>envSize
|
|
then begin
|
|
result:=$301;
|
|
GetEnvPath:=false;
|
|
exit;
|
|
end;
|
|
result:=0;
|
|
GetEnvPath:=true;
|
|
{ 00 successful
|
|
300 'Path' not found
|
|
301 Path value could not be read }
|
|
end;
|
|
|
|
{BA.. }
|
|
Function SetEnvPath(EnvPath:string):boolean; {#d}
|
|
Type Tarr=array[1..2048] of byte;
|
|
Var regs:TTregisters;
|
|
penv:^Tarr;
|
|
i,t,envSize:word;
|
|
state:byte;
|
|
pbegin,pend:word;
|
|
NewPathSize,OldPathSize:byte;
|
|
diff:integer;
|
|
sVector:TsearchDriveVector;
|
|
Vecind,p:byte;
|
|
dn:Byte;
|
|
begin
|
|
Upstring(EnvPath);
|
|
If pos('PATH=',envPath)=1
|
|
then delete(EnvPath,1,5);
|
|
regs.ah:=$BA;
|
|
RealModeIntr($21,regs);
|
|
envSize:=word(nwPtr(regs.dx-1,3)^) SHL 4;
|
|
penv:=nwPtr(regs.dx,0);
|
|
|
|
i:=1;
|
|
state:=0;
|
|
while (i<envSize) and (state<5)
|
|
do begin
|
|
CASE state of
|
|
0:if penv^[i]=ord('P')
|
|
then state:=1;
|
|
1:if penv^[i]=ord('A')
|
|
then state:=2
|
|
else state:=0;
|
|
2:if penv^[i]=ord('T')
|
|
then state:=3
|
|
else state:=0;
|
|
3:if penv^[i]=ord('H')
|
|
then state:=4
|
|
else state:=0;
|
|
4:if penv^[i]=ord('=')
|
|
then state:=5
|
|
else state:=0;
|
|
end; {case}
|
|
inc(i);
|
|
end;
|
|
|
|
if state<5
|
|
then begin
|
|
result:=$300;
|
|
SetEnvPath:=false;
|
|
exit;
|
|
end;
|
|
{ determine starting and ending character of path variable }
|
|
pbegin:=i;
|
|
while (i<envSize) and (penv^[i]<>0)
|
|
do inc(i);
|
|
if i>envSize
|
|
then begin
|
|
result:=$301;
|
|
SetEnvPath:=false;
|
|
exit;
|
|
end;
|
|
dec(i);
|
|
pend:=i;
|
|
|
|
{ determine end of 'active' environment / marked by $00 00}
|
|
while (i<envSize) and NOT ((penv^[i]=0) and (penv^[i+1]=0))
|
|
do inc(i);
|
|
if i=envSize
|
|
then begin
|
|
result:=$301;
|
|
SetEnvPath:=false;
|
|
exit;
|
|
end;
|
|
inc(i); { penv^[i] = 'second' 00, end-of-environment }
|
|
|
|
OldPathSize:=1+pend-pbegin;
|
|
NewPathSize:=ord(EnvPath[0]);
|
|
|
|
If (i+NewPathSize-OldPathSize)>envSize
|
|
then begin
|
|
result:=$302;
|
|
SetEnvPath:=false;
|
|
exit;
|
|
end;
|
|
|
|
diff:=NewPathSize-OldPathSize;
|
|
if diff>0
|
|
then for t:=i downto pend
|
|
do penv^[t+diff]:=penv^[t];
|
|
if diff<0
|
|
then for t:=pend to i
|
|
do penv^[t+diff]:=penv^[t];
|
|
Move(EnvPath[1],penv^[pbegin],NewPathSize);
|
|
|
|
FillChar(Svector,SizeOf(TsearchDriveVector),#$FF);
|
|
VecInd:=1;
|
|
REPEAT
|
|
p:=pos(':',envPath);
|
|
if p>0
|
|
then begin
|
|
dn:=ord(ord(envPath[p-1])-ord('A'));
|
|
p:=pos(';',envPath);
|
|
if p=0
|
|
then envPath:=''
|
|
else delete(envPath,1,p);
|
|
IF IsNetworkDrive(dn)
|
|
then begin
|
|
Svector[VecInd]:=dn;
|
|
inc(VecInd)
|
|
end;
|
|
end;
|
|
UNTIL (p=0) or (VecInd=17);
|
|
SetSearchDriveVector(Svector);
|
|
|
|
result:=0;
|
|
SetEnvPath:=true;
|
|
{ 00 successful
|
|
300 'Path' not found
|
|
301 Environment failure
|
|
302 Environment overflow (new path too large) }
|
|
end;
|
|
|
|
|
|
{F216/01}
|
|
Function GetDirectoryPath(DirHandle:byte; Var PathName:string):boolean;
|
|
{ path includes volumename }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc:byte;
|
|
_dh :byte;
|
|
end;
|
|
Trep=record
|
|
DirPath:string[255];
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$01;
|
|
_dh:=DirHandle;
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
|
|
PathName:=TPrep(GlobalReplyBuf)^.DirPath;
|
|
GetDirectoryPath:=(result=0)
|
|
{ 00 Successful 9B Bad directory handle }
|
|
end;
|
|
|
|
{EF02 [2.0/2.1/3.x]}
|
|
Function GetDriveConnectionID( DriveNumber:Byte; Var connID:Byte):boolean;
|
|
{ returns the servernumber (1..8) associated with a drive. }
|
|
Type pArr=^arr;
|
|
arr=array[0..31] of byte;
|
|
Var regs:TTregisters;
|
|
begin
|
|
regs.ax:=$EF02;
|
|
RealModeIntr($21,Regs);
|
|
If DriveNumber>31
|
|
then result:=$0105
|
|
else begin
|
|
connID:=Parr(nwPtr(Regs.es,regs.si))^[DriveNumber];
|
|
Result:=0;
|
|
end;
|
|
GetDriveConnectionID:=(Result=0);
|
|
end;
|
|
|
|
{EF02 [2.0/2.1/3.x]}
|
|
Function SetDriveConnectionID( DriveNumber:Byte; connID:Byte):boolean;
|
|
Type pArr=^arr;
|
|
arr=array[0..31] of byte;
|
|
Var regs:TTregisters;
|
|
begin
|
|
regs.ax:=$EF02;
|
|
RealModeIntr($21,Regs);
|
|
If DriveNumber>31
|
|
then result:=$0105
|
|
else begin
|
|
Parr(nwPtr(Regs.es,regs.si))^[DriveNumber]:=connId;
|
|
Result:=0;
|
|
end;
|
|
SetDriveConnectionID:=(Result=0);
|
|
end;
|
|
|
|
|
|
{EF00 [2.0/2.1/3.x]}
|
|
Function GetDriveHandle( DriveNumber:Byte; Var DirHandle:Byte ):boolean;
|
|
{ The call returns a pointer to the shell's Drive Handle Table. (32 bytes)
|
|
(Drives A..Z and temporary drives [\]^_' )
|
|
If a drive has been assigned a directory handle on the file server,
|
|
the handle can be found in the DHT at the position corresponding with the drive letter.}
|
|
Type pArr=^arr;
|
|
arr=array[0..31] of byte;
|
|
Var regs:TTregisters;
|
|
begin
|
|
regs.ax:=$EF00;
|
|
RealModeIntr($21,regs);
|
|
if DriveNumber>31
|
|
then result:=$0105
|
|
else begin
|
|
DirHandle:=Parr(nwPtr(Regs.Es,Regs.Si))^[DriveNumber];
|
|
Result:=0;
|
|
end;
|
|
GetDriveHandle:=(Result=0);
|
|
end;
|
|
|
|
{EF00 [2.0/2.1/3.x]}
|
|
Function SetDriveHandle( DriveNumber:Byte; DirHandle:Byte ):boolean;
|
|
Type pArr=^arr;
|
|
arr=array[0..31] of byte;
|
|
Var regs:TTregisters;
|
|
begin
|
|
regs.ax:=$EF00;
|
|
RealModeIntr($21,regs);
|
|
if DriveNumber>31
|
|
then result:=$0105
|
|
else begin
|
|
Parr(nwPtr(Regs.Es,Regs.Si))^[DriveNumber]:=DirHandle;
|
|
Result:=0;
|
|
end;
|
|
SetDriveHandle:=(Result=0);
|
|
end;
|
|
|
|
{EF01 [2.0/2.1/3.x]}
|
|
Function GetDriveFlag( DriveNumber:Byte; Var DriveStatus:Byte ):Boolean;
|
|
{ This call returns a pointer to the shell's Drive Flag Table (32 Bytes)
|
|
Each entry indicates a drive's status (permanent,temporary,local,unassigned)
|
|
For further explanation see the DRIVE_xxx constants.}
|
|
Type pArr=^arr;
|
|
arr=array[0..31] of byte;
|
|
Var regs:TTregisters;
|
|
begin
|
|
regs.ax:=$EF01;
|
|
RealModeIntr($21,Regs);
|
|
If DriveNumber>31
|
|
then result:=$0105
|
|
else begin
|
|
DriveStatus:=Parr(nwPtr(Regs.es,regs.si))^[DriveNumber];
|
|
Result:=0;
|
|
end;
|
|
GetDriveFlag:=(Result=0);
|
|
end;
|
|
|
|
{EF01 [2.0/2.1/3.x]}
|
|
Function SetDriveFlag( DriveNumber:Byte; DriveStatus:Byte ):Boolean;
|
|
Type pArr=^arr;
|
|
arr=array[0..31] of byte;
|
|
Var regs:TTregisters;
|
|
begin
|
|
regs.ax:=$EF01;
|
|
RealModeIntr($21,Regs);
|
|
If DriveNumber>31
|
|
then result:=$0105
|
|
else begin
|
|
Parr(nwPtr(Regs.es,regs.si))^[DriveNumber]:=DriveStatus;
|
|
Result:=0;
|
|
end;
|
|
SetDriveFlag:=(Result=0);
|
|
end;
|
|
|
|
|
|
{E900 [2.0/2.1/3.x]}
|
|
Function GetDirectoryHandle( DriveNumber:Byte; Var dirHandle,status:byte):Boolean;
|
|
{ Returns directory handle and status flags for a drive. }
|
|
{ Drivenumber = 0..31 (A..Z = 0..25) and temp drives (26..31) }
|
|
{ Status Byte
|
|
7 6 5 4 3 2 1 0
|
|
| | +-Permenant Directory Handle
|
|
| +----Temporary Directory Handle
|
|
+----------------------Mapped to a local drive }
|
|
{ in case of an invalid driveNumber, handle and status will be set to 0 }
|
|
Var Regs:TTRegisters;
|
|
begin
|
|
With Regs
|
|
do begin
|
|
AX:=$E900;
|
|
DX:=DriveNumber;
|
|
RealModeIntr($21,Regs);
|
|
{ AH = Status Flags;
|
|
01 mapped to a permanent dir handle;
|
|
02 mapped to a temporary dir handle;
|
|
80 local drive. }
|
|
dirHandle:=AL;
|
|
status:=AH;
|
|
If dirHandle=0
|
|
then begin status:=0;Result:=$FF end {INVALID_DRIVE_NUMBER}
|
|
else Result:=0;
|
|
GetDirectoryHandle:=(Result=0)
|
|
end;
|
|
{ result: $00 success; $FF Invalid Drive Number }
|
|
end;
|
|
|
|
|
|
{F216/00 [2.15c+]}
|
|
Function SetDirectoryHandle( sourceDirHandle:Byte; sourceDirPath:String;
|
|
targetDirHandle:Byte ):boolean;
|
|
{ make handle 'targetHandle' point to the directory provided by
|
|
sourceHandle and/or sourceDirPath. ( "Volume:dir\subdir" ) }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_TargetDH :Byte;
|
|
_SourceDH :Byte;
|
|
_SourceDP :String[255]
|
|
end;
|
|
TPreq=^Treq;
|
|
Var p:Byte;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$00;
|
|
_TargetDH:=targetDirHandle;
|
|
_SourceDH:=SourceDirHandle;
|
|
if SourceDirHandle=0
|
|
then ConvertPathToVolFormat(SourceDirPath);
|
|
_sourceDP:=sourceDirPath;
|
|
UpString(_sourceDP);
|
|
len:=4+ord(_SourceDP[0]);
|
|
F2SystemCall($16,len+2,0,result);
|
|
end;
|
|
SetDirectoryHandle:=(result=0)
|
|
{ resultcodes:
|
|
00 Success; 98h Volume does not exist;
|
|
9Bh Bad directory handle; 9Ch Invalid Path. }
|
|
end;
|
|
|
|
|
|
{F216/12 [2.15c+]}
|
|
FUNCTION AllocPermanentDirHandle( DriveNumber:Byte;
|
|
DirHandle : byte; DirPath : string ;
|
|
var NewDirHandle, EffectiveRights: byte ) :boolean;
|
|
{ Effective server must be the server involved, i.e. where the dir is stored }
|
|
Type Treq=record
|
|
len : word;
|
|
subf : byte;
|
|
_dirHandle : byte;
|
|
_driveLetter : char;
|
|
_DirectoryPath: String[255];
|
|
end;
|
|
Trep=record
|
|
_newDirHandle : byte;
|
|
_EffectiveRights : byte; { e.r. mask }
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Var p:Byte;
|
|
BEGIN
|
|
With TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subf := $12;
|
|
_dirHandle := dirHandle;
|
|
_driveLetter := chr(DriveNumber+ord('A'));
|
|
if Dirhandle=0
|
|
then ConvertPathToVolFormat(DirPath);
|
|
_DirectoryPath:=DirPath;
|
|
UpString(_DirectoryPath);
|
|
len:=4+ord(_DirectoryPath[0]);
|
|
F2SystemCall($16,len+2,sizeof(Trep),result);
|
|
end;
|
|
if result = 0
|
|
then with TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
effectiveRights := _effectiveRights;
|
|
newDirHandle := _newDirHandle;
|
|
end;
|
|
AllocPermanentDirHandle:=(result=0);
|
|
{ $00 Successful $98 Volume doen't exist $9C Invalid path }
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
{F216/13 [2.15c+]}
|
|
function AllocTemporaryDirHandle( DriveNumber:byte;
|
|
DirHandle : Byte; DirPath : String;
|
|
var NewDirHandle,EffectiveRights : Byte) : Boolean;
|
|
{ Allocates a temporary directory handle, deleted automatically by EOJ. }
|
|
{ Effective server must be the server involved, i.e. where the dir is stored }
|
|
Type TReq=record
|
|
Len : Word;
|
|
SubF : Byte;
|
|
Handle : Byte;
|
|
Letter : Char;
|
|
_DirectoryPath : String;
|
|
end;
|
|
TRep=record
|
|
NewH : Byte;
|
|
Mask : Byte;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Var p:Byte;
|
|
begin
|
|
with TPReq(GlobalReqBuf)^
|
|
do begin
|
|
SubF := $13;
|
|
Handle := DirHandle;
|
|
Letter := chr(DriveNumber+ord('A'));
|
|
{ Allocating handles requires paths to be in
|
|
the VOL:path format.. NOT canonical }
|
|
if handle=0
|
|
then ConvertPathToVolFormat(DirPath);
|
|
_DirectoryPath:=DirPath;
|
|
UpString(_DirectoryPath);
|
|
Len:=4+length(_DirectoryPath);
|
|
F2SystemCall($16,len+2,SizeOf(Trep),result);
|
|
end;
|
|
with TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
NewDirHandle := NewH;
|
|
EffectiveRights := Mask;
|
|
end;
|
|
AllocTemporaryDirHandle:=(result=0);
|
|
{ result: 00 success; 98h Volume doesn't exist; 9Ch Invalid Path }
|
|
end;
|
|
|
|
|
|
{F216/14 [2.15c+]}
|
|
function DeallocateDirHandle(DirHandle : Byte) : Boolean;
|
|
{ This function deletes a directory handle }
|
|
Type TReq=record
|
|
Len : Word;
|
|
SubF : Byte;
|
|
Handle : Byte;
|
|
end;
|
|
TPreq=^Treq;
|
|
begin
|
|
with TPReq(GlobalReqBuf)^
|
|
do begin
|
|
Len := 2;
|
|
SubF := $14;
|
|
Handle:= DirHandle;
|
|
end;
|
|
F2SystemCall($16,Sizeof(Treq),0,result);
|
|
DeallocateDirHandle:=(result=0);
|
|
{ result:
|
|
00h - Success; 9Bh - Bad directory handle }
|
|
end;
|
|
|
|
|
|
{E901 }
|
|
Function GetSearchDriveVector(Var vector:TsearchDriveVector):boolean;
|
|
Var regs:TTregisters;
|
|
tmp1,tmp2:word;
|
|
begin
|
|
regs.ax:=$E901;
|
|
GetGlobalBufferAddress(tmp1,tmp2,regs.ds,regs.dx);
|
|
{ DS:DX real-mode address of GlobalReplyBuffer }
|
|
RealModeIntr($21,regs);
|
|
result:=0;
|
|
Move(GlobalReplyBuf^,vector,sizeof(TsearchDriveVector));
|
|
vector[17]:=$FF;
|
|
GetSearchDriveVector:=True;
|
|
end;
|
|
|
|
{E902 }
|
|
Function SetSearchDriveVector(vector:TsearchDriveVector):boolean;
|
|
Var regs:TTregisters;
|
|
tmp1,tmp2:word;
|
|
begin
|
|
regs.ax:=$E902;
|
|
Move(vector,GlobalReqBuf^,sizeof(TsearchDriveVector));
|
|
GetGlobalBufferAddress(regs.ds,regs.dx,tmp1,tmp2);
|
|
{ DS:DX real-mode address of GlobalRequestBuffer }
|
|
RealModeIntr($21,regs);
|
|
result:=0;
|
|
SetSearchDriveVector:=True;
|
|
end;
|
|
|
|
Function IsSearchDrive(DriveNumber:byte):boolean;
|
|
Var pth:string;
|
|
begin
|
|
IsSearchDrive:=(getEnvPath(pth)
|
|
and (pos(chr(DriveNumber+ord('A'))+':',pth)>0));
|
|
end;
|
|
|
|
|
|
{E905 (shell 3.00+)}
|
|
Function MapFakeRootDirectory(DriveNumber:byte; DirPath:string):boolean;
|
|
{ Dirpath may include server and volumename }
|
|
Var regs:TTregisters;
|
|
tmp1,tmp2:word;
|
|
PName:string;
|
|
begin
|
|
with regs
|
|
do begin
|
|
ax:=$E905;
|
|
bl:=driveNumber+1; { FF default, 0=A, 2= B etc. }
|
|
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
|
|
{ VLM patch for SERVER/VOL: and VOL: type paths }
|
|
if (DirPath[0]>#2) and (pos(':',DirPath)>2)
|
|
then GetTrueEntryName(DirPath,PName)
|
|
else PName:=DirPath;
|
|
Pname:=Pname+#0;
|
|
move(PName[1],GlobalReqBuf^,ord(PName[1]));
|
|
{ DS:DX real-mode address of GlobalRequestBuffer holding new path }
|
|
RealModeIntr($21,regs);
|
|
if (flags and 1 {carry})>0
|
|
then result:=al
|
|
else result:=0;
|
|
end;
|
|
MapFakeRootDirectory:=(result=0);
|
|
{ $00 Successful $03 Invalid path $0F Invalid Drive $11 Not same device }
|
|
end;
|
|
|
|
{E906 (shell 3.00+)}
|
|
Function DeleteFakeRootDirectory(DriveNumber:byte):boolean;
|
|
Var regs:TTregisters;
|
|
begin
|
|
with regs
|
|
do begin
|
|
ax:=$E906;
|
|
bl:=DriveNumber+1;
|
|
RealModeIntr($21,regs);
|
|
result:=0;
|
|
end;
|
|
DeleteFakeRootDirectory:=(result=0);
|
|
end;
|
|
|
|
{E907 (shell 3.00+)}
|
|
Function GetRelativeDriveDepth(DriveNumber:byte; Var depth:byte):boolean;
|
|
Var regs:TTregisters;
|
|
begin
|
|
with regs
|
|
do begin
|
|
ax:=$E907;
|
|
bl:=DriveNumber+1;
|
|
RealModeIntr($21,regs);
|
|
depth:=al;
|
|
if al<$FF
|
|
then result:=0
|
|
else result:=$FF; { no fake root assigned }
|
|
end;
|
|
GetRelativeDriveDepth:=(result=0);
|
|
{ 00 Succesful $FF No fake root assigned }
|
|
end;
|
|
|
|
{secondary}
|
|
Function DeleteDriveMapping(DriveNumber:Byte):boolean;
|
|
Var dirHandle,status:byte;
|
|
pth:string;
|
|
ch:char;
|
|
p:byte;
|
|
DDepth,Dflag:byte;
|
|
begin
|
|
{ if searchdrive, remove drive from searchtable and PATH environment string }
|
|
IF GetEnvPath(pth)
|
|
then begin
|
|
if pth[ord(pth[0])]<>';'
|
|
then pth:=pth+';';
|
|
p:=pos(chr(DriveNumber+ord('A'))+':',pth);
|
|
if p>0
|
|
then begin { it is a searchdrive, remove from path }
|
|
Repeat
|
|
ch:=pth[p];
|
|
delete(pth,p,1);
|
|
UNTIL ch=';';
|
|
SetEnvPath(pth); { also creates a new searchdriveVector }
|
|
end;
|
|
end;
|
|
IF (result=0) and GetDirectoryHandle(DriveNumber,dirHandle,status)
|
|
then begin
|
|
IF GetRelativeDriveDepth(DriveNumber,DDepth) { is it a fake root ? }
|
|
then DeleteFakeRootDirectory(DriveNumber);
|
|
GetDriveFlag(DriveNumber,Dflag);
|
|
SetDriveFlag(DriveNumber,(Dflag and $F0) or DRIVE_UNUSED);
|
|
SetDriveHandle(DriveNumber,0);
|
|
SetDriveConnectionId(DriveNumber,0);
|
|
DeallocateDirHandle(dirHandle);
|
|
end;
|
|
DeleteDriveMapping:=(result=0);
|
|
end;
|
|
|
|
|
|
{secondary }
|
|
FUNCTION MapPermanentDrive(DriveNumber:byte; DirectoryPath:string;
|
|
Root:boolean):boolean;
|
|
var pth : string;
|
|
DriveHandle: Byte;
|
|
begin
|
|
IF GetTrueEntryName(DirectoryPath,pth)
|
|
then begin
|
|
while pth[ord(pth[0])] IN ['\','.','*','?']
|
|
do dec(pth[0]);
|
|
if pth[1]<>'\'
|
|
then result:=$104 { attempt to map network drive to local drive }
|
|
else begin
|
|
If GetDriveHandle(DriveNumber,DriveHandle) and (DriveHandle<>0)
|
|
then DeleteDriveMapping(DriveNumber);
|
|
|
|
IF MapFakeRootDirectory(DriveNumber,pth)
|
|
then begin
|
|
if (not root)
|
|
then DeleteFakeRootDirectory(DriveNumber);
|
|
{ does not delete the mapping itself,
|
|
only the fake root. }
|
|
end;
|
|
end;
|
|
end
|
|
else result:=$101; { direcory not locatable }
|
|
MapPermanentDrive:=(result=0);
|
|
end;
|
|
|
|
{secondary}
|
|
FUNCTION MapDrive(DriveNumber:Byte; DirectoryPath:string;
|
|
Root, Permanent:boolean):boolean;
|
|
var rights : byte;
|
|
newHandle : byte;
|
|
HandlePth,pth,srvr,vol: string;
|
|
OldConnId,VolConnId:byte;
|
|
p:byte;
|
|
VolNbr:byte;
|
|
Dflag:byte;
|
|
begin
|
|
IF Permanent
|
|
then begin
|
|
MapDrive:=MapPermanentDrive(DriveNumber,DirectoryPath,Root);
|
|
exit;
|
|
end;
|
|
{ map temporary drive }
|
|
IF GetTrueEntryName(DirectoryPath,pth)
|
|
then begin
|
|
if pth[ord(pth[0])]<>'\'
|
|
then pth:=pth+'\';
|
|
if pth[1]<>'\'
|
|
then result:=$104 { attempt to map network drive to local drive }
|
|
else begin
|
|
delete(pth,1,2);
|
|
p:=pos('\',pth);
|
|
if p=0 then result:=$106;
|
|
srvr:=copy(pth,1,p-1);
|
|
delete(pth,1,p);
|
|
p:=pos('\',pth);
|
|
if p=0 then result:=$105; { volume does not exist }
|
|
vol:=copy(pth,1,p-1);
|
|
delete(pth,1,p);
|
|
IF NOT GetConnectionId(srvr,VolConnId)
|
|
then result:=$106; { server does not exist }
|
|
end;
|
|
end
|
|
else result:=$101; { direcory not locatable }
|
|
if (result=0)
|
|
then begin
|
|
while pth[ord(pth[0])] IN ['\','.','*','?']
|
|
do dec(pth[0]);
|
|
|
|
{ rebuild path: Alloc handle requires VOL:path format }
|
|
HandlePth:=vol+':\'+pth;
|
|
GetPreferredConnectionId(OldConnId);
|
|
SetPreferredConnectionId(VolConnId);
|
|
|
|
{ IF Permanent
|
|
then AllocPermanentDirHandle(DriveNumber,0,HandlePth,
|
|
newHandle,rights)
|
|
else}
|
|
AllocTemporaryDirHandle(DriveNumber,0,HandlePth,
|
|
newHandle,rights);
|
|
if (result=0)
|
|
then begin
|
|
GetDriveFlag(DriveNumber,Dflag);
|
|
{If Permanent
|
|
then SetDriveFlag(DriveNumber,(Dflag and $F0) or DRIVE_PERMANENT)
|
|
else}
|
|
SetDriveFlag(DriveNumber,(Dflag and $F0) or DRIVE_TEMPORARY);
|
|
SetDriveHandle(DriveNumber,newHandle);
|
|
SetDriveConnectionId(DriveNumber,VolConnId);
|
|
IF root
|
|
then MapFakeRootDirectory(DriveNumber,'\\'+srvr+'\'+vol+'\'+pth);
|
|
end;
|
|
SetPreferredConnectionId(OldConnId);
|
|
end;
|
|
MapDrive:=(result=0);
|
|
end;
|
|
|
|
|
|
|
|
Function MapSearchDrive(DriveNumber:byte; DirPath:string;
|
|
PathPosition:byte;
|
|
Insert,Root,Permanent:Boolean):boolean;
|
|
Var pth:string;
|
|
p,scCount:byte;
|
|
ch:char;
|
|
begin
|
|
IF MapDrive(DriveNumber,DirPath,Root,Permanent)
|
|
then begin
|
|
GetEnvPath(pth);
|
|
if pth[ord(pth[0])]<>';'
|
|
then pth:=pth+';';
|
|
scCount:=1;p:=1;
|
|
while (scCount<PathPosition) and (p<=ord(pth[0]))
|
|
do begin
|
|
if pth[p]=';'
|
|
then inc(scCount);
|
|
inc(p);
|
|
end;
|
|
{ pth[p] is first character of PathPositions' entry in path }
|
|
If p<ord(pth[0])
|
|
then begin
|
|
IF (Not Insert)
|
|
then Repeat
|
|
ch:=pth[p];
|
|
delete(pth,P,1);
|
|
UNTIL (ch=';') or (p>=ord(pth[0]));
|
|
pth:=copy(pth,1,p-1)+chr(DriveNumber+ord('A'))
|
|
+':.;'+copy(pth,p,255);
|
|
end
|
|
else pth:=pth+chr(DriveNumber+ord('A'))+':.;';
|
|
SetEnvPath(pth);
|
|
end;
|
|
MapSearchDrive:=(result=0);
|
|
end;
|
|
|
|
{secondary}
|
|
Function DeleteConnectionsDriveMappings(ConnId:Byte):Boolean;
|
|
Var t,connId2,res:Byte;
|
|
begin
|
|
res:=$FF;
|
|
for t:=0 to 31
|
|
do if GetDriveConnectionId(t,connId2) and (connId2=connId)
|
|
then begin
|
|
DeleteDriveMapping(t);
|
|
if result=0
|
|
then res:=0;
|
|
end;
|
|
result:=res;
|
|
DeleteConnectionsDriveMappings:=(result=0);
|
|
{00 successful FF No mappings affected OR Invalid connectionId }
|
|
end;
|
|
|
|
|
|
{4409 / implemented as a secondary function }
|
|
Function IsNetworkDrive(driveNumber:Byte):boolean;
|
|
{ isNetworkDrive is set to TRUE if the drive is a) a network drive, and
|
|
b) a legal drive letter was used. }
|
|
Var regs:TTRegisters;
|
|
begin
|
|
With regs
|
|
do begin
|
|
AX:=$4409;
|
|
BL:=DriveNumber+1;
|
|
RealModeIntr($21,Regs);
|
|
IsNetworkDrive:=(DX and $1000)<>0
|
|
end;
|
|
end;
|
|
|
|
|
|
{--======================-- Entries --===============================--}
|
|
|
|
|
|
{60.. (extended DOS call)}
|
|
Function GetTrueEntryName(DirPath:string; Var CanonicalPath:string):boolean;
|
|
{ SERVER/VOL:[\]Path -> \\SERVER\VOL\path
|
|
VOL:[\]Path -> \\effective_server_name\VOL\path
|
|
D:\ -> D:\.
|
|
|
|
{ if a volumename is supplied without a servername, the name of the
|
|
effective server will be returned. }
|
|
|
|
{ Format of returned string:
|
|
a) D:\path\file.ext or
|
|
b) \\servername\volumename\path\file.ext }
|
|
|
|
LABEL skip;
|
|
|
|
Var reply :array[1..128] of byte;
|
|
regs :TTregisters;
|
|
pcolon,
|
|
pslash :byte;
|
|
srvr,
|
|
volname:string[47];
|
|
connId :Byte;
|
|
begin
|
|
{ ----- Pre processing }
|
|
if DirPath[0]>#2
|
|
then begin
|
|
if ((DirPath[1]='\') and (DirPath[2]='\'))
|
|
then begin
|
|
CanonicalPath:=DirPath;
|
|
UpString(Canonicalpath);
|
|
goto skip
|
|
end;
|
|
pcolon:=pos(':',DirPath);
|
|
if (pcolon=2) and (DirPath[0]=#3) and (DirPath[3]='\')
|
|
then DirPath:=DirPath+'.';
|
|
{ fix known problem of netware: D:\. instead of D:\ }
|
|
if (pcolon=2) and (DirPath[0]=#2)
|
|
then DirPath:=DirPath+'.';
|
|
{ fix know problem of -among others- OS/2-dos: D:. instead of D: }
|
|
end;
|
|
pcolon:=pos(':',DirPath);
|
|
if pcolon>2
|
|
then begin { format must be VOL:[\]path or SERVER/VOL:[\]Path }
|
|
pslash:=pos('/',DirPath);
|
|
if pslash=0
|
|
then pslash:=$FF;
|
|
if (pslash<pcolon)
|
|
then begin { SERVER/VOL: }
|
|
srvr:=copy(DirPath,1,pslash-1);
|
|
delete(DirPath,1,pslash);
|
|
pcolon:=pos(':',DirPath);
|
|
end
|
|
else begin { VOL: }
|
|
GetEffectiveConnectionId(connId);
|
|
GetFileServerName(connId,srvr);
|
|
end;
|
|
volname:=copy(dirPath,1,pcolon-1);
|
|
delete(dirPath,1,pcolon);
|
|
if (dirPath[0]>#0) and (dirPath[1]='\')
|
|
then delete(DirPath,1,1);
|
|
DirPath:='\\'+srvr+'\'+volname+'\'+DirPath;
|
|
end;
|
|
if dirPath=''
|
|
then dirPath:='\';
|
|
{ ----- actual call }
|
|
dirPath:=dirPath+#0; { zero terminate }
|
|
WITH regs
|
|
do begin
|
|
Move(dirPath[1],GlobalReqBuf^,ord(dirPath[0]));
|
|
GetGlobalBufferAddress(ds,si,es,di);
|
|
{ DS:SI real mode pointer to GlobalRequestBuffer holding asciiz path ;
|
|
ES:DI real mode pointer to GlbalReplyBuffer }
|
|
ah:=$60;
|
|
RealModeIntr($21,regs);
|
|
Move(GlobalReplyBuf^,reply[1],128);
|
|
if (regs.flags and 1 {carry})>0
|
|
then begin
|
|
result:=ax;
|
|
reply[1]:=0;
|
|
end
|
|
else result:=0;
|
|
end;
|
|
ZstrCopy(CanonicalPath,reply[1],128);
|
|
{ ----- post-processing -- strip \ and . }
|
|
skip: ;
|
|
While CanonicalPath[ord(CanonicalPath[0])] in ['\','.']
|
|
do dec(CanonicalPath[0]);
|
|
GetTrueEntryName:=(result=0);
|
|
{ $00 successful
|
|
$02 Invalid component in directory path OR drive letter only
|
|
$03 Malformed path OR invalid drive letter }
|
|
end;
|
|
|
|
|
|
|
|
{3B.. }
|
|
Function ChangeDirectory(DirPath:string):boolean;
|
|
{ does not change the default drive }
|
|
Var regs:TTregisters;
|
|
tmp1,tmp2:word;
|
|
begin
|
|
if DirPath[0]>#63
|
|
then result:=$110 { length of path too long }
|
|
else begin
|
|
DirPath:=DirPath+#0;
|
|
with regs
|
|
do begin
|
|
ah:=$3b;
|
|
Move(DirPath[1],GlobalReqBuf^,ord(DirPath[0]));
|
|
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
|
|
{ DS:DX real-mode pointer to GlobalRequestBuffer holding DirPath }
|
|
RealModeIntr($21,regs);
|
|
If (flags and 1 {carry})>0
|
|
then result:=$111 { invalid pathname }
|
|
else result:=0;
|
|
end;
|
|
end;
|
|
ChangeDirectory:=(result=0);
|
|
end;
|
|
|
|
{F216/0A [2.15+]}
|
|
Function CreateDirectory(DirHandle:Byte; DirPath:string; MaxRightsMask:byte):boolean;
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_DirHandle:byte;
|
|
_MRM :byte;
|
|
_dirPath :string[255];
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalreqBuf)^
|
|
do begin
|
|
subFunc:=$0A;
|
|
_dirHandle:=DirHandle;
|
|
_MRM:=MaxRightsMask;
|
|
_DirPath:=DirPath;
|
|
len:=4+ord(_dirPath[0]);
|
|
F2SystemCall($16,len+2,0,result);
|
|
end;
|
|
CreateDirectory:=(result=0)
|
|
{ 00 successful 84 No create privileges 98 Volume doesn't exist
|
|
FF directory already exists }
|
|
end;
|
|
|
|
|
|
{F216/0B [2.15c+]}
|
|
Function DeleteDirectory(DirHandle:Byte; DirPath:string):boolean;
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_DirHandle:byte;
|
|
unused :byte;
|
|
_DirPath :string[255];
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalreqBuf)^
|
|
do begin
|
|
subFunc:=$0B;
|
|
_DirHandle:=DirHandle;
|
|
_DirPath:=DirPath;
|
|
unused:=0;
|
|
len:=4+ord(_DirPath[0]);
|
|
F2SystemCall($16,len+2,0,result);
|
|
end;
|
|
DeleteDirectory:=(result=0)
|
|
{ 00 successful 8A No delete privileges
|
|
98 Volume doesn't exist 9B Bad directory handle
|
|
9C Invalid path 9F Directory in use
|
|
A0 Directory not empty }
|
|
end;
|
|
|
|
|
|
{F217/F4 [3.0+]}
|
|
Function ConvertPathToDirEntryId(dirHandle:Byte; dirPath:string;
|
|
Var VolNbr :byte;
|
|
Var dirEntryID:LongInt):boolean;
|
|
{ aka ConvertPathToDirEntry }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_dirHandle:byte;
|
|
_DirPath :string[255];
|
|
end;
|
|
Trep=record
|
|
_volNbr:Byte;
|
|
_EntryId:Longint; {hi-lo}
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$F4;
|
|
_dirHandle:=DirHandle;
|
|
_dirPath:=DirPath;
|
|
UpString(_DirPath);
|
|
If DirHandle=0
|
|
then ConvertPathToVolFormat(_DirPath);
|
|
len:=3+ord(_DirPath[0]);
|
|
F2SystemCall($17,len+2,SizeOf(Trep),result);
|
|
end;
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
VolNbr :=_volNbr;
|
|
dirEntryId:=_EntryId;
|
|
end;
|
|
ConvertPathToDirEntryId:=(result=0)
|
|
{ 00 Successful 9B Bad directory Handle
|
|
9C Invalid Path C6 No console rights }
|
|
end;
|
|
|
|
{F217/F3 [3.0+]}
|
|
Function MapDirEntryIdToPath(VolNbr:byte;DirEntryId:Longint; NStype:byte;
|
|
Var ExtPath:string):boolean;
|
|
{aka MapDirectoryNumberToPath }
|
|
{ Returns full path/ with nameSpace information;
|
|
Doesn't return server or volumename. }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_VolNbr :byte;
|
|
_EntryId:longint; {hi-lo}
|
|
_NameSp :byte;
|
|
end;
|
|
Trep=record
|
|
_path:array[1..255] of byte; {!! maximum: 512 bytes in path ! }
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Var TempPath:string;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$F3;
|
|
_VolNbr:=VolNbr;
|
|
_EntryId:=DirEntryId;
|
|
_NameSp:=NStype;
|
|
end;
|
|
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
|
|
if result=0
|
|
then begin
|
|
With TPrep(GlobalReplyBuf)^
|
|
do ZstrCopy(TempPath,_path,255);
|
|
{ TempPath according to the 'new' Novell format;
|
|
translate into a 'DOS' style path }
|
|
NovPath2DOSPath(TempPath,ExtPath); { dir\subdir (no server or volume name) }
|
|
end;
|
|
MapDirentryIdtoPath:=(result=0)
|
|
{ 00 Successful C6 No console rights FF ? }
|
|
end;
|
|
|
|
|
|
{F216/02}
|
|
Function ScanDirectoryInformation(dirHandle:byte; searchDirPath:string;
|
|
{i/o} Var sequenceNumber:word;
|
|
{out:} Var dirInfo:Tentry ):boolean;
|
|
{ set sequenceNumber to 0 before the first call.
|
|
|
|
If wildcards (* or ?) are included in the searchDirPath:
|
|
Iterate until a $9C error is returned.
|
|
|
|
If you don't include a wildcard in the searchDirPath, only use
|
|
this call once. Do not iterate, the same entry will be returned
|
|
eternaly.
|
|
|
|
}
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_dirHandle :byte;
|
|
_subDirNumber:word; {hi-lo}
|
|
_dirPath :string[255]
|
|
end;
|
|
Trep=record
|
|
_subDirName :array[1..16] of byte;
|
|
_creationDate :word;
|
|
_creationTime :word;
|
|
_ownerObjId :LongInt; {hi-lo}
|
|
_maxRightsMask:word;
|
|
_SubDirNbr :word; {hi-lo}
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$02;
|
|
_dirHandle:=dirHandle;
|
|
_subDirNumber:=swap(sequenceNumber); { force hi-lo}
|
|
_dirPath:=searchDirPath;
|
|
UpString(_dirPath);
|
|
len:=5+ord(searchDirPath[0]);
|
|
F2SystemCall($16,len+2,SizeOf(Trep),result);
|
|
end;
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
FillChar(dirInfo,SizeOf(Tentry),0);
|
|
ZstrCopy(dirInfo.EntryName,_SubDirName,16);
|
|
|
|
DosTime2NovTime(MakeLong(swap(_CreationDate),swap(_CreationTime)),
|
|
dirInfo.creationTime);
|
|
dirInfo.ownerId:=Lswap(_ownerObjId);
|
|
dirInfo.RightsMask:=_maxRightsMask;
|
|
sequenceNumber:=swap(_SubDirNbr)+1;
|
|
end;
|
|
ScanDirectoryInformation:=(result=0)
|
|
{resultcodes: $00 success; $98 Volume does not exist;
|
|
$9B Bad directory Handle $9C Invalid Path }
|
|
end;
|
|
|
|
|
|
{F216/0F [2.0/2.1/3.x]}
|
|
Function RenameDirectory( dirHandle:Byte; dirPath, newDirName :String):Boolean;
|
|
{ The new directory name must be a regular (legal) directory name,
|
|
max 14 chars long.
|
|
The user must have Parental and Modify rights in the parent directory of
|
|
the directory to be renamed. }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_dirHandle :Byte;
|
|
_dirNames :Array[0..255+1+14] of byte; { _dirpath[0] is allowed to be 0 }
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$0F;
|
|
_dirHandle:=dirHandle;
|
|
Upstring(dirPath);
|
|
UpString(newDirName);
|
|
Move(DirPath[0],_DirNames[0],ord(DirPath[0])+1);
|
|
Move(newDirName[0],_DirNames[1+_DirNames[0]],ord(newDirName[0])+1);
|
|
len:=4+ord(dirPath[0])+ord(newDirName[0]);
|
|
F2SystemCall($16,len+2,0,result);
|
|
end;
|
|
RenameDirectory:=(result=0)
|
|
{ Possible ResultCodes:
|
|
8B No Rename Privileges; 9B Bad Directory Handle;
|
|
9C Invalid Path; 9E Invalid (new) Dir Name. }
|
|
end;
|
|
|
|
|
|
{F216/1F [2.15c+]}
|
|
Function GetDirectoryEntry(DirHandle:byte;
|
|
Var dirEntry:Tentry):boolean;
|
|
Type Treq=record
|
|
len:word;
|
|
subFunc:byte;
|
|
_dirHandle:byte;
|
|
end;
|
|
Trep=record
|
|
_Entry :TintEntry;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$1F;
|
|
_dirHandle:=dirHandle;
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
Convert2ExtEntry(_entry,dirEntry);
|
|
end;
|
|
GetDirectoryEntry:=(result=0)
|
|
{ 00 successful 98 Volume doesn't exist
|
|
9B Bad directory handle 9C Invalid path }
|
|
end;
|
|
|
|
|
|
{B601 [2.0+] }
|
|
function SetExtendedFileAttributes(FilePath:String; Attr:Byte) : Boolean;
|
|
{ See GetExtFAttr for meaning of Attr the Attribute
|
|
Function result code:
|
|
00h Success;
|
|
FFh File not found;
|
|
FEh Access denied }
|
|
Var Novregs:TTRegisters;
|
|
tmp1,tmp2:word;
|
|
begin
|
|
with NovRegs
|
|
do begin
|
|
AX := $B601;
|
|
if FilePath[0]=#255
|
|
then FilePath[255]:=#0
|
|
else FilePath:=FilePath+#0;
|
|
Move(FilePath[1],GlobalReqBuf^,ord(FilePath[0]));
|
|
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
|
|
{ DS:DX real mode pointer to GlobalRequestBuffer holding FilePath }
|
|
CL := Attr;
|
|
RealModeIntr($21,NovRegs);
|
|
IF (Flags AND 1 {carry})>0
|
|
then Result:=AL
|
|
else Result:=$00;
|
|
Result := AL
|
|
end;
|
|
SetExtendedFileAttributes:=(Result=0);
|
|
end;
|
|
|
|
|
|
|
|
{B600 [2.0+]}
|
|
function GetExtendedFileAttributes(FilePath:String; var Attributes:Byte) : Boolean;
|
|
{ Meaning of Attributes:
|
|
7 6 5 4 3 2 1 0
|
|
| | | | | | |
|
|
| | | | +---+---+------Search mode
|
|
| | | +----------------------transactional bit A_TRANSACTIONAL
|
|
| | +--------------------------Indexing bit A_INDEXED
|
|
| +------------------------------Read Audit bit A_READ_AUDIT
|
|
+----------------------------------Write Audit bit A_WRITE_AUDIT
|
|
}
|
|
Var NovRegs:TTRegisters;
|
|
tmp1,tmp2:word;
|
|
begin
|
|
with NovRegs
|
|
do begin
|
|
AX := $B600;
|
|
if FilePath[0]=#255
|
|
then FilePath[255]:=#0
|
|
else FilePath:=FilePath+#0; { null terminate string }
|
|
Move(FilePath[1],GlobalReqBuf^,ord(FilePath[0]));
|
|
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
|
|
{ DS:DX real mode pointer to GlobalRequestBuffer hloding FilePath }
|
|
RealModeIntr($21,NovRegs);
|
|
IF (Flags and 1 {carry})>0
|
|
then Result := AL
|
|
else Result:=$00;
|
|
Attributes := CL;
|
|
end;
|
|
GetExtendedFileAttributes:=(Result=0);
|
|
{ $8C caller lacks privileges
|
|
FEh not permitted to search directory
|
|
FFh file not found }
|
|
end;
|
|
|
|
|
|
|
|
|
|
{F3.. [2.x/3.x]}
|
|
Function FileServerFileCopy( sourceFileHandle, destFileHandle:word;
|
|
sourceFileOffset, destFileOffset:Longint;
|
|
numberOfBytesToCopy :Longint;
|
|
VAR numberOfBytesCopied :Longint ):boolean;
|
|
{Note: both source and destination must be on the same file server
|
|
SeeAlso: 3C..,3F..}
|
|
Type Treq=record
|
|
_sFH,_dFH :word; {lo-hi} {as returned by GetFileHandle.}
|
|
_sFoffs,_dfOffs:Longint; {lo-hi}
|
|
_NbrOfBytes :Longint; {lo-hi}
|
|
end;
|
|
TPreq=^Treq;
|
|
Var regs:TTRegisters;
|
|
tmp1,tmp2:word;
|
|
begin
|
|
with TPreq(GlobalReqBuf)^
|
|
do begin
|
|
_sFH:=sourceFileHandle;
|
|
_dFH:=destFileHandle;
|
|
_sFoffs:=sourceFileOffset;
|
|
_dFoffs:=destFileOffset;
|
|
_NbrOfBytes:=numberOfBytesToCopy;
|
|
end;
|
|
with regs
|
|
do begin
|
|
AH:=$F3;
|
|
GetGlobalBufferAddress(es,di,tmp1,tmp2);
|
|
{ ES:DI real mode pointer to GlobalRequestBuffer }
|
|
RealModeIntr($21,regs);
|
|
result:=AL;
|
|
end;
|
|
numberOfBytesCopied:=MakeLong(regs.cx,regs.dx); { ? swap those regs for correct byte order ? }
|
|
FileServerFileCopy:=(Result=0);
|
|
end;
|
|
|
|
{level-0 function. See GetFileAttributes and SetFileAttributes }
|
|
Function DoFileAttributes(subf:byte;FilePath:string;VAR attr:byte):boolean;
|
|
Var regs:TTregisters;
|
|
tmp1,tmp2:word;
|
|
begin
|
|
with regs
|
|
do begin
|
|
AH:=$43;
|
|
AL:=subf;
|
|
if subf=$01 then CX:=attr;
|
|
if filePath[0]=#255
|
|
then filePath[255]:=#0
|
|
else filePath:=filePath+#0;
|
|
Move(FilePath[1],GlobalReqBuf^,ord(FilePath[0]));
|
|
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
|
|
{ DS:DX real mode pointer to GlobalRequestBuffer holding FilePath }
|
|
RealModeIntr($21,regs);
|
|
IF ((Flags and 1 {Fcarry})<>0)
|
|
then result:=AL
|
|
else begin
|
|
result:=$00;
|
|
if subf=$00 then attr:=CX
|
|
end;
|
|
end;
|
|
DoFileAttributes:=(result=$00);
|
|
{ resultcodes: 00 success; 01 invalid function;
|
|
03 path not found; 05 access denied. }
|
|
end;
|
|
|
|
{4300 [1.x/2.x/3.x]}
|
|
Function GetFileAttributes(FilePath:string; Var attr:byte):boolean;
|
|
{ A_READ_ONLY,A_HIDDEN,A_SYSTEM and A_SHAREABLE only. }
|
|
begin
|
|
GetFileAttributes:=DoFileAttributes($00,FilePath,attr);
|
|
end;
|
|
|
|
{4301 [1.x/2.x/3.x]}
|
|
Function SetFileAttributes(FilePath:string; attr:byte):boolean;
|
|
{ A_READ_ONLY,A_HIDDEN,A_SYSTEM and A_SHAREABLE only. }
|
|
Var _attr:byte;
|
|
begin
|
|
_attr:=attr;
|
|
SetFileAttributes:=DoFileAttributes($01,FilePath,_attr);
|
|
end;
|
|
|
|
|
|
|
|
{F217/0F [2.15c+]}
|
|
Function ScanFileInformation(DirHandle:Byte; FilePath:string;
|
|
SearchAttrib:Byte;
|
|
{i/o} VAR SequenceNbr:Integer;
|
|
{out} VAR fileInfo:Tentry):Boolean;
|
|
{ To be called Iteratatively; initial value for seqNbr=-1 }
|
|
{ wildcards in filename allowed.
|
|
Iterate util an error $FF occurs }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_seqNbr :word; {hi-lo}
|
|
_dirHandle :byte;
|
|
_searchAttrib:Byte;
|
|
_filePath :string;
|
|
end;
|
|
Trep=record
|
|
_seqNbr :word; {hi-lo}
|
|
_fileName :array[1..14] of byte;
|
|
_Fattr,
|
|
_ExtFattr :Byte;
|
|
_Fsize :LongInt; {hi-lo}
|
|
_Crdate :word; {hi-lo}
|
|
_LastAccDate :word; {hi-lo}
|
|
_LastUpdDate,
|
|
_LastUpdTime :Word;
|
|
_ownerObjId :Longint; {hi-lo}
|
|
_LastArchDate,
|
|
_lastArchTime:Word;
|
|
_reserved :array[1..56] of byte;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$0F;
|
|
_seqNbr:=swap(word(SequenceNbr)); { force hi-lo }
|
|
_dirHandle:=dirHandle;
|
|
_searchAttrib:=searchAttrib;
|
|
_filePath:=FilePath;
|
|
len:=6+ord(_filePath[0]);
|
|
F2SystemCall($17,len+2,SizeOf(Trep),result);
|
|
end;
|
|
with TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
FillChar(fileInfo,sizeOf(fileInfo),#0);
|
|
SequenceNbr:=Integer(swap(_seqNbr)); { force lo-hi }
|
|
ZstrCopy(fileInfo.EntryName,_filename,15);
|
|
fileInfo.Attributes:=(_ExtFattr SHL 8)+_Fattr;
|
|
fileInfo.filesize:=Lswap(_Fsize); { force lo-hi}
|
|
fileinfo.OwnerID:=Lswap(_ownerObjID); { force lo-hi}
|
|
DosTime2NovTime(MakeLong(swap(_CrDate),0),fileinfo.creationTime);
|
|
DosTime2NovTime(MakeLong(swap(_LastAccDate),0),fileinfo.lastAccessTime);
|
|
DosTime2NovTime(MakeLong(swap(_LastUpdDate),swap(_LastUpdTime))
|
|
,fileinfo.ModifyTime);
|
|
DosTime2NovTime(MakeLong(swap(_LastArchDate),swap(_lastArchTime))
|
|
,fileinfo.ArchiveTime);
|
|
end;
|
|
ScanFileInformation:=(result=0)
|
|
{ 89 No search privileges FF No more matching files }
|
|
end;
|
|
|
|
|
|
{F217/10 [2.15c+]}
|
|
Function SetFileInformation(DirHandle:Byte; FilePath:string;
|
|
SearchAttrib:Byte;
|
|
fileInfo:TEntry):boolean;
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_Fattr,
|
|
_ExtFattr :Byte;
|
|
reserved1 :LongInt; {hi-lo}
|
|
_crDate :word; {hi-lo}
|
|
_lastAccDate :word; {hi-lo}
|
|
_lastUpdTime :Longint;
|
|
_ownerObjId :Longint; {hi-lo}
|
|
_lastArchTime:Longint;
|
|
reserved2 :array[1..56] of byte;
|
|
_dirHandle :Byte;
|
|
_searchAttr :byte;
|
|
_filePath :string;
|
|
end;
|
|
TPreq=^Treq;
|
|
Var DummyDate:Longint;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$10;
|
|
_Fattr:=Lo(LowLong(fileInfo.Attributes));
|
|
_ExtFattr:=Hi(LowLong(fileinfo.Attributes));
|
|
_ownerObjId:=Lswap(fileinfo.OwnerId); {force hi-lo}
|
|
_dirHandle:=DirHandle;
|
|
_searchAttr:=SearchAttrib;
|
|
_filePath:=FilePath;
|
|
If Dirhandle=0
|
|
then ConvertPathToVolFormat(_FilePath);
|
|
UpString(_filePath);
|
|
NovTime2DosTime(fileinfo.CreationTime,dummyDate);
|
|
_crDate:=HiLong(dummyDate);
|
|
NovTime2DosTime(fileinfo.LastAccessTime,dummyDate);
|
|
_lastAccDate:=HiLong(dummyDate);
|
|
NovTime2DosTime(fileinfo.ModifyTime,_lastUpdTime);
|
|
NovTime2DosTime(fileinfo.ArchiveTime,_lastArchTime);
|
|
len:=82+ord(_filepath[0]);
|
|
F2SystemCall($17,len+2,0,result);
|
|
end;
|
|
SetFileInformation:=(result=0);
|
|
{ result codes: 00 Success }
|
|
end;
|
|
|
|
|
|
{F244 [2.1x/3.x]}
|
|
Function EraseFiles(dirHandle, searchAttrib:Byte; filePath:string ):boolean;
|
|
{ marks files for deletion / in DOS parlance: delete file, file remains purgable }
|
|
Type Treq=record
|
|
_dirHandle:Byte;
|
|
_Sattr:Byte;
|
|
_filePath:string;
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
_dirHandle:=dirHandle;
|
|
_Sattr:=searchAttrib;
|
|
_filePath:=filePath;
|
|
F2SystemCall($44,3+ord(_filepath[0]),0,result);
|
|
end;
|
|
EraseFiles:=(result=0);
|
|
{ resultcodes: 00 Success; 98h Volume doesn't exist; 9Bh bad directory handle;
|
|
9Ch invalid path; FFh no files found error. }
|
|
end;
|
|
|
|
{F216/1B [3.0+]}
|
|
Function ScanSalvagableFiles(DirHandle:Byte;
|
|
{i/o} Var EntryId:Longint;
|
|
{out} Var Entry:Tentry ):boolean;
|
|
{ Iterate (with entryId set to -1 at first) until an error $FF occurs }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_DirHandle:Byte;
|
|
_EntryId :Longint; {low_word-hi_word & each word lo-hi }
|
|
end;
|
|
Trep=record
|
|
_EntryId :Longint;
|
|
_Entry :TintEntry;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$1B;
|
|
_DirHandle:=DirHandle;
|
|
_EntryId:=EntryId;
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),Sizeof(Trep),result);
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
EntryId:=_EntryId; {return next EntryId for iteration}
|
|
{low_word-hi_word & each word lo-hi }
|
|
Convert2ExtEntry(_Entry,Entry);
|
|
end;
|
|
ScanSalvagableFiles:=(result=0)
|
|
{ 98 Volume does not exist FF No more erased files }
|
|
end;
|
|
|
|
{F216/1D [3.0+]}
|
|
Function PurgeSalvagableFile(DirHandle:Byte;
|
|
EntryId:Longint; FileName:string):boolean;
|
|
{ either supply an entryId and an empty filename,
|
|
or supply an entryId of -1 and a filename. Note that the filename
|
|
may not be unique: there may be more than one old deleted versions
|
|
of a filename. }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_DirHandle:Byte;
|
|
_EntryId :Longint; {low_word-hi_word & each word lo-hi }
|
|
_Name :string[255];
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$1D;
|
|
_DirHandle:=DirHandle;
|
|
_EntryId:=EntryId;
|
|
_Name:=FileName;
|
|
UpString(_name);
|
|
len:=7+ord(_Name[0]);
|
|
F2SystemCall($16,len+2,0,result);
|
|
end;
|
|
PurgeSalvagableFile:=(result=0)
|
|
end;
|
|
|
|
{F216/1C [3.0+] }
|
|
Function RecoverSalvagableFile(dirHandle:Byte; EntryId:Longint;
|
|
OldName,NewName:string):boolean;
|
|
{ entryId may be set to -1
|
|
OldName is the name of the file before it was deleted.
|
|
NewName is the name to be assigned to the recovered file }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_DirHandle :Byte;
|
|
_EntryId :Longint; {low_word-hi_word & each word lo-hi }
|
|
_OldAndNewName:string[255];
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$1C;
|
|
_DirHandle:=DirHandle;
|
|
_EntryId:=EntryId;
|
|
UpString(OldName);
|
|
UpString(NewName);
|
|
_OldAndNewName:=OldName;
|
|
move(NewName[0],_OldAndNewName[ord(oldname[0])+1],ord(NewName[0])+1);
|
|
len:=8+ord(oldName[0])+ord(NewName[0]);
|
|
F2SystemCall($16,len+2,0,result);
|
|
end;
|
|
RecoverSalvagableFile:=(result=0)
|
|
{ 98 Volume does not exist FF No more erased files }
|
|
end;
|
|
|
|
|
|
{F216/24 [3.0+]}
|
|
Function SetDirRestriction(DirHandle:Byte; DiskSpaceLimit:Longint):boolean;
|
|
{ limit expressed in Blocks. set limit to 0 to lift limit.
|
|
use a negative number if limit should be equal to 0 }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_DirHandle:Byte;
|
|
_Limit :Longint;
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$24;
|
|
_DirHandle:=DirHandle;
|
|
_Limit:=DiskSpaceLimit;
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),0,result);
|
|
SetDirRestriction:=(result=0)
|
|
end;
|
|
|
|
|
|
{F216/23 [3.0+]}
|
|
Function ScanDirRestrictions(DirHandle:Byte;
|
|
Var NumberOfEntries:Byte;
|
|
Var RestrInfo:TdirRestrList):boolean;
|
|
Type Treq=record
|
|
len:word;
|
|
subFunc:byte;
|
|
_DirHandle:Byte;
|
|
end;
|
|
Trep=record
|
|
_Entries:Byte;
|
|
_Info:TdirRestrList;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$23;
|
|
_DirHandle:=DirHandle;
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),Sizeof(Trep),result);
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
NumberOfEntries:=_Entries;
|
|
RestrInfo:=_Info;
|
|
end;
|
|
ScanDirRestrictions:=(result=0)
|
|
end;
|
|
|
|
|
|
Procedure FixEntryNameFormat(Var s:string);
|
|
Var res:string;
|
|
p:byte;
|
|
begin
|
|
res:='';
|
|
for p:=1 to ord(s[0])
|
|
do begin
|
|
if s[p]='?'
|
|
then res:=res+#$FF+#$BF
|
|
else if s[p]='*'
|
|
then res:=res+#$FF+'*'
|
|
else res:=res+s[p]
|
|
end;
|
|
s:=res;
|
|
end;
|
|
|
|
|
|
{F216/1E [2.15c+]}
|
|
Function ScanDirectoryEntry(DirHandle:Byte; EntryName:string; SearchFlags:Longint;
|
|
{i/o} Var EntryId:Longint;
|
|
{out} Var Entry:Tentry ):boolean;
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_DirHandle :Byte;
|
|
_SearchFlags:Byte; { standard: $16 for dirs / $06 for files }
|
|
_SeqNbr :Longint; { lo-hi , set to -1 initially }
|
|
_EntryName :string;
|
|
end;
|
|
|
|
Trep=record { len = 84h = 132 dec. }
|
|
_EntryID :Longint; { lo-hi }
|
|
_Entry :TintEntry;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$1E;
|
|
_DirHandle:=DirHandle;
|
|
_SearchFlags:=SearchFlags;
|
|
_SeqNbr:=EntryId;
|
|
_EntryName:=EntryName;UpString(_EntryName);
|
|
FixEntryNameFormat(_EntryName);
|
|
len:=8+ord(_EntryName[0]);
|
|
F2SystemCall($16,len+2,Sizeof(Trep),result);
|
|
end;
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
EntryId:=_EntryId; {return next EntryId for iteration}
|
|
Convert2ExtEntry(_Entry,entry);
|
|
end;
|
|
ScanDirectoryEntry:=(result=0)
|
|
end;
|
|
|
|
{F216/25 [2.15c+] }
|
|
Function SetEntry(DirHandle:Byte;EntryId:Longint;SearchFlags:Byte;
|
|
ModFlags:Longint; Entry:Tentry ):boolean;
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_dirHandle:Byte;
|
|
_SFlags :Byte;
|
|
_EntryId :Longint; {lo-hi}
|
|
_ModFlags :Longint; {lo-hi}
|
|
_Entry :TintEntry;
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$25;
|
|
_dirHandle:=DirHandle;
|
|
_EntryId:=EntryId;
|
|
_ModFlags:=ModFlags;
|
|
Convert2IntEntry(Entry,_Entry);
|
|
end;
|
|
F2SystemCall($16,SizeOf(Treq),0,result);
|
|
SetEntry:=(result=0)
|
|
end;
|
|
|
|
{------------------ Secondary Functions ----------------------------}
|
|
|
|
Function IsFileShareable(Path : String):boolean;
|
|
|
|
var F: File;
|
|
FAttr : Word;
|
|
|
|
begin
|
|
{ Assign(F, Path);
|
|
GetFAttr(F, FAttr);
|
|
result:=DOSerror; }
|
|
IsFileShareable:=(result=0) and ((FAttr and $80)>0)
|
|
end;
|
|
|
|
function FlagFileShareable(Path : String) : Boolean;
|
|
{ when the file could NOT be made shareable, false is returned as the
|
|
function result, a doserror# is returned as the result code. }
|
|
var F : File;
|
|
Attr : Word;
|
|
ErrCode : word;
|
|
Share : Boolean;
|
|
begin
|
|
if NOT IsFileShareable(Path) { Share: is it sharable? }
|
|
then begin
|
|
Assign(F,Path);
|
|
{SetFAttr(F,Attr or A_SHAREABLE); OR existing atrib. with SHARE bit }
|
|
{Result := DOSError;}
|
|
end;
|
|
FlagFileShareable := (Result=0);
|
|
end;
|
|
|
|
|
|
Function GetFileHandle(Var f):word;
|
|
begin
|
|
{GetFileHandle:=filerec(f).handle;}
|
|
end;
|
|
|
|
{------===================-- Trustee/Max. Rights masks --=================--}
|
|
|
|
|
|
{F216/27 [3.0+]}
|
|
Function SetTrustee(DirHandle:Byte;DirPath:string;
|
|
TrusteeObjectID:Longint;
|
|
RightsMask:Word ):boolean;
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_DirHandle:byte;
|
|
_ObjId :Longint; { hi-lo }
|
|
_Rights :Word; { lo-hi }
|
|
_DirPath :string;
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$27;
|
|
_DirHandle:=DirHandle;
|
|
if DirHandle=0
|
|
then ConvertPathToVolFormat(DirPath);
|
|
_DirPath:=DirPath;UpString(_DirPath);
|
|
_ObjId:=Lswap(TrusteeObjectId);
|
|
_Rights:=RightsMask;
|
|
len:=9+ord(_DirPath[0]);
|
|
F2SystemCall($16,len+2,0,result);
|
|
end;
|
|
SetTrustee:=(result=0)
|
|
{ Possible resultcodes: 8C No modify privileges;
|
|
98 Volume doesn't exist; 9B Bad directory handle
|
|
9C Invalid path; FC No such bindery object }
|
|
end;
|
|
|
|
|
|
{F216/2B [3.0+]}
|
|
Function DeleteTrustee(DirHandle:Byte;DirPath:String;
|
|
TrusteeObjectId:Longint):boolean;
|
|
{ If DirHandle equals 0, DirPath should be according to the
|
|
VOL:\path format. All other path formats will result in
|
|
an resultcode of 98h (No such volume) }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc :byte;
|
|
_DirHandle:byte;
|
|
_ObjId :Longint; { hi-lo }
|
|
_Unused :Byte;
|
|
_DirPath :string;
|
|
end;
|
|
TPreq=^Treq;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
subFunc:=$2B;
|
|
_DirHandle:=DirHandle;
|
|
if DirHandle=0
|
|
then ConvertPathToVolFormat(DirPath);
|
|
_DirPath:=DirPath;UpString(_DirPath);
|
|
_ObjId:=Lswap(TrusteeObjectId);
|
|
_Unused:=0;
|
|
len:=8+ord(_DirPath[0]);
|
|
F2SystemCall($16,len+2,0,result);
|
|
end;
|
|
DeleteTrustee:=(result=0);
|
|
{ Possible resultcodes: 98 Volume doesn't exist
|
|
9B Bad directory handle; 9C Invalid path
|
|
FE no such trustee }
|
|
end;
|
|
|
|
|
|
{F216/2A [3.0+]}
|
|
function GetEffectiveRights(DirHandle:Byte;DirPath:String;
|
|
var Rights:Word) : Boolean;
|
|
{ returns the requesting workstation's effective directory rights }
|
|
Type Treq=record
|
|
Len : word;
|
|
SubF : Byte;
|
|
_DirHandle : Byte;
|
|
_DirName : String;
|
|
end;
|
|
TRep=record
|
|
_RightsMask : Word;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
begin
|
|
with TPreq(GlobalReqBuf)^
|
|
do begin
|
|
SubF := $2A;
|
|
_DirHandle := DirHandle;
|
|
if DirHandle=0
|
|
then ConvertPathToVolFormat(DirPath);
|
|
_DirName := DirPath;UpString(_DirName);
|
|
Len := 3+ord(DirPath[0]);
|
|
F2SystemCall($16,len+2,SizeOf(Trep),result);
|
|
end;
|
|
with TPrep(GlobalReplyBuf)^
|
|
do Rights:=_RightsMask;
|
|
GetEffectiveRights:=(Result=0);
|
|
{ return byte
|
|
00h - Success
|
|
98h - Volume Does Not Exist
|
|
9Bh - Bad Directory Handle }
|
|
end;
|
|
|
|
|
|
{F216/04 [2.15c+]}
|
|
Function ModifyMaximumRightsMask(DirHandle:Byte;DirPath:string;
|
|
RevokeRightsMask,GrantRightsMask:Word):boolean;
|
|
Type Treq=record
|
|
len:word;
|
|
subFunc:byte;
|
|
_DirHandle:Byte;
|
|
_GrantRM,
|
|
_RevokeRM:Byte;
|
|
_DirPath:String;
|
|
end;
|
|
Trep=record
|
|
_EffectiveRightsMask:Byte;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=5+ord(DirPath[0]);
|
|
subFunc:=$04;
|
|
_DirHandle:=DirHandle;
|
|
if DirHandle=0
|
|
then ConvertPathToVolFormat(DirPath);
|
|
_GrantRM:=MapV3RightsToV2(GrantRightsMask);
|
|
_RevokeRM:=MapV3RightsToV2(RevokeRightsMask);
|
|
_DirPath:=DirPath;
|
|
F2SystemCall($16,len+2,Sizeof(Trep),result);
|
|
end;
|
|
{With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
--- nothing is done with the returned value---
|
|
end;}
|
|
ModifyMaximumRightsMask:=(result=0)
|
|
{ result codes: 8C No modify privileges; 98 Volume dosn't exist;
|
|
9C Invalid path }
|
|
end;
|
|
|
|
|
|
|
|
{F217/47 [2.15c+]}
|
|
Function ScanBinderyObjectTrusteePaths(TrusteeObjectId:Longint;
|
|
VolumeNumber:Byte;
|
|
{i/o} Var SequenceNumber:word;
|
|
{out} Var AccessMask:Word;
|
|
Var Path:string ):boolean;
|
|
{ You must be supervisor (-equivalent) or the TrusteeObject itself
|
|
to use this function.
|
|
Initially, sequencenumber should be set to 0. }
|
|
Type Treq=record
|
|
len :word;
|
|
subFunc:byte;
|
|
_VolNbr:Byte;
|
|
_SeqNbr:word; {hi-lo}
|
|
_ObjId :Longint; {hi-lo}
|
|
end;
|
|
Trep=record
|
|
_NextSeqNbr:Word; {hi-lo}
|
|
_ObjId :Longint; {hi-lo}
|
|
_AccMask :byte;
|
|
_Path :string;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$47;
|
|
_VolNbr:=VolumeNumber;
|
|
_SeqNbr:=swap(SequenceNumber);
|
|
_ObjId:=Lswap(TrusteeObjectId);
|
|
end;
|
|
F2SystemCall($17,SizeOf(Treq),Sizeof(Trep),result);
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
SequenceNumber:=Lswap(_NextSeqNbr);
|
|
Accessmask:=_AccMask; {MapV2RightsToV3(_accMask);}
|
|
Path:=_Path;
|
|
end;
|
|
ScanBinderyObjectTrusteePaths:=(result=0)
|
|
{ resultcodes:
|
|
$96 Server out of memory; $F0 Wildcard not allowed;
|
|
$F1 Invalid bindery security; $FC No such object;
|
|
$FE Server bindery locked; $FF Bindery failure }
|
|
end;
|
|
|
|
{F216/26 [3.0+]}
|
|
Function ScanEntryForTrustees(DirHandle:Byte;DirPath:String;
|
|
{i/o} Var SequenceNumber:Byte;
|
|
{out} Var TrusteeInfo: TtrusteeInformation):boolean;
|
|
{ Set SequenceNumber to 0 initially,
|
|
iterate until error $9C (no more trustees) is returned }
|
|
{ see GETTR in the XFILE archive for an example }
|
|
Type Treq=record
|
|
len:word;
|
|
subFunc:byte;
|
|
_DirHandle:Byte;
|
|
_SeqNbr:Byte;
|
|
_DirPath:String;
|
|
end;
|
|
Trep=record
|
|
_Info:TtrusteeInformation;
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Var t:Byte;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=4+ord(DirPath[0]);
|
|
subFunc:=$26;
|
|
_DirHandle:=DirHandle;
|
|
if DirHandle=0
|
|
then ConvertPathToVolFormat(DirPath);
|
|
_SeqNbr:=SequenceNumber;
|
|
_DirPath:=DirPath;UpString(_DirPath);
|
|
F2SystemCall($16,len+2,Sizeof(Trep),result);
|
|
end;
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
inc(SequenceNumber);
|
|
TrusteeInfo.NumberOfTrustees:=_Info.NumberOfTrustees;
|
|
for t:=1 to 20
|
|
do begin
|
|
TrusteeInfo.TrusteeId[t]:=Lswap(_Info.TrusteeId[t]);
|
|
TrusteeInfo.TrusteeRights[t]:=_Info.TrusteeRights[t];
|
|
end;
|
|
end;
|
|
ScanEntryForTrustees:=(result=0)
|
|
{ resultcodes:
|
|
$9C No more trustees }
|
|
end;
|
|
|
|
|
|
|
|
|
|
{F2 [2.15c+]
|
|
Function ( ):boolean;
|
|
Type Treq=record
|
|
len:word;
|
|
subFunc:byte;
|
|
|
|
end;
|
|
Trep=record
|
|
|
|
end;
|
|
TPreq=^Treq;
|
|
TPrep=^Trep;
|
|
Begin
|
|
WITH TPreq(GlobalReqBuf)^
|
|
do begin
|
|
len:=SizeOf(Treq)-2;
|
|
subFunc:=$
|
|
|
|
end;
|
|
F2SystemCall($ ,SizeOf(Treq),Sizeof(Trep),result);
|
|
With TPrep(GlobalReplyBuf)^
|
|
do begin
|
|
|
|
end;
|
|
:=(result=0)
|
|
end; }
|
|
|
|
end. |