mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 11:24:16 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1095 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			1095 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
 | 
						|
    This file is part of the Free Pascal run time library.
 | 
						|
    Copyright (c) 1999-2000 by Florian Klaempfl
 | 
						|
    member of the Free Pascal development team
 | 
						|
 | 
						|
    Sysutils unit for OS/2
 | 
						|
 | 
						|
    See the file COPYING.FPC, included in this distribution,
 | 
						|
    for details about the copyright.
 | 
						|
 | 
						|
    This program is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | 
						|
 | 
						|
 **********************************************************************}
 | 
						|
{$IFNDEF FPC_DOTTEDUNITS}
 | 
						|
unit sysutils;
 | 
						|
{$ENDIF FPC_DOTTEDUNITS}
 | 
						|
interface
 | 
						|
 | 
						|
{$MODE objfpc}
 | 
						|
{$MODESWITCH OUT}
 | 
						|
{$IFDEF UNICODERTL}
 | 
						|
{$MODESWITCH UNICODESTRINGS}
 | 
						|
{$ELSE}
 | 
						|
{$H+}
 | 
						|
{$ENDIF}
 | 
						|
{$modeswitch typehelpers}
 | 
						|
{$modeswitch advancedrecords}
 | 
						|
 | 
						|
{$DEFINE HAS_SLEEP}
 | 
						|
{$DEFINE HAS_OSERROR}
 | 
						|
 | 
						|
{ used OS file system APIs use ansistring }
 | 
						|
{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
 | 
						|
{ OS has an ansistring/single byte environment variable API }
 | 
						|
{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
 | 
						|
{ OS has an ansistring/single byte API for executing other processes }
 | 
						|
{$DEFINE EXECUTEPROCUNI}
 | 
						|
 | 
						|
{ Include platform independent interface part }
 | 
						|
{$i sysutilh.inc}
 | 
						|
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
{$IFDEF FPC_DOTTEDUNITS}
 | 
						|
  uses
 | 
						|
    System.SysConst, OS2Api.doscalls;
 | 
						|
{$ELSE FPC_DOTTEDUNITS}
 | 
						|
  uses
 | 
						|
    sysconst, DosCalls;
 | 
						|
{$ENDIF FPC_DOTTEDUNITS}
 | 
						|
 | 
						|
 | 
						|
type
 | 
						|
(* Necessary here due to a different definition of TDateTime in DosCalls. *)
 | 
						|
  TDateTime = System.TDateTime;
 | 
						|
 | 
						|
threadvar
 | 
						|
  LastOSError: cardinal;
 | 
						|
 | 
						|
{$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
 | 
						|
{$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
 | 
						|
{$DEFINE FPC_FEXPAND_GETENV_PCHAR}
 | 
						|
{$DEFINE HAS_GETTICKCOUNT}
 | 
						|
{$DEFINE HAS_GETTICKCOUNT64}
 | 
						|
{$DEFINE HAS_LOCALTIMEZONEOFFSET}
 | 
						|
 | 
						|
{ Include platform independent implementation part }
 | 
						|
{$i sysutils.inc}
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                              File Functions
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
const
 | 
						|
 ofRead        = $0000;     {Open for reading}
 | 
						|
 ofWrite       = $0001;     {Open for writing}
 | 
						|
 ofReadWrite   = $0002;     {Open for reading/writing}
 | 
						|
 doDenyRW      = $0010;     {DenyAll (no sharing)}
 | 
						|
 faCreateNew   = $00010000; {Create if file does not exist}
 | 
						|
 faOpenReplace = $00040000; {Truncate if file exists}
 | 
						|
 faCreate      = $00050000; {Create if file does not exist, truncate otherwise}
 | 
						|
 | 
						|
 FindResvdMask = $00003737  {Allowed bits for DosFindFirst parameter Attribute}
 | 
						|
             and $000000FF; {combined with a mask for allowed attributes only}
 | 
						|
 | 
						|
function FileOpen (const FileName: rawbytestring; Mode: integer): THandle;
 | 
						|
Var
 | 
						|
  SystemFileName: RawByteString;
 | 
						|
  Handle: THandle;
 | 
						|
  Rc, Action: cardinal;
 | 
						|
begin
 | 
						|
  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
 | 
						|
(* DenyReadWrite if sharing not specified. *)
 | 
						|
  if (Mode and 112 = 0) or (Mode and 112 > 64) then
 | 
						|
   Mode := Mode or doDenyRW;
 | 
						|
  Rc:=Sys_DosOpenL(PAnsiChar (SystemFileName), Handle, Action, 0, 0, 1, Mode, nil);
 | 
						|
  If Rc=0 then
 | 
						|
    FileOpen:=Handle
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    FileOpen:=feInvalidHandle; //FileOpen:=-RC;
 | 
						|
    //should return feInvalidHandle(=-1) if fail, other negative returned value are no more errors
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
function FileCreate (const FileName: RawByteString): THandle;
 | 
						|
begin
 | 
						|
  FileCreate := FileCreate (FileName, doDenyRW, 777); (* Sharing to DenyAll *)
 | 
						|
end;
 | 
						|
 | 
						|
function FileCreate (const FileName: RawByteString; Rights: integer): THandle;
 | 
						|
begin
 | 
						|
  FileCreate := FileCreate (FileName, doDenyRW, Rights);
 | 
						|
                                      (* Sharing to DenyAll *)
 | 
						|
end;
 | 
						|
 | 
						|
function FileCreate (const FileName: RawByteString; ShareMode: integer;
 | 
						|
                                                     Rights: integer): THandle;
 | 
						|
var
 | 
						|
  SystemFileName: RawByteString;
 | 
						|
  Handle: THandle;
 | 
						|
  RC, Action: cardinal;
 | 
						|
begin
 | 
						|
  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
 | 
						|
  ShareMode := ShareMode and 112;
 | 
						|
  (* Sharing to DenyAll as default in case of values not allowed by OS/2. *)
 | 
						|
  if (ShareMode = 0) or (ShareMode > 64) then
 | 
						|
   ShareMode := doDenyRW;
 | 
						|
  RC := Sys_DosOpenL (PAnsiChar (SystemFileName), Handle, Action, 0, 0, $12,
 | 
						|
                                    faCreate or ofReadWrite or ShareMode, nil);
 | 
						|
  if RC = 0 then
 | 
						|
   FileCreate := Handle
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    FileCreate := feInvalidHandle;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
End;
 | 
						|
 | 
						|
 | 
						|
function FileRead (Handle: THandle; Out Buffer; Count: longint): longint;
 | 
						|
Var
 | 
						|
  T: cardinal;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  RC := DosRead (Handle, Buffer, Count, T);
 | 
						|
  if RC = 0 then
 | 
						|
   FileRead := longint (T)
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    FileRead := -1;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
function FileWrite (Handle: THandle; const Buffer; Count: longint): longint;
 | 
						|
Var
 | 
						|
  T: cardinal;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  RC := DosWrite (Handle, Buffer, Count, T);
 | 
						|
  if RC = 0 then
 | 
						|
   FileWrite := longint (T)
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    FileWrite := -1;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
function FileSeek (Handle: THandle; FOffset, Origin: longint): longint;
 | 
						|
var
 | 
						|
  NPos: int64;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  RC := Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos);
 | 
						|
  if (RC = 0) and (NPos < high (longint)) then
 | 
						|
    FileSeek:= longint (NPos)
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    FileSeek:=-1;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
function FileSeek (Handle: THandle; FOffset: Int64; Origin: Longint): Int64;
 | 
						|
var
 | 
						|
  NPos: int64;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  RC := Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos);
 | 
						|
  if RC = 0 then
 | 
						|
    FileSeek:= NPos
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    FileSeek:=-1;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure FileClose (Handle: THandle);
 | 
						|
var
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  RC := DosClose (Handle);
 | 
						|
  if RC <> 0 then
 | 
						|
   OSErrorWatch (RC);
 | 
						|
end;
 | 
						|
 | 
						|
function FileTruncate (Handle: THandle; Size: Int64): boolean;
 | 
						|
var
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  RC := Sys_DosSetFileSizeL(Handle, Size);
 | 
						|
  FileTruncate := RC = 0;
 | 
						|
  if RC = 0 then
 | 
						|
   FileSeek(Handle, 0, 2)
 | 
						|
  else
 | 
						|
   OSErrorWatch (RC);
 | 
						|
end;
 | 
						|
 | 
						|
function FileAge (const FileName: RawByteString): Int64;
 | 
						|
var Handle: longint;
 | 
						|
begin
 | 
						|
    Handle := FileOpen (FileName, 0);
 | 
						|
    if Handle <> -1 then
 | 
						|
        begin
 | 
						|
            Result := FileGetDate (Handle);
 | 
						|
            FileClose (Handle);
 | 
						|
        end
 | 
						|
    else
 | 
						|
        Result := -1;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function FileGetSymLinkTarget(const FileName: RawByteString; out SymLinkRec: TRawbyteSymLinkRec): Boolean;
 | 
						|
begin
 | 
						|
  Result := False;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function FileExists (const FileName: RawByteString; FollowLink : Boolean): boolean;
 | 
						|
var
 | 
						|
  L: longint;
 | 
						|
begin
 | 
						|
  { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
 | 
						|
  if FileName = '' then
 | 
						|
    Result := false
 | 
						|
  else
 | 
						|
   begin
 | 
						|
     L := FileGetAttr (FileName);
 | 
						|
     Result := (L >= 0) and (L and (faDirectory or faVolumeID) = 0);
 | 
						|
(* Neither VolumeIDs nor directories are files. *)
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
type    PSearchRec = ^TSearchRec;
 | 
						|
 | 
						|
Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
 | 
						|
 | 
						|
var SR: PSearchRec;
 | 
						|
    FStat: PFileFindBuf3L;
 | 
						|
    Count: cardinal;
 | 
						|
    Err: cardinal;
 | 
						|
    I: cardinal;
 | 
						|
    SystemEncodedPath: RawByteString;
 | 
						|
 | 
						|
begin
 | 
						|
  SystemEncodedPath := ToSingleByteFileSystemEncodedFileName(Path);
 | 
						|
  New (FStat);
 | 
						|
  Rslt.FindHandle := THandle ($FFFFFFFF);
 | 
						|
  Count := 1;
 | 
						|
  if FSApi64 then
 | 
						|
   Err := DosFindFirst (PAnsiChar (SystemEncodedPath), Rslt.FindHandle,
 | 
						|
            Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandardL)
 | 
						|
  else
 | 
						|
   Err := DosFindFirst (PAnsiChar (SystemEncodedPath), Rslt.FindHandle,
 | 
						|
            Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandard);
 | 
						|
  if Err <> 0 then
 | 
						|
   OSErrorWatch (Err)
 | 
						|
  else if Count = 0 then
 | 
						|
   Err := 18;
 | 
						|
  InternalFindFirst := -Err;
 | 
						|
  if Err = 0 then
 | 
						|
   begin
 | 
						|
    Rslt.ExcludeAttr := 0;
 | 
						|
    Rslt.Time := cardinal (FStat^.DateLastWrite) shl 16 + FStat^.TimeLastWrite;
 | 
						|
    if FSApi64 then
 | 
						|
     begin
 | 
						|
      Rslt.Size := FStat^.FileSize;
 | 
						|
      Name := FStat^.Name;
 | 
						|
      Rslt.Attr := FStat^.AttrFile;
 | 
						|
     end
 | 
						|
    else
 | 
						|
     begin
 | 
						|
      Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
 | 
						|
      Name := PFileFindBuf3 (FStat)^.Name;
 | 
						|
      Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
 | 
						|
     end;
 | 
						|
    SetCodePage (Name, DefaultFileSystemCodePage, false);
 | 
						|
   end
 | 
						|
  else
 | 
						|
   InternalFindClose(Rslt.FindHandle);
 | 
						|
 | 
						|
  Dispose (FStat);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 | 
						|
var
 | 
						|
  SR: PSearchRec;
 | 
						|
  FStat: PFileFindBuf3L;
 | 
						|
  Count: cardinal;
 | 
						|
  Err: cardinal;
 | 
						|
begin
 | 
						|
  New (FStat);
 | 
						|
  Count := 1;
 | 
						|
  Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^), Count);
 | 
						|
  if Err <> 0 then
 | 
						|
   OSErrorWatch (Err)
 | 
						|
  else if Count = 0 then
 | 
						|
   Err := 18;
 | 
						|
  InternalFindNext := -Err;
 | 
						|
  if Err = 0 then
 | 
						|
  begin
 | 
						|
    Rslt.ExcludeAttr := 0;
 | 
						|
    Rslt.Time := cardinal (FStat^.DateLastWrite) shl 16 + FStat^.TimeLastWrite;
 | 
						|
    if FSApi64 then
 | 
						|
     begin
 | 
						|
      Rslt.Size := FStat^.FileSize;
 | 
						|
      Name := FStat^.Name;
 | 
						|
      Rslt.Attr := FStat^.AttrFile;
 | 
						|
     end
 | 
						|
    else
 | 
						|
     begin
 | 
						|
      Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
 | 
						|
      Name := PFileFindBuf3 (FStat)^.Name;
 | 
						|
      Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
 | 
						|
     end;
 | 
						|
    SetCodePage (Name, DefaultFileSystemCodePage, false);
 | 
						|
  end;
 | 
						|
  Dispose (FStat);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
Procedure InternalFindClose(var Handle: THandle);
 | 
						|
var
 | 
						|
  SR: PSearchRec;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  RC := DosFindClose (Handle);
 | 
						|
  Handle := 0;
 | 
						|
  if RC <> 0 then
 | 
						|
   OSErrorWatch (RC);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function FileGetDate (Handle: THandle): Int64;
 | 
						|
var
 | 
						|
  FStat: TFileStatus3;
 | 
						|
  Time: Longint;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  RC := DosQueryFileInfo(Handle, ilStandard, @FStat, SizeOf(FStat));
 | 
						|
  if RC = 0 then
 | 
						|
  begin
 | 
						|
    Time := FStat.TimeLastWrite + dword (FStat.DateLastWrite) shl 16;
 | 
						|
    if Time = 0 then
 | 
						|
      Time := FStat.TimeCreation + dword (FStat.DateCreation) shl 16;
 | 
						|
  end else
 | 
						|
   begin
 | 
						|
    Time:=0;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
  FileGetDate:=Time;
 | 
						|
end;
 | 
						|
 | 
						|
function FileSetDate (Handle: THandle; Age: Int64): longint;
 | 
						|
var
 | 
						|
  FStat: PFileStatus3;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  New (FStat);
 | 
						|
  RC := DosQueryFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^));
 | 
						|
  if RC <> 0 then
 | 
						|
   begin
 | 
						|
    FileSetDate := -1;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    FStat^.DateLastAccess := Hi (dword (Age));
 | 
						|
    FStat^.DateLastWrite := Hi (dword (Age));
 | 
						|
    FStat^.TimeLastAccess := Lo (dword (Age));
 | 
						|
    FStat^.TimeLastWrite := Lo (dword (Age));
 | 
						|
    RC := DosSetFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^));
 | 
						|
    if RC <> 0 then
 | 
						|
     begin
 | 
						|
      FileSetDate := -1;
 | 
						|
      OSErrorWatch (RC);
 | 
						|
     end
 | 
						|
    else
 | 
						|
     FileSetDate := 0;
 | 
						|
   end;
 | 
						|
  Dispose (FStat);
 | 
						|
