sysutils.pp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  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 OS/2
  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:cardinal; {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. TFileFindBuf3L=object(TFileStatus)
  92. NextEntryOffset: cardinal; {Offset of next entry}
  93. DateCreation, {Date of file creation.}
  94. TimeCreation, {Time of file creation.}
  95. DateLastAccess, {Date of last access to file.}
  96. TimeLastAccess, {Time of last access to file.}
  97. DateLastWrite, {Date of last modification of file.}
  98. TimeLastWrite:word; {Time of last modification of file.}
  99. FileSize, {Size of file.}
  100. FileAlloc:int64; {Amount of space the file really
  101. occupies on disk.}
  102. AttrFile:cardinal; {Attributes of file.}
  103. Name:shortstring; {Also possible to use as ASCIIZ.
  104. The byte following the last string
  105. character is always zero.}
  106. end;
  107. PFileFindBuf3L=^TFileFindBuf3L;
  108. TFileFindBuf4L=object(TFileStatus)
  109. NextEntryOffset: cardinal; {Offset of next entry}
  110. DateCreation, {Date of file creation.}
  111. TimeCreation, {Time of file creation.}
  112. DateLastAccess, {Date of last access to file.}
  113. TimeLastAccess, {Time of last access to file.}
  114. DateLastWrite, {Date of last modification of file.}
  115. TimeLastWrite:word; {Time of last modification of file.}
  116. FileSize, {Size of file.}
  117. FileAlloc:int64; {Amount of space the file really
  118. occupies on disk.}
  119. AttrFile:cardinal; {Attributes of file.}
  120. cbList:cardinal; {Size of the file's extended attributes.}
  121. Name:shortstring; {Also possible to use as ASCIIZ.
  122. The byte following the last string
  123. character is always zero.}
  124. end;
  125. PFileFindBuf4L=^TFileFindBuf4L;
  126. TFSInfo = record
  127. case word of
  128. 1:
  129. (File_Sys_ID,
  130. Sectors_Per_Cluster,
  131. Total_Clusters,
  132. Free_Clusters: cardinal;
  133. Bytes_Per_Sector: word);
  134. 2: {For date/time description,
  135. see file searching realted
  136. routines.}
  137. (Label_Date, {Date when volume label was created.}
  138. Label_Time: word; {Time when volume label was created.}
  139. VolumeLabel: ShortString); {Volume label. Can also be used
  140. as ASCIIZ, because the byte
  141. following the last character of
  142. the string is always zero.}
  143. end;
  144. PFSInfo = ^TFSInfo;
  145. TCountryCode=record
  146. Country, {Country to query info about (0=current).}
  147. CodePage: cardinal; {Code page to query info about (0=current).}
  148. end;
  149. PCountryCode=^TCountryCode;
  150. TTimeFmt = (Clock12, Clock24);
  151. TCountryInfo=record
  152. Country, CodePage: cardinal; {Country and codepage requested.}
  153. case byte of
  154. 0:
  155. (DateFormat: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  156. CurrencyUnit: array [0..4] of char;
  157. ThousandSeparator: char; {Thousands separator.}
  158. Zero1: byte; {Always zero.}
  159. DecimalSeparator: char; {Decimals separator,}
  160. Zero2: byte;
  161. DateSeparator: char; {Date separator.}
  162. Zero3: byte;
  163. TimeSeparator: char; {Time separator.}
  164. Zero4: byte;
  165. CurrencyFormat, {Bit field:
  166. Bit 0: 0=indicator before value
  167. 1=indicator after value
  168. Bit 1: 1=insert space after
  169. indicator.
  170. Bit 2: 1=Ignore bit 0&1, replace
  171. decimal separator with
  172. indicator.}
  173. DecimalPlace: byte; {Number of decimal places used in
  174. currency indication.}
  175. TimeFormat: TTimeFmt; {12/24 hour.}
  176. Reserve1: array [0..1] of word;
  177. DataSeparator: char; {Data list separator}
  178. Zero5: byte;
  179. Reserve2: array [0..4] of word);
  180. 1:
  181. (fsDateFmt: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  182. szCurrency: array [0..4] of char;
  183. {null terminated currency symbol}
  184. szThousandsSeparator: array [0..1] of char;
  185. {Thousands separator + #0}
  186. szDecimal: array [0..1] of char;
  187. {Decimals separator + #0}
  188. szDateSeparator: array [0..1] of char;
  189. {Date separator + #0}
  190. szTimeSeparator: array [0..1] of char;
  191. {Time separator + #0}
  192. fsCurrencyFmt, {Bit field:
  193. Bit 0: 0=indicator before value
  194. 1=indicator after value
  195. Bit 1: 1=insert space after
  196. indicator.
  197. Bit 2: 1=Ignore bit 0&1, replace
  198. decimal separator with
  199. indicator}
  200. cDecimalPlace: byte; {Number of decimal places used in
  201. currency indication}
  202. fsTimeFmt: byte; {0=12,1=24 hours}
  203. abReserved1: array [0..1] of word;
  204. szDataSeparator: array [0..1] of char;
  205. {Data list separator + #0}
  206. abReserved2: array [0..4] of word);
  207. end;
  208. PCountryInfo=^TCountryInfo;
  209. TRequestData=record
  210. PID, {ID of process that wrote element.}
  211. Data: cardinal; {Information from process writing the data.}
  212. end;
  213. PRequestData=^TRequestData;
  214. {Queue data structure for synchronously started sessions.}
  215. TChildInfo = record
  216. case boolean of
  217. false:
  218. (SessionID,
  219. Return: word); {Return code from the child process.}
  220. true:
  221. (usSessionID,
  222. usReturn: word); {Return code from the child process.}
  223. end;
  224. PChildInfo = ^TChildInfo;
  225. TStartData=record
  226. {Note: to omit some fields, use a length smaller than SizeOf(TStartData).}
  227. Length:word; {Length, in bytes, of datastructure
  228. (24/30/32/50/60).}
  229. Related:word; {Independent/child session (0/1).}
  230. FgBg:word; {Foreground/background (0/1).}
  231. TraceOpt:word; {No trace/trace this/trace all (0/1/2).}
  232. PgmTitle:PChar; {Program title.}
  233. PgmName:PChar; {Filename to program.}
  234. PgmInputs:PChar; {Command parameters (nil allowed).}
  235. TermQ:PChar; {System queue. (nil allowed).}
  236. Environment:PChar; {Environment to pass (nil allowed).}
  237. InheritOpt:word; {Inherit environment from shell/
  238. inherit environment from parent (0/1).}
  239. SessionType:word; {Auto/full screen/window/presentation
  240. manager/full screen Dos/windowed Dos
  241. (0/1/2/3/4/5/6/7).}
  242. Iconfile:PChar; {Icon file to use (nil allowed).}
  243. PgmHandle:cardinal; {0 or the program handle.}
  244. PgmControl:word; {Bitfield describing initial state
  245. of windowed sessions.}
  246. InitXPos,InitYPos:word; {Initial top coordinates.}
  247. InitXSize,InitYSize:word; {Initial size.}
  248. Reserved:word;
  249. ObjectBuffer:PChar; {If a module cannot be loaded, its
  250. name will be returned here.}
  251. ObjectBuffLen:cardinal; {Size of your buffer.}
  252. end;
  253. PStartData=^TStartData;
  254. TResultCodes=record
  255. TerminateReason, {0 = Normal termionation.
  256. 1 = Critical error.
  257. 2 = Trapped. (GPE, etc.)
  258. 3 = Killed by DosKillProcess.}
  259. ExitCode:cardinal; {Exit code of child.}
  260. end;
  261. const
  262. ilStandard = 1;
  263. ilQueryEAsize = 2;
  264. ilQueryEAs = 3;
  265. ilQueryFullName = 5;
  266. quFIFO = 0;
  267. quLIFO = 1;
  268. quPriority = 2;
  269. quNoConvert_Address = 0;
  270. quConvert_Address = 4;
  271. {Start the new session independent or as a child.}
  272. ssf_Related_Independent = 0; {Start new session independent
  273. of the calling session.}
  274. ssf_Related_Child = 1; {Start new session as a child
  275. session to the calling session.}
  276. {Start the new session in the foreground or in the background.}
  277. ssf_FgBg_Fore = 0; {Start new session in foreground.}
  278. ssf_FgBg_Back = 1; {Start new session in background.}
  279. {Should the program started in the new session
  280. be executed under conditions for tracing?}
  281. ssf_TraceOpt_None = 0; {No trace.}
  282. ssf_TraceOpt_Trace = 1; {Trace with no notification
  283. of descendants.}
  284. ssf_TraceOpt_TraceAll = 2; {Trace all descendant sessions.
  285. A termination queue must be
  286. supplied and Related must be
  287. ssf_Related_Child (=1).}
  288. {Will the new session inherit open file handles
  289. and environment from the calling process.}
  290. ssf_InhertOpt_Shell = 0; {Inherit from the shell.}
  291. ssf_InhertOpt_Parent = 1; {Inherit from the calling process.}
  292. {Specifies the type of session to start.}
  293. ssf_Type_Default = 0; {Use program's type.}
  294. ssf_Type_FullScreen = 1; {OS/2 full screen.}
  295. ssf_Type_WindowableVIO = 2; {OS/2 window.}
  296. ssf_Type_PM = 3; {Presentation Manager.}
  297. ssf_Type_VDM = 4; {DOS full screen.}
  298. ssf_Type_WindowedVDM = 7; {DOS window.}
  299. {Additional values for Windows programs}
  300. Prog_31_StdSeamlessVDM = 15; {Windows 3.1 program in its
  301. own windowed session.}
  302. Prog_31_StdSeamlessCommon = 16; {Windows 3.1 program in a
  303. common windowed session.}
  304. Prog_31_EnhSeamlessVDM = 17; {Windows 3.1 program in enhanced
  305. compatibility mode in its own
  306. windowed session.}
  307. Prog_31_EnhSeamlessCommon = 18; {Windows 3.1 program in enhanced
  308. compatibility mode in a common
  309. windowed session.}
  310. Prog_31_Enh = 19; {Windows 3.1 program in enhanced
  311. compatibility mode in a full
  312. screen session.}
  313. Prog_31_Std = 20; {Windows 3.1 program in a full
  314. screen session.}
  315. {Specifies the initial attributes for a OS/2 window or DOS window session.}
  316. ssf_Control_Visible = 0; {Window is visible.}
  317. ssf_Control_Invisible = 1; {Window is invisible.}
  318. ssf_Control_Maximize = 2; {Window is maximized.}
  319. ssf_Control_Minimize = 4; {Window is minimized.}
  320. ssf_Control_NoAutoClose = 8; {Window will not close after
  321. the program has ended.}
  322. ssf_Control_SetPos = 32768; {Use InitXPos, InitYPos,
  323. InitXSize, and InitYSize for
  324. the size and placement.}
  325. function DosSetFileInfo (Handle: THandle; InfoLevel: cardinal; AFileStatus: PFileStatus;
  326. FileStatusLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 218;
  327. function DosQueryFSInfo (DiskNum, InfoLevel: cardinal; var Buffer: TFSInfo;
  328. BufLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 278;
  329. function DosQueryFileInfo (Handle: THandle; InfoLevel: cardinal;
  330. AFileStatus: PFileStatus; FileStatusLen: cardinal): cardinal; cdecl;
  331. external 'DOSCALLS' index 279;
  332. function DosScanEnv (Name: PChar; var Value: PChar): cardinal; cdecl;
  333. external 'DOSCALLS' index 227;
  334. function DosFindFirst (FileMask: PChar; var Handle: THandle; Attrib: cardinal;
  335. AFileStatus: PFileStatus; FileStatusLen: cardinal;
  336. var Count: cardinal; InfoLevel: cardinal): cardinal; cdecl;
  337. external 'DOSCALLS' index 264;
  338. function DosFindNext (Handle: THandle; AFileStatus: PFileStatus;
  339. FileStatusLen: cardinal; var Count: cardinal): cardinal; cdecl;
  340. external 'DOSCALLS' index 265;
  341. function DosFindClose (Handle: THandle): cardinal; cdecl;
  342. external 'DOSCALLS' index 263;
  343. function DosQueryCtryInfo (Size: cardinal; var Country: TCountryCode;
  344. var Res: TCountryInfo; var ActualSize: cardinal): cardinal; cdecl;
  345. external 'NLS' index 5;
  346. function DosMapCase (Size: cardinal; var Country: TCountryCode;
  347. AString: PChar): cardinal; cdecl; external 'NLS' index 7;
  348. function DosDelete(FileName:PChar): cardinal; cdecl;
  349. external 'DOSCALLS' index 259;
  350. function DosMove(OldFile, NewFile:PChar): cardinal; cdecl;
  351. external 'DOSCALLS' index 271;
  352. function DosQueryPathInfo(FileName:PChar;InfoLevel:cardinal;
  353. AFileStatus:PFileStatus;FileStatusLen:cardinal): cardinal; cdecl;
  354. external 'DOSCALLS' index 223;
  355. function DosSetPathInfo(FileName:PChar;InfoLevel:cardinal;
  356. AFileStatus:PFileStatus;FileStatusLen,
  357. Options:cardinal):cardinal; cdecl;
  358. external 'DOSCALLS' index 219;
  359. function DosClose(Handle: THandle): cardinal; cdecl;
  360. external 'DOSCALLS' index 257;
  361. function DosRead(Handle:THandle; var Buffer; Count: cardinal;
  362. var ActCount: cardinal): cardinal; cdecl;
  363. external 'DOSCALLS' index 281;
  364. function DosWrite(Handle: THandle; Buffer: pointer; Count: cardinal;
  365. var ActCount: cardinal): cardinal; cdecl;
  366. external 'DOSCALLS' index 282;
  367. procedure DosSleep (MSec: cardinal); cdecl; external 'DOSCALLS' index 229;
  368. function DosCreateQueue (var Handle: THandle; Priority:longint;
  369. Name: PChar): cardinal; cdecl;
  370. external 'QUECALLS' index 16;
  371. function DosReadQueue (Handle: THandle; var ReqBuffer: TRequestData;
  372. var DataLen: cardinal; var DataPtr: pointer;
  373. Element, Wait: cardinal; var Priority: byte;
  374. ASem: THandle): cardinal; cdecl;
  375. external 'QUECALLS' index 9;
  376. function DosCloseQueue (Handle: THandle): cardinal; cdecl;
  377. external 'QUECALLS' index 11;
  378. function DosStartSession (var AStartData: TStartData;
  379. var SesID, PID: cardinal): cardinal; cdecl;
  380. external 'SESMGR' index 37;
  381. function DosFreeMem(P:pointer):cardinal; cdecl; external 'DOSCALLS' index 304;
  382. function DosExecPgm (ObjName: PChar; ObjLen: longint; ExecFlag: cardinal;
  383. Args, Env: PByteArray; var Res: TResultCodes;
  384. FileName:PChar): cardinal; cdecl;
  385. external 'DOSCALLS' index 283;
  386. type
  387. TDT=packed record
  388. Hour,
  389. Minute,
  390. Second,
  391. Sec100,
  392. Day,
  393. Month: byte;
  394. Year: word;
  395. TimeZone: smallint;
  396. WeekDay: byte;
  397. end;
  398. function DosGetDateTime(var Buf: TDT): cardinal; cdecl;
  399. external 'DOSCALLS' index 230;
  400. {****************************************************************************
  401. File Functions
  402. ****************************************************************************}
  403. const
  404. ofRead = $0000; {Open for reading}
  405. ofWrite = $0001; {Open for writing}
  406. ofReadWrite = $0002; {Open for reading/writing}
  407. doDenyRW = $0010; {DenyAll (no sharing)}
  408. faCreateNew = $00010000; {Create if file does not exist}
  409. faOpenReplace = $00040000; {Truncate if file exists}
  410. faCreate = $00050000; {Create if file does not exist, truncate otherwise}
  411. FindResvdMask = $00003737; {Allowed bits in attribute
  412. specification for DosFindFirst call.}
  413. function FileOpen (const FileName: string; Mode: integer): THandle;
  414. Var
  415. Handle: THandle;
  416. Rc, Action: cardinal;
  417. begin
  418. (* DenyNone if sharing not specified. *)
  419. if (Mode and 112 = 0) or (Mode and 112 > 64) then
  420. Mode := Mode or 64;
  421. Rc:=Sys_DosOpenL(PChar (FileName), Handle, Action, 0, 0, 1, Mode, nil);
  422. If Rc=0 then
  423. FileOpen:=Handle
  424. else
  425. FileOpen:=feInvalidHandle; //FileOpen:=-RC;
  426. //should return feInvalidHandle(=-1) if fail, other negative returned value are no more errors
  427. end;
  428. function FileCreate (const FileName: string): THandle;
  429. begin
  430. FileCreate := FileCreate (FileName, doDenyRW, 777); (* Sharing to DenyAll *)
  431. end;
  432. function FileCreate (const FileName: string; Rights: integer): THandle;
  433. begin
  434. FileCreate := FileCreate (FileName, doDenyRW, Rights);
  435. (* Sharing to DenyAll *)
  436. end;
  437. function FileCreate (const FileName: string; ShareMode: integer;
  438. Rights: integer): THandle;
  439. var
  440. Handle: THandle;
  441. RC, Action: cardinal;
  442. begin
  443. ShareMode := ShareMode and 112;
  444. (* Sharing to DenyAll as default in case of values not allowed by OS/2. *)
  445. if (ShareMode = 0) or (ShareMode > 64) then
  446. ShareMode := doDenyRW;
  447. RC := Sys_DosOpenL (PChar (FileName), Handle, Action, 0, 0, $12,
  448. faCreate or ofReadWrite or ShareMode, nil);
  449. if RC = 0 then
  450. FileCreate := Handle
  451. else
  452. FileCreate := feInvalidHandle;
  453. End;
  454. function FileRead (Handle: THandle; Out Buffer; Count: longint): longint;
  455. Var
  456. T: cardinal;
  457. begin
  458. DosRead(Handle, Buffer, Count, T);
  459. FileRead := longint (T);
  460. end;
  461. function FileWrite (Handle: THandle; const Buffer; Count: longint): longint;
  462. Var
  463. T: cardinal;
  464. begin
  465. DosWrite (Handle, @Buffer, Count, T);
  466. FileWrite := longint (T);
  467. end;
  468. function FileSeek (Handle: THandle; FOffset, Origin: longint): longint;
  469. var
  470. NPos: int64;
  471. begin
  472. if (Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos) = 0)
  473. and (NPos < high (longint)) then
  474. FileSeek:= longint (NPos)
  475. else
  476. FileSeek:=-1;
  477. end;
  478. function FileSeek (Handle: THandle; FOffset: Int64; Origin: Longint): Int64;
  479. var
  480. NPos: int64;
  481. begin
  482. if Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos) = 0 then
  483. FileSeek:= NPos
  484. else
  485. FileSeek:=-1;
  486. end;
  487. procedure FileClose (Handle: THandle);
  488. begin
  489. DosClose(Handle);
  490. end;
  491. function FileTruncate (Handle: THandle; Size: Int64): boolean;
  492. begin
  493. FileTruncate:=Sys_DosSetFileSizeL(Handle, Size)=0;
  494. FileSeek(Handle, 0, 2);
  495. end;
  496. function FileAge (const FileName: string): longint;
  497. var Handle: longint;
  498. begin
  499. Handle := FileOpen (FileName, 0);
  500. if Handle <> -1 then
  501. begin
  502. Result := FileGetDate (Handle);
  503. FileClose (Handle);
  504. end
  505. else
  506. Result := -1;
  507. end;
  508. function FileExists (const FileName: string): boolean;
  509. var
  510. SR: TSearchRec;
  511. RC: longint;
  512. begin
  513. FileExists:=False;
  514. if FindFirst (FileName, faAnyFile and not (faDirectory), SR) = 0
  515. then FileExists := True;
  516. FindClose(SR);
  517. end;
  518. type TRec = record
  519. T, D: word;
  520. end;
  521. PSearchRec = ^SearchRec;
  522. function FindFirst (const Path: string; Attr: longint; out Rslt: TSearchRec): longint;
  523. var SR: PSearchRec;
  524. FStat: PFileFindBuf3;
  525. Count: cardinal;
  526. Err: cardinal;
  527. I: cardinal;
  528. begin
  529. New (FStat);
  530. Rslt.FindHandle := THandle ($FFFFFFFF);
  531. Count := 1;
  532. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  533. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandard);
  534. if (Err = 0) and (Count = 0) then Err := 18;
  535. FindFirst := -Err;
  536. if Err = 0 then
  537. begin
  538. Rslt.Name := FStat^.Name;
  539. Rslt.Size := FStat^.FileSize;
  540. Rslt.Attr := FStat^.AttrFile;
  541. Rslt.ExcludeAttr := 0;
  542. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  543. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  544. end else if (Rslt.Findhandle<>0) then
  545. begin
  546. FindClose(Rslt);
  547. end;
  548. Dispose (FStat);
  549. end;
  550. function FindNext (var Rslt: TSearchRec): longint;
  551. var
  552. SR: PSearchRec;
  553. FStat: PFileFindBuf3;
  554. Count: cardinal;
  555. Err: cardinal;
  556. begin
  557. New (FStat);
  558. Count := 1;
  559. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^),
  560. Count);
  561. if (Err = 0) and (Count = 0) then Err := 18;
  562. FindNext := -Err;
  563. if Err = 0 then
  564. begin
  565. Rslt.Name := FStat^.Name;
  566. Rslt.Size := FStat^.FileSize;
  567. Rslt.Attr := FStat^.AttrFile;
  568. Rslt.ExcludeAttr := 0;
  569. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  570. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  571. end;
  572. Dispose (FStat);
  573. end;
  574. procedure FindClose (var F: TSearchrec);
  575. var
  576. SR: PSearchRec;
  577. begin
  578. DosFindClose (F.FindHandle);
  579. F.FindHandle := 0;
  580. end;
  581. function FileGetDate (Handle: THandle): longint;
  582. var
  583. FStat: TFileStatus3;
  584. Time: Longint;
  585. begin
  586. DosError := DosQueryFileInfo(Handle, ilStandard, @FStat, SizeOf(FStat));
  587. if DosError=0 then
  588. begin
  589. Time := FStat.TimeLastWrite + longint (FStat.DateLastWrite) shl 16;
  590. if Time = 0 then
  591. Time := FStat.TimeCreation + longint (FStat.DateCreation) shl 16;
  592. end else
  593. Time:=0;
  594. FileGetDate:=Time;
  595. end;
  596. function FileSetDate (Handle: THandle; Age: longint): longint;
  597. var
  598. FStat: PFileStatus3;
  599. RC: cardinal;
  600. begin
  601. New (FStat);
  602. RC := DosQueryFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^));
  603. if RC <> 0 then
  604. FileSetDate := -1
  605. else
  606. begin
  607. FStat^.DateLastAccess := Hi (Age);
  608. FStat^.DateLastWrite := Hi (Age);
  609. FStat^.TimeLastAccess := Lo (Age);
  610. FStat^.TimeLastWrite := Lo (Age);
  611. RC := DosSetFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^));
  612. if RC <> 0 then
  613. FileSetDate := -1
  614. else
  615. FileSetDate := 0;
  616. end;
  617. Dispose (FStat);
  618. end;
  619. function FileGetAttr (const FileName: string): longint;
  620. var
  621. FS: PFileStatus3;
  622. begin
  623. New(FS);
  624. Result:=-DosQueryPathInfo(PChar (FileName), ilStandard, FS, SizeOf(FS^));
  625. If Result=0 Then Result:=FS^.attrFile;
  626. Dispose(FS);
  627. end;
  628. function FileSetAttr (const Filename: string; Attr: longint): longint;
  629. Var
  630. FS: PFileStatus3;
  631. Begin
  632. New(FS);
  633. FillChar(FS, SizeOf(FS^), 0);
  634. FS^.AttrFile:=Attr;
  635. Result:=-DosSetPathInfo(PChar (FileName), ilStandard, FS, SizeOf(FS^), 0);
  636. Dispose(FS);
  637. end;
  638. function DeleteFile (const FileName: string): boolean;
  639. Begin
  640. Result:=(DosDelete(PChar (FileName))=0);
  641. End;
  642. function RenameFile (const OldName, NewName: string): boolean;
  643. Begin
  644. Result:=(DosMove(PChar (OldName), PChar (NewName))=0);
  645. End;
  646. {****************************************************************************
  647. Disk Functions
  648. ****************************************************************************}
  649. function DiskFree (Drive: byte): int64;
  650. var FI: TFSinfo;
  651. RC: cardinal;
  652. begin
  653. {In OS/2, we use the filesystem information.}
  654. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  655. if RC = 0 then
  656. DiskFree := int64 (FI.Free_Clusters) *
  657. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  658. else
  659. DiskFree := -1;
  660. end;
  661. function DiskSize (Drive: byte): int64;
  662. var FI: TFSinfo;
  663. RC: cardinal;
  664. begin
  665. {In OS/2, we use the filesystem information.}
  666. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  667. if RC = 0 then
  668. DiskSize := int64 (FI.Total_Clusters) *
  669. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  670. else
  671. DiskSize := -1;
  672. end;
  673. function GetCurrentDir: string;
  674. begin
  675. GetDir (0, Result);
  676. end;
  677. function SetCurrentDir (const NewDir: string): boolean;
  678. begin
  679. {$I-}
  680. {$WARNING Should be rewritten to avoid unit dos dependency!}
  681. ChDir (NewDir);
  682. Result := (IOResult = 0);
  683. {$I+}
  684. end;
  685. function CreateDir (const NewDir: string): boolean;
  686. begin
  687. {$I-}
  688. {$WARNING Should be rewritten to avoid unit dos dependency!}
  689. MkDir (NewDir);
  690. Result := (IOResult = 0);
  691. {$I+}
  692. end;
  693. function RemoveDir (const Dir: string): boolean;
  694. begin
  695. {$I-}
  696. {$WARNING Should be rewritten to avoid unit dos dependency!}
  697. RmDir (Dir);
  698. Result := (IOResult = 0);
  699. {$I+}
  700. end;
  701. function DirectoryExists (const Directory: string): boolean;
  702. var
  703. SR: TSearchRec;
  704. begin
  705. DirectoryExists := (FindFirst (Directory, faAnyFile, SR) = 0) and
  706. (SR.Attr and faDirectory <> 0);
  707. FindClose(SR);
  708. end;
  709. {****************************************************************************
  710. Time Functions
  711. ****************************************************************************}
  712. procedure GetLocalTime (var SystemTime: TSystemTime);
  713. var
  714. DT: TDT;
  715. begin
  716. DosGetDateTime(DT);
  717. with SystemTime do
  718. begin
  719. Year:=DT.Year;
  720. Month:=DT.Month;
  721. Day:=DT.Day;
  722. Hour:=DT.Hour;
  723. Minute:=DT.Minute;
  724. Second:=DT.Second;
  725. MilliSecond:=DT.Sec100;
  726. end;
  727. end;
  728. {****************************************************************************
  729. Misc Functions
  730. ****************************************************************************}
  731. procedure sysbeep;
  732. begin
  733. // Maybe implement later on ?
  734. end;
  735. {****************************************************************************
  736. Locale Functions
  737. ****************************************************************************}
  738. procedure InitAnsi;
  739. var I: byte;
  740. Country: TCountryCode;
  741. begin
  742. for I := 0 to 255 do
  743. UpperCaseTable [I] := Chr (I);
  744. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  745. FillChar (Country, SizeOf (Country), 0);
  746. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  747. for I := 0 to 255 do
  748. if UpperCaseTable [I] <> Chr (I) then
  749. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  750. end;
  751. procedure InitInternational;
  752. var Country: TCountryCode;
  753. CtryInfo: TCountryInfo;
  754. Size: cardinal;
  755. RC: cardinal;
  756. begin
  757. Size := 0;
  758. FillChar (Country, SizeOf (Country), 0);
  759. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  760. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  761. if RC = 0 then
  762. begin
  763. DateSeparator := CtryInfo.DateSeparator;
  764. case CtryInfo.DateFormat of
  765. 1: begin
  766. ShortDateFormat := 'd/m/y';
  767. LongDateFormat := 'dd" "mmmm" "yyyy';
  768. end;
  769. 2: begin
  770. ShortDateFormat := 'y/m/d';
  771. LongDateFormat := 'yyyy" "mmmm" "dd';
  772. end;
  773. 3: begin
  774. ShortDateFormat := 'm/d/y';
  775. LongDateFormat := 'mmmm" "dd" "yyyy';
  776. end;
  777. end;
  778. TimeSeparator := CtryInfo.TimeSeparator;
  779. DecimalSeparator := CtryInfo.DecimalSeparator;
  780. ThousandSeparator := CtryInfo.ThousandSeparator;
  781. CurrencyFormat := CtryInfo.CurrencyFormat;
  782. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  783. end;
  784. InitAnsi;
  785. InitInternationalGeneric;
  786. end;
  787. function SysErrorMessage(ErrorCode: Integer): String;
  788. begin
  789. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  790. end;
  791. {****************************************************************************
  792. OS Utils
  793. ****************************************************************************}
  794. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  795. begin
  796. GetEnvironmentVariable := StrPas (GetEnvPChar (EnvVar));
  797. end;
  798. Function GetEnvironmentVariableCount : Integer;
  799. begin
  800. (* Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
  801. GetEnvironmentVariableCount := EnvC;
  802. end;
  803. Function GetEnvironmentString(Index : Integer) : String;
  804. begin
  805. Result:=FPCGetEnvStrFromP (EnvP, Index);
  806. end;
  807. procedure Sleep (Milliseconds: cardinal);
  808. begin
  809. DosSleep (Milliseconds);
  810. end;
  811. function ExecuteProcess (const Path: AnsiString; const ComLine: AnsiString;Flags:TExecuteFlags=[]):
  812. integer;
  813. var
  814. HQ: THandle;
  815. SPID, STID, QName: shortstring;
  816. SD: TStartData;
  817. SID, PID: cardinal;
  818. RD: TRequestData;
  819. PCI: PChildInfo;
  820. CISize: cardinal;
  821. Prio: byte;
  822. E: EOSError;
  823. CommandLine: ansistring;
  824. Args0, Args: PByteArray;
  825. ObjNameBuf: PChar;
  826. ArgSize: word;
  827. Res: TResultCodes;
  828. ObjName: shortstring;
  829. const
  830. MaxArgsSize = 3072; (* Amount of memory reserved for arguments in bytes. *)
  831. ObjBufSize = 512;
  832. begin
  833. ObjName := '';
  834. GetMem (ObjNameBuf, ObjBufSize);
  835. FillChar (ObjNameBuf^, ObjBufSize, 0);
  836. if ComLine = '' then
  837. begin
  838. Args0 := nil;
  839. Args := nil;
  840. end
  841. else
  842. begin
  843. GetMem (Args0, MaxArgsSize);
  844. Args := Args0;
  845. (* Work around a bug in OS/2 - argument to DosExecPgm *)
  846. (* should not cross 64K boundary. *)
  847. if ((PtrUInt (Args) + 1024) and $FFFF) < 1024 then
  848. Inc (pointer (Args), 1024);
  849. ArgSize := 0;
  850. Move (Path [1], Args^ [ArgSize], Length (Path));
  851. Inc (ArgSize, Length (Path));
  852. Args^ [ArgSize] := 0;
  853. Inc (ArgSize);
  854. {Now do the real arguments.}
  855. Move (ComLine [1], Args^ [ArgSize], Length (ComLine));
  856. Inc (ArgSize, Length (ComLine));
  857. Args^ [ArgSize] := 0;
  858. Inc (ArgSize);
  859. Args^ [ArgSize] := 0;
  860. end;
  861. Result := DosExecPgm (ObjNameBuf, ObjBufSize, 0, Args, nil, Res, PChar (Path));
  862. if Args0 <> nil then
  863. FreeMem (Args0, MaxArgsSize);
  864. if Result = 0 then
  865. begin
  866. Result := Res.ExitCode;
  867. FreeMem (ObjNameBuf, ObjBufSize);
  868. end
  869. else
  870. begin
  871. if (Result = 190) or (Result = 191) then
  872. begin
  873. FillChar (SD, SizeOf (SD), 0);
  874. SD.Length := 24;
  875. SD.Related := ssf_Related_Child;
  876. CommandLine := FExpand (Path); (* Needed for other session types... *)
  877. SD.PgmName := PChar (CommandLine);
  878. if ComLine <> '' then
  879. SD.PgmInputs := PChar (ComLine);
  880. SD.InheritOpt := ssf_InhertOpt_Parent;
  881. Str (GetProcessID, SPID);
  882. Str (ThreadID, STID);
  883. QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
  884. SD.TermQ := @QName [1];
  885. Result := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
  886. if Result = 0 then
  887. begin
  888. Result := DosStartSession (SD, SID, PID);
  889. if (Result = 0) or (Result = 457) then
  890. begin
  891. Result := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
  892. if Result = 0 then
  893. begin
  894. Result := PCI^.Return;
  895. DosCloseQueue (HQ);
  896. DosFreeMem (PCI);
  897. Exit;
  898. end;
  899. end;
  900. DosCloseQueue (HQ);
  901. end;
  902. end
  903. else
  904. ObjName := StrPas (ObjNameBuf);
  905. FreeMem (ObjNameBuf, ObjBufSize);
  906. if ComLine = '' then
  907. CommandLine := Path
  908. else
  909. CommandLine := Path + ' ' + ComLine;
  910. if ObjName = '' then
  911. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, Result])
  912. else
  913. E := EOSError.CreateFmt (SExecuteProcessFailed + '(' + ObjName + ')', [CommandLine, Result]);
  914. E.ErrorCode := Result;
  915. raise E;
  916. end;
  917. end;
  918. function ExecuteProcess (const Path: AnsiString;
  919. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  920. var
  921. CommandLine: AnsiString;
  922. I: integer;
  923. begin
  924. Commandline := '';
  925. for I := 0 to High (ComLine) do
  926. if Pos (' ', ComLine [I]) <> 0 then
  927. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  928. else
  929. CommandLine := CommandLine + ' ' + Comline [I];
  930. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  931. end;
  932. {****************************************************************************
  933. Initialization code
  934. ****************************************************************************}
  935. Initialization
  936. InitExceptions; { Initialize exceptions. OS independent }
  937. InitInternational; { Initialize internationalization settings }
  938. OnBeep:=@SysBeep;
  939. Finalization
  940. DoneExceptions;
  941. end.