system.pp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815
  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. {$define DISABLE_NO_THREAD_MANAGER}
  19. {$define HAS_CMDLINE}
  20. {$define HAS_MT_MEMORYMANAGER} // comment this line to switch from wincemm to fpcmm
  21. {$define HAS_WIDESTRINGMANAGER}
  22. { include system-independent routine headers }
  23. {$I systemh.inc}
  24. const
  25. LineEnding = #13#10;
  26. LFNSupport = true;
  27. DirectorySeparator = '\';
  28. DriveSeparator = ':';
  29. PathSeparator = ';';
  30. { FileNameCaseSensitive is defined separately below!!! }
  31. maxExitCode = 65535;
  32. MaxPathLen = 260;
  33. const
  34. { Default filehandles }
  35. UnusedHandle : THandle = THandle(-1);
  36. StdInputHandle : THandle = 0;
  37. StdOutputHandle : THandle = 0;
  38. StdErrorHandle : THandle = 0;
  39. FileNameCaseSensitive : boolean = true;
  40. CtrlZMarksEOF: boolean = true; (* #26 not considered as end of file *)
  41. sLineBreak = LineEnding;
  42. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  43. { Thread count for DLL }
  44. Thread_count : longint = 0;
  45. var
  46. { WinCE Info }
  47. hprevinst,
  48. MainInstance,
  49. DLLreason,DLLparam:DWord;
  50. type
  51. TDLL_Process_Entry_Hook = function (dllparam : longint) : longbool;
  52. TDLL_Entry_Hook = procedure (dllparam : longint);
  53. const
  54. Dll_Process_Attach_Hook : TDLL_Process_Entry_Hook = nil;
  55. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  56. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  57. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  58. { ANSI <-> Wide }
  59. function AnsiToWideBuf(AnsiBuf: PChar; AnsiBufLen: longint; WideBuf: PWideChar; WideBufLen: longint): longint;
  60. function WideToAnsiBuf(WideBuf: PWideChar; WideBufLen: longint; AnsiBuf: PChar; AnsiBufLen: longint): longint;
  61. function PCharToPWideChar(str: PChar; strlen: longint = -1; outlen: PLongInt = nil): PWideChar;
  62. function StringToPWideChar(const s: AnsiString; outlen: PLongInt = nil): PWideChar;
  63. { Wrappers for some WinAPI calls }
  64. function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle;
  65. function ResetEvent(h: THandle): LONGBOOL;
  66. function SetEvent(h: THandle): LONGBOOL;
  67. function GetCurrentProcessId:DWORD;
  68. function Win32GetCurrentThreadId:DWORD;
  69. function TlsAlloc : DWord;
  70. function TlsFree(dwTlsIndex : DWord) : LongBool;
  71. function GetFileAttributes(p : pchar) : dword;
  72. function DeleteFile(p : pchar) : longint;
  73. function MoveFile(old,_new : pchar) : longint;
  74. function CreateFile(lpFileName:pchar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  75. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  76. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  77. function CreateDirectory(name : pointer;sec : pointer) : longbool;
  78. function RemoveDirectory(name:pointer):longbool;
  79. {$ifdef CPUARM}
  80. { the external directive isn't really necessary here because it is overriden by external (FK) }
  81. function addd(d1,d2 : double) : double; compilerproc;
  82. cdecl;external 'coredll' name '__addd';
  83. function subd(d1,d2 : double) : double; compilerproc;
  84. cdecl;external 'coredll' name '__subd';
  85. function muld(d1,d2 : double) : double; compilerproc;
  86. cdecl;external 'coredll' name '__muld';
  87. function divd(d1,d2 : double) : double; compilerproc;
  88. cdecl;external 'coredll' name '__divd';
  89. function eqd(d1,d2 : double) : boolean; compilerproc;
  90. cdecl;external 'coredll' name '__eqd';
  91. function ned(d1,d2 : double) : boolean; compilerproc;
  92. cdecl;external 'coredll' name '__ned';
  93. function ltd(d1,d2 : double) : boolean; compilerproc;
  94. cdecl;external 'coredll' name '__ltd';
  95. function gtd(d1,d2 : double) : boolean; compilerproc;
  96. cdecl;external 'coredll' name '__gtd';
  97. function ged(d1,d2 : double) : boolean; compilerproc;
  98. cdecl;external 'coredll' name '__ged';
  99. function led(d1,d2 : double) : boolean; compilerproc;
  100. cdecl;external 'coredll' name '__led';
  101. { ***************** single ******************** }
  102. function eqs(d1,d2 : single) : boolean; compilerproc;
  103. cdecl;external 'coredll' name '__eqs';
  104. function nes(d1,d2 : single) : boolean; compilerproc;
  105. cdecl;external 'coredll' name '__nes';
  106. function lts(d1,d2 : single) : boolean; compilerproc;
  107. cdecl;external 'coredll' name '__lts';
  108. function gts(d1,d2 : single) : boolean; compilerproc;
  109. cdecl;external 'coredll' name '__gts';
  110. function ges(d1,d2 : single) : boolean; compilerproc;
  111. cdecl;external 'coredll' name '__ges';
  112. function les(d1,d2 : single) : boolean; compilerproc;
  113. cdecl;external 'coredll' name '__les';
  114. function dtos(d : double) : single; compilerproc;
  115. cdecl;external 'coredll' name '__dtos';
  116. function stod(d : single) : double; compilerproc;
  117. cdecl;external 'coredll' name '__stod';
  118. function negs(d : single) : single; compilerproc;
  119. cdecl;external 'coredll' name '__negs';
  120. function negd(d : double) : double; compilerproc;
  121. cdecl;external 'coredll' name '__negd';
  122. function utod(i : dword) : double; compilerproc;
  123. cdecl;external 'coredll' name '__utod';
  124. function itod(i : longint) : double; compilerproc;
  125. cdecl;external 'coredll' name '__itod';
  126. function ui64tod(i : qword) : double; compilerproc;
  127. cdecl;external 'coredll' name '__u64tod';
  128. function i64tod(i : int64) : double; compilerproc;
  129. cdecl;external 'coredll' name '__i64tod';
  130. function adds(s1,s2 : single) : single; compilerproc;
  131. function subs(s1,s2 : single) : single; compilerproc;
  132. function muls(s1,s2 : single) : single; compilerproc;
  133. function divs(s1,s2 : single) : single; compilerproc;
  134. {$endif CPUARM}
  135. function CmdLine: PChar;
  136. { C compatible arguments }
  137. function argc: longint;
  138. function argv: ppchar;
  139. implementation
  140. var
  141. SysInstance : Longint;
  142. {$define HAS_RESOURCES}
  143. {$i winres.inc}
  144. function MessageBox(w1:longint;l1,l2:PWideChar;w2:longint):longint;
  145. cdecl; external 'coredll' name 'MessageBoxW';
  146. {*****************************************************************************}
  147. {$define FPC_SYSTEM_HAS_MOVE}
  148. procedure memmove(dest, src: pointer; count: longint);
  149. cdecl; external 'coredll' name 'memmove';
  150. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE']; {$ifdef SYSTEMINLINE}inline;{$endif}
  151. begin
  152. if count > 0 then
  153. memmove(@dest, @source, count);
  154. end;
  155. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  156. function memcmp(buf1, buf2: pointer; count: longint): longint;
  157. cdecl; external 'coredll' name 'memcmp';
  158. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt; {$ifdef SYSTEMINLINE}inline;{$endif}
  159. begin
  160. CompareByte := memcmp(@buf1, @buf2, len);
  161. end;
  162. {$ifdef CPUARM}
  163. {$define FPC_SYSTEM_HAS_INT}
  164. function floor(d : double) : double;
  165. cdecl;external 'coredll' name 'floor';
  166. function ceil(d : double) : double;
  167. cdecl;external 'coredll' name 'ceil';
  168. function fpc_int_real(d: ValReal): ValReal;compilerproc;
  169. begin
  170. if d > 0 then
  171. fpc_int_real:=floor(d)
  172. else
  173. fpc_int_real:=ceil(d);
  174. end;
  175. {$define FPC_SYSTEM_HAS_TRUNC}
  176. function __dtoi64(d: double) : int64; cdecl; external 'coredll';
  177. function fpc_trunc_real(d : ValReal) : int64; assembler; nostackframe; compilerproc;
  178. asm
  179. b __dtoi64
  180. end;
  181. {$define FPC_SYSTEM_HAS_ABS}
  182. function fabs(d: double): double; cdecl; external 'coredll';
  183. function fpc_abs_real(d : ValReal) : ValReal; assembler; nostackframe; compilerproc;
  184. asm
  185. b fabs
  186. end;
  187. {$define FPC_SYSTEM_HAS_SQRT}
  188. function coresqrt(d: double): double; cdecl; external 'coredll' name 'sqrt';
  189. function fpc_sqrt_real(d : ValReal) : ValReal; assembler; nostackframe; compilerproc;
  190. asm
  191. b coresqrt
  192. end;
  193. function adds(s1,s2 : single) : single;
  194. begin
  195. adds := addd(s1, s2);
  196. end;
  197. function subs(s1,s2 : single) : single;
  198. begin
  199. subs := subd(s1, s2);
  200. end;
  201. function muls(s1,s2 : single) : single;
  202. begin
  203. muls := muld(s1, s2);
  204. end;
  205. function divs(s1,s2 : single) : single;
  206. begin
  207. divs := divd(s1, s2);
  208. end;
  209. {$endif CPUARM}
  210. {*****************************************************************************}
  211. { include system independent routines }
  212. {$I system.inc}
  213. {*****************************************************************************
  214. ANSI <-> Wide
  215. *****************************************************************************}
  216. const
  217. { MultiByteToWideChar }
  218. MB_PRECOMPOSED = 1;
  219. MB_COMPOSITE = 2;
  220. MB_ERR_INVALID_CHARS = 8;
  221. MB_USEGLYPHCHARS = 4;
  222. CP_ACP = 0;
  223. CP_OEMCP = 1;
  224. function MultiByteToWideChar(CodePage:UINT; dwFlags:DWORD; lpMultiByteStr:PChar; cchMultiByte:longint; lpWideCharStr:PWideChar;cchWideChar:longint):longint;
  225. cdecl; external 'coredll' name 'MultiByteToWideChar';
  226. function WideCharToMultiByte(CodePage:UINT; dwFlags:DWORD; lpWideCharStr:PWideChar; cchWideChar:longint; lpMultiByteStr:PChar;cchMultiByte:longint; lpDefaultChar:PChar; lpUsedDefaultChar:pointer):longint;
  227. cdecl; external 'coredll' name 'WideCharToMultiByte';
  228. function AnsiToWideBuf(AnsiBuf: PChar; AnsiBufLen: longint; WideBuf: PWideChar; WideBufLen: longint): longint;
  229. begin
  230. Result := MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, AnsiBuf, AnsiBufLen, WideBuf, WideBufLen div SizeOf(WideChar));
  231. if ((AnsiBufLen <> -1) or (Result = 0)) and (WideBuf <> nil) then
  232. begin
  233. if (Result + 1)*SizeOf(WideChar) > WideBufLen then
  234. begin
  235. Result := 0;
  236. if WideBufLen < SizeOf(WideChar) then
  237. exit;
  238. end;
  239. WideBuf[Result] := #0;
  240. if (Result <> 0) or (AnsiBufLen = 0) then
  241. Inc(Result);
  242. end;
  243. Result:=Result*SizeOf(WideChar);
  244. end;
  245. function WideToAnsiBuf(WideBuf: PWideChar; WideBufLen: longint; AnsiBuf: PChar; AnsiBufLen: longint): longint;
  246. begin
  247. Result := WideCharToMultiByte(CP_ACP, 0, WideBuf, WideBufLen, AnsiBuf, AnsiBufLen, nil, nil);
  248. if ((WideBufLen <> -1) or (Result = 0)) and (AnsiBuf <> nil) then
  249. begin
  250. if Result + 1 > AnsiBufLen then
  251. begin
  252. Result := 0;
  253. if AnsiBufLen < 1 then
  254. exit;
  255. end;
  256. AnsiBuf[Result] := #0;
  257. if (Result <> 0) or (WideBufLen = 0) then
  258. Inc(Result);
  259. end;
  260. end;
  261. function PCharToPWideChar(str: PChar; strlen: longint = -1; outlen: PLongInt = nil): PWideChar;
  262. var
  263. len: longint;
  264. begin
  265. while True do begin
  266. if strlen <> -1 then
  267. len:=(strlen + 1)
  268. else
  269. len:=AnsiToWideBuf(str, -1, nil, 0);
  270. if len > 0 then
  271. begin
  272. len:=len*SizeOf(WideChar);
  273. GetMem(Result, len);
  274. if (AnsiToWideBuf(str, -1, Result, len) = 0) and (strlen <> -1) then
  275. begin
  276. strlen:=-1;
  277. continue;
  278. end;
  279. end
  280. else begin
  281. GetMem(Result, SizeOf(WideChar));
  282. Inc(len);
  283. Result^:=#0;
  284. end;
  285. break;
  286. end;
  287. if outlen <> nil then
  288. outlen^:=(len - 1)*SizeOf(WideChar);
  289. end;
  290. function StringToPWideChar(const s: AnsiString; outlen: PLongInt = nil): PWideChar;
  291. var
  292. len, wlen: longint;
  293. begin
  294. len:=Length(s);
  295. wlen:=(len + 1)*SizeOf(WideChar);
  296. GetMem(Result, wlen);
  297. wlen:=AnsiToWideBuf(PChar(s), len, Result, wlen);
  298. if wlen = 0 then
  299. begin
  300. wlen:=AnsiToWideBuf(PChar(s), len, nil, 0);
  301. if wlen > 0 then
  302. begin
  303. ReAllocMem(Result, wlen);
  304. wlen:=AnsiToWideBuf(PChar(s), len, Result, wlen);
  305. end
  306. else
  307. begin
  308. Result^:=#0;
  309. wlen:=SizeOf(WideChar);
  310. end;
  311. end;
  312. if outlen <> nil then
  313. outlen^:=(wlen - 1) div SizeOf(WideChar);
  314. end;
  315. {*****************************************************************************
  316. WinAPI wrappers implementation
  317. *****************************************************************************}
  318. function GetFileAttributesW(p : pwidechar) : dword;
  319. cdecl; external KernelDLL name 'GetFileAttributesW';
  320. function DeleteFileW(p : pwidechar) : longint;
  321. cdecl; external KernelDLL name 'DeleteFileW';
  322. function MoveFileW(old,_new : pwidechar) : longint;
  323. cdecl; external KernelDLL name 'MoveFileW';
  324. function CreateFileW(lpFileName:pwidechar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  325. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  326. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  327. cdecl; external KernelDLL name 'CreateFileW';
  328. function CreateDirectoryW(name : pwidechar;sec : pointer) : longbool;
  329. cdecl; external KernelDLL name 'CreateDirectoryW';
  330. function RemoveDirectoryW(name:pwidechar):longbool;
  331. cdecl; external KernelDLL name 'RemoveDirectoryW';
  332. function GetFileAttributes(p : pchar) : dword;
  333. var
  334. buf: array[0..MaxPathLen] of WideChar;
  335. begin
  336. AnsiToWideBuf(p, -1, buf, SizeOf(buf));
  337. GetFileAttributes := GetFileAttributesW(buf);
  338. end;
  339. function DeleteFile(p : pchar) : longint;
  340. var
  341. buf: array[0..MaxPathLen] of WideChar;
  342. begin
  343. AnsiToWideBuf(p, -1, buf, SizeOf(buf));
  344. DeleteFile := DeleteFileW(buf);
  345. end;
  346. function MoveFile(old,_new : pchar) : longint;
  347. var
  348. buf_old, buf_new: array[0..MaxPathLen] of WideChar;
  349. begin
  350. AnsiToWideBuf(old, -1, buf_old, SizeOf(buf_old));
  351. AnsiToWideBuf(_new, -1, buf_new, SizeOf(buf_new));
  352. MoveFile := MoveFileW(buf_old, buf_new);
  353. end;
  354. function CreateFile(lpFileName:pchar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  355. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  356. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  357. var
  358. buf: array[0..MaxPathLen] of WideChar;
  359. begin
  360. AnsiToWideBuf(lpFileName, -1, buf, SizeOf(buf));
  361. CreateFile := CreateFileW(buf, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  362. dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  363. end;
  364. function CreateDirectory(name : pointer;sec : pointer) : longbool;
  365. var
  366. buf: array[0..MaxPathLen] of WideChar;
  367. begin
  368. AnsiToWideBuf(name, -1, buf, SizeOf(buf));
  369. CreateDirectory := CreateDirectoryW(buf, sec);
  370. end;
  371. function RemoveDirectory(name:pointer):longbool;
  372. var
  373. buf: array[0..MaxPathLen] of WideChar;
  374. begin
  375. AnsiToWideBuf(name, -1, buf, SizeOf(buf));
  376. RemoveDirectory := RemoveDirectoryW(buf);
  377. end;
  378. const
  379. {$ifdef CPUARM}
  380. UserKData = $FFFFC800;
  381. {$else CPUARM}
  382. UserKData = $00005800;
  383. {$endif CPUARM}
  384. SYSHANDLE_OFFSET = $004;
  385. SYS_HANDLE_BASE = 64;
  386. SH_CURTHREAD = 1;
  387. SH_CURPROC = 2;
  388. type
  389. PHandle = ^THandle;
  390. const
  391. EVENT_PULSE = 1;
  392. EVENT_RESET = 2;
  393. EVENT_SET = 3;
  394. function CreateEventW(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:PWideChar): THandle;
  395. cdecl; external KernelDLL name 'CreateEventW';
  396. function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle;
  397. var
  398. buf: array[0..MaxPathLen] of WideChar;
  399. begin
  400. AnsiToWideBuf(lpName, -1, buf, SizeOf(buf));
  401. CreateEvent := CreateEventW(lpEventAttributes, bManualReset, bInitialState, buf);
  402. end;
  403. function EventModify(h: THandle; func: DWORD): LONGBOOL;
  404. cdecl; external KernelDLL name 'EventModify';
  405. function TlsCall(p1, p2: DWORD): DWORD;
  406. cdecl; external KernelDLL name 'TlsCall';
  407. function ResetEvent(h: THandle): LONGBOOL;
  408. begin
  409. ResetEvent := EventModify(h,EVENT_RESET);
  410. end;
  411. function SetEvent(h: THandle): LONGBOOL;
  412. begin
  413. SetEvent := EventModify(h,EVENT_SET);
  414. end;
  415. function GetCurrentProcessId:DWORD;
  416. var
  417. p: PHandle;
  418. begin
  419. p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURPROC*SizeOf(THandle));
  420. GetCurrentProcessId := p^;
  421. end;
  422. function Win32GetCurrentThreadId:DWORD;
  423. var
  424. p: PHandle;
  425. begin
  426. p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURTHREAD*SizeOf(THandle));
  427. Win32GetCurrentThreadId := p^;
  428. end;
  429. const
  430. TLS_FUNCALLOC = 0;
  431. TLS_FUNCFREE = 1;
  432. function TlsAlloc : DWord;
  433. begin
  434. TlsAlloc := TlsCall(TLS_FUNCALLOC, 0);
  435. end;
  436. function TlsFree(dwTlsIndex : DWord) : LongBool;
  437. begin
  438. TlsFree := LongBool(TlsCall(TLS_FUNCFREE, dwTlsIndex));
  439. end;
  440. {*****************************************************************************
  441. Parameter Handling
  442. *****************************************************************************}
  443. function GetCommandLine : pwidechar;
  444. cdecl; external KernelDLL name 'GetCommandLineW';
  445. var
  446. ModuleName : array[0..255] of char;
  447. function GetCommandFile:pchar;
  448. var
  449. buf: array[0..MaxPathLen] of WideChar;
  450. begin
  451. if ModuleName[0] = #0 then begin
  452. GetModuleFileName(0, @buf, SizeOf(buf));
  453. WideToAnsiBuf(buf, -1, @ModuleName, SizeOf(ModuleName));
  454. end;
  455. GetCommandFile:=@ModuleName;
  456. end;
  457. var
  458. Fargc: longint;
  459. Fargv: ppchar;
  460. FCmdLine: PChar;
  461. procedure setup_arguments;
  462. var
  463. arglen,
  464. count : longint;
  465. argstart,
  466. pc,arg : pchar;
  467. quote : char;
  468. argvlen : longint;
  469. procedure allocarg(idx,len:longint);
  470. var
  471. oldargvlen : longint;
  472. begin
  473. if idx>=argvlen then
  474. begin
  475. oldargvlen:=argvlen;
  476. argvlen:=(idx+8) and (not 7);
  477. sysreallocmem(Fargv,argvlen*sizeof(pointer));
  478. fillchar(Fargv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);
  479. end;
  480. { use realloc to reuse already existing memory }
  481. { always allocate, even if length is zero, since }
  482. { the arg. is still present! }
  483. sysreallocmem(Fargv[idx],len+1);
  484. end;
  485. begin
  486. { create commandline, it starts with the executed filename which is argv[0] }
  487. { WinCE passes the command NOT via the args, but via getmodulefilename}
  488. if FCmdLine <> nil then exit;
  489. argvlen:=0;
  490. pc:=getcommandfile;
  491. Arglen:=0;
  492. while pc[Arglen] <> #0 do
  493. Inc(Arglen);
  494. allocarg(0,arglen);
  495. move(pc^,Fargv[0]^,arglen+1);
  496. { Setup FCmdLine variable }
  497. arg:=PChar(GetCommandLine);
  498. count:=WideToAnsiBuf(PWideChar(arg), -1, nil, 0);
  499. FCmdLine:=SysGetMem(arglen + count + 3);
  500. FCmdLine^:='"';
  501. move(pc^, (FCmdLine + 1)^, arglen);
  502. (FCmdLine + arglen + 1)^:='"';
  503. (FCmdLine + arglen + 2)^:=' ';
  504. WideToAnsiBuf(PWideChar(arg), -1, FCmdLine + arglen + 3, count);
  505. { process arguments }
  506. count:=0;
  507. pc:=FCmdLine;
  508. {$IfDef SYSTEM_DEBUG_STARTUP}
  509. Writeln(stderr,'WinCE GetCommandLine is #',pc,'#');
  510. {$EndIf }
  511. while pc^<>#0 do
  512. begin
  513. { skip leading spaces }
  514. while pc^ in [#1..#32] do
  515. inc(pc);
  516. if pc^=#0 then
  517. break;
  518. { calc argument length }
  519. quote:=' ';
  520. argstart:=pc;
  521. arglen:=0;
  522. while (pc^<>#0) do
  523. begin
  524. case pc^ of
  525. #1..#32 :
  526. begin
  527. if quote<>' ' then
  528. inc(arglen)
  529. else
  530. break;
  531. end;
  532. '"' :
  533. begin
  534. if quote<>'''' then
  535. begin
  536. if pchar(pc+1)^<>'"' then
  537. begin
  538. if quote='"' then
  539. quote:=' '
  540. else
  541. quote:='"';
  542. end
  543. else
  544. inc(pc);
  545. end
  546. else
  547. inc(arglen);
  548. end;
  549. '''' :
  550. begin
  551. if quote<>'"' then
  552. begin
  553. if pchar(pc+1)^<>'''' then
  554. begin
  555. if quote='''' then
  556. quote:=' '
  557. else
  558. quote:='''';
  559. end
  560. else
  561. inc(pc);
  562. end
  563. else
  564. inc(arglen);
  565. end;
  566. else
  567. inc(arglen);
  568. end;
  569. inc(pc);
  570. end;
  571. { copy argument }
  572. { Don't copy the first one, it is already there.}
  573. If Count<>0 then
  574. begin
  575. allocarg(count,arglen);
  576. quote:=' ';
  577. pc:=argstart;
  578. arg:=Fargv[count];
  579. while (pc^<>#0) do
  580. begin
  581. case pc^ of
  582. #1..#32 :
  583. begin
  584. if quote<>' ' then
  585. begin
  586. arg^:=pc^;
  587. inc(arg);
  588. end
  589. else
  590. break;
  591. end;
  592. '"' :
  593. begin
  594. if quote<>'''' then
  595. begin
  596. if pchar(pc+1)^<>'"' then
  597. begin
  598. if quote='"' then
  599. quote:=' '
  600. else
  601. quote:='"';
  602. end
  603. else
  604. inc(pc);
  605. end
  606. else
  607. begin
  608. arg^:=pc^;
  609. inc(arg);
  610. end;
  611. end;
  612. '''' :
  613. begin
  614. if quote<>'"' then
  615. begin
  616. if pchar(pc+1)^<>'''' then
  617. begin
  618. if quote='''' then
  619. quote:=' '
  620. else
  621. quote:='''';
  622. end
  623. else
  624. inc(pc);
  625. end
  626. else
  627. begin
  628. arg^:=pc^;
  629. inc(arg);
  630. end;
  631. end;
  632. else
  633. begin
  634. arg^:=pc^;
  635. inc(arg);
  636. end;
  637. end;
  638. inc(pc);
  639. end;
  640. arg^:=#0;
  641. end;
  642. {$IfDef SYSTEM_DEBUG_STARTUP}
  643. Writeln(stderr,'dos arg ',count,' #',arglen,'#',Fargv[count],'#');
  644. {$EndIf SYSTEM_DEBUG_STARTUP}
  645. inc(count);
  646. end;
  647. { get argc and create an nil entry }
  648. Fargc:=count;
  649. allocarg(argc,0);
  650. { free unused memory }
  651. sysreallocmem(Fargv,(argc+1)*sizeof(pointer));
  652. end;
  653. function CmdLine: PChar;
  654. begin
  655. setup_arguments;
  656. Result:=FCmdLine;
  657. end;
  658. function argc: longint;
  659. begin
  660. setup_arguments;
  661. Result:=Fargc;
  662. end;
  663. function argv: ppchar;
  664. begin
  665. setup_arguments;
  666. Result:=Fargv;
  667. end;
  668. function paramcount : longint;
  669. begin
  670. paramcount := argc - 1;
  671. end;
  672. function paramstr(l : longint) : string;
  673. begin
  674. setup_arguments;
  675. if (l>=0) and (l<Fargc) then
  676. paramstr:=strpas(Fargv[l])
  677. else
  678. paramstr:='';
  679. end;
  680. procedure randomize;
  681. begin
  682. randseed:=GetTickCount;
  683. end;
  684. {*****************************************************************************
  685. System Dependent Exit code
  686. *****************************************************************************}
  687. procedure PascalMain;external name 'PASCALMAIN';
  688. procedure ExitThread(Exitcode : longint); cdecl; external 'coredll';
  689. Procedure system_exit;
  690. begin
  691. if IsLibrary then
  692. exit;
  693. if not IsConsole then
  694. begin
  695. Close(stderr);
  696. Close(stdout);
  697. Close(erroutput);
  698. Close(Input);
  699. Close(Output);
  700. end;
  701. ExitThread(exitcode);
  702. end;
  703. {$ifdef cpu386}
  704. var
  705. { value of the stack segment
  706. to check if the call stack can be written on exceptions }
  707. _SS : Cardinal;
  708. {$endif cpu386}
  709. Const
  710. { DllEntryPoint }
  711. DLL_PROCESS_ATTACH = 1;
  712. DLL_THREAD_ATTACH = 2;
  713. DLL_PROCESS_DETACH = 0;
  714. DLL_THREAD_DETACH = 3;
  715. function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
  716. var
  717. res : longbool;
  718. begin
  719. IsLibrary:=true;
  720. Dll_entry:=false;
  721. case DLLreason of
  722. DLL_PROCESS_ATTACH :
  723. begin
  724. if assigned(Dll_Process_Attach_Hook) then
  725. begin
  726. res:=Dll_Process_Attach_Hook(DllParam);
  727. if not res then
  728. exit(false);
  729. end;
  730. PASCALMAIN;
  731. Dll_entry:=true;
  732. end;
  733. DLL_THREAD_ATTACH :
  734. begin
  735. inclocked(Thread_count);
  736. {$warning Allocate Threadvars !}
  737. if assigned(Dll_Thread_Attach_Hook) then
  738. Dll_Thread_Attach_Hook(DllParam);
  739. end;
  740. DLL_THREAD_DETACH :
  741. begin
  742. declocked(Thread_count);
  743. if assigned(Dll_Thread_Detach_Hook) then
  744. Dll_Thread_Detach_Hook(DllParam);
  745. {$warning Release Threadvars !}
  746. end;
  747. DLL_PROCESS_DETACH :
  748. begin
  749. Lib_Exit;
  750. if assigned(Dll_Process_Detach_Hook) then
  751. Dll_Process_Detach_Hook(DllParam);
  752. end;
  753. end;
  754. end;
  755. {$ifdef WINCE_EXCEPTION_HANDLING}
  756. //
  757. // Hardware exception handling
  758. //
  759. {
  760. Error code definitions for the WinCE API functions
  761. Values are 32 bit values layed out as follows:
  762. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  763. 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
  764. +---+-+-+-----------------------+-------------------------------+
  765. |Sev|C|R| Facility | Code |
  766. +---+-+-+-----------------------+-------------------------------+
  767. where
  768. Sev - is the severity code
  769. 00 - Success
  770. 01 - Informational
  771. 10 - Warning
  772. 11 - Error
  773. C - is the Customer code flag
  774. R - is a reserved bit
  775. Facility - is the facility code
  776. Code - is the facility's status code
  777. }
  778. const
  779. SEVERITY_SUCCESS = $00000000;
  780. SEVERITY_INFORMATIONAL = $40000000;
  781. SEVERITY_WARNING = $80000000;
  782. SEVERITY_ERROR = $C0000000;
  783. const
  784. STATUS_SEGMENT_NOTIFICATION = $40000005;
  785. DBG_TERMINATE_THREAD = $40010003;
  786. DBG_TERMINATE_PROCESS = $40010004;
  787. DBG_CONTROL_C = $40010005;
  788. DBG_CONTROL_BREAK = $40010008;
  789. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  790. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  791. STATUS_BREAKPOINT = $80000003;
  792. STATUS_SINGLE_STEP = $80000004;
  793. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  794. STATUS_ACCESS_VIOLATION = $C0000005;
  795. STATUS_IN_PAGE_ERROR = $C0000006;
  796. STATUS_INVALID_HANDLE = $C0000008;
  797. STATUS_NO_MEMORY = $C0000017;
  798. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  799. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  800. STATUS_INVALID_DISPOSITION = $C0000026;
  801. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  802. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  803. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  804. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  805. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  806. STATUS_FLOAT_OVERFLOW = $C0000091;
  807. STATUS_FLOAT_STACK_CHECK = $C0000092;
  808. STATUS_FLOAT_UNDERFLOW = $C0000093;
  809. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  810. STATUS_INTEGER_OVERFLOW = $C0000095;
  811. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  812. STATUS_STACK_OVERFLOW = $C00000FD;
  813. STATUS_CONTROL_C_EXIT = $C000013A;
  814. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  815. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  816. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  817. const
  818. ExceptionContinueExecution = 0;
  819. ExceptionContinueSearch = 1;
  820. ExceptionNestedException = 2;
  821. ExceptionCollidedUnwind = 3;
  822. ExceptionExecuteHandler = 4;
  823. MaxExceptionLevel = 16;
  824. exceptLevel : Byte = 0;
  825. {$ifdef CPUARM}
  826. const
  827. CONTEXT_ARM = $0000040;
  828. CONTEXT_CONTROL = CONTEXT_ARM or $00000001;
  829. CONTEXT_INTEGER = CONTEXT_ARM or $00000002;
  830. CONTEXT_SEGMENTS = CONTEXT_ARM or $00000004;
  831. CONTEXT_FLOATING_POINT = CONTEXT_ARM or $00000008;
  832. CONTEXT_DEBUG_REGISTERS = CONTEXT_ARM or $00000010;
  833. CONTEXT_EXTENDED_REGISTERS = CONTEXT_ARM or $00000020;
  834. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  835. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  836. NUM_VFP_REGS = 32;
  837. NUM_EXTRA_CONTROL_REGS = 8;
  838. type
  839. PContext = ^TContext;
  840. TContext = record
  841. ContextFlags : LongWord;
  842. // This section is specified/returned if the ContextFlags word contains
  843. // the flag CONTEXT_INTEGER.
  844. R0 : LongWord;
  845. R1 : LongWord;
  846. R2 : LongWord;
  847. R3 : LongWord;
  848. R4 : LongWord;
  849. R5 : LongWord;
  850. R6 : LongWord;
  851. R7 : LongWord;
  852. R8 : LongWord;
  853. R9 : LongWord;
  854. R10 : LongWord;
  855. R11 : LongWord;
  856. R12 : LongWord;
  857. // This section is specified/returned if the ContextFlags word contains
  858. // the flag CONTEXT_CONTROL.
  859. Sp : LongWord;
  860. Lr : LongWord;
  861. Pc : LongWord;
  862. Psr : LongWord;
  863. Fpscr : LongWord;
  864. FpExc : LongWord;
  865. // Floating point registers
  866. S : array[0..(NUM_VFP_REGS + 1)-1] of LongWord;
  867. FpExtra : array[0..(NUM_EXTRA_CONTROL_REGS)-1] of LongWord;
  868. end;
  869. {$endif CPUARM}
  870. {$ifdef CPUI386}
  871. const
  872. CONTEXT_X86 = $00010000;
  873. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  874. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  875. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  876. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  877. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  878. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  879. MAXIMUM_SUPPORTED_EXTENSION = 512;
  880. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  881. type
  882. PFloatingSaveArea = ^TFloatingSaveArea;
  883. TFloatingSaveArea = packed record
  884. ControlWord : Cardinal;
  885. StatusWord : Cardinal;
  886. TagWord : Cardinal;
  887. ErrorOffset : Cardinal;
  888. ErrorSelector : Cardinal;
  889. DataOffset : Cardinal;
  890. DataSelector : Cardinal;
  891. RegisterArea : array[0..79] of Byte;
  892. Cr0NpxState : Cardinal;
  893. end;
  894. PContext = ^TContext;
  895. TContext = packed record
  896. //
  897. // The flags values within this flag control the contents of
  898. // a CONTEXT record.
  899. //
  900. ContextFlags : Cardinal;
  901. //
  902. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  903. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  904. // included in CONTEXT_FULL.
  905. //
  906. Dr0, Dr1, Dr2,
  907. Dr3, Dr6, Dr7 : Cardinal;
  908. //
  909. // This section is specified/returned if the
  910. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  911. //
  912. FloatSave : TFloatingSaveArea;
  913. //
  914. // This section is specified/returned if the
  915. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  916. //
  917. SegGs, SegFs,
  918. SegEs, SegDs : Cardinal;
  919. //
  920. // This section is specified/returned if the
  921. // ContextFlags word contains the flag CONTEXT_INTEGER.
  922. //
  923. Edi, Esi, Ebx,
  924. Edx, Ecx, Eax : Cardinal;
  925. //
  926. // This section is specified/returned if the
  927. // ContextFlags word contains the flag CONTEXT_CONTROL.
  928. //
  929. Ebp : Cardinal;
  930. Eip : Cardinal;
  931. SegCs : Cardinal;
  932. EFlags, Esp, SegSs : Cardinal;
  933. //
  934. // This section is specified/returned if the ContextFlags word
  935. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  936. // The format and contexts are processor specific
  937. //
  938. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  939. end;
  940. {$endif CPUI386}
  941. type
  942. PExceptionRecord = ^TExceptionRecord;
  943. TExceptionRecord = packed record
  944. ExceptionCode : Longint;
  945. ExceptionFlags : Longint;
  946. ExceptionRecord : PExceptionRecord;
  947. ExceptionAddress : Pointer;
  948. NumberParameters : Longint;
  949. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  950. end;
  951. PExceptionPointers = ^TExceptionPointers;
  952. TExceptionPointers = packed record
  953. ExceptionRecord : PExceptionRecord;
  954. ContextRecord : PContext;
  955. end;
  956. {$ifdef CPUI386}
  957. {**************************** i386 Exception handling *****************************************}
  958. function GetCurrentProcess:DWORD;
  959. begin
  960. GetCurrentProcess := SH_CURPROC+SYS_HANDLE_BASE;
  961. end;
  962. function ReadProcessMemory(process : dword;address : pointer;dest : pointer;size : dword;bytesread : pdword) : longbool;
  963. cdecl; external 'coredll' name 'ReadProcessMemory';
  964. function is_prefetch(p : pointer) : boolean;
  965. var
  966. a : array[0..15] of byte;
  967. doagain : boolean;
  968. instrlo,instrhi,opcode : byte;
  969. i : longint;
  970. begin
  971. result:=false;
  972. { read memory savely without causing another exeception }
  973. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  974. exit;
  975. i:=0;
  976. doagain:=true;
  977. while doagain and (i<15) do
  978. begin
  979. opcode:=a[i];
  980. instrlo:=opcode and $f;
  981. instrhi:=opcode and $f0;
  982. case instrhi of
  983. { prefix? }
  984. $20,$30:
  985. doagain:=(instrlo and 7)=6;
  986. $60:
  987. doagain:=(instrlo and $c)=4;
  988. $f0:
  989. doagain:=instrlo in [0,2,3];
  990. $0:
  991. begin
  992. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  993. exit;
  994. end;
  995. else
  996. doagain:=false;
  997. end;
  998. inc(i);
  999. end;
  1000. end;
  1001. var
  1002. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  1003. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1004. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  1005. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1006. procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
  1007. begin
  1008. if IsConsole then
  1009. begin
  1010. write(stderr,'HandleErrorAddrFrame(error=',error);
  1011. write(stderr,',addr=',hexstr(addr,8));
  1012. writeln(stderr,',frame=',hexstr(frame,8),')');
  1013. end;
  1014. HandleErrorAddrFrame(error,addr,frame);
  1015. end;
  1016. {$endif SYSTEMEXCEPTIONDEBUG}
  1017. procedure JumpToHandleErrorFrame;
  1018. var
  1019. eip, ebp, error : Longint;
  1020. begin
  1021. // save ebp
  1022. asm
  1023. movl (%ebp),%eax
  1024. movl %eax,ebp
  1025. end;
  1026. if (exceptLevel > 0) then
  1027. dec(exceptLevel);
  1028. eip:=exceptEip[exceptLevel];
  1029. error:=exceptError[exceptLevel];
  1030. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1031. if IsConsole then
  1032. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  1033. {$endif SYSTEMEXCEPTIONDEBUG}
  1034. if resetFPU[exceptLevel] then
  1035. SysResetFPU;
  1036. { build a fake stack }
  1037. asm
  1038. {$ifdef REGCALL}
  1039. movl ebp,%ecx
  1040. movl eip,%edx
  1041. movl error,%eax
  1042. pushl eip
  1043. movl ebp,%ebp // Change frame pointer
  1044. {$else}
  1045. movl ebp,%eax
  1046. pushl %eax
  1047. movl eip,%eax
  1048. pushl %eax
  1049. movl error,%eax
  1050. pushl %eax
  1051. movl eip,%eax
  1052. pushl %eax
  1053. movl ebp,%ebp // Change frame pointer
  1054. {$endif}
  1055. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1056. jmpl DebugHandleErrorAddrFrame
  1057. {$else not SYSTEMEXCEPTIONDEBUG}
  1058. jmpl HandleErrorAddrFrame
  1059. {$endif SYSTEMEXCEPTIONDEBUG}
  1060. end;
  1061. end;
  1062. function i386_exception_handler(ExceptionRecord: PExceptionRecord;
  1063. EstablisherFrame: pointer; ContextRecord: PContext;
  1064. DispatcherContext: pointer): longint; cdecl;
  1065. var
  1066. res: longint;
  1067. must_reset_fpu: boolean;
  1068. begin
  1069. res := ExceptionContinueSearch;
  1070. if ContextRecord^.SegSs=_SS then begin
  1071. must_reset_fpu := true;
  1072. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1073. if IsConsole then Writeln(stderr,'Exception ',
  1074. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  1075. {$endif SYSTEMEXCEPTIONDEBUG}
  1076. case cardinal(ExceptionRecord^.ExceptionCode) of
  1077. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1078. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1079. res := 200;
  1080. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1081. begin
  1082. res := 201;
  1083. must_reset_fpu := false;
  1084. end;
  1085. STATUS_STACK_OVERFLOW :
  1086. begin
  1087. res := 202;
  1088. must_reset_fpu := false;
  1089. end;
  1090. STATUS_FLOAT_OVERFLOW :
  1091. res := 205;
  1092. STATUS_FLOAT_DENORMAL_OPERAND,
  1093. STATUS_FLOAT_UNDERFLOW :
  1094. res := 206;
  1095. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  1096. STATUS_FLOAT_INEXACT_RESULT,
  1097. STATUS_FLOAT_INVALID_OPERATION,
  1098. STATUS_FLOAT_STACK_CHECK :
  1099. res := 207;
  1100. STATUS_INTEGER_OVERFLOW :
  1101. begin
  1102. res := 215;
  1103. must_reset_fpu := false;
  1104. end;
  1105. STATUS_ILLEGAL_INSTRUCTION:
  1106. res := 216;
  1107. STATUS_ACCESS_VIOLATION:
  1108. { Athlon prefetch bug? }
  1109. if is_prefetch(pointer(ContextRecord^.Eip)) then
  1110. begin
  1111. { if yes, then retry }
  1112. ExceptionRecord^.ExceptionCode := 0;
  1113. res:=ExceptionContinueExecution;
  1114. end
  1115. else
  1116. res := 216;
  1117. STATUS_CONTROL_C_EXIT:
  1118. res := 217;
  1119. STATUS_PRIVILEGED_INSTRUCTION:
  1120. begin
  1121. res := 218;
  1122. must_reset_fpu := false;
  1123. end;
  1124. else
  1125. begin
  1126. if ((ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1127. res := 217
  1128. else
  1129. res := 255;
  1130. end;
  1131. end;
  1132. if (res >= 200) and (exceptLevel < MaxExceptionLevel) then begin
  1133. exceptEip[exceptLevel] := ContextRecord^.Eip;
  1134. exceptError[exceptLevel] := res;
  1135. resetFPU[exceptLevel] := must_reset_fpu;
  1136. inc(exceptLevel);
  1137. ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  1138. ExceptionRecord^.ExceptionCode := 0;
  1139. res := ExceptionContinueExecution;
  1140. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1141. if IsConsole then begin
  1142. writeln(stderr,'Exception Continue Exception set at ',
  1143. hexstr(exceptEip[exceptLevel],8));
  1144. writeln(stderr,'Eip changed to ',
  1145. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1146. end;
  1147. {$endif SYSTEMEXCEPTIONDEBUG}
  1148. end;
  1149. end;
  1150. i386_exception_handler := res;
  1151. end;
  1152. {$endif CPUI386}
  1153. {$ifdef CPUARM}
  1154. {**************************** ARM Exception handling *****************************************}
  1155. var
  1156. exceptPC : array[0..MaxExceptionLevel-1] of Longint;
  1157. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1158. procedure JumpToHandleErrorFrame;
  1159. var
  1160. _pc, _fp, _error : Longint;
  1161. begin
  1162. // get original fp
  1163. asm
  1164. ldr r0,[r11,#-12]
  1165. str r0,_fp
  1166. end;
  1167. if (exceptLevel > 0) then
  1168. dec(exceptLevel);
  1169. _pc:=exceptPC[exceptLevel];
  1170. _error:=exceptError[exceptLevel];
  1171. asm
  1172. ldr r0,_error
  1173. ldr r1,_pc
  1174. ldr r2,_fp
  1175. mov r11,r2 // Change frame pointer
  1176. b HandleErrorAddrFrame
  1177. end;
  1178. end;
  1179. function ARM_ExceptionHandler(ExceptionRecord: PExceptionRecord;
  1180. EstablisherFrame: pointer; ContextRecord: PContext;
  1181. DispatcherContext: pointer): longint; [public, alias : '_ARM_ExceptionHandler'];
  1182. var
  1183. res: longint;
  1184. begin
  1185. res := ExceptionContinueSearch;
  1186. case cardinal(ExceptionRecord^.ExceptionCode) of
  1187. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1188. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1189. res := 200;
  1190. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1191. res := 201;
  1192. STATUS_STACK_OVERFLOW :
  1193. res := 202;
  1194. STATUS_FLOAT_OVERFLOW :
  1195. res := 205;
  1196. STATUS_FLOAT_DENORMAL_OPERAND,
  1197. STATUS_FLOAT_UNDERFLOW :
  1198. res := 206;
  1199. STATUS_FLOAT_INEXACT_RESULT,
  1200. STATUS_FLOAT_INVALID_OPERATION,
  1201. STATUS_FLOAT_STACK_CHECK :
  1202. res := 207;
  1203. STATUS_INTEGER_OVERFLOW :
  1204. res := 215;
  1205. STATUS_ILLEGAL_INSTRUCTION:
  1206. res := 216;
  1207. STATUS_ACCESS_VIOLATION:
  1208. res := 216;
  1209. STATUS_DATATYPE_MISALIGNMENT:
  1210. res := 214;
  1211. STATUS_CONTROL_C_EXIT:
  1212. res := 217;
  1213. STATUS_PRIVILEGED_INSTRUCTION:
  1214. res := 218;
  1215. else
  1216. begin
  1217. if ((cardinal(ExceptionRecord^.ExceptionCode) and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1218. res := 217
  1219. else
  1220. res := 255;
  1221. end;
  1222. end;
  1223. if (res <> ExceptionContinueSearch) and (exceptLevel < MaxExceptionLevel) then begin
  1224. exceptPC[exceptLevel] := ContextRecord^.PC;
  1225. exceptError[exceptLevel] := res;
  1226. inc(exceptLevel);
  1227. ContextRecord^.PC := Longint(@JumpToHandleErrorFrame);
  1228. ExceptionRecord^.ExceptionCode := 0;
  1229. res := ExceptionContinueExecution;
  1230. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1231. if IsConsole then begin
  1232. writeln(stderr,'Exception Continue Exception set at ',
  1233. hexstr(exceptEip[exceptLevel],8));
  1234. writeln(stderr,'Eip changed to ',
  1235. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1236. end;
  1237. {$endif SYSTEMEXCEPTIONDEBUG}
  1238. end;
  1239. ARM_ExceptionHandler := res;
  1240. end;
  1241. {$endif CPUARM}
  1242. {$endif WINCE_EXCEPTION_HANDLING}
  1243. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  1244. var
  1245. st: pointer;
  1246. begin
  1247. IsLibrary:=false;
  1248. {$ifdef CPUARM}
  1249. asm
  1250. str sp,st
  1251. end;
  1252. StackTop:=st;
  1253. asm
  1254. mov fp,#0
  1255. bl PASCALMAIN;
  1256. end;
  1257. {$endif CPUARM}
  1258. {$ifdef CPUI386}
  1259. asm
  1260. {$ifdef WINCE_EXCEPTION_HANDLING}
  1261. pushl i386_exception_handler
  1262. pushl %fs:(0)
  1263. mov %esp,%fs:(0)
  1264. {$endif WINCE_EXCEPTION_HANDLING}
  1265. pushl %ebp
  1266. movl %esp,%eax
  1267. movl %eax,st
  1268. end;
  1269. StackTop:=st;
  1270. asm
  1271. xorl %eax,%eax
  1272. movw %ss,%ax
  1273. movl %eax,_SS
  1274. call SysResetFPU
  1275. xorl %ebp,%ebp
  1276. call PASCALMAIN
  1277. popl %ebp
  1278. {$ifdef WINCE_EXCEPTION_HANDLING}
  1279. popl %fs:(0)
  1280. addl $4, %esp
  1281. {$endif WINCE_EXCEPTION_HANDLING}
  1282. end;
  1283. {$endif CPUI386}
  1284. end;
  1285. procedure _FPC_mainCRTStartup;public name '_mainCRTStartup';
  1286. begin
  1287. IsConsole:=True;
  1288. Exe_entry;
  1289. end;
  1290. procedure _FPC_WinMainCRTStartup;public name '_WinMainCRTStartup';
  1291. begin
  1292. IsConsole:=False;
  1293. Exe_entry;
  1294. end;
  1295. procedure _FPC_DLLMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);public name '_DLLMainCRTStartup';
  1296. begin
  1297. IsConsole:=true;
  1298. sysinstance:=_hinstance;
  1299. dllreason:=_dllreason;
  1300. dllparam:=_dllparam;
  1301. DLL_Entry;
  1302. end;
  1303. procedure _FPC_DLLWinMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);public name '_DLLWinMainCRTStartup';
  1304. begin
  1305. IsConsole:=false;
  1306. sysinstance:=_hinstance;
  1307. dllreason:=_dllreason;
  1308. dllparam:=_dllparam;
  1309. DLL_Entry;
  1310. end;
  1311. {****************************************************************************
  1312. OS dependend widestrings
  1313. ****************************************************************************}
  1314. function CharUpperBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; cdecl; external KernelDLL name 'CharUpperBuffW';
  1315. function CharLowerBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; cdecl; external KernelDLL name 'CharLowerBuffW';
  1316. procedure WinCEWide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
  1317. var
  1318. i: integer;
  1319. begin
  1320. if len = 0 then
  1321. dest:=''
  1322. else
  1323. begin
  1324. for i:=1 to 2 do begin
  1325. setlength(dest, len);
  1326. len:=WideCharToMultiByte(CP_ACP, 0, source, len, @dest[1], len, nil, nil);
  1327. if len > 0 then
  1328. break;
  1329. len:=WideCharToMultiByte(CP_ACP, 0, source, len, nil, 0, nil, nil);
  1330. end;
  1331. setlength(dest, len);
  1332. end;
  1333. end;
  1334. procedure WinCEAnsi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
  1335. var
  1336. i: integer;
  1337. begin
  1338. if len = 0 then
  1339. dest:=''
  1340. else
  1341. begin
  1342. for i:=1 to 2 do begin
  1343. setlength(dest, len);
  1344. len:=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, source, len, @dest[1], len);
  1345. if len > 0 then
  1346. break;
  1347. len:=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, source, len, nil, 0);
  1348. end;
  1349. setlength(dest, len);
  1350. end;
  1351. end;
  1352. function WinCEWideUpper(const s : WideString) : WideString;
  1353. begin
  1354. result:=s;
  1355. UniqueString(result);
  1356. if length(result)>0 then
  1357. CharUpperBuff(LPWSTR(result),length(result));
  1358. end;
  1359. function WinCEWideLower(const s : WideString) : WideString;
  1360. begin
  1361. result:=s;
  1362. UniqueString(result);
  1363. if length(result)>0 then
  1364. CharLowerBuff(LPWSTR(result),length(result));
  1365. end;
  1366. { there is a similiar procedure in sysutils which inits the fields which
  1367. are only relevant for the sysutils units }
  1368. procedure InitWinCEWidestrings;
  1369. begin
  1370. widestringmanager.Wide2AnsiMoveProc:=@WinCEWide2AnsiMove;
  1371. widestringmanager.Ansi2WideMoveProc:=@WinCEAnsi2WideMove;
  1372. widestringmanager.UpperWideStringProc:=@WinCEWideUpper;
  1373. widestringmanager.LowerWideStringProc:=@WinCEWideLower;
  1374. end;
  1375. {$IFDEF HAS_MT_MEMORYMANAGER}
  1376. {****************************************************************************
  1377. Memory manager
  1378. ****************************************************************************}
  1379. function malloc(Size : ptrint) : Pointer; cdecl; external 'coredll';
  1380. procedure free(P : pointer); cdecl; external 'coredll';
  1381. function realloc(P : Pointer; Size : ptrint) : pointer; cdecl; external 'coredll';
  1382. function _msize(P : pointer): ptrint; cdecl; external 'coredll';
  1383. function SysGetMem (Size : ptrint) : Pointer;
  1384. begin
  1385. Result:=malloc(Size);
  1386. end;
  1387. Function SysFreeMem (P : pointer) : ptrint;
  1388. begin
  1389. free(P);
  1390. Result:=0;
  1391. end;
  1392. Function SysFreeMemSize(p:pointer;Size:ptrint):ptrint;
  1393. begin
  1394. Result:=0;
  1395. if size < 0 then
  1396. runerror(204)
  1397. else
  1398. if (size > 0) and (p <> nil) then
  1399. Result:=SysFreeMem(P);
  1400. end;
  1401. Function SysAllocMem(Size : ptrint) : Pointer;
  1402. begin
  1403. Result:=SysGetMem(Size);
  1404. if Result <> nil then
  1405. FillChar(Result^, Size, 0);
  1406. end;
  1407. Function SysReAllocMem (var p:pointer;Size:ptrint):Pointer;
  1408. begin
  1409. Result:=realloc(p, Size);
  1410. p:=Result;
  1411. end;
  1412. function SysTryResizeMem(var p:pointer;size : ptrint):boolean;
  1413. var
  1414. res: pointer;
  1415. begin
  1416. res:=realloc(p, Size);
  1417. Result:=(res <> nil) or (Size = 0);
  1418. if Result then
  1419. p:=res;
  1420. end;
  1421. function SysMemSize(P : pointer): ptrint;
  1422. begin
  1423. Result:=_msize(P);
  1424. end;
  1425. function SysGetHeapStatus:THeapStatus;
  1426. begin
  1427. fillchar(Result,sizeof(Result),0);
  1428. end;
  1429. function SysGetFPCHeapStatus:TFPCHeapStatus;
  1430. begin
  1431. fillchar(Result,sizeof(Result),0);
  1432. end;
  1433. {$ENDIF HAS_MT_MEMORYMANAGER}
  1434. {****************************************************************************
  1435. Error Message writing using messageboxes
  1436. ****************************************************************************}
  1437. const
  1438. ErrorBufferLength = 1024;
  1439. var
  1440. ErrorBuf : array[0..ErrorBufferLength] of char;
  1441. ErrorBufW : array[0..ErrorBufferLength] of widechar;
  1442. ErrorLen : longint;
  1443. Function ErrorWrite(Var F: TextRec): Integer;
  1444. {
  1445. An error message should always end with #13#10#13#10
  1446. }
  1447. var
  1448. p : pchar;
  1449. i : longint;
  1450. Begin
  1451. if F.BufPos>0 then
  1452. begin
  1453. if F.BufPos+ErrorLen>ErrorBufferLength then
  1454. i:=ErrorBufferLength-ErrorLen
  1455. else
  1456. i:=F.BufPos;
  1457. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  1458. inc(ErrorLen,i);
  1459. ErrorBuf[ErrorLen]:=#0;
  1460. end;
  1461. if ErrorLen>3 then
  1462. begin
  1463. p:=@ErrorBuf[ErrorLen];
  1464. for i:=1 to 4 do
  1465. begin
  1466. dec(p);
  1467. if not(p^ in [#10,#13]) then
  1468. break;
  1469. end;
  1470. end;
  1471. if ErrorLen=ErrorBufferLength then
  1472. i:=4;
  1473. if (i=4) then
  1474. begin
  1475. AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
  1476. MessageBox(0,@ErrorBufW,'Error',0);
  1477. ErrorLen:=0;
  1478. end;
  1479. F.BufPos:=0;
  1480. ErrorWrite:=0;
  1481. End;
  1482. Function ErrorClose(Var F: TextRec): Integer;
  1483. begin
  1484. if ErrorLen>0 then
  1485. begin
  1486. AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
  1487. MessageBox(0,@ErrorBufW,'Error',0);
  1488. ErrorLen:=0;
  1489. end;
  1490. ErrorLen:=0;
  1491. ErrorClose:=0;
  1492. end;
  1493. Function ErrorOpen(Var F: TextRec): Integer;
  1494. Begin
  1495. TextRec(F).InOutFunc:=@ErrorWrite;
  1496. TextRec(F).FlushFunc:=@ErrorWrite;
  1497. TextRec(F).CloseFunc:=@ErrorClose;
  1498. ErrorOpen:=0;
  1499. End;
  1500. procedure AssignError(Var T: Text);
  1501. begin
  1502. Assign(T,'');
  1503. TextRec(T).OpenFunc:=@ErrorOpen;
  1504. Rewrite(T);
  1505. end;
  1506. function _getstdfilex(fd: integer): pointer; cdecl; external 'coredll';
  1507. function _fileno(fd: pointer): THandle; cdecl; external 'coredll';
  1508. function _controlfp(new: DWORD; mask: DWORD): DWORD; cdecl; external 'coredll';
  1509. procedure SysInitStdIO;
  1510. begin
  1511. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1512. displayed in and messagebox }
  1513. if not IsConsole then begin
  1514. AssignError(stderr);
  1515. AssignError(stdout);
  1516. Assign(Output,'');
  1517. Assign(Input,'');
  1518. Assign(ErrOutput,'');
  1519. end
  1520. else begin
  1521. StdInputHandle:=_fileno(_getstdfilex(0));
  1522. StdOutputHandle:=_fileno(_getstdfilex(1));
  1523. StdErrorHandle:=_fileno(_getstdfilex(2));
  1524. OpenStdIO(Input,fmInput,StdInputHandle);
  1525. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1526. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  1527. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1528. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1529. end;
  1530. end;
  1531. (* ProcessID cached to avoid repeated calls to GetCurrentProcess. *)
  1532. var
  1533. ProcessID: SizeUInt;
  1534. function GetProcessID: SizeUInt;
  1535. begin
  1536. GetProcessID := ProcessID;
  1537. end;
  1538. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  1539. begin
  1540. result := stklen;
  1541. end;
  1542. procedure SysCleanup;
  1543. var
  1544. i: integer;
  1545. begin
  1546. if FCmdLine = nil then
  1547. exit;
  1548. SysFreeMem(FCmdLine);
  1549. for i:=0 to Fargc do
  1550. sysfreemem(Fargv[i]);
  1551. sysfreemem(Fargv);
  1552. end;
  1553. initialization
  1554. StackLength := CheckInitialStkLen(InitialStkLen);
  1555. StackBottom := StackTop - StackLength;
  1556. { Enable FPU exceptions, but disable INEXACT, UNDERFLOW, DENORMAL }
  1557. { FPU precision 64 bit, rounding to nearest, affine infinity }
  1558. _controlfp($000C0003, $030F031F);
  1559. { some misc stuff }
  1560. hprevinst:=0;
  1561. if not IsLibrary then
  1562. SysInstance:=GetModuleHandle(nil);
  1563. MainInstance:=SysInstance;
  1564. {$IFNDEF HAS_MT_MEMORYMANAGER}
  1565. { Setup Heap }
  1566. InitHeap;
  1567. {$ENDIF HAS_MT_MEMORYMANAGER}
  1568. SysInitExceptions;
  1569. if not IsLibrary then
  1570. begin
  1571. SysInitStdIO;
  1572. end;
  1573. { Reset IO Error }
  1574. InOutRes:=0;
  1575. ProcessID := GetCurrentProcessID;
  1576. { threading }
  1577. InitSystemThreads;
  1578. { Reset internal error variable }
  1579. errno:=0;
  1580. initvariantmanager;
  1581. initwidestringmanager;
  1582. InitWinCEWidestrings;
  1583. DispCallByIDProc:=@DoDispCallByIDError;
  1584. finalization
  1585. SysCleanup;
  1586. end.