sysutils.pp 37 KB

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