558 lines
14 KiB
C++
558 lines
14 KiB
C++
/*++
|
||
|
||
Copyright (c) 1995-1997 Microsoft Corporation
|
||
|
||
Module Name :
|
||
wam.cpp
|
||
|
||
Abstract:
|
||
This module implements the exported routines for WAM object
|
||
|
||
Author:
|
||
David Kaplan ( DaveK ) 26-Feb-1997
|
||
|
||
Environment:
|
||
User Mode - Win32
|
||
|
||
Project:
|
||
Wam DLL
|
||
|
||
--*/
|
||
|
||
//
|
||
// Following are the notes from the original MSDEV generated file
|
||
// Note: Proxy/Stub Information
|
||
// To merge the proxy/stub code into the object DLL, add the file
|
||
// dlldatax.c to the project. Make sure precompiled headers
|
||
// are turned off for this file, and add _MERGE_PROXYSTUB to the
|
||
// defines for the project.
|
||
//
|
||
// If you are not running WinNT4.0 or Win95 with DCOM, then you
|
||
// need to remove the following define from dlldatax.c
|
||
// #define _WIN32_WINNT 0x0400
|
||
//
|
||
// Further, if you are running MIDL without /Oicf switch, you also
|
||
// need to remove the following define from dlldatax.c.
|
||
// #define USE_STUBLESS_PROXY
|
||
//
|
||
// Modify the custom build rule for Wam.idl by adding the following
|
||
// files to the Outputs.
|
||
// Wam_p.c
|
||
// dlldata.c
|
||
// To build a separate proxy/stub DLL,
|
||
// run nmake -f Wamps.mk in the project directory.
|
||
|
||
// BEGIN mods
|
||
// Post-wizard mods appear within BEGIN mods ... END mods
|
||
// END mods
|
||
|
||
#include <isapip.hxx>
|
||
#include "pudebug.h"
|
||
|
||
#include "resource.h"
|
||
#include "initguid.h"
|
||
|
||
#include "wamobj.hxx"
|
||
#include "Wam_i.c"
|
||
|
||
// BEGIN mods
|
||
#include <irtldbg.h>
|
||
#include "setable.hxx"
|
||
#include "wamccf.hxx"
|
||
|
||
#include <ooptoken.h>
|
||
|
||
#ifdef _ATL_STATIC_REGISTRY
|
||
#include <statreg.h>
|
||
#include <statreg.cpp>
|
||
#endif
|
||
|
||
#include <atlimpl.cpp>
|
||
// END mods
|
||
|
||
/************************************************************
|
||
* Global Variables
|
||
************************************************************/
|
||
|
||
const CHAR g_pszModuleName[] = "WAM";
|
||
const CHAR g_pszWamRegLocation[] =
|
||
"System\\CurrentControlSet\\Services\\W3Svc\\WAM";
|
||
|
||
#ifdef _MERGE_PROXYSTUB
|
||
extern "C" HINSTANCE hProxyDll;
|
||
#endif
|
||
|
||
CWamModule _Module;
|
||
|
||
BEGIN_OBJECT_MAP(ObjectMap)
|
||
OBJECT_ENTRY(CLSID_Wam, WAM)
|
||
END_OBJECT_MAP()
|
||
|
||
// BEGIN mods
|
||
WAM_CCF_MODULE _WAMCCFModule; // Custom Class Factory Module
|
||
|
||
DECLARE_PLATFORM_TYPE();
|
||
#ifndef _NO_TRACING_
|
||
#include <initguid.h>
|
||
DEFINE_GUID(IisWamObjectGuid,
|
||
0x784d8909, 0xaa8c, 0x11d2, 0x92, 0x5e, 0x00, 0xc0, 0x4f, 0x72, 0xd9, 0x0e);
|
||
#else
|
||
DECLARE_DEBUG_VARIABLE();
|
||
#endif
|
||
DECLARE_DEBUG_PRINTS_OBJECT();
|
||
BOOL g_fGlobalInitDone = FALSE;
|
||
CRITICAL_SECTION g_csGlobalLock;
|
||
|
||
BOOL g_fEnableTryExcept = TRUE;
|
||
|
||
|
||
// WAM needs to ensure that IISRTL is fully initialized. This happens
|
||
// automatically in infocomm when running in-process, but the following
|
||
// hack is needed for OOP apps. InitializeIISRTL and TerminateIISRTL
|
||
// use an internal refcount, so tying the initialization/termination to
|
||
// _Module.GetLockCount works.
|
||
|
||
LONG CWamModule::Lock()
|
||
{
|
||
IF_DEBUG( WAM_REFCOUNTS)
|
||
DBGPRINTF((DBG_CONTEXT, "WamModule::Lock(%d)\n", GetLockCount()));
|
||
InitializeIISRTL();
|
||
AtqInitialize(0);
|
||
return CComModule::Lock();
|
||
}
|
||
|
||
LONG CWamModule::Unlock()
|
||
{
|
||
IF_DEBUG( WAM_REFCOUNTS)
|
||
DBGPRINTF((DBG_CONTEXT, "WamModule::Unlock(%d)\n", GetLockCount()));
|
||
AtqTerminate();
|
||
TerminateIISRTL();
|
||
return CComModule::Unlock();
|
||
}
|
||
|
||
|
||
/************************************************************
|
||
* Local Functions
|
||
************************************************************/
|
||
|
||
static void
|
||
WAMLoadNTApis(VOID);
|
||
|
||
static void
|
||
WAMUnloadNTApis(VOID);
|
||
|
||
PFN_INTERLOCKED_COMPARE_EXCHANGE g_pfnInterlockedCompareExchange = NULL;
|
||
|
||
// END mods
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// DLL Entry Point
|
||
|
||
extern "C"
|
||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
|
||
{
|
||
DWORD dwErr = NO_ERROR;
|
||
|
||
#ifdef _MERGE_PROXYSTUB
|
||
if (!PrxDllMain(hInstance, dwReason, lpReserved))
|
||
return FALSE;
|
||
#endif
|
||
|
||
if (dwReason == DLL_PROCESS_ATTACH) {
|
||
|
||
//
|
||
// BEGIN mods
|
||
//
|
||
|
||
#ifdef _NO_TRACING_
|
||
CREATE_DEBUG_PRINT_OBJECT( g_pszModuleName);
|
||
#else
|
||
CREATE_DEBUG_PRINT_OBJECT( g_pszModuleName, IisWamObjectGuid);
|
||
#endif
|
||
if ( !VALID_DEBUG_PRINT_OBJECT()) {
|
||
return ( FALSE);
|
||
}
|
||
|
||
(VOID)IISGetPlatformType();
|
||
#ifdef _NO_TRACING_
|
||
LOAD_DEBUG_FLAGS_FROM_REG_STR( g_pszWamRegLocation,
|
||
(DEBUG_ERROR | DEBUG_IID) );
|
||
#endif
|
||
|
||
INITIALIZE_PLATFORM_TYPE();
|
||
DBG_ASSERT( IISIsValidPlatform());
|
||
|
||
INITIALIZE_CRITICAL_SECTION( &g_csGlobalLock);
|
||
WAMLoadNTApis();
|
||
|
||
DBG_REQUIRE( WAM_EXEC_INFO::InitClass());
|
||
|
||
dwErr = InitializeHseExtensions();
|
||
|
||
if ( NOERROR == dwErr ) {
|
||
|
||
IF_DEBUG( INIT_CLEAN) {
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
" InitializeHseExtensions succeeded.\n" ) );
|
||
}
|
||
|
||
// From ATL generated
|
||
_Module.Init(ObjectMap, hInstance);
|
||
DisableThreadLibraryCalls(hInstance);
|
||
// End of ATL generated
|
||
|
||
_WAMCCFModule.Init(); // must be after _Module.Init()
|
||
}
|
||
else {
|
||
dwErr = GetLastError();
|
||
IF_DEBUG( ERROR ) {
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
" InitializeHseExtensions failed. Error=%d.\n",
|
||
dwErr) );
|
||
}
|
||
}
|
||
|
||
// END mods
|
||
|
||
} else if (dwReason == DLL_PROCESS_DETACH) {
|
||
|
||
DBGPRINTF( (DBG_CONTEXT,
|
||
" Termination of WAM.dll called with lpvReserved=%08x\n",
|
||
lpReserved) );
|
||
|
||
if ( NULL != lpReserved ) {
|
||
|
||
//
|
||
// Only cleanup if there is a FreeLibrary() call
|
||
//
|
||
|
||
return ( TRUE);
|
||
}
|
||
|
||
// BEGIN mods
|
||
_WAMCCFModule.Term(); // must be before _Module.Term()
|
||
// END mods
|
||
|
||
_Module.Term();
|
||
|
||
// BEGIN mods
|
||
|
||
CleanupHseExtensions();
|
||
|
||
WAM_EXEC_INFO::CleanupClass();
|
||
|
||
DoGlobalCleanup();
|
||
|
||
DeleteCriticalSection( &g_csGlobalLock);
|
||
|
||
WAMUnloadNTApis();
|
||
|
||
DELETE_DEBUG_PRINT_OBJECT();
|
||
// END mods
|
||
}
|
||
|
||
return (dwErr == NO_ERROR);
|
||
} // DllMain()
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Used to determine whether the DLL can be unloaded by OLE
|
||
|
||
STDAPI DllCanUnloadNow(void)
|
||
{
|
||
#ifdef _MERGE_PROXYSTUB
|
||
if (PrxDllCanUnloadNow() != S_OK)
|
||
return S_FALSE;
|
||
#endif
|
||
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
|
||
}
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Returns a class factory to create an object of the requested type
|
||
|
||
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
||
{
|
||
HRESULT hr;
|
||
|
||
if (ppv == NULL) {
|
||
return ( NULL);
|
||
}
|
||
*ppv = NULL; // reset the value before getting inside.
|
||
|
||
IF_DEBUG( IID)
|
||
{
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"GetClassObject( " GUID_FORMAT "," GUID_FORMAT ", %08x)\n",
|
||
GUID_EXPAND( &rclsid),
|
||
GUID_EXPAND( &riid),
|
||
ppv));
|
||
}
|
||
|
||
if (ppv == NULL) {
|
||
return ( E_POINTER);
|
||
}
|
||
*ppv = NULL; // set the incoming value to be invalid entry
|
||
|
||
#ifdef _MERGE_PROXYSTUB
|
||
if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
|
||
return S_OK;
|
||
#endif
|
||
|
||
hr = _Module.GetClassObject(rclsid, riid, ppv);
|
||
|
||
// BEGIN mods
|
||
if (hr == CLASS_E_CLASSNOTAVAILABLE) {
|
||
// If request for standard CF failed -> try custom
|
||
IF_DEBUG( IID){
|
||
DBGPRINTF(( DBG_CONTEXT, "Trying Custom CF GetClassObject()\n"));
|
||
}
|
||
|
||
#ifdef USE_DEFAULT_CF
|
||
hr = _Module.GetClassObject(CLSID_Wam, riid, ppv);
|
||
#else
|
||
hr = _WAMCCFModule.GetClassObject(rclsid, riid, ppv);
|
||
#endif
|
||
}
|
||
|
||
IF_DEBUG( IID)
|
||
{
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"GetClassObject() returns %08x. (*ppv=%08x)\n",
|
||
hr, *ppv));
|
||
}
|
||
|
||
// END mods
|
||
|
||
return ( hr);
|
||
|
||
} // DllGetClassObject()
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// DllRegisterServer - Adds entries to the system registry
|
||
|
||
STDAPI DllRegisterServer(void)
|
||
{
|
||
#ifdef _MERGE_PROXYSTUB
|
||
HRESULT hRes = PrxDllRegisterServer();
|
||
if (FAILED(hRes))
|
||
return hRes;
|
||
#endif
|
||
// registers object, typelib and all interfaces in typelib
|
||
return _Module.RegisterServer(TRUE);
|
||
}
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// DllUnregisterServer - Removes entries from the system registry
|
||
|
||
STDAPI DllUnregisterServer(void)
|
||
{
|
||
#ifdef _MERGE_PROXYSTUB
|
||
PrxDllUnregisterServer();
|
||
#endif
|
||
_Module.UnregisterServer();
|
||
return S_OK;
|
||
}
|
||
|
||
|
||
|
||
/************************************************************
|
||
* Global Init/Cleanup functions
|
||
************************************************************/
|
||
HRESULT
|
||
DoGlobalInitializations(IN BOOL fInProc, IN BOOL fEnableTryExcept)
|
||
/*++
|
||
Description:
|
||
This function is used to initialize the global state of various
|
||
variable in use. RPC runtime runs into deadlocks with respect to the
|
||
NT DLL loader lock. Eventlog for one uses RPC to establish the connections.
|
||
Hence, we use this separate global initialize function to setup state
|
||
outside the NT DLL loader lock boundary (outside the DllMain())
|
||
|
||
Arguments:
|
||
fInProc - Is this WAM instance running InProc?
|
||
fEnableTryExcept - Catch exceptions in ISAPIs?
|
||
|
||
Returns:
|
||
HRESULT - NOERROR means success; otherwise returns custom error.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = NOERROR;
|
||
|
||
//
|
||
// Use Locks to ensure that only one guy is initializing the data
|
||
//
|
||
EnterCriticalSection( &g_csGlobalLock);
|
||
|
||
if ( !g_fGlobalInitDone) {
|
||
|
||
// remember fEnableTryExcept flag
|
||
g_fEnableTryExcept = fEnableTryExcept;
|
||
|
||
if( !fInProc )
|
||
{
|
||
hr = CWamOopTokenInfo::Create();
|
||
DBG_ASSERT( SUCCEEDED(hr) );
|
||
|
||
if( WAM_EXEC_INFO::sm_pSVCacheMap == NULL )
|
||
{
|
||
WAM_EXEC_INFO::sm_pSVCacheMap = new SV_CACHE_MAP();
|
||
DBG_ASSERT( WAM_EXEC_INFO::sm_pSVCacheMap != NULL );
|
||
|
||
if( WAM_EXEC_INFO::sm_pSVCacheMap != NULL )
|
||
{
|
||
DBG_REQUIRE( WAM_EXEC_INFO::sm_pSVCacheMap->Initialize() );
|
||
}
|
||
}
|
||
}
|
||
|
||
#ifndef _NO_TRACING_
|
||
CREATE_INITIALIZE_DEBUG();
|
||
#endif
|
||
|
||
g_fGlobalInitDone = TRUE;
|
||
}
|
||
|
||
LeaveCriticalSection( &g_csGlobalLock);
|
||
|
||
IF_DEBUG( INIT_CLEAN) {
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" DoGlobalInitializations() returns hr = %08x\n",
|
||
hr));
|
||
}
|
||
|
||
return ( hr);
|
||
} // DoGlobalInitializations()
|
||
|
||
|
||
HRESULT DoGlobalCleanup(VOID)
|
||
{
|
||
HRESULT hr = NOERROR;
|
||
|
||
if ( !g_fGlobalInitDone) {
|
||
return ( hr);
|
||
}
|
||
|
||
EnterCriticalSection( &g_csGlobalLock);
|
||
|
||
if( CWamOopTokenInfo::HasInstance() )
|
||
{
|
||
CWamOopTokenInfo::Destroy();
|
||
}
|
||
|
||
delete WAM_EXEC_INFO::sm_pSVCacheMap;
|
||
WAM_EXEC_INFO::sm_pSVCacheMap = NULL;
|
||
|
||
g_fGlobalInitDone = FALSE;
|
||
|
||
LeaveCriticalSection( &g_csGlobalLock);
|
||
|
||
return ( hr);
|
||
|
||
} // DoGlobalCleanup()
|
||
|
||
|
||
|
||
/************************************************************
|
||
* Thunks for Fake NT APIs
|
||
************************************************************/
|
||
|
||
CRITICAL_SECTION g_csNonNTAPIs;
|
||
|
||
LONG
|
||
FakeInterlockedCompareExchange(
|
||
LONG *Destination,
|
||
LONG Exchange,
|
||
LONG Comperand
|
||
)
|
||
/*++
|
||
Description:
|
||
This function fakes the interlocked compare exchange operation for non NT platforms
|
||
See WAMLoadNTApis() for details
|
||
|
||
Returns:
|
||
returns the old value at Destination
|
||
--*/
|
||
{
|
||
LONG oldValue;
|
||
|
||
EnterCriticalSection( &g_csNonNTAPIs);
|
||
|
||
oldValue = *Destination;
|
||
|
||
if ( oldValue == Comperand ) {
|
||
*Destination = Exchange;
|
||
}
|
||
|
||
LeaveCriticalSection( &g_csNonNTAPIs);
|
||
|
||
return( oldValue);
|
||
} // FakeInterlockedCompareExchange()
|
||
|
||
|
||
static VOID
|
||
WAMLoadNTApis(VOID)
|
||
/*++
|
||
Description:
|
||
This function loads the entry point for functions from
|
||
Kernel32.dll. If the entry point is missing, the function
|
||
pointer will point to a fake routine which does nothing. Otherwise,
|
||
it will point to the real function.
|
||
|
||
It dynamically loads the kernel32.dll to find the entry ponit and then
|
||
unloads it after getting the address. For the resulting function
|
||
pointer to work correctly one has to ensure that the kernel32.dll is
|
||
linked with the dll/exe which links to this file.
|
||
--*/
|
||
{
|
||
// Initialize the critical section for non NT API support, in case if we need this
|
||
INITIALIZE_CRITICAL_SECTION( &g_csNonNTAPIs);
|
||
|
||
if ( g_pfnInterlockedCompareExchange == NULL ) {
|
||
|
||
HINSTANCE tmpInstance;
|
||
|
||
//
|
||
// load kernel32 and get NT specific entry points
|
||
//
|
||
|
||
tmpInstance = LoadLibrary("kernel32.dll");
|
||
if ( tmpInstance != NULL ) {
|
||
|
||
// For some reason the original function is _InterlockedCompareExchange!
|
||
g_pfnInterlockedCompareExchange = (PFN_INTERLOCKED_COMPARE_EXCHANGE )
|
||
GetProcAddress( tmpInstance, "InterlockedCompareExchange");
|
||
|
||
if ( g_pfnInterlockedCompareExchange == NULL ) {
|
||
// the function is not available
|
||
// Just thunk it.
|
||
g_pfnInterlockedCompareExchange = FakeInterlockedCompareExchange;
|
||
}
|
||
|
||
//
|
||
// We can free this because we are statically linked to it
|
||
//
|
||
|
||
FreeLibrary(tmpInstance);
|
||
}
|
||
}
|
||
|
||
return;
|
||
} // WAMLoadNTApis()
|
||
|
||
static void
|
||
WAMUnloadNTApis(VOID)
|
||
{
|
||
DeleteCriticalSection( &g_csNonNTAPIs);
|
||
|
||
return;
|
||
} // WAMUnloadNTApis()
|
||
|