lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / sal / osl / w32 / dllentry.cxx
blobe9323248e3db5ea7b0e47e641564a547f370d090
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <systools/win32/uwinapi.h>
21 #include <tlhelp32.h>
22 #include <rpc.h>
23 #include <winsock.h>
24 #ifdef _DEBUG
25 #include <crtdbg.h>
26 #endif
27 #include <osl/diagnose.h>
28 #include <sal/types.h>
29 #include <float.h>
31 #include <osl/mutex.h>
32 #include <osl/thread.h>
34 #include "file_url.hxx"
35 #include "gmutex.hxx"
36 #include <rtllifecycle.h>
38 #include "thread.hxx"
41 This is needed because DllMain is called after static constructors. A DLL's
42 startup and shutdown sequence looks like this:
44 _pRawDllMain()
45 _CRT_INIT()
46 DllMain()
47 ....
48 DllMain()
49 _CRT_INIT()
50 _pRawDllMain()
54 extern "C" {
56 static BOOL WINAPI RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved );
57 BOOL (WINAPI *_pRawDllMain)(HINSTANCE, DWORD, LPVOID) = RawDllMain;
61 static BOOL WINAPI RawDllMain( HINSTANCE, DWORD fdwReason, LPVOID )
63 switch (fdwReason)
65 case DLL_PROCESS_ATTACH:
67 #ifdef _DEBUG
68 WCHAR buf[64];
69 DWORD const res = GetEnvironmentVariableW(L"SAL_NO_ASSERT_DIALOGS", buf, SAL_N_ELEMENTS(buf));
70 if (res && res < SAL_N_ELEMENTS(buf))
72 // disable the dialog on abort()
73 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
74 _CrtSetReportMode(_CRT_ERROR, (_CRTDBG_MODE_DEBUG|_CRTDBG_MODE_FILE));
75 // not sure which assertions this affects
76 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
77 _CrtSetReportMode(_CRT_ASSERT, (_CRTDBG_MODE_DEBUG|_CRTDBG_MODE_FILE));
78 // disable the dialog on assert(false)
79 _set_error_mode(_OUT_TO_STDERR);
81 #endif
83 #if OSL_DEBUG_LEVEL < 2
84 /* Suppress file error messages from system like "Floppy A: not inserted" */
85 SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS );
86 #endif
88 /* initialize global mutex */
89 g_Mutex = osl_createMutex();
91 /* initialize "current directory" mutex */
92 g_CurrentDirectoryMutex = osl_createMutex();
94 g_dwTLSTextEncodingIndex = TlsAlloc();
95 InitializeCriticalSection( &g_ThreadKeyListCS );
97 //We disable floating point exceptions. This is the usual state at program startup
98 //but on Windows 98 and ME this is not always the case.
99 _control87(_MCW_EM, _MCW_EM);
100 break;
103 case DLL_PROCESS_DETACH:
104 WSACleanup( );
106 TlsFree( g_dwTLSTextEncodingIndex );
107 DeleteCriticalSection( &g_ThreadKeyListCS );
109 osl_destroyMutex( g_Mutex );
111 osl_destroyMutex( g_CurrentDirectoryMutex );
115 On a product build memory management finalization might
116 cause a crash without assertion (assertions off) if heap is
117 corrupted. But a crash report won't help here because at
118 this point all other threads have been terminated and only
119 ntdll is on the stack. No chance to find the reason for the
120 corrupted heap if so.
122 So annoying the user with a crash report is completely useless.
126 #ifndef DBG_UTIL
127 __try
128 #endif
130 /* cleanup locale hashtable */
131 rtl_locale_fini();
133 /* finalize memory management */
134 rtl_cache_fini();
135 rtl_arena_fini();
137 #ifndef DBG_UTIL
138 __except( EXCEPTION_EXECUTE_HANDLER )
141 #endif
142 break;
145 return TRUE;
148 static DWORD GetParentProcessId()
150 DWORD dwParentProcessId = 0;
151 HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
153 if ( IsValidHandle( hSnapshot ) )
155 PROCESSENTRY32 pe;
156 BOOL fSuccess;
158 ZeroMemory( &pe, sizeof(pe) );
159 pe.dwSize = sizeof(pe);
160 fSuccess = Process32First( hSnapshot, &pe );
162 while( fSuccess )
164 if ( GetCurrentProcessId() == pe.th32ProcessID )
166 dwParentProcessId = pe.th32ParentProcessID;
167 break;
170 fSuccess = Process32Next( hSnapshot, &pe );
173 CloseHandle( hSnapshot );
176 return dwParentProcessId;
179 static DWORD WINAPI ParentMonitorThreadProc( LPVOID lpParam )
181 DWORD_PTR dwParentProcessId = reinterpret_cast<DWORD_PTR>(lpParam);
183 HANDLE hParentProcess = OpenProcess( SYNCHRONIZE, FALSE, dwParentProcessId );
185 osl_setThreadName("headless ParentMonitorThread");
187 if ( IsValidHandle( hParentProcess ) )
189 if ( WAIT_OBJECT_0 == WaitForSingleObject( hParentProcess, INFINITE ) )
191 TerminateProcess( GetCurrentProcess(), 0 );
193 CloseHandle( hParentProcess );
195 return 0;
198 extern "C"
199 BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID )
201 switch (fdwReason)
203 case DLL_PROCESS_ATTACH:
205 WCHAR szBuffer[64];
207 // This code will attach the process to its parent process
208 // if the parent process had set the environment variable.
209 // The corresponding code (setting the environment variable)
210 // is desktop/win32/source/officeloader.cxx
212 DWORD dwResult = GetEnvironmentVariableW( L"ATTACHED_PARENT_PROCESSID", szBuffer, SAL_N_ELEMENTS(szBuffer) );
214 if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
216 DWORD dwThreadId = 0;
218 DWORD_PTR dwParentProcessId = static_cast<DWORD_PTR>(_wtol( szBuffer ));
220 if ( dwParentProcessId && GetParentProcessId() == dwParentProcessId )
222 // No error check, it works or it does not
223 // Thread should only be started for headless mode, see desktop/win32/source/officeloader.cxx
224 HANDLE hThread
225 = CreateThread(nullptr, 0, ParentMonitorThreadProc,
226 reinterpret_cast<LPVOID>(dwParentProcessId), 0, &dwThreadId);
227 // Note: calling CreateThread in DllMain is discouraged
228 // but this is only done in the headless mode and in
229 // that case no other threads should be running at startup
230 // when sal3.dll is loaded; also there is no
231 // synchronization with the spawned thread, so there
232 // does not appear to be a real risk of deadlock here
233 if (hThread)
234 CloseHandle(hThread);
238 return TRUE;
241 case DLL_THREAD_ATTACH:
242 break;
244 case DLL_THREAD_DETACH:
245 osl_callThreadKeyCallbackOnThreadDetach( );
246 break;
249 return TRUE;
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */