sysutils.pp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  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 enviroment 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. (* DenyAll if sharing not specified. *)
  348. test ecx, 112
  349. jnz @FOpen1
  350. or ecx, 16
  351. @FOpen1:
  352. mov eax, 7F2Bh
  353. call syscall
  354. (* syscall __open() returns -1 in case of error, i.e. exactly what we need *)
  355. pop ebx
  356. end {['eax', 'ebx', 'ecx', 'edx']};
  357. function FileCreate (const FileName: string): longint; assembler;
  358. asm
  359. push ebx
  360. {$IFDEF REGCALL}
  361. mov edx, eax
  362. {$ELSE REGCALL}
  363. mov edx, FileName
  364. {$ENDIF REGCALL}
  365. mov eax, 7F2Bh
  366. mov ecx, ofReadWrite or faCreate or doDenyRW (* Sharing to DenyAll *)
  367. call syscall
  368. pop ebx
  369. end {['eax', 'ebx', 'ecx', 'edx']};
  370. function FileCreate (const FileName: string; Mode: integer): longint;
  371. begin
  372. FileCreate:=FileCreate(FileName);
  373. end;
  374. function FileRead (Handle: longint; Out Buffer; Count: longint): longint;
  375. assembler;
  376. asm
  377. push ebx
  378. {$IFDEF REGCALL}
  379. mov ebx, eax
  380. {$ELSE REGCALL}
  381. mov ebx, Handle
  382. mov ecx, Count
  383. mov edx, Buffer
  384. {$ENDIF REGCALL}
  385. mov eax, 3F00h
  386. call syscall
  387. jnc @FReadEnd
  388. mov eax, -1
  389. @FReadEnd:
  390. pop ebx
  391. end {['eax', 'ebx', 'ecx', 'edx']};
  392. function FileWrite (Handle: longint; const Buffer; Count: longint): longint;
  393. assembler;
  394. asm
  395. push ebx
  396. {$IFDEF REGCALL}
  397. mov ebx, eax
  398. {$ELSE REGCALL}
  399. mov ebx, Handle
  400. mov ecx, Count
  401. mov edx, Buffer
  402. {$ENDIF REGCALL}
  403. mov eax, 4000h
  404. call syscall
  405. jnc @FWriteEnd
  406. mov eax, -1
  407. @FWriteEnd:
  408. pop ebx
  409. end {['eax', 'ebx', 'ecx', 'edx']};
  410. function FileSeek (Handle, FOffset, Origin: longint): longint; assembler;
  411. asm
  412. push ebx
  413. {$IFDEF REGCALL}
  414. mov ebx, eax
  415. mov eax, ecx
  416. {$ELSE REGCALL}
  417. mov ebx, Handle
  418. mov eax, Origin
  419. mov edx, FOffset
  420. {$ENDIF REGCALL}
  421. mov ah, 42h
  422. call syscall
  423. jnc @FSeekEnd
  424. mov eax, -1
  425. @FSeekEnd:
  426. pop ebx
  427. end {['eax', 'ebx', 'edx']};
  428. function FileSeek (Handle: longint; FOffset: Int64; Origin: longint): Int64;
  429. begin
  430. {$warning need to add 64bit call }
  431. Result:=FileSeek(Handle,Longint(Foffset),Longint(Origin));
  432. end;
  433. procedure FileClose (Handle: longint);
  434. begin
  435. if (Handle > 4) or ((os_mode = osOS2) and (Handle > 2)) then
  436. asm
  437. push ebx
  438. mov eax, 3E00h
  439. mov ebx, Handle
  440. call syscall
  441. pop ebx
  442. end ['eax'];
  443. end;
  444. function FileTruncate (Handle: THandle; Size: Int64): boolean; assembler;
  445. asm
  446. push ebx
  447. {$IFDEF REGCALL}
  448. mov ebx, eax
  449. {$ELSE REGCALL}
  450. mov ebx, Handle
  451. {$ENDIF REGCALL}
  452. mov edx, dword ptr Size
  453. mov eax, dword ptr Size+4
  454. or eax, eax
  455. mov eax, 0
  456. jz @FTruncEnd (* file sizes > 4 GB not supported with EMX *)
  457. mov eax, 7F25h
  458. push ebx
  459. call syscall
  460. pop ebx
  461. jc @FTruncEnd
  462. mov eax, 4202h
  463. mov edx, 0
  464. call syscall
  465. mov eax, 0
  466. jnc @FTruncEnd
  467. dec eax
  468. @FTruncEnd:
  469. pop ebx
  470. end {['eax', 'ebx', 'ecx', 'edx']};
  471. function FileAge (const FileName: string): longint;
  472. var Handle: longint;
  473. begin
  474. Handle := FileOpen (FileName, 0);
  475. if Handle <> -1 then
  476. begin
  477. Result := FileGetDate (Handle);
  478. FileClose (Handle);
  479. end
  480. else
  481. Result := -1;
  482. end;
  483. function FileExists (const FileName: string): boolean; assembler;
  484. asm
  485. {$IFDEF REGCALL}
  486. mov edx, eax
  487. {$ELSE REGCALL}
  488. mov edx, FileName
  489. {$ENDIF REGCALL}
  490. mov ax, 4300h
  491. call syscall
  492. mov eax, 0
  493. jc @FExistsEnd
  494. test cx, 18h
  495. jnz @FExistsEnd
  496. inc eax
  497. @FExistsEnd:
  498. end {['eax', 'ecx', 'edx']};
  499. type TRec = record
  500. T, D: word;
  501. end;
  502. PSearchRec = ^SearchRec;
  503. function FindFirst (const Path: string; Attr: longint; out Rslt: TSearchRec): longint;
  504. var SR: PSearchRec;
  505. FStat: PFileFindBuf3;
  506. Count: cardinal;
  507. Err: cardinal;
  508. begin
  509. if os_mode = osOS2 then
  510. begin
  511. New (FStat);
  512. Rslt.FindHandle := THandle ($FFFFFFFF);
  513. Count := 1;
  514. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  515. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count,
  516. ilStandard);
  517. if (Err = 0) and (Count = 0) then Err := 18;
  518. FindFirst := -Err;
  519. if Err = 0 then
  520. begin
  521. Rslt.Name := FStat^.Name;
  522. Rslt.Size := FStat^.FileSize;
  523. Rslt.Attr := FStat^.AttrFile;
  524. Rslt.ExcludeAttr := 0;
  525. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  526. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  527. end;
  528. Dispose (FStat);
  529. end
  530. else
  531. begin
  532. Err := DOS.DosError;
  533. GetMem (SR, SizeOf (SearchRec));
  534. Rslt.FindHandle := longint(SR);
  535. DOS.FindFirst (Path, Attr, SR^);
  536. FindFirst := -DOS.DosError;
  537. if DosError = 0 then
  538. begin
  539. Rslt.Time := SR^.Time;
  540. Rslt.Size := SR^.Size;
  541. Rslt.Attr := SR^.Attr;
  542. Rslt.ExcludeAttr := 0;
  543. Rslt.Name := SR^.Name;
  544. end;
  545. DOS.DosError := Err;
  546. end;
  547. end;
  548. function FindNext (var Rslt: TSearchRec): longint;
  549. var SR: PSearchRec;
  550. FStat: PFileFindBuf3;
  551. Count: cardinal;
  552. Err: cardinal;
  553. begin
  554. if os_mode = osOS2 then
  555. begin
  556. New (FStat);
  557. Count := 1;
  558. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^),
  559. Count);
  560. if (Err = 0) and (Count = 0) then Err := 18;
  561. FindNext := -Err;
  562. if Err = 0 then
  563. begin
  564. Rslt.Name := FStat^.Name;
  565. Rslt.Size := FStat^.FileSize;
  566. Rslt.Attr := FStat^.AttrFile;
  567. Rslt.ExcludeAttr := 0;
  568. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  569. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  570. end;
  571. Dispose (FStat);
  572. end
  573. else
  574. begin
  575. SR := PSearchRec (Rslt.FindHandle);
  576. if SR <> nil then
  577. begin
  578. DOS.FindNext (SR^);
  579. FindNext := -DosError;
  580. if DosError = 0 then
  581. begin
  582. Rslt.Time := SR^.Time;
  583. Rslt.Size := SR^.Size;
  584. Rslt.Attr := SR^.Attr;
  585. Rslt.ExcludeAttr := 0;
  586. Rslt.Name := SR^.Name;
  587. end;
  588. end;
  589. end;
  590. end;
  591. procedure FindClose (var F: TSearchrec);
  592. var SR: PSearchRec;
  593. begin
  594. if os_mode = osOS2 then
  595. begin
  596. DosFindClose (F.FindHandle);
  597. end
  598. else
  599. begin
  600. SR := PSearchRec (F.FindHandle);
  601. DOS.FindClose (SR^);
  602. FreeMem (SR, SizeOf (SearchRec));
  603. end;
  604. F.FindHandle := 0;
  605. end;
  606. function FileGetDate (Handle: longint): longint; assembler;
  607. asm
  608. push ebx
  609. {$IFDEF REGCALL}
  610. mov ebx, eax
  611. {$ELSE REGCALL}
  612. mov ebx, Handle
  613. {$ENDIF REGCALL}
  614. mov ax, 5700h
  615. call syscall
  616. mov eax, -1
  617. jc @FGetDateEnd
  618. mov ax, dx
  619. shld eax, ecx, 16
  620. @FGetDateEnd:
  621. pop ebx
  622. end {['eax', 'ebx', 'ecx', 'edx']};
  623. function FileSetDate (Handle, Age: longint): longint;
  624. var FStat: PFileStatus3;
  625. RC: cardinal;
  626. begin
  627. if os_mode = osOS2 then
  628. begin
  629. New (FStat);
  630. RC := DosQueryFileInfo (Handle, ilStandard, FStat,
  631. SizeOf (FStat^));
  632. if RC <> 0 then
  633. FileSetDate := -1
  634. else
  635. begin
  636. FStat^.DateLastAccess := Hi (Age);
  637. FStat^.DateLastWrite := Hi (Age);
  638. FStat^.TimeLastAccess := Lo (Age);
  639. FStat^.TimeLastWrite := Lo (Age);
  640. RC := DosSetFileInfo (Handle, ilStandard, FStat,
  641. SizeOf (FStat^));
  642. if RC <> 0 then
  643. FileSetDate := -1
  644. else
  645. FileSetDate := 0;
  646. end;
  647. Dispose (FStat);
  648. end
  649. else
  650. asm
  651. push ebx
  652. mov ax, 5701h
  653. mov ebx, Handle
  654. mov cx, word ptr [Age]
  655. mov dx, word ptr [Age + 2]
  656. call syscall
  657. jnc @FSetDateEnd
  658. mov eax, -1
  659. @FSetDateEnd:
  660. mov Result, eax
  661. pop ebx
  662. end ['eax', 'ecx', 'edx'];
  663. end;
  664. function FileGetAttr (const FileName: string): longint; assembler;
  665. asm
  666. {$IFDEF REGCALL}
  667. mov edx, eax
  668. {$ELSE REGCALL}
  669. mov edx, FileName
  670. {$ENDIF REGCALL}
  671. mov ax, 4300h
  672. call syscall
  673. jnc @FGetAttrEnd
  674. mov eax, -1
  675. @FGetAttrEnd:
  676. end {['eax', 'edx']};
  677. function FileSetAttr (const Filename: string; Attr: longint): longint; assembler;
  678. asm
  679. {$IFDEF REGCALL}
  680. mov ecx, edx
  681. mov edx, eax
  682. {$ELSE REGCALL}
  683. mov ecx, Attr
  684. mov edx, FileName
  685. {$ENDIF REGCALL}
  686. mov ax, 4301h
  687. call syscall
  688. mov eax, 0
  689. jnc @FSetAttrEnd
  690. mov eax, -1
  691. @FSetAttrEnd:
  692. end {['eax', 'ecx', 'edx']};
  693. function DeleteFile (const FileName: string): boolean; assembler;
  694. asm
  695. {$IFDEF REGCALL}
  696. mov edx, eax
  697. {$ELSE REGCALL}
  698. mov edx, FileName
  699. {$ENDIF REGCALL}
  700. mov ax, 4100h
  701. call syscall
  702. mov eax, 0
  703. jc @FDeleteEnd
  704. inc eax
  705. @FDeleteEnd:
  706. end {['eax', 'edx']};
  707. function RenameFile (const OldName, NewName: string): boolean; assembler;
  708. asm
  709. push edi
  710. {$IFDEF REGCALL}
  711. mov edx, eax
  712. mov edi, edx
  713. {$ELSE REGCALL}
  714. mov edx, OldName
  715. mov edi, NewName
  716. {$ENDIF REGCALL}
  717. mov ax, 5600h
  718. call syscall
  719. mov eax, 0
  720. jc @FRenameEnd
  721. inc eax
  722. @FRenameEnd:
  723. pop edi
  724. end {['eax', 'edx', 'edi']};
  725. {****************************************************************************
  726. Disk Functions
  727. ****************************************************************************}
  728. {$ASMMODE ATT}
  729. function DiskFree (Drive: byte): int64;
  730. var FI: TFSinfo;
  731. RC: cardinal;
  732. begin
  733. if (os_mode = osDOS) or (os_mode = osDPMI) then
  734. {Function 36 is not supported in OS/2.}
  735. asm
  736. pushl %ebx
  737. movb Drive,%dl
  738. movb $0x36,%ah
  739. call syscall
  740. cmpw $-1,%ax
  741. je .LDISKFREE1
  742. mulw %cx
  743. mulw %bx
  744. shll $16,%edx
  745. movw %ax,%dx
  746. movl $0,%eax
  747. xchgl %edx,%eax
  748. jmp .LDISKFREE2
  749. .LDISKFREE1:
  750. cltd
  751. .LDISKFREE2:
  752. popl %ebx
  753. leave
  754. ret
  755. end
  756. else
  757. {In OS/2, we use the filesystem information.}
  758. begin
  759. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  760. if RC = 0 then
  761. DiskFree := int64 (FI.Free_Clusters) *
  762. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  763. else
  764. DiskFree := -1;
  765. end;
  766. end;
  767. function DiskSize (Drive: byte): int64;
  768. var FI: TFSinfo;
  769. RC: cardinal;
  770. begin
  771. if (os_mode = osDOS) or (os_mode = osDPMI) then
  772. {Function 36 is not supported in OS/2.}
  773. asm
  774. pushl %ebx
  775. movb Drive,%dl
  776. movb $0x36,%ah
  777. call syscall
  778. movw %dx,%bx
  779. cmpw $-1,%ax
  780. je .LDISKSIZE1
  781. mulw %cx
  782. mulw %bx
  783. shll $16,%edx
  784. movw %ax,%dx
  785. movl $0,%eax
  786. xchgl %edx,%eax
  787. jmp .LDISKSIZE2
  788. .LDISKSIZE1:
  789. cltd
  790. .LDISKSIZE2:
  791. popl %ebx
  792. leave
  793. ret
  794. end
  795. else
  796. {In OS/2, we use the filesystem information.}
  797. begin
  798. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  799. if RC = 0 then
  800. DiskSize := int64 (FI.Total_Clusters) *
  801. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  802. else
  803. DiskSize := -1;
  804. end;
  805. end;
  806. function GetCurrentDir: string;
  807. begin
  808. GetDir (0, Result);
  809. end;
  810. function SetCurrentDir (const NewDir: string): boolean;
  811. begin
  812. {$I-}
  813. ChDir (NewDir);
  814. Result := (IOResult = 0);
  815. {$I+}
  816. end;
  817. function CreateDir (const NewDir: string): boolean;
  818. begin
  819. {$I-}
  820. MkDir (NewDir);
  821. Result := (IOResult = 0);
  822. {$I+}
  823. end;
  824. function RemoveDir (const Dir: string): boolean;
  825. begin
  826. {$I-}
  827. RmDir (Dir);
  828. Result := (IOResult = 0);
  829. {$I+}
  830. end;
  831. {$ASMMODE INTEL}
  832. function DirectoryExists (const Directory: string): boolean; assembler;
  833. asm
  834. {$IFDEF REGCALL}
  835. mov edx, eax
  836. {$ELSE REGCALL}
  837. mov edx, Directory
  838. {$ENDIF REGCALL}
  839. mov ax, 4300h
  840. call syscall
  841. mov eax, 0
  842. jc @FExistsEnd
  843. test cx, 10h
  844. jz @FExistsEnd
  845. inc eax
  846. @FExistsEnd:
  847. end {['eax', 'ecx', 'edx']};
  848. {****************************************************************************
  849. Time Functions
  850. ****************************************************************************}
  851. procedure GetLocalTime (var SystemTime: TSystemTime); assembler;
  852. asm
  853. (* Expects the default record alignment (word)!!! *)
  854. push edi
  855. {$IFDEF REGCALL}
  856. push eax
  857. {$ENDIF REGCALL}
  858. mov ah, 2Ah
  859. call syscall
  860. {$IFDEF REGCALL}
  861. pop eax
  862. {$ELSE REGCALL}
  863. mov edi, SystemTime
  864. {$ENDIF REGCALL}
  865. mov ax, cx
  866. stosw
  867. xor eax, eax
  868. mov al, 10
  869. mul dl
  870. shl eax, 16
  871. mov al, dh
  872. stosd
  873. push edi
  874. mov ah, 2Ch
  875. call syscall
  876. pop edi
  877. xor eax, eax
  878. mov al, cl
  879. shl eax, 16
  880. mov al, ch
  881. stosd
  882. mov al, dl
  883. shl eax, 16
  884. mov al, dh
  885. stosd
  886. pop edi
  887. end {['eax', 'ecx', 'edx', 'edi']};
  888. {$asmmode default}
  889. {****************************************************************************
  890. Misc Functions
  891. ****************************************************************************}
  892. procedure Beep;
  893. begin
  894. end;
  895. {****************************************************************************
  896. Locale Functions
  897. ****************************************************************************}
  898. procedure InitAnsi;
  899. var I: byte;
  900. Country: TCountryCode;
  901. begin
  902. for I := 0 to 255 do
  903. UpperCaseTable [I] := Chr (I);
  904. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  905. if os_mode = osOS2 then
  906. begin
  907. FillChar (Country, SizeOf (Country), 0);
  908. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  909. end
  910. else
  911. begin
  912. (* !!! TODO: DOS/DPMI mode support!!! *)
  913. end;
  914. for I := 0 to 255 do
  915. if UpperCaseTable [I] <> Chr (I) then
  916. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  917. end;
  918. procedure InitInternational;
  919. var Country: TCountryCode;
  920. CtryInfo: TCountryInfo;
  921. Size: cardinal;
  922. RC: cardinal;
  923. begin
  924. Size := 0;
  925. FillChar (Country, SizeOf (Country), 0);
  926. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  927. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  928. if RC = 0 then
  929. begin
  930. DateSeparator := CtryInfo.DateSeparator;
  931. case CtryInfo.DateFormat of
  932. 1: begin
  933. ShortDateFormat := 'd/m/y';
  934. LongDateFormat := 'dd" "mmmm" "yyyy';
  935. end;
  936. 2: begin
  937. ShortDateFormat := 'y/m/d';
  938. LongDateFormat := 'yyyy" "mmmm" "dd';
  939. end;
  940. 3: begin
  941. ShortDateFormat := 'm/d/y';
  942. LongDateFormat := 'mmmm" "dd" "yyyy';
  943. end;
  944. end;
  945. TimeSeparator := CtryInfo.TimeSeparator;
  946. DecimalSeparator := CtryInfo.DecimalSeparator;
  947. ThousandSeparator := CtryInfo.ThousandSeparator;
  948. CurrencyFormat := CtryInfo.CurrencyFormat;
  949. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  950. end;
  951. InitAnsi;
  952. InitInternationalGeneric;
  953. end;
  954. function SysErrorMessage(ErrorCode: Integer): String;
  955. begin
  956. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  957. end;
  958. {****************************************************************************
  959. OS Utils
  960. ****************************************************************************}
  961. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  962. begin
  963. GetEnvironmentVariable := StrPas (GetEnvPChar (EnvVar));
  964. end;
  965. Function GetEnvironmentVariableCount : Integer;
  966. begin
  967. (* Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
  968. GetEnvironmentVariableCount := EnvC;
  969. end;
  970. Function GetEnvironmentString(Index : Integer) : String;
  971. begin
  972. Result:=FPCGetEnvStrFromP (EnvP, Index);
  973. end;
  974. {$ASMMODE INTEL}
  975. procedure Sleep (Milliseconds: cardinal);
  976. begin
  977. if os_mode = osOS2 then DosSleep (Milliseconds) else
  978. asm
  979. mov edx, Milliseconds
  980. mov eax, 7F30h
  981. call syscall
  982. end ['eax', 'edx'];
  983. end;
  984. {$ASMMODE DEFAULT}
  985. function ExecuteProcess (const Path: AnsiString; const ComLine: AnsiString;Flags:TExecuteFlags=[]):
  986. integer;
  987. var
  988. HQ: THandle;
  989. SPID, STID, QName: shortstring;
  990. SD: TStartData;
  991. SID, PID: cardinal;
  992. RD: TRequestData;
  993. PCI: PChildInfo;
  994. CISize: cardinal;
  995. Prio: byte;
  996. E: EOSError;
  997. CommandLine: ansistring;
  998. begin
  999. if os_Mode = osOS2 then
  1000. begin
  1001. FillChar (SD, SizeOf (SD), 0);
  1002. SD.Length := 24;
  1003. SD.Related := ssf_Related_Child;
  1004. SD.PgmName := PChar (Path);
  1005. SD.PgmInputs := PChar (ComLine);
  1006. Str (GetProcessID, SPID);
  1007. Str (ThreadID, STID);
  1008. QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
  1009. SD.TermQ := @QName [1];
  1010. Result := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
  1011. if Result = 0 then
  1012. begin
  1013. Result := DosStartSession (SD, SID, PID);
  1014. if (Result = 0) or (Result = 457) then
  1015. begin
  1016. Result := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
  1017. if Result = 0 then
  1018. begin
  1019. Result := PCI^.Return;
  1020. DosCloseQueue (HQ);
  1021. DosFreeMem (PCI);
  1022. Exit;
  1023. end;
  1024. end;
  1025. DosCloseQueue (HQ);
  1026. end;
  1027. if ComLine = '' then
  1028. CommandLine := Path
  1029. else
  1030. CommandLine := Path + ' ' + ComLine;
  1031. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, Result]);
  1032. E.ErrorCode := Result;
  1033. raise E;
  1034. end else
  1035. begin
  1036. Dos.Exec (Path, ComLine);
  1037. if DosError <> 0 then
  1038. begin
  1039. if ComLine = '' then
  1040. CommandLine := Path
  1041. else
  1042. CommandLine := Path + ' ' + ComLine;
  1043. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, DosError]);
  1044. E.ErrorCode := DosError;
  1045. raise E;
  1046. end;
  1047. ExecuteProcess := DosExitCode;
  1048. end;
  1049. end;
  1050. function ExecuteProcess (const Path: AnsiString;
  1051. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  1052. var
  1053. CommandLine: AnsiString;
  1054. I: integer;
  1055. begin
  1056. Commandline := '';
  1057. for I := 0 to High (ComLine) do
  1058. if Pos (' ', ComLine [I]) <> 0 then
  1059. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  1060. else
  1061. CommandLine := CommandLine + ' ' + Comline [I];
  1062. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  1063. end;
  1064. {****************************************************************************
  1065. Initialization code
  1066. ****************************************************************************}
  1067. Initialization
  1068. InitExceptions; { Initialize exceptions. OS independent }
  1069. InitInternational; { Initialize internationalization settings }
  1070. Finalization
  1071. DoneExceptions;
  1072. end.