/*++ 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 #include #include "wamobj.hxx" #include "IWam_i.c" #include "wamccf.hxx" #include // BEGIN mods #ifdef _ATL_STATIC_REGISTRY #include #include #endif #include // 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( 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; }