You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
694 lines
16 KiB
694 lines
16 KiB
/*++
|
|
|
|
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;
|
|
|
|
//
|
|
// First, set the process ID for the process hosting this object
|
|
//
|
|
|
|
*pdwProcessId = GetCurrentProcessId();
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
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;
|
|
DWORD cbReadBuffer;
|
|
|
|
pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( IsapiContext );
|
|
|
|
DBG_ASSERT( pIsapiContext );
|
|
DBG_ASSERT( pIsapiContext->QueryIoState() == AsyncReadPending );
|
|
|
|
pReadBuffer = pIsapiContext->QueryAsyncIoBuffer();
|
|
cbReadBuffer = pIsapiContext->QueryLastAsyncIo();
|
|
|
|
DBG_ASSERT( pReadBuffer != NULL );
|
|
DBG_ASSERT( cbBuffer <= cbReadBuffer );
|
|
|
|
//
|
|
// Ensure that we don't overrun the ISAPI_CONTEXT buffer
|
|
//
|
|
|
|
if ( cbBuffer > cbReadBuffer )
|
|
{
|
|
cbBuffer = cbReadBuffer;
|
|
}
|
|
|
|
memcpy( pReadBuffer, pBuffer, cbBuffer );
|
|
|
|
pIsapiContext->SetAsyncIoBuffer( NULL );
|
|
pIsapiContext->SetLastAsyncIo( 0 );
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
HRESULT
|
|
WAM::CallerHasAccess()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the COM call context and examine the calling thread to determine
|
|
if the caller has sufficient access to make this call.
|
|
|
|
Currently the check is just made that the caller is local system.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) - If caller is denied.
|
|
FAILED() if failed for some other reason.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
IServerSecurity * pServerSecurity = NULL;
|
|
BOOL fImpersonated = FALSE;
|
|
HANDLE hToken = NULL;
|
|
STACK_BUFFER( TokenUserBuffer, 80 );
|
|
DWORD dwRequiredSize;
|
|
TOKEN_USER * pTokenUser;
|
|
|
|
hr = CoGetCallContext( IID_IServerSecurity, (VOID **)&pServerSecurity );
|
|
if( FAILED(hr) )
|
|
{
|
|
DBGERROR(( DBG_CONTEXT,
|
|
"Failed to get IServerSecurity. %0x\n",
|
|
hr ));
|
|
goto exit;
|
|
}
|
|
|
|
hr = pServerSecurity->ImpersonateClient();
|
|
if( FAILED(hr) )
|
|
{
|
|
DBGERROR(( DBG_CONTEXT,
|
|
"Failed to ImpersonateClient. %0x\n",
|
|
hr ));
|
|
goto exit;
|
|
}
|
|
fImpersonated = TRUE;
|
|
|
|
if( !OpenThreadToken( GetCurrentThread(),
|
|
TOKEN_QUERY,
|
|
TRUE,
|
|
&hToken ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
|
|
DBGERROR(( DBG_CONTEXT,
|
|
"Failed to OpenThreadToken gle=%d\n",
|
|
GetLastError() ));
|
|
goto exit;
|
|
}
|
|
|
|
if( !GetTokenInformation( hToken,
|
|
TokenUser,
|
|
TokenUserBuffer.QueryPtr(),
|
|
TokenUserBuffer.QuerySize(),
|
|
&dwRequiredSize ) )
|
|
{
|
|
if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
|
|
DBGERROR(( DBG_CONTEXT,
|
|
"Failed to GetTokenInformation gle=%d\n",
|
|
GetLastError() ));
|
|
goto exit;
|
|
}
|
|
|
|
if( !TokenUserBuffer.Resize( dwRequiredSize ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
|
|
goto exit;
|
|
}
|
|
|
|
if( !GetTokenInformation( hToken,
|
|
TokenUser,
|
|
TokenUserBuffer.QueryPtr(),
|
|
TokenUserBuffer.QuerySize(),
|
|
&dwRequiredSize ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
|
|
DBGERROR(( DBG_CONTEXT,
|
|
"Failed to GetTokenInformation gle=%d\n",
|
|
GetLastError() ));
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
pTokenUser = (TOKEN_USER *)TokenUserBuffer.QueryPtr();
|
|
|
|
if( !IsWellKnownSid( pTokenUser->User.Sid,
|
|
WinLocalSystemSid ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
|
|
DBGERROR(( DBG_CONTEXT,
|
|
"Unknown user attempting to access\n" ));
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
if( hToken )
|
|
{
|
|
CloseHandle( hToken );
|
|
}
|
|
|
|
if( fImpersonated )
|
|
{
|
|
DBG_ASSERT( pServerSecurity );
|
|
pServerSecurity->RevertToSelf();
|
|
}
|
|
|
|
if( pServerSecurity )
|
|
{
|
|
pServerSecurity->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|