/*========================================================================== * * Copyright (C) 1998-2002 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" #define DPN_REG_LOCAL_MODEM_SERIAL_ROOT L"\\DPNSPModemSerial" #define DPN_REG_LOCAL_MODEM_MODEM_ROOT L"\\DPNSPModemModem" #undef DPF_SUBCOMP #define DPF_SUBCOMP DN_SUBCOMP_MODEM HRESULT ModemLoadAndAllocString( UINT uiResourceID, wchar_t **lpswzString ); #undef DPF_MODNAME #define DPF_MODNAME "DNModemInit" BOOL DNModemInit(HANDLE hModule) { DNASSERT( g_hModemDLLInstance == NULL ); g_hModemDLLInstance = (HINSTANCE) hModule; // // attempt to initialize process-global items // if ( ModemInitProcessGlobals() == FALSE ) { DPFX(DPFPREP, 0, "Failed to initialize globals!" ); return FALSE; } return TRUE; } #undef DPF_MODNAME #define DPF_MODNAME "DNModemDeInit" void DNModemDeInit() { DPFX(DPFPREP, 5, "Deinitializing Serial SP"); DNASSERT( g_hModemDLLInstance != NULL ); g_hModemDLLInstance = NULL; ModemDeinitProcessGlobals(); } #ifndef DPNBUILD_NOCOMREGISTER #undef DPF_MODNAME #define DPF_MODNAME "DNModemRegister" BOOL DNModemRegister(LPCWSTR wszDLLName) { HRESULT hr = S_OK; BOOL fReturn = TRUE; if( !CRegistry::Register( L"DirectPlay8SPModem.Modem.1", L"DirectPlay8 Modem Provider Object", wszDLLName, &CLSID_DP8SP_MODEM, L"DirectPlay8SPModem.Modem") ) { DPFERR( "Could not register dp8 Modem object" ); fReturn = FALSE; } if( !CRegistry::Register( L"DirectPlay8SPModem.Serial.1", L"DirectPlay8 Serial Provider Object", wszDLLName, &CLSID_DP8SP_SERIAL, L"DirectPlay8SPModem.Serial") ) { DPFERR( "Could not register dp8 Serial object" ); fReturn = FALSE; } CRegistry creg; WCHAR *wszFriendlyName = NULL; 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" ); fReturn = FALSE; } else { hr = ModemLoadAndAllocString( IDS_FRIENDLYNAME_MODEM, &wszFriendlyName ); if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Could not load Modem name hr=0x%x", hr ); fReturn = FALSE; } else { // 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" ); fReturn = FALSE; } else { hr = ModemLoadAndAllocString( IDS_FRIENDLYNAME_SERIAL, &wszFriendlyName ); if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Could not load Serial name hr=0x%x", hr ); fReturn = FALSE; } else { // 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 fReturn; } #undef DPF_MODNAME #define DPF_MODNAME "DNModemUnRegister" BOOL DNModemUnRegister() { HRESULT hr = S_OK; BOOL fReturn = TRUE; if( !CRegistry::UnRegister(&CLSID_DP8SP_MODEM) ) { DPFX(DPFPREP, 0, "Failed to unregister Modem object" ); fReturn = FALSE; } if( !CRegistry::UnRegister(&CLSID_DP8SP_SERIAL) ) { DPFX(DPFPREP, 0, "Failed to unregister Serial object" ); fReturn = FALSE; } 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 fReturn; } #endif // ! DPNBUILD_NOCOMREGISTER #ifndef DPNBUILD_LIBINTERFACE #undef DPF_MODNAME #define DPF_MODNAME "DNModemGetRemainingObjectCount" DWORD DNModemGetRemainingObjectCount() { return g_lModemOutstandingInterfaceCount; } #endif // ! DPNBUILD_LIBINTERFACE //********************************************************************** // Constant definitions //********************************************************************** //********************************************************************** // Macro definitions //********************************************************************** #ifdef __MWERKS__ #define EXP __declspec(dllexport) #else #define EXP #endif //********************************************************************** // Structure definitions //********************************************************************** //********************************************************************** // Variable definitions //********************************************************************** //********************************************************************** // Function prototypes //********************************************************************** static STDMETHODIMP DNMODEMSP_QueryInterface( IDP8ServiceProvider* lpDNSP, REFIID riid, LPVOID * ppvObj ); #define NOTSUPPORTED(parm) (HRESULT (__stdcall *) (struct IDP8ServiceProvider *, parm)) DNMODEMSP_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 = { DNMODEMSP_QueryInterface, DNMODEMSP_AddRef, DNMODEMSP_Release, DNMODEMSP_Initialize, DNMODEMSP_Close, DNMODEMSP_Connect, DNMODEMSP_Disconnect, DNMODEMSP_Listen, DNMODEMSP_SendData, DNMODEMSP_EnumQuery, DNMODEMSP_EnumRespond, DNMODEMSP_CancelCommand, NOTSUPPORTED(PSPENUMMULTICASTSCOPESDATA), // EnumMulticastScopes NOTSUPPORTED(PSPSHAREENDPOINTINFODATA), // ShareEndpointInfo NOTSUPPORTED(PSPGETENDPOINTBYADDRESSDATA), // GetEndpointByAddress NOTSUPPORTED(PSPUPDATEDATA), // Update DNMODEMSP_GetCaps, DNMODEMSP_SetCaps, DNMODEMSP_ReturnReceiveBuffers, DNMODEMSP_GetAddressInfo, DNMODEMSP_IsApplicationSupported, DNMODEMSP_EnumAdapters, NOTSUPPORTED(PSPPROXYENUMQUERYDATA) // ProxyEnumQuery }; static IDP8ServiceProviderVtbl g_ModemInterface = { DNMODEMSP_QueryInterface, DNMODEMSP_AddRef, DNMODEMSP_Release, DNMODEMSP_Initialize, DNMODEMSP_Close, DNMODEMSP_Connect, DNMODEMSP_Disconnect, DNMODEMSP_Listen, DNMODEMSP_SendData, DNMODEMSP_EnumQuery, DNMODEMSP_EnumRespond, DNMODEMSP_CancelCommand, NOTSUPPORTED(PSPENUMMULTICASTSCOPESDATA), // EnumMulticastScopes NOTSUPPORTED(PSPSHAREENDPOINTINFODATA), // ShareEndpointInfo NOTSUPPORTED(PSPGETENDPOINTBYADDRESSDATA), // GetEndpointByAddress NOTSUPPORTED(PSPUPDATEDATA), // Update DNMODEMSP_GetCaps, DNMODEMSP_SetCaps, DNMODEMSP_ReturnReceiveBuffers, DNMODEMSP_GetAddressInfo, DNMODEMSP_IsApplicationSupported, DNMODEMSP_EnumAdapters, NOTSUPPORTED(PSPPROXYENUMQUERYDATA) // ProxyEnumQuery }; //********************************************************************** // Function definitions //********************************************************************** //********************************************************************** // ------------------------------ // DNMODEMSP_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 "DNMODEMSP_QueryInterface" static STDMETHODIMP DNMODEMSP_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; DNMODEMSP_AddRef( lpDNSP ); } else { hr = E_NOINTERFACE; } return hr; } //********************************************************************** //********************************************************************** // ------------------------------ // CreateModemInterface - create a modem interface // // Entry: Pointer to pointer to SP interface // // Exit: Error code // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CreateModemInterface" #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL HRESULT CreateModemInterface( const XDP8CREATE_PARAMS * const pDP8CreateParams, IDP8ServiceProvider **const ppiDP8SP ) #else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL HRESULT CreateModemInterface( IDP8ServiceProvider **const ppiDP8SP ) #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL { HRESULT hr; CModemSPData *pSPData; DNASSERT( ppiDP8SP != NULL ); // // initialize // hr = DPN_OK; pSPData = NULL; *ppiDP8SP = NULL; // // create main data class // hr = CreateSPData( &pSPData, TYPE_MODEM, #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL pDP8CreateParams, #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL &g_ModemInterface ); if ( hr != DPN_OK ) { DNASSERT( pSPData == NULL ); DPFX(DPFPREP, 0, "Problem creating SPData!" ); DisplayDNError( 0, hr ); goto Failure; } DNASSERT( pSPData != NULL ); *ppiDP8SP = pSPData->COMInterface(); Exit: return hr; Failure: if ( pSPData != NULL ) { pSPData->DecRef(); pSPData = NULL; } goto Exit; } //********************************************************************** //********************************************************************** // ------------------------------ // CreateSerialInterface - create a serial interface // // Entry: Pointer to pointer to SP interface // // Exit: Error code // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CreateSerialInterface" #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL HRESULT CreateSerialInterface( const XDP8CREATE_PARAMS * const pDP8CreateParams, IDP8ServiceProvider **const ppiDP8SP ) #else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL HRESULT CreateSerialInterface( IDP8ServiceProvider **const ppiDP8SP ) #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL { HRESULT hr; CModemSPData *pSPData; DNASSERT( ppiDP8SP != NULL ); // // initialize // hr = DPN_OK; pSPData = NULL; *ppiDP8SP = NULL; // // create main data class // hr = CreateSPData( &pSPData, TYPE_SERIAL, #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL pDP8CreateParams, #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL &g_SerialInterface ); if ( hr != DPN_OK ) { DNASSERT( pSPData == NULL ); DPFX(DPFPREP, 0, "Problem creating SPData!" ); DisplayDNError( 0, hr ); goto Failure; } DNASSERT( pSPData != NULL ); *ppiDP8SP = pSPData->COMInterface(); Exit: return hr; Failure: if ( pSPData != NULL ) { pSPData->DecRef(); pSPData = NULL; } goto Exit; } //********************************************************************** #ifndef DPNBUILD_LIBINTERFACE //********************************************************************** // ------------------------------ // ModemDoCreateInstance - 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 ModemDoCreateInstance( LPCLASSFACTORY This, LPUNKNOWN pUnkOuter, REFCLSID rclsid, REFIID riid, LPVOID *ppvObj ) { HRESULT hr; DNASSERT( ppvObj != NULL ); // // initialize // *ppvObj = NULL; // // we can either create an IPX instance or an IP instance // if (IsEqualCLSID(rclsid, CLSID_DP8SP_MODEM)) { hr = CreateModemInterface( reinterpret_cast( ppvObj ) ); } else if (IsEqualCLSID(rclsid, CLSID_DP8SP_SERIAL)) { hr = CreateSerialInterface( reinterpret_cast( ppvObj ) ); } else { // this shouldn't happen if they called IClassFactory::CreateObject correctly DPFX(DPFPREP, 0, "Got unexpected CLSID!"); hr = E_UNEXPECTED; } return hr; } //********************************************************************** #endif // ! DPNBUILD_LIBINTERFACE //********************************************************************** // ------------------------------ // 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 ); } //********************************************************************** #define MAX_RESOURCE_STRING_LENGTH _MAX_PATH #undef DPF_MODNAME #define DPF_MODNAME "ModemLoadAndAllocString" HRESULT ModemLoadAndAllocString( UINT uiResourceID, wchar_t **lpswzString ) { int length; HRESULT hr; TCHAR szTmpBuffer[MAX_RESOURCE_STRING_LENGTH]; length = LoadString( g_hModemDLLInstance, 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 DPNERR_GENERIC; } else { *lpswzString = new wchar_t[length+1]; if( *lpswzString == NULL ) { DPFX(DPFPREP, 0, "Alloc failure" ); return DPNERR_OUTOFMEMORY; } #ifdef UNICODE wcscpy( *lpswzString, szTmpBuffer ); #else // !UNICODE if( STR_jkAnsiToWide( *lpswzString, szTmpBuffer, length+1 ) != DPN_OK ) { hr = GetLastError(); delete[] *lpswzString; *lpswzString = NULL; DPFX(DPFPREP, 0, "Unable to upconvert from ansi to unicode hr=0x%x", hr ); return DPNERR_GENERIC; } #endif // !UNICODE return DPN_OK; } }