| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950 | {    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 Go32v2    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. **********************************************************************}{$inline on}{$IFNDEF FPC_DOTTEDUNITS}unit sysutils;{$ENDIF FPC_DOTTEDUNITS}interface{$MODE objfpc}{$MODESWITCH OUT}{$IFDEF UNICODERTL}{$MODESWITCH UNICODESTRINGS}{$ELSE}{$H+}{$ENDIF}{$modeswitch typehelpers}{$modeswitch advancedrecords}{$IFDEF FPC_DOTTEDUNITS}uses  DOSApi.GO32,TP.DOS;{$ELSE FPC_DOTTEDUNITS}uses  go32,dos;{$ENDIF FPC_DOTTEDUNITS}{$DEFINE HAS_SLEEP}{ 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}{ Include platform independent interface part }{$i sysutilh.inc}implementation{$IFDEF FPC_DOTTEDUNITS}  uses    System.SysConst;{$ELSE FPC_DOTTEDUNITS}  uses    sysconst;{$ENDIF FPC_DOTTEDUNITS}{$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *){$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *){$DEFINE HAS_LOCALTIMEZONEOFFSET}{ Include platform independent implementation part }{$i sysutils.inc}{****************************************************************************                              File Functions****************************************************************************}{ some internal constants }const   ofRead        = $0000;    { Open for reading }   ofWrite       = $0001;    { Open for writing }   ofReadWrite   = $0002;    { Open for reading/writing }   faFail        = $0000;    { Fail if file does not exist }   faCreate      = $0010;    { Create if file does not exist }   faOpen        = $0001;    { Open if file exists }   faOpenReplace = $0002;    { Clear if file exists }Type  PSearchrec = ^Searchrec;{  converts S to a PAnsiChar and copies it to the transfer-buffer.   }procedure StringToTB(const S: rawbytestring);var  P: PAnsiChar;  Len: longint;begin  Len := Length(S) + 1;  if Len > tb_size then    Len := tb_size;  P := StrPCopy(StrAlloc(Len), S);  SysCopyToDos(longint(P), Len);  StrDispose(P);end ;{  Native OpenFile function.   if return value <> 0 call failed.  }function OpenFile(const FileName: rawbytestring; var Handle: longint; Mode, Action: word): longint;var   Regs: registers;begin  result := 0;  Handle := UnusedHandle;  StringToTB(FileName);  if LFNSupport then    begin      Regs.Eax := $716c;                    { Use LFN Open/Create API }      Regs.Edx := Action;                   { Action if file does/doesn't exist }      Regs.Esi := tb_offset;      Regs.Ebx := $2000 + (Mode and $ff);   { File open mode }    end  else    begin      if (Action and $00f0) <> 0 then        Regs.Eax := $3c00                   { Map to Create/Replace API }      else        Regs.Eax := $3d00 + (Mode and $ff); { Map to Open_Existing API }      Regs.Edx := tb_offset;    end;  Regs.Ds := tb_segment;  Regs.Ecx := $20;                          { Attributes }  RealIntr($21, Regs);  if (Regs.Flags and CarryFlag) <> 0 then    result := Regs.Ax  else    Handle := Regs.Ax;end;Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : Longint;var  SystemFileName: RawByteString;  e: integer;begin  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);  e := OpenFile(SystemFileName, result, Mode, faOpen);  if e <> 0 then    result := -1;end;Function FileCreate (Const FileName : RawByteString) : Longint;var  SystemFileName: RawByteString;  e: integer;begin  SystemFileName := ToSingleByteFileSystemEncodedFileName(FileName);  e := OpenFile(SystemFileName, result, ofReadWrite, faCreate or faOpenReplace);  if e <> 0 then    result := -1;end;Function FileCreate (Const FileName : RawByteString; ShareMode:longint; Rights : longint) : Longint;begin  FileCreate:=FileCreate(FileName);end;Function FileCreate (Const FileName : RawByteString; Rights:longint) : Longint;begin  FileCreate:=FileCreate(FileName);end;Function FileRead (Handle : Longint; Out Buffer; Count : longint) : Longint;var  regs     : registers;  size,  readsize : longint;begin  readsize:=0;  while Count > 0 do   begin     if Count>tb_size then      size:=tb_size     else      size:=Count;     regs.realecx:=size;     regs.realedx:=tb_offset;     regs.realds:=tb_segment;     regs.realebx:=Handle;     regs.realeax:=$3f00;     RealIntr($21,regs);     if (regs.realflags and carryflag) <> 0 then      begin        Result:=-1;        exit;      end;     syscopyfromdos(Longint(dword(@Buffer)+readsize),lo(regs.realeax));     inc(readsize,lo(regs.realeax));     dec(Count,lo(regs.realeax));     { stop when not the specified size is read }     if lo(regs.realeax)<size then      break;   end;  Result:=readsize;end;Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;var  regs      : registers;  size,  writesize : longint;begin  writesize:=0;  while Count > 0 do   begin     if Count>tb_size then      size:=tb_size     else      size:=Count;     syscopytodos(Longint(dword(@Buffer)+writesize),size);     regs.realecx:=size;     regs.realedx:=tb_offset;     regs.realds:=tb_segment;     regs.realebx:=Handle;     regs.realeax:=$4000;     RealIntr($21,regs);     if (regs.realflags and carryflag) <> 0 then      begin        Result:=-1;        exit;      end;     inc(writesize,lo(regs.realeax));     dec(Count,lo(regs.realeax));     { stop when not the specified size is written }     if lo(regs.realeax)<size then      break;   end;  Result:=WriteSize;end;Function FileSeek (Handle, FOffset, Origin : Longint) : Longint;var  Regs: registers;begin  Regs.Eax := $4200;  Regs.Al := Origin;  Regs.Edx := Lo(FOffset);  Regs.Ecx := Hi(FOffset);  Regs.Ebx := Handle;  RealIntr($21, Regs);  if Regs.Flags and CarryFlag <> 0 then     result := -1  else begin     LongRec(result).Lo := Regs.Ax;     LongRec(result).Hi := Regs.Dx;     end ;end;Function FileSeek (Handle : Longint; FOffset: Int64; Origin: Integer) : Int64;begin  {$warning need to add 64bit call }  FileSeek:=FileSeek(Handle,Longint(FOffset),Longint(Origin));end;Procedure FileClose (Handle : Longint);var  Regs: registers;begin  if Handle<=4 then   exit;  Regs.Eax := $3e00;  Regs.Ebx := Handle;  RealIntr($21, Regs);end;Function FileTruncate (Handle: THandle; Size: Int64) : boolean;var  regs : trealregs;begin  if Size > high (longint) then   FileTruncate := false  else   begin    FileSeek(Handle,Size,0);    Regs.realecx := 0;    Regs.realedx := tb_offset;    Regs.ds := tb_segment;    Regs.ebx := Handle;    Regs.eax:=$4000;    RealIntr($21, Regs);    FileTruncate:=(regs.realflags and carryflag)=0;   end;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  if FileName = '' then   Result := false  else   begin    { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }    L := FileGetAttr (FileName);    Result := (L >= 0) and (L and (faDirectory or faVolumeID) = 0);(* Neither VolumeIDs nor directories are files. *)   end;end;Function DirectoryExists (Const Directory : RawByteString; FollowLink : Boolean) : Boolean;Var  Dir : RawByteString;  drive : byte;  FADir, StoredIORes : longint;begin  { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }  Dir:=Directory;  if (length(dir)=2) and (dir[2]=':') and     ((dir[1] in ['A'..'Z']) or (dir[1] in ['a'..'z'])) then    begin      { We want to test GetCurDir }      if dir[1] in ['A'..'Z'] then        drive:=ord(dir[1])-ord('A')+1      else        drive:=ord(dir[1])-ord('a')+1;{$push}{$I-}      StoredIORes:=InOutRes;      InOutRes:=0;      GetDir(drive,dir);      if InOutRes <> 0 then        begin          InOutRes:=StoredIORes;          result:=false;          exit;        end;    end;{$pop}  if (Length (Dir) > 1) and    (Dir [Length (Dir)] in AllowDirectorySeparators) and(* Do not remove '\' after ':' (root directory of a drive)   or in '\\' (invalid path, possibly broken UNC path). *)     not (Dir [Length (Dir) - 1] in (AllowDriveSeparators + AllowDirectorySeparators)) then    dir:=copy(dir,1,length(dir)-1);(* FileGetAttr returns -1 on error *)  FADir := FileGetAttr (Dir);  Result := (FADir <> -1) and            ((FADir and faDirectory) = faDirectory);end;Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;Var Sr : PSearchrec;begin  //!! Sr := New(PSearchRec);  getmem(sr,sizeof(searchrec));  Rslt.FindHandle := longint(Sr);  { no use in converting to defaultfilesystemcodepage, since the Dos shortstring    interface is called here }  DOS.FindFirst(Path, Attr, Sr^);  result := -DosError;  if result = 0 then   begin     Rslt.Time := Sr^.Time;     Rslt.Size := Sr^.Size;     Rslt.Attr := Sr^.Attr;     Rslt.ExcludeAttr := 0;     Name := Sr^.Name;     SetCodePage(Name,DefaultFileSystemCodePage,False);   end ;end;Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;var  Sr: PSearchRec;begin  Sr := PSearchRec(Rslt.FindHandle);  if Sr <> nil then   begin     DOS.FindNext(Sr^);     result := -DosError;     if result = 0 then      begin        Rslt.Time := Sr^.Time;        Rslt.Size := Sr^.Size;        Rslt.Attr := Sr^.Attr;        Rslt.ExcludeAttr := 0;        Name := Sr^.Name;        SetCodePage(Name,DefaultFileSystemCodePage,False);      end;   end;end;Procedure InternalFindClose(var Handle: THandle);var  Sr: PSearchRec;begin  Sr := PSearchRec(Handle);  if Sr <> nil then    begin      //!! Dispose(Sr);      // This call is non dummy if LFNSupport is true PM      DOS.FindClose(SR^);      freemem(sr,sizeof(searchrec));    end;  Handle := 0;end;Function FileGetDate (Handle : Longint) : Int64;var  Regs: registers;begin  //!! for win95 an alternative function is available.  Regs.Ebx := Handle;  Regs.Eax := $5700;  RealIntr($21, Regs);  if Regs.Flags and CarryFlag <> 0 then   result := -1  else   result:=(Regs.dx shl 16) or Regs.cx;end;Function FileSetDate (Handle: longint; Age: Int64) : Longint;var  Regs: registers;begin  Regs.Ebx := Handle;  Regs.Eax := $5701;  Regs.Ecx := Lo(dword(Age));  Regs.Edx := Hi(dword(Age));  RealIntr($21, Regs);  if Regs.Flags and CarryFlag <> 0 then   result := -Regs.Ax  else   result := 0;end;Function FileGetAttr (Const FileName : RawByteString) : Longint;var  Regs: registers;  SystemFileName: RawByteString;begin  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);  StringToTB(SystemFileName);  Regs.Edx := tb_offset;  Regs.Ds := tb_segment;  if LFNSupport then   begin     Regs.Ax := $7143;     Regs.Bx := 0;   end  else   Regs.Ax := $4300;  RealIntr($21, Regs);  if Regs.Flags and CarryFlag <> 0 then    result := -1  else    result := Regs.Cx;end;Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;var  Regs: registers;  SystemFileName: RawByteString;begin  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);  StringToTB(SystemFileName);  Regs.Edx := tb_offset;  Regs.Ds := tb_segment;  if LFNSupport then    begin      Regs.Ax := $7143;      Regs.Bx := 1;    end  else    Regs.Ax := $4301;  Regs.Cx := Attr;  RealIntr($21, Regs);  if Regs.Flags and CarryFlag <> 0 then   result := -Regs.Ax  else   result := 0;end;Function DeleteFile (Const FileName : RawByteString) : Boolean;var  Regs: registers;  SystemFileName: RawByteString;begin  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);  StringToTB(SystemFileName);  Regs.Edx := tb_offset;  Regs.Ds := tb_segment;  if LFNSupport then    Regs.Eax := $7141  else    Regs.Eax := $4100;  Regs.Esi := 0;  Regs.Ecx := 0;  RealIntr($21, Regs);  result := (Regs.Flags and CarryFlag = 0);end;Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;var  Regs: registers;  OldSystemFileName, NewSystemFileName: RawByteString;Begin  OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);  NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);  StringToTB(OldSystemFileName + #0 + NewSystemFileName);  Regs.Edx := tb_offset;  Regs.Ds := tb_segment;  Regs.Edi := tb_offset + Length(OldSystemFileName) + 1;  Regs.Es := tb_segment;  if LFNSupport then    Regs.Eax := $7156  else    Regs.Eax := $5600;  Regs.Ecx := $ff;  RealIntr($21, Regs);  result := (Regs.Flags and CarryFlag = 0);end;{****************************************************************************                              Disk Functions****************************************************************************}TYPE  ExtendedFat32FreeSpaceRec=packed Record         RetSize           : WORD; { (ret) size of returned structure}         Strucversion      : WORD; {(call) structure version (0000h)                                    (ret) actual structure version (0000h)}         SecPerClus,               {number of sectors per cluster}         BytePerSec,               {number of bytes per sector}         AvailClusters,            {number of available clusters}         TotalClusters,            {total number of clusters on the drive}         AvailPhysSect,            {physical sectors available on the drive}         TotalPhysSect,            {total physical sectors on the drive}         AvailAllocUnits,          {Available allocation units}         TotalAllocUnits : DWORD;  {Total allocation units}         Dummy,Dummy2    : DWORD;  {8 bytes reserved}         END;function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;VAR S    : String;    Rec  : ExtendedFat32FreeSpaceRec;    regs : registers;  procedure OldDosDiskData;  begin   regs.dl:=drive;   regs.ah:=$36;   msdos(regs);   if regs.ax<>$FFFF then    begin     if Free then      Do_DiskData:=int64(regs.ax)*regs.bx*regs.cx     else      Do_DiskData:=int64(regs.ax)*regs.cx*regs.dx;    end   else    do_diskdata:=-1;  end;BEGIN if LFNSupport then  begin   S:='C:\'#0;   if Drive=0 then    begin     GetDir(Drive,S);     Setlength(S,4);     S[4]:=#0;    end   else    S[1]:=chr(Drive+64);   Rec.Strucversion:=0;   Rec.RetSize := 0;   dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));   dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);   regs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;   regs.ds:=tb_segment;   regs.di:=tb_offset;   regs.es:=tb_segment;   regs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);   regs.ax:=$7303;   msdos(regs);   if (regs.flags and fcarry) = 0 then {No error clausule in int except cf}    begin     copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));     if Rec.RetSize = 0 then (* Error - "FAT32" function not supported! *)      OldDosDiskData     else      if Free then       Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec      else       Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;    end   else    OldDosDiskData;  end else  OldDosDiskData;end;function diskfree(drive : byte) : int64;begin   diskfree:=Do_DiskData(drive,TRUE);end;function disksize(drive : byte) : int64;begin  disksize:=Do_DiskData(drive,false);end;{****************************************************************************                              Time Functions****************************************************************************}{$I tzenv.inc}Procedure GetLocalTime(var SystemTime: TSystemTime);var  Regs: Registers;begin  Regs.ah := $2C;  RealIntr($21, Regs);  SystemTime.Hour := Regs.Ch;  SystemTime.Minute := Regs.Cl;  SystemTime.Second := Regs.Dh;  SystemTime.MilliSecond := Regs.Dl*10;  Regs.ah := $2A;  RealIntr($21, Regs);  SystemTime.Year := Regs.Cx;  SystemTime.Month := Regs.Dh;  SystemTime.Day := Regs.Dl;  SystemTime.DayOfWeek := Regs.Al;end ;{****************************************************************************                              Misc Functions****************************************************************************}const  BeepChars: array [1..2] of AnsiChar = #7'$';procedure sysBeep;var  Regs: Registers;begin  Regs.dx := Ofs (BeepChars);  Regs.ah := 9;  MsDos (Regs);end;{****************************************************************************                              Locale Functions****************************************************************************}{  Codepage constants  }const   CP_US = 437;   CP_MultiLingual = 850;   CP_SlavicLatin2 = 852;   CP_Turkish = 857;   CP_Portugal = 860;   CP_IceLand = 861;   CP_Canada = 863;   CP_NorwayDenmark = 865;{  CountryInfo   }type   TCountryInfo = packed record      InfoId: byte;      case integer of         1: ( Size: word;              CountryId: word;              CodePage: word;              CountryInfo: array[0..33] of byte );         2: ( UpperCaseTable: longint );         4: ( FilenameUpperCaseTable: longint );         5: ( FilecharacterTable: longint );         6: ( CollatingTable: longint );         7: ( DBCSLeadByteTable: longint );   end ;procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);Var Regs: Registers;begin  Regs.AH := $65;  Regs.AL := InfoId;  Regs.BX := CodePage;  Regs.DX := CountryId;  Regs.ES := transfer_buffer div 16;  Regs.DI := transfer_buffer and 15;  Regs.CX := SizeOf(TCountryInfo);  RealIntr($21, Regs);  DosMemGet(transfer_buffer div 16,            transfer_buffer and 15,            CountryInfo, Regs.CX );end;procedure InitAnsi;var  CountryInfo: TCountryInfo; i: integer;begin  {  Fill table entries 0 to 127  }  for i := 0 to 96 do    UpperCaseTable[i] := chr(i);  for i := 97 to 122 do    UpperCaseTable[i] := chr(i - 32);  for i := 123 to 127 do    UpperCaseTable[i] := chr(i);  for i := 0 to 64 do    LowerCaseTable[i] := chr(i);  for i := 65 to 90 do    LowerCaseTable[i] := chr(i + 32);  for i := 91 to 255 do    LowerCaseTable[i] := chr(i);  {  Get country and codepage info  }  GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);  if CountryInfo.CodePage = 850 then    begin    { Special, known case }    Move(CP850UCT, UpperCaseTable[128], 128);    Move(CP850LCT, LowerCaseTable[128], 128);    end  else    begin    { this needs to be checked !!    this is correct only if UpperCaseTable is    and Offset:Segment word record (PM) }    {  get the uppercase table from dosmemory  }    GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);    DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);    for i := 128 to 255 do       begin       { Never modify the lowercase of any char if ord(char) < 127 }       if (UpperCaseTable[i] <> chr(i)) and (ord(UpperCaseTable[i])>=128) then          LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);       end;    end;end;Procedure InitInternational;begin  InitInternationalGeneric;  InitAnsi;end;function SysErrorMessage(ErrorCode: Integer): String;begin  Result:=Format(SUnknownErrorCode,[ErrorCode]);end;{****************************************************************************                              Os utils****************************************************************************}Function GetEnvironmentVariable(Const EnvVar : String) : String;begin  Result:=FPCGetEnvVarFromP(envp,EnvVar);end;Function GetEnvironmentVariableCount : Integer;begin  Result:=FPCCountEnvVar(EnvP);end;Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};begin  Result:=FPCGetEnvStrFromP(Envp,Index);end;function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;var  e : EOSError;  CommandLine: AnsiString;begin  dos.exec_ansistring(path,comline);  if (Dos.DosError <> 0) then    begin      if ComLine <> '' then       CommandLine := Path + ' ' + ComLine      else       CommandLine := Path;      e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,Dos.DosError]);      e.ErrorCode:=Dos.DosError;      raise e;    end;  Result := DosExitCode;end;function ExecuteProcess (const Path: RawByteString;                                  const ComLine: array of RawByteString;Flags:TExecuteFlags=[]): integer;var  CommandLine: RawByteString;  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 ExecuteProcess(Const Path: unicodeString; Const ComLine: unicodeString;Flags:TExecuteFlags=[]):integer;var  e : EOSError;  CommandLine: UnicodeString;begin  dos.exec_ansistring(path,comline);  if (Dos.DosError <> 0) then    begin      if ComLine <> '' then       CommandLine := Path + ' ' + ComLine      else       CommandLine := Path;      e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,Dos.DosError]);      e.ErrorCode:=Dos.DosError;      raise e;    end;  Result := DosExitCode;end;function ExecuteProcess (const Path: unicodeString;                                  const ComLine: array of unicodeString;Flags:TExecuteFlags=[]): integer;var  CommandLine: UnicodeString;  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;{*************************************************************************                                   Sleep*************************************************************************}procedure Sleep (MilliSeconds: Cardinal);var  R: Registers;  T0, T1, T2: int64;  DayOver: boolean;begin(* Sleep is supposed to give up time slice - DOS Idle Interrupt chosen   because it should be supported in all DOS versions. Not precise at all,   though - the smallest step is 10 ms even in the best case. *)  R.AH := $2C;  RealIntr($21, R);  T0 := R.CH * 3600000 + R.CL * 60000 + R.DH * 1000 + R.DL * 10;  T2 := T0 + MilliSeconds;  DayOver := T2 > (24 * 3600000);  repeat    Intr ($28, R);(*    R.AH := $2C; - should be preserved. *)    RealIntr($21, R);    T1 := R.CH * 3600000 + R.CL * 60000 + R.DH * 1000 + R.DL * 10;    if DayOver and (T1 < T0) then     Inc (T1, 24 * 3600000);  until T1 >= T2;end;{****************************************************************************                              Initialization code****************************************************************************}Initialization  InitExceptions;       { Initialize exceptions. OS independent }  InitInternational;    { Initialize internationalization settings }  InitTZ;  OnBeep:=@SysBeep;Finalization  FreeTerminateProcs;  DoneExceptions;end.
 |