system.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. {
  2. ****************************************************************************
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2005 by Free Pascal development team
  5. Free Pascal - OS/2 runtime library
  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 system;
  13. interface
  14. {$ifdef SYSTEMDEBUG}
  15. {$define SYSTEMEXCEPTIONDEBUG}
  16. {.$define IODEBUG}
  17. {.$define DEBUGENVIRONMENT}
  18. {.$define DEBUGARGUMENTS}
  19. {$endif SYSTEMDEBUG}
  20. { $DEFINE OS2EXCEPTIONS}
  21. {$I systemh.inc}
  22. {$IFDEF OS2EXCEPTIONS}
  23. (* Types and constants for exception handler support *)
  24. type
  25. {x} PEXCEPTION_FRAME = ^TEXCEPTION_FRAME;
  26. {x} TEXCEPTION_FRAME = record
  27. {x} next : PEXCEPTION_FRAME;
  28. {x} handler : pointer;
  29. {x} end;
  30. {$ENDIF OS2EXCEPTIONS}
  31. const
  32. LineEnding = #13#10;
  33. { LFNSupport is defined separately below!!! }
  34. DirectorySeparator = '\';
  35. DriveSeparator = ':';
  36. PathSeparator = ';';
  37. { FileNameCaseSensitive is defined separately below!!! }
  38. MaxExitCode = 65535;
  39. MaxPathLen = 256;
  40. type Tos=(osDOS,osOS2,osDPMI);
  41. const os_mode: Tos = osOS2;
  42. first_meg: pointer = nil;
  43. {$IFDEF OS2EXCEPTIONS}
  44. {x} System_exception_frame : PEXCEPTION_FRAME =nil;
  45. {$ENDIF OS2EXCEPTIONS}
  46. type TByteArray = array [0..$ffff] of byte;
  47. PByteArray = ^TByteArray;
  48. TSysThreadIB = record
  49. TID,
  50. Priority,
  51. Version: cardinal;
  52. MCCount,
  53. MCForceFlag: word;
  54. end;
  55. PSysThreadIB = ^TSysThreadIB;
  56. TThreadInfoBlock = record
  57. PExChain,
  58. Stack,
  59. StackLimit: pointer;
  60. TIB2: PSysThreadIB;
  61. Version,
  62. Ordinal: cardinal;
  63. end;
  64. PThreadInfoBlock = ^TThreadInfoBlock;
  65. PPThreadInfoBlock = ^PThreadInfoBlock;
  66. TProcessInfoBlock = record
  67. PID,
  68. ParentPid,
  69. Handle: cardinal;
  70. Cmd,
  71. Env: PByteArray;
  72. Status,
  73. ProcType: cardinal;
  74. end;
  75. PProcessInfoBlock = ^TProcessInfoBlock;
  76. PPProcessInfoBlock = ^PProcessInfoBlock;
  77. const UnusedHandle=-1;
  78. StdInputHandle=0;
  79. StdOutputHandle=1;
  80. StdErrorHandle=2;
  81. LFNSupport: boolean = true;
  82. FileNameCaseSensitive: boolean = false;
  83. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  84. sLineBreak = LineEnding;
  85. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  86. var
  87. { C-compatible arguments and environment }
  88. argc : longint;
  89. argv : ppchar;
  90. envp : ppchar;
  91. EnvC: cardinal;
  92. (* Pointer to the block of environment variables - used e.g. in unit Dos. *)
  93. Environment: PChar;
  94. var
  95. (* Type / run mode of the current process: *)
  96. (* 0 .. full screen OS/2 session *)
  97. (* 1 .. DOS session *)
  98. (* 2 .. VIO windowable OS/2 session *)
  99. (* 3 .. Presentation Manager OS/2 session *)
  100. (* 4 .. detached (background) OS/2 process *)
  101. ApplicationType: cardinal;
  102. (* Is allocation of memory above 512 MB address limit allowed? Initialized *)
  103. (* during initialization of system unit according to capabilities of the *)
  104. (* underlying OS/2 version, can be overridden by user - heap is allocated *)
  105. (* for all threads, so the setting isn't declared as a threadvar and *)
  106. (* should be only changed at the beginning of the main thread if needed. *)
  107. UseHighMem: boolean;
  108. const
  109. (* Are file sizes > 2 GB (64-bit) supported on the current system? *)
  110. FSApi64: boolean = false;
  111. procedure SetDefaultOS2FileType (FType: ShortString);
  112. procedure SetDefaultOS2Creator (Creator: ShortString);
  113. implementation
  114. {$I system.inc}
  115. {****************************************************************************
  116. Miscellaneous related routines.
  117. ****************************************************************************}
  118. procedure system_exit;
  119. begin
  120. DosExit (1{process}, exitcode);
  121. end;
  122. {$ASMMODE ATT}
  123. function paramcount:longint;assembler;
  124. asm
  125. movl argc,%eax
  126. decl %eax
  127. end {['EAX']};
  128. function args:pointer;assembler;
  129. asm
  130. movl argv,%eax
  131. end {['EAX']};
  132. function paramstr(l:longint):string;
  133. var p:^Pchar;
  134. begin
  135. if (l>=0) and (l<=paramcount) then
  136. begin
  137. p:=args;
  138. paramstr:=strpas(p[l]);
  139. end
  140. else paramstr:='';
  141. end;
  142. procedure randomize;
  143. var
  144. dt: TSysDateTime;
  145. begin
  146. // Hmm... Lets use timer
  147. DosGetDateTime(dt);
  148. randseed:=dt.hour+(dt.minute shl 8)+(dt.second shl 16)+(dt.sec100 shl 32);
  149. end;
  150. {$ASMMODE ATT}
  151. {*****************************************************************************
  152. System unit initialization.
  153. ****************************************************************************}
  154. {****************************************************************************
  155. Error Message writing using messageboxes
  156. ****************************************************************************}
  157. type
  158. TWinMessageBox = function (Parent, Owner: cardinal;
  159. BoxText, BoxTitle: PChar; Identity, Style: cardinal): cardinal; cdecl;
  160. TWinInitialize = function (Options: cardinal): cardinal; cdecl;
  161. TWinCreateMsgQueue = function (Handle: cardinal; cmsg: longint): cardinal;
  162. cdecl;
  163. const
  164. ErrorBufferLength = 1024;
  165. mb_OK = $0000;
  166. mb_Error = $0040;
  167. mb_Moveable = $4000;
  168. MBStyle = mb_OK or mb_Error or mb_Moveable;
  169. WinInitialize: TWinInitialize = nil;
  170. WinCreateMsgQueue: TWinCreateMsgQueue = nil;
  171. WinMessageBox: TWinMessageBox = nil;
  172. EnvSize: cardinal = 0;
  173. var
  174. ErrorBuf: array [0..ErrorBufferLength] of char;
  175. ErrorLen: longint;
  176. PMWinHandle: cardinal;
  177. function ErrorWrite (var F: TextRec): integer;
  178. {
  179. An error message should always end with #13#10#13#10
  180. }
  181. var
  182. P: PChar;
  183. I: longint;
  184. begin
  185. if F.BufPos > 0 then
  186. begin
  187. if F.BufPos + ErrorLen > ErrorBufferLength then
  188. I := ErrorBufferLength - ErrorLen
  189. else
  190. I := F.BufPos;
  191. Move (F.BufPtr^, ErrorBuf [ErrorLen], I);
  192. Inc (ErrorLen, I);
  193. ErrorBuf [ErrorLen] := #0;
  194. end;
  195. if ErrorLen > 3 then
  196. begin
  197. P := @ErrorBuf [ErrorLen];
  198. for I := 1 to 4 do
  199. begin
  200. Dec (P);
  201. if not (P^ in [#10, #13]) then
  202. break;
  203. end;
  204. end;
  205. if ErrorLen = ErrorBufferLength then
  206. I := 4;
  207. if (I = 4) then
  208. begin
  209. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  210. ErrorLen := 0;
  211. end;
  212. F.BufPos := 0;
  213. ErrorWrite := 0;
  214. end;
  215. function ErrorClose (var F: TextRec): integer;
  216. begin
  217. if ErrorLen > 0 then
  218. begin
  219. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  220. ErrorLen := 0;
  221. end;
  222. ErrorLen := 0;
  223. ErrorClose := 0;
  224. end;
  225. function ErrorOpen (var F: TextRec): integer;
  226. begin
  227. TextRec(F).InOutFunc := @ErrorWrite;
  228. TextRec(F).FlushFunc := @ErrorWrite;
  229. TextRec(F).CloseFunc := @ErrorClose;
  230. ErrorOpen := 0;
  231. end;
  232. procedure AssignError (var T: Text);
  233. begin
  234. Assign (T, '');
  235. TextRec (T).OpenFunc := @ErrorOpen;
  236. Rewrite (T);
  237. end;
  238. procedure SysInitStdIO;
  239. begin
  240. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  241. displayed in a messagebox }
  242. (*
  243. StdInputHandle := longint(GetStdHandle(cardinal(STD_INPUT_HANDLE)));
  244. StdOutputHandle := longint(GetStdHandle(cardinal(STD_OUTPUT_HANDLE)));
  245. StdErrorHandle := longint(GetStdHandle(cardinal(STD_ERROR_HANDLE)));
  246. if not IsConsole then
  247. begin
  248. if (DosLoadModule (nil, 0, 'PMWIN', PMWinHandle) = 0) and
  249. (DosQueryProcAddr (PMWinHandle, 789, nil, pointer (WinMessageBox)) = 0)
  250. and
  251. (DosQueryProcAddr (PMWinHandle, 763, nil, pointer (WinInitialize)) = 0)
  252. and
  253. (DosQueryProcAddr (PMWinHandle, 716, nil, pointer (WinCreateMsgQueue))
  254. = 0)
  255. then
  256. begin
  257. WinInitialize (0);
  258. WinCreateMsgQueue (0, 0);
  259. end
  260. else
  261. HandleError (2);
  262. AssignError (StdErr);
  263. AssignError (StdOut);
  264. Assign (Output, '');
  265. Assign (Input, '');
  266. end
  267. else
  268. begin
  269. *)
  270. OpenStdIO (Input, fmInput, StdInputHandle);
  271. OpenStdIO (Output, fmOutput, StdOutputHandle);
  272. OpenStdIO (ErrOutput, fmOutput, StdErrorHandle);
  273. OpenStdIO (StdOut, fmOutput, StdOutputHandle);
  274. OpenStdIO (StdErr, fmOutput, StdErrorHandle);
  275. (*
  276. end;
  277. *)
  278. end;
  279. function strcopy(dest,source : pchar) : pchar;assembler;
  280. var
  281. saveeax,saveesi,saveedi : longint;
  282. asm
  283. movl %edi,saveedi
  284. movl %esi,saveesi
  285. {$ifdef REGCALL}
  286. movl %eax,saveeax
  287. movl %edx,%edi
  288. {$else}
  289. movl source,%edi
  290. {$endif}
  291. testl %edi,%edi
  292. jz .LStrCopyDone
  293. leal 3(%edi),%ecx
  294. andl $-4,%ecx
  295. movl %edi,%esi
  296. subl %edi,%ecx
  297. {$ifdef REGCALL}
  298. movl %eax,%edi
  299. {$else}
  300. movl dest,%edi
  301. {$endif}
  302. jz .LStrCopyAligned
  303. .LStrCopyAlignLoop:
  304. movb (%esi),%al
  305. incl %edi
  306. incl %esi
  307. testb %al,%al
  308. movb %al,-1(%edi)
  309. jz .LStrCopyDone
  310. decl %ecx
  311. jnz .LStrCopyAlignLoop
  312. .balign 16
  313. .LStrCopyAligned:
  314. movl (%esi),%eax
  315. movl %eax,%edx
  316. leal 0x0fefefeff(%eax),%ecx
  317. notl %edx
  318. addl $4,%esi
  319. andl %edx,%ecx
  320. andl $0x080808080,%ecx
  321. jnz .LStrCopyEndFound
  322. movl %eax,(%edi)
  323. addl $4,%edi
  324. jmp .LStrCopyAligned
  325. .LStrCopyEndFound:
  326. testl $0x0ff,%eax
  327. jz .LStrCopyByte
  328. testl $0x0ff00,%eax
  329. jz .LStrCopyWord
  330. testl $0x0ff0000,%eax
  331. jz .LStrCopy3Bytes
  332. movl %eax,(%edi)
  333. jmp .LStrCopyDone
  334. .LStrCopy3Bytes:
  335. xorb %dl,%dl
  336. movw %ax,(%edi)
  337. movb %dl,2(%edi)
  338. jmp .LStrCopyDone
  339. .LStrCopyWord:
  340. movw %ax,(%edi)
  341. jmp .LStrCopyDone
  342. .LStrCopyByte:
  343. movb %al,(%edi)
  344. .LStrCopyDone:
  345. {$ifdef REGCALL}
  346. movl saveeax,%eax
  347. {$else}
  348. movl dest,%eax
  349. {$endif}
  350. movl saveedi,%edi
  351. movl saveesi,%esi
  352. end;
  353. threadvar
  354. DefaultCreator: ShortString;
  355. DefaultFileType: ShortString;
  356. procedure SetDefaultOS2FileType (FType: ShortString);
  357. begin
  358. {$WARNING Not implemented yet!}
  359. DefaultFileType := FType;
  360. end;
  361. procedure SetDefaultOS2Creator (Creator: ShortString);
  362. begin
  363. {$WARNING Not implemented yet!}
  364. DefaultCreator := Creator;
  365. end;
  366. procedure InitEnvironment;
  367. var env_count : longint;
  368. dos_env,cp : pchar;
  369. begin
  370. env_count:=0;
  371. cp:=environment;
  372. while cp ^ <> #0 do
  373. begin
  374. inc(env_count);
  375. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  376. inc(longint(cp)); { skip to next character }
  377. end;
  378. envp := sysgetmem((env_count+1) * sizeof(pchar));
  379. envc := env_count;
  380. if (envp = nil) then exit;
  381. cp:=environment;
  382. env_count:=0;
  383. while cp^ <> #0 do
  384. begin
  385. envp[env_count] := sysgetmem(strlen(cp)+1);
  386. strcopy(envp[env_count], cp);
  387. {$IfDef DEBUGENVIRONMENT}
  388. Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
  389. {$EndIf}
  390. inc(env_count);
  391. while (cp^ <> #0) do
  392. inc(longint(cp)); { skip to NUL }
  393. inc(longint(cp)); { skip to next character }
  394. end;
  395. envp[env_count]:=nil;
  396. end;
  397. var
  398. (* Initialized by system unit initialization *)
  399. PIB: PProcessInfoBlock;
  400. procedure InitArguments;
  401. var
  402. arglen,
  403. count : PtrInt;
  404. argstart,
  405. pc,arg : pchar;
  406. quote : char;
  407. argvlen : PtrInt;
  408. procedure allocarg(idx,len: PtrInt);
  409. var
  410. oldargvlen : PtrInt;
  411. begin
  412. if idx>=argvlen then
  413. begin
  414. oldargvlen:=argvlen;
  415. argvlen:=(idx+8) and (not 7);
  416. sysreallocmem(argv,argvlen*sizeof(pointer));
  417. { fillchar(argv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);}
  418. end;
  419. { use realloc to reuse already existing memory }
  420. { always allocate, even if length is zero, since }
  421. { the arg. is still present! }
  422. ArgV [Idx] := SysAllocMem (Succ (Len));
  423. end;
  424. begin
  425. CmdLine := SysAllocMem (MaxPathLen);
  426. ArgV := SysAllocMem (8 * SizeOf (pointer));
  427. ArgLen := StrLen (PChar (PIB^.Cmd));
  428. Inc (ArgLen);
  429. if DosQueryModuleName (PIB^.Handle, MaxPathLen, CmdLine) = 0 then
  430. ArgVLen := Succ (StrLen (CmdLine))
  431. else
  432. (* Error occurred - use program name from command line as fallback. *)
  433. begin
  434. Move (PIB^.Cmd^, CmdLine, ArgLen);
  435. ArgVLen := ArgLen;
  436. end;
  437. { Get ArgV [0] }
  438. ArgV [0] := SysAllocMem (ArgVLen);
  439. Move (CmdLine^, ArgV [0]^, ArgVLen);
  440. Count := 1;
  441. (* PC points to leading space after program name on command line *)
  442. PC := PChar (PIB^.Cmd) + ArgLen;
  443. (* ArgLen contains size of command line arguments including leading space. *)
  444. ArgLen := Succ (StrLen (PC));
  445. SysReallocMem (CmdLine, ArgVLen + ArgLen);
  446. Move (PC^, CmdLine [ArgVLen], Succ (ArgLen));
  447. (* ArgV has space for 8 parameters from the first allocation. *)
  448. ArgVLen := 8;
  449. { process arguments }
  450. while pc^<>#0 do
  451. begin
  452. { skip leading spaces }
  453. while pc^ in [#1..#32] do
  454. inc(pc);
  455. if pc^=#0 then
  456. break;
  457. { calc argument length }
  458. quote:=' ';
  459. argstart:=pc;
  460. arglen:=0;
  461. while (pc^<>#0) do
  462. begin
  463. case pc^ of
  464. #1..#32 :
  465. begin
  466. if quote<>' ' then
  467. inc(arglen)
  468. else
  469. break;
  470. end;
  471. '"' :
  472. begin
  473. if quote<>'''' then
  474. begin
  475. if pchar(pc+1)^<>'"' then
  476. begin
  477. if quote='"' then
  478. quote:=' '
  479. else
  480. quote:='"';
  481. end
  482. else
  483. inc(pc);
  484. end
  485. else
  486. inc(arglen);
  487. end;
  488. '''' :
  489. begin
  490. if quote<>'"' then
  491. begin
  492. if pchar(pc+1)^<>'''' then
  493. begin
  494. if quote='''' then
  495. quote:=' '
  496. else
  497. quote:='''';
  498. end
  499. else
  500. inc(pc);
  501. end
  502. else
  503. inc(arglen);
  504. end;
  505. else
  506. inc(arglen);
  507. end;
  508. inc(pc);
  509. end;
  510. { copy argument }
  511. { Don't copy the first one, it is already there.}
  512. If Count<>0 then
  513. begin
  514. allocarg(count,arglen);
  515. quote:=' ';
  516. pc:=argstart;
  517. arg:=argv[count];
  518. while (pc^<>#0) do
  519. begin
  520. case pc^ of
  521. #1..#32 :
  522. begin
  523. if quote<>' ' then
  524. begin
  525. arg^:=pc^;
  526. inc(arg);
  527. end
  528. else
  529. break;
  530. end;
  531. '"' :
  532. begin
  533. if quote<>'''' then
  534. begin
  535. if pchar(pc+1)^<>'"' then
  536. begin
  537. if quote='"' then
  538. quote:=' '
  539. else
  540. quote:='"';
  541. end
  542. else
  543. inc(pc);
  544. end
  545. else
  546. begin
  547. arg^:=pc^;
  548. inc(arg);
  549. end;
  550. end;
  551. '''' :
  552. begin
  553. if quote<>'"' then
  554. begin
  555. if pchar(pc+1)^<>'''' then
  556. begin
  557. if quote='''' then
  558. quote:=' '
  559. else
  560. quote:='''';
  561. end
  562. else
  563. inc(pc);
  564. end
  565. else
  566. begin
  567. arg^:=pc^;
  568. inc(arg);
  569. end;
  570. end;
  571. else
  572. begin
  573. arg^:=pc^;
  574. inc(arg);
  575. end;
  576. end;
  577. inc(pc);
  578. end;
  579. arg^:=#0;
  580. end;
  581. {$IfDef DEBUGARGUMENTS}
  582. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  583. {$EndIf}
  584. inc(count);
  585. end;
  586. { get argc and create an nil entry }
  587. argc:=count;
  588. allocarg(argc,0);
  589. { free unused memory }
  590. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  591. end;
  592. function GetFileHandleCount: longint;
  593. var L1: longint;
  594. L2: cardinal;
  595. begin
  596. L1 := 0; (* Don't change the amount, just check. *)
  597. if DosSetRelMaxFH (L1, L2) <> 0 then GetFileHandleCount := 50
  598. else GetFileHandleCount := L2;
  599. end;
  600. function CheckInitialStkLen (StkLen: SizeUInt): SizeUInt;
  601. begin
  602. CheckInitialStkLen := StkLen;
  603. end;
  604. var TIB: PThreadInfoBlock;
  605. RC: cardinal;
  606. ErrStr: string;
  607. P: pointer;
  608. DosCallsHandle: THandle;
  609. const
  610. DosCallsName: array [0..8] of char = 'DOSCALLS'#0;
  611. begin
  612. IsLibrary := FALSE;
  613. (* Initialize the amount of file handles *)
  614. FileHandleCount := GetFileHandleCount;
  615. DosGetInfoBlocks (@TIB, @PIB);
  616. StackBottom := TIB^.Stack;
  617. StackTop := TIB^.StackLimit;
  618. StackLength := CheckInitialStkLen (InitialStkLen);
  619. {Set type of application}
  620. ApplicationType := PIB^.ProcType;
  621. ProcessID := PIB^.PID;
  622. ThreadID := TIB^.TIB2^.TID;
  623. IsConsole := ApplicationType <> 3;
  624. ExitProc := nil;
  625. {Initialize the heap.}
  626. (* Logic is following:
  627. The heap is initially restricted to low address space (< 512 MB).
  628. If underlying OS/2 version allows using more than 512 MB per process
  629. (OS/2 WarpServer for e-Business, eComStation, possibly OS/2 Warp 4.0
  630. with FP13 and above as well), use of this high memory is allowed for
  631. future memory allocations at the end of System unit initialization.
  632. The consequences are that the compiled application can allocate more
  633. memory, but it must make sure to use direct DosAllocMem calls if it
  634. needs a memory block for some system API not supporting high memory.
  635. This is probably no problem for direct calls to these APIs, but
  636. there might be situations when a memory block needs to be passed
  637. to a 3rd party DLL which in turn calls such an API call. In case
  638. of problems usage of high memory can be turned off by setting
  639. UseHighMem to false - the program should change the setting at its
  640. very beginning (e.g. in initialization section of the first unit
  641. listed in the "uses" section) to avoid having preallocated memory
  642. from the high memory region before changing value of this variable. *)
  643. InitHeap;
  644. if DosQueryModuleHandle (@DosCallsName [0], DosCallsHandle) = 0 then
  645. begin
  646. if DosQueryProcAddr (DosCallsHandle, OrdDosOpenL, nil, P) = 0 then
  647. begin
  648. DosOpenL := TDosOpenL (P);
  649. if DosQueryProcAddr (DosCallsHandle, OrdDosSetFilePtrL, nil, P) = 0
  650. then
  651. begin
  652. DosSetFilePtrL := TDosSetFilePtrL (P);
  653. if DosQueryProcAddr (DosCallsHandle, OrdDosSetFileSizeL, nil,
  654. P) = 0 then
  655. begin
  656. DosSetFileSizeL := TDosSetFileSizeL (P);
  657. FSApi64 := true;
  658. end;
  659. end;
  660. end;
  661. end;
  662. { ... and exceptions }
  663. SysInitExceptions;
  664. { ... and I/O }
  665. SysInitStdIO;
  666. { no I/O-Error }
  667. inoutres:=0;
  668. {Initialize environment (must be after InitHeap because allocates memory)}
  669. Environment := pointer (PIB^.Env);
  670. InitEnvironment;
  671. InitArguments;
  672. DefaultCreator := '';
  673. DefaultFileType := '';
  674. InitSystemThreads;
  675. InitVariantManager;
  676. {$ifdef HASWIDESTRING}
  677. InitWideStringManager;
  678. {$endif HASWIDESTRING}
  679. {$IFDEF EXTDUMPGROW}
  680. { Int_HeapSize := high (cardinal);}
  681. {$ENDIF EXTDUMPGROW}
  682. RC := DosAllocMem (P, 4096, $403);
  683. if RC = 87 then
  684. (* Using of high memory address space (> 512 MB) *)
  685. (* is not supported on this system. *)
  686. UseHighMem := false
  687. else
  688. begin
  689. UseHighMem := true;
  690. if RC <> 0 then
  691. begin
  692. Str (RC, ErrStr);
  693. ErrStr := 'Error during heap initialization (DosAllocMem - ' + ErrStr + ')!!'#13#10;
  694. if IsConsole then
  695. DosWrite (2, @ErrStr [1], Length (ErrStr), RC);
  696. HandleError (204);
  697. end
  698. else
  699. DosFreeMem (P);
  700. end;
  701. end.