syswin.inc 8.5 KB

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