sysutils.pp 37 KB

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