双接口组件的简单实现

来源:互联网 发布:淘宝客分佣cms系统 编辑:程序博客网 时间:2024/06/06 09:07

 

// Math.h 

//
// Math.h 
//

// access to the global variables
extern DWORD g_dwObjs;
extern DWORD g_dwLocks;


const int DISPID_ADD = 1;
const int DISPID_SUBTRACT = 2;
const int DISPID_MULTIPLY = 3;
const int DISPID_DIVIDE = 4;

class Math : public IMath               // 而对于IDispatch接口 class Math : public IDispatch
{
protected:
   
// Reference count
   DWORD          m_dwRef;

public:
   Math();
   
~Math();

public:
   
// IUnknown
   STDMETHOD(QueryInterface( REFIID, void** ));
   STDMETHOD_(ULONG, AddRef());
   STDMETHOD_(ULONG, Release());

   
// IDispatch
   STDMETHOD(GetTypeInfoCount( UINT* pctinfo ));
   STDMETHOD(GetTypeInfo( UINT itinfo,
                            LCID lcid,
                            ITypeInfo
** pptinfo ));
   STDMETHOD(GetIDsOfNames( REFIID riid,
                            OLECHAR
** rgszNames,
                            UINT cNames,
                            LCID lcid,
                            DISPID
* rgdispid ));
   STDMETHOD(Invoke( DISPID dispid,
                        REFIID riid,
                        LCID lcid,
                        WORD wFlags,
                        DISPPARAMS FAR
* pDispParams,
                        VARIANT FAR
* pvarResult,
                        EXCEPINFO FAR
* pExcepInfo,
                        unsigned 
int FAR* puArgErr ));

   
// IMath                            // 对于IDispatch接口,这里没有IMath定义
   STDMETHOD(Add( longlonglong* ));
   STDMETHOD(Subtract( 
longlonglong* ));
   STDMETHOD(Multiply( 
longlonglong* ));
   STDMETHOD(Divide( 
longlonglong* ));

};

class MathClassFactory : public IClassFactory
{
protected:
   DWORD           m_dwRef;

public:
   MathClassFactory();
   
~MathClassFactory();

   
// IUnknown
   STDMETHOD( QueryInterface(REFIID, void** ));
   STDMETHOD_(ULONG, AddRef());
   STDMETHOD_(ULONG, Release());

   
// IClassFactory
   STDMETHOD( CreateInstance(LPUNKNOWN, REFIID, void**));
   STDMETHOD( LockServer(BOOL));
};

// Math.cpp

//
// Math.cpp
//
//

#include 
<windows.h>

#include 
"DualServer.h"
#include 
"math.h"


//
// Math class implementation
//
// Constructors
Math::Math()
{
   m_dwRef 
= 0;
}

Math::
~Math()
{
    g_dwObjs
--;
}

// IUnknown implementation


STDMETHODIMP Math::QueryInterface( REFIID riid, 
void** ppv )
{  
   
*ppv = NULL;

   
if ( riid == IID_IUnknown  || 
        riid 
== IID_IDispatch ||
        riid 
== IID_IMath ) 
      
*ppv = this;

   
if ( *ppv )
   {
      ( (IUnknown
*)*ppv)->AddRef();
      
return( S_OK );
   }
   
return E_NOINTERFACE;
}

STDMETHODIMP_(ULONG) Math::AddRef()
{
   
return ++m_dwRef;
}

STDMETHODIMP_(ULONG) Math::Release()
{
   
if ( --m_dwRef )
      
return m_dwRef;

   delete 
this;
   
return 0;
}

// IDispatch implementation

STDMETHODIMP Math::GetTypeInfoCount( UINT* pctinfo )
{
   
*pctinfo = 0;
   
return S_OK;
}

STDMETHODIMP Math::GetTypeInfo( UINT itinfo,
                                LCID lcid,
                                ITypeInfo
** pptinfo )
{
   
// Not implemented
   if ( pptinfo )
      
*pptinfo = 0;
   
return( E_NOTIMPL );
}