end;
 | 
						|
 | 
						|
function FileGetAttr (const FileName: RawByteString): longint;
 | 
						|
var
 | 
						|
  FS: PFileStatus3;
 | 
						|
  SystemFileName: RawByteString;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
 | 
						|
  New(FS);
 | 
						|
  RC := DosQueryPathInfo(PAnsiChar (SystemFileName), ilStandard, FS, SizeOf(FS^));
 | 
						|
  if RC = 0 then
 | 
						|
   Result := FS^.AttrFile
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    Result := - longint (RC);
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
  Dispose(FS);
 | 
						|
end;
 | 
						|
 | 
						|
function FileSetAttr (const Filename: RawByteString; Attr: longint): longint;
 | 
						|
Var
 | 
						|
  FS: PFileStatus3;
 | 
						|
  SystemFileName: RawByteString;
 | 
						|
  RC: cardinal;
 | 
						|
Begin
 | 
						|
  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
 | 
						|
  New(FS);
 | 
						|
  RC := DosQueryPathInfo (PAnsiChar (SystemFileName), ilStandard, FS, SizeOf (FS^));
 | 
						|
  if RC = 0 then
 | 
						|
   begin
 | 
						|
    FS^.AttrFile:=Attr;
 | 
						|
    RC := DosSetPathInfo(PAnsiChar (SystemFileName), ilStandard, FS, SizeOf(FS^), 0);
 | 
						|
    if RC <> 0 then
 | 
						|
     OSErrorWatch (RC);
 | 
						|
   end
 | 
						|
  else
 | 
						|
   OSErrorWatch (RC);
 | 
						|
  Result := - longint (RC);
 | 
						|
  Dispose(FS);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function DeleteFile (const FileName: RawByteString): boolean;
 | 
						|
