syswin.inc 9.1 KB

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