// init.cpp
#include <windows.h>
#include <_vcclrit.h>
// Call this function before you call anything in this DLL.
// It is safe to call from multiple threads; it is not reference
// counted; and is reentrancy safe.
__declspec(dllexport) void __cdecl DllEnsureInit(void)
{
// Do nothing else here. If you need extra initialization steps,
// create static objects with constructors that perform initialization.
__crt_dll_initialize();
// Do nothing else here.
}
// Call this function after this whole process is totally done
// calling anything in this DLL. It is safe to call from multiple
// threads; is not reference counted; and is reentrancy safe.
// First call will terminate.
__declspec(dllexport) void __cdecl DllForceTerm(void)
{
// Do nothing else here. If you need extra terminate steps,
// use atexit.
__crt_dll_terminate();
// Do nothing else here.
}
/***
* _vcclrit.h
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Purpose:
* This file defines the functions and variables used by user
* to initialize CRT and the dll in IJW scenario.
*
****/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
extern IMAGE_DOS_HEADER __ImageBase;
BOOL WINAPI _DllMainCRTStartup(
HANDLE hDllHandle,
DWORD dwReason,
LPVOID lpreserved
);
#ifdef __cplusplus
}
#endif
#ifdef _cplusplus
#define __USE_GLOBAL_NAMESPACE ::
#else
#define __USE_GLOBAL_NAMESPACE
#endif
// Used to lock
__declspec( selectany ) LONG volatile __lock_handle = 0;
// Init called
__declspec(selectany) BOOL volatile __initialized = FALSE;
// Term called
__declspec( selectany ) BOOL volatile __terminated = FALSE;
__inline BOOL WINAPI __crt_dll_initialize()
{
// Try to make the variable names unique, so that the variables
// do not even clash with macros.
static BOOL volatile (__retval) = FALSE;
static DWORD volatile (__lockThreadId) = 0xffffffff;
DWORD volatile (__currentThreadId) = __USE_GLOBAL_NAMESPACE(GetCurrentThreadId)();
int (__int_var)=0;
// Take Lock; this is needed for multithreaded scenario.
// Additionally, the threads need to wait here to make sure that the dll
// is initialized when they get past this function.
while ( __USE_GLOBAL_NAMESPACE(InterlockedExchange)( &(__lock_handle), 1) == 1 )
{
++(__int_var);
if ((__lockThreadId) == (__currentThreadId))
{
return TRUE;
}
__USE_GLOBAL_NAMESPACE(Sleep)( (__int_var)>1000?100:0 );
// If you hang in this loop, this implies that your
// dllMainCRTStartup is hung on another thread.
// The most likely cause of this is a hang in one of your
// static constructors or destructors.
}
// Note: you do not really need any interlocked stuff here because the
// writes are always in the lock. Only reads are outside the lock.
(__lockThreadId) = (__currentThreadId);
__try {
if ( (__terminated) == TRUE )
{
(__retval) = FALSE;
}
else if ( (__initialized) == FALSE )
{
(__retval) = (_DllMainCRTStartup)( ( HINSTANCE )( &__ImageBase ), DLL_PROCESS_ATTACH, 0 );
(__initialized) = TRUE;
}
} __finally {
// revert the __lockThreadId
(__lockThreadId) = 0xffffffff;
// Release Lock
__USE_GLOBAL_NAMESPACE(InterlockedExchange)(&(__lock_handle),0);
}
return (__retval);
}
__inline BOOL WINAPI __crt_dll_terminate()
{
static BOOL volatile (__retval) = TRUE;
static DWORD volatile (__lockThreadId) = 0xffffffff;
DWORD volatile (__currentThreadId) = __USE_GLOBAL_NAMESPACE(GetCurrentThreadId)();
int (__int_var)=0;
// Take Lock; this lock is needed to keep Terminate
// in sync with Initialize.
while ( __USE_GLOBAL_NAMESPACE(InterlockedExchange)( &(__lock_handle), 1) == 1 )
{
++(__int_var);
if ((__lockThreadId) == (__currentThreadId))
{
return TRUE;
}
__USE_GLOBAL_NAMESPACE(Sleep)( (__int_var)>1000?100:0 );
// If you hang in this loop, this implies that your
// dllMainCRTStartup is hung on another thread. The most likely
// cause of this is a hang in one of your static constructors
// or destructors.
}
// Note: you do not really need any interlocked stuff here because the
// writes are always in the lock. Only reads are outside the lock.
(__lockThreadId) = (__currentThreadId);
__try {
if ( (__initialized) == FALSE )
{
(__retval) = FALSE;
}
else if ( (__terminated) == FALSE )
{
(__retval) = _DllMainCRTStartup( ( HINSTANCE )( &(__ImageBase) ), DLL_PROCESS_DETACH, 0 );
(__terminated) = TRUE;
}
} __finally {
// revert the __lockThreadId
(__lockThreadId) = 0xffffffff;
// Release Lock
__USE_GLOBAL_NAMESPACE(InterlockedExchange)(&(__lock_handle),0);
}
return (__retval);
}