var
 | 
						|
  SystemFileName: RawByteString;
 | 
						|
  RC: cardinal;
 | 
						|
Begin
 | 
						|
  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
 | 
						|
  RC := DosDelete (PAnsiChar (SystemFileName));
 | 
						|
  if RC <> 0 then
 | 
						|
   begin
 | 
						|
    Result := false;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end
 | 
						|
  else
 | 
						|
   Result := true;
 | 
						|
End;
 | 
						|
 | 
						|
function RenameFile (const OldName, NewName: RawByteString): boolean;
 | 
						|
var
 | 
						|
  OldSystemFileName, NewSystemFileName: RawByteString;
 | 
						|
  RC: cardinal;
 | 
						|
Begin
 | 
						|
  OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
 | 
						|
  NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
 | 
						|
  RC := DosMove (PAnsiChar (OldSystemFileName), PAnsiChar (NewSystemFileName));
 | 
						|
  if RC <> 0 then
 | 
						|
   begin
 | 
						|
    Result := false;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end
 | 
						|
  else
 | 
						|
   Result := true;
 | 
						|
End;
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                              Disk Functions
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
function DiskFree (Drive: byte): int64;
 | 
						|
 | 
						|
var FI: TFSinfo;
 | 
						|
    RC: cardinal;
 | 
						|
 | 
						|
