sysutils.pp 36 KB

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