sysutils.pp 20 KB

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