sc: factor out common code
[LibreOffice.git] / sal / osl / w32 / dllentry.cxx
blob5389c056d5a279221997aa2cd3409f53a6719d33
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 <process.h>
22 #include <tlhelp32.h>
23 #include <rpc.h>
24 #include <winsock.h>
25 #ifdef _DEBUG
26 #include <crtdbg.h>
27 #endif
28 #include <osl/diagnose.h>
29 #include <sal/types.h>
30 #include <float.h>
32 #include <osl/mutex.h>
33 #include <osl/thread.h>
35 #include "file_url.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 //We disable floating point exceptions. This is the usual state at program startup
89 //but on Windows 98 and ME this is not always the case.
90 _control87(_MCW_EM, _MCW_EM);
91 break;
94 case DLL_PROCESS_DETACH:
95 WSACleanup( );
99 On a product build memory management finalization might
100 cause a crash without assertion (assertions off) if heap is
101 corrupted. But a crash report won't help here because at
102 this point all other threads have been terminated and only
103 ntdll is on the stack. No chance to find the reason for the
104 corrupted heap if so.
106 So annoying the user with a crash report is completely useless.
110 #ifndef DBG_UTIL
111 __try
112 #endif
114 /* cleanup locale hashtable */
115 rtl_locale_fini();
117 /* finalize memory management */
118 rtl_cache_fini();
119 rtl_arena_fini();
121 #ifndef DBG_UTIL
122 __except( EXCEPTION_EXECUTE_HANDLER )
125 #endif
126 break;
129 return TRUE;
132 static DWORD GetParentProcessId()
134 DWORD dwParentProcessId = 0;
135 HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
137 if ( IsValidHandle( hSnapshot ) )
139 PROCESSENTRY32 pe;
140 bool fSuccess;
142 ZeroMemory( &pe, sizeof(pe) );
143 pe.dwSize = sizeof(pe);
144 fSuccess = Process32First( hSnapshot, &pe );
146 while( fSuccess )
148 if ( GetCurrentProcessId() == pe.th32ProcessID )
150 dwParentProcessId = pe.th32ParentProcessID;
151 break;
154 fSuccess = Process32Next( hSnapshot, &pe );
157 CloseHandle( hSnapshot );
160 return dwParentProcessId;
163 static unsigned __stdcall ParentMonitorThreadProc(void* lpParam)
165 DWORD_PTR dwParentProcessId = reinterpret_cast<DWORD_PTR>(lpParam);
167 HANDLE hParentProcess = OpenProcess( SYNCHRONIZE, FALSE, dwParentProcessId );
169 osl_setThreadName("headless ParentMonitorThread");
171 if ( IsValidHandle( hParentProcess ) )
173 if ( WAIT_OBJECT_0 == WaitForSingleObject( hParentProcess, INFINITE ) )
175 TerminateProcess( GetCurrentProcess(), 0 );
177 CloseHandle( hParentProcess );
179 return 0;
182 extern "C"
183 BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID )
185 switch (fdwReason)
187 case DLL_PROCESS_ATTACH:
189 WCHAR szBuffer[64];
191 // This code will attach the process to its parent process
192 // if the parent process had set the environment variable.
193 // The corresponding code (setting the environment variable)
194 // is desktop/win32/source/officeloader.cxx
196 DWORD dwResult = GetEnvironmentVariableW( L"ATTACHED_PARENT_PROCESSID", szBuffer, SAL_N_ELEMENTS(szBuffer) );
198 if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
200 DWORD_PTR dwParentProcessId = static_cast<DWORD_PTR>(_wtol( szBuffer ));
202 if ( dwParentProcessId && GetParentProcessId() == dwParentProcessId )
204 // No error check, it works or it does not
205 // Thread should only be started for headless mode, see desktop/win32/source/officeloader.cxx
206 HANDLE hThread
207 = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, ParentMonitorThreadProc,
208 reinterpret_cast<LPVOID>(dwParentProcessId), 0, nullptr));
209 // Note: calling CreateThread in DllMain is discouraged
210 // but this is only done in the headless mode and in
211 // that case no other threads should be running at startup
212 // when sal3.dll is loaded; also there is no
213 // synchronization with the spawned thread, so there
214 // does not appear to be a real risk of deadlock here
215 if (hThread)
216 CloseHandle(hThread);
220 return TRUE;
223 case DLL_THREAD_ATTACH:
224 break;
226 case DLL_THREAD_DETACH:
227 osl_callThreadKeyCallbackOnThreadDetach( );
228 break;
231 return TRUE;
234 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */