sysutils.pp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221
  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 EMX
  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. 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. System (imported) calls
  29. ****************************************************************************}
  30. (* "uses DosCalls" could not be used here due to type *)
  31. (* conflicts, so needed parts had to be redefined here). *)
  32. type
  33. TFileStatus = object
  34. end;
  35. PFileStatus = ^TFileStatus;
  36. TFileStatus3 = object (TFileStatus)
  37. DateCreation, {Date of file creation.}
  38. TimeCreation, {Time of file creation.}
  39. DateLastAccess, {Date of last access to file.}
  40. TimeLastAccess, {Time of last access to file.}
  41. DateLastWrite, {Date of last modification of file.}
  42. TimeLastWrite:word; {Time of last modification of file.}
  43. FileSize, {Size of file.}
  44. FileAlloc:cardinal; {Amount of space the file really
  45. occupies on disk.}
  46. AttrFile:cardinal; {Attributes of file.}
  47. end;
  48. PFileStatus3=^TFileStatus3;
  49. TFileStatus4=object(TFileStatus3)
  50. cbList:cardinal; {Length of entire EA set.}
  51. end;
  52. PFileStatus4=^TFileStatus4;
  53. TFileFindBuf3=object(TFileStatus)
  54. NextEntryOffset: cardinal; {Offset of next entry}
  55. DateCreation, {Date of file creation.}
  56. TimeCreation, {Time of file creation.}
  57. DateLastAccess, {Date of last access to file.}
  58. TimeLastAccess, {Time of last access to file.}
  59. DateLastWrite, {Date of last modification of file.}
  60. TimeLastWrite:word; {Time of last modification of file.}
  61. FileSize, {Size of file.}
  62. FileAlloc:cardinal; {Amount of space the file really
  63. occupies on disk.}
  64. AttrFile:cardinal; {Attributes of file.}
  65. Name:shortstring; {Also possible to use as ASCIIZ.
  66. The byte following the last string
  67. character is always zero.}
  68. end;
  69. PFileFindBuf3=^TFileFindBuf3;
  70. TFileFindBuf4=object(TFileStatus)
  71. NextEntryOffset: cardinal; {Offset of next entry}
  72. DateCreation, {Date of file creation.}
  73. TimeCreation, {Time of file creation.}
  74. DateLastAccess, {Date of last access to file.}
  75. TimeLastAccess, {Time of last access to file.}
  76. DateLastWrite, {Date of last modification of file.}
  77. TimeLastWrite:word; {Time of last modification of file.}
  78. FileSize, {Size of file.}
  79. FileAlloc:cardinal; {Amount of space the file really
  80. occupies on disk.}
  81. AttrFile:cardinal; {Attributes of file.}
  82. cbList:longint; {Size of the file's extended attributes.}
  83. Name:shortstring; {Also possible to use as ASCIIZ.
  84. The byte following the last string
  85. character is always zero.}
  86. end;
  87. PFileFindBuf4=^TFileFindBuf4;
  88. TFSInfo = record
  89. case word of
  90. 1:
  91. (File_Sys_ID,
  92. Sectors_Per_Cluster,
  93. Total_Clusters,
  94. Free_Clusters: cardinal;
  95. Bytes_Per_Sector: word);
  96. 2: {For date/time description,
  97. see file searching realted
  98. routines.}
  99. (Label_Date, {Date when volume label was created.}
  100. Label_Time: word; {Time when volume label was created.}
  101. VolumeLabel: ShortString); {Volume label. Can also be used
  102. as ASCIIZ, because the byte
  103. following the last character of
  104. the string is always zero.}
  105. end;
  106. PFSInfo = ^TFSInfo;
  107. TCountryCode=record
  108. Country, {Country to query info about (0=current).}
  109. CodePage: cardinal; {Code page to query info about (0=current).}
  110. end;
  111. PCountryCode=^TCountryCode;
  112. TTimeFmt = (Clock12, Clock24);
  113. TCountryInfo=record
  114. Country, CodePage: cardinal; {Country and codepage requested.}
  115. case byte of
  116. 0:
  117. (DateFormat: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  118. CurrencyUnit: array [0..4] of char;
  119. ThousandSeparator: char; {Thousands separator.}
  120. Zero1: byte; {Always zero.}
  121. DecimalSeparator: char; {Decimals separator,}
  122. Zero2: byte;
  123. DateSeparator: char; {Date separator.}
  124. Zero3: byte;
  125. TimeSeparator: char; {Time separator.}
  126. Zero4: byte;
  127. CurrencyFormat, {Bit field:
  128. Bit 0: 0=indicator before value
  129. 1=indicator after value
  130. Bit 1: 1=insert space after
  131. indicator.
  132. Bit 2: 1=Ignore bit 0&1, replace
  133. decimal separator with
  134. indicator.}
  135. DecimalPlace: byte; {Number of decimal places used in
  136. currency indication.}
  137. TimeFormat: TTimeFmt; {12/24 hour.}
  138. Reserve1: array [0..1] of word;
  139. DataSeparator: char; {Data list separator}
  140. Zero5: byte;
  141. Reserve2: array [0..4] of word);
  142. 1:
  143. (fsDateFmt: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  144. szCurrency: array [0..4] of char;
  145. {null terminated currency symbol}
  146. szThousandsSeparator: array [0..1] of char;
  147. {Thousands separator + #0}
  148. szDecimal: array [0..1] of char;
  149. {Decimals separator + #0}
  150. szDateSeparator: array [0..1] of char;
  151. {Date separator + #0}
  152. szTimeSeparator: array [0..1] of char;
  153. {Time separator + #0}
  154. fsCurrencyFmt, {Bit field:
  155. Bit 0: 0=indicator before value
  156. 1=indicator after value
  157. Bit 1: 1=insert space after
  158. indicator.
  159. Bit 2: 1=Ignore bit 0&1, replace
  160. decimal separator with
  161. indicator}
  162. cDecimalPlace: byte; {Number of decimal places used in
  163. currency indication}
  164. fsTimeFmt: byte; {0=12,1=24 hours}
  165. abReserved1: array [0..1] of word;
  166. szDataSeparator: array [0..1] of char;
  167. {Data list separator + #0}
  168. abReserved2: array [0..4] of word);
  169. end;
  170. PCountryInfo=^TCountryInfo;
  171. TRequestData=record
  172. PID, {ID of process that wrote element.}
  173. Data: cardinal; {Information from process writing the data.}
  174. end;
  175. PRequestData=^TRequestData;
  176. {Queue data structure for synchronously started sessions.}
  177. TChildInfo = record
  178. case boolean of
  179. false:
  180. (SessionID,
  181. Return: word); {Return code from the child process.}
  182. true:
  183. (usSessionID,
  184. usReturn: word); {Return code from the child process.}
  185. end;
  186. PChildInfo = ^TChildInfo;
  187. TStartData=record
  188. {Note: to omit some fields, use a length smaller than SizeOf(TStartData).}
  189. Length:word; {Length, in bytes, of datastructure
  190. (24/30/32/50/60).}
  191. Related:word; {Independent/child session (0/1).}
  192. FgBg:word; {Foreground/background (0/1).}
  193. TraceOpt:word; {No trace/trace this/trace all (0/1/2).}
  194. PgmTitle:PChar; {Program title.}
  195. PgmName:PChar; {Filename to program.}
  196. PgmInputs:PChar; {Command parameters (nil allowed).}
  197. TermQ:PChar; {System queue. (nil allowed).}
  198. Environment:PChar; {Environment to pass (nil allowed).}
  199. InheritOpt:word; {Inherit enviroment from shell/
  200. inherit environment from parent (0/1).}
  201. SessionType:word; {Auto/full screen/window/presentation
  202. manager/full screen Dos/windowed Dos
  203. (0/1/2/3/4/5/6/7).}
  204. Iconfile:PChar; {Icon file to use (nil allowed).}
  205. PgmHandle:cardinal; {0 or the program handle.}
  206. PgmControl:word; {Bitfield describing initial state
  207. of windowed sessions.}
  208. InitXPos,InitYPos:word; {Initial top coordinates.}
  209. InitXSize,InitYSize:word; {Initial size.}
  210. Reserved:word;
  211. ObjectBuffer:PChar; {If a module cannot be loaded, its
  212. name will be returned here.}
  213. ObjectBuffLen:cardinal; {Size of your buffer.}
  214. end;
  215. PStartData=^TStartData;
  216. const
  217. ilStandard = 1;
  218. ilQueryEAsize = 2;
  219. ilQueryEAs = 3;
  220. ilQueryFullName = 5;
  221. quFIFO = 0;
  222. quLIFO = 1;
  223. quPriority = 2;
  224. quNoConvert_Address = 0;
  225. quConvert_Address = 4;
  226. {Start the new session independent or as a child.}
  227. ssf_Related_Independent = 0; {Start new session independent
  228. of the calling session.}
  229. ssf_Related_Child = 1; {Start new session as a child
  230. session to the calling session.}
  231. {Start the new session in the foreground or in the background.}
  232. ssf_FgBg_Fore = 0; {Start new session in foreground.}
  233. ssf_FgBg_Back = 1; {Start new session in background.}
  234. {Should the program started in the new session
  235. be executed under conditions for tracing?}
  236. ssf_TraceOpt_None = 0; {No trace.}
  237. ssf_TraceOpt_Trace = 1; {Trace with no notification
  238. of descendants.}
  239. ssf_TraceOpt_TraceAll = 2; {Trace all descendant sessions.
  240. A termination queue must be
  241. supplied and Related must be
  242. ssf_Related_Child (=1).}
  243. {Will the new session inherit open file handles
  244. and environment from the calling process.}
  245. ssf_InhertOpt_Shell = 0; {Inherit from the shell.}
  246. ssf_InhertOpt_Parent = 1; {Inherit from the calling process.}
  247. {Specifies the type of session to start.}
  248. ssf_Type_Default = 0; {Use program's type.}
  249. ssf_Type_FullScreen = 1; {OS/2 full screen.}
  250. ssf_Type_WindowableVIO = 2; {OS/2 window.}
  251. ssf_Type_PM = 3; {Presentation Manager.}
  252. ssf_Type_VDM = 4; {DOS full screen.}
  253. ssf_Type_WindowedVDM = 7; {DOS window.}
  254. {Additional values for Windows programs}
  255. Prog_31_StdSeamlessVDM = 15; {Windows 3.1 program in its
  256. own windowed session.}
  257. Prog_31_StdSeamlessCommon = 16; {Windows 3.1 program in a
  258. common windowed session.}
  259. Prog_31_EnhSeamlessVDM = 17; {Windows 3.1 program in enhanced
  260. compatibility mode in its own
  261. windowed session.}
  262. Prog_31_EnhSeamlessCommon = 18; {Windows 3.1 program in enhanced
  263. compatibility mode in a common
  264. windowed session.}
  265. Prog_31_Enh = 19; {Windows 3.1 program in enhanced
  266. compatibility mode in a full
  267. screen session.}
  268. Prog_31_Std = 20; {Windows 3.1 program in a full
  269. screen session.}
  270. {Specifies the initial attributes for a OS/2 window or DOS window session.}
  271. ssf_Control_Visible = 0; {Window is visible.}
  272. ssf_Control_Invisible = 1; {Window is invisible.}
  273. ssf_Control_Maximize = 2; {Window is maximized.}
  274. ssf_Control_Minimize = 4; {Window is minimized.}
  275. ssf_Control_NoAutoClose = 8; {Window will not close after
  276. the program has ended.}
  277. ssf_Control_SetPos = 32768; {Use InitXPos, InitYPos,
  278. InitXSize, and InitYSize for
  279. the size and placement.}
  280. {This is the correct way to call external assembler procedures.}
  281. procedure syscall;external name '___SYSCALL';
  282. function DosSetFileInfo (Handle: THandle; InfoLevel: cardinal; AFileStatus: PFileStatus;
  283. FileStatusLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 218;
  284. function DosQueryFSInfo (DiskNum, InfoLevel: cardinal; var Buffer: TFSInfo;
  285. BufLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 278;
  286. function DosQueryFileInfo (Handle: THandle; InfoLevel: cardinal;
  287. AFileStatus: PFileStatus; FileStatusLen: cardinal): cardinal; cdecl;
  288. external 'DOSCALLS' index 279;
  289. function DosScanEnv (Name: PChar; var Value: PChar): cardinal; cdecl;
  290. external 'DOSCALLS' index 227;
  291. function DosFindFirst (FileMask: PChar; var Handle: THandle; Attrib: cardinal;
  292. AFileStatus: PFileStatus; FileStatusLen: cardinal;
  293. var Count: cardinal; InfoLevel: cardinal): cardinal; cdecl;
  294. external 'DOSCALLS' index 264;
  295. function DosFindNext (Handle: THandle; AFileStatus: PFileStatus;
  296. FileStatusLen: cardinal; var Count: cardinal): cardinal; cdecl;
  297. external 'DOSCALLS' index 265;
  298. function DosFindClose (Handle: THandle): cardinal; cdecl;
  299. external 'DOSCALLS' index 263;
  300. function DosQueryCtryInfo (Size: cardinal; var Country: TCountryCode;
  301. var Res: TCountryInfo; var ActualSize: cardinal): cardinal; cdecl;
  302. external 'NLS' index 5;
  303. function DosMapCase (Size: cardinal; var Country: TCountryCode;
  304. AString: PChar): cardinal; cdecl; external 'NLS' index 7;
  305. procedure DosSleep (MSec: cardinal); cdecl; external 'DOSCALLS' index 229;
  306. function DosCreateQueue (var Handle: THandle; Priority:longint;
  307. Name: PChar): cardinal; cdecl;
  308. external 'QUECALLS' index 16;
  309. function DosReadQueue (Handle: THandle; var ReqBuffer: TRequestData;
  310. var DataLen: cardinal; var DataPtr: pointer;
  311. Element, Wait: cardinal; var Priority: byte;
  312. ASem: THandle): cardinal; cdecl;
  313. external 'QUECALLS' index 9;
  314. function DosCloseQueue (Handle: THandle): cardinal; cdecl;
  315. external 'QUECALLS' index 11;
  316. function DosStartSession (var AStartData: TStartData;
  317. var SesID, PID: cardinal): cardinal; cdecl;
  318. external 'SESMGR' index 37;
  319. function DosFreeMem(P:pointer):cardinal; cdecl; external 'DOSCALLS' index 304;
  320. {****************************************************************************
  321. File Functions
  322. ****************************************************************************}
  323. const
  324. ofRead = $0000; {Open for reading}
  325. ofWrite = $0001; {Open for writing}
  326. ofReadWrite = $0002; {Open for reading/writing}
  327. doDenyRW = $0010; {DenyAll (no sharing)}
  328. faCreateNew = $00010000; {Create if file does not exist}
  329. faOpenReplace = $00040000; {Truncate if file exists}
  330. faCreate = $00050000; {Create if file does not exist, truncate otherwise}
  331. FindResvdMask = $00003737; {Allowed bits in attribute
  332. specification for DosFindFirst call.}
  333. {$ASMMODE INTEL}
  334. function FileOpen (const FileName: string; Mode: integer): longint; assembler;
  335. asm
  336. push ebx
  337. {$IFDEF REGCALL}
  338. mov ecx, edx
  339. mov edx, eax
  340. {$ELSE REGCALL}
  341. mov ecx, Mode
  342. mov edx, FileName
  343. {$ENDIF REGCALL}
  344. (* DenyAll if sharing not specified. *)
  345. test ecx, 112
  346. jnz @FOpen1
  347. or ecx, 16
  348. @FOpen1:
  349. mov eax, 7F2Bh
  350. call syscall
  351. pop ebx
  352. end {['eax', 'ebx', 'ecx', 'edx']};
  353. function FileCreate (const FileName: string): longint; assembler;
  354. asm
  355. push ebx
  356. {$IFDEF REGCALL}
  357. mov edx, eax
  358. {$ELSE REGCALL}
  359. mov edx, FileName
  360. {$ENDIF REGCALL}
  361. mov eax, 7F2Bh
  362. mov ecx, ofReadWrite or faCreate or doDenyRW (* Sharing to DenyAll *)
  363. call syscall
  364. pop ebx
  365. end {['eax', 'ebx', 'ecx', 'edx']};
  366. function FileCreate (const FileName: string; Mode: integer): longint;
  367. begin
  368. FileCreate:=FileCreate(FileName);
  369. end;
  370. function FileRead (Handle: longint; var Buffer; Count: longint): longint;
  371. assembler;
  372. asm
  373. push ebx
  374. {$IFDEF REGCALL}
  375. mov ebx, eax
  376. {$ELSE REGCALL}
  377. mov ebx, Handle
  378. mov ecx, Count
  379. mov edx, Buffer
  380. {$ENDIF REGCALL}
  381. mov eax, 3F00h
  382. call syscall
  383. jnc @FReadEnd
  384. mov eax, -1
  385. @FReadEnd:
  386. pop ebx
  387. end {['eax', 'ebx', 'ecx', 'edx']};
  388. function FileWrite (Handle: longint; const Buffer; Count: longint): longint;
  389. assembler;
  390. asm
  391. push ebx
  392. {$IFDEF REGCALL}
  393. mov ebx, eax
  394. {$ELSE REGCALL}
  395. mov ebx, Handle
  396. mov ecx, Count
  397. mov edx, Buffer
  398. {$ENDIF REGCALL}
  399. mov eax, 4000h
  400. call syscall
  401. jnc @FWriteEnd
  402. mov eax, -1
  403. @FWriteEnd:
  404. pop ebx
  405. end {['eax', 'ebx', 'ecx', 'edx']};
  406. function FileSeek (Handle, FOffset, Origin: longint): longint; assembler;
  407. asm
  408. push ebx
  409. {$IFDEF REGCALL}
  410. mov ebx, eax
  411. mov eax, ecx
  412. {$ELSE REGCALL}
  413. mov ebx, Handle
  414. mov eax, Origin
  415. mov edx, FOffset
  416. {$ENDIF REGCALL}
  417. mov ah, 42h
  418. call syscall
  419. jnc @FSeekEnd
  420. mov eax, -1
  421. @FSeekEnd:
  422. pop ebx
  423. end {['eax', 'ebx', 'edx']};
  424. function FileSeek (Handle: longint; FOffset, Origin: Int64): Int64;
  425. begin
  426. {$warning need to add 64bit call }
  427. Result:=FileSeek(Handle,Longint(Foffset),Longint(Origin));
  428. end;
  429. procedure FileClose (Handle: longint);
  430. begin
  431. if (Handle > 4) or ((os_mode = osOS2) and (Handle > 2)) then
  432. asm
  433. push ebx
  434. mov eax, 3E00h
  435. mov ebx, Handle
  436. call syscall
  437. pop ebx
  438. end ['eax'];
  439. end;
  440. function FileTruncate (Handle, Size: longint): boolean; assembler;
  441. asm
  442. push ebx
  443. {$IFDEF REGCALL}
  444. mov ebx, eax
  445. {$ELSE REGCALL}
  446. mov ebx, Handle
  447. mov edx, Size
  448. {$ENDIF REGCALL}
  449. mov eax, 7F25h
  450. push ebx
  451. call syscall
  452. pop ebx
  453. jc @FTruncEnd
  454. mov eax, 4202h
  455. mov edx, 0
  456. call syscall
  457. mov eax, 0
  458. jnc @FTruncEnd
  459. dec eax
  460. @FTruncEnd:
  461. pop ebx
  462. end {['eax', 'ebx', 'ecx', 'edx']};
  463. function FileAge (const FileName: string): longint;
  464. var Handle: longint;
  465. begin
  466. Handle := FileOpen (FileName, 0);
  467. if Handle <> -1 then
  468. begin
  469. Result := FileGetDate (Handle);
  470. FileClose (Handle);
  471. end
  472. else
  473. Result := -1;
  474. end;
  475. function FileExists (const FileName: string): boolean; assembler;
  476. asm
  477. {$IFDEF REGCALL}
  478. mov edx, eax
  479. {$ELSE REGCALL}
  480. mov edx, FileName
  481. {$ENDIF REGCALL}
  482. mov ax, 4300h
  483. call syscall
  484. mov eax, 0
  485. jc @FExistsEnd
  486. test cx, 18h
  487. jnz @FExistsEnd
  488. inc eax
  489. @FExistsEnd:
  490. end {['eax', 'ecx', 'edx']};
  491. type TRec = record
  492. T, D: word;
  493. end;
  494. PSearchRec = ^SearchRec;
  495. function FindFirst (const Path: string; Attr: longint; out Rslt: TSearchRec): longint;
  496. var SR: PSearchRec;
  497. FStat: PFileFindBuf3;
  498. Count: cardinal;
  499. Err: cardinal;
  500. begin
  501. if os_mode = osOS2 then
  502. begin
  503. New (FStat);
  504. Rslt.FindHandle := $FFFFFFFF;
  505. Count := 1;
  506. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  507. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count,
  508. ilStandard);
  509. if (Err = 0) and (Count = 0) then Err := 18;
  510. FindFirst := -Err;
  511. if Err = 0 then
  512. begin
  513. Rslt.Name := FStat^.Name;
  514. Rslt.Size := FStat^.FileSize;
  515. Rslt.Attr := FStat^.AttrFile;
  516. Rslt.ExcludeAttr := 0;
  517. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  518. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  519. end;
  520. Dispose (FStat);
  521. end
  522. else
  523. begin
  524. Err := DOS.DosError;
  525. GetMem (SR, SizeOf (SearchRec));
  526. Rslt.FindHandle := longint(SR);
  527. DOS.FindFirst (Path, Attr, SR^);
  528. FindFirst := -DOS.DosError;
  529. if DosError = 0 then
  530. begin
  531. Rslt.Time := SR^.Time;
  532. Rslt.Size := SR^.Size;
  533. Rslt.Attr := SR^.Attr;
  534. Rslt.ExcludeAttr := 0;
  535. Rslt.Name := SR^.Name;
  536. end;
  537. DOS.DosError := Err;
  538. end;
  539. end;
  540. function FindNext (var Rslt: TSearchRec): longint;
  541. var SR: PSearchRec;
  542. FStat: PFileFindBuf3;
  543. Count: cardinal;
  544. Err: cardinal;
  545. begin
  546. if os_mode = osOS2 then
  547. begin
  548. New (FStat);
  549. Count := 1;
  550. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^),
  551. Count);
  552. if (Err = 0) and (Count = 0) then Err := 18;
  553. FindNext := -Err;
  554. if Err = 0 then
  555. begin
  556. Rslt.Name := FStat^.Name;
  557. Rslt.Size := FStat^.FileSize;
  558. Rslt.Attr := FStat^.AttrFile;
  559. Rslt.ExcludeAttr := 0;
  560. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  561. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  562. end;
  563. Dispose (FStat);
  564. end
  565. else
  566. begin
  567. SR := PSearchRec (Rslt.FindHandle);
  568. if SR <> nil then
  569. begin
  570. DOS.FindNext (SR^);
  571. FindNext := -DosError;
  572. if DosError = 0 then
  573. begin
  574. Rslt.Time := SR^.Time;
  575. Rslt.Size := SR^.Size;
  576. Rslt.Attr := SR^.Attr;
  577. Rslt.ExcludeAttr := 0;
  578. Rslt.Name := SR^.Name;
  579. end;
  580. end;
  581. end;
  582. end;
  583. procedure FindClose (var F: TSearchrec);
  584. var SR: PSearchRec;
  585. begin
  586. if os_mode = osOS2 then
  587. begin
  588. DosFindClose (F.FindHandle);
  589. end
  590. else
  591. begin
  592. SR := PSearchRec (F.FindHandle);
  593. DOS.FindClose (SR^);
  594. FreeMem (SR, SizeOf (SearchRec));
  595. end;
  596. F.FindHandle := 0;
  597. end;
  598. function FileGetDate (Handle: longint): longint; assembler;
  599. asm
  600. push ebx
  601. {$IFDEF REGCALL}
  602. mov ebx, eax
  603. {$ELSE REGCALL}
  604. mov ebx, Handle
  605. {$ENDIF REGCALL}
  606. mov ax, 5700h
  607. call syscall
  608. mov eax, -1
  609. jc @FGetDateEnd
  610. mov ax, dx
  611. shld eax, ecx, 16
  612. @FGetDateEnd:
  613. pop ebx
  614. end {['eax', 'ebx', 'ecx', 'edx']};
  615. function FileSetDate (Handle, Age: longint): longint;
  616. var FStat: PFileStatus3;
  617. RC: cardinal;
  618. begin
  619. if os_mode = osOS2 then
  620. begin
  621. New (FStat);
  622. RC := DosQueryFileInfo (Handle, ilStandard, FStat,
  623. SizeOf (FStat^));
  624. if RC <> 0 then
  625. FileSetDate := -1
  626. else
  627. begin
  628. FStat^.DateLastAccess := Hi (Age);
  629. FStat^.DateLastWrite := Hi (Age);
  630. FStat^.TimeLastAccess := Lo (Age);
  631. FStat^.TimeLastWrite := Lo (Age);
  632. RC := DosSetFileInfo (Handle, ilStandard, FStat,
  633. SizeOf (FStat^));
  634. if RC <> 0 then
  635. FileSetDate := -1
  636. else
  637. FileSetDate := 0;
  638. end;
  639. Dispose (FStat);
  640. end
  641. else
  642. asm
  643. push ebx
  644. mov ax, 5701h
  645. mov ebx, Handle
  646. mov cx, word ptr [Age]
  647. mov dx, word ptr [Age + 2]
  648. call syscall
  649. jnc @FSetDateEnd
  650. mov eax, -1
  651. @FSetDateEnd:
  652. mov Result, eax
  653. pop ebx
  654. end ['eax', 'ecx', 'edx'];
  655. end;
  656. function FileGetAttr (const FileName: string): longint; assembler;
  657. asm
  658. {$IFDEF REGCALL}
  659. mov edx, eax
  660. {$ELSE REGCALL}
  661. mov edx, FileName
  662. {$ENDIF REGCALL}
  663. mov ax, 4300h
  664. call syscall
  665. jnc @FGetAttrEnd
  666. mov eax, -1
  667. @FGetAttrEnd:
  668. end {['eax', 'edx']};
  669. function FileSetAttr (const Filename: string; Attr: longint): longint; assembler;
  670. asm
  671. {$IFDEF REGCALL}
  672. mov ecx, edx
  673. mov edx, eax
  674. {$ELSE REGCALL}
  675. mov ecx, Attr
  676. mov edx, FileName
  677. {$ENDIF REGCALL}
  678. mov ax, 4301h
  679. call syscall
  680. mov eax, 0
  681. jnc @FSetAttrEnd
  682. mov eax, -1
  683. @FSetAttrEnd:
  684. end {['eax', 'ecx', 'edx']};
  685. function DeleteFile (const FileName: string): boolean; assembler;
  686. asm
  687. {$IFDEF REGCALL}
  688. mov edx, eax
  689. {$ELSE REGCALL}
  690. mov edx, FileName
  691. {$ENDIF REGCALL}
  692. mov ax, 4100h
  693. call syscall
  694. mov eax, 0
  695. jc @FDeleteEnd
  696. inc eax
  697. @FDeleteEnd:
  698. end {['eax', 'edx']};
  699. function RenameFile (const OldName, NewName: string): boolean; assembler;
  700. asm
  701. push edi
  702. {$IFDEF REGCALL}
  703. mov edx, eax
  704. mov edi, edx
  705. {$ELSE REGCALL}
  706. mov edx, OldName
  707. mov edi, NewName
  708. {$ENDIF REGCALL}
  709. mov ax, 5600h
  710. call syscall
  711. mov eax, 0
  712. jc @FRenameEnd
  713. inc eax
  714. @FRenameEnd:
  715. pop edi
  716. end {['eax', 'edx', 'edi']};
  717. {****************************************************************************
  718. Disk Functions
  719. ****************************************************************************}
  720. {$ASMMODE ATT}
  721. function DiskFree (Drive: byte): int64;
  722. var FI: TFSinfo;
  723. RC: cardinal;
  724. begin
  725. if (os_mode = osDOS) or (os_mode = osDPMI) then
  726. {Function 36 is not supported in OS/2.}
  727. asm
  728. pushl %ebx
  729. movb Drive,%dl
  730. movb $0x36,%ah
  731. call syscall
  732. cmpw $-1,%ax
  733. je .LDISKFREE1
  734. mulw %cx
  735. mulw %bx
  736. shll $16,%edx
  737. movw %ax,%dx
  738. movl $0,%eax
  739. xchgl %edx,%eax
  740. jmp .LDISKFREE2
  741. .LDISKFREE1:
  742. cltd
  743. .LDISKFREE2:
  744. popl %ebx
  745. leave
  746. ret
  747. end
  748. else
  749. {In OS/2, we use the filesystem information.}
  750. begin
  751. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  752. if RC = 0 then
  753. DiskFree := int64 (FI.Free_Clusters) *
  754. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  755. else
  756. DiskFree := -1;
  757. end;
  758. end;
  759. function DiskSize (Drive: byte): int64;
  760. var FI: TFSinfo;
  761. RC: cardinal;
  762. begin
  763. if (os_mode = osDOS) or (os_mode = osDPMI) then
  764. {Function 36 is not supported in OS/2.}
  765. asm
  766. pushl %ebx
  767. movb Drive,%dl
  768. movb $0x36,%ah
  769. call syscall
  770. movw %dx,%bx
  771. cmpw $-1,%ax
  772. je .LDISKSIZE1
  773. mulw %cx
  774. mulw %bx
  775. shll $16,%edx
  776. movw %ax,%dx
  777. movl $0,%eax
  778. xchgl %edx,%eax
  779. jmp .LDISKSIZE2
  780. .LDISKSIZE1:
  781. cltd
  782. .LDISKSIZE2:
  783. popl %ebx
  784. leave
  785. ret
  786. end
  787. else
  788. {In OS/2, we use the filesystem information.}
  789. begin
  790. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  791. if RC = 0 then
  792. DiskSize := int64 (FI.Total_Clusters) *
  793. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  794. else
  795. DiskSize := -1;
  796. end;
  797. end;
  798. function GetCurrentDir: string;
  799. begin
  800. GetDir (0, Result);
  801. end;
  802. function SetCurrentDir (const NewDir: string): boolean;
  803. begin
  804. {$I-}
  805. ChDir (NewDir);
  806. Result := (IOResult = 0);
  807. {$I+}
  808. end;
  809. function CreateDir (const NewDir: string): boolean;
  810. begin
  811. {$I-}
  812. MkDir (NewDir);
  813. Result := (IOResult = 0);
  814. {$I+}
  815. end;
  816. function RemoveDir (const Dir: string): boolean;
  817. begin
  818. {$I-}
  819. RmDir (Dir);
  820. Result := (IOResult = 0);
  821. {$I+}
  822. end;
  823. {$ASMMODE INTEL}
  824. function DirectoryExists (const Directory: string): boolean; assembler;
  825. asm
  826. {$IFDEF REGCALL}
  827. mov edx, eax
  828. {$ELSE REGCALL}
  829. mov edx, Directory
  830. {$ENDIF REGCALL}
  831. mov ax, 4300h
  832. call syscall
  833. mov eax, 0
  834. jc @FExistsEnd
  835. test cx, 10h
  836. jz @FExistsEnd
  837. inc eax
  838. @FExistsEnd:
  839. end {['eax', 'ecx', 'edx']};
  840. {****************************************************************************
  841. Time Functions
  842. ****************************************************************************}
  843. procedure GetLocalTime (var SystemTime: TSystemTime); assembler;
  844. asm
  845. (* Expects the default record alignment (word)!!! *)
  846. push edi
  847. {$IFDEF REGCALL}
  848. push eax
  849. {$ENDIF REGCALL}
  850. mov ah, 2Ah
  851. call syscall
  852. {$IFDEF REGCALL}
  853. pop eax
  854. {$ELSE REGCALL}
  855. mov edi, SystemTime
  856. {$ENDIF REGCALL}
  857. mov ax, cx
  858. stosw
  859. xor eax, eax
  860. mov al, 10
  861. mul dl
  862. shl eax, 16
  863. mov al, dh
  864. stosd
  865. push edi
  866. mov ah, 2Ch
  867. call syscall
  868. pop edi
  869. xor eax, eax
  870. mov al, cl
  871. shl eax, 16
  872. mov al, ch
  873. stosd
  874. mov al, dl
  875. shl eax, 16
  876. mov al, dh
  877. stosd
  878. pop edi
  879. end {['eax', 'ecx', 'edx', 'edi']};
  880. {$asmmode default}
  881. {****************************************************************************
  882. Misc Functions
  883. ****************************************************************************}
  884. procedure Beep;
  885. begin
  886. end;
  887. {****************************************************************************
  888. Locale Functions
  889. ****************************************************************************}
  890. procedure InitAnsi;
  891. var I: byte;
  892. Country: TCountryCode;
  893. begin
  894. for I := 0 to 255 do
  895. UpperCaseTable [I] := Chr (I);
  896. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  897. if os_mode = osOS2 then
  898. begin
  899. FillChar (Country, SizeOf (Country), 0);
  900. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  901. end
  902. else
  903. begin
  904. (* !!! TODO: DOS/DPMI mode support!!! *)
  905. end;
  906. for I := 0 to 255 do
  907. if UpperCaseTable [I] <> Chr (I) then
  908. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  909. end;
  910. procedure InitInternational;
  911. var Country: TCountryCode;
  912. CtryInfo: TCountryInfo;
  913. Size: cardinal;
  914. RC: cardinal;
  915. begin
  916. Size := 0;
  917. FillChar (Country, SizeOf (Country), 0);
  918. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  919. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  920. if RC = 0 then
  921. begin
  922. DateSeparator := CtryInfo.DateSeparator;
  923. case CtryInfo.DateFormat of
  924. 1: begin
  925. ShortDateFormat := 'd/m/y';
  926. LongDateFormat := 'dd" "mmmm" "yyyy';
  927. end;
  928. 2: begin
  929. ShortDateFormat := 'y/m/d';
  930. LongDateFormat := 'yyyy" "mmmm" "dd';
  931. end;
  932. 3: begin
  933. ShortDateFormat := 'm/d/y';
  934. LongDateFormat := 'mmmm" "dd" "yyyy';
  935. end;
  936. end;
  937. TimeSeparator := CtryInfo.TimeSeparator;
  938. DecimalSeparator := CtryInfo.DecimalSeparator;
  939. ThousandSeparator := CtryInfo.ThousandSeparator;
  940. CurrencyFormat := CtryInfo.CurrencyFormat;
  941. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  942. end;
  943. InitAnsi;
  944. InitInternationalGeneric;
  945. end;
  946. function SysErrorMessage(ErrorCode: Integer): String;
  947. begin
  948. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  949. end;
  950. {****************************************************************************
  951. OS Utils
  952. ****************************************************************************}
  953. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  954. begin
  955. GetEnvironmentVariable := StrPas (GetEnvPChar (EnvVar));
  956. end;
  957. Function GetEnvironmentVariableCount : Integer;
  958. begin
  959. (* Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
  960. GetEnvironmentVariableCount := EnvC;
  961. end;
  962. Function GetEnvironmentString(Index : Integer) : String;
  963. begin
  964. Result:=FPCGetEnvStrFromP (EnvP, Index);
  965. end;
  966. {$ASMMODE INTEL}
  967. procedure Sleep (Milliseconds: cardinal);
  968. begin
  969. if os_mode = osOS2 then DosSleep (Milliseconds) else
  970. asm
  971. mov edx, Milliseconds
  972. mov eax, 7F30h
  973. call syscall
  974. end ['eax', 'edx'];
  975. end;
  976. {$ASMMODE DEFAULT}
  977. function ExecuteProcess (const Path: AnsiString; const ComLine: AnsiString):
  978. integer;
  979. var
  980. HQ: THandle;
  981. SPID, STID, QName: shortstring;
  982. SD: TStartData;
  983. SID, PID: cardinal;
  984. RD: TRequestData;
  985. PCI: PChildInfo;
  986. CISize: cardinal;
  987. Prio: byte;
  988. E: EOSError;
  989. CommandLine: ansistring;
  990. begin
  991. if os_Mode = osOS2 then
  992. begin
  993. FillChar (SD, SizeOf (SD), 0);
  994. SD.Length := 24;
  995. SD.Related := ssf_Related_Child;
  996. SD.PgmName := PChar (Path);
  997. SD.PgmInputs := PChar (ComLine);
  998. Str (GetProcessID, SPID);
  999. Str (ThreadID, STID);
  1000. QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
  1001. SD.TermQ := @QName [1];
  1002. Result := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
  1003. if Result = 0 then
  1004. begin
  1005. Result := DosStartSession (SD, SID, PID);
  1006. if (Result = 0) or (Result = 457) then
  1007. begin
  1008. Result := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
  1009. if Result = 0 then
  1010. begin
  1011. Result := PCI^.Return;
  1012. DosCloseQueue (HQ);
  1013. DosFreeMem (PCI);
  1014. Exit;
  1015. end;
  1016. end;
  1017. DosCloseQueue (HQ);
  1018. end;
  1019. if ComLine = '' then
  1020. CommandLine := Path
  1021. else
  1022. CommandLine := Path + ' ' + ComLine;
  1023. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, Result]);
  1024. E.ErrorCode := Result;
  1025. raise E;
  1026. end else
  1027. begin
  1028. Dos.Exec (Path, ComLine);
  1029. if DosError <> 0 then
  1030. begin
  1031. if ComLine = '' then
  1032. CommandLine := Path
  1033. else
  1034. CommandLine := Path + ' ' + ComLine;
  1035. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, DosError]);
  1036. E.ErrorCode := DosError;
  1037. raise E;
  1038. end;
  1039. ExecuteProcess := DosExitCode;
  1040. end;
  1041. end;
  1042. function ExecuteProcess (const Path: AnsiString;
  1043. const ComLine: array of AnsiString): integer;
  1044. var
  1045. CommandLine: AnsiString;
  1046. I: integer;
  1047. begin
  1048. Commandline := '';
  1049. for I := 0 to High (ComLine) do
  1050. if Pos (' ', ComLine [I]) <> 0 then
  1051. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  1052. else
  1053. CommandLine := CommandLine + ' ' + Comline [I];
  1054. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  1055. end;
  1056. {****************************************************************************
  1057. Initialization code
  1058. ****************************************************************************}
  1059. Initialization
  1060. InitExceptions; { Initialize exceptions. OS independent }
  1061. InitInternational; { Initialize internationalization settings }
  1062. Finalization
  1063. DoneExceptions;
  1064. end.