sysutils.pp 43 KB

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