STDMETHODIMP Math::GetIDsOfNames( REFIID riid,
                                  OLECHAR
** rgszNames,
                                  UINT cNames,
                                  LCID lcid,
                                  DISPID
* rgdispid )
{
   
// To make things simple, we only support 1 name at a time
   if ( cNames > 1 )
      
return( E_INVALIDARG );

   
// Convert the member name to ANSI
   CHAR  szAnsi[128];
   
long lLen = WideCharToMultiByte( CP_ACP,
                        
0,
                        rgszNames[
0],
                        wcslen( rgszNames[
0] ),
                        szAnsi,
                        
sizeof( szAnsi ),
                        
0,
                        
0 );
   szAnsi[lLen] 
= '/0';

   
// Compare the member name to see if it's one that we have
   
// and return the correct DISPID
   if ( strncmp( "Add", szAnsi, 3 ) == 0 )
      rgdispid[
0= DISPID_ADD;
   
else if ( strncmp( "Subtract", szAnsi, 8 ) == 0 )
      rgdispid[
0= DISPID_SUBTRACT;
   
else if ( strncmp( "Multiply", szAnsi, 8 ) == 0 )
      rgdispid[
0= DISPID_MULTIPLY;
   
else if ( strncmp( "Divide", szAnsi, 6 ) == 0 )
      rgdispid[
0= DISPID_DIVIDE;
   
else
      
return( DISPID_UNKNOWN );

   
return S_OK;
}

STDMETHODIMP Math::Invoke( DISPID dispid,
                           REFIID riid,
                           LCID lcid,
                           WORD wFlags,
                           DISPPARAMS FAR
* pDispParams,
                           VARIANT FAR
* pvarResult,
                           EXCEPINFO FAR
* pExcepInfo,
                           unsigned 
int FAR* puArgErr )
{
   
// All of our methods take two parameters
   if ( !pDispParams ||
         pDispParams
->cArgs != 2 )
      
return( DISP_E_BADPARAMCOUNT );

   
// We don't support named arguments
   if ( pDispParams->cNamedArgs > 0 )
      
return( DISP_E_NONAMEDARGS );

   
// Break out the parameters and coerce them
   
// to the proper type
   HRESULT hr;
   VARIANT varOp1;
   VARIANT varOp2;

   
// Coerce the variant into the desired type
   
// In this case we would like a long
   VariantInit( &varOp1 );
   hr 
= VariantChangeType(  &varOp1,
                      
&(pDispParams->rgvarg[1]),
                      
0,
                      VT_I4 );
   
// If we can't get a long return invalidate argument
   if ( FAILED( hr ))
      
return( DISP_E_TYPEMISMATCH );

   
// Coerce the variant into the desired type
   
// In this case we would like a long
   VariantInit( &varOp2 );
   hr 
= VariantChangeType( &varOp2,
                      
&(pDispParams->rgvarg[0]),
                      
0,
                      VT_I4 );

   
// If we can't get a long return invalidate argument
   if ( FAILED( hr ))
      
return( DISP_E_TYPEMISMATCH );

   
// Initialize the return value
   
// If there isn't one, then just return
   if ( pvarResult )
   {
      VariantInit( pvarResult );
      pvarResult
->vt = VT_I4;
   }
   
else
      
return S_OK;

   
switch( dispid )
   {
      
case DISPID_ADD:
         pvarResult
->lVal = varOp1.lVal + varOp2.lVal;
         
return S_OK;

      
case DISPID_SUBTRACT:
         pvarResult
->lVal = varOp1.lVal - varOp2.lVal;
         
return S_OK;

      
case DISPID_MULTIPLY:
         pvarResult
->lVal = varOp1.lVal * varOp2.lVal;
         
return S_OK;

      
case DISPID_DIVIDE:
         pvarResult
->lVal = varOp1.lVal / varOp2.lVal;
         
return S_OK;

      
default:
         
return( DISP_E_MEMBERNOTFOUND );
   }
}

// IMath implementation

STDMETHODIMP Math::Add(
long lOp1, long lOp2, long * plResult)
{
   
*plResult = lOp1 + lOp2;
   
return S_OK;
}

STDMETHODIMP Math::Subtract(
long lOp1, long lOp2, long * plResult)
{
   
*plResult = lOp1 - lOp2;
   
return S_OK;
}

STDMETHODIMP Math::Multiply(
long lOp1, long lOp2, long * plResult)
{
   
*plResult = lOp1 * lOp2;
   
return S_OK;
}

STDMETHODIMP Math::Divide(
long lOp1, long lOp2, long * plResult)
{
   
*plResult = lOp1 / lOp2;
   
return S_OK;
}

MathClassFactory::MathClassFactory()
{
    m_dwRef 
= 0;
}

MathClassFactory::
~MathClassFactory()
{
}

STDMETHODIMP MathClassFactory::QueryInterface( REFIID riid, 
void** ppv )
{
   
*ppv = NULL;

   
if ( riid == IID_IUnknown || riid == IID_IClassFactory )
      
*ppv = this;

   
if ( *ppv )
   {
      ( (LPUNKNOWN)
*ppv )->AddRef();
      
return S_OK;
   }

   
return(E_NOINTERFACE);
}

STDMETHODIMP_(ULONG) MathClassFactory::AddRef()
{
    
return ++m_dwRef;
}

STDMETHODIMP_(ULONG) MathClassFactory::Release()
{
   
if ( --m_dwRef )
      
return m_dwRef;
   
else
      delete 
this;

    
return 0;
}

STDMETHODIMP MathClassFactory::CreateInstance
( LPUNKNOWN pUnkOuter, REFIID riid, 
void** ppvObj )
{
    Math
* pMath;
    HRESULT     hr;

    
*ppvObj = NULL;

    pMath 
= new Math;

    
if ( pMath == NULL )
        
return( E_OUTOFMEMORY );

    hr 
= pMath->QueryInterface( riid, ppvObj );

    
if ( FAILED( hr ) )
        delete pMath;
    
else
        g_dwObjs
++;  // Increment the global object count

    
return hr;
}

STDMETHODIMP MathClassFactory::LockServer( BOOL fLock )
{
    
if ( fLock )
        g_dwLocks
++;
    
else
        g_dwLocks
--;

    
return S_OK;
}