system.pas 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315
  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. {$define DISABLE_NO_THREAD_MANAGER}
  22. {$DEFINE HAS_GETCPUCOUNT}
  23. {$I systemh.inc}
  24. const
  25. LineEnding = #13#10;
  26. { LFNSupport is defined separately below!!! }
  27. DirectorySeparator = '\';
  28. DriveSeparator = ':';
  29. ExtensionSeparator = '.';
  30. PathSeparator = ';';
  31. AllowDirectorySeparators : set of char = ['\','/'];
  32. AllowDriveSeparators : set of char = [':'];
  33. { FileNameCaseSensitive and FileNameCasePreserving are defined separately below!!! }
  34. MaxExitCode = 65535;
  35. MaxPathLen = 260;
  36. (* MaxPathLen is referenced as constant from unit SysUtils *)
  37. (* - changing to variable or typed constant is not possible. *)
  38. AllFilesMask = '*';
  39. RealMaxPathLen: word = MaxPathLen;
  40. (* Default value only - real value queried from the system on startup. *)
  41. type Tos=(osDOS,osOS2,osDPMI);
  42. const OS_Mode: Tos = osOS2;
  43. First_Meg: pointer = nil;
  44. const UnusedHandle=-1;
  45. StdInputHandle=0;
  46. StdOutputHandle=1;
  47. StdErrorHandle=2;
  48. LFNSupport: boolean = true;
  49. FileNameCaseSensitive: boolean = false;
  50. FileNameCasePreserving: boolean = true;
  51. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  52. sLineBreak = LineEnding;
  53. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  54. var
  55. { C-compatible arguments and environment }
  56. argc : longint;
  57. argv : ppchar;
  58. envp : ppchar;
  59. EnvC: cardinal;
  60. (* Pointer to the block of environment variables - used e.g. in unit Dos. *)
  61. Environment: PChar;
  62. var
  63. (* Type / run mode of the current process: *)
  64. (* 0 .. full screen OS/2 session *)
  65. (* 1 .. DOS session *)
  66. (* 2 .. VIO windowable OS/2 session *)
  67. (* 3 .. Presentation Manager OS/2 session *)
  68. (* 4 .. detached (background) OS/2 process *)
  69. ApplicationType: cardinal;
  70. const
  71. HeapAllocFlags: cardinal = $53; (* Compatible to VP/2 *)
  72. (* mfPag_Commit or mfObj_Tile or mfPag_Write or mfPag_Read *)
  73. function ReadUseHighMem: boolean;
  74. procedure WriteUseHighMem (B: boolean);
  75. (* Is allocation of memory above 512 MB address limit allowed? Initialized *)
  76. (* during initialization of system unit according to capabilities of the *)
  77. (* underlying OS/2 version, can be overridden by user - heap is allocated *)
  78. (* for all threads, so the setting isn't declared as a threadvar and *)
  79. (* should be only changed at the beginning of the main thread if needed. *)
  80. property
  81. UseHighMem: boolean read ReadUseHighMem write WriteUseHighMem;
  82. (* UseHighMem is provided for compatibility with 2.0.x. *)
  83. const
  84. (* Are file sizes > 2 GB (64-bit) supported on the current system? *)
  85. FSApi64: boolean = false;
  86. (* Support for tracking I/O errors returned by OS/2 API calls - emulation *)
  87. (* of GetLastError / fpGetError functionality used e.g. in Sysutils. *)
  88. type
  89. TOSErrorWatch = procedure (Error: cardinal);
  90. procedure NoErrorTracking (Error: cardinal);
  91. (* This shall be invoked whenever a non-zero error is returned by OS/2 APIs *)
  92. (* used in the RTL. Direct OS/2 API calls in user programs are not covered! *)
  93. const
  94. OSErrorWatch: TOSErrorWatch = @NoErrorTracking;
  95. procedure SetOSErrorTracking (P: pointer);
  96. procedure SetDefaultOS2FileType (FType: ShortString);
  97. procedure SetDefaultOS2Creator (Creator: ShortString);
  98. type
  99. TDosOpenL = function (FileName: PChar; var Handle: THandle;
  100. var Action: cardinal; InitSize: int64;
  101. Attrib, OpenFlags, FileMode: cardinal;
  102. EA: pointer): cardinal; cdecl;
  103. TDosSetFilePtrL = function (Handle: THandle; Pos: int64; Method: cardinal;
  104. var PosActual: int64): cardinal; cdecl;
  105. TDosSetFileSizeL = function (Handle: THandle; Size: int64): cardinal; cdecl;
  106. function DummyDosOpenL (FileName: PChar; var Handle: THandle;
  107. var Action: cardinal; InitSize: int64;
  108. Attrib, OpenFlags, FileMode: cardinal;
  109. EA: pointer): cardinal; cdecl;
  110. function DummyDosSetFilePtrL (Handle: THandle; Pos: int64; Method: cardinal;
  111. var PosActual: int64): cardinal; cdecl;
  112. function DummyDosSetFileSizeL (Handle: THandle; Size: int64): cardinal; cdecl;
  113. const
  114. Sys_DosOpenL: TDosOpenL = @DummyDosOpenL;
  115. Sys_DosSetFilePtrL: TDosSetFilePtrL = @DummyDosSetFilePtrL;
  116. Sys_DosSetFileSizeL: TDosSetFileSizeL = @DummyDosSetFileSizeL;
  117. DosCallsHandle: THandle = THandle (-1);
  118. implementation
  119. {*****************************************************************************
  120. System unit initialization.
  121. ****************************************************************************}
  122. {$I system.inc}
  123. {*****************************************************************************
  124. Exception handling.
  125. ****************************************************************************}
  126. {$IFDEF OS2EXCEPTIONS}
  127. var
  128. { value of the stack segment
  129. to check if the call stack can be written on exceptions }
  130. _SS : Cardinal;
  131. function Is_Prefetch (P: pointer): boolean;
  132. var
  133. A: array [0..15] of byte;
  134. DoAgain: boolean;
  135. InstrLo, InstrHi, OpCode: byte;
  136. I: longint;
  137. MemSize, MemAttrs: cardinal;
  138. RC: cardinal;
  139. begin
  140. Is_Prefetch := false;
  141. MemSize := SizeOf (A);
  142. RC := DosQueryMem (P, MemSize, MemAttrs);
  143. if RC <> 0 then
  144. OSErrorWatch (RC)
  145. else if (MemAttrs and (mfPag_Free or mfPag_Commit) <> 0)
  146. and (MemSize >= SizeOf (A)) then
  147. Move (P^, A [0], SizeOf (A))
  148. else
  149. Exit;
  150. I := 0;
  151. DoAgain := true;
  152. while DoAgain and (I < 15) do
  153. begin
  154. OpCode := A [I];
  155. InstrLo := OpCode and $f;
  156. InstrHi := OpCode and $f0;
  157. case InstrHi of
  158. { prefix? }
  159. $20, $30:
  160. DoAgain := (InstrLo and 7) = 6;
  161. $60:
  162. DoAgain := (InstrLo and $c) = 4;
  163. $f0:
  164. DoAgain := InstrLo in [0, 2, 3];
  165. $0:
  166. begin
  167. Is_Prefetch := (InstrLo = $f) and (A [I + 1] in [$D, $18]);
  168. Exit;
  169. end;
  170. else
  171. DoAgain := false;
  172. end;
  173. Inc (I);
  174. end;
  175. end;
  176. const
  177. MaxExceptionLevel = 16;
  178. ExceptLevel: byte = 0;
  179. var
  180. ExceptEIP: array [0..MaxExceptionLevel - 1] of longint;
  181. ExceptError: array [0..MaxExceptionLevel - 1] of byte;
  182. ResetFPU: array [0..MaxExceptionLevel - 1] of boolean;
  183. {$ifdef SYSTEMEXCEPTIONDEBUG}
  184. procedure DebugHandleErrorAddrFrame (Error: longint; Addr, Frame: pointer);
  185. begin
  186. if IsConsole then
  187. begin
  188. Write (StdErr, ' HandleErrorAddrFrame (error = ', Error);
  189. Write (StdErr, ', addr = ', hexstr (PtrUInt (Addr), 8));
  190. WriteLn (StdErr, ', frame = ', hexstr (PtrUInt (Frame), 8), ')');
  191. end;
  192. HandleErrorAddrFrame (Error, Addr, Frame);
  193. end;
  194. {$endif SYSTEMEXCEPTIONDEBUG}
  195. procedure JumpToHandleErrorFrame;
  196. var
  197. EIP, EBP, Error: longint;
  198. begin
  199. (* save ebp *)
  200. asm
  201. movl (%ebp),%eax
  202. movl %eax,ebp
  203. end;
  204. if (ExceptLevel > 0) then
  205. Dec (ExceptLevel);
  206. EIP := ExceptEIP [ExceptLevel];
  207. Error := ExceptError [ExceptLevel];
  208. {$ifdef SYSTEMEXCEPTIONDEBUG}
  209. if IsConsole then
  210. WriteLn (StdErr, 'In JumpToHandleErrorFrame error = ', Error);
  211. {$endif SYSTEMEXCEPTIONDEBUG}
  212. if ResetFPU [ExceptLevel] then
  213. SysResetFPU;
  214. { build a fake stack }
  215. asm
  216. {$ifdef REGCALL}
  217. movl ebp,%ecx
  218. movl eip,%edx
  219. movl error,%eax
  220. pushl eip
  221. movl ebp,%ebp // Change frame pointer
  222. {$else}
  223. movl ebp,%eax
  224. pushl %eax
  225. movl eip,%eax
  226. pushl %eax
  227. movl error,%eax
  228. pushl %eax
  229. movl eip,%eax
  230. pushl %eax
  231. movl ebp,%ebp // Change frame pointer
  232. {$endif}
  233. {$ifdef SYSTEMEXCEPTIONDEBUG}
  234. jmpl DebugHandleErrorAddrFrame
  235. {$else not SYSTEMEXCEPTIONDEBUG}
  236. jmpl HandleErrorAddrFrame
  237. {$endif SYSTEMEXCEPTIONDEBUG}
  238. end;
  239. end;
  240. function System_Exception_Handler (Report: PExceptionReportRecord;
  241. RegRec: PExceptionRegistrationRecord;
  242. Context: PContextRecord;
  243. DispContext: pointer): cardinal; cdecl;
  244. var
  245. Res: cardinal;
  246. Err: byte;
  247. Must_Reset_FPU: boolean;
  248. RC: cardinal;
  249. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  250. CurSS: cardinal;
  251. B: byte;
  252. {$ENDIF SYSTEMEXCEPTIONDEBUG}
  253. begin
  254. {$ifdef SYSTEMEXCEPTIONDEBUG}
  255. if IsConsole then
  256. begin
  257. asm
  258. xorl %eax,%eax
  259. movw %ss,%ax
  260. movl %eax,CurSS
  261. end;
  262. WriteLn (StdErr, 'In System_Exception_Handler, error = ',
  263. HexStr (Report^.Exception_Num, 8));
  264. WriteLn (StdErr, 'Context SS = ', HexStr (Context^.Reg_SS, 8),
  265. ', current SS = ', HexStr (CurSS, 8));
  266. end;
  267. {$endif SYSTEMEXCEPTIONDEBUG}
  268. Res := Xcpt_Continue_Search;
  269. if Context^.Reg_SS = _SS then
  270. begin
  271. Err := 0;
  272. Must_Reset_FPU := true;
  273. {$ifdef SYSTEMEXCEPTIONDEBUG}
  274. if IsConsole then
  275. Writeln (StdErr, 'Exception ', HexStr (Report^.Exception_Num, 8));
  276. {$endif SYSTEMEXCEPTIONDEBUG}
  277. case Report^.Exception_Num of
  278. Xcpt_Integer_Divide_By_Zero,
  279. Xcpt_Float_Divide_By_Zero:
  280. Err := 200;
  281. Xcpt_Array_Bounds_Exceeded:
  282. begin
  283. Err := 201;
  284. Must_Reset_FPU := false;
  285. end;
  286. Xcpt_Unable_To_Grow_Stack:
  287. begin
  288. Err := 202;
  289. Must_Reset_FPU := false;
  290. end;
  291. Xcpt_Float_Overflow:
  292. Err := 205;
  293. Xcpt_Float_Denormal_Operand,
  294. Xcpt_Float_Underflow:
  295. Err := 206;
  296. {Context^.FloatSave.StatusWord := Context^.FloatSave.StatusWord and $ffffff00;}
  297. Xcpt_Float_Inexact_Result,
  298. Xcpt_Float_Invalid_Operation,
  299. Xcpt_Float_Stack_Check:
  300. Err := 207;
  301. Xcpt_Integer_Overflow:
  302. begin
  303. Err := 215;
  304. Must_Reset_FPU := false;
  305. end;
  306. Xcpt_Illegal_Instruction:
  307. { if we're testing sse support, simply set the flag and continue }
  308. if SSE_Check then
  309. begin
  310. OS_Supports_SSE := false;
  311. { skip the offending movaps %xmm7, %xmm6 instruction }
  312. Inc (Context^.Reg_EIP, 3);
  313. Report^.Exception_Num := 0;
  314. Res := Xcpt_Continue_Execution;
  315. end
  316. else
  317. Err := 216;
  318. Xcpt_Access_Violation:
  319. { Athlon prefetch bug? }
  320. if Is_Prefetch (pointer (Context^.Reg_EIP)) then
  321. begin
  322. { if yes, then retry }
  323. Report^.Exception_Num := 0;
  324. Res := Xcpt_Continue_Execution;
  325. end
  326. else
  327. Err := 216;
  328. Xcpt_Signal:
  329. case Report^.Parameters [0] of
  330. Xcpt_Signal_KillProc:
  331. Err := 217;
  332. Xcpt_Signal_Break,
  333. Xcpt_Signal_Intr:
  334. if Assigned (CtrlBreakHandler) then
  335. if CtrlBreakHandler (Report^.Parameters [0] = Xcpt_Signal_Break) then
  336. begin
  337. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  338. WriteLn (StdErr, 'CtrlBreakHandler returned true');
  339. {$ENDIF SYSTEMEXCEPTIONDEBUG}
  340. Report^.Exception_Num := 0;
  341. Res := Xcpt_Continue_Execution;
  342. RC := DosAcknowledgeSignalException (Report^.Parameters [0]);
  343. if RC <> 0 then
  344. OSErrorWatch (RC);
  345. end
  346. else
  347. Err := 217;
  348. end;
  349. Xcpt_Privileged_Instruction:
  350. begin
  351. Err := 218;
  352. Must_Reset_FPU := false;
  353. end;
  354. else
  355. begin
  356. if ((Report^.Exception_Num and Xcpt_Severity_Code)
  357. = Xcpt_Fatal_Exception) then
  358. Err := 217
  359. else
  360. Err := 255;
  361. end;
  362. end;
  363. if (Err <> 0) and (ExceptLevel < MaxExceptionLevel)
  364. (* TH: The following line is necessary to avoid an endless loop *)
  365. and (Report^.Exception_Num < Xcpt_Process_Terminate)
  366. then
  367. begin
  368. ExceptEIP [ExceptLevel] := Context^.Reg_EIP;
  369. ExceptError [ExceptLevel] := Err;
  370. ResetFPU [ExceptLevel] := Must_Reset_FPU;
  371. Inc (ExceptLevel);
  372. Context^.Reg_EIP := cardinal (@JumpToHandleErrorFrame);
  373. Report^.Exception_Num := 0;
  374. Res := Xcpt_Continue_Execution;
  375. {$ifdef SYSTEMEXCEPTIONDEBUG}
  376. if IsConsole then
  377. begin
  378. WriteLn (StdErr, 'Exception Continue Exception set at ',
  379. HexStr (ExceptEIP [ExceptLevel], 8));
  380. WriteLn (StdErr, 'EIP changed to ',
  381. HexStr (longint (@JumpToHandleErrorFrame), 8), ', error = ', Err);
  382. end;
  383. {$endif SYSTEMEXCEPTIONDEBUG}
  384. end;
  385. end
  386. else
  387. if (Report^.Exception_Num = Xcpt_Signal) and
  388. (Report^.Parameters [0] and (Xcpt_Signal_Intr or Xcpt_Signal_Break) <> 0)
  389. and Assigned (CtrlBreakHandler) then
  390. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  391. begin
  392. WriteLn (StdErr, 'XCPT_SIGNAL caught, CtrlBreakHandler assigned, Param = ',
  393. Report^.Parameters [0]);
  394. {$ENDIF SYSTEMEXCEPTIONDEBUG}
  395. if CtrlBreakHandler (Report^.Parameters [0] = Xcpt_Signal_Break) then
  396. begin
  397. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  398. WriteLn (StdErr, 'CtrlBreakHandler returned true');
  399. {$ENDIF SYSTEMEXCEPTIONDEBUG}
  400. Report^.Exception_Num := 0;
  401. Res := Xcpt_Continue_Execution;
  402. RC := DosAcknowledgeSignalException (Report^.Parameters [0]);
  403. if RC <> 0 then
  404. OSErrorWatch (RC);
  405. end
  406. else
  407. Err := 217;
  408. {$IFDEF SYSTEMEXCEPTIONDEBUG}
  409. end
  410. else
  411. if IsConsole then
  412. begin
  413. WriteLn (StdErr, 'Ctx flags = ', HexStr (Context^.ContextFlags, 8));
  414. if Context^.ContextFlags and Context_Floating_Point <> 0 then
  415. begin
  416. for B := 1 to 6 do
  417. Write (StdErr, 'Ctx Env [', B, '] = ', HexStr (Context^.Env [B], 8),
  418. ', ');
  419. WriteLn (StdErr, 'Ctx Env [7] = ', HexStr (Context^.Env [7], 8));
  420. for B := 0 to 6 do
  421. Write (StdErr, 'FPU stack [', B, '] = ', Context^.FPUStack [B], ', ');
  422. WriteLn (StdErr, 'FPU stack [7] = ', Context^.FPUStack [7]);
  423. end;
  424. if Context^.ContextFlags and Context_Segments <> 0 then
  425. WriteLn (StdErr, 'GS = ', HexStr (Context^.Reg_GS, 8),
  426. ', FS = ', HexStr (Context^.Reg_FS, 8),
  427. ', ES = ', HexStr (Context^.Reg_ES, 8),
  428. ', DS = ', HexStr (Context^.Reg_DS, 8));
  429. if Context^.ContextFlags and Context_Integer <> 0 then
  430. begin
  431. WriteLn (StdErr, 'EDI = ', HexStr (Context^.Reg_EDI, 8),
  432. ', ESI = ', HexStr (Context^.Reg_ESI, 8));
  433. WriteLn (StdErr, 'EAX = ', HexStr (Context^.Reg_EAX, 8),
  434. ', EBX = ', HexStr (Context^.Reg_EBX, 8),
  435. ', ECX = ', HexStr (Context^.Reg_ECX, 8),
  436. ', EDX = ', HexStr (Context^.Reg_EDX, 8));
  437. end;
  438. if Context^.ContextFlags and Context_Control <> 0 then
  439. begin
  440. WriteLn (StdErr, 'EBP = ', HexStr (Context^.Reg_EBP, 8),
  441. ', SS = ', HexStr (Context^.Reg_SS, 8),
  442. ', ESP = ', HexStr (Context^.Reg_ESP, 8));
  443. WriteLn (StdErr, 'CS = ', HexStr (Context^.Reg_CS, 8),
  444. ', EIP = ', HexStr (Context^.Reg_EIP, 8),
  445. ', EFlags = ', HexStr (Context^.Flags, 8));
  446. end;
  447. end;
  448. {$endif SYSTEMEXCEPTIONDEBUG}
  449. System_Exception_Handler := Res;
  450. end;
  451. var
  452. ExcptReg: PExceptionRegistrationRecord; public name '_excptregptr';
  453. {$ifdef SYSTEMEXCEPTIONDEBUG}
  454. var
  455. OldExceptAddr,
  456. NewExceptAddr: PtrUInt;
  457. {$endif SYSTEMEXCEPTIONDEBUG}
  458. procedure Install_Exception_Handler;
  459. var
  460. T: cardinal;
  461. RC: cardinal;
  462. begin
  463. {$ifdef SYSTEMEXCEPTIONDEBUG}
  464. (* ThreadInfoBlock is located at FS:[0], the first *)
  465. (* entry is pointer to head of exception handler chain. *)
  466. asm
  467. movl $0,%eax
  468. movl %fs:(%eax),%eax
  469. movl %eax, OldExceptAddr
  470. end;
  471. {$endif SYSTEMEXCEPTIONDEBUG}
  472. with ExcptReg^ do
  473. begin
  474. Prev_Structure := nil;
  475. ExceptionHandler := TExceptionHandler (@System_Exception_Handler);
  476. end;
  477. (* Disable pop-up windows for errors and exceptions *)
  478. DosError (deDisableExceptions);
  479. DosSetExceptionHandler (ExcptReg^);
  480. if IsConsole then
  481. begin
  482. RC := DosSetSignalExceptionFocus (1, T);
  483. if RC <> 0 then
  484. OSErrorWatch (RC);
  485. RC := DosAcknowledgeSignalException (Xcpt_Signal_Intr);
  486. if RC <> 0 then
  487. OSErrorWatch (RC);
  488. RC := DosAcknowledgeSignalException (Xcpt_Signal_Break);
  489. if RC <> 0 then
  490. OSErrorWatch (RC);
  491. end;
  492. {$ifdef SYSTEMEXCEPTIONDEBUG}
  493. asm
  494. movl $0,%eax
  495. movl %fs:(%eax),%eax
  496. movl %eax, NewExceptAddr
  497. end;
  498. {$endif SYSTEMEXCEPTIONDEBUG}
  499. end;
  500. procedure Remove_Exception_Handlers;
  501. var
  502. RC: cardinal;
  503. begin
  504. RC := DosUnsetExceptionHandler (ExcptReg^);
  505. end;
  506. {$ENDIF OS2EXCEPTIONS}
  507. procedure system_exit;
  508. begin
  509. (* if IsLibrary then
  510. ExitDLL(ExitCode);
  511. *)
  512. (*
  513. if not IsConsole then
  514. begin
  515. Close(stderr);
  516. Close(stdout);
  517. Close(erroutput);
  518. Close(Input);
  519. Close(Output);
  520. end;
  521. *)
  522. {$IFDEF OS2EXCEPTIONS}
  523. Remove_Exception_Handlers;
  524. {$ENDIF OS2EXCEPTIONS}
  525. DosExit (1{process}, exitcode);
  526. end;
  527. {$ASMMODE ATT}
  528. {****************************************************************************
  529. Miscellaneous related routines.
  530. ****************************************************************************}
  531. function paramcount:longint;assembler;
  532. asm
  533. movl argc,%eax
  534. decl %eax
  535. end {['EAX']};
  536. function paramstr(l:longint):string;
  537. var p:^Pchar;
  538. begin
  539. if (l>=0) and (l<=paramcount) then
  540. begin
  541. p:=argv;
  542. paramstr:=strpas(p[l]);
  543. end
  544. else paramstr:='';
  545. end;
  546. procedure randomize;
  547. var
  548. dt: TSysDateTime;
  549. begin
  550. // Hmm... Lets use timer
  551. DosGetDateTime(dt);
  552. randseed:=dt.hour+(dt.minute shl 8)+(dt.second shl 16)+(dt.sec100 shl 32);
  553. end;
  554. {****************************************************************************
  555. Error Message writing using messageboxes
  556. ****************************************************************************}
  557. const
  558. WinInitialize: TWinInitialize = nil;
  559. WinCreateMsgQueue: TWinCreateMsgQueue = nil;
  560. WinMessageBox: TWinMessageBox = nil;
  561. EnvSize: cardinal = 0;
  562. var
  563. ErrorBuf: array [0..ErrorBufferLength] of char;
  564. ErrorLen: longint;
  565. PMWinHandle: cardinal;
  566. function ErrorWrite (var F: TextRec): integer;
  567. {
  568. An error message should always end with #13#10#13#10
  569. }
  570. var
  571. P: PChar;
  572. I: longint;
  573. begin
  574. if F.BufPos > 0 then
  575. begin
  576. if F.BufPos + ErrorLen > ErrorBufferLength then
  577. I := ErrorBufferLength - ErrorLen
  578. else
  579. I := F.BufPos;
  580. Move (F.BufPtr^, ErrorBuf [ErrorLen], I);
  581. Inc (ErrorLen, I);
  582. ErrorBuf [ErrorLen] := #0;
  583. end;
  584. if ErrorLen > 3 then
  585. begin
  586. P := @ErrorBuf [ErrorLen];
  587. for I := 1 to 4 do
  588. begin
  589. Dec (P);
  590. if not (P^ in [#10, #13]) then
  591. break;
  592. end;
  593. end;
  594. if ErrorLen = ErrorBufferLength then
  595. I := 4;
  596. if (I = 4) then
  597. begin
  598. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  599. ErrorLen := 0;
  600. end;
  601. F.BufPos := 0;
  602. ErrorWrite := 0;
  603. end;
  604. function ErrorClose (var F: TextRec): integer;
  605. begin
  606. if ErrorLen > 0 then
  607. begin
  608. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  609. ErrorLen := 0;
  610. end;
  611. ErrorLen := 0;
  612. ErrorClose := 0;
  613. end;
  614. function ErrorOpen (var F: TextRec): integer;
  615. begin
  616. TextRec(F).InOutFunc := @ErrorWrite;
  617. TextRec(F).FlushFunc := @ErrorWrite;
  618. TextRec(F).CloseFunc := @ErrorClose;
  619. ErrorOpen := 0;
  620. end;
  621. procedure AssignError (var T: Text);
  622. begin
  623. Assign (T, '');
  624. TextRec (T).OpenFunc := @ErrorOpen;
  625. Rewrite (T);
  626. end;
  627. procedure SysInitStdIO;
  628. (*
  629. var
  630. RC: cardinal;
  631. *)
  632. begin
  633. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  634. displayed in a messagebox }
  635. (*
  636. StdInputHandle := longint(GetStdHandle(cardinal(STD_INPUT_HANDLE)));
  637. StdOutputHandle := longint(GetStdHandle(cardinal(STD_OUTPUT_HANDLE)));
  638. StdErrorHandle := longint(GetStdHandle(cardinal(STD_ERROR_HANDLE)));
  639. if not IsConsole then
  640. begin
  641. RC := DosLoadModule (nil, 0, 'PMWIN', PMWinHandle);
  642. if RC <> 0 then
  643. OSErrorWatch (RC)
  644. else
  645. begin
  646. RC := DosQueryProcAddr (PMWinHandle, 789, nil, pointer (WinMessageBox));
  647. if RC <> 0 then
  648. OSErrorWatch (RC)
  649. else
  650. begin
  651. RC := DosQueryProcAddr (PMWinHandle, 763, nil, pointer (WinInitialize));
  652. if RC <> 0 then
  653. OSErrorWatch (RC)
  654. else
  655. begin
  656. RC := DosQueryProcAddr (PMWinHandle, 716, nil, pointer (WinCreateMsgQueue));
  657. if RC <> 0 then
  658. OSErrorWatch (RC)
  659. else
  660. begin
  661. WinInitialize (0);
  662. WinCreateMsgQueue (0, 0);
  663. end
  664. end
  665. end
  666. end;
  667. if RC <> 0 then
  668. HandleError (2);
  669. AssignError (StdErr);
  670. AssignError (StdOut);
  671. Assign (Output, '');
  672. Assign (Input, '');
  673. end
  674. else
  675. begin
  676. *)
  677. OpenStdIO (Input, fmInput, StdInputHandle);
  678. OpenStdIO (Output, fmOutput, StdOutputHandle);
  679. OpenStdIO (ErrOutput, fmOutput, StdErrorHandle);
  680. OpenStdIO (StdOut, fmOutput, StdOutputHandle);
  681. OpenStdIO (StdErr, fmOutput, StdErrorHandle);
  682. (*
  683. end;
  684. *)
  685. end;
  686. function strcopy(dest,source : pchar) : pchar;assembler;
  687. var
  688. saveeax,saveesi,saveedi : longint;
  689. asm
  690. movl %edi,saveedi
  691. movl %esi,saveesi
  692. {$ifdef REGCALL}
  693. movl %eax,saveeax
  694. movl %edx,%edi
  695. {$else}
  696. movl source,%edi
  697. {$endif}
  698. testl %edi,%edi
  699. jz .LStrCopyDone
  700. leal 3(%edi),%ecx
  701. andl $-4,%ecx
  702. movl %edi,%esi
  703. subl %edi,%ecx
  704. {$ifdef REGCALL}
  705. movl %eax,%edi
  706. {$else}
  707. movl dest,%edi
  708. {$endif}
  709. jz .LStrCopyAligned
  710. .LStrCopyAlignLoop:
  711. movb (%esi),%al
  712. incl %edi
  713. incl %esi
  714. testb %al,%al
  715. movb %al,-1(%edi)
  716. jz .LStrCopyDone
  717. decl %ecx
  718. jnz .LStrCopyAlignLoop
  719. .balign 16
  720. .LStrCopyAligned:
  721. movl (%esi),%eax
  722. movl %eax,%edx
  723. leal 0x0fefefeff(%eax),%ecx
  724. notl %edx
  725. addl $4,%esi
  726. andl %edx,%ecx
  727. andl $0x080808080,%ecx
  728. jnz .LStrCopyEndFound
  729. movl %eax,(%edi)
  730. addl $4,%edi
  731. jmp .LStrCopyAligned
  732. .LStrCopyEndFound:
  733. testl $0x0ff,%eax
  734. jz .LStrCopyByte
  735. testl $0x0ff00,%eax
  736. jz .LStrCopyWord
  737. testl $0x0ff0000,%eax
  738. jz .LStrCopy3Bytes
  739. movl %eax,(%edi)
  740. jmp .LStrCopyDone
  741. .LStrCopy3Bytes:
  742. xorb %dl,%dl
  743. movw %ax,(%edi)
  744. movb %dl,2(%edi)
  745. jmp .LStrCopyDone
  746. .LStrCopyWord:
  747. movw %ax,(%edi)
  748. jmp .LStrCopyDone
  749. .LStrCopyByte:
  750. movb %al,(%edi)
  751. .LStrCopyDone:
  752. {$ifdef REGCALL}
  753. movl saveeax,%eax
  754. {$else}
  755. movl dest,%eax
  756. {$endif}
  757. movl saveedi,%edi
  758. movl saveesi,%esi
  759. end;
  760. threadvar
  761. DefaultCreator: ShortString;
  762. DefaultFileType: ShortString;
  763. procedure SetDefaultOS2FileType (FType: ShortString);
  764. begin
  765. {$WARNING Not implemented yet!}
  766. DefaultFileType := FType;
  767. end;
  768. procedure SetDefaultOS2Creator (Creator: ShortString);
  769. begin
  770. {$WARNING Not implemented yet!}
  771. DefaultCreator := Creator;
  772. end;
  773. (* The default handler does not store the OS/2 API error codes. *)
  774. procedure NoErrorTracking (Error: cardinal);
  775. begin
  776. end;
  777. procedure SetOSErrorTracking (P: pointer);
  778. begin
  779. if P = nil then
  780. OSErrorWatch := @NoErrorTracking
  781. else
  782. OSErrorWatch := TOSErrorWatch (P);
  783. end;
  784. procedure InitEnvironment;
  785. var env_count : longint;
  786. dos_env,cp : pchar;
  787. begin
  788. env_count:=0;
  789. cp:=environment;
  790. while cp ^ <> #0 do
  791. begin
  792. inc(env_count);
  793. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  794. inc(longint(cp)); { skip to next character }
  795. end;
  796. envp := sysgetmem((env_count+1) * sizeof(pchar));
  797. envc := env_count;
  798. if (envp = nil) then exit;
  799. cp:=environment;
  800. env_count:=0;
  801. while cp^ <> #0 do
  802. begin
  803. envp[env_count] := sysgetmem(strlen(cp)+1);
  804. strcopy(envp[env_count], cp);
  805. {$IfDef DEBUGENVIRONMENT}
  806. Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
  807. {$EndIf}
  808. inc(env_count);
  809. while (cp^ <> #0) do
  810. inc(longint(cp)); { skip to NUL }
  811. inc(longint(cp)); { skip to next character }
  812. end;
  813. envp[env_count]:=nil;
  814. end;
  815. var
  816. (* Initialized by system unit initialization *)
  817. PIB: PProcessInfoBlock;
  818. procedure InitArguments;
  819. var
  820. arglen,
  821. count : PtrInt;
  822. argstart,
  823. pc,arg : pchar;
  824. quote : char;
  825. argvlen : PtrInt;
  826. RC: cardinal;
  827. procedure allocarg(idx,len: PtrInt);
  828. var
  829. oldargvlen : PtrInt;
  830. begin
  831. if idx>=argvlen then
  832. begin
  833. oldargvlen:=argvlen;
  834. argvlen:=(idx+8) and (not 7);
  835. sysreallocmem(argv,argvlen*sizeof(pointer));
  836. { fillchar(argv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);}
  837. end;
  838. { use realloc to reuse already existing memory }
  839. { always allocate, even if length is zero, since }
  840. { the arg. is still present! }
  841. ArgV [Idx] := SysAllocMem (Succ (Len));
  842. end;
  843. begin
  844. CmdLine := SysAllocMem (MaxPathLen);
  845. ArgV := SysAllocMem (8 * SizeOf (pointer));
  846. ArgLen := StrLen (PChar (PIB^.Cmd));
  847. Inc (ArgLen);
  848. RC := DosQueryModuleName (PIB^.Handle, MaxPathLen, CmdLine);
  849. if RC = 0 then
  850. ArgVLen := Succ (StrLen (CmdLine))
  851. else
  852. (* Error occurred - use program name from command line as fallback. *)
  853. begin
  854. Move (PIB^.Cmd^, CmdLine, ArgLen);
  855. ArgVLen := ArgLen;
  856. end;
  857. { Get ArgV [0] }
  858. ArgV [0] := SysAllocMem (ArgVLen);
  859. Move (CmdLine^, ArgV [0]^, ArgVLen);
  860. Count := 1;
  861. (* PC points to leading space after program name on command line *)
  862. PC := PChar (PIB^.Cmd) + ArgLen;
  863. (* ArgLen contains size of command line arguments including leading space. *)
  864. ArgLen := Succ (StrLen (PC));
  865. SysReallocMem (CmdLine, ArgVLen + ArgLen);
  866. Move (PC^, CmdLine [ArgVLen], Succ (ArgLen));
  867. (* ArgV has space for 8 parameters from the first allocation. *)
  868. ArgVLen := 8;
  869. { process arguments }
  870. while pc^<>#0 do
  871. begin
  872. { skip leading spaces }
  873. while pc^ in [#1..#32] do
  874. inc(pc);
  875. if pc^=#0 then
  876. break;
  877. { calc argument length }
  878. quote:=' ';
  879. argstart:=pc;
  880. arglen:=0;
  881. while (pc^<>#0) do
  882. begin
  883. case pc^ of
  884. #1..#32 :
  885. begin
  886. if quote<>' ' then
  887. inc(arglen)
  888. else
  889. break;
  890. end;
  891. '"' :
  892. begin
  893. if quote<>'''' then
  894. begin
  895. if pchar(pc+1)^<>'"' then
  896. begin
  897. if quote='"' then
  898. quote:=' '
  899. else
  900. quote:='"';
  901. end
  902. else
  903. inc(pc);
  904. end
  905. else
  906. inc(arglen);
  907. end;
  908. '''' :
  909. begin
  910. if quote<>'"' then
  911. begin
  912. if pchar(pc+1)^<>'''' then
  913. begin
  914. if quote='''' then
  915. quote:=' '
  916. else
  917. quote:='''';
  918. end
  919. else
  920. inc(pc);
  921. end
  922. else
  923. inc(arglen);
  924. end;
  925. else
  926. inc(arglen);
  927. end;
  928. inc(pc);
  929. end;
  930. { copy argument }
  931. { Don't copy the first one, it is already there.}
  932. If Count<>0 then
  933. begin
  934. allocarg(count,arglen);
  935. quote:=' ';
  936. pc:=argstart;
  937. arg:=argv[count];
  938. while (pc^<>#0) do
  939. begin
  940. case pc^ of
  941. #1..#32 :
  942. begin
  943. if quote<>' ' then
  944. begin
  945. arg^:=pc^;
  946. inc(arg);
  947. end
  948. else
  949. break;
  950. end;
  951. '"' :
  952. begin
  953. if quote<>'''' then
  954. begin
  955. if pchar(pc+1)^<>'"' then
  956. begin
  957. if quote='"' then
  958. quote:=' '
  959. else
  960. quote:='"';
  961. end
  962. else
  963. inc(pc);
  964. end
  965. else
  966. begin
  967. arg^:=pc^;
  968. inc(arg);
  969. end;
  970. end;
  971. '''' :
  972. begin
  973. if quote<>'"' then
  974. begin
  975. if pchar(pc+1)^<>'''' then
  976. begin
  977. if quote='''' then
  978. quote:=' '
  979. else
  980. quote:='''';
  981. end
  982. else
  983. inc(pc);
  984. end
  985. else
  986. begin
  987. arg^:=pc^;
  988. inc(arg);
  989. end;
  990. end;
  991. else
  992. begin
  993. arg^:=pc^;
  994. inc(arg);
  995. end;
  996. end;
  997. inc(pc);
  998. end;
  999. arg^:=#0;
  1000. end;
  1001. {$IfDef DEBUGARGUMENTS}
  1002. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  1003. {$EndIf}
  1004. inc(count);
  1005. end;
  1006. { get argc and create an nil entry }
  1007. argc:=count;
  1008. allocarg(argc,0);
  1009. { free unused memory }
  1010. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  1011. end;
  1012. function GetFileHandleCount: longint;
  1013. var L1: longint;
  1014. L2: cardinal;
  1015. RC: cardinal;
  1016. begin
  1017. L1 := 0; (* Don't change the amount, just check. *)
  1018. RC := DosSetRelMaxFH (L1, L2);
  1019. if RC <> 0 then
  1020. begin
  1021. GetFileHandleCount := 50;
  1022. OSErrorWatch (RC);
  1023. end
  1024. else
  1025. GetFileHandleCount := L2;
  1026. end;
  1027. function CheckInitialStkLen (StkLen: SizeUInt): SizeUInt;
  1028. begin
  1029. CheckInitialStkLen := StkLen;
  1030. end;
  1031. var TIB: PThreadInfoBlock;
  1032. RC: cardinal;
  1033. ErrStr: string;
  1034. P: pointer;
  1035. DW: cardinal;
  1036. CPArr: TCPArray;
  1037. ReturnedSize: cardinal;
  1038. const
  1039. DosCallsName: array [0..8] of char = 'DOSCALLS'#0;
  1040. {$IFDEF OS2UNICODE}
  1041. {$I sysucode.inc}
  1042. {$ENDIF OS2UNICODE}
  1043. begin
  1044. {$IFDEF OS2EXCEPTIONS}
  1045. asm
  1046. xorl %eax,%eax
  1047. movw %ss,%ax
  1048. movl %eax,_SS
  1049. end;
  1050. {$ENDIF OS2EXCEPTIONS}
  1051. DosGetInfoBlocks (@TIB, @PIB);
  1052. StackLength := CheckInitialStkLen (InitialStkLen);
  1053. { OS/2 has top of stack in TIB^.StackLimit - unlike Windows where it is in TIB^.Stack }
  1054. StackBottom := TIB^.StackLimit - StackLength;
  1055. {Set type of application}
  1056. ApplicationType := PIB^.ProcType;
  1057. ProcessID := PIB^.PID;
  1058. ThreadID := TIB^.TIB2^.TID;
  1059. IsConsole := ApplicationType <> 3;
  1060. {Query maximum path length (QSV_MAX_PATH_LEN = 1)}
  1061. if DosQuerySysInfo (1, 1, DW, SizeOf (DW)) = 0 then
  1062. RealMaxPathLen := DW;
  1063. ExitProc := nil;
  1064. {$IFDEF OS2EXCEPTIONS}
  1065. Install_Exception_Handler;
  1066. {$ENDIF OS2EXCEPTIONS}
  1067. (* Initialize the amount of file handles *)
  1068. FileHandleCount := GetFileHandleCount;
  1069. {Initialize the heap.}
  1070. (* Logic is following:
  1071. The heap is initially restricted to low address space (< 512 MB).
  1072. If underlying OS/2 version allows using more than 512 MB per process
  1073. (OS/2 WarpServer for e-Business, eComStation, possibly OS/2 Warp 4.0
  1074. with FP13 and above as well), use of this high memory is allowed for
  1075. future memory allocations at the end of System unit initialization.
  1076. The consequences are that the compiled application can allocate more
  1077. memory, but it must make sure to use direct DosAllocMem calls if it
  1078. needs a memory block for some system API not supporting high memory.
  1079. This is probably no problem for direct calls to these APIs, but
  1080. there might be situations when a memory block needs to be passed
  1081. to a 3rd party DLL which in turn calls such an API call. In case
  1082. of problems usage of high memory can be turned off by setting
  1083. UseHighMem to false - the program should change the setting at its
  1084. very beginning (e.g. in initialization section of the first unit
  1085. listed in the "uses" section) to avoid having preallocated memory
  1086. from the high memory region before changing value of this variable. *)
  1087. InitHeap;
  1088. RC := DosQueryModuleHandle (@DosCallsName [0], DosCallsHandle);
  1089. if RC = 0 then
  1090. begin
  1091. RC := DosQueryProcAddr (DosCallsHandle, OrdDosOpenL, nil, P);
  1092. if RC = 0 then
  1093. begin
  1094. Sys_DosOpenL := TDosOpenL (P);
  1095. RC := DosQueryProcAddr (DosCallsHandle, OrdDosSetFilePtrL, nil, P);
  1096. if RC = 0 then
  1097. begin
  1098. Sys_DosSetFilePtrL := TDosSetFilePtrL (P);
  1099. RC := DosQueryProcAddr (DosCallsHandle, OrdDosSetFileSizeL, nil, P);
  1100. if RC = 0 then
  1101. begin
  1102. Sys_DosSetFileSizeL := TDosSetFileSizeL (P);
  1103. FSApi64 := true;
  1104. end;
  1105. end;
  1106. end;
  1107. if RC <> 0 then
  1108. OSErrorWatch (RC);
  1109. RC := DosQueryProcAddr (DosCallsHandle, OrdDosAllocThreadLocalMemory,
  1110. nil, P);
  1111. if RC = 0 then
  1112. begin
  1113. DosAllocThreadLocalMemory := TDosAllocThreadLocalMemory (P);
  1114. RC := DosQueryProcAddr (DosCallsHandle, OrdDosAllocThreadLocalMemory,
  1115. nil, P);
  1116. if RC = 0 then
  1117. begin
  1118. DosFreeThreadLocalMemory := TDosFreeThreadLocalMemory (P);
  1119. TLSAPISupported := true;
  1120. end
  1121. else
  1122. OSErrorWatch (RC);
  1123. end
  1124. else
  1125. OSErrorWatch (RC);
  1126. end
  1127. else
  1128. OSErrorWatch (RC);
  1129. { ... and exceptions }
  1130. SysInitExceptions;
  1131. fpc_cpucodeinit;
  1132. InitUnicodeStringManager;
  1133. {$ifdef OS2UCODE}
  1134. InitOS2WideStrings;
  1135. {$endif OS2UCODE}
  1136. { ... and I/O }
  1137. SysInitStdIO;
  1138. { no I/O-Error }
  1139. inoutres:=0;
  1140. {Initialize environment (must be after InitHeap because allocates memory)}
  1141. Environment := pointer (PIB^.Env);
  1142. InitEnvironment;
  1143. InitArguments;
  1144. DefaultCreator := '';
  1145. DefaultFileType := '';
  1146. InitSystemThreads;
  1147. InitVariantManager;
  1148. {$IFDEF EXTDUMPGROW}
  1149. { Int_HeapSize := high (cardinal);}
  1150. {$ENDIF EXTDUMPGROW}
  1151. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1152. if IsConsole then
  1153. WriteLn (StdErr, 'Old exception ', HexStr (OldExceptAddr, 8),
  1154. ', new exception ', HexStr (NewExceptAddr, 8), ', _SS = ', HexStr (_SS, 8));
  1155. {$endif SYSTEMEXCEPTIONDEBUG}
  1156. RC := DosQueryCP (SizeOf (CPArr), @CPArr, ReturnedSize);
  1157. if (RC <> 0) and (RC <> 473) then
  1158. OSErrorWatch (RC)
  1159. else if (ReturnedSize >= 4) then
  1160. begin
  1161. DefaultSystemCodePage := CPArr [0];
  1162. DefaultRTLFileSystemCodePage := DefaultSystemCodePage;
  1163. DefaultFileSystemCodePage := DefaultSystemCodePage;
  1164. DefaultUnicodeCodePage := CP_UTF16;
  1165. end
  1166. else
  1167. OSErrorWatch (RC);
  1168. end.