sysutils.pp 38 KB

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