sysutils.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  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. begin
  142. if FileName = '' then
  143. Result := false
  144. else
  145. Result := FileGetAttr (ExpandFileName (FileName)) and
  146. (faDirectory or faVolumeID) = 0;
  147. (* Neither VolumeIDs nor directories are files. *)
  148. end;
  149. type TRec = record
  150. T, D: word;
  151. end;
  152. PSearchRec = ^TSearchRec;
  153. function FindFirst (const Path: string; Attr: longint; out Rslt: TSearchRec): longint;
  154. var SR: PSearchRec;
  155. FStat: PFileFindBuf3L;
  156. Count: cardinal;
  157. Err: cardinal;
  158. I: cardinal;
  159. begin
  160. New (FStat);
  161. Rslt.FindHandle := THandle ($FFFFFFFF);
  162. Count := 1;
  163. if FSApi64 then
  164. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  165. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandardL)
  166. else
  167. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  168. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandard);
  169. if (Err = 0) and (Count = 0) then
  170. Err := 18;
  171. FindFirst := -Err;
  172. if Err = 0 then
  173. begin
  174. Rslt.ExcludeAttr := 0;
  175. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  176. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  177. if FSApi64 then
  178. begin
  179. Rslt.Size := FStat^.FileSize;
  180. Rslt.Name := FStat^.Name;
  181. Rslt.Attr := FStat^.AttrFile;
  182. end
  183. else
  184. begin
  185. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  186. Rslt.Name := PFileFindBuf3 (FStat)^.Name;
  187. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  188. end;
  189. end
  190. else
  191. FindClose(Rslt);
  192. Dispose (FStat);
  193. end;
  194. function FindNext (var Rslt: TSearchRec): longint;
  195. var
  196. SR: PSearchRec;
  197. FStat: PFileFindBuf3L;
  198. Count: cardinal;
  199. Err: cardinal;
  200. begin
  201. New (FStat);
  202. Count := 1;
  203. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^), Count);
  204. if (Err = 0) and (Count = 0) then
  205. Err := 18;
  206. FindNext := -Err;
  207. if Err = 0 then
  208. begin
  209. Rslt.ExcludeAttr := 0;
  210. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  211. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  212. if FSApi64 then
  213. begin
  214. Rslt.Size := FStat^.FileSize;
  215. Rslt.Name := FStat^.Name;
  216. Rslt.Attr := FStat^.AttrFile;
  217. end
  218. else
  219. begin
  220. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  221. Rslt.Name := PFileFindBuf3 (FStat)^.Name;
  222. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  223. end;
  224. end;
  225. Dispose (FStat);
  226. end;
  227. procedure FindClose (var F: TSearchrec);
  228. var
  229. SR: PSearchRec;
  230. begin
  231. DosFindClose (F.FindHandle);
  232. F.FindHandle := 0;
  233. end;
  234. function FileGetDate (Handle: THandle): longint;
  235. var
  236. FStat: TFileStatus3;
  237. Time: Longint;
  238. RC: cardinal;
  239. begin
  240. RC := DosQueryFileInfo(Handle, ilStandard, @FStat, SizeOf(FStat));
  241. if RC = 0 then
  242. begin
  243. Time := FStat.TimeLastWrite + longint (FStat.DateLastWrite) shl 16;
  244. if Time = 0 then
  245. Time := FStat.TimeCreation + longint (FStat.DateCreation) shl 16;
  246. end else
  247. Time:=0;
  248. FileGetDate:=Time;
  249. end;
  250. function FileSetDate (Handle: THandle; Age: longint): longint;
  251. var
  252. FStat: PFileStatus3;
  253. RC: cardinal;
  254. begin
  255. New (FStat);
  256. RC := DosQueryFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^));
  257. if RC <> 0 then
  258. FileSetDate := -1
  259. else
  260. begin
  261. FStat^.DateLastAccess := Hi (Age);
  262. FStat^.DateLastWrite := Hi (Age);
  263. FStat^.TimeLastAccess := Lo (Age);
  264. FStat^.TimeLastWrite := Lo (Age);
  265. RC := DosSetFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^));
  266. if RC <> 0 then
  267. FileSetDate := -1
  268. else
  269. FileSetDate := 0;
  270. end;
  271. Dispose (FStat);
  272. end;
  273. function FileGetAttr (const FileName: string): longint;
  274. var
  275. FS: PFileStatus3;
  276. begin
  277. New(FS);
  278. Result:=-DosQueryPathInfo(PChar (FileName), ilStandard, FS, SizeOf(FS^));
  279. If Result=0 Then Result:=FS^.attrFile;
  280. Dispose(FS);
  281. end;
  282. function FileSetAttr (const Filename: string; Attr: longint): longint;
  283. Var
  284. FS: PFileStatus3;
  285. Begin
  286. New(FS);
  287. FillChar(FS, SizeOf(FS^), 0);
  288. FS^.AttrFile:=Attr;
  289. Result:=-DosSetPathInfo(PChar (FileName), ilStandard, FS, SizeOf(FS^), 0);
  290. Dispose(FS);
  291. end;
  292. function DeleteFile (const FileName: string): boolean;
  293. Begin
  294. Result:=(DosDelete(PChar (FileName))=0);
  295. End;
  296. function RenameFile (const OldName, NewName: string): boolean;
  297. Begin
  298. Result:=(DosMove(PChar (OldName), PChar (NewName))=0);
  299. End;
  300. {****************************************************************************
  301. Disk Functions
  302. ****************************************************************************}
  303. function DiskFree (Drive: byte): int64;
  304. var FI: TFSinfo;
  305. RC: cardinal;
  306. begin
  307. {In OS/2, we use the filesystem information.}
  308. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  309. if RC = 0 then
  310. DiskFree := int64 (FI.Free_Clusters) *
  311. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  312. else
  313. DiskFree := -1;
  314. end;
  315. function DiskSize (Drive: byte): int64;
  316. var FI: TFSinfo;
  317. RC: cardinal;
  318. begin
  319. {In OS/2, we use the filesystem information.}
  320. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  321. if RC = 0 then
  322. DiskSize := int64 (FI.Total_Clusters) *
  323. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  324. else
  325. DiskSize := -1;
  326. end;
  327. function GetCurrentDir: string;
  328. begin
  329. GetDir (0, Result);
  330. end;
  331. function SetCurrentDir (const NewDir: string): boolean;
  332. var
  333. OrigInOutRes: word;
  334. begin
  335. OrigInOutRes := InOutRes;
  336. InOutRes := 0;
  337. {$I-}
  338. ChDir (NewDir);
  339. Result := InOutRes = 0;
  340. {$I+}
  341. InOutRes := OrigInOutRes;
  342. end;
  343. function CreateDir (const NewDir: string): boolean;
  344. var
  345. OrigInOutRes: word;
  346. begin
  347. OrigInOutRes := InOutRes;
  348. InOutRes := 0;
  349. {$I-}
  350. MkDir (NewDir);
  351. Result := InOutRes = 0;
  352. {$I+}
  353. InOutRes := OrigInOutRes;
  354. end;
  355. function RemoveDir (const Dir: string): boolean;
  356. var
  357. OrigInOutRes: word;
  358. begin
  359. OrigInOutRes := InOutRes;
  360. InOutRes := 0;
  361. {$I-}
  362. RmDir (Dir);
  363. Result := InOutRes = 0;
  364. {$I+}
  365. InOutRes := OrigInOutRes;
  366. end;
  367. function DirectoryExists (const Directory: string): boolean;
  368. var
  369. L: longint;
  370. begin
  371. if Directory = '' then
  372. Result := false
  373. else
  374. begin
  375. if (Directory [Length (Directory)] in AllowDirectorySeparators) and
  376. (Length (Directory) > 1) and
  377. (* Do not remove '\' after ':' (root directory of a drive)
  378. or in '\\' (invalid path, possibly broken UNC path). *)
  379. not (Directory [Length (Directory) - 1] in AllowDriveSeparators + AllowDirectorySeparators) then
  380. L := FileGetAttr (ExpandFileName (Copy (Directory, 1, Length (Directory) - 1)))
  381. else
  382. L := FileGetAttr (ExpandFileName (Directory));
  383. Result := (L > 0) and (L and faDirectory = faDirectory);
  384. end;
  385. end;
  386. {****************************************************************************
  387. Time Functions
  388. ****************************************************************************}
  389. procedure GetLocalTime (var SystemTime: TSystemTime);
  390. var
  391. DT: DosCalls.TDateTime;
  392. begin
  393. DosGetDateTime(DT);
  394. with SystemTime do
  395. begin
  396. Year:=DT.Year;
  397. Month:=DT.Month;
  398. Day:=DT.Day;
  399. Hour:=DT.Hour;
  400. Minute:=DT.Minute;
  401. Second:=DT.Second;
  402. MilliSecond:=DT.Sec100;
  403. end;
  404. end;
  405. {****************************************************************************
  406. Misc Functions
  407. ****************************************************************************}
  408. procedure sysbeep;
  409. begin
  410. // Maybe implement later on ?
  411. end;
  412. {****************************************************************************
  413. Locale Functions
  414. ****************************************************************************}
  415. procedure InitAnsi;
  416. var I: byte;
  417. Country: TCountryCode;
  418. begin
  419. for I := 0 to 255 do
  420. UpperCaseTable [I] := Chr (I);
  421. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  422. FillChar (Country, SizeOf (Country), 0);
  423. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  424. for I := 0 to 255 do
  425. if UpperCaseTable [I] <> Chr (I) then
  426. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  427. end;
  428. procedure InitInternational;
  429. var Country: TCountryCode;
  430. CtryInfo: TCountryInfo;
  431. Size: cardinal;
  432. RC: cardinal;
  433. begin
  434. Size := 0;
  435. FillChar (Country, SizeOf (Country), 0);
  436. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  437. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  438. if RC = 0 then
  439. begin
  440. DateSeparator := CtryInfo.DateSeparator;
  441. case CtryInfo.DateFormat of
  442. 1: begin
  443. ShortDateFormat := 'd/m/y';
  444. LongDateFormat := 'dd" "mmmm" "yyyy';
  445. end;
  446. 2: begin
  447. ShortDateFormat := 'y/m/d';
  448. LongDateFormat := 'yyyy" "mmmm" "dd';
  449. end;
  450. 3: begin
  451. ShortDateFormat := 'm/d/y';
  452. LongDateFormat := 'mmmm" "dd" "yyyy';
  453. end;
  454. end;
  455. TimeSeparator := CtryInfo.TimeSeparator;
  456. DecimalSeparator := CtryInfo.DecimalSeparator;
  457. ThousandSeparator := CtryInfo.ThousandSeparator;
  458. CurrencyFormat := CtryInfo.CurrencyFormat;
  459. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  460. end;
  461. InitAnsi;
  462. InitInternationalGeneric;
  463. end;
  464. function SysErrorMessage(ErrorCode: Integer): String;
  465. begin
  466. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  467. end;
  468. {****************************************************************************
  469. OS Utils
  470. ****************************************************************************}
  471. function GetEnvPChar (EnvVar: shortstring): PChar;
  472. (* The assembler version is more than three times as fast as Pascal. *)
  473. var
  474. P: PChar;
  475. begin
  476. EnvVar := UpCase (EnvVar);
  477. {$ASMMODE INTEL}
  478. asm
  479. cld
  480. mov edi, Environment
  481. lea esi, EnvVar
  482. xor eax, eax
  483. lodsb
  484. @NewVar:
  485. cmp byte ptr [edi], 0
  486. jz @Stop
  487. push eax { eax contains length of searched variable name }
  488. push esi { esi points to the beginning of the variable name }
  489. mov ecx, -1 { our character ('=' - see below) _must_ be found }
  490. mov edx, edi { pointer to beginning of variable name saved in edx }
  491. mov al, '=' { searching until '=' (end of variable name) }
  492. repne
  493. scasb { scan until '=' not found }
  494. neg ecx { what was the name length? }
  495. dec ecx { corrected }
  496. dec ecx { exclude the '=' character }
  497. pop esi { restore pointer to beginning of variable name }
  498. pop eax { restore length of searched variable name }
  499. push eax { and save both of them again for later use }
  500. push esi
  501. cmp ecx, eax { compare length of searched variable name with name }
  502. jnz @NotEqual { ... of currently found variable, jump if different }
  503. xchg edx, edi { pointer to current variable name restored in edi }
  504. repe
  505. cmpsb { compare till the end of variable name }
  506. xchg edx, edi { pointer to beginning of variable contents in edi }
  507. jz @Equal { finish if they're equal }
  508. @NotEqual:
  509. xor eax, eax { look for 00h }
  510. mov ecx, -1 { it _must_ be found }
  511. repne
  512. scasb { scan until found }
  513. pop esi { restore pointer to beginning of variable name }
  514. pop eax { restore length of searched variable name }
  515. jmp @NewVar { ... or continue with new variable otherwise }
  516. @Stop:
  517. xor eax, eax
  518. mov P, eax { Not found - return nil }
  519. jmp @End
  520. @Equal:
  521. pop esi { restore the stack position }
  522. pop eax
  523. mov P, edi { place pointer to variable contents in P }
  524. @End:
  525. end ['eax','ecx','edx','esi','edi'];
  526. GetEnvPChar := P;
  527. end;
  528. {$ASMMODE ATT}
  529. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  530. begin
  531. GetEnvironmentVariable := StrPas (GetEnvPChar (EnvVar));
  532. end;
  533. Function GetEnvironmentVariableCount : Integer;
  534. begin
  535. (* Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
  536. GetEnvironmentVariableCount := EnvC;
  537. end;
  538. Function GetEnvironmentString(Index : Integer) : String;
  539. begin
  540. Result:=FPCGetEnvStrFromP (EnvP, Index);
  541. end;
  542. procedure Sleep (Milliseconds: cardinal);
  543. begin
  544. DosSleep (Milliseconds);
  545. end;
  546. function ExecuteProcess (const Path: AnsiString; const ComLine: AnsiString;Flags:TExecuteFlags=[]):
  547. integer;
  548. var
  549. E: EOSError;
  550. CommandLine: ansistring;
  551. Args0, Args: DosCalls.PByteArray;
  552. ObjNameBuf: PChar;
  553. ArgSize: word;
  554. Res: TResultCodes;
  555. ObjName: shortstring;
  556. RC: cardinal;
  557. ExecAppType: cardinal;
  558. const
  559. MaxArgsSize = 3072; (* Amount of memory reserved for arguments in bytes. *)
  560. ObjBufSize = 512;
  561. function StartSession: cardinal;
  562. var
  563. HQ: THandle;
  564. SPID, STID, QName: shortstring;
  565. SID, PID: cardinal;
  566. SD: TStartData;
  567. RD: TRequestData;
  568. PCI: PChildInfo;
  569. CISize: cardinal;
  570. Prio: byte;
  571. begin
  572. Result := $FFFFFFFF;
  573. FillChar (SD, SizeOf (SD), 0);
  574. SD.Length := SizeOf (SD);
  575. SD.Related := ssf_Related_Child;
  576. if FileExists (Path) then
  577. (* Full path necessary for starting different executable files from current *)
  578. (* directory. *)
  579. CommandLine := ExpandFileName (Path)
  580. else
  581. CommandLine := Path;
  582. SD.PgmName := PChar (CommandLine);
  583. if ComLine <> '' then
  584. SD.PgmInputs := PChar (ComLine);
  585. if ExecInheritsHandles in Flags then
  586. SD.InheritOpt := ssf_InhertOpt_Parent;
  587. Str (GetProcessID, SPID);
  588. Str (ThreadID, STID);
  589. QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
  590. SD.TermQ := @QName [1];
  591. SD.ObjectBuffer := ObjNameBuf;
  592. SD.ObjectBuffLen := ObjBufSize;
  593. RC := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
  594. if RC <> 0 then
  595. Move (QName [1], ObjNameBuf^, Length (QName))
  596. else
  597. begin
  598. RC := DosStartSession (SD, SID, PID);
  599. if (RC = 0) or (RC = 457) then
  600. begin
  601. RC := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
  602. if RC = 0 then
  603. begin
  604. Result := PCI^.Return;
  605. DosCloseQueue (HQ);
  606. DosFreeMem (PCI);
  607. FreeMem (ObjNameBuf, ObjBufSize);
  608. end
  609. else
  610. DosCloseQueue (HQ);
  611. end
  612. else
  613. DosCloseQueue (HQ);
  614. end;
  615. end;
  616. begin
  617. Result := integer ($FFFFFFFF);
  618. ObjName := '';
  619. GetMem (ObjNameBuf, ObjBufSize);
  620. FillChar (ObjNameBuf^, ObjBufSize, 0);
  621. if (DosQueryAppType (PChar (Path), ExecAppType) = 0) and
  622. (ApplicationType and 3 = ExecAppType and 3) then
  623. (* DosExecPgm should work... *)
  624. begin
  625. if ComLine = '' then
  626. begin
  627. Args0 := nil;
  628. Args := nil;
  629. end
  630. else
  631. begin
  632. GetMem (Args0, MaxArgsSize);
  633. Args := Args0;
  634. (* Work around a bug in OS/2 - argument to DosExecPgm *)
  635. (* should not cross 64K boundary. *)
  636. if ((PtrUInt (Args) + 1024) and $FFFF) < 1024 then
  637. Inc (pointer (Args), 1024);
  638. ArgSize := 0;
  639. Move (Path [1], Args^ [ArgSize], Length (Path));
  640. Inc (ArgSize, Length (Path));
  641. Args^ [ArgSize] := 0;
  642. Inc (ArgSize);
  643. {Now do the real arguments.}
  644. Move (ComLine [1], Args^ [ArgSize], Length (ComLine));
  645. Inc (ArgSize, Length (ComLine));
  646. Args^ [ArgSize] := 0;
  647. Inc (ArgSize);
  648. Args^ [ArgSize] := 0;
  649. end;
  650. Res.ExitCode := $FFFFFFFF;
  651. RC := DosExecPgm (ObjNameBuf, ObjBufSize, 0, Args, nil, Res, PChar (Path));
  652. if Args0 <> nil then
  653. FreeMem (Args0, MaxArgsSize);
  654. if RC = 0 then
  655. begin
  656. Result := Res.ExitCode;
  657. FreeMem (ObjNameBuf, ObjBufSize);
  658. end
  659. else
  660. begin
  661. if (RC = 190) or (RC = 191) then
  662. Result := StartSession;
  663. end;
  664. end
  665. else
  666. Result := StartSession;
  667. if RC <> 0 then
  668. begin
  669. ObjName := StrPas (ObjNameBuf);
  670. FreeMem (ObjNameBuf, ObjBufSize);
  671. if ComLine = '' then
  672. CommandLine := Path
  673. else
  674. CommandLine := Path + ' ' + ComLine;
  675. if ObjName = '' then
  676. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, RC])
  677. else
  678. E := EOSError.CreateFmt (SExecuteProcessFailed + ' (' + ObjName + ')', [CommandLine, RC]);
  679. E.ErrorCode := Result;
  680. raise E;
  681. end;
  682. end;
  683. function ExecuteProcess (const Path: AnsiString;
  684. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  685. var
  686. CommandLine: AnsiString;
  687. I: integer;
  688. begin
  689. Commandline := '';
  690. for I := 0 to High (ComLine) do
  691. if Pos (' ', ComLine [I]) <> 0 then
  692. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  693. else
  694. CommandLine := CommandLine + ' ' + Comline [I];
  695. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  696. end;
  697. {****************************************************************************
  698. Initialization code
  699. ****************************************************************************}
  700. Initialization
  701. InitExceptions; { Initialize exceptions. OS independent }
  702. InitInternational; { Initialize internationalization settings }
  703. OnBeep:=@SysBeep;
  704. Finalization
  705. DoneExceptions;
  706. end.