diff options
Diffstat (limited to 'src/ccapi/lib/win/dllmain.cxx')
| -rw-r--r-- | src/ccapi/lib/win/dllmain.cxx | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/ccapi/lib/win/dllmain.cxx b/src/ccapi/lib/win/dllmain.cxx new file mode 100644 index 000000000000..82cacad9c87c --- /dev/null +++ b/src/ccapi/lib/win/dllmain.cxx @@ -0,0 +1,222 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { +#include <windows.h> +#include <LMCons.h> + +#include "dllmain.h" +#include "tls.h" +#include "cci_debugging.h" +#include "ccapi_context.h" +#include "ccapi_ipc.h" +#include "client.h" + +void cci_process_init__auxinit(); + } + + +#define CCAPI_V2_MUTEX_NAME TEXT("MIT_CCAPI_V4_MUTEX") + +// Process-specific data: +static DWORD dwTlsIndex; +static char _user[UNLEN+1]; // Username is used as part of the server and client endpoints. +static HANDLE sessionToken; +static char* ep_prefices[] = {"CCS", "CCAPI"}; +HANDLE hCCAPIv2Mutex = NULL; +DWORD firstThreadID = 0; + +// These data structures are used by the old CCAPI implementation +// to keep track of the state of the RPC connection. All data is static. +static Init init; +static Client client; + +DWORD GetTlsIndex() {return dwTlsIndex;} + +// DllMain() is the entry-point function for this DLL. +BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD fdwReason, // reason called + LPVOID lpvReserved) { // reserved + + struct tspdata* ptspdata; + BOOL fIgnore; + BOOL bStatus; + DWORD status = 0; // 0 is success. + DWORD maxUN = sizeof(_user); + unsigned int i = 0; + unsigned int j = 0; + + switch (fdwReason) { + // The DLL is loading due to process initialization or a call to LoadLibrary: + case DLL_PROCESS_ATTACH: + cci_debug_printf("%s DLL_PROCESS_ATTACH", __FUNCTION__); + // Process-wide mutex used to allow only one thread at a time into the RPC code: + hCCAPIv2Mutex = CreateMutex(NULL, FALSE, CCAPI_V2_MUTEX_NAME); + + // Figure out our username; it's process-wide: + bStatus = GetUserName(_user, &maxUN); + if (!bStatus) return bStatus; + + // Remove any characters that aren't valid endpoint characters: + while (_user[j] != 0) { + if (isalnum(_user[j])) _user[i++] = _user[j]; + j++; + } + _user[i] = '\0'; + + // Our logon session is determined in client.cxx, old CCAPI code carried + // over to this implementation. + + // Allocate a TLS index: + if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; + + cci_process_init__auxinit(); + // Don't break; fallthrough: Initialize the TLS index for first thread. + + // The attached process creates a new thread: + case DLL_THREAD_ATTACH: + cci_debug_printf("%s DLL_THREAD_ATTACH", __FUNCTION__); + // Don't actually rely on this case for allocation of resources. + // Applications (like SecureCRT) may have threads already + // created (say 'A' and 'B') before the dll is loaded. If the dll + // is loaded in thread 'A' but then used in thread 'B', thread 'B' + // will never execute this code. + fIgnore = TlsSetValue(dwTlsIndex, NULL); + + // Do not call cci_ipc_thread_init() yet; defer until we actually + // need it. On XP, cci_ipc_thread_init() will cause additional + // threads to be immediately spawned, which will bring us right + // back here again ad infinitum, until windows + // resources are exhausted. + break; + + // The thread of the attached process terminates: + case DLL_THREAD_DETACH: + cci_debug_printf("%s DLL_THREAD_DETACH", __FUNCTION__); + // Release the allocated memory for this thread + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) { + free(ptspdata); + TlsSetValue(dwTlsIndex, NULL); + } + break; + + // DLL unload due to process termination or FreeLibrary: + case DLL_PROCESS_DETACH: + cci_debug_printf("%s DLL_PROCESS_DETACH", __FUNCTION__); + //++ Copied from previous implementation: + // Process Teardown "Problem" + // + // There are two problems that occur during process teardown: + // + // 1) Windows (NT/9x/2000) does not keep track of load/unload + // ordering dependencies for use in process teardown. + // + // 2) The RPC exception handling in the RPC calls do not work + // during process shutdown in Win9x. + // + // When a process is being torn down in Windows, the krbcc DLL + // may get a DLL_PROCESS_DETACH before other DLLs are done + // with it. Thus, it may disconnect from the RPC server + // before the last shutdown RPC call. + // + // On NT/2000, this is ok because the RPC call will fail and just + // return an error. + // + // On Win9x/Me, the RPC exception will not be caught. + // However, Win9x ignores exceptions during process shutdown, + // so the exception will never be seen unless a debugger is + // attached to the proccess. + // + // A good potential woraround would be to have a global + // variable that denotes whether the DLL is attached to the + // process. If it is not, all entrypoints into the DLL should + // return failure. + // + // A not as good workaround is below but ifdefed out. + // + // However, we can safely ignore this problem since it can + // only affects people running debuggers under 9x/Me who are + // using multiple DLLs that use this DLL. + // + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); +#if 0 + bool process_teardown_workaround = false; + if (lpvReserved) { + Init::InitInfo info; + status = Init::Info(info); + if (status) break; + if (!info.isNT) process_teardown_workaround = true; + } + if (process_teardown_workaround) + break; +#endif + // return value is ignored, so we set status for debugging purposes + status = Client::Cleanup(); + status = Init::Cleanup(); + ReleaseMutex( hCCAPIv2Mutex ); + CloseHandle( hCCAPIv2Mutex ); + //-- Copied from previous implementation. + + // Release the allocated memory for this thread: + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) + free(ptspdata); + TlsFree(dwTlsIndex); // Release the TLS index. + // Ideally, we would enumerate all other threads here and + // release their thread local storage as well. + break; + + default: + cci_debug_printf("%s unexpected reason %d", __FUNCTION__, fdwReason); + break; + } + + UNREFERENCED_PARAMETER(hinstDLL); // no whining! + UNREFERENCED_PARAMETER(lpvReserved); + return status ? FALSE : TRUE; +} + + +#ifdef __cplusplus // If used by C++ code, +extern "C" { // we need to export the C interface +#endif + +#ifdef __cplusplus +} +#endif + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +extern "C" void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len) { + return(malloc(len)); + } + +extern "C" void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr) { + free(ptr); + } |
