/*========================================================================== * * Copyright (C) 1998-2000 Microsoft Corporation. All Rights Reserved. * * File: Unk.cpp * Content: IUnknown implementation * History: * Date By Reason * ==== == ====== * 08/06/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles. ***************************************************************************/ #include "dnwsocki.h" #undef DPF_SUBCOMP #define DPF_SUBCOMP DN_SUBCOMP_WSOCK //********************************************************************** // Constant definitions //********************************************************************** #ifdef __MWERKS__ #define EXP __declspec(dllexport) #else #define EXP #endif #define DPN_REG_LOCAL_WSOCK_IPX_ROOT L"\\DPNSPWinsockIPX" #define DPN_REG_LOCAL_WSOCK_TCPIP_ROOT L"\\DPNSPWinsockTCP" //********************************************************************** // Macro definitions //********************************************************************** //********************************************************************** // Structure definitions //********************************************************************** //********************************************************************** // Variable definitions //********************************************************************** //********************************************************************** // Function prototypes //********************************************************************** static STDMETHODIMP DNSP_QueryInterface( IDP8ServiceProvider *lpDNSP, REFIID riid, LPVOID * ppvObj); #define NOTSUPPORTED(parm) (HRESULT (__stdcall *) (struct IDP8ServiceProvider *, parm)) DNSP_NotSupported //********************************************************************** // Function definitions //********************************************************************** // these are the vtables for IPX and IP. One or the other is used depending on // what is passed to DoCreateInstance. The interfaces are presently the same, // but are different structures to facilitate potential future changes. static IDP8ServiceProviderVtbl ipxInterface = { DNSP_QueryInterface, DNSP_AddRef, DNSP_Release, DNSP_Initialize, DNSP_Close, DNSP_Connect, DNSP_Disconnect, DNSP_Listen, DNSP_SendData, DNSP_EnumQuery, DNSP_EnumRespond, DNSP_CancelCommand, NOTSUPPORTED(PSPCREATEGROUPDATA), // CreateGroup NOTSUPPORTED(PSPDELETEGROUPDATA), // DeleteGroup NOTSUPPORTED(PSPADDTOGROUPDATA), // AddToGroup NOTSUPPORTED(PSPREMOVEFROMGROUPDATA), // RemoveFromGroup DNSP_GetCaps, DNSP_SetCaps, DNSP_ReturnReceiveBuffers, DNSP_GetAddressInfo, DNSP_IsApplicationSupported, DNSP_EnumAdapters, DNSP_ProxyEnumQuery }; static IDP8ServiceProviderVtbl ipInterface = { DNSP_QueryInterface, DNSP_AddRef, DNSP_Release, DNSP_Initialize, DNSP_Close, DNSP_Connect, DNSP_Disconnect, DNSP_Listen, DNSP_SendData, DNSP_EnumQuery, DNSP_EnumRespond, DNSP_CancelCommand, NOTSUPPORTED(PSPCREATEGROUPDATA), // CreateGroup NOTSUPPORTED(PSPDELETEGROUPDATA), // DeleteGroup NOTSUPPORTED(PSPADDTOGROUPDATA), // AddToGroup NOTSUPPORTED(PSPREMOVEFROMGROUPDATA), // RemoveFromGroup DNSP_GetCaps, DNSP_SetCaps, DNSP_ReturnReceiveBuffers, DNSP_GetAddressInfo, DNSP_IsApplicationSupported, DNSP_EnumAdapters, DNSP_ProxyEnumQuery }; //********************************************************************** // ------------------------------ // DNSP_QueryInterface - query for interface // // Entry: Pointer to current interface // GUID of desired interface // Pointer to pointer to new interface // // Exit: Error code // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "DNSP_QueryInterface" static STDMETHODIMP DNSP_QueryInterface( IDP8ServiceProvider *lpDNSP, REFIID riid, LPVOID * ppvObj) { HRESULT hr = S_OK; *ppvObj=NULL; // hmmm, switch would be cleaner... if( IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDP8ServiceProvider) ) { *ppvObj = lpDNSP; DNSP_AddRef(lpDNSP); } else { hr = E_NOINTERFACE; } return hr; } //********************************************************************** //********************************************************************** // ------------------------------ // CreateIPXInterface - create an IPX interface // // Entry: Pointer to pointer to SP interface // Pointer to pointer to associated SP data // // Exit: Error code // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CreateIPXInterface" static HRESULT CreateIPXInterface( IDP8ServiceProvider **const ppiDNSP, CSPData **const ppSPData ) { HRESULT hr; CSPData *pSPData; DNASSERT( ppiDNSP != NULL ); DNASSERT( ppSPData != NULL ); // // initialize // hr = DPN_OK; pSPData = NULL; *ppiDNSP = NULL; *ppSPData = NULL; // // create main data class // hr = CreateSPData( &pSPData, &CLSID_DP8SP_IPX, TYPE_IPX, &ipxInterface ); if ( hr != DPN_OK ) { DNASSERT( pSPData == NULL ); DPFX(DPFPREP, 0, "Problem creating SPData!" ); DisplayDNError( 0, hr ); goto Failure; } DNASSERT( pSPData != NULL ); *ppiDNSP = pSPData->COMInterface(); *ppSPData = pSPData; Exit: return hr; Failure: if ( pSPData != NULL ) { pSPData->DecRef(); pSPData = NULL; } goto Exit; } //********************************************************************** //********************************************************************** // ------------------------------ // CreateIPInterface - create an IP interface // // Entry: Pointer to pointer to SP interface // Pointer to associated SP data // // Exit: Error code // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CreateIPInterface" static HRESULT CreateIPInterface( IDP8ServiceProvider **const ppiDNSP, CSPData **const ppSPData ) { HRESULT hr; CSPData *pSPData; DNASSERT( ppiDNSP != NULL ); DNASSERT( ppSPData != NULL ); // // initialize // hr = DPN_OK; pSPData = NULL; *ppiDNSP = NULL; *ppSPData = NULL; // // create main data class // hr = CreateSPData( &pSPData, &CLSID_DP8SP_TCPIP, TYPE_IP, &ipInterface ); if ( hr != DPN_OK ) { DNASSERT( pSPData == NULL ); DPFX(DPFPREP, 0, "Problem creating SPData!" ); DisplayDNError( 0, hr ); goto Failure; } DNASSERT( pSPData != NULL ); *ppiDNSP = pSPData->COMInterface(); *ppSPData = pSPData; Exit: return hr; Failure: if ( pSPData != NULL ) { pSPData->DecRef(); pSPData = NULL; } goto Exit; } //********************************************************************** //********************************************************************** // ------------------------------ // DoCreateInstance - create an instance of an interface // // Entry: Pointer to class factory // Pointer to unknown interface // Refernce of GUID of desired interface // Reference to another GUID? // Pointer to pointer to interface // // Exit: Error code // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "DoCreateInstance" HRESULT DoCreateInstance( LPCLASSFACTORY This, LPUNKNOWN pUnkOuter, REFCLSID rclsid, REFIID riid, LPVOID *ppvObj ) { HRESULT hr; IDP8ServiceProvider **ppIDNSP; CSPData *pSPData; DNASSERT( ppvObj != NULL ); // // initialize // *ppvObj = NULL; ppIDNSP = NULL; pSPData = NULL; // // we can either create an IPX instance or an IP instance // DBG_CASSERT( sizeof( ppvObj ) == sizeof( ppIDNSP ) ); ppIDNSP = reinterpret_cast( ppvObj ); if (IsEqualCLSID(rclsid, CLSID_DP8SP_TCPIP)) { hr = CreateIPInterface( ppIDNSP, &pSPData ); } else if (IsEqualCLSID(rclsid, CLSID_DP8SP_IPX)) { hr = CreateIPXInterface( ppIDNSP, &pSPData ); } else { // this shouldn't happen if they called IClassFactory::CreateObject correctly hr = E_UNEXPECTED; DNASSERT( FALSE ); } if (hr == S_OK) { // get the right interface and bump the refcount hr = IDP8ServiceProvider_QueryInterface( *ppIDNSP, riid, ppvObj ); } // // release any outstanding reference on the SP data // if ( pSPData != NULL ) { pSPData->DecRef(); pSPData = NULL; } return hr; } //********************************************************************** //********************************************************************** // ------------------------------ // IsClassImplemented - determine if a class is implemented in this .DLL // // Entry: Reference to class GUID // // Exit: Boolean indicating whether this .DLL implements the class // TRUE = this .DLL implements the class // FALSE = this .DLL doesn't implement the class // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "IsClassImplemented" BOOL IsClassImplemented(REFCLSID rclsid) { return ( IsEqualCLSID( rclsid, CLSID_DP8SP_TCPIP ) || IsEqualCLSID( rclsid, CLSID_DP8SP_IPX ) ); } //********************************************************************** //********************************************************************** // ------------------------------ // DllMain - main .DLL function // // Entry: DLL instance handle // Reason why this function is being called // Pointer to something // // Exit: Boolean return // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "DllMain" EXP BOOL WINAPI DllMain( HINSTANCE hDllInst, DWORD fdwReason, LPVOID lpvReserved ) { BOOL bResult = TRUE; switch( fdwReason ) { case DLL_PROCESS_ATTACH: { DPFX(DPFPREP, 2, "====> ENTER: DLLMAIN(%p): Process Attach: %08lx, tid=%08lx", DllMain, GetCurrentProcessId(), GetCurrentThreadId() ); DNASSERT( g_hDLLInstance == NULL ); g_hDLLInstance = hDllInst; // // attempt to initialize the OS abstraction layer // if ( DNOSIndirectionInit() != FALSE ) { #ifdef UNICODE // Make sure no one is trying to run the UNICODE version on Win9x DNASSERT(IsUnicodePlatform); #endif if (SUCCEEDED(COM_Init())) { // // attempt to initialize process-global items // if ( InitProcessGlobals() == FALSE ) { COM_Free(); DNOSIndirectionDeinit(); DPFX(DPFPREP, 0, "Failed to initialize globals!" ); bResult = FALSE; } } else { DPFX(DPFPREP, 0, "Failed to initialize COM indirection layer!" ); bResult = FALSE; DNOSIndirectionDeinit(); } } else { DPFX(DPFPREP, 0, "Failed to initialize OS indirection layer!" ); bResult = FALSE; } break; } case DLL_THREAD_ATTACH: { // // Nothing to do. // break; } case DLL_THREAD_DETACH: { #ifdef USE_THREADLOCALPOOLS // // Clear thread local storage for this thread, if any. // RELEASE_CURRENTTHREAD_LOCALPTRS(WSockThreadLocalPools, CleanupThreadLocalPools); #endif // USE_THREADLOCALPOOLS break; } case DLL_PROCESS_DETACH: { DPFX(DPFPREP, 2, "====> EXIT: DLLMAIN(%p): Process Detach %08lx, tid=%08lx", DllMain, GetCurrentProcessId(), GetCurrentThreadId() ); DNASSERT( g_hDLLInstance != NULL ); g_hDLLInstance = NULL; DeinitProcessGlobals(); COM_Free(); DNOSIndirectionDeinit(); break; } default: { DNASSERT( FALSE ); break; } } return bResult; } //********************************************************************** #define MAX_RESOURCE_STRING_LENGTH _MAX_PATH #undef DPF_MODNAME #define DPF_MODNAME "LoadAndAllocString" HRESULT LoadAndAllocString( UINT uiResourceID, wchar_t **lpswzString ) { int length; HRESULT hr; #ifdef WINNT wchar_t wszTmpBuffer[MAX_RESOURCE_STRING_LENGTH]; length = LoadStringW( g_hDLLInstance, uiResourceID, wszTmpBuffer, MAX_RESOURCE_STRING_LENGTH ); if( length == 0 ) { hr = GetLastError(); DPFX(DPFPREP, 0, "Unable to load resource ID %d error 0x%x", uiResourceID, hr ); *lpswzString = NULL; return hr; } else { *lpswzString = new wchar_t[length+1]; if( *lpswzString == NULL ) { DPFX(DPFPREP, 0, "Alloc failure" ); return DPNERR_OUTOFMEMORY; } wcscpy( *lpswzString, wszTmpBuffer ); return DPN_OK; } #else // WIN95 char szTmpBuffer[MAX_RESOURCE_STRING_LENGTH]; length = LoadStringA( g_hDLLInstance, uiResourceID, szTmpBuffer, MAX_RESOURCE_STRING_LENGTH ); if( length == 0 ) { hr = GetLastError(); DPFX(DPFPREP, 0, "Unable to load resource ID %d error 0x%x", uiResourceID, hr ); *lpswzString = NULL; return hr; } else { *lpswzString = new wchar_t[length+1]; if( *lpswzString == NULL ) { DPFX(DPFPREP, 0, "Alloc failure" ); return DPNERR_OUTOFMEMORY; } if( STR_jkAnsiToWide( *lpswzString, szTmpBuffer, length+1 ) == DPN_OK ) { hr = GetLastError(); DPFX(DPFPREP, 0, "Unable to upconvert from ansi to unicode hr=0x%x", hr ); return hr; } return DPN_OK; } #endif } #undef DPF_MODNAME #define DPF_MODNAME "RegisterDefaultSettings" // // RegisterDefaultSettings // // This function registers the default settings for this module. // // For DPVOICE.DLL this is making sure the compression provider sub-key is created. // HRESULT RegisterDefaultSettings() { CRegistry creg; WCHAR *wszFriendlyName = NULL; HRESULT hr; if( !creg.Open( HKEY_LOCAL_MACHINE, DPN_REG_LOCAL_SP_SUBKEY DPN_REG_LOCAL_WSOCK_IPX_ROOT, FALSE, TRUE ) ) { DPFERR( "Cannot create IPX sub-area!" ); return DPNERR_GENERIC; } hr = LoadAndAllocString( IDS_FRIENDLYNAME_IPX, &wszFriendlyName ); if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Could not load IPX name! hr=0x%x", hr ); return hr; } // Load from resource file creg.WriteString( DPN_REG_KEYNAME_FRIENDLY_NAME, wszFriendlyName ); delete [] wszFriendlyName; creg.WriteGUID( DPN_REG_KEYNAME_GUID, CLSID_DP8SP_IPX ); creg.Close(); if( !creg.Open( HKEY_LOCAL_MACHINE, DPN_REG_LOCAL_SP_SUBKEY DPN_REG_LOCAL_WSOCK_TCPIP_ROOT, FALSE, TRUE ) ) { DPFERR( "Cannot create TCPIP sub-area!" ); return DPNERR_GENERIC; } hr = LoadAndAllocString( IDS_FRIENDLYNAME_TCPIP, &wszFriendlyName ); if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Could not load IPX name! hr=0x%x", hr ); return hr; } // Load from resource file creg.WriteString( DPN_REG_KEYNAME_FRIENDLY_NAME, wszFriendlyName ); delete [] wszFriendlyName; creg.WriteGUID( DPN_REG_KEYNAME_GUID, CLSID_DP8SP_TCPIP ); creg.Close(); return DPN_OK; } #undef DPF_MODNAME #define DPF_MODNAME "UnRegisterDefaultSettings" // // UnRegisterDefaultSettings // // This function registers the default settings for this module. // HRESULT UnRegisterDefaultSettings() { CRegistry creg; if( !creg.Open( HKEY_LOCAL_MACHINE, DPN_REG_LOCAL_SP_SUBKEY, FALSE, TRUE ) ) { DPFERR( "Cannot remove app, does not exist" ); } else { if( !creg.DeleteSubKey( &(DPN_REG_LOCAL_WSOCK_IPX_ROOT)[1] ) ) { DPFERR( "Cannot remove IPX sub-key, could have elements" ); } if( !creg.DeleteSubKey( &(DPN_REG_LOCAL_WSOCK_TCPIP_ROOT)[1] ) ) { DPFERR( "Cannot remove TCPIP sub-key, could have elements" ); } } return DPN_OK; } #undef DPF_MODNAME #define DPF_MODNAME "DllRegisterServer" HRESULT WINAPI DllRegisterServer() { HRESULT hr = S_OK; BOOL fFailed = FALSE; if( !CRegistry::Register( L"DirectPlay8SPWSock.IPX.1", L"DirectPlay8 WSock IPX Provider Object", L"dpnwsock.dll", CLSID_DP8SP_IPX, L"DirectPlay8SPWSock.IPX") ) { DPFERR( "Could not register dp8 IPX object" ); fFailed = TRUE; } if( !CRegistry::Register( L"DirectPlay8SPWSock.TCPIP.1", L"DirectPlay8 WSock TCPIP Provider Object", L"dpnwsock.dll", CLSID_DP8SP_TCPIP, L"DirectPlay8SPWSock.TCPIP") ) { DPFERR( "Could not register dp8 IP object" ); fFailed = TRUE; } if( FAILED( hr = RegisterDefaultSettings() ) ) { DPFX(DPFPREP, 0, "Could not register default settings hr = 0x%x", hr ); fFailed = TRUE; } if( fFailed ) { return E_FAIL; } else { return S_OK; } } #undef DPF_MODNAME #define DPF_MODNAME "DllUnregisterServer" STDAPI DllUnregisterServer() { HRESULT hr = S_OK; BOOL fFailed = FALSE; if( !CRegistry::UnRegister(CLSID_DP8SP_IPX) ) { DPFX(DPFPREP, 0, "Failed to unregister IPX object" ); fFailed = TRUE; } if( !CRegistry::UnRegister(CLSID_DP8SP_TCPIP) ) { DPFX(DPFPREP, 0, "Failed to unregister IP object" ); fFailed = TRUE; } if( FAILED( hr = UnRegisterDefaultSettings() ) ) { DPFX(DPFPREP, 0, "Failed to remove default settings hr=0x%x", hr ); } if( fFailed ) { return E_FAIL; } else { return S_OK; } }