sysutils.pp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345
  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. var
  560. L: longint;
  561. begin
  562. if FileName = '' then
  563. Result := false
  564. else
  565. begin
  566. L := FileGetAttr (FileName);
  567. Result := (L >= 0) and (L and (faDirectory or faVolumeID) = 0);
  568. (* Neither VolumeIDs nor directories are files. *)
  569. end;
  570. end;
  571. type
  572. TRec = record
  573. T, D: word;
  574. end;
  575. PSearchRec = ^SearchRec;
  576. function FindFirst (const Path: string; Attr: longint; out Rslt: TSearchRec): longint;
  577. var
  578. SR: PSearchRec;
  579. FStat: PFileFindBuf3L;
  580. Count: cardinal;
  581. Err: cardinal;
  582. begin
  583. if os_mode = osOS2 then
  584. begin
  585. New (FStat);
  586. Rslt.FindHandle := THandle ($FFFFFFFF);
  587. Count := 1;
  588. if FSApi64 then
  589. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  590. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandardL)
  591. else
  592. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  593. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandard);
  594. if (Err = 0) and (Count = 0) then
  595. Err := 18;
  596. FindFirst := -Err;
  597. if Err = 0 then
  598. begin
  599. Rslt.ExcludeAttr := 0;
  600. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  601. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  602. if FSApi64 then
  603. begin
  604. Rslt.Size := FStat^.FileSize;
  605. Rslt.Name := FStat^.Name;
  606. Rslt.Attr := FStat^.AttrFile;
  607. end
  608. else
  609. begin
  610. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  611. Rslt.Name := PFileFindBuf3 (FStat)^.Name;
  612. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  613. end;
  614. end
  615. else
  616. FindClose (Rslt);
  617. Dispose (FStat);
  618. end
  619. else
  620. begin
  621. Err := DOS.DosError;
  622. GetMem (SR, SizeOf (SearchRec));
  623. Rslt.FindHandle := longint(SR);
  624. DOS.FindFirst (Path, Attr, SR^);
  625. FindFirst := -DOS.DosError;
  626. if DosError = 0 then
  627. begin
  628. Rslt.Time := SR^.Time;
  629. (* Extend the supported file sizes from 2 GB to 4 GB at least. *)
  630. Rslt.Size := cardinal (SR^.Size);
  631. Rslt.Attr := SR^.Attr;
  632. Rslt.ExcludeAttr := 0;
  633. Rslt.Name := SR^.Name;
  634. end;
  635. DOS.DosError := Err;
  636. end;
  637. end;
  638. function FindNext (var Rslt: TSearchRec): longint;
  639. var
  640. SR: PSearchRec;
  641. FStat: PFileFindBuf3L;
  642. Count: cardinal;
  643. Err: cardinal;
  644. begin
  645. if os_mode = osOS2 then
  646. begin
  647. New (FStat);
  648. Count := 1;
  649. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^), Count);
  650. if (Err = 0) and (Count = 0) then
  651. Err := 18;
  652. FindNext := -Err;
  653. if Err = 0 then
  654. begin
  655. Rslt.ExcludeAttr := 0;
  656. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  657. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  658. if FSApi64 then
  659. begin
  660. Rslt.Size := FStat^.FileSize;
  661. Rslt.Name := FStat^.Name;
  662. Rslt.Attr := FStat^.AttrFile;
  663. end
  664. else
  665. begin
  666. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  667. Rslt.Name := PFileFindBuf3 (FStat)^.Name;
  668. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  669. end;
  670. end;
  671. Dispose (FStat);
  672. end
  673. else
  674. begin
  675. SR := PSearchRec (Rslt.FindHandle);
  676. if SR <> nil then
  677. begin
  678. DOS.FindNext (SR^);
  679. FindNext := -DosError;
  680. if DosError = 0 then
  681. begin
  682. Rslt.Time := SR^.Time;
  683. (* Extend the supported file sizes from 2 GB to 4 GB at least. *)
  684. Rslt.Size := cardinal (SR^.Size);
  685. Rslt.Attr := SR^.Attr;
  686. Rslt.ExcludeAttr := 0;
  687. Rslt.Name := SR^.Name;
  688. end;
  689. end;
  690. end;
  691. end;
  692. procedure FindClose (var F: TSearchrec);
  693. var SR: PSearchRec;
  694. begin
  695. if os_mode = osOS2 then
  696. begin
  697. DosFindClose (F.FindHandle);
  698. end
  699. else
  700. begin
  701. SR := PSearchRec (F.FindHandle);
  702. DOS.FindClose (SR^);
  703. FreeMem (SR, SizeOf (SearchRec));
  704. end;
  705. F.FindHandle := 0;
  706. end;
  707. function FileGetDate (Handle: longint): longint; assembler;
  708. asm
  709. push ebx
  710. {$IFDEF REGCALL}
  711. mov ebx, eax
  712. {$ELSE REGCALL}
  713. mov ebx, Handle
  714. {$ENDIF REGCALL}
  715. mov ax, 5700h
  716. call syscall
  717. mov eax, -1
  718. jc @FGetDateEnd
  719. mov ax, dx
  720. shld eax, ecx, 16
  721. @FGetDateEnd:
  722. pop ebx
  723. end {['eax', 'ebx', 'ecx', 'edx']};
  724. function FileSetDate (Handle, Age: longint): longint;
  725. var FStat: PFileStatus3;
  726. RC: cardinal;
  727. begin
  728. if os_mode = osOS2 then
  729. begin
  730. New (FStat);
  731. RC := DosQueryFileInfo (Handle, ilStandard, FStat,
  732. SizeOf (FStat^));
  733. if RC <> 0 then
  734. FileSetDate := -1
  735. else
  736. begin
  737. FStat^.DateLastAccess := Hi (Age);
  738. FStat^.DateLastWrite := Hi (Age);
  739. FStat^.TimeLastAccess := Lo (Age);
  740. FStat^.TimeLastWrite := Lo (Age);
  741. RC := DosSetFileInfo (Handle, ilStandard, FStat,
  742. SizeOf (FStat^));
  743. if RC <> 0 then
  744. FileSetDate := -1
  745. else
  746. FileSetDate := 0;
  747. end;
  748. Dispose (FStat);
  749. end
  750. else
  751. asm
  752. push ebx
  753. mov ax, 5701h
  754. mov ebx, Handle
  755. mov cx, word ptr [Age]
  756. mov dx, word ptr [Age + 2]
  757. call syscall
  758. jnc @FSetDateEnd
  759. mov eax, -1
  760. @FSetDateEnd:
  761. mov Result, eax
  762. pop ebx
  763. end ['eax', 'ecx', 'edx'];
  764. end;
  765. function FileGetAttr (const FileName: string): longint; assembler;
  766. asm
  767. {$IFDEF REGCALL}
  768. mov edx, eax
  769. {$ELSE REGCALL}
  770. mov edx, FileName
  771. {$ENDIF REGCALL}
  772. mov ax, 4300h
  773. call syscall
  774. jnc @FGetAttrEnd
  775. mov eax, -1
  776. @FGetAttrEnd:
  777. end {['eax', 'edx']};
  778. function FileSetAttr (const Filename: string; Attr: longint): longint; assembler;
  779. asm
  780. {$IFDEF REGCALL}
  781. mov ecx, edx
  782. mov edx, eax
  783. {$ELSE REGCALL}
  784. mov ecx, Attr
  785. mov edx, FileName
  786. {$ENDIF REGCALL}
  787. mov ax, 4301h
  788. call syscall
  789. mov eax, 0
  790. jnc @FSetAttrEnd
  791. mov eax, -1
  792. @FSetAttrEnd:
  793. end {['eax', 'ecx', 'edx']};
  794. function DeleteFile (const FileName: string): boolean; assembler;
  795. asm
  796. {$IFDEF REGCALL}
  797. mov edx, eax
  798. {$ELSE REGCALL}
  799. mov edx, FileName
  800. {$ENDIF REGCALL}
  801. mov ax, 4100h
  802. call syscall
  803. mov eax, 0
  804. jc @FDeleteEnd
  805. inc eax
  806. @FDeleteEnd:
  807. end {['eax', 'edx']};
  808. function RenameFile (const OldName, NewName: string): boolean; assembler;
  809. asm
  810. push edi
  811. {$IFDEF REGCALL}
  812. mov edx, eax
  813. mov edi, edx
  814. {$ELSE REGCALL}
  815. mov edx, OldName
  816. mov edi, NewName
  817. {$ENDIF REGCALL}
  818. mov ax, 5600h
  819. call syscall
  820. mov eax, 0
  821. jc @FRenameEnd
  822. inc eax
  823. @FRenameEnd:
  824. pop edi
  825. end {['eax', 'edx', 'edi']};
  826. {****************************************************************************
  827. Disk Functions
  828. ****************************************************************************}
  829. {$ASMMODE ATT}
  830. function DiskFree (Drive: byte): int64;
  831. var FI: TFSinfo;
  832. RC: cardinal;
  833. begin
  834. if (os_mode = osDOS) or (os_mode = osDPMI) then
  835. {Function 36 is not supported in OS/2.}
  836. asm
  837. pushl %ebx
  838. movb Drive,%dl
  839. movb $0x36,%ah
  840. call syscall
  841. cmpw $-1,%ax
  842. je .LDISKFREE1
  843. mulw %cx
  844. mulw %bx
  845. shll $16,%edx
  846. movw %ax,%dx
  847. movl $0,%eax
  848. xchgl %edx,%eax
  849. jmp .LDISKFREE2
  850. .LDISKFREE1:
  851. cltd
  852. .LDISKFREE2:
  853. popl %ebx
  854. leave
  855. ret
  856. end
  857. else
  858. {In OS/2, we use the filesystem information.}
  859. begin
  860. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  861. if RC = 0 then
  862. DiskFree := int64 (FI.Free_Clusters) *
  863. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  864. else
  865. DiskFree := -1;
  866. end;
  867. end;
  868. function DiskSize (Drive: byte): int64;
  869. var FI: TFSinfo;
  870. RC: cardinal;
  871. begin
  872. if (os_mode = osDOS) or (os_mode = osDPMI) then
  873. {Function 36 is not supported in OS/2.}
  874. asm
  875. pushl %ebx
  876. movb Drive,%dl
  877. movb $0x36,%ah
  878. call syscall
  879. movw %dx,%bx
  880. cmpw $-1,%ax
  881. je .LDISKSIZE1
  882. mulw %cx
  883. mulw %bx
  884. shll $16,%edx
  885. movw %ax,%dx
  886. movl $0,%eax
  887. xchgl %edx,%eax
  888. jmp .LDISKSIZE2
  889. .LDISKSIZE1:
  890. cltd
  891. .LDISKSIZE2:
  892. popl %ebx
  893. leave
  894. ret
  895. end
  896. else
  897. {In OS/2, we use the filesystem information.}
  898. begin
  899. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  900. if RC = 0 then
  901. DiskSize := int64 (FI.Total_Clusters) *
  902. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  903. else
  904. DiskSize := -1;
  905. end;
  906. end;
  907. function GetCurrentDir: string;
  908. begin
  909. GetDir (0, Result);
  910. end;
  911. function SetCurrentDir (const NewDir: string): boolean;
  912. begin
  913. {$I-}
  914. ChDir (NewDir);
  915. Result := (IOResult = 0);
  916. {$I+}
  917. end;
  918. function CreateDir (const NewDir: string): boolean;
  919. begin
  920. {$I-}
  921. MkDir (NewDir);
  922. Result := (IOResult = 0);
  923. {$I+}
  924. end;
  925. function RemoveDir (const Dir: string): boolean;
  926. begin
  927. {$I-}
  928. RmDir (Dir);
  929. Result := (IOResult = 0);
  930. {$I+}
  931. end;
  932. function DirectoryExists (const Directory: string): boolean;
  933. var
  934. L: longint;
  935. begin
  936. if Directory = '' then
  937. Result := false
  938. else
  939. begin
  940. if ((Length (Directory) = 2) or
  941. (Length (Directory) = 3) and
  942. (Directory [3] in AllowDirectorySeparators)) and
  943. (Directory [2] in AllowDriveSeparators) and
  944. (UpCase (Directory [1]) in ['A'..'Z']) then
  945. (* Checking attributes for 'x:' is not possible but for 'x:.' it is. *)
  946. L := FileGetAttr (Directory + '.')
  947. else if (Directory [Length (Directory)] in AllowDirectorySeparators) and
  948. (Length (Directory) > 1) and
  949. (* Do not remove '\' in '\\' (invalid path, possibly broken UNC path). *)
  950. not (Directory [Length (Directory) - 1] in AllowDirectorySeparators) then
  951. L := FileGetAttr (Copy (Directory, 1, Length (Directory) - 1))
  952. else
  953. L := FileGetAttr (Directory);
  954. Result := (L > 0) and (L and faDirectory = faDirectory);
  955. end;
  956. end;
  957. {****************************************************************************
  958. Time Functions
  959. ****************************************************************************}
  960. {$ASMMODE INTEL}
  961. procedure GetLocalTime (var SystemTime: TSystemTime); assembler;
  962. asm
  963. (* Expects the default record alignment (word)!!! *)
  964. push edi
  965. {$IFDEF REGCALL}
  966. push eax
  967. {$ENDIF REGCALL}
  968. mov ah, 2Ah
  969. call syscall
  970. {$IFDEF REGCALL}
  971. pop eax
  972. {$ELSE REGCALL}
  973. mov edi, SystemTime
  974. {$ENDIF REGCALL}
  975. mov ax, cx
  976. stosw
  977. xor eax, eax
  978. mov al, 10
  979. mul dl
  980. shl eax, 16
  981. mov al, dh
  982. stosd
  983. push edi
  984. mov ah, 2Ch
  985. call syscall
  986. pop edi
  987. xor eax, eax
  988. mov al, cl
  989. shl eax, 16
  990. mov al, ch
  991. stosd
  992. mov al, dl
  993. shl eax, 16
  994. mov al, dh
  995. stosd
  996. pop edi
  997. end {['eax', 'ecx', 'edx', 'edi']};
  998. {$asmmode default}
  999. {****************************************************************************
  1000. Misc Functions
  1001. ****************************************************************************}
  1002. procedure Beep;
  1003. begin
  1004. end;
  1005. {****************************************************************************
  1006. Locale Functions
  1007. ****************************************************************************}
  1008. procedure InitAnsi;
  1009. var I: byte;
  1010. Country: TCountryCode;
  1011. begin
  1012. for I := 0 to 255 do
  1013. UpperCaseTable [I] := Chr (I);
  1014. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  1015. if os_mode = osOS2 then
  1016. begin
  1017. FillChar (Country, SizeOf (Country), 0);
  1018. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  1019. end
  1020. else
  1021. begin
  1022. (* !!! TODO: DOS/DPMI mode support!!! *)
  1023. end;
  1024. for I := 0 to 255 do
  1025. if UpperCaseTable [I] <> Chr (I) then
  1026. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  1027. end;
  1028. procedure InitInternational;
  1029. var Country: TCountryCode;
  1030. CtryInfo: TCountryInfo;
  1031. Size: cardinal;
  1032. RC: cardinal;
  1033. begin
  1034. Size := 0;
  1035. FillChar (Country, SizeOf (Country), 0);
  1036. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  1037. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  1038. if RC = 0 then
  1039. begin
  1040. DateSeparator := CtryInfo.DateSeparator;
  1041. case CtryInfo.DateFormat of
  1042. 1: begin
  1043. ShortDateFormat := 'd/m/y';
  1044. LongDateFormat := 'dd" "mmmm" "yyyy';
  1045. end;
  1046. 2: begin
  1047. ShortDateFormat := 'y/m/d';
  1048. LongDateFormat := 'yyyy" "mmmm" "dd';
  1049. end;
  1050. 3: begin
  1051. ShortDateFormat := 'm/d/y';
  1052. LongDateFormat := 'mmmm" "dd" "yyyy';
  1053. end;
  1054. end;
  1055. TimeSeparator := CtryInfo.TimeSeparator;
  1056. DecimalSeparator := CtryInfo.DecimalSeparator;
  1057. ThousandSeparator := CtryInfo.ThousandSeparator;
  1058. CurrencyFormat := CtryInfo.CurrencyFormat;
  1059. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  1060. end;
  1061. InitAnsi;
  1062. InitInternationalGeneric;
  1063. end;
  1064. function SysErrorMessage(ErrorCode: Integer): String;
  1065. begin
  1066. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  1067. end;
  1068. {****************************************************************************
  1069. OS Utils
  1070. ****************************************************************************}
  1071. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  1072. begin
  1073. GetEnvironmentVariable := StrPas (GetEnvPChar (EnvVar));
  1074. end;
  1075. Function GetEnvironmentVariableCount : Integer;
  1076. begin
  1077. (* Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
  1078. GetEnvironmentVariableCount := EnvC;
  1079. end;
  1080. Function GetEnvironmentString(Index : Integer) : String;
  1081. begin
  1082. Result:=FPCGetEnvStrFromP (EnvP, Index);
  1083. end;
  1084. {$ASMMODE INTEL}
  1085. procedure Sleep (Milliseconds: cardinal);
  1086. begin
  1087. if os_mode = osOS2 then DosSleep (Milliseconds) else
  1088. asm
  1089. mov edx, Milliseconds
  1090. mov eax, 7F30h
  1091. call syscall
  1092. end ['eax', 'edx'];
  1093. end;
  1094. {$ASMMODE DEFAULT}
  1095. function ExecuteProcess (const Path: AnsiString; const ComLine: AnsiString;Flags:TExecuteFlags=[]):
  1096. integer;
  1097. var
  1098. HQ: THandle;
  1099. SPID, STID, QName: shortstring;
  1100. SD: TStartData;
  1101. SID, PID: cardinal;
  1102. RD: TRequestData;
  1103. PCI: PChildInfo;
  1104. CISize: cardinal;
  1105. Prio: byte;
  1106. E: EOSError;
  1107. CommandLine: ansistring;
  1108. begin
  1109. if os_Mode = osOS2 then
  1110. begin
  1111. FillChar (SD, SizeOf (SD), 0);
  1112. SD.Length := 24;
  1113. SD.Related := ssf_Related_Child;
  1114. SD.PgmName := PChar (Path);
  1115. SD.PgmInputs := PChar (ComLine);
  1116. Str (GetProcessID, SPID);
  1117. Str (ThreadID, STID);
  1118. QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
  1119. SD.TermQ := @QName [1];
  1120. Result := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
  1121. if Result = 0 then
  1122. begin
  1123. Result := DosStartSession (SD, SID, PID);
  1124. if (Result = 0) or (Result = 457) then
  1125. begin
  1126. Result := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
  1127. if Result = 0 then
  1128. begin
  1129. Result := PCI^.Return;
  1130. DosCloseQueue (HQ);
  1131. DosFreeMem (PCI);
  1132. Exit;
  1133. end;
  1134. end;
  1135. DosCloseQueue (HQ);
  1136. end;
  1137. if ComLine = '' then
  1138. CommandLine := Path
  1139. else
  1140. CommandLine := Path + ' ' + ComLine;
  1141. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, Result]);
  1142. E.ErrorCode := Result;
  1143. raise E;
  1144. end else
  1145. begin
  1146. Dos.Exec (Path, ComLine);
  1147. if DosError <> 0 then
  1148. begin
  1149. if ComLine = '' then
  1150. CommandLine := Path
  1151. else
  1152. CommandLine := Path + ' ' + ComLine;
  1153. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, DosError]);
  1154. E.ErrorCode := DosError;
  1155. raise E;
  1156. end;
  1157. ExecuteProcess := DosExitCode;
  1158. end;
  1159. end;
  1160. function ExecuteProcess (const Path: AnsiString;
  1161. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  1162. var
  1163. CommandLine: AnsiString;
  1164. I: integer;
  1165. begin
  1166. Commandline := '';
  1167. for I := 0 to High (ComLine) do
  1168. if Pos (' ', ComLine [I]) <> 0 then
  1169. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  1170. else
  1171. CommandLine := CommandLine + ' ' + Comline [I];
  1172. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  1173. end;
  1174. {****************************************************************************
  1175. Initialization code
  1176. ****************************************************************************}
  1177. Initialization
  1178. InitExceptions; { Initialize exceptions. OS independent }
  1179. InitInternational; { Initialize internationalization settings }
  1180. Finalization
  1181. DoneExceptions;
  1182. end.