syswin.inc 9.0 KB

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