sysutils.pp 21 KB

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