windows-nt/Source/XPSP1/NT/inetsrv/iis/iisrearc/iisplus/wam/wam.cpp
2020-09-26 16:20:57 +08:00

552 lines
12 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
Wade Hilmo ( WadeH ) 08-Sep-2000
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 "precomp.hxx"
#include <w3isapi.h>
#include <isapi_context.hxx>
#include "wamobj.hxx"
#include "IWam_i.c"
#include "wamccf.hxx"
#include <atlbase.h>
// BEGIN mods
#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";
HMODULE WAM::sm_hIsapiModule;
PFN_ISAPI_TERM_MODULE WAM::sm_pfnTermIsapiModule;
PFN_ISAPI_PROCESS_REQUEST WAM::sm_pfnProcessIsapiRequest;
PFN_ISAPI_PROCESS_COMPLETION WAM::sm_pfnProcessIsapiCompletion;
#ifdef _MERGE_PROXYSTUB
extern "C" HINSTANCE hProxyDll;
#endif
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_Wam, WAM)
END_OBJECT_MAP()
// BEGIN mods
WAM_CCF_MODULE _WAMCCFModule;
DECLARE_PLATFORM_TYPE();
DECLARE_DEBUG_VARIABLE();
DECLARE_DEBUG_PRINTS_OBJECT();
// END mods
/************************************************************
* Type Definitions
************************************************************/
// BUGBUG
#undef INET_INFO_KEY
#undef INET_INFO_PARAMETERS_KEY
//
// Configuration parameters registry key.
//
#define INET_INFO_KEY \
"System\\CurrentControlSet\\Services\\iisw3adm"
#define INET_INFO_PARAMETERS_KEY \
INET_INFO_KEY "\\Parameters"
const CHAR g_pszWpRegLocation[] =
INET_INFO_PARAMETERS_KEY "\\WP";
class DEBUG_WRAPPER {
public:
DEBUG_WRAPPER( IN LPCSTR pszModule )
{
#if DBG
CREATE_DEBUG_PRINT_OBJECT( pszModule );
#else
UNREFERENCED_PARAMETER( pszModule );
#endif
LOAD_DEBUG_FLAGS_FROM_REG_STR( g_pszWpRegLocation, DEBUG_ERROR );
}
~DEBUG_WRAPPER(void)
{ DELETE_DEBUG_PRINT_OBJECT(); }
};
class CWamModule _Module;
/////////////////////////////////////////////////////////////////////////////
// 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
//
// From ATL generated
_Module.Init(ObjectMap, hInstance);
DisableThreadLibraryCalls(hInstance);
// End of ATL generated
_WAMCCFModule.Init();
// END mods
}
else if (dwReason == DLL_PROCESS_DETACH)
{
if ( NULL != lpReserved )
{
//
// Only cleanup if there is a FreeLibrary() call
//
return ( TRUE);
}
_WAMCCFModule.Term();
_Module.Term();
// BEGIN mods
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 (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 = _WAMCCFModule.GetClassObject(rclsid, riid, ppv);
// BEGIN mods
if (hr == CLASS_E_CLASSNOTAVAILABLE)
{
// If request for standard CF failed -> try custom
hr = _Module.GetClassObject(CLSID_Wam, riid, 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;
}
HRESULT
WAM::WamProcessIsapiRequest(
BYTE *pCoreData,
DWORD cbCoreData,
IIsapiCore *pIsapiCore,
DWORD *pdwHseResult
)
/*++
Routine Description:
Processes an ISAPI request
Arguments:
pCoreData - The core data from the server for the request
cbCoreData - The size of pCoreData
pIsapiCore - The IIsapiCore interface pointer for this request
pdwHseResult - Upon return, contains the return from HttpExtensionProc
Return Value:
HRESULT
--*/
{
HRESULT hr = NOERROR;
pIsapiCore->AddRef();
hr = sm_pfnProcessIsapiRequest(
pIsapiCore,
(ISAPI_CORE_DATA*)pCoreData,
pdwHseResult
);
pIsapiCore->Release();
return hr;
}
HRESULT
WAM::WamProcessIsapiCompletion(
DWORD64 IsapiContext,
DWORD cbCompletion,
DWORD cbCompletionStatus
)
/*++
Routine Description:
Processes an ISAPI I/O completion
Arguments:
IsapiContext - The ISAPI_CONTEXT that identifies the request
cbCompletion - The number of bytes associated with the completion
cbCompletionStatus - The status code associated with the completion
Return Value:
HRESULT
--*/
{
HRESULT hr = NOERROR;
hr = sm_pfnProcessIsapiCompletion(
IsapiContext,
cbCompletion,
cbCompletionStatus
);
return hr;
}
HRESULT
WAM::WamInitProcess(
BYTE *szIsapiModule,
DWORD cbIsapiModule,
DWORD *pdwProcessId,
LPSTR szClsid,
LPSTR szIsapiHandlerInstance,
DWORD dwCallingProcess
)
/*++
Routine Description:
Initializes WAM for the host process. This includes loading
w3isapi.dll and getting function pointers for the relevant stuff
Arguments:
szIsapiModule - The full path (UNICODE) of w3isapi.dll
cbIsapiModule - The number of bytes in the above path
pdwProcessId - Upon return, contains the process ID of the
host process
szClsid - The CLSID of the WAM object being initialized
szIsapiHandlerInstance - The instance ID of the W3_ISAPI_HANDLER that's
initializing this WAM.
dwCallingProcess - The process ID of this function's caller
Return Value:
HRESULT
--*/
{
HRESULT hr = NOERROR;
PFN_ISAPI_INIT_MODULE pfnInit = NULL;
//
// Initialize IISUTIL
//
if ( !InitializeIISUtil() )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
DBGPRINTF(( DBG_CONTEXT,
"Error initializing IISUTIL. hr = %x\n",
hr ));
goto ErrorExit;
}
//
// Load and initialize the ISAPI module
//
sm_hIsapiModule = LoadLibraryW( (LPWSTR)szIsapiModule );
if( sm_hIsapiModule == NULL )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
goto ErrorExit;
}
sm_pfnTermIsapiModule =
(PFN_ISAPI_TERM_MODULE)GetProcAddress( sm_hIsapiModule,
ISAPI_TERM_MODULE
);
sm_pfnProcessIsapiRequest =
(PFN_ISAPI_PROCESS_REQUEST)GetProcAddress( sm_hIsapiModule,
ISAPI_PROCESS_REQUEST
);
sm_pfnProcessIsapiCompletion =
(PFN_ISAPI_PROCESS_COMPLETION)GetProcAddress( sm_hIsapiModule,
ISAPI_PROCESS_COMPLETION
);
if( !sm_pfnTermIsapiModule ||
!sm_pfnProcessIsapiRequest ||
!sm_pfnProcessIsapiCompletion )
{
hr = E_FAIL;
goto ErrorExit;
}
pfnInit =
(PFN_ISAPI_INIT_MODULE)GetProcAddress( sm_hIsapiModule,
ISAPI_INIT_MODULE
);
if( !pfnInit )
{
hr = E_FAIL;
goto ErrorExit;
}
hr = pfnInit(
szClsid,
szIsapiHandlerInstance,
dwCallingProcess
);
if( FAILED(hr) )
{
goto ErrorExit;
}
//
// Set the process ID for the process hosting this object
//
*pdwProcessId = GetCurrentProcessId();
return hr;
ErrorExit:
DBG_ASSERT( FAILED( hr ) );
return hr;
}
HRESULT
WAM::WamUninitProcess(
VOID
)
/*++
Routine Description:
Uninitializes WAM for the host process. This function ultimately
causes TerminateExtension to get called for each loaded extension.
Arguments:
None
Return Value:
HRESULT
--*/
{
HRESULT hr = NOERROR;
DBG_ASSERT( sm_pfnTermIsapiModule );
DBG_ASSERT( sm_hIsapiModule );
if( sm_pfnTermIsapiModule )
{
sm_pfnTermIsapiModule();
sm_pfnTermIsapiModule = NULL;
}
if( sm_hIsapiModule )
{
FreeLibrary( sm_hIsapiModule );
sm_hIsapiModule = NULL;
}
TerminateIISUtil();
return hr;
}
HRESULT
WAM::WamMarshalAsyncReadBuffer(
DWORD64 IsapiContext,
BYTE *pBuffer,
DWORD cbBuffer
)
/*++
Routine Description:
Receives a buffer to be passed to a request. This function will be
called just prior to an I/O completion in the case where and OOP
extension does an asynchronous ReadClient.
Arguments:
IsapiContext - The ISAPI_CONTEXT that identifies the request
pBuffer - The data buffer
cbBuffer - The size of pBuffer
Return Value:
HRESULT
--*/
{
ISAPI_CONTEXT * pIsapiContext;
VOID * pReadBuffer;
pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( IsapiContext );
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->QueryIoState() == AsyncReadPending );
pReadBuffer = pIsapiContext->QueryAsyncIoBuffer();
DBG_ASSERT( pReadBuffer != NULL );
memcpy( pReadBuffer, pBuffer, cbBuffer );
pIsapiContext->SetAsyncIoBuffer( NULL );
return NO_ERROR;
}