syswin.inc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2008 by Florian Klaempfl and Pavel Ozerski
  4. member of the Free Pascal development team.
  5. FPC Pascal system unit part shared by win32/win64.
  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. Const
  13. DLL_PROCESS_ATTACH = 1;
  14. DLL_THREAD_ATTACH = 2;
  15. DLL_PROCESS_DETACH = 0;
  16. DLL_THREAD_DETACH = 3;
  17. DLLExitOK : boolean = true;
  18. Var
  19. DLLBuf : Jmp_buf;
  20. function Dll_entry{$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}(const info : TEntryInformation){$endif FPC_HAS_INDIRECT_MAIN_INFORMATION} : longbool; [public,alias:'_FPC_DLL_Entry'];
  21. begin
  22. {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
  23. EntryInformation:=info;
  24. {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
  25. IsLibrary:=true;
  26. Dll_entry:=false;
  27. case DLLreason of
  28. DLL_PROCESS_ATTACH :
  29. begin
  30. MainThreadIdWin32 := Win32GetCurrentThreadId;
  31. If SetJmp(DLLBuf) = 0 then
  32. begin
  33. {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
  34. EntryInformation.PascalMain();
  35. {$else FPC_HAS_INDIRECT_MAIN_INFORMATION}
  36. PascalMain;
  37. {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
  38. Dll_entry:=true;
  39. end
  40. else
  41. Dll_entry:=DLLExitOK;
  42. end;
  43. DLL_THREAD_ATTACH :
  44. begin
  45. inclocked(Thread_count);
  46. if Win32GetCurrentThreadId <> MainThreadIdWin32 then
  47. begin
  48. { Allocate Threadvars }
  49. SysAllocateThreadVars;
  50. { NS : no idea what is correct to pass here - pass dummy value for now }
  51. { passing a dummy is ok, the correct value is read from the coff header of SysInstance (FK) }
  52. InitThread($1000000); { Assume everything is idempotent there, as the thread could have been created with BeginThread... }
  53. end;
  54. if assigned(Dll_Thread_Attach_Hook) then
  55. Dll_Thread_Attach_Hook(DllParam);
  56. Dll_entry:=true; { return value is ignored }
  57. end;
  58. DLL_THREAD_DETACH :
  59. begin
  60. declocked(Thread_count);
  61. if assigned(Dll_Thread_Detach_Hook) then
  62. Dll_Thread_Detach_Hook(DllParam);
  63. { Release Threadvars }
  64. if Win32GetCurrentThreadId<>MainThreadIdWin32 then
  65. DoneThread; { Assume everything is idempotent there }
  66. Dll_entry:=true; { return value is ignored }
  67. end;
  68. DLL_PROCESS_DETACH :
  69. begin
  70. Dll_entry:=true; { return value is ignored }
  71. if MainThreadIDWin32=0 then // already been here.
  72. exit;
  73. If SetJmp(DLLBuf) = 0 then
  74. FPC_Do_Exit;
  75. if assigned(Dll_Process_Detach_Hook) then
  76. Dll_Process_Detach_Hook(DllParam);
  77. DoneThread;
  78. { Free TLS resources used by ThreadVars }
  79. SysFiniMultiThreading;
  80. MainThreadIDWin32:=0;
  81. end;
  82. end;
  83. end;
  84. Procedure ExitDLL(Exitcode : longint);
  85. begin
  86. DLLExitOK:=ExitCode=0;
  87. LongJmp(DLLBuf,1);
  88. end;
  89. {****************************************************************************
  90. Error Message writing using messageboxes
  91. ****************************************************************************}
  92. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  93. stdcall;external 'user32' name 'MessageBoxA';
  94. const
  95. ErrorBufferLength = 1024;
  96. var
  97. ErrorBuf : array[0..ErrorBufferLength] of char;
  98. ErrorLen : SizeInt;
  99. Function ErrorWrite(Var F: TextRec): Integer;
  100. {
  101. An error message should always end with #13#10#13#10
  102. }
  103. var
  104. i : SizeInt;
  105. Begin
  106. while F.BufPos>0 do
  107. begin
  108. begin
  109. if F.BufPos+ErrorLen>ErrorBufferLength then
  110. i:=ErrorBufferLength-ErrorLen
  111. else
  112. i:=F.BufPos;
  113. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  114. inc(ErrorLen,i);
  115. ErrorBuf[ErrorLen]:=#0;
  116. end;
  117. if ErrorLen=ErrorBufferLength then
  118. begin
  119. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  120. ErrorLen:=0;
  121. end;
  122. Dec(F.BufPos,i);
  123. end;
  124. ErrorWrite:=0;
  125. End;
  126. Function ErrorClose(Var F: TextRec): Integer;
  127. begin
  128. if ErrorLen>0 then
  129. begin
  130. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  131. ErrorLen:=0;
  132. end;
  133. ErrorLen:=0;
  134. ErrorClose:=0;
  135. end;
  136. Function ErrorOpen(Var F: TextRec): Integer;
  137. Begin
  138. TextRec(F).InOutFunc:=@ErrorWrite;
  139. TextRec(F).FlushFunc:=@ErrorWrite;
  140. TextRec(F).CloseFunc:=@ErrorClose;
  141. ErrorLen:=0;
  142. ErrorOpen:=0;
  143. End;
  144. procedure AssignError(Var T: Text);
  145. begin
  146. Assign(T,'');
  147. TextRec(T).OpenFunc:=@ErrorOpen;
  148. Rewrite(T);
  149. end;
  150. procedure SysInitStdIO;
  151. begin
  152. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  153. displayed in a messagebox }
  154. StdInputHandle:=longint(GetStdHandle(cardinal(STD_INPUT_HANDLE)));
  155. StdOutputHandle:=longint(GetStdHandle(cardinal(STD_OUTPUT_HANDLE)));
  156. StdErrorHandle:=longint(GetStdHandle(cardinal(STD_ERROR_HANDLE)));
  157. if not IsConsole then
  158. begin
  159. AssignError(stderr);
  160. AssignError(StdOut);
  161. Assign(Output,'');
  162. Assign(Input,'');
  163. Assign(ErrOutput,'');
  164. end
  165. else
  166. begin
  167. OpenStdIO(Input,fmInput,StdInputHandle);
  168. OpenStdIO(Output,fmOutput,StdOutputHandle);
  169. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  170. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  171. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  172. end;
  173. end;
  174. { ProcessID cached to avoid repeated calls to GetCurrentProcess. }
  175. var
  176. ProcessID: SizeUInt;
  177. function GetProcessID: SizeUInt;
  178. begin
  179. GetProcessID := ProcessID;
  180. end;
  181. {******************************************************************************
  182. Unicode
  183. ******************************************************************************}
  184. procedure Win32Unicode2AnsiMove(source:punicodechar;var dest:ansistring;len:SizeInt);
  185. var
  186. destlen: SizeInt;
  187. begin
  188. // retrieve length including trailing #0
  189. // not anymore, because this must also be usable for single characters
  190. destlen:=WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, source, len, nil, 0, nil, nil);
  191. // this will null-terminate
  192. setlength(dest, destlen);
  193. WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, source, len, @dest[1], destlen, nil, nil);
  194. end;
  195. procedure Win32Ansi2UnicodeMove(source:pchar;var dest:UnicodeString;len:SizeInt);
  196. var
  197. destlen: SizeInt;
  198. begin
  199. // retrieve length including trailing #0
  200. // not anymore, because this must also be usable for single characters
  201. destlen:=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, source, len, nil, 0);
  202. // this will null-terminate
  203. setlength(dest, destlen);
  204. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, source, len, @dest[1], destlen);
  205. end;
  206. function Win32UnicodeUpper(const s : UnicodeString) : UnicodeString;
  207. begin
  208. result:=s;
  209. UniqueString(result);
  210. if length(result)>0 then
  211. CharUpperBuff(LPWSTR(result),length(result));
  212. end;
  213. function Win32UnicodeLower(const s : UnicodeString) : UnicodeString;
  214. begin
  215. result:=s;
  216. UniqueString(result);
  217. if length(result)>0 then
  218. CharLowerBuff(LPWSTR(result),length(result));
  219. end;
  220. type
  221. PWStrInitEntry = ^TWStrInitEntry;
  222. TWStrInitEntry = record
  223. addr: PPointer;
  224. data: Pointer;
  225. end;
  226. PWStrInitTablesTable = ^TWStrInitTablesTable;
  227. TWStrInitTablesTable = packed record
  228. count : longint;
  229. tables : packed array [1..32767] of PWStrInitEntry;
  230. end;
  231. {$if not(defined(VER2_2) or defined(VER2_4))}
  232. var
  233. WStrInitTablesTable: TWStrInitTablesTable; external name 'FPC_WIDEINITTABLES';
  234. {$endif}
  235. { there is a similiar procedure in sysutils which inits the fields which
  236. are only relevant for the sysutils units }
  237. procedure InitWin32Widestrings;
  238. var
  239. i: longint;
  240. ptable: PWStrInitEntry;
  241. begin
  242. {$if not(defined(VER2_2) or defined(VER2_4))}
  243. { assign initial values to global Widestring typed consts }
  244. for i:=1 to WStrInitTablesTable.count do
  245. begin
  246. ptable:=WStrInitTablesTable.tables[i];
  247. while Assigned(ptable^.addr) do
  248. begin
  249. fpc_widestr_assign(ptable^.addr^, ptable^.data);
  250. Inc(ptable);
  251. end;
  252. end;
  253. {$endif}
  254. { Widestring }
  255. widestringmanager.Wide2AnsiMoveProc:=@Win32Wide2AnsiMove;
  256. widestringmanager.Ansi2WideMoveProc:=@Win32Ansi2WideMove;
  257. widestringmanager.UpperWideStringProc:=@Win32WideUpper;
  258. widestringmanager.LowerWideStringProc:=@Win32WideLower;
  259. {$ifndef VER2_2}
  260. { Unicode }
  261. widestringmanager.Unicode2AnsiMoveProc:=@Win32Unicode2AnsiMove;
  262. widestringmanager.Ansi2UnicodeMoveProc:=@Win32Ansi2UnicodeMove;
  263. widestringmanager.UpperUnicodeStringProc:=@Win32UnicodeUpper;
  264. widestringmanager.LowerUnicodeStringProc:=@Win32UnicodeLower;
  265. {$endif VER2_2}
  266. end;