|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // Windows doesn't support pthread_key_create's destr_function, and in fact | 
|  | // it's a bit tricky to get code to run when a thread exits.  This is | 
|  | // cargo-cult magic from http://www.codeproject.com/threads/tls.asp. | 
|  | // We are trying to be compatible with both a LoadLibrary style invocation, as | 
|  | // well as static linking. This code only needs to be included if we use | 
|  | // LoadLibrary, but it hooks into the "standard" set of TLS callbacks that are | 
|  | // provided for static linking. | 
|  |  | 
|  | // This code is deliberately written to match the style of calls seen in | 
|  | // base/threading/thread_local_storage_win.cc.  Please keep the two in sync if | 
|  | // coding conventions are changed. | 
|  |  | 
|  | // WARNING: Do *NOT* try to include this in the construction of the base | 
|  | // library, even though it potentially drives code in | 
|  | // base/threading/thread_local_storage_win.cc.  If you do, some users will end | 
|  | // up getting duplicate definition of DllMain() in some of their later links. | 
|  |  | 
|  | // Force a reference to _tls_used to make the linker create the TLS directory | 
|  | // if it's not already there (that is, even if __declspec(thread) is not used). | 
|  | // Force a reference to p_thread_callback_dllmain_typical_entry to prevent whole | 
|  | // program optimization from discarding the variables. | 
|  |  | 
|  | #include <windows.h> | 
|  |  | 
|  | #include "base/compiler_specific.h" | 
|  | #include "base/win/win_util.h" | 
|  |  | 
|  | // Indicate if another service is scanning the callbacks.  When this becomes | 
|  | // set to true, then DllMain() will stop supporting the callback service. This | 
|  | // value is set to true the first time any of our callbacks are called, as that | 
|  | // shows that some other service is handling callbacks. | 
|  | static bool linker_notifications_are_active = false; | 
|  |  | 
|  | // This will be our mostly no-op callback that we'll list.  We won't | 
|  | // deliberately call it, and if it is called, that means we don't need to do any | 
|  | // of the callbacks anymore.  We expect such a call to arrive via a | 
|  | // THREAD_ATTACH message, long before we'd have to perform our THREAD_DETACH | 
|  | // callbacks. | 
|  | static void NTAPI on_callback(PVOID h, DWORD reason, PVOID reserved); | 
|  |  | 
|  | #ifdef _WIN64 | 
|  |  | 
|  | #pragma comment(linker, "/INCLUDE:_tls_used") | 
|  | #pragma comment(linker, "/INCLUDE:p_thread_callback_dllmain_typical_entry") | 
|  |  | 
|  | #else  // _WIN64 | 
|  |  | 
|  | #pragma comment(linker, "/INCLUDE:__tls_used") | 
|  | #pragma comment(linker, "/INCLUDE:_p_thread_callback_dllmain_typical_entry") | 
|  |  | 
|  | #endif  // _WIN64 | 
|  |  | 
|  | // Explicitly depend on VC\crt\src\tlssup.c variables | 
|  | // to bracket the list of TLS callbacks. | 
|  | extern "C" PIMAGE_TLS_CALLBACK __xl_a, __xl_z; | 
|  |  | 
|  | // extern "C" suppresses C++ name mangling so we know the symbol names for the | 
|  | // linker /INCLUDE:symbol pragmas above. | 
|  | extern "C" { | 
|  | #ifdef _WIN64 | 
|  |  | 
|  | // .CRT section is merged with .rdata on x64 so it must be constant data. | 
|  | #pragma data_seg(push, old_seg) | 
|  | // Use a typical possible name in the .CRT$XL? list of segments. | 
|  | #pragma const_seg(".CRT$XLB") | 
|  | // When defining a const variable, it must have external linkage to be sure the | 
|  | // linker doesn't discard it. | 
|  | extern const PIMAGE_TLS_CALLBACK p_thread_callback_dllmain_typical_entry; | 
|  | const PIMAGE_TLS_CALLBACK p_thread_callback_dllmain_typical_entry = on_callback; | 
|  | #pragma data_seg(pop, old_seg) | 
|  |  | 
|  | #else  // _WIN64 | 
|  |  | 
|  | #pragma data_seg(push, old_seg) | 
|  | // Use a typical possible name in the .CRT$XL? list of segments. | 
|  | #pragma data_seg(".CRT$XLB") | 
|  | PIMAGE_TLS_CALLBACK p_thread_callback_dllmain_typical_entry = on_callback; | 
|  | #pragma data_seg(pop, old_seg) | 
|  |  | 
|  | #endif  // _WIN64 | 
|  | }  // extern "C" | 
|  |  | 
|  | // Custom crash code to get a unique entry in crash reports. | 
|  | NOINLINE static void CrashOnProcessDetach() { | 
|  | *static_cast<volatile int*>(0) = 0x356; | 
|  | } | 
|  |  | 
|  | // Make DllMain call the listed callbacks.  This way any third parties that are | 
|  | // linked in will also be called. | 
|  | BOOL WINAPI DllMain(PVOID h, DWORD reason, PVOID reserved) { | 
|  | if (DLL_PROCESS_DETACH == reason && base::win::ShouldCrashOnProcessDetach()) | 
|  | CrashOnProcessDetach(); | 
|  |  | 
|  | if (DLL_THREAD_DETACH != reason && DLL_PROCESS_DETACH != reason) | 
|  | return true;  // We won't service THREAD_ATTACH calls. | 
|  |  | 
|  | if (linker_notifications_are_active) | 
|  | return true;  // Some other service is doing this work. | 
|  |  | 
|  | for (PIMAGE_TLS_CALLBACK* it = &__xl_a; it < &__xl_z; ++it) { | 
|  | if (*it == NULL || *it == on_callback) | 
|  | continue;  // Don't bother to call our own callback. | 
|  | (*it)(h, reason, reserved); | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static void NTAPI on_callback(PVOID h, DWORD reason, PVOID reserved) { | 
|  | // Do nothing.  We were just a place holder in the list used to test that we | 
|  | // call all items. | 
|  | // If we are called, it means that some other system is scanning the callbacks | 
|  | // and we don't need to do so in DllMain(). | 
|  | linker_notifications_are_active = true; | 
|  | // Note: If some other routine some how plays this same game... we could both | 
|  | // decide not to do the scanning <sigh>, but this trick should suppress | 
|  | // duplicate calls on Vista, where the runtime takes care of the callbacks, | 
|  | // and allow us to do the callbacks on XP, where we are currently devoid of | 
|  | // callbacks (due to an explicit LoadLibrary call). | 
|  | } |