sysutils.pp 41 KB

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