2025-04-27 07:49:33 -04:00

724 lines
17 KiB
C++

/*==========================================================================
*
* 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<IDP8ServiceProvider**>( 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;
}
}