begin
 | 
						|
  {In OS/2, we use the filesystem information.}
 | 
						|
  RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
 | 
						|
  if RC = 0 then
 | 
						|
   DiskFree := int64 (FI.Free_Clusters) *
 | 
						|
                   int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    DiskFree := -1;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
function DiskSize (Drive: byte): int64;
 | 
						|
 | 
						|
var FI: TFSinfo;
 | 
						|
    RC: cardinal;
 | 
						|
 | 
						|
begin
 | 
						|
  {In OS/2, we use the filesystem information.}
 | 
						|
  RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
 | 
						|
  if RC = 0 then
 | 
						|
   DiskSize := int64 (FI.Total_Clusters) *
 | 
						|
                   int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    DiskSize := -1;
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function DirectoryExists (const Directory: RawByteString; FollowLink : Boolean): boolean;
 | 
						|
var
 | 
						|
  L: longint;
 | 
						|
begin
 | 
						|
  { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
 | 
						|
  if Directory = '' then
 | 
						|
   Result := false
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    if ((Length (Directory) = 2) or
 | 
						|
        (Length (Directory) = 3) and
 | 
						|
        (Directory [3] in AllowDirectorySeparators)) and
 | 
						|
       (Directory [2] in AllowDriveSeparators) and
 | 
						|
       (UpCase (Directory [1]) in ['A'..'Z']) then
 | 
						|
(* Checking attributes for 'x:' is not possible but for 'x:.' it is. *)
 | 
						|
     L := FileGetAttr (Directory + '.')
 | 
						|
    else if (Directory [Length (Directory)] in AllowDirectorySeparators) and
 | 
						|
                                              (Length (Directory) > 1) and
 | 
						|
(* Do not remove '\' in '\\' (invalid path, possibly broken UNC path). *)
 | 
						|
      not (Directory [Length (Directory) - 1] in AllowDirectorySeparators) then
 | 
						|
     L := FileGetAttr (Copy (Directory, 1, Length (Directory) - 1))
 | 
						|
    else
 | 
						|
     L := FileGetAttr (Directory);
 | 
						|
    Result := (L > 0) and (L and faDirectory = faDirectory);
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                              Time Functions
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
{$DEFINE HAS_DUAL_TZHANDLING}
 | 
						|
{$I tzenv.inc}
 | 
						|
 | 
						|
var
 | 
						|
  TZAlwaysFromEnv: boolean;
 | 
						|
 | 
						|
procedure InitTZ2; inline;
 | 
						|
var
 | 
						|
  DT: {$IFDEF FPC_DOTTEDUNITS}OS2Api.{$endif}DosCalls.TDateTime;
 | 
						|
begin
 | 
						|
  DosGetDateTime (DT);
 | 
						|
  TZAlwaysFromEnv := DT.TimeZone = -1;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure GetLocalTime (var SystemTime: TSystemTime);
 | 
						|
var
 | 
						|
  DT: {$IFDEF FPC_DOTTEDUNITS}OS2Api.{$endif}DosCalls.TDateTime;
 | 
						|
begin
 | 
						|
  DosGetDateTime(DT);
 | 
						|
  with SystemTime do
 | 
						|
  begin
 | 
						|
    Year:=DT.Year;
 | 
						|
    Month:=DT.Month;
 | 
						|
    Day:=DT.Day;
 | 
						|
    DayOfWeek:=DT.WeekDay;
 | 
						|
    Hour:=DT.Hour;
 | 
						|
    Minute:=DT.Minute;
 | 
						|
    Second:=DT.Second;
 | 
						|
    MilliSecond:=DT.Sec100 * 10;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function GetUniversalTime (var SystemTime: TSystemTime): boolean;
 | 
						|
var
 | 
						|
  DT: {$IFDEF FPC_DOTTEDUNITS}OS2Api.{$endif}DosCalls.TDateTime;
 | 
						|
  Offset: longint;
 | 
						|
begin
 | 
						|
  if TZAlwaysFromEnv then
 | 
						|
   begin
 | 
						|
    GetLocalTime (SystemTime);
 | 
						|
    Offset := GetLocalTimeOffset;
 | 
						|
   end
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    DosGetDateTime (DT);
 | 
						|
    with SystemTime do
 | 
						|
     begin
 | 
						|
      Year := DT.Year;
 | 
						|
      Month := DT.Month;
 | 
						|
      Day := DT.Day;
 | 
						|
      DayOfWeek := DT.WeekDay;
 | 
						|
      Hour := DT.Hour;
 | 
						|
      Minute := DT.Minute;
 | 
						|
      Second := DT.Second;
 | 
						|
      MilliSecond := DT.Sec100 * 10;
 | 
						|
     end;
 | 
						|
    if DT.TimeZone = -1 then
 | 
						|
     Offset := GetLocalTimeOffset
 | 
						|
    else
 | 
						|
     Offset := DT.TimeZone;
 | 
						|
   end;
 | 
						|
  UpdateTimeWithOffset (SystemTime, Offset);
 | 
						|
  GetUniversalTime := true;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function GetLocalTimeOffset: integer;
 | 
						|
var
 | 
						|
  DT: {$IFDEF FPC_DOTTEDUNITS}OS2Api.{$endif}DosCalls.TDateTime;
 | 
						|
begin
 | 
						|
  if TZAlwaysFromEnv then
 | 
						|
   begin
 | 
						|
    if InDST then
 | 
						|
     GetLocalTimeOffset := DSTOffsetMin
 | 
						|
    else
 | 
						|
     GetLocalTimeOffset := TZOffsetMin;
 | 
						|
   end
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    DosGetDateTime (DT);
 | 
						|
    if DT.TimeZone <> -1 then
 | 
						|
     GetLocalTimeOffset := DT.TimeZone
 | 
						|
    else
 | 
						|
     begin
 | 
						|
      if InDST then
 | 
						|
       GetLocalTimeOffset := DSTOffsetMin
 | 
						|
      else
 | 
						|
       GetLocalTimeOffset := TZOffsetMin;
 | 
						|
     end;
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                              Misc Functions
 | 
						|
****************************************************************************}
 | 
						|
procedure sysbeep;
 | 
						|
 | 
						|
begin
 | 
						|
  DosBeep (800, 250);
 | 
						|
end;
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                              Locale Functions
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
var
 | 
						|
  Country: TCountryCode;
 | 
						|
  CtryInfo: TCountryInfo;
 | 
						|
 | 
						|
procedure InitAnsi;
 | 
						|
var
 | 
						|
  I: byte;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
    for I := 0 to 255 do
 | 
						|
        UpperCaseTable [I] := Chr (I);
 | 
						|
    Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
 | 
						|
            FillChar (Country, SizeOf (Country), 0);
 | 
						|
            DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
 | 
						|
    for I := 0 to 255 do
 | 
						|
        if UpperCaseTable [I] <> Chr (I) then
 | 
						|
            LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure InitInternational;
 | 
						|
var
 | 
						|
  Size: cardinal;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  Size := 0;
 | 
						|
  FillChar (Country, SizeOf (Country), 0);
 | 
						|
  FillChar (CtryInfo, SizeOf (CtryInfo), 0);
 | 
						|
  RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
 | 
						|
  if RC = 0 then
 | 
						|
   begin
 | 
						|
    DateSeparator := CtryInfo.DateSeparator;
 | 
						|
    case CtryInfo.DateFormat of
 | 
						|
     1: begin
 | 
						|
         ShortDateFormat := 'd/m/y';
 | 
						|
         LongDateFormat := 'dd" "mmmm" "yyyy';
 | 
						|
        end;
 | 
						|
     2: begin
 | 
						|
         ShortDateFormat := 'y/m/d';
 | 
						|
         LongDateFormat := 'yyyy" "mmmm" "dd';
 | 
						|
        end;
 | 
						|
     3: begin
 | 
						|
         ShortDateFormat := 'm/d/y';
 | 
						|
         LongDateFormat := 'mmmm" "dd" "yyyy';
 | 
						|
        end;
 | 
						|
    end;
 | 
						|
    TimeSeparator := CtryInfo.TimeSeparator;
 | 
						|
    DecimalSeparator := CtryInfo.DecimalSeparator;
 | 
						|
    ThousandSeparator := CtryInfo.ThousandSeparator;
 | 
						|
    CurrencyFormat := CtryInfo.CurrencyFormat;
 | 
						|
    CurrencyString := PAnsiChar (CtryInfo.CurrencyUnit);
 | 
						|
   end
 | 
						|
  else
 | 
						|
   OSErrorWatch (RC);
 | 
						|
  InitAnsi;
 | 
						|
  InitInternationalGeneric;
 | 
						|
end;
 | 
						|
 | 
						|
function SysErrorMessage(ErrorCode: Integer): String;
 | 
						|
const
 | 
						|
  SysMsgFile: array [0..10] of AnsiChar = 'OSO001.MSG'#0;
 | 
						|
var
 | 
						|
  OutBuf: array [0..999] of AnsiChar;
 | 
						|
  RetMsgSize: cardinal;
 | 
						|
  RC: cardinal;
 | 
						|
begin
 | 
						|
  RC := DosGetMessage (nil, 0, @OutBuf [0], SizeOf (OutBuf),
 | 
						|
                                       ErrorCode, @SysMsgFile [0], RetMsgSize);
 | 
						|
  if RC = 0 then
 | 
						|
   begin
 | 
						|
    SetLength (Result, RetMsgSize);
 | 
						|
    Move (OutBuf [0], Result [1], RetMsgSize);
 | 
						|
   end
 | 
						|
  else
 | 
						|
   begin
 | 
						|
    Result:=Format(SUnknownErrorCode,[ErrorCode]);
 | 
						|
    OSErrorWatch (RC);
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                              OS Utils
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
function GetEnvPChar (EnvVar: shortstring): PAnsiChar;
 | 
						|
(* The assembler version is more than three times as fast as Pascal. *)
 | 
						|
var
 | 
						|
 P: PAnsiChar;
 | 
						|
begin
 | 
						|
 EnvVar := UpCase (EnvVar);
 | 
						|
{$ASMMODE INTEL}
 | 
						|
 asm
 | 
						|
  cld
 | 
						|
  mov edi, Environment
 | 
						|
  lea esi, EnvVar
 | 
						|
  xor eax, eax
 | 
						|
  lodsb
 | 
						|
@NewVar:
 | 
						|
  cmp byte ptr [edi], 0
 | 
						|
  jz @Stop
 | 
						|
  push eax        { eax contains length of searched variable name }
 | 
						|
  push esi        { esi points to the beginning of the variable name }
 | 
						|
  mov ecx, -1     { our character ('=' - see below) _must_ be found }
 | 
						|
  mov edx, edi    { pointer to beginning of variable name saved in edx }
 | 
						|
  mov al, '='     { searching until '=' (end of variable name) }
 | 
						|
  repne
 | 
						|
  scasb           { scan until '=' not found }
 | 
						|
  neg ecx         { what was the name length? }
 | 
						|
  dec ecx         { corrected }
 | 
						|
  dec ecx         { exclude the '=' character }
 | 
						|
  pop esi         { restore pointer to beginning of variable name }
 | 
						|
  pop eax         { restore length of searched variable name }
 | 
						|
  push eax        { and save both of them again for later use }
 | 
						|
  push esi
 | 
						|
  cmp ecx, eax    { compare length of searched variable name with name }
 | 
						|
  jnz @NotEqual   { ... of currently found variable, jump if different }
 | 
						|
  xchg edx, edi   { pointer to current variable name restored in edi }
 | 
						|
  repe
 | 
						|
  cmpsb           { compare till the end of variable name }
 | 
						|
  xchg edx, edi   { pointer to beginning of variable contents in edi }
 | 
						|
  jz @Equal       { finish if they're equal }
 | 
						|
@NotEqual:
 | 
						|
  xor eax, eax    { look for 00h }
 | 
						|
  mov ecx, -1     { it _must_ be found }
 | 
						|
  repne
 | 
						|
  scasb           { scan until found }
 | 
						|
  pop esi         { restore pointer to beginning of variable name }
 | 
						|
  pop eax         { restore length of searched variable name }
 | 
						|
  jmp @NewVar     { ... or continue with new variable otherwise }
 | 
						|
@Stop:
 | 
						|
  xor eax, eax
 | 
						|
  mov P, eax      { Not found - return nil }
 | 
						|
  jmp @End
 | 
						|
@Equal:
 | 
						|
  pop esi         { restore the stack position }
 | 
						|
  pop eax
 | 
						|
  mov P, edi      { place pointer to variable contents in P }
 | 
						|
@End:
 | 
						|
 end ['eax','ecx','edx','esi','edi'];
 | 
						|
 GetEnvPChar := P;
 | 
						|
end;
 | 
						|
{$ASMMODE ATT}
 | 
						|
 | 
						|
 | 
						|
Function GetEnvironmentVariable(Const EnvVar : String) : String;
 | 
						|
 | 
						|
begin
 | 
						|
    GetEnvironmentVariable := GetEnvPChar (EnvVar);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
Function GetEnvironmentVariableCount : Integer;
 | 
						|
 | 
						|
begin
 | 
						|
(*  Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
 | 
						|
  GetEnvironmentVariableCount := EnvC;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=FPCGetEnvStrFromP (EnvP, Index);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure Sleep (Milliseconds: cardinal);
 | 
						|
 | 
						|
begin
 | 
						|
 DosSleep (Milliseconds);
 | 
						|
end;
 | 
						|
 | 
						|
function SysTimerTick: QWord;
 | 
						|
var
 | 
						|
  L: cardinal;
 | 
						|
begin
 | 
						|
  DosQuerySysInfo (svMsCount, svMsCount, L, 4);
 | 
						|
  SysTimerTick := L;
 | 
						|
end;
 | 
						|
 | 
						|
function ExecuteProcess (const Path: RawByteString;
 | 
						|
                 const ComLine: RawByteString;Flags:TExecuteFlags=[]): integer;
 | 
						|
var
 | 
						|
 E: EOSError;
 | 
						|
 CommandLine: RawByteString;
 | 
						|
 Args0, Args: {$IFDEF FPC_DOTTEDUNITS}OS2Api.{$endif}DosCalls.PByteArray;
 | 
						|
 ObjNameBuf: PAnsiChar;
 | 
						|
 ArgSize: word;
 | 
						|
 Res: TResultCodes;
 | 
						|
 ObjName: shortstring;
 | 
						|
 RC: cardinal;
 | 
						|
 ExecAppType: cardinal;
 | 
						|
 MaxArgsSize: PtrUInt; (* Amount of memory reserved for arguments in bytes. *)
 | 
						|
 MaxArgsSizeInc: word;
 | 
						|
 | 
						|
const
 | 
						|
 ObjBufSize = 512;
 | 
						|
 | 
						|
function StartSession: cardinal;
 | 
						|
var
 | 
						|
 HQ: THandle;
 | 
						|
 SPID, STID, QName: shortstring;
 | 
						|
 SID, PID: cardinal;
 | 
						|
 SD: TStartData;
 | 
						|
 RD: TRequestData;
 | 
						|
 PCI: PChildInfo;
 | 
						|
 CISize: cardinal;
 | 
						|
 Prio: byte;
 | 
						|
begin
 | 
						|
 Result := $FFFFFFFF;
 | 
						|
 FillChar (SD, SizeOf (SD), 0);
 | 
						|
 SD.Length := SizeOf (SD);
 | 
						|
 SD.Related := ssf_Related_Child;
 | 
						|
 if FileExists (Path) then
 | 
						|
(* Full path necessary for starting different executable files from current *)
 | 
						|
(* directory. *)
 | 
						|
  CommandLine := ExpandFileName (Path)
 | 
						|
 else
 | 
						|
  CommandLine := Path;
 | 
						|
 SD.PgmName := PAnsiChar (CommandLine);
 | 
						|
 if ComLine <> '' then
 | 
						|
  SD.PgmInputs := PAnsiChar (ComLine);
 | 
						|
 if ExecInheritsHandles in Flags then
 | 
						|
   SD.InheritOpt := ssf_InhertOpt_Parent;
 | 
						|
 Str (GetProcessID, SPID);
 | 
						|
 Str (ThreadID, STID);
 | 
						|
 QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
 | 
						|
 SD.TermQ := @QName [1];
 | 
						|
 SD.ObjectBuffer := ObjNameBuf;
 | 
						|
 SD.ObjectBuffLen := ObjBufSize;
 | 
						|
 RC := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
 | 
						|
 if RC <> 0 then
 | 
						|
  begin
 | 
						|
   Move (QName [1], ObjNameBuf^, Length (QName));
 | 
						|
   OSErrorWatch (RC);
 | 
						|
  end
 | 
						|
 else
 | 
						|
  begin
 | 
						|
   RC := DosStartSession (SD, SID, PID);
 | 
						|
   if (RC = 0) or (RC = 457) then
 | 
						|
    begin
 | 
						|
     RC := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
 | 
						|
     if RC = 0 then
 | 
						|
      begin
 | 
						|
       Result := PCI^.Return;
 | 
						|
       RC := DosCloseQueue (HQ);
 | 
						|
       if RC <> 0 then
 | 
						|
        OSErrorWatch (RC);
 | 
						|
       RC := DosFreeMem (PCI);
 | 
						|
       if RC <> 0 then
 | 
						|
        OSErrorWatch (RC);
 | 
						|
       FreeMem (ObjNameBuf, ObjBufSize);
 | 
						|
      end
 | 
						|
     else
 | 
						|
      begin
 | 
						|
       OSErrorWatch (RC);
 | 
						|
       RC := DosCloseQueue (HQ);
 | 
						|
       OSErrorWatch (RC);
 | 
						|
      end;
 | 
						|
    end
 | 
						|
   else
 | 
						|
    begin
 | 
						|
     OSErrorWatch (RC);
 | 
						|
     RC := DosCloseQueue (HQ);
 | 
						|
     if RC <> 0 then
 | 
						|
      OSErrorWatch (RC);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
begin
 | 
						|
 Result := integer ($FFFFFFFF);
 | 
						|
 ObjName := '';
 | 
						|
 GetMem (ObjNameBuf, ObjBufSize);
 | 
						|
 FillChar (ObjNameBuf^, ObjBufSize, 0);
 | 
						|
 | 
						|
 RC := DosQueryAppType (PAnsiChar (Path), ExecAppType);
 | 
						|
 if RC <> 0 then
 | 
						|
  begin
 | 
						|
   OSErrorWatch (RC);
 | 
						|
   if (RC = 190) or (RC = 191) then
 | 
						|
    Result := StartSession;
 | 
						|
  end
 | 
						|
 else
 | 
						|
  begin
 | 
						|
   if (ApplicationType and 3 = ExecAppType and 3) then
 | 
						|
(* DosExecPgm should work... *)
 | 
						|
    begin
 | 
						|
     MaxArgsSize := Length (ComLine) + Length (Path) + 256; (* More than enough *)
 | 
						|
     if MaxArgsSize > high (word) then
 | 
						|
      Exit;
 | 
						|
     if ComLine = '' then
 | 
						|
      begin
 | 
						|
       Args0 := nil;
 | 
						|
       Args := nil;
 | 
						|
      end
 | 
						|
     else
 | 
						|
      begin
 | 
						|
       GetMem (Args0, MaxArgsSize);
 | 
						|
       Args := Args0;
 | 
						|
(* Work around a bug in OS/2 - argument to DosExecPgm *)
 | 
						|
(* should not cross 64K boundary. *)
 | 
						|
       while ((PtrUInt (Args) + MaxArgsSize) and $FFFF) < MaxArgsSize do
 | 
						|
        begin
 | 
						|
         MaxArgsSizeInc := MaxArgsSize -
 | 
						|
                                    ((PtrUInt (Args) + MaxArgsSize) and $FFFF);
 | 
						|
         Inc (MaxArgsSize, MaxArgsSizeInc);
 | 
						|
         if MaxArgsSize > high (word) then
 | 
						|
          Exit;
 | 
						|
         ReallocMem (Args0, MaxArgsSize);
 | 
						|
         Inc (pointer (Args), MaxArgsSizeInc);
 | 
						|
        end;
 | 
						|
       ArgSize := 0;
 | 
						|
       Move (Path [1], Args^ [ArgSize], Length (Path));
 | 
						|
       Inc (ArgSize, Length (Path));
 | 
						|
       Args^ [ArgSize] := 0;
 | 
						|
       Inc (ArgSize);
 | 
						|
       {Now do the real arguments.}
 | 
						|
       Move (ComLine [1], Args^ [ArgSize], Length (ComLine));
 | 
						|
       Inc (ArgSize, Length (ComLine));
 | 
						|
       Args^ [ArgSize] := 0;
 | 
						|
       Inc (ArgSize);
 | 
						|
       Args^ [ArgSize] := 0;
 | 
						|
      end;
 | 
						|
     Res.ExitCode := $FFFFFFFF;
 | 
						|
     RC := DosExecPgm (ObjNameBuf, ObjBufSize, 0, Args, nil, Res,
 | 
						|
                                                                 PAnsiChar (Path));
 | 
						|
     if RC <> 0 then
 | 
						|
      OSErrorWatch (RC);
 | 
						|
     if Args0 <> nil then
 | 
						|
      FreeMem (Args0, MaxArgsSize);
 | 
						|
     if RC = 0 then
 | 
						|
      begin
 | 
						|
       Result := Res.ExitCode;
 | 
						|
       FreeMem (ObjNameBuf, ObjBufSize);
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end;
 | 
						|
 if RC <> 0 then
 | 
						|
  begin
 | 
						|
   ObjName := StrPas (ObjNameBuf);
 | 
						|
   FreeMem (ObjNameBuf, ObjBufSize);
 | 
						|
   if ComLine = '' then
 | 
						|
    CommandLine := Path
 | 
						|
   else
 | 
						|
    CommandLine := Path + ' ' + ComLine;
 | 
						|
   if ObjName = '' then
 | 
						|
    E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, RC])
 | 
						|
   else
 | 
						|
    E := EOSError.CreateFmt (SExecuteProcessFailed + ' (' + ObjName + ')', [CommandLine, RC]);
 | 
						|
   E.ErrorCode := Result;
 | 
						|
   raise E;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function ExecuteProcess (const Path: RawByteString;
 | 
						|
        const ComLine: array of RawByteString;Flags:TExecuteFlags=[]): integer;
 | 
						|
 | 
						|
var
 | 
						|
  CommandLine: AnsiString;
 | 
						|
  I: integer;
 | 
						|
 | 
						|
begin
 | 
						|
  Commandline := '';
 | 
						|
  for I := 0 to High (ComLine) do
 | 
						|
   if Pos (' ', ComLine [I]) <> 0 then
 | 
						|
    CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
 | 
						|
   else
 | 
						|
    CommandLine := CommandLine + ' ' + Comline [I];
 | 
						|
  ExecuteProcess := ExecuteProcess (Path, CommandLine);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function GetTickCount: LongWord;
 | 
						|
var
 | 
						|
  L: cardinal;
 | 
						|
begin
 | 
						|
  DosQuerySysInfo (svMsCount, svMsCount, L, 4);
 | 
						|
  GetTickCount := L;
 | 
						|
end;
 | 
						|
 | 
						|
function GetTickCount64: QWord;
 | 
						|
var
 | 
						|
  Freq2: cardinal;
 | 
						|
  T: QWord;
 | 
						|
begin
 | 
						|
  DosTmrQueryFreq (Freq2);
 | 
						|
  DosTmrQueryTime (T);
 | 
						|
  GetTickCount64 := T div (QWord (Freq2) div 1000);
 | 
						|
{$NOTE GetTickCount64 takes 20 microseconds on 1GHz CPU, GetTickCount not measurable}
 | 
						|
end;
 | 
						|
 | 
						|
const
 | 
						|
  OrigOSErrorWatch: TOSErrorWatch = nil;
 | 
						|
 | 
						|
procedure TrackLastOSError (Error: cardinal);
 | 
						|
begin
 | 
						|
  LastOSError := Error;
 | 
						|
  OrigOSErrorWatch (Error);
 | 
						|
end;
 | 
						|
 | 
						|
function GetLastOSError: Integer;
 | 
						|
begin
 | 
						|
  GetLastOSError := Integer (LastOSError);
 | 
						|
end;
 | 
						|
 | 
						|
{****************************************************************************
 | 
						|
                              Initialization code
 | 
						|
****************************************************************************}
 | 
						|
 | 
						|
Initialization
 | 
						|
  InitExceptions;       { Initialize exceptions. OS independent }
 | 
						|
  InitInternational;    { Initialize internationalization settings }
 | 
						|
  OnBeep:=@SysBeep;
 | 
						|
  LastOSError := 0;
 | 
						|
  OrigOSErrorWatch := TOSErrorWatch (SetOSErrorTracking (@TrackLastOSError));
 | 
						|
  InitTZ;
 | 
						|
  InitTZ2;
 | 
						|
Finalization
 | 
						|
  FreeTerminateProcs;
 | 
						|
  DoneExceptions;
 | 
						|
end.
 |