syswin.inc 8.3 KB

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