Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sal / osl / w32 / dllentry.cxx
blob81139a05852b96ce0f456257c7fce3ce4f39be5f
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 <rtllifecycle.h>
37 #include "thread.hxx"
40 This is needed because DllMain is called after static constructors. A DLL's
41 startup and shutdown sequence looks like this:
43 _pRawDllMain()
44 _CRT_INIT()
45 DllMain()
46 ...
47 DllMain()
48 _CRT_INIT()
49 _pRawDllMain()
53 extern "C" {
55 static BOOL WINAPI RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved );
56 BOOL (WINAPI *_pRawDllMain)(HINSTANCE, DWORD, LPVOID) = RawDllMain;
60 static BOOL WINAPI RawDllMain( HINSTANCE, DWORD fdwReason, LPVOID )
62 switch (fdwReason)
64 case DLL_PROCESS_ATTACH:
66 #ifdef _DEBUG
67 WCHAR buf[64];
68 DWORD const res = GetEnvironmentVariableW(L"SAL_NO_ASSERT_DIALOGS", buf, SAL_N_ELEMENTS(buf));
69 if (res && res < SAL_N_ELEMENTS(buf))
71 // disable the dialog on abort()
72 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
73 _CrtSetReportMode(_CRT_ERROR, (_CRTDBG_MODE_DEBUG|_CRTDBG_MODE_FILE));
74 // not sure which assertions this affects
75 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
76 _CrtSetReportMode(_CRT_ASSERT, (_CRTDBG_MODE_DEBUG|_CRTDBG_MODE_FILE));
77 // disable the dialog on assert(false)
78 _set_error_mode(_OUT_TO_STDERR);
80 #endif
82 #if OSL_DEBUG_LEVEL < 2
83 /* Suppress file error messages from system like "Floppy A: not inserted" */
84 SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS );
85 #endif
87 //We disable floating point exceptions. This is the usual state at program startup
88 //but on Windows 98 and ME this is not always the case.
89 _control87(_MCW_EM, _MCW_EM);
90 break;
93 case DLL_PROCESS_DETACH:
94 WSACleanup( );
98 On a product build memory management finalization might
99 cause a crash without assertion (assertions off) if heap is
100 corrupted. But a crash report won't help here because at
101 this point all other threads have been terminated and only
102 ntdll is on the stack. No chance to find the reason for the
103 corrupted heap if so.
105 So annoying the user with a crash report is completely useless.
109 #ifndef DBG_UTIL
110 __try
111 #endif
113 /* cleanup locale hashtable */
114 rtl_locale_fini();
116 /* finalize memory management */
117 rtl_cache_fini();
118 rtl_arena_fini();
120 #ifndef DBG_UTIL
121 __except( EXCEPTION_EXECUTE_HANDLER )
124 #endif
125 break;
128 return TRUE;
131 static DWORD GetParentProcessId()
133 DWORD dwParentProcessId = 0;
134 HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
136 if ( IsValidHandle( hSnapshot ) )
138 PROCESSENTRY32 pe;
139 bool fSuccess;
141 ZeroMemory( &pe, sizeof(pe) );
142 pe.dwSize = sizeof(pe);
143 fSuccess = Process32First( hSnapshot, &pe );
145 while( fSuccess )
147 if ( GetCurrentProcessId() == pe.th32ProcessID )
149 dwParentProcessId = pe.th32ParentProcessID;
150 break;
153 fSuccess = Process32Next( hSnapshot, &pe );
156 CloseHandle( hSnapshot );
159 return dwParentProcessId;
162 static DWORD WINAPI ParentMonitorThreadProc( LPVOID lpParam )
164 DWORD_PTR dwParentProcessId = reinterpret_cast<DWORD_PTR>(lpParam);
166 HANDLE hParentProcess = OpenProcess( SYNCHRONIZE, FALSE, dwParentProcessId );
168 osl_setThreadName("headless ParentMonitorThread");
170 if ( IsValidHandle( hParentProcess ) )
172 if ( WAIT_OBJECT_0 == WaitForSingleObject( hParentProcess, INFINITE ) )
174 TerminateProcess( GetCurrentProcess(), 0 );
176 CloseHandle( hParentProcess );
178 return 0;
181 extern "C"
182 BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID )
184 switch (fdwReason)
186 case DLL_PROCESS_ATTACH:
188 WCHAR szBuffer[64];
190 // This code will attach the process to its parent process
191 // if the parent process had set the environment variable.
192 // The corresponding code (setting the environment variable)
193 // is desktop/win32/source/officeloader.cxx
195 DWORD dwResult = GetEnvironmentVariableW( L"ATTACHED_PARENT_PROCESSID", szBuffer, SAL_N_ELEMENTS(szBuffer) );
197 if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
199 DWORD dwThreadId = 0;
201 DWORD_PTR dwParentProcessId = static_cast<DWORD_PTR>(_wtol( szBuffer ));
203 if ( dwParentProcessId && GetParentProcessId() == dwParentProcessId )
205 // No error check, it works or it does not
206 // Thread should only be started for headless mode, see desktop/win32/source/officeloader.cxx
207 HANDLE hThread
208 = CreateThread(nullptr, 0, ParentMonitorThreadProc,
209 reinterpret_cast<LPVOID>(dwParentProcessId), 0, &dwThreadId);
210 // Note: calling CreateThread in DllMain is discouraged
211 // but this is only done in the headless mode and in
212 // that case no other threads should be running at startup
213 // when sal3.dll is loaded; also there is no
214 // synchronization with the spawned thread, so there
215 // does not appear to be a real risk of deadlock here
216 if (hThread)
217 CloseHandle(hThread);
221 return TRUE;
224 case DLL_THREAD_ATTACH:
225 break;
227 case DLL_THREAD_DETACH:
228 osl_callThreadKeyCallbackOnThreadDetach( );
229 break;
232 return TRUE;
235 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */