sysutils.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for OS/2
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH OUT}
  16. { force ansistrings }
  17. {$H+}
  18. {$DEFINE HAS_SLEEP}
  19. { Include platform independent interface part }
  20. {$i sysutilh.inc}
  21. implementation
  22. uses
  23. sysconst, DosCalls;
  24. type
  25. (* Necessary here due to a different definition of TDateTime in DosCalls. *)
  26. TDateTime = System.TDateTime;
  27. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  28. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  29. {$DEFINE FPC_FEXPAND_GETENV_PCHAR}
  30. { Include platform independent implementation part }
  31. {$i sysutils.inc}
  32. {****************************************************************************
  33. File Functions
  34. ****************************************************************************}
  35. const
  36. ofRead = $0000; {Open for reading}
  37. ofWrite = $0001; {Open for writing}
  38. ofReadWrite = $0002; {Open for reading/writing}
  39. doDenyRW = $0010; {DenyAll (no sharing)}
  40. faCreateNew = $00010000; {Create if file does not exist}
  41. faOpenReplace = $00040000; {Truncate if file exists}
  42. faCreate = $00050000; {Create if file does not exist, truncate otherwise}
  43. FindResvdMask = $00003737; {Allowed bits in attribute
  44. specification for DosFindFirst call.}
  45. function FileOpen (const FileName: string; Mode: integer): THandle;
  46. Var
  47. Handle: THandle;
  48. Rc, Action: cardinal;
  49. begin
  50. (* DenyNone if sharing not specified. *)
  51. if (Mode and 112 = 0) or (Mode and 112 > 64) then
  52. Mode := Mode or 64;
  53. Rc:=Sys_DosOpenL(PChar (FileName), Handle, Action, 0, 0, 1, Mode, nil);
  54. If Rc=0 then
  55. FileOpen:=Handle
  56. else
  57. FileOpen:=feInvalidHandle; //FileOpen:=-RC;
  58. //should return feInvalidHandle(=-1) if fail, other negative returned value are no more errors
  59. end;
  60. function FileCreate (const FileName: string): THandle;
  61. begin
  62. FileCreate := FileCreate (FileName, doDenyRW, 777); (* Sharing to DenyAll *)
  63. end;
  64. function FileCreate (const FileName: string; Rights: integer): THandle;
  65. begin
  66. FileCreate := FileCreate (FileName, doDenyRW, Rights);
  67. (* Sharing to DenyAll *)
  68. end;
  69. function FileCreate (const FileName: string; ShareMode: integer;
  70. Rights: integer): THandle;
  71. var
  72. Handle: THandle;
  73. RC, Action: cardinal;
  74. begin
  75. ShareMode := ShareMode and 112;
  76. (* Sharing to DenyAll as default in case of values not allowed by OS/2. *)
  77. if (ShareMode = 0) or (ShareMode > 64) then
  78. ShareMode := doDenyRW;
  79. RC := Sys_DosOpenL (PChar (FileName), Handle, Action, 0, 0, $12,
  80. faCreate or ofReadWrite or ShareMode, nil);
  81. if RC = 0 then
  82. FileCreate := Handle
  83. else
  84. FileCreate := feInvalidHandle;
  85. End;
  86. function FileRead (Handle: THandle; Out Buffer; Count: longint): longint;
  87. Var
  88. T: cardinal;
  89. begin
  90. DosRead(Handle, Buffer, Count, T);
  91. FileRead := longint (T);
  92. end;
  93. function FileWrite (Handle: THandle; const Buffer; Count: longint): longint;
  94. Var
  95. T: cardinal;
  96. begin
  97. DosWrite (Handle, Buffer, Count, T);
  98. FileWrite := longint (T);
  99. end;
  100. function FileSeek (Handle: THandle; FOffset, Origin: longint): longint;
  101. var
  102. NPos: int64;
  103. begin
  104. if (Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos) = 0)
  105. and (NPos < high (longint)) then
  106. FileSeek:= longint (NPos)
  107. else
  108. FileSeek:=-1;
  109. end;
  110. function FileSeek (Handle: THandle; FOffset: Int64; Origin: Longint): Int64;
  111. var
  112. NPos: int64;
  113. begin
  114. if Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos) = 0 then
  115. FileSeek:= NPos
  116. else
  117. FileSeek:=-1;
  118. end;
  119. procedure FileClose (Handle: THandle);
  120. begin
  121. DosClose(Handle);
  122. end;
  123. function FileTruncate (Handle: THandle; Size: Int64): boolean;
  124. begin
  125. FileTruncate:=Sys_DosSetFileSizeL(Handle, Size)=0;
  126. FileSeek(Handle, 0, 2);
  127. end;
  128. function FileAge (const FileName: string): longint;
  129. var Handle: longint;
  130. begin
  131. Handle := FileOpen (FileName, 0);
  132. if Handle <> -1 then
  133. begin
  134. Result := FileGetDate (Handle);
  135. FileClose (Handle);
  136. end
  137. else
  138. Result := -1;
  139. end;
  140. function FileExists (const FileName: string): boolean;
  141. var
  142. L: longint;
  143. begin
  144. if FileName = '' then
  145. Result := false
  146. else
  147. begin
  148. L := FileGetAttr (FileName);
  149. Result := (L >= 0) and (L and (faDirectory or faVolumeID) = 0);
  150. (* Neither VolumeIDs nor directories are files. *)
  151. end;
  152. end;
  153. type TRec = record
  154. T, D: word;
  155. end;
  156. PSearchRec = ^TSearchRec;
  157. function FindFirst (const Path: string; Attr: longint; out Rslt: TSearchRec): longint;
  158. var SR: PSearchRec;
  159. FStat: PFileFindBuf3L;
  160. Count: cardinal;
  161. Err: cardinal;
  162. I: cardinal;
  163. begin
  164. New (FStat);
  165. Rslt.FindHandle := THandle ($FFFFFFFF);
  166. Count := 1;
  167. if FSApi64 then
  168. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  169. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandardL)
  170. else
  171. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  172. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandard);
  173. if (Err = 0) and (Count = 0) then
  174. Err := 18;
  175. FindFirst := -Err;
  176. if Err = 0 then
  177. begin
  178. Rslt.ExcludeAttr := 0;
  179. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  180. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  181. if FSApi64 then
  182. begin
  183. Rslt.Size := FStat^.FileSize;
  184. Rslt.Name := FStat^.Name;
  185. Rslt.Attr := FStat^.AttrFile;
  186. end
  187. else
  188. begin
  189. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  190. Rslt.Name := PFileFindBuf3 (FStat)^.Name;
  191. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  192. end;
  193. end
  194. else
  195. FindClose(Rslt);
  196. Dispose (FStat);
  197. end;
  198. function FindNext (var Rslt: TSearchRec): longint;
  199. var
  200. SR: PSearchRec;
  201. FStat: PFileFindBuf3L;
  202. Count: cardinal;
  203. Err: cardinal;
  204. begin
  205. New (FStat);
  206. Count := 1;
  207. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^), Count);
  208. if (Err = 0) and (Count = 0) then
  209. Err := 18;
  210. FindNext := -Err;
  211. if Err = 0 then
  212. begin
  213. Rslt.ExcludeAttr := 0;
  214. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  215. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  216. if FSApi64 then
  217. begin
  218. Rslt.Size := FStat^.FileSize;
  219. Rslt.Name := FStat^.Name;
  220. Rslt.Attr := FStat^.AttrFile;
  221. end
  222. else
  223. begin
  224. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  225. Rslt.Name := PFileFindBuf3 (FStat)^.Name;
  226. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  227. end;
  228. end;
  229. Dispose (FStat);
  230. end;
  231. procedure FindClose (var F: TSearchrec);
  232. var
  233. SR: PSearchRec;
  234. begin
  235. DosFindClose (F.FindHandle);
  236. F.FindHandle := 0;
  237. end;
  238. function FileGetDate (Handle: THandle): longint;
  239. var
  240. FStat: TFileStatus3;
  241. Time: Longint;
  242. RC: cardinal;
  243. begin
  244. RC := DosQueryFileInfo(Handle, ilStandard, @FStat, SizeOf(FStat));
  245. if RC = 0 then
  246. begin
  247. Time := FStat.TimeLastWrite + longint (FStat.DateLastWrite) shl 16;
  248. if Time = 0 then
  249. Time := FStat.TimeCreation + longint (FStat.DateCreation) shl 16;
  250. end else
  251. Time:=0;
  252. FileGetDate:=Time;
  253. end;
  254. function FileSetDate (Handle: THandle; Age: longint): longint;
  255. var
  256. FStat: PFileStatus3;
  257. RC: cardinal;
  258. begin
  259. New (FStat);
  260. RC := DosQueryFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^));
  261. if RC <> 0 then
  262. FileSetDate := -1
  263. else
  264. begin
  265. FStat^.DateLastAccess := Hi (Age);
  266. FStat^.DateLastWrite := Hi (Age);
  267. FStat^.TimeLastAccess := Lo (Age);
  268. FStat^.TimeLastWrite := Lo (Age);
  269. RC := DosSetFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^));
  270. if RC <> 0 then
  271. FileSetDate := -1
  272. else
  273. FileSetDate := 0;
  274. end;
  275. Dispose (FStat);
  276. end;
  277. function FileGetAttr (const FileName: string): longint;
  278. var
  279. FS: PFileStatus3;
  280. begin
  281. New(FS);
  282. Result:=-DosQueryPathInfo(PChar (FileName), ilStandard, FS, SizeOf(FS^));
  283. If Result=0 Then Result:=FS^.attrFile;
  284. Dispose(FS);
  285. end;
  286. function FileSetAttr (const Filename: string; Attr: longint): longint;
  287. Var
  288. FS: PFileStatus3;
  289. Begin
  290. New(FS);
  291. FillChar(FS, SizeOf(FS^), 0);
  292. FS^.AttrFile:=Attr;
  293. Result:=-DosSetPathInfo(PChar (FileName), ilStandard, FS, SizeOf(FS^), 0);
  294. Dispose(FS);
  295. end;
  296. function DeleteFile (const FileName: string): boolean;
  297. Begin
  298. Result:=(DosDelete(PChar (FileName))=0);
  299. End;
  300. function RenameFile (const OldName, NewName: string): boolean;
  301. Begin
  302. Result:=(DosMove(PChar (OldName), PChar (NewName))=0);
  303. End;
  304. {****************************************************************************
  305. Disk Functions
  306. ****************************************************************************}
  307. function DiskFree (Drive: byte): int64;
  308. var FI: TFSinfo;
  309. RC: cardinal;
  310. begin
  311. {In OS/2, we use the filesystem information.}
  312. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  313. if RC = 0 then
  314. DiskFree := int64 (FI.Free_Clusters) *
  315. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  316. else
  317. DiskFree := -1;
  318. end;
  319. function DiskSize (Drive: byte): int64;
  320. var FI: TFSinfo;
  321. RC: cardinal;
  322. begin
  323. {In OS/2, we use the filesystem information.}
  324. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  325. if RC = 0 then
  326. DiskSize := int64 (FI.Total_Clusters) *
  327. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  328. else
  329. DiskSize := -1;
  330. end;
  331. function GetCurrentDir: string;
  332. begin
  333. GetDir (0, Result);
  334. end;
  335. function SetCurrentDir (const NewDir: string): boolean;
  336. var
  337. OrigInOutRes: word;
  338. begin
  339. OrigInOutRes := InOutRes;
  340. InOutRes := 0;
  341. {$I-}
  342. ChDir (NewDir);
  343. Result := InOutRes = 0;
  344. {$I+}
  345. InOutRes := OrigInOutRes;
  346. end;
  347. function CreateDir (const NewDir: string): boolean;
  348. var
  349. OrigInOutRes: word;
  350. begin
  351. OrigInOutRes := InOutRes;
  352. InOutRes := 0;
  353. {$I-}
  354. MkDir (NewDir);
  355. Result := InOutRes = 0;
  356. {$I+}
  357. InOutRes := OrigInOutRes;
  358. end;
  359. function RemoveDir (const Dir: string): boolean;
  360. var
  361. OrigInOutRes: word;
  362. begin
  363. OrigInOutRes := InOutRes;
  364. InOutRes := 0;
  365. {$I-}
  366. RmDir (Dir);
  367. Result := InOutRes = 0;
  368. {$I+}
  369. InOutRes := OrigInOutRes;
  370. end;
  371. function DirectoryExists (const Directory: string): boolean;
  372. var
  373. L: longint;
  374. begin
  375. if Directory = '' then
  376. Result := false
  377. else
  378. begin
  379. if ((Length (Directory) = 2) or
  380. (Length (Directory) = 3) and
  381. (Directory [3] in AllowDirectorySeparators)) and
  382. (Directory [2] in AllowDriveSeparators) and
  383. (UpCase (Directory [1]) in ['A'..'Z']) then
  384. (* Checking attributes for 'x:' is not possible but for 'x:.' it is. *)
  385. L := FileGetAttr (Directory + '.')
  386. else if (Directory [Length (Directory)] in AllowDirectorySeparators) and
  387. (Length (Directory) > 1) and
  388. (* Do not remove '\' in '\\' (invalid path, possibly broken UNC path). *)
  389. not (Directory [Length (Directory) - 1] in AllowDirectorySeparators) then
  390. L := FileGetAttr (Copy (Directory, 1, Length (Directory) - 1))
  391. else
  392. L := FileGetAttr (Directory);
  393. Result := (L > 0) and (L and faDirectory = faDirectory);
  394. end;
  395. end;
  396. {****************************************************************************
  397. Time Functions
  398. ****************************************************************************}
  399. procedure GetLocalTime (var SystemTime: TSystemTime);
  400. var
  401. DT: DosCalls.TDateTime;
  402. begin
  403. DosGetDateTime(DT);
  404. with SystemTime do
  405. begin
  406. Year:=DT.Year;
  407. Month:=DT.Month;
  408. Day:=DT.Day;
  409. Hour:=DT.Hour;
  410. Minute:=DT.Minute;
  411. Second:=DT.Second;
  412. MilliSecond:=DT.Sec100;
  413. end;
  414. end;
  415. {****************************************************************************
  416. Misc Functions
  417. ****************************************************************************}
  418. procedure sysbeep;
  419. begin
  420. // Maybe implement later on ?
  421. end;
  422. {****************************************************************************
  423. Locale Functions
  424. ****************************************************************************}
  425. procedure InitAnsi;
  426. var I: byte;
  427. Country: TCountryCode;
  428. begin
  429. for I := 0 to 255 do
  430. UpperCaseTable [I] := Chr (I);
  431. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  432. FillChar (Country, SizeOf (Country), 0);
  433. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  434. for I := 0 to 255 do
  435. if UpperCaseTable [I] <> Chr (I) then
  436. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  437. end;
  438. procedure InitInternational;
  439. var Country: TCountryCode;
  440. CtryInfo: TCountryInfo;
  441. Size: cardinal;
  442. RC: cardinal;
  443. begin
  444. Size := 0;
  445. FillChar (Country, SizeOf (Country), 0);
  446. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  447. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  448. if RC = 0 then
  449. begin
  450. DateSeparator := CtryInfo.DateSeparator;
  451. case CtryInfo.DateFormat of
  452. 1: begin
  453. ShortDateFormat := 'd/m/y';
  454. LongDateFormat := 'dd" "mmmm" "yyyy';
  455. end;
  456. 2: begin
  457. ShortDateFormat := 'y/m/d';
  458. LongDateFormat := 'yyyy" "mmmm" "dd';
  459. end;
  460. 3: begin
  461. ShortDateFormat := 'm/d/y';
  462. LongDateFormat := 'mmmm" "dd" "yyyy';
  463. end;
  464. end;
  465. TimeSeparator := CtryInfo.TimeSeparator;
  466. DecimalSeparator := CtryInfo.DecimalSeparator;
  467. ThousandSeparator := CtryInfo.ThousandSeparator;
  468. CurrencyFormat := CtryInfo.CurrencyFormat;
  469. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  470. end;
  471. InitAnsi;
  472. InitInternationalGeneric;
  473. end;
  474. function SysErrorMessage(ErrorCode: Integer): String;
  475. begin
  476. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  477. end;
  478. {****************************************************************************
  479. OS Utils
  480. ****************************************************************************}
  481. function GetEnvPChar (EnvVar: shortstring): PChar;
  482. (* The assembler version is more than three times as fast as Pascal. *)
  483. var
  484. P: PChar;
  485. begin
  486. EnvVar := UpCase (EnvVar);
  487. {$ASMMODE INTEL}
  488. asm
  489. cld
  490. mov edi, Environment
  491. lea esi, EnvVar
  492. xor eax, eax
  493. lodsb
  494. @NewVar:
  495. cmp byte ptr [edi], 0
  496. jz @Stop
  497. push eax { eax contains length of searched variable name }
  498. push esi { esi points to the beginning of the variable name }
  499. mov ecx, -1 { our character ('=' - see below) _must_ be found }
  500. mov edx, edi { pointer to beginning of variable name saved in edx }
  501. mov al, '=' { searching until '=' (end of variable name) }
  502. repne
  503. scasb { scan until '=' not found }
  504. neg ecx { what was the name length? }
  505. dec ecx { corrected }
  506. dec ecx { exclude the '=' character }
  507. pop esi { restore pointer to beginning of variable name }
  508. pop eax { restore length of searched variable name }
  509. push eax { and save both of them again for later use }
  510. push esi
  511. cmp ecx, eax { compare length of searched variable name with name }
  512. jnz @NotEqual { ... of currently found variable, jump if different }
  513. xchg edx, edi { pointer to current variable name restored in edi }
  514. repe
  515. cmpsb { compare till the end of variable name }
  516. xchg edx, edi { pointer to beginning of variable contents in edi }
  517. jz @Equal { finish if they're equal }
  518. @NotEqual:
  519. xor eax, eax { look for 00h }
  520. mov ecx, -1 { it _must_ be found }
  521. repne
  522. scasb { scan until found }
  523. pop esi { restore pointer to beginning of variable name }
  524. pop eax { restore length of searched variable name }
  525. jmp @NewVar { ... or continue with new variable otherwise }
  526. @Stop:
  527. xor eax, eax
  528. mov P, eax { Not found - return nil }
  529. jmp @End
  530. @Equal:
  531. pop esi { restore the stack position }
  532. pop eax
  533. mov P, edi { place pointer to variable contents in P }
  534. @End:
  535. end ['eax','ecx','edx','esi','edi'];
  536. GetEnvPChar := P;
  537. end;
  538. {$ASMMODE ATT}
  539. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  540. begin
  541. GetEnvironmentVariable := StrPas (GetEnvPChar (EnvVar));
  542. end;
  543. Function GetEnvironmentVariableCount : Integer;
  544. begin
  545. (* Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
  546. GetEnvironmentVariableCount := EnvC;
  547. end;
  548. Function GetEnvironmentString(Index : Integer) : String;
  549. begin
  550. Result:=FPCGetEnvStrFromP (EnvP, Index);
  551. end;
  552. procedure Sleep (Milliseconds: cardinal);
  553. begin
  554. DosSleep (Milliseconds);
  555. end;
  556. function ExecuteProcess (const Path: AnsiString; const ComLine: AnsiString;Flags:TExecuteFlags=[]):
  557. integer;
  558. var
  559. E: EOSError;
  560. CommandLine: ansistring;
  561. Args0, Args: DosCalls.PByteArray;
  562. ObjNameBuf: PChar;
  563. ArgSize: word;
  564. Res: TResultCodes;
  565. ObjName: shortstring;
  566. RC: cardinal;
  567. ExecAppType: cardinal;
  568. const
  569. MaxArgsSize = 3072; (* Amount of memory reserved for arguments in bytes. *)
  570. ObjBufSize = 512;
  571. function StartSession: cardinal;
  572. var
  573. HQ: THandle;
  574. SPID, STID, QName: shortstring;
  575. SID, PID: cardinal;
  576. SD: TStartData;
  577. RD: TRequestData;
  578. PCI: PChildInfo;
  579. CISize: cardinal;
  580. Prio: byte;
  581. begin
  582. Result := $FFFFFFFF;
  583. FillChar (SD, SizeOf (SD), 0);
  584. SD.Length := SizeOf (SD);
  585. SD.Related := ssf_Related_Child;
  586. if FileExists (Path) then
  587. (* Full path necessary for starting different executable files from current *)
  588. (* directory. *)
  589. CommandLine := ExpandFileName (Path)
  590. else
  591. CommandLine := Path;
  592. SD.PgmName := PChar (CommandLine);
  593. if ComLine <> '' then
  594. SD.PgmInputs := PChar (ComLine);
  595. if ExecInheritsHandles in Flags then
  596. SD.InheritOpt := ssf_InhertOpt_Parent;
  597. Str (GetProcessID, SPID);
  598. Str (ThreadID, STID);
  599. QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
  600. SD.TermQ := @QName [1];
  601. SD.ObjectBuffer := ObjNameBuf;
  602. SD.ObjectBuffLen := ObjBufSize;
  603. RC := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
  604. if RC <> 0 then
  605. Move (QName [1], ObjNameBuf^, Length (QName))
  606. else
  607. begin
  608. RC := DosStartSession (SD, SID, PID);
  609. if (RC = 0) or (RC = 457) then
  610. begin
  611. RC := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
  612. if RC = 0 then
  613. begin
  614. Result := PCI^.Return;
  615. DosCloseQueue (HQ);
  616. DosFreeMem (PCI);
  617. FreeMem (ObjNameBuf, ObjBufSize);
  618. end
  619. else
  620. DosCloseQueue (HQ);
  621. end
  622. else
  623. DosCloseQueue (HQ);
  624. end;
  625. end;
  626. begin
  627. Result := integer ($FFFFFFFF);
  628. ObjName := '';
  629. GetMem (ObjNameBuf, ObjBufSize);
  630. FillChar (ObjNameBuf^, ObjBufSize, 0);
  631. if (DosQueryAppType (PChar (Path), ExecAppType) = 0) and
  632. (ApplicationType and 3 = ExecAppType and 3) then
  633. (* DosExecPgm should work... *)
  634. begin
  635. if ComLine = '' then
  636. begin
  637. Args0 := nil;
  638. Args := nil;
  639. end
  640. else
  641. begin
  642. GetMem (Args0, MaxArgsSize);
  643. Args := Args0;
  644. (* Work around a bug in OS/2 - argument to DosExecPgm *)
  645. (* should not cross 64K boundary. *)
  646. if ((PtrUInt (Args) + 1024) and $FFFF) < 1024 then
  647. Inc (pointer (Args), 1024);
  648. ArgSize := 0;
  649. Move (Path [1], Args^ [ArgSize], Length (Path));
  650. Inc (ArgSize, Length (Path));
  651. Args^ [ArgSize] := 0;
  652. Inc (ArgSize);
  653. {Now do the real arguments.}
  654. Move (ComLine [1], Args^ [ArgSize], Length (ComLine));
  655. Inc (ArgSize, Length (ComLine));
  656. Args^ [ArgSize] := 0;
  657. Inc (ArgSize);
  658. Args^ [ArgSize] := 0;
  659. end;
  660. Res.ExitCode := $FFFFFFFF;
  661. RC := DosExecPgm (ObjNameBuf, ObjBufSize, 0, Args, nil, Res, PChar (Path));
  662. if Args0 <> nil then
  663. FreeMem (Args0, MaxArgsSize);
  664. if RC = 0 then
  665. begin
  666. Result := Res.ExitCode;
  667. FreeMem (ObjNameBuf, ObjBufSize);
  668. end
  669. else
  670. begin
  671. if (RC = 190) or (RC = 191) then
  672. Result := StartSession;
  673. end;
  674. end
  675. else
  676. Result := StartSession;
  677. if RC <> 0 then
  678. begin
  679. ObjName := StrPas (ObjNameBuf);
  680. FreeMem (ObjNameBuf, ObjBufSize);
  681. if ComLine = '' then
  682. CommandLine := Path
  683. else
  684. CommandLine := Path + ' ' + ComLine;
  685. if ObjName = '' then
  686. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, RC])
  687. else
  688. E := EOSError.CreateFmt (SExecuteProcessFailed + ' (' + ObjName + ')', [CommandLine, RC]);
  689. E.ErrorCode := Result;
  690. raise E;
  691. end;
  692. end;
  693. function ExecuteProcess (const Path: AnsiString;
  694. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  695. var
  696. CommandLine: AnsiString;
  697. I: integer;
  698. begin
  699. Commandline := '';
  700. for I := 0 to High (ComLine) do
  701. if Pos (' ', ComLine [I]) <> 0 then
  702. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  703. else
  704. CommandLine := CommandLine + ' ' + Comline [I];
  705. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  706. end;
  707. {****************************************************************************
  708. Initialization code
  709. ****************************************************************************}
  710. Initialization
  711. InitExceptions; { Initialize exceptions. OS independent }
  712. InitInternational; { Initialize internationalization settings }
  713. OnBeep:=@SysBeep;
  714. Finalization
  715. DoneExceptions;
  716. end.