| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960 | {    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}{$hugecode on}{$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}{$DEFINE executeprocuni} (* Only 1 byte version of ExecuteProcess is provided by the OS *){ Include platform independent implementation part }{$i sysutils.inc}type  PFarChar=^AnsiChar;far;  PPFarChar=^PFarChar;var  dos_env_count:smallint;external name '__dos_env_count';{ This is implemented inside system unit }function envp:PPFarChar;external name '__fpc_envp';{****************************************************************************                              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: string);var  P: PAnsiChar;  Len: integer;begin  Len := Length(S) + 1;  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: THandle; Mode, Action: word): longint;var   Regs: registers;begin  result := 0;  Handle := UnusedHandle;//  StringToTB(FileName);  if LFNSupport then    begin      Regs.ax := $716c;                    { Use LFN Open/Create API }      Regs.dx := Action;                   { Action if file does/doesn't exist }      Regs.si := Ofs(PAnsiChar(FileName)^);      Regs.bx := $2000 + (Mode and $ff);   { File open mode }    end  else    begin      if (Action and $00f0) <> 0 then        Regs.ax := $3c00                   { Map to Create/Replace API }      else        Regs.ax := $3d00 + (Mode and $ff); { Map to Open_Existing API }      Regs.dx := Ofs(PAnsiChar(FileName)^);    end;  Regs.Ds := Seg(PAnsiChar(FileName)^);  Regs.cx := $20;                          { Attributes }  MsDos(Regs);  if (Regs.Flags and fCarry) <> 0 then    result := Regs.Ax  else    Handle := Regs.Ax;end;Function FileOpen (Const FileName : RawByteString; Mode : Integer) : THandle;var  e: integer;Begin  e := OpenFile(FileName, result, Mode, faOpen);  if e <> 0 then    result := unusedhandle;end;Function FileCreate (Const FileName : RawByteString) : THandle;var  e: integer;begin  e := OpenFile(FileName, result, ofReadWrite, faCreate or faOpenReplace);  if e <> 0 then    result := unusedhandle;end;Function FileCreate (Const FileName : RawByteString; ShareMode:integer; Rights : integer) : THandle;begin  FileCreate:=FileCreate(FileName);end;Function FileCreate (Const FileName : RawByteString; Rights:integer) : THandle;begin  FileCreate:=FileCreate(FileName);end;Function FileRead (Handle : THandle; Out Buffer; Count : longint) : Longint;var  regs     : registers;  size,  readsize : longint;begin  readsize:=0;  while Count > 0 do   begin     if Count>65535 then      size:=65535     else      size:=Count;     regs.cx:=size;     regs.dx:=Ofs(Buffer);     regs.ds:=Seg(Buffer);     regs.bx:=Handle;     regs.ax:=$3f00;     MsDos(regs);     if (regs.flags and fCarry) <> 0 then      begin        Result:=-1;        exit;      end;//     syscopyfromdos(Longint(dword(@Buffer)+readsize),lo(regs.realeax));     inc(readsize,regs.ax);     dec(Count,regs.ax);     { stop when not the specified size is read }     if regs.ax<size then      break;   end;  Result:=readsize;end;Function FileWrite (Handle : THandle; const Buffer; Count : Longint) : Longint;var  regs      : registers;  size,  writesize : longint;begin  writesize:=0;  while Count > 0 do   begin     if Count>65535 then      size:=65535     else      size:=Count;//     syscopytodos(Longint(dword(@Buffer)+writesize),size);     regs.cx:=size;     regs.dx:=Ofs(Buffer);     regs.ds:=Seg(Buffer);     regs.bx:=Handle;     regs.ax:=$4000;     MsDos(regs);     if (regs.flags and fCarry) <> 0 then      begin        Result:=-1;        exit;      end;     inc(writesize,regs.ax);     dec(Count,regs.ax);     { stop when not the specified size is written }     if regs.ax<size then      break;   end;  Result:=WriteSize;end;Function FileSeek (Handle : THandle; FOffset, Origin : Longint) : Longint;var  Regs: registers;begin  Regs.ax := $4200;  Regs.Al := Origin;  Regs.dx := Lo(FOffset);  Regs.cx := Hi(FOffset);  Regs.bx := Handle;  MsDos(Regs);  if Regs.Flags and fCarry <> 0 then     result := -1  else begin     LongRec(result).Lo := Regs.Ax;     LongRec(result).Hi := Regs.Dx;     end ;end;Function FileSeek (Handle : THandle; FOffset: Int64; Origin: {Integer}Longint) : Int64;begin  {$warning need to add 64bit call }  FileSeek:=FileSeek(Handle,Longint(FOffset),Longint(Origin));end;Procedure FileClose (Handle : THandle);var  Regs: registers;begin  if Handle<=4 then   exit;  Regs.ax := $3e00;  Regs.bx := Handle;  MsDos(Regs);end;Function FileTruncate (Handle: THandle; Size: Int64) : boolean;var  regs : registers;begin  if Size > high (longint) then   FileTruncate := false  else   begin    FileSeek(Handle,Size,0);    Regs.cx := 0;    Regs.dx := 0{tb_offset};    Regs.ds := 0{tb_segment};    Regs.bx := Handle;    Regs.ax:=$4000;    MsDos(Regs);    FileTruncate:=(regs.flags and fCarry)=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    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  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 := Sr;  {$IFDEF FPC_DOTTEDUNITS}TP.{$endif}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;   end ;end;Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;var  Sr: PSearchRec;begin  Sr := PSearchRec(Rslt.FindHandle);  if Sr <> nil then   begin     {$IFDEF FPC_DOTTEDUNITS}TP.{$endif}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;      end;   end;end;Procedure InternalFindClose(var Handle: Pointer);var  Sr: PSearchRec;begin  Sr := PSearchRec(Handle);  if Sr <> nil then    begin      //!! Dispose(Sr);      // This call is non dummy if LFNSupport is true PM      {$IFDEF FPC_DOTTEDUNITS}TP.{$endif}DOS.FindClose(SR^);      freemem(sr,sizeof(searchrec));    end;  Handle := nil;end;Function FileGetDate (Handle : THandle) : Int64;var  Regs: registers;begin  //!! for win95 an alternative function is available.  Regs.bx := Handle;  Regs.ax := $5700;  MsDos(Regs);  if Regs.Flags and fCarry <> 0 then   result := -1  else   result:=(Regs.dx shl 16) or Regs.cx;end;Function FileSetDate (Handle : THandle; Age : Int64) : Longint;var  Regs: registers;begin  Regs.bx := Handle;  Regs.ax := $5701;  Regs.cx := Lo(dword(Age));  Regs.dx := Hi(dword(Age));  MsDos(Regs);  if Regs.Flags and fCarry <> 0 then   result := -Regs.Ax  else   result := 0;end;Function FileGetAttr (Const FileName : RawByteString) : Longint;var  Regs: registers;begin  Regs.dx := Ofs(PAnsiChar(FileName)^);  Regs.Ds := Seg(PAnsiChar(FileName)^);  if LFNSupport then   begin     Regs.Ax := $7143;     Regs.Bx := 0;   end  else   Regs.Ax := $4300;  MsDos(Regs);  if Regs.Flags and fCarry <> 0 then    result := -1  else    result := Regs.Cx;end;Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;var  Regs: registers;begin  Regs.dx := Ofs(PAnsiChar(FileName)^);  Regs.Ds := Seg(PAnsiChar(FileName)^);  if LFNSupport then    begin      Regs.Ax := $7143;      Regs.Bx := 1;    end  else    Regs.Ax := $4301;  Regs.Cx := Attr;  MsDos(Regs);  if Regs.Flags and fCarry <> 0 then   result := -Regs.Ax  else   result := 0;end;Function DeleteFile (Const FileName : RawByteString) : Boolean;var  Regs: registers;begin  Regs.dx := Ofs(PAnsiChar(FileName)^);  Regs.Ds := Seg(PAnsiChar(FileName)^);  if LFNSupport then    Regs.ax := $7141  else    Regs.ax := $4100;  Regs.si := 0;  Regs.cx := 0;  MsDos(Regs);  result := (Regs.Flags and fCarry = 0);end;Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;var  Regs: registers;begin//  StringToTB(OldName + #0 + NewName);  Regs.dx := Ofs(PAnsiChar(OldName)^);  Regs.Ds := Seg(PAnsiChar(OldName)^);  Regs.di := Ofs(PAnsiChar(NewName)^);  Regs.Es := Seg(PAnsiChar(NewName)^);  if LFNSupport then    Regs.ax := $7156  else    Regs.ax := $5600;  Regs.cx := $ff;  MsDos(Regs);  result := (Regs.Flags and fCarry = 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;   regs.dx:=Ofs(S[1]);   regs.ds:=Seg(S[1]);   regs.di:=Ofs(Rec);   regs.es:=Seg(Rec);   regs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);   regs.ax:=$7303;   msdos(regs);   if (regs.flags and fcarry) = 0 then {No error clausule in int except cf}    begin     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;  MsDos(Regs);  SystemTime.Hour := Regs.Ch;  SystemTime.Minute := Regs.Cl;  SystemTime.Second := Regs.Dh;  SystemTime.MilliSecond := Regs.Dl*10;  Regs.ah := $2A;  MsDos(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}Seg(CountryInfo);  Regs.DI := {transfer_buffer and 15}Ofs(CountryInfo);  Regs.CX := SizeOf(TCountryInfo);  MsDos(Regs);{  DosMemGet(transfer_buffer div 16,            transfer_buffer and 15,            CountryInfo, Regs.CX );}end;procedure InitAnsi;type  PFarChar = ^AnsiChar; far;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);    for i := 128 to 255 do       begin       UpperCaseTable[i] := PFarChar(CountryInfo.UpperCaseTable)[i+(2-128)];       if UpperCaseTable[i] <> chr(i) 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****************************************************************************}{$if defined(FPC_MM_TINY) or defined(FPC_MM_SMALL) or defined(FPC_MM_MEDIUM)}{ environment handling for near data memory models }function far_strpas(p: pfarchar): string;begin  Result:='';  if p<>nil then    while p^<>#0 do      begin        Result:=Result+p^;        Inc(p);      end;end;Function small_FPCGetEnvVarFromP(EP : PPFarChar; EnvVar : String) : String;var  hp         : ppfarchar;  lenvvar,hs : string;  eqpos      : smallint;begin  lenvvar:=upcase(envvar);  hp:=EP;  Result:='';  If (hp<>Nil) then    while assigned(hp^) do     begin       hs:=far_strpas(hp^);       eqpos:=pos('=',hs);       if upcase(copy(hs,1,eqpos-1))=lenvvar then        begin          Result:=copy(hs,eqpos+1,length(hs)-eqpos);          exit;        end;       inc(hp);     end;end;Function small_FPCGetEnvStrFromP(EP : PPFarChar; Index : SmallInt) : String;begin  Result:='';  while assigned(EP^) and (Index>1) do    begin      dec(Index);      inc(EP);    end;  if Assigned(EP^) then    Result:=far_strpas(EP^);end;Function GetEnvironmentVariable(Const EnvVar : String) : String;begin  Result:=small_FPCGetEnvVarFromP(envp,EnvVar);end;Function GetEnvironmentVariableCount : Integer;begin  Result:=dos_env_count;end;Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};begin  Result:=small_FPCGetEnvStrFromP(Envp,Index);end;{$else}{ environment handling for far data memory models }Function GetEnvironmentVariable(Const EnvVar : String) : String;begin  Result:=FPCGetEnvVarFromP(envp,EnvVar);end;Function GetEnvironmentVariableCount : Integer;begin  Result:=dos_env_count;end;Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};begin  Result:=FPCGetEnvStrFromP(Envp,Index);end;{$endif}function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;var  e : EOSError;  CommandLine: RawByteString;begin  {$IFDEF FPC_DOTTEDUNITS}TP.{$endif}dos.exec_ansistring(path,comline);  if ({$IFDEF FPC_DOTTEDUNITS}TP.{$endif}Dos.DosError <> 0) then    begin      if ComLine <> '' then       CommandLine := Path + ' ' + ComLine      else       CommandLine := Path;      e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,{$IFDEF FPC_DOTTEDUNITS}TP.{$endif}Dos.DosError]);      e.ErrorCode:={$IFDEF FPC_DOTTEDUNITS}TP.{$endif}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;{*************************************************************************                                   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;  MsDos(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. *)    MsDos(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 }  OnBeep:=@SysBeep;  InitTZ;Finalization  FreeTerminateProcs;  DoneExceptions;end.
 |