syswin.inc 9.1 KB

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