2
0

sysutils.pp 37 KB

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