2
0

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