sysutils.pp 37 KB

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