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

619 lines
15 KiB
C++

/*==========================================================================
*
* Copyright (C) 1998-2000 Microsoft Corporation. All Rights Reserved.
*
* File: Unk.cpp
* Content: IUnknown implementation
* History:
* Date By Reason
* ==== == ======
* 11/25/98 jtk Copied from winsock provider
* 11/30/98 jtk Initial checkin into SLM
* 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
***************************************************************************/
#include "dnmdmi.h"
//**********************************************************************
// Constant definitions
//**********************************************************************
//**********************************************************************
// Macro definitions
//**********************************************************************
#ifdef __MWERKS__
#define EXP __declspec(dllexport)
#else
#define EXP
#endif
#define DPN_REG_LOCAL_MODEM_SERIAL_ROOT L"\\DPNSPModemSerial"
#define DPN_REG_LOCAL_MODEM_MODEM_ROOT L"\\DPNSPModemModem"
//**********************************************************************
// 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 pointers
//**********************************************************************
// these are the vtables for serial and modem. One or the other is used depending on
// what is passed to DoCreateInstance
static IDP8ServiceProviderVtbl g_SerialInterface =
{
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,
NOTSUPPORTED(PSPPROXYENUMQUERYDATA) // ProxyEnumQuery
};
static IDP8ServiceProviderVtbl g_ModemInterface =
{
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,
NOTSUPPORTED(PSPPROXYENUMQUERYDATA) // ProxyEnumQuery
};
//**********************************************************************
// Function definitions
//**********************************************************************
//**********************************************************************
// ------------------------------
// DNSP_QueryInterface - query for a particular interface
//
// Entry: Pointer to current interface
// Desired interface ID
// 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;
// assume no interface
*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;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// DoCreateInstance - create in instance of an interface
//
// Entry: Pointer to class factory
// Pointer to Unkown interface
// Class reference
// Desired interface ID
// 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;
CSPData *pSPData;
//
// intialize
//
hr = DPN_OK;
pSPData = NULL;
// we can either create an modem instance or a serial instance
if ( IsEqualCLSID( rclsid, CLSID_DP8SP_MODEM ) )
{
//
// finish interface intialization
//
hr = CreateSPData( &pSPData, &CLSID_DP8SP_MODEM, TYPE_MODEM, &g_ModemInterface );
if ( hr != DPN_OK )
{
DNASSERT( pSPData == NULL );
DPFX(DPFPREP, 0, "Problem creating modem interface!" );
DisplayDNError( 0, hr );
goto Failure;
}
}
else
{
// is it a serial GUID?
if ( IsEqualCLSID( rclsid, CLSID_DP8SP_SERIAL ) )
{
//
// finish interface intialization
//
hr = CreateSPData( &pSPData, &CLSID_DP8SP_SERIAL, TYPE_SERIAL, &g_SerialInterface );
if ( hr != DPN_OK )
{
DNASSERT( pSPData == NULL );
DPFX(DPFPREP, 0, "Problem creating serial interface!" );
DisplayDNError( 0, hr );
goto Failure;
}
}
else
{
DPFX(DPFPREP, 0, "Invalid interface requested!" );
// this shouldn't happen if they called IClassFactory::CreateObject correctly
hr = E_UNEXPECTED;
DNASSERT( FALSE );
goto Failure;
}
}
if (hr == S_OK)
{
// get the right interface and bump the refcount
DNASSERT( pSPData != NULL );
*ppvObj = pSPData->COMInterface();
hr = DNSP_QueryInterface( static_cast<IDP8ServiceProvider*>( *ppvObj ), riid, ppvObj);
DNASSERT( hr == S_OK );
}
if ( pSPData != NULL )
{
pSPData->DecRef();
pSPData = NULL;
}
Exit:
if ( hr != DPN_OK )
{
DPFX(DPFPREP, 0, "Problem with DoCreateInstance!" );
DisplayDNError( 0, hr );
}
return hr;
Failure:
goto Exit;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// IsClassImplemented - tells asked if this DLL implements a given class.
// DLLs may implement multiple classes and multiple interfaces on those classes
//
// Entry: Class reference
//
// Exit: Boolean indicating whether the class is implemented
// TRUE = class implemented
// FALSE = class not implemented
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "IsClassImplemented"
BOOL IsClassImplemented( REFCLSID rclsid )
{
return IsSerialGUID( &rclsid );
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// DllMain - main entry point for .DLL
//
// Entry: Pointer to the service provider to initialize
//
// Exit: Error Code
// ------------------------------
#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_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:
{
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_MODEM_MODEM_ROOT, FALSE, TRUE ) )
{
DPFERR( "Cannot create Modem sub-area" );
return DPNERR_GENERIC;
}
hr = LoadAndAllocString( IDS_FRIENDLYNAME_MODEM, &wszFriendlyName );
if( FAILED( hr ) )
{
DPFX(DPFPREP, 0, "Could not load Modem 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_MODEM );
creg.Close();
if( !creg.Open( HKEY_LOCAL_MACHINE, DPN_REG_LOCAL_SP_SUBKEY DPN_REG_LOCAL_MODEM_SERIAL_ROOT, FALSE, TRUE ) )
{
DPFERR( "Cannot create Serial sub-aread" );
return DPNERR_GENERIC;
}
hr = LoadAndAllocString( IDS_FRIENDLYNAME_SERIAL, &wszFriendlyName );
if( FAILED( hr ) )
{
DPFX(DPFPREP, 0, "Could not load Serial 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_SERIAL );
creg.Close();
return DPN_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "UnRegisterDefaultSettings"
//
// UnRegisterDefaultSettings
//
// This function registers the default settings for this module.
//
// For DPVOICE.DLL this is making sure the compression provider sub-key is created.
//
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_MODEM_MODEM_ROOT)[1] ) )
{
DPFERR( "Cannot remove Modem sub-key, could have elements" );
}
if( !creg.DeleteSubKey( &(DPN_REG_LOCAL_MODEM_SERIAL_ROOT)[1] ) )
{
DPFERR( "Cannot remove Serial 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"DirectPlay8SPModem.Modem.1", L"DirectPlay8 Modem Provider Object",
L"dpnmodem.dll", CLSID_DP8SP_MODEM, L"DirectPlay8SPModem.Modem") )
{
DPFERR( "Could not register dp8 Modem object" );
fFailed = TRUE;
}
if( !CRegistry::Register( L"DirectPlay8SPModem.Serial.1", L"DirectPlay8 Serial Provider Object",
L"dpnmodem.dll", CLSID_DP8SP_SERIAL, L"DirectPlay8SPModem.Serial") )
{
DPFERR( "Could not register dp8 Serial 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_MODEM) )
{
DPFX(DPFPREP, 0, "Failed to unregister Modem object" );
fFailed = TRUE;
}
if( !CRegistry::UnRegister(CLSID_DP8SP_SERIAL) )
{
DPFX(DPFPREP, 0, "Failed to unregister Serial 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;
}
}