sysutils.pp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for Go32v2
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. { force ansistrings }
  16. {$H+}
  17. uses
  18. go32,dos;
  19. {$DEFINE HAS_SLEEP}
  20. { Include platform independent interface part }
  21. {$i sysutilh.inc}
  22. implementation
  23. uses
  24. sysconst;
  25. { Include platform independent implementation part }
  26. {$i sysutils.inc}
  27. {****************************************************************************
  28. File Functions
  29. ****************************************************************************}
  30. { some internal constants }
  31. const
  32. ofRead = $0000; { Open for reading }
  33. ofWrite = $0001; { Open for writing }
  34. ofReadWrite = $0002; { Open for reading/writing }
  35. faFail = $0000; { Fail if file does not exist }
  36. faCreate = $0010; { Create if file does not exist }
  37. faOpen = $0001; { Open if file exists }
  38. faOpenReplace = $0002; { Clear if file exists }
  39. Type
  40. PSearchrec = ^Searchrec;
  41. { converts S to a pchar and copies it to the transfer-buffer. }
  42. procedure StringToTB(const S: string);
  43. var
  44. P: pchar;
  45. Len: integer;
  46. begin
  47. Len := Length(S) + 1;
  48. P := StrPCopy(StrAlloc(Len), S);
  49. SysCopyToDos(longint(P), Len);
  50. StrDispose(P);
  51. end ;
  52. { Native OpenFile function.
  53. if return value <> 0 call failed. }
  54. function OpenFile(const FileName: string; var Handle: longint; Mode, Action: word): longint;
  55. var
  56. Regs: registers;
  57. begin
  58. result := 0;
  59. Handle := UnusedHandle;
  60. StringToTB(FileName);
  61. if LFNSupport then
  62. begin
  63. Regs.Eax := $716c; { Use LFN Open/Create API }
  64. Regs.Edx := Action; { Action if file does/doesn't exist }
  65. Regs.Esi := tb_offset;
  66. Regs.Ebx := $2000 + (Mode and $ff); { File open mode }
  67. end
  68. else
  69. begin
  70. if (Action and $00f0) <> 0 then
  71. Regs.Eax := $3c00 { Map to Create/Replace API }
  72. else
  73. Regs.Eax := $3d00 + (Mode and $ff); { Map to Open_Existing API }
  74. Regs.Edx := tb_offset;
  75. end;
  76. Regs.Ds := tb_segment;
  77. Regs.Ecx := $20; { Attributes }
  78. RealIntr($21, Regs);
  79. if (Regs.Flags and CarryFlag) <> 0 then
  80. result := Regs.Ax
  81. else
  82. Handle := Regs.Ax;
  83. end;
  84. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  85. var
  86. e: integer;
  87. Begin
  88. e := OpenFile(FileName, result, Mode, faOpen);
  89. if e <> 0 then
  90. result := -1;
  91. end;
  92. Function FileCreate (Const FileName : String) : Longint;
  93. var
  94. e: integer;
  95. begin
  96. e := OpenFile(FileName, result, ofReadWrite, faCreate or faOpenReplace);
  97. if e <> 0 then
  98. result := -1;
  99. end;
  100. Function FileCreate (Const FileName : String; Mode:longint) : Longint;
  101. begin
  102. FileCreate:=FileCreate(FileName);
  103. end;
  104. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  105. var
  106. regs : registers;
  107. size,
  108. readsize : longint;
  109. begin
  110. readsize:=0;
  111. while Count > 0 do
  112. begin
  113. if Count>tb_size then
  114. size:=tb_size
  115. else
  116. size:=Count;
  117. regs.realecx:=size;
  118. regs.realedx:=tb_offset;
  119. regs.realds:=tb_segment;
  120. regs.realebx:=Handle;
  121. regs.realeax:=$3f00;
  122. RealIntr($21,regs);
  123. if (regs.realflags and carryflag) <> 0 then
  124. begin
  125. Result:=-1;
  126. exit;
  127. end;
  128. syscopyfromdos(Longint(@Buffer)+readsize,lo(regs.realeax));
  129. inc(readsize,lo(regs.realeax));
  130. dec(Count,lo(regs.realeax));
  131. { stop when not the specified size is read }
  132. if lo(regs.realeax)<size then
  133. break;
  134. end;
  135. Result:=readsize;
  136. end;
  137. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  138. var
  139. regs : registers;
  140. size,
  141. writesize : longint;
  142. begin
  143. writesize:=0;
  144. while Count > 0 do
  145. begin
  146. if Count>tb_size then
  147. size:=tb_size
  148. else
  149. size:=Count;
  150. syscopytodos(Longint(@Buffer)+writesize,size);
  151. regs.realecx:=size;
  152. regs.realedx:=tb_offset;
  153. regs.realds:=tb_segment;
  154. regs.realebx:=Handle;
  155. regs.realeax:=$4000;
  156. RealIntr($21,regs);
  157. if (regs.realflags and carryflag) <> 0 then
  158. begin
  159. Result:=-1;
  160. exit;
  161. end;
  162. inc(writesize,lo(regs.realeax));
  163. dec(Count,lo(regs.realeax));
  164. { stop when not the specified size is written }
  165. if lo(regs.realeax)<size then
  166. break;
  167. end;
  168. Result:=WriteSize;
  169. end;
  170. Function FileSeek (Handle, FOffset, Origin : Longint) : Longint;
  171. var
  172. Regs: registers;
  173. begin
  174. Regs.Eax := $4200;
  175. Regs.Al := Origin;
  176. Regs.Edx := Lo(FOffset);
  177. Regs.Ecx := Hi(FOffset);
  178. Regs.Ebx := Handle;
  179. RealIntr($21, Regs);
  180. if Regs.Flags and CarryFlag <> 0 then
  181. result := -1
  182. else begin
  183. LongRec(result).Lo := Regs.Ax;
  184. LongRec(result).Hi := Regs.Dx;
  185. end ;
  186. end;
  187. Function FileSeek (Handle : Longint; FOffset,Origin : Int64) : Int64;
  188. begin
  189. {$warning need to add 64bit call }
  190. FileSeek:=FileSeek(Handle,Longint(FOffset),Longint(Origin));
  191. end;
  192. Procedure FileClose (Handle : Longint);
  193. var
  194. Regs: registers;
  195. begin
  196. if Handle<=4 then
  197. exit;
  198. Regs.Eax := $3e00;
  199. Regs.Ebx := Handle;
  200. RealIntr($21, Regs);
  201. end;
  202. Function FileTruncate (Handle,Size: Longint) : boolean;
  203. var
  204. regs : trealregs;
  205. begin
  206. FileSeek(Handle,Size,0);
  207. Regs.realecx := 0;
  208. Regs.realedx := tb_offset;
  209. Regs.ds := tb_segment;
  210. Regs.ebx := Handle;
  211. Regs.eax:=$4000;
  212. RealIntr($21, Regs);
  213. FileTruncate:=(regs.realflags and carryflag)=0;
  214. end;
  215. Function FileAge (Const FileName : String): Longint;
  216. var Handle: longint;
  217. begin
  218. Handle := FileOpen(FileName, 0);
  219. if Handle <> -1 then
  220. begin
  221. result := FileGetDate(Handle);
  222. FileClose(Handle);
  223. end
  224. else
  225. result := -1;
  226. end;
  227. Function FileExists (Const FileName : String) : Boolean;
  228. Var
  229. Sr : Searchrec;
  230. begin
  231. DOS.FindFirst(FileName,$3f,sr);
  232. if DosError = 0 then
  233. begin
  234. { No volumeid,directory }
  235. Result:=(sr.attr and $18)=0;
  236. Dos.FindClose(sr);
  237. end
  238. else
  239. Result:=false;
  240. end;
  241. Function DirectoryExists (Const Directory : String) : Boolean;
  242. Var
  243. Sr : Searchrec;
  244. begin
  245. DOS.FindFirst(Directory,$3f,sr);
  246. if DosError = 0 then
  247. begin
  248. Result:=(sr.attr and $10)=$10;
  249. Dos.FindClose(sr);
  250. end
  251. else
  252. Result:=false;
  253. end;
  254. Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
  255. Var Sr : PSearchrec;
  256. begin
  257. //!! Sr := New(PSearchRec);
  258. getmem(sr,sizeof(searchrec));
  259. Rslt.FindHandle := longint(Sr);
  260. DOS.FindFirst(Path, Attr, Sr^);
  261. result := -DosError;
  262. if result = 0 then
  263. begin
  264. Rslt.Time := Sr^.Time;
  265. Rslt.Size := Sr^.Size;
  266. Rslt.Attr := Sr^.Attr;
  267. Rslt.ExcludeAttr := 0;
  268. Rslt.Name := Sr^.Name;
  269. end ;
  270. end;
  271. Function FindNext (Var Rslt : TSearchRec) : Longint;
  272. var
  273. Sr: PSearchRec;
  274. begin
  275. Sr := PSearchRec(Rslt.FindHandle);
  276. if Sr <> nil then
  277. begin
  278. DOS.FindNext(Sr^);
  279. result := -DosError;
  280. if result = 0 then
  281. begin
  282. Rslt.Time := Sr^.Time;
  283. Rslt.Size := Sr^.Size;
  284. Rslt.Attr := Sr^.Attr;
  285. Rslt.ExcludeAttr := 0;
  286. Rslt.Name := Sr^.Name;
  287. end;
  288. end;
  289. end;
  290. Procedure FindClose (Var F : TSearchrec);
  291. var
  292. Sr: PSearchRec;
  293. begin
  294. Sr := PSearchRec(F.FindHandle);
  295. if Sr <> nil then
  296. begin
  297. //!! Dispose(Sr);
  298. // This call is non dummy if LFNSupport is true PM
  299. DOS.FindClose(SR^);
  300. freemem(sr,sizeof(searchrec));
  301. end;
  302. F.FindHandle := 0;
  303. end;
  304. Function FileGetDate (Handle : Longint) : Longint;
  305. var
  306. Regs: registers;
  307. begin
  308. //!! for win95 an alternative function is available.
  309. Regs.Ebx := Handle;
  310. Regs.Eax := $5700;
  311. RealIntr($21, Regs);
  312. if Regs.Flags and CarryFlag <> 0 then
  313. result := -1
  314. else
  315. begin
  316. LongRec(result).Lo := Regs.cx;
  317. LongRec(result).Hi := Regs.dx;
  318. end ;
  319. end;
  320. Function FileSetDate (Handle, Age : Longint) : Longint;
  321. var
  322. Regs: registers;
  323. begin
  324. Regs.Ebx := Handle;
  325. Regs.Eax := $5701;
  326. Regs.Ecx := Lo(Age);
  327. Regs.Edx := Hi(Age);
  328. RealIntr($21, Regs);
  329. if Regs.Flags and CarryFlag <> 0 then
  330. result := -Regs.Ax
  331. else
  332. result := 0;
  333. end;
  334. Function FileGetAttr (Const FileName : String) : Longint;
  335. var
  336. Regs: registers;
  337. begin
  338. StringToTB(FileName);
  339. Regs.Edx := tb_offset;
  340. Regs.Ds := tb_segment;
  341. if LFNSupport then
  342. begin
  343. Regs.Ax := $7143;
  344. Regs.Bx := 0;
  345. end
  346. else
  347. Regs.Ax := $4300;
  348. RealIntr($21, Regs);
  349. if Regs.Flags and CarryFlag <> 0 then
  350. result := -1
  351. else
  352. result := Regs.Cx;
  353. end;
  354. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  355. var
  356. Regs: registers;
  357. begin
  358. StringToTB(FileName);
  359. Regs.Edx := tb_offset;
  360. Regs.Ds := tb_segment;
  361. if LFNSupport then
  362. begin
  363. Regs.Ax := $7143;
  364. Regs.Bx := 1;
  365. end
  366. else
  367. Regs.Ax := $4301;
  368. Regs.Cx := Attr;
  369. RealIntr($21, Regs);
  370. if Regs.Flags and CarryFlag <> 0 then
  371. result := -Regs.Ax
  372. else
  373. result := 0;
  374. end;
  375. Function DeleteFile (Const FileName : String) : Boolean;
  376. var
  377. Regs: registers;
  378. begin
  379. StringToTB(FileName);
  380. Regs.Edx := tb_offset;
  381. Regs.Ds := tb_segment;
  382. if LFNSupport then
  383. Regs.Eax := $7141
  384. else
  385. Regs.Eax := $4100;
  386. Regs.Esi := 0;
  387. Regs.Ecx := 0;
  388. RealIntr($21, Regs);
  389. result := (Regs.Flags and CarryFlag = 0);
  390. end;
  391. Function RenameFile (Const OldName, NewName : String) : Boolean;
  392. var
  393. Regs: registers;
  394. begin
  395. StringToTB(OldName + #0 + NewName);
  396. Regs.Edx := tb_offset;
  397. Regs.Ds := tb_segment;
  398. Regs.Edi := tb_offset + Length(OldName) + 1;
  399. Regs.Es := tb_segment;
  400. if LFNSupport then
  401. Regs.Eax := $7156
  402. else
  403. Regs.Eax := $5600;
  404. Regs.Ecx := $ff;
  405. RealIntr($21, Regs);
  406. result := (Regs.Flags and CarryFlag = 0);
  407. end;
  408. {****************************************************************************
  409. Disk Functions
  410. ****************************************************************************}
  411. TYPE ExtendedFat32FreeSpaceRec=packed Record
  412. RetSize : WORD; { (ret) size of returned structure}
  413. Strucversion : WORD; {(call) structure version (0000h)
  414. (ret) actual structure version (0000h)}
  415. SecPerClus, {number of sectors per cluster}
  416. BytePerSec, {number of bytes per sector}
  417. AvailClusters, {number of available clusters}
  418. TotalClusters, {total number of clusters on the drive}
  419. AvailPhysSect, {physical sectors available on the drive}
  420. TotalPhysSect, {total physical sectors on the drive}
  421. AvailAllocUnits, {Available allocation units}
  422. TotalAllocUnits : DWORD; {Total allocation units}
  423. Dummy,Dummy2 : DWORD; {8 bytes reserved}
  424. END;
  425. function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;
  426. VAR S : String;
  427. Rec : ExtendedFat32FreeSpaceRec;
  428. regs : registers;
  429. BEGIN
  430. if (swap(dosversion)>=$070A) AND LFNSupport then
  431. begin
  432. DosError:=0;
  433. S:='C:\'#0;
  434. if Drive=0 then
  435. begin
  436. GetDir(Drive,S);
  437. Setlength(S,4);
  438. S[4]:=#0;
  439. end
  440. else
  441. S[1]:=chr(Drive+64);
  442. Rec.Strucversion:=0;
  443. dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));
  444. dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);
  445. regs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;
  446. regs.ds:=tb_segment;
  447. regs.di:=tb_offset;
  448. regs.es:=tb_segment;
  449. regs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
  450. regs.ax:=$7303;
  451. msdos(regs);
  452. if regs.ax<>$ffff then
  453. begin
  454. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  455. if Free then
  456. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  457. else
  458. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  459. end
  460. else
  461. Do_DiskData:=-1;
  462. end
  463. else
  464. begin
  465. DosError:=0;
  466. regs.dl:=drive;
  467. regs.ah:=$36;
  468. msdos(regs);
  469. if regs.ax<>$FFFF then
  470. begin
  471. if Free then
  472. Do_DiskData:=int64(regs.ax)*regs.bx*regs.cx
  473. else
  474. Do_DiskData:=int64(regs.ax)*regs.cx*regs.dx;
  475. end
  476. else
  477. do_diskdata:=-1;
  478. end;
  479. end;
  480. function diskfree(drive : byte) : int64;
  481. begin
  482. diskfree:=Do_DiskData(drive,TRUE);
  483. end;
  484. function disksize(drive : byte) : int64;
  485. begin
  486. disksize:=Do_DiskData(drive,false);
  487. end;
  488. Function GetCurrentDir : String;
  489. begin
  490. GetDir(0, result);
  491. end;
  492. Function SetCurrentDir (Const NewDir : String) : Boolean;
  493. begin
  494. {$I-}
  495. ChDir(NewDir);
  496. {$I+}
  497. result := (IOResult = 0);
  498. end;
  499. Function CreateDir (Const NewDir : String) : Boolean;
  500. begin
  501. {$I-}
  502. MkDir(NewDir);
  503. {$I+}
  504. result := (IOResult = 0);
  505. end;
  506. Function RemoveDir (Const Dir : String) : Boolean;
  507. begin
  508. {$I-}
  509. RmDir(Dir);
  510. {$I+}
  511. result := (IOResult = 0);
  512. end;
  513. {****************************************************************************
  514. Time Functions
  515. ****************************************************************************}
  516. Procedure GetLocalTime(var SystemTime: TSystemTime);
  517. var
  518. Regs: Registers;
  519. begin
  520. Regs.ah := $2C;
  521. RealIntr($21, Regs);
  522. SystemTime.Hour := Regs.Ch;
  523. SystemTime.Minute := Regs.Cl;
  524. SystemTime.Second := Regs.Dh;
  525. SystemTime.MilliSecond := Regs.Dl*10;
  526. Regs.ah := $2A;
  527. RealIntr($21, Regs);
  528. SystemTime.Year := Regs.Cx;
  529. SystemTime.Month := Regs.Dh;
  530. SystemTime.Day := Regs.Dl;
  531. end ;
  532. {****************************************************************************
  533. Misc Functions
  534. ****************************************************************************}
  535. procedure Beep;
  536. begin
  537. end;
  538. {****************************************************************************
  539. Locale Functions
  540. ****************************************************************************}
  541. { Codepage constants }
  542. const
  543. CP_US = 437;
  544. CP_MultiLingual = 850;
  545. CP_SlavicLatin2 = 852;
  546. CP_Turkish = 857;
  547. CP_Portugal = 860;
  548. CP_IceLand = 861;
  549. CP_Canada = 863;
  550. CP_NorwayDenmark = 865;
  551. { CountryInfo }
  552. type
  553. TCountryInfo = packed record
  554. InfoId: byte;
  555. case integer of
  556. 1: ( Size: word;
  557. CountryId: word;
  558. CodePage: word;
  559. CountryInfo: array[0..33] of byte );
  560. 2: ( UpperCaseTable: longint );
  561. 4: ( FilenameUpperCaseTable: longint );
  562. 5: ( FilecharacterTable: longint );
  563. 6: ( CollatingTable: longint );
  564. 7: ( DBCSLeadByteTable: longint );
  565. end ;
  566. procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);
  567. Var Regs: Registers;
  568. begin
  569. Regs.AH := $65;
  570. Regs.AL := InfoId;
  571. Regs.BX := CodePage;
  572. Regs.DX := CountryId;
  573. Regs.ES := transfer_buffer div 16;
  574. Regs.DI := transfer_buffer and 15;
  575. Regs.CX := SizeOf(TCountryInfo);
  576. RealIntr($21, Regs);
  577. DosMemGet(transfer_buffer div 16,
  578. transfer_buffer and 15,
  579. CountryInfo, Regs.CX );
  580. end;
  581. procedure InitAnsi;
  582. var
  583. CountryInfo: TCountryInfo; i: integer;
  584. begin
  585. { Fill table entries 0 to 127 }
  586. for i := 0 to 96 do
  587. UpperCaseTable[i] := chr(i);
  588. for i := 97 to 122 do
  589. UpperCaseTable[i] := chr(i - 32);
  590. for i := 123 to 127 do
  591. UpperCaseTable[i] := chr(i);
  592. for i := 0 to 64 do
  593. LowerCaseTable[i] := chr(i);
  594. for i := 65 to 90 do
  595. LowerCaseTable[i] := chr(i + 32);
  596. for i := 91 to 255 do
  597. LowerCaseTable[i] := chr(i);
  598. { Get country and codepage info }
  599. GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);
  600. if CountryInfo.CodePage = 850 then
  601. begin
  602. { Special, known case }
  603. Move(CP850UCT, UpperCaseTable[128], 128);
  604. Move(CP850LCT, LowerCaseTable[128], 128);
  605. end
  606. else
  607. begin
  608. { this needs to be checked !!
  609. this is correct only if UpperCaseTable is
  610. and Offset:Segment word record (PM) }
  611. { get the uppercase table from dosmemory }
  612. GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);
  613. DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);
  614. for i := 128 to 255 do
  615. begin
  616. if UpperCaseTable[i] <> chr(i) then
  617. LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);
  618. end;
  619. end;
  620. end;
  621. Procedure InitInternational;
  622. begin
  623. InitInternationalGeneric;
  624. InitAnsi;
  625. end;
  626. function SysErrorMessage(ErrorCode: Integer): String;
  627. begin
  628. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  629. end;
  630. {****************************************************************************
  631. Os utils
  632. ****************************************************************************}
  633. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  634. begin
  635. Result:=FPCGetEnvVarFromP(envp,EnvVar);
  636. end;
  637. Function GetEnvironmentVariableCount : Integer;
  638. begin
  639. Result:=FPCCountEnvVar(EnvP);
  640. end;
  641. Function GetEnvironmentString(Index : Integer) : String;
  642. begin
  643. Result:=FPCGetEnvStrFromP(Envp,Index);
  644. end;
  645. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString):integer;
  646. var
  647. e : EOSError;
  648. CommandLine: AnsiString;
  649. begin
  650. dos.exec(path,comline);
  651. if (Dos.DosError <> 0) then
  652. begin
  653. if ComLine <> '' then
  654. CommandLine := Path + ' ' + ComLine
  655. else
  656. CommandLine := Path;
  657. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,Dos.DosError]);
  658. e.ErrorCode:=Dos.DosError;
  659. raise e;
  660. end;
  661. Result := DosExitCode;
  662. end;
  663. function ExecuteProcess (const Path: AnsiString;
  664. const ComLine: array of AnsiString): integer;
  665. var
  666. CommandLine: AnsiString;
  667. I: integer;
  668. begin
  669. Commandline := '';
  670. for I := 0 to High (ComLine) do
  671. if Pos (' ', ComLine [I]) <> 0 then
  672. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  673. else
  674. CommandLine := CommandLine + ' ' + Comline [I];
  675. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  676. end;
  677. {*************************************************************************
  678. Sleep
  679. *************************************************************************}
  680. procedure Sleep (MilliSeconds: Cardinal);
  681. var
  682. R: Registers;
  683. T0, T1, T2: int64;
  684. DayOver: boolean;
  685. begin
  686. (* Sleep is supposed to give up time slice - DOS Idle Interrupt chosen
  687. because it should be supported in all DOS versions. Not precise at all,
  688. though - the smallest step is 10 ms even in the best case. *)
  689. R.AH := $2C;
  690. RealIntr($21, R);
  691. T0 := R.CH * 3600000 + R.CL * 60000 + R.DH * 1000 + R.DL * 10;
  692. T2 := T0 + MilliSeconds;
  693. DayOver := T2 > (24 * 3600000);
  694. repeat
  695. Intr ($28, R);
  696. (* R.AH := $2C; - should be preserved. *)
  697. RealIntr($21, R);
  698. T1 := R.CH * 3600000 + R.CL * 60000 + R.DH * 1000 + R.DL * 10;
  699. if DayOver and (T1 < T0) then
  700. Inc (T1, 24 * 3600000);
  701. until T1 >= T2;
  702. end;
  703. {****************************************************************************
  704. Initialization code
  705. ****************************************************************************}
  706. Initialization
  707. InitExceptions; { Initialize exceptions. OS independent }
  708. InitInternational; { Initialize internationalization settings }
  709. Finalization
  710. DoneExceptions;
  711. end.