sysutils.pp 38 KB

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