system.pp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2005 by Florian Klaempfl and Pavel Ozerski
  4. and Yury Sidorov member of the Free Pascal development team.
  5. FPC Pascal system unit for the WinCE.
  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. {$endif SYSTEMDEBUG}
  17. {$define WINCE_EXCEPTION_HANDLING}
  18. { include system-independent routine headers }
  19. {$I systemh.inc}
  20. const
  21. LineEnding = #13#10;
  22. LFNSupport = true;
  23. DirectorySeparator = '\';
  24. DriveSeparator = ':';
  25. PathSeparator = ';';
  26. { FileNameCaseSensitive is defined separately below!!! }
  27. maxExitCode = 65535;
  28. MaxPathLen = 260;
  29. const
  30. { Default filehandles }
  31. UnusedHandle : THandle = -1;
  32. StdInputHandle : THandle = 0;
  33. StdOutputHandle : THandle = 0;
  34. StdErrorHandle : THandle = 0;
  35. FileNameCaseSensitive : boolean = true;
  36. CtrlZMarksEOF: boolean = true; (* #26 not considered as end of file *)
  37. sLineBreak = LineEnding;
  38. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  39. { Thread count for DLL }
  40. Thread_count : longint = 0;
  41. var
  42. { C compatible arguments }
  43. argc : longint;
  44. argv : ppchar;
  45. { Win32 Info }
  46. hprevinst,
  47. HInstance,
  48. MainInstance,
  49. DLLreason,DLLparam:longint;
  50. Win32StackTop : Dword;
  51. type
  52. TDLL_Process_Entry_Hook = function (dllparam : longint) : longbool;
  53. TDLL_Entry_Hook = procedure (dllparam : longint);
  54. const
  55. Dll_Process_Attach_Hook : TDLL_Process_Entry_Hook = nil;
  56. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  57. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  58. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  59. type
  60. HMODULE = THandle;
  61. { Wrappers for some WinAPI calls }
  62. function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle; stdcall;
  63. function ResetEvent(h: THandle): LONGBOOL; stdcall;
  64. function SetEvent(h: THandle): LONGBOOL; stdcall;
  65. function GetCurrentProcessId:DWORD; stdcall;
  66. function Win32GetCurrentThreadId:DWORD; stdcall;
  67. function TlsAlloc : DWord; stdcall;
  68. function TlsFree(dwTlsIndex : DWord) : LongBool; stdcall;
  69. function GetFileAttributes(p : pchar) : dword; stdcall;
  70. function DeleteFile(p : pchar) : longint; stdcall;
  71. function MoveFile(old,_new : pchar) : longint; stdcall;
  72. function CreateFile(lpFileName:pchar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  73. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  74. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint; stdcall;
  75. function CreateDirectory(name : pointer;sec : pointer) : longbool; stdcall;
  76. function RemoveDirectory(name:pointer):longbool; stdcall;
  77. implementation
  78. { used by wstrings.inc because wstrings.inc is included before sysos.inc
  79. this is put here (FK) }
  80. (*
  81. function SysAllocStringLen(psz:pointer;len:dword):pointer;stdcall;
  82. external 'oleaut32.dll' name 'SysAllocStringLen';
  83. procedure SysFreeString(bstr:pointer);stdcall;
  84. external 'oleaut32.dll' name 'SysFreeString';
  85. function SysReAllocStringLen(var bstr:pointer;psz: pointer;
  86. len:dword): Integer; stdcall;external 'oleaut32.dll' name 'SysReAllocStringLen';
  87. *)
  88. function MessageBox(w1:longint;l1,l2:PWideChar;w2:longint):longint;
  89. stdcall;external 'coredll' name 'MessageBoxW';
  90. { include system independent routines }
  91. {$I system.inc}
  92. {*****************************************************************************
  93. ANSI <-> Wide
  94. *****************************************************************************}
  95. const
  96. { MultiByteToWideChar }
  97. MB_PRECOMPOSED = 1;
  98. MB_COMPOSITE = 2;
  99. MB_ERR_INVALID_CHARS = 8;
  100. MB_USEGLYPHCHARS = 4;
  101. CP_ACP = 0;
  102. CP_OEMCP = 1;
  103. function MultiByteToWideChar(CodePage:UINT; dwFlags:DWORD; lpMultiByteStr:PChar; cchMultiByte:longint; lpWideCharStr:PWideChar;cchWideChar:longint):longint;
  104. stdcall; external 'coredll' name 'MultiByteToWideChar';
  105. function WideCharToMultiByte(CodePage:UINT; dwFlags:DWORD; lpWideCharStr:PWideChar; cchWideChar:longint; lpMultiByteStr:PChar;cchMultiByte:longint; lpDefaultChar:PChar; lpUsedDefaultChar:pointer):longint;
  106. stdcall; external 'coredll' name 'WideCharToMultiByte';
  107. function AnsiToWideBuf(AnsiBuf: PChar; AnsiBufLen: longint; WideBuf: PWideChar; WideBufLen: longint): longint;
  108. begin
  109. Result := MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, AnsiBuf, AnsiBufLen, WideBuf, WideBufLen);
  110. end;
  111. function WideToAnsiBuf(WideBuf: PWideChar; WideBufLen: longint; AnsiBuf: PChar; AnsiBufLen: longint): longint;
  112. begin
  113. Result := WideCharToMultiByte(CP_ACP, 0, WideBuf, WideBufLen, AnsiBuf, AnsiBufLen, nil, nil);
  114. end;
  115. {*****************************************************************************
  116. WinAPI wrappers implementation
  117. *****************************************************************************}
  118. function GetFileAttributesW(p : pwidechar) : dword;
  119. stdcall;external KernelDLL name 'GetFileAttributesW';
  120. function DeleteFileW(p : pwidechar) : longint;
  121. stdcall;external KernelDLL name 'DeleteFileW';
  122. function MoveFileW(old,_new : pwidechar) : longint;
  123. stdcall;external KernelDLL name 'MoveFileW';
  124. function CreateFileW(lpFileName:pwidechar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  125. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  126. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  127. stdcall;external KernelDLL name 'CreateFileW';
  128. function CreateDirectoryW(name : pwidechar;sec : pointer) : longbool;
  129. stdcall;external KernelDLL name 'CreateDirectoryW';
  130. function RemoveDirectoryW(name:pwidechar):longbool;
  131. stdcall;external KernelDLL name 'RemoveDirectoryW';
  132. function GetFileAttributes(p : pchar) : dword; stdcall;
  133. var
  134. buf: array[0..MaxPathLen] of WideChar;
  135. begin
  136. AnsiToWideBuf(p, -1, buf, SizeOf(buf));
  137. GetFileAttributes := GetFileAttributesW(buf);
  138. end;
  139. function DeleteFile(p : pchar) : longint; stdcall;
  140. var
  141. buf: array[0..MaxPathLen] of WideChar;
  142. begin
  143. AnsiToWideBuf(p, -1, buf, SizeOf(buf));
  144. DeleteFile := DeleteFileW(buf);
  145. end;
  146. function MoveFile(old,_new : pchar) : longint; stdcall;
  147. var
  148. buf_old, buf_new: array[0..MaxPathLen] of WideChar;
  149. begin
  150. AnsiToWideBuf(old, -1, buf_old, SizeOf(buf_old));
  151. AnsiToWideBuf(_new, -1, buf_new, SizeOf(buf_new));
  152. MoveFile := MoveFileW(buf_old, buf_new);
  153. end;
  154. function CreateFile(lpFileName:pchar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  155. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  156. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint; stdcall;
  157. var
  158. buf: array[0..MaxPathLen] of WideChar;
  159. begin
  160. AnsiToWideBuf(lpFileName, -1, buf, SizeOf(buf));
  161. CreateFile := CreateFileW(buf, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  162. dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  163. end;
  164. function CreateDirectory(name : pointer;sec : pointer) : longbool; stdcall;
  165. var
  166. buf: array[0..MaxPathLen] of WideChar;
  167. begin
  168. AnsiToWideBuf(name, -1, buf, SizeOf(buf));
  169. CreateDirectory := CreateDirectoryW(buf, sec);
  170. end;
  171. function RemoveDirectory(name:pointer):longbool; stdcall;
  172. var
  173. buf: array[0..MaxPathLen] of WideChar;
  174. begin
  175. AnsiToWideBuf(name, -1, buf, SizeOf(buf));
  176. RemoveDirectory := RemoveDirectoryW(buf);
  177. end;
  178. const
  179. {$ifdef CPUARM}
  180. UserKData = $FFFFC800;
  181. {$else CPUARM}
  182. UserKData = $00005800;
  183. {$endif CPUARM}
  184. SYSHANDLE_OFFSET = $004;
  185. SYS_HANDLE_BASE = 64;
  186. SH_CURTHREAD = 1;
  187. SH_CURPROC = 2;
  188. type
  189. PHandle = ^THandle;
  190. const
  191. EVENT_PULSE = 1;
  192. EVENT_RESET = 2;
  193. EVENT_SET = 3;
  194. function CreateEventW(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:PWideChar): THandle;
  195. stdcall; external KernelDLL name 'CreateEventW';
  196. function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle; stdcall;
  197. var
  198. buf: array[0..MaxPathLen] of WideChar;
  199. begin
  200. AnsiToWideBuf(lpName, -1, buf, SizeOf(buf));
  201. CreateEvent := CreateEventW(lpEventAttributes, bManualReset, bInitialState, buf);
  202. end;
  203. function EventModify(h: THandle; func: DWORD): LONGBOOL;
  204. stdcall; external KernelDLL name 'EventModify';
  205. function TlsCall(p1, p2: DWORD): DWORD;
  206. stdcall; external KernelDLL name 'TlsCall';
  207. function ResetEvent(h: THandle): LONGBOOL; stdcall;
  208. begin
  209. ResetEvent := EventModify(h,EVENT_RESET);
  210. end;
  211. function SetEvent(h: THandle): LONGBOOL; stdcall;
  212. begin
  213. SetEvent := EventModify(h,EVENT_SET);
  214. end;
  215. function GetCurrentProcessId:DWORD; stdcall;
  216. var
  217. p: PHandle;
  218. begin
  219. p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURPROC*SizeOf(THandle));
  220. GetCurrentProcessId := p^;
  221. end;
  222. function Win32GetCurrentThreadId:DWORD; stdcall;
  223. var
  224. p: PHandle;
  225. begin
  226. p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURTHREAD*SizeOf(THandle));
  227. Win32GetCurrentThreadId := p^;
  228. end;
  229. const
  230. TLS_FUNCALLOC = 0;
  231. TLS_FUNCFREE = 1;
  232. function TlsAlloc : DWord; stdcall;
  233. begin
  234. TlsAlloc := TlsCall(TLS_FUNCALLOC, 0);
  235. end;
  236. function TlsFree(dwTlsIndex : DWord) : LongBool; stdcall;
  237. begin
  238. TlsFree := LongBool(TlsCall(TLS_FUNCFREE, dwTlsIndex));
  239. end;
  240. {*****************************************************************************
  241. Parameter Handling
  242. *****************************************************************************}
  243. function GetCommandLine : pwidechar;
  244. stdcall;external KernelDLL name 'GetCommandLineW';
  245. var
  246. ModuleName : array[0..255] of char;
  247. function GetCommandFile:pchar;
  248. var
  249. buf: array[0..MaxPathLen] of WideChar;
  250. begin
  251. if ModuleName[0] = #0 then begin
  252. GetModuleFileName(0, @buf, SizeOf(buf));
  253. WideToAnsiBuf(buf, -1, @ModuleName, SizeOf(ModuleName));
  254. end;
  255. GetCommandFile:=@ModuleName;
  256. end;
  257. procedure setup_arguments;
  258. var
  259. arglen,
  260. count : longint;
  261. argstart,
  262. pc,arg : pchar;
  263. quote : char;
  264. argvlen : longint;
  265. procedure allocarg(idx,len:longint);
  266. var
  267. oldargvlen : longint;
  268. begin
  269. if idx>=argvlen then
  270. begin
  271. oldargvlen:=argvlen;
  272. argvlen:=(idx+8) and (not 7);
  273. sysreallocmem(argv,argvlen*sizeof(pointer));
  274. fillchar(argv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);
  275. end;
  276. { use realloc to reuse already existing memory }
  277. { always allocate, even if length is zero, since }
  278. { the arg. is still present! }
  279. sysreallocmem(argv[idx],len+1);
  280. end;
  281. begin
  282. { create commandline, it starts with the executed filename which is argv[0] }
  283. { Win32 passes the command NOT via the args, but via getmodulefilename}
  284. argv:=nil;
  285. argvlen:=0;
  286. pc:=getcommandfile;
  287. Arglen:=0;
  288. while pc[Arglen] <> #0 do
  289. Inc(Arglen);
  290. allocarg(0,arglen);
  291. move(pc^,argv[0]^,arglen+1);
  292. { Setup cmdline variable }
  293. arg:=PChar(GetCommandLine);
  294. count:=WideToAnsiBuf(PWideChar(arg), -1, nil, 0);
  295. GetMem(cmdline, arglen + count + 3);
  296. cmdline^:='"';
  297. move(pc^, (cmdline + 1)^, arglen);
  298. (cmdline + arglen + 1)^:='"';
  299. (cmdline + arglen + 2)^:=' ';
  300. WideToAnsiBuf(PWideChar(arg), -1, cmdline + arglen + 3, count);
  301. { process arguments }
  302. count:=0;
  303. pc:=cmdline;
  304. {$IfDef SYSTEM_DEBUG_STARTUP}
  305. Writeln(stderr,'Win32 GetCommandLine is #',pc,'#');
  306. {$EndIf }
  307. while pc^<>#0 do
  308. begin
  309. { skip leading spaces }
  310. while pc^ in [#1..#32] do
  311. inc(pc);
  312. if pc^=#0 then
  313. break;
  314. { calc argument length }
  315. quote:=' ';
  316. argstart:=pc;
  317. arglen:=0;
  318. while (pc^<>#0) do
  319. begin
  320. case pc^ of
  321. #1..#32 :
  322. begin
  323. if quote<>' ' then
  324. inc(arglen)
  325. else
  326. break;
  327. end;
  328. '"' :
  329. begin
  330. if quote<>'''' then
  331. begin
  332. if pchar(pc+1)^<>'"' then
  333. begin
  334. if quote='"' then
  335. quote:=' '
  336. else
  337. quote:='"';
  338. end
  339. else
  340. inc(pc);
  341. end
  342. else
  343. inc(arglen);
  344. end;
  345. '''' :
  346. begin
  347. if quote<>'"' then
  348. begin
  349. if pchar(pc+1)^<>'''' then
  350. begin
  351. if quote='''' then
  352. quote:=' '
  353. else
  354. quote:='''';
  355. end
  356. else
  357. inc(pc);
  358. end
  359. else
  360. inc(arglen);
  361. end;
  362. else
  363. inc(arglen);
  364. end;
  365. inc(pc);
  366. end;
  367. { copy argument }
  368. { Don't copy the first one, it is already there.}
  369. If Count<>0 then
  370. begin
  371. allocarg(count,arglen);
  372. quote:=' ';
  373. pc:=argstart;
  374. arg:=argv[count];
  375. while (pc^<>#0) do
  376. begin
  377. case pc^ of
  378. #1..#32 :
  379. begin
  380. if quote<>' ' then
  381. begin
  382. arg^:=pc^;
  383. inc(arg);
  384. end
  385. else
  386. break;
  387. end;
  388. '"' :
  389. begin
  390. if quote<>'''' then
  391. begin
  392. if pchar(pc+1)^<>'"' then
  393. begin
  394. if quote='"' then
  395. quote:=' '
  396. else
  397. quote:='"';
  398. end
  399. else
  400. inc(pc);
  401. end
  402. else
  403. begin
  404. arg^:=pc^;
  405. inc(arg);
  406. end;
  407. end;
  408. '''' :
  409. begin
  410. if quote<>'"' then
  411. begin
  412. if pchar(pc+1)^<>'''' then
  413. begin
  414. if quote='''' then
  415. quote:=' '
  416. else
  417. quote:='''';
  418. end
  419. else
  420. inc(pc);
  421. end
  422. else
  423. begin
  424. arg^:=pc^;
  425. inc(arg);
  426. end;
  427. end;
  428. else
  429. begin
  430. arg^:=pc^;
  431. inc(arg);
  432. end;
  433. end;
  434. inc(pc);
  435. end;
  436. arg^:=#0;
  437. end;
  438. {$IfDef SYSTEM_DEBUG_STARTUP}
  439. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  440. {$EndIf SYSTEM_DEBUG_STARTUP}
  441. inc(count);
  442. end;
  443. { get argc and create an nil entry }
  444. argc:=count;
  445. allocarg(argc,0);
  446. { free unused memory }
  447. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  448. end;
  449. function paramcount : longint;
  450. begin
  451. paramcount := argc - 1;
  452. end;
  453. function paramstr(l : longint) : string;
  454. begin
  455. if (l>=0) and (l<argc) then
  456. paramstr:=strpas(argv[l])
  457. else
  458. paramstr:='';
  459. end;
  460. procedure randomize;
  461. begin
  462. randseed:=GetTickCount;
  463. end;
  464. {*****************************************************************************
  465. System Dependent Exit code
  466. *****************************************************************************}
  467. procedure PascalMain;stdcall;external name 'PASCALMAIN';
  468. procedure fpc_do_exit;stdcall;external name 'FPC_DO_EXIT';
  469. Procedure ExitDLL(Exitcode : longint); forward;
  470. procedure asm_exit(Exitcode : longint);external name 'asm_exit';
  471. Procedure system_exit;
  472. begin
  473. FreeMem(cmdline);
  474. { don't call ExitProcess inside
  475. the DLL exit code !!
  476. This crashes Win95 at least PM }
  477. if IsLibrary then
  478. ExitDLL(ExitCode);
  479. if not IsConsole then begin
  480. Close(stderr);
  481. Close(stdout);
  482. { what about Input and Output ?? PM }
  483. end;
  484. { call exitprocess, with cleanup as required }
  485. asm_exit(exitcode);
  486. end;
  487. var
  488. { value of the stack segment
  489. to check if the call stack can be written on exceptions }
  490. _SS : Cardinal;
  491. Const
  492. { DllEntryPoint }
  493. DLL_PROCESS_ATTACH = 1;
  494. DLL_THREAD_ATTACH = 2;
  495. DLL_PROCESS_DETACH = 0;
  496. DLL_THREAD_DETACH = 3;
  497. Var
  498. DLLBuf : Jmp_buf;
  499. Const
  500. DLLExitOK : boolean = true;
  501. function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
  502. var
  503. res : longbool;
  504. begin
  505. IsLibrary:=true;
  506. Dll_entry:=false;
  507. case DLLreason of
  508. DLL_PROCESS_ATTACH :
  509. begin
  510. If SetJmp(DLLBuf) = 0 then
  511. begin
  512. if assigned(Dll_Process_Attach_Hook) then
  513. begin
  514. res:=Dll_Process_Attach_Hook(DllParam);
  515. if not res then
  516. exit(false);
  517. end;
  518. PASCALMAIN;
  519. Dll_entry:=true;
  520. end
  521. else
  522. Dll_entry:=DLLExitOK;
  523. end;
  524. DLL_THREAD_ATTACH :
  525. begin
  526. inc(Thread_count);
  527. {$warning Allocate Threadvars !}
  528. if assigned(Dll_Thread_Attach_Hook) then
  529. Dll_Thread_Attach_Hook(DllParam);
  530. Dll_entry:=true; { return value is ignored }
  531. end;
  532. DLL_THREAD_DETACH :
  533. begin
  534. dec(Thread_count);
  535. if assigned(Dll_Thread_Detach_Hook) then
  536. Dll_Thread_Detach_Hook(DllParam);
  537. {$warning Release Threadvars !}
  538. Dll_entry:=true; { return value is ignored }
  539. end;
  540. DLL_PROCESS_DETACH :
  541. begin
  542. Dll_entry:=true; { return value is ignored }
  543. If SetJmp(DLLBuf) = 0 then
  544. begin
  545. FPC_DO_EXIT;
  546. end;
  547. if assigned(Dll_Process_Detach_Hook) then
  548. Dll_Process_Detach_Hook(DllParam);
  549. end;
  550. end;
  551. end;
  552. Procedure ExitDLL(Exitcode : longint);
  553. begin
  554. DLLExitOK:=ExitCode=0;
  555. LongJmp(DLLBuf,1);
  556. end;
  557. {$ifdef WINCE_EXCEPTION_HANDLING}
  558. //
  559. // Hardware exception handling
  560. //
  561. {
  562. Error code definitions for the Win32 API functions
  563. Values are 32 bit values layed out as follows:
  564. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  565. 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  566. +---+-+-+-----------------------+-------------------------------+
  567. |Sev|C|R| Facility | Code |
  568. +---+-+-+-----------------------+-------------------------------+
  569. where
  570. Sev - is the severity code
  571. 00 - Success
  572. 01 - Informational
  573. 10 - Warning
  574. 11 - Error
  575. C - is the Customer code flag
  576. R - is a reserved bit
  577. Facility - is the facility code
  578. Code - is the facility's status code
  579. }
  580. const
  581. SEVERITY_SUCCESS = $00000000;
  582. SEVERITY_INFORMATIONAL = $40000000;
  583. SEVERITY_WARNING = $80000000;
  584. SEVERITY_ERROR = $C0000000;
  585. const
  586. STATUS_SEGMENT_NOTIFICATION = $40000005;
  587. DBG_TERMINATE_THREAD = $40010003;
  588. DBG_TERMINATE_PROCESS = $40010004;
  589. DBG_CONTROL_C = $40010005;
  590. DBG_CONTROL_BREAK = $40010008;
  591. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  592. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  593. STATUS_BREAKPOINT = $80000003;
  594. STATUS_SINGLE_STEP = $80000004;
  595. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  596. STATUS_ACCESS_VIOLATION = $C0000005;
  597. STATUS_IN_PAGE_ERROR = $C0000006;
  598. STATUS_INVALID_HANDLE = $C0000008;
  599. STATUS_NO_MEMORY = $C0000017;
  600. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  601. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  602. STATUS_INVALID_DISPOSITION = $C0000026;
  603. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  604. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  605. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  606. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  607. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  608. STATUS_FLOAT_OVERFLOW = $C0000091;
  609. STATUS_FLOAT_STACK_CHECK = $C0000092;
  610. STATUS_FLOAT_UNDERFLOW = $C0000093;
  611. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  612. STATUS_INTEGER_OVERFLOW = $C0000095;
  613. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  614. STATUS_STACK_OVERFLOW = $C00000FD;
  615. STATUS_CONTROL_C_EXIT = $C000013A;
  616. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  617. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  618. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  619. const
  620. ExceptionContinueExecution = 0;
  621. ExceptionContinueSearch = 1;
  622. ExceptionNestedException = 2;
  623. ExceptionCollidedUnwind = 3;
  624. ExceptionExecuteHandler = 4;
  625. MaxExceptionLevel = 16;
  626. exceptLevel : Byte = 0;
  627. {$ifdef CPUARM}
  628. const
  629. CONTEXT_ARM = $0000040;
  630. CONTEXT_CONTROL = CONTEXT_ARM or $00000001;
  631. CONTEXT_INTEGER = CONTEXT_ARM or $00000002;
  632. CONTEXT_SEGMENTS = CONTEXT_ARM or $00000004;
  633. CONTEXT_FLOATING_POINT = CONTEXT_ARM or $00000008;
  634. CONTEXT_DEBUG_REGISTERS = CONTEXT_ARM or $00000010;
  635. CONTEXT_EXTENDED_REGISTERS = CONTEXT_ARM or $00000020;
  636. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  637. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  638. NUM_VFP_REGS = 32;
  639. NUM_EXTRA_CONTROL_REGS = 8;
  640. type
  641. PContext = ^TContext;
  642. TContext = record
  643. ContextFlags : LongWord;
  644. // This section is specified/returned if the ContextFlags word contains
  645. // the flag CONTEXT_INTEGER.
  646. R0 : LongWord;
  647. R1 : LongWord;
  648. R2 : LongWord;
  649. R3 : LongWord;
  650. R4 : LongWord;
  651. R5 : LongWord;
  652. R6 : LongWord;
  653. R7 : LongWord;
  654. R8 : LongWord;
  655. R9 : LongWord;
  656. R10 : LongWord;
  657. R11 : LongWord;
  658. R12 : LongWord;
  659. // This section is specified/returned if the ContextFlags word contains
  660. // the flag CONTEXT_CONTROL.
  661. Sp : LongWord;
  662. Lr : LongWord;
  663. Pc : LongWord;
  664. Psr : LongWord;
  665. Fpscr : LongWord;
  666. FpExc : LongWord;
  667. // Floating point registers
  668. S : array[0..(NUM_VFP_REGS + 1)-1] of LongWord;
  669. FpExtra : array[0..(NUM_EXTRA_CONTROL_REGS)-1] of LongWord;
  670. end;
  671. {$endif CPUARM}
  672. {$ifdef CPUI386}
  673. const
  674. CONTEXT_X86 = $00010000;
  675. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  676. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  677. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  678. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  679. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  680. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  681. MAXIMUM_SUPPORTED_EXTENSION = 512;
  682. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  683. type
  684. PFloatingSaveArea = ^TFloatingSaveArea;
  685. TFloatingSaveArea = packed record
  686. ControlWord : Cardinal;
  687. StatusWord : Cardinal;
  688. TagWord : Cardinal;
  689. ErrorOffset : Cardinal;
  690. ErrorSelector : Cardinal;
  691. DataOffset : Cardinal;
  692. DataSelector : Cardinal;
  693. RegisterArea : array[0..79] of Byte;
  694. Cr0NpxState : Cardinal;
  695. end;
  696. PContext = ^TContext;
  697. TContext = packed record
  698. //
  699. // The flags values within this flag control the contents of
  700. // a CONTEXT record.
  701. //
  702. ContextFlags : Cardinal;
  703. //
  704. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  705. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  706. // included in CONTEXT_FULL.
  707. //
  708. Dr0, Dr1, Dr2,
  709. Dr3, Dr6, Dr7 : Cardinal;
  710. //
  711. // This section is specified/returned if the
  712. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  713. //
  714. FloatSave : TFloatingSaveArea;
  715. //
  716. // This section is specified/returned if the
  717. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  718. //
  719. SegGs, SegFs,
  720. SegEs, SegDs : Cardinal;
  721. //
  722. // This section is specified/returned if the
  723. // ContextFlags word contains the flag CONTEXT_INTEGER.
  724. //
  725. Edi, Esi, Ebx,
  726. Edx, Ecx, Eax : Cardinal;
  727. //
  728. // This section is specified/returned if the
  729. // ContextFlags word contains the flag CONTEXT_CONTROL.
  730. //
  731. Ebp : Cardinal;
  732. Eip : Cardinal;
  733. SegCs : Cardinal;
  734. EFlags, Esp, SegSs : Cardinal;
  735. //
  736. // This section is specified/returned if the ContextFlags word
  737. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  738. // The format and contexts are processor specific
  739. //
  740. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  741. end;
  742. {$endif CPUI386}
  743. type
  744. PExceptionRecord = ^TExceptionRecord;
  745. TExceptionRecord = packed record
  746. ExceptionCode : Longint;
  747. ExceptionFlags : Longint;
  748. ExceptionRecord : PExceptionRecord;
  749. ExceptionAddress : Pointer;
  750. NumberParameters : Longint;
  751. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  752. end;
  753. PExceptionPointers = ^TExceptionPointers;
  754. TExceptionPointers = packed record
  755. ExceptionRecord : PExceptionRecord;
  756. ContextRecord : PContext;
  757. end;
  758. {$ifdef CPUI386}
  759. {**************************** i386 Exception handling *****************************************}
  760. function GetCurrentProcess:DWORD; stdcall;
  761. begin
  762. GetCurrentProcess := SH_CURPROC+SYS_HANDLE_BASE;
  763. end;
  764. function ReadProcessMemory(process : dword;address : pointer;dest : pointer;size : dword;bytesread : pdword) : longbool;
  765. stdcall;external 'coredll' name 'ReadProcessMemory';
  766. function is_prefetch(p : pointer) : boolean;
  767. var
  768. a : array[0..15] of byte;
  769. doagain : boolean;
  770. instrlo,instrhi,opcode : byte;
  771. i : longint;
  772. begin
  773. result:=false;
  774. { read memory savely without causing another exeception }
  775. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  776. exit;
  777. i:=0;
  778. doagain:=true;
  779. while doagain and (i<15) do
  780. begin
  781. opcode:=a[i];
  782. instrlo:=opcode and $f;
  783. instrhi:=opcode and $f0;
  784. case instrhi of
  785. { prefix? }
  786. $20,$30:
  787. doagain:=(instrlo and 7)=6;
  788. $60:
  789. doagain:=(instrlo and $c)=4;
  790. $f0:
  791. doagain:=instrlo in [0,2,3];
  792. $0:
  793. begin
  794. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  795. exit;
  796. end;
  797. else
  798. doagain:=false;
  799. end;
  800. inc(i);
  801. end;
  802. end;
  803. var
  804. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  805. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  806. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  807. {$ifdef SYSTEMEXCEPTIONDEBUG}
  808. procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
  809. begin
  810. if IsConsole then
  811. begin
  812. write(stderr,'HandleErrorAddrFrame(error=',error);
  813. write(stderr,',addr=',hexstr(addr,8));
  814. writeln(stderr,',frame=',hexstr(frame,8),')');
  815. end;
  816. HandleErrorAddrFrame(error,addr,frame);
  817. end;
  818. {$endif SYSTEMEXCEPTIONDEBUG}
  819. procedure JumpToHandleErrorFrame;
  820. var
  821. eip, ebp, error : Longint;
  822. begin
  823. // save ebp
  824. asm
  825. movl (%ebp),%eax
  826. movl %eax,ebp
  827. end;
  828. if (exceptLevel > 0) then
  829. dec(exceptLevel);
  830. eip:=exceptEip[exceptLevel];
  831. error:=exceptError[exceptLevel];
  832. {$ifdef SYSTEMEXCEPTIONDEBUG}
  833. if IsConsole then
  834. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  835. {$endif SYSTEMEXCEPTIONDEBUG}
  836. if resetFPU[exceptLevel] then asm
  837. fninit
  838. fldcw fpucw
  839. end;
  840. { build a fake stack }
  841. asm
  842. {$ifdef REGCALL}
  843. movl ebp,%ecx
  844. movl eip,%edx
  845. movl error,%eax
  846. pushl eip
  847. movl ebp,%ebp // Change frame pointer
  848. {$else}
  849. movl ebp,%eax
  850. pushl %eax
  851. movl eip,%eax
  852. pushl %eax
  853. movl error,%eax
  854. pushl %eax
  855. movl eip,%eax
  856. pushl %eax
  857. movl ebp,%ebp // Change frame pointer
  858. {$endif}
  859. {$ifdef SYSTEMEXCEPTIONDEBUG}
  860. jmpl DebugHandleErrorAddrFrame
  861. {$else not SYSTEMEXCEPTIONDEBUG}
  862. jmpl HandleErrorAddrFrame
  863. {$endif SYSTEMEXCEPTIONDEBUG}
  864. end;
  865. end;
  866. function i386_exception_handler(ExceptionRecord: PExceptionRecord;
  867. EstablisherFrame: pointer; ContextRecord: PContext;
  868. DispatcherContext: pointer): longint; cdecl;
  869. var
  870. res: longint;
  871. must_reset_fpu: boolean;
  872. begin
  873. res := ExceptionContinueSearch;
  874. if ContextRecord^.SegSs=_SS then begin
  875. must_reset_fpu := true;
  876. {$ifdef SYSTEMEXCEPTIONDEBUG}
  877. if IsConsole then Writeln(stderr,'Exception ',
  878. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  879. {$endif SYSTEMEXCEPTIONDEBUG}
  880. case cardinal(ExceptionRecord^.ExceptionCode) of
  881. STATUS_INTEGER_DIVIDE_BY_ZERO,
  882. STATUS_FLOAT_DIVIDE_BY_ZERO :
  883. res := 200;
  884. STATUS_ARRAY_BOUNDS_EXCEEDED :
  885. begin
  886. res := 201;
  887. must_reset_fpu := false;
  888. end;
  889. STATUS_STACK_OVERFLOW :
  890. begin
  891. res := 202;
  892. must_reset_fpu := false;
  893. end;
  894. STATUS_FLOAT_OVERFLOW :
  895. res := 205;
  896. STATUS_FLOAT_DENORMAL_OPERAND,
  897. STATUS_FLOAT_UNDERFLOW :
  898. res := 206;
  899. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  900. STATUS_FLOAT_INEXACT_RESULT,
  901. STATUS_FLOAT_INVALID_OPERATION,
  902. STATUS_FLOAT_STACK_CHECK :
  903. res := 207;
  904. STATUS_INTEGER_OVERFLOW :
  905. begin
  906. res := 215;
  907. must_reset_fpu := false;
  908. end;
  909. STATUS_ILLEGAL_INSTRUCTION:
  910. res := 216;
  911. STATUS_ACCESS_VIOLATION:
  912. { Athlon prefetch bug? }
  913. if is_prefetch(pointer(ContextRecord^.Eip)) then
  914. begin
  915. { if yes, then retry }
  916. ExceptionRecord^.ExceptionCode := 0;
  917. res:=ExceptionContinueExecution;
  918. end
  919. else
  920. res := 216;
  921. STATUS_CONTROL_C_EXIT:
  922. res := 217;
  923. STATUS_PRIVILEGED_INSTRUCTION:
  924. begin
  925. res := 218;
  926. must_reset_fpu := false;
  927. end;
  928. else
  929. begin
  930. if ((ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  931. res := 217
  932. else
  933. res := 255;
  934. end;
  935. end;
  936. if (res >= 200) and (exceptLevel < MaxExceptionLevel) then begin
  937. exceptEip[exceptLevel] := ContextRecord^.Eip;
  938. exceptError[exceptLevel] := res;
  939. resetFPU[exceptLevel] := must_reset_fpu;
  940. inc(exceptLevel);
  941. ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  942. ExceptionRecord^.ExceptionCode := 0;
  943. res := ExceptionContinueExecution;
  944. {$ifdef SYSTEMEXCEPTIONDEBUG}
  945. if IsConsole then begin
  946. writeln(stderr,'Exception Continue Exception set at ',
  947. hexstr(exceptEip[exceptLevel],8));
  948. writeln(stderr,'Eip changed to ',
  949. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  950. end;
  951. {$endif SYSTEMEXCEPTIONDEBUG}
  952. end;
  953. end;
  954. i386_exception_handler := res;
  955. end;
  956. {$endif CPUI386}
  957. {$ifdef CPUARM}
  958. {**************************** ARM Exception handling *****************************************}
  959. var
  960. exceptPC : array[0..MaxExceptionLevel-1] of Longint;
  961. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  962. procedure JumpToHandleErrorFrame;
  963. var
  964. _pc, _fp, _error : Longint;
  965. begin
  966. // get original fp
  967. asm
  968. ldr r0,[r11,#-12]
  969. str r0,_fp
  970. end;
  971. if (exceptLevel > 0) then
  972. dec(exceptLevel);
  973. _pc:=exceptPC[exceptLevel];
  974. _error:=exceptError[exceptLevel];
  975. asm
  976. ldr r0,_error
  977. ldr r1,_pc
  978. ldr r2,_fp
  979. mov r11,r2 // Change frame pointer
  980. b HandleErrorAddrFrame
  981. end;
  982. end;
  983. function ARM_ExceptionHandler(ExceptionRecord: PExceptionRecord;
  984. EstablisherFrame: pointer; ContextRecord: PContext;
  985. DispatcherContext: pointer): longint; [public, alias : '_ARM_ExceptionHandler'];
  986. var
  987. res: longint;
  988. begin
  989. res := ExceptionContinueSearch;
  990. case cardinal(ExceptionRecord^.ExceptionCode) of
  991. STATUS_INTEGER_DIVIDE_BY_ZERO,
  992. STATUS_FLOAT_DIVIDE_BY_ZERO :
  993. res := 200;
  994. STATUS_ARRAY_BOUNDS_EXCEEDED :
  995. res := 201;
  996. STATUS_STACK_OVERFLOW :
  997. res := 202;
  998. STATUS_FLOAT_OVERFLOW :
  999. res := 205;
  1000. STATUS_FLOAT_DENORMAL_OPERAND,
  1001. STATUS_FLOAT_UNDERFLOW :
  1002. res := 206;
  1003. STATUS_FLOAT_INEXACT_RESULT,
  1004. STATUS_FLOAT_INVALID_OPERATION,
  1005. STATUS_FLOAT_STACK_CHECK :
  1006. res := 207;
  1007. STATUS_INTEGER_OVERFLOW :
  1008. res := 215;
  1009. STATUS_ILLEGAL_INSTRUCTION:
  1010. res := 216;
  1011. STATUS_ACCESS_VIOLATION:
  1012. res := 216;
  1013. STATUS_CONTROL_C_EXIT:
  1014. res := 217;
  1015. STATUS_PRIVILEGED_INSTRUCTION:
  1016. res := 218;
  1017. else
  1018. begin
  1019. if ((ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1020. res := 217
  1021. else
  1022. res := 255;
  1023. end;
  1024. end;
  1025. if (res <> ExceptionContinueSearch) and (exceptLevel < MaxExceptionLevel) then begin
  1026. exceptPC[exceptLevel] := ContextRecord^.PC;
  1027. exceptError[exceptLevel] := res;
  1028. inc(exceptLevel);
  1029. ContextRecord^.PC := Longint(@JumpToHandleErrorFrame);
  1030. ExceptionRecord^.ExceptionCode := 0;
  1031. res := ExceptionContinueExecution;
  1032. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1033. if IsConsole then begin
  1034. writeln(stderr,'Exception Continue Exception set at ',
  1035. hexstr(exceptEip[exceptLevel],8));
  1036. writeln(stderr,'Eip changed to ',
  1037. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1038. end;
  1039. {$endif SYSTEMEXCEPTIONDEBUG}
  1040. end;
  1041. ARM_ExceptionHandler := res;
  1042. end;
  1043. {$endif CPUARM}
  1044. {$endif WINCE_EXCEPTION_HANDLING}
  1045. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  1046. begin
  1047. IsLibrary:=false;
  1048. {$ifdef CPUARM}
  1049. asm
  1050. mov fp,#0
  1051. bl PASCALMAIN;
  1052. end;
  1053. {$endif CPUARM}
  1054. {$ifdef CPUI386}
  1055. asm
  1056. {$ifdef WINCE_EXCEPTION_HANDLING}
  1057. pushl i386_exception_handler
  1058. pushl %fs:(0)
  1059. mov %esp,%fs:(0)
  1060. {$endif WINCE_EXCEPTION_HANDLING}
  1061. pushl %ebp
  1062. xorl %ebp,%ebp
  1063. movl %esp,%eax
  1064. movl %eax,Win32StackTop
  1065. movw %ss,%bp
  1066. movl %ebp,_SS
  1067. call SysResetFPU
  1068. xorl %ebp,%ebp
  1069. call PASCALMAIN
  1070. popl %ebp
  1071. {$ifdef WINCE_EXCEPTION_HANDLING}
  1072. popl %fs:(0)
  1073. addl $4, %esp
  1074. {$endif WINCE_EXCEPTION_HANDLING}
  1075. end;
  1076. {$endif CPUI386}
  1077. { if we pass here there was no error ! }
  1078. system_exit;
  1079. end;
  1080. {****************************************************************************
  1081. OS dependend widestrings
  1082. ****************************************************************************}
  1083. function CharUpperBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; stdcall; external KernelDLL name 'CharUpperBuffW';
  1084. function CharLowerBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; stdcall; external KernelDLL name 'CharLowerBuffW';
  1085. function Win32WideUpper(const s : WideString) : WideString;
  1086. begin
  1087. result:=s;
  1088. UniqueString(result);
  1089. if length(result)>0 then
  1090. CharUpperBuff(LPWSTR(result),length(result));
  1091. end;
  1092. function Win32WideLower(const s : WideString) : WideString;
  1093. begin
  1094. result:=s;
  1095. UniqueString(result);
  1096. if length(result)>0 then
  1097. CharLowerBuff(LPWSTR(result),length(result));
  1098. end;
  1099. { there is a similiar procedure in sysutils which inits the fields which
  1100. are only relevant for the sysutils units }
  1101. procedure InitWin32Widestrings;
  1102. begin
  1103. widestringmanager.UpperWideStringProc:=@Win32WideUpper;
  1104. widestringmanager.LowerWideStringProc:=@Win32WideLower;
  1105. end;
  1106. {****************************************************************************
  1107. Error Message writing using messageboxes
  1108. ****************************************************************************}
  1109. const
  1110. ErrorBufferLength = 1024;
  1111. var
  1112. ErrorBuf : array[0..ErrorBufferLength] of char;
  1113. ErrorBufW : array[0..ErrorBufferLength] of widechar;
  1114. ErrorLen : longint;
  1115. Function ErrorWrite(Var F: TextRec): Integer;
  1116. {
  1117. An error message should always end with #13#10#13#10
  1118. }
  1119. var
  1120. p : pchar;
  1121. i : longint;
  1122. Begin
  1123. if F.BufPos>0 then
  1124. begin
  1125. if F.BufPos+ErrorLen>ErrorBufferLength then
  1126. i:=ErrorBufferLength-ErrorLen
  1127. else
  1128. i:=F.BufPos;
  1129. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  1130. inc(ErrorLen,i);
  1131. ErrorBuf[ErrorLen]:=#0;
  1132. end;
  1133. if ErrorLen>3 then
  1134. begin
  1135. p:=@ErrorBuf[ErrorLen];
  1136. for i:=1 to 4 do
  1137. begin
  1138. dec(p);
  1139. if not(p^ in [#10,#13]) then
  1140. break;
  1141. end;
  1142. end;
  1143. if ErrorLen=ErrorBufferLength then
  1144. i:=4;
  1145. if (i=4) then
  1146. begin
  1147. AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
  1148. MessageBox(0,@ErrorBufW,'Error',0);
  1149. ErrorLen:=0;
  1150. end;
  1151. F.BufPos:=0;
  1152. ErrorWrite:=0;
  1153. End;
  1154. Function ErrorClose(Var F: TextRec): Integer;
  1155. begin
  1156. if ErrorLen>0 then
  1157. begin
  1158. AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
  1159. MessageBox(0,@ErrorBufW,'Error',0);
  1160. ErrorLen:=0;
  1161. end;
  1162. ErrorLen:=0;
  1163. ErrorClose:=0;
  1164. end;
  1165. Function ErrorOpen(Var F: TextRec): Integer;
  1166. Begin
  1167. TextRec(F).InOutFunc:=@ErrorWrite;
  1168. TextRec(F).FlushFunc:=@ErrorWrite;
  1169. TextRec(F).CloseFunc:=@ErrorClose;
  1170. ErrorOpen:=0;
  1171. End;
  1172. procedure AssignError(Var T: Text);
  1173. begin
  1174. Assign(T,'');
  1175. TextRec(T).OpenFunc:=@ErrorOpen;
  1176. Rewrite(T);
  1177. end;
  1178. function _getstdfilex(fd: integer): pointer; cdecl; external 'coredll';
  1179. function _fileno(fd: pointer): THandle; cdecl; external 'coredll';
  1180. procedure SysInitStdIO;
  1181. begin
  1182. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1183. displayed in and messagebox }
  1184. StdInputHandle:=_fileno(_getstdfilex(0));
  1185. StdOutputHandle:=_fileno(_getstdfilex(1));
  1186. StdErrorHandle:=_fileno(_getstdfilex(3));
  1187. if not IsConsole then begin
  1188. AssignError(stderr);
  1189. AssignError(stdout);
  1190. Assign(Output,'');
  1191. Assign(Input,'');
  1192. Assign(ErrOutput,'');
  1193. end
  1194. else begin
  1195. OpenStdIO(Input,fmInput,StdInputHandle);
  1196. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1197. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  1198. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1199. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1200. end;
  1201. end;
  1202. (* ProcessID cached to avoid repeated calls to GetCurrentProcess. *)
  1203. var
  1204. ProcessID: SizeUInt;
  1205. function GetProcessID: SizeUInt;
  1206. begin
  1207. GetProcessID := ProcessID;
  1208. end;
  1209. procedure GetLibraryInstance;
  1210. var
  1211. buf: array[0..MaxPathLen] of WideChar;
  1212. begin
  1213. GetModuleFileName(0, @buf, SizeOf(buf));
  1214. HInstance:=GetModuleHandle(@buf);
  1215. end;
  1216. const
  1217. Exe_entry_code : pointer = @Exe_entry;
  1218. Dll_entry_code : pointer = @Dll_entry;
  1219. begin
  1220. StackLength := InitialStkLen;
  1221. StackBottom := Sptr - StackLength;
  1222. { some misc stuff }
  1223. hprevinst:=0;
  1224. if not IsLibrary then
  1225. GetLibraryInstance;
  1226. MainInstance:=HInstance;
  1227. { Setup heap }
  1228. InitHeap;
  1229. SysInitExceptions;
  1230. SysInitStdIO;
  1231. { Arguments }
  1232. setup_arguments;
  1233. { Reset IO Error }
  1234. InOutRes:=0;
  1235. ProcessID := GetCurrentProcessID;
  1236. { threading }
  1237. InitSystemThreads;
  1238. { Reset internal error variable }
  1239. errno:=0;
  1240. initvariantmanager;
  1241. initwidestringmanager;
  1242. InitWin32Widestrings
  1243. end.