390 lines
8.7 KiB
C++
390 lines
8.7 KiB
C++
/***
|
|
*cpoint.cpp
|
|
*
|
|
* Copyright (C) 1992-1994, Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
*Purpose:
|
|
* This module implements the CPoint and CPointCF classes.
|
|
*
|
|
* This module is intended as a sample implementation of the IDispatch
|
|
* interface, and its purpose is to demonstrate how an object can
|
|
* expose methods and properties for programatic and cross-process
|
|
* access via the IDispatch interface.
|
|
*
|
|
*Implementation Notes:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "spoly.h"
|
|
#include "cpoint.h"
|
|
|
|
|
|
CPoint::CPoint()
|
|
{
|
|
m_x = 0;
|
|
m_y = 0;
|
|
m_refs = 0;
|
|
}
|
|
|
|
/***
|
|
*CPoint::Create(void)
|
|
*Purpose:
|
|
* Create an instance of a CPoint object.
|
|
*
|
|
*Entry:
|
|
* None
|
|
*
|
|
*Exit:
|
|
* returns a CPoint*, NULL if creation failed.
|
|
*
|
|
***********************************************************************/
|
|
CPoint FAR*
|
|
CPoint::Create()
|
|
{
|
|
CPoint FAR* ppoint;
|
|
|
|
if((ppoint = new FAR CPoint()) == NULL)
|
|
return NULL;
|
|
ppoint->AddRef();
|
|
return ppoint;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// IUnknown Methods
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP
|
|
CPoint::QueryInterface(REFIID riid, void FAR* FAR* ppv)
|
|
{
|
|
if(!IsEqualIID(riid, IID_IUnknown))
|
|
if(!IsEqualIID(riid, IID_IDispatch)) {
|
|
*ppv = NULL;
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
*ppv = this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPoint::AddRef(void)
|
|
{
|
|
return ++m_refs;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPoint::Release(void)
|
|
{
|
|
if(--m_refs == 0){
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_refs;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// IDispatch methods
|
|
//---------------------------------------------------------------------
|
|
|
|
/*
|
|
* NOTE: Support for the following two methods is not available
|
|
* in this version.
|
|
*
|
|
*/
|
|
|
|
STDMETHODIMP
|
|
CPoint::GetTypeInfoCount(unsigned int FAR* pctinfo)
|
|
{
|
|
*pctinfo = 0;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CPoint::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
|
|
{
|
|
UNUSED(itinfo);
|
|
UNUSED(lcid);
|
|
UNUSED(pptinfo);
|
|
|
|
return ResultFromScode(E_NOTIMPL);
|
|
}
|
|
|
|
|
|
/***
|
|
*HRESULT CPoint::GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, long*)
|
|
*Purpose:
|
|
* This method translates the given array of names to a corresponding
|
|
* array of DISPIDs.
|
|
*
|
|
* Index 0 of the name array is the member name, and indices 1-N if
|
|
* present represent named parameters on that member.
|
|
*
|
|
* The local ID ('lcid') is unused by this naive implementation. A more
|
|
* sophisticated implementation, sensitive to localization and natural
|
|
* language support would use the locale ID to interpret the given names
|
|
* in a correct locale specific context.
|
|
*
|
|
*Entry:
|
|
* rgszNames = pointer to an array of names
|
|
* cNames = the number of names in the rgszNames array
|
|
* lcid = the callers locale ID
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
* rgid = array of name IDs corresponding to the rgszNames array
|
|
* this array will contain -1 for each entry that is not known.
|
|
*
|
|
***********************************************************************/
|
|
STDMETHODIMP
|
|
CPoint::GetIDsOfNames(
|
|
REFIID riid,
|
|
OLECHAR FAR* FAR* rgszNames,
|
|
unsigned int cNames,
|
|
LCID lcid,
|
|
DISPID FAR* rgdispid)
|
|
{
|
|
static MEMBERDESC rgmdCPoint[] = {
|
|
{OLESTR("GETX"), IDMEMBER_CPOINT_GETX, NULL, 0},
|
|
{OLESTR("SETX"), IDMEMBER_CPOINT_SETX, NULL, 0},
|
|
{OLESTR("GETY"), IDMEMBER_CPOINT_GETY, NULL, 0},
|
|
{OLESTR("SETY"), IDMEMBER_CPOINT_SETY, NULL, 0}
|
|
};
|
|
|
|
// this object only exposed the "default" interface.
|
|
//
|
|
if(!IsEqualIID(riid, IID_NULL))
|
|
return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
|
|
|
|
return SPolyGetIDsOfNames(
|
|
rgmdCPoint, DIM(rgmdCPoint), rgszNames, cNames, lcid, rgdispid);
|
|
}
|
|
|
|
|
|
/***
|
|
*HRESULT CPoint::Invoke(...)
|
|
*Purpose:
|
|
* Dispatch a method or property request for objects of type CPoint.
|
|
*
|
|
* see the IDispatch document for more information, and a general
|
|
* description of this method.
|
|
*
|
|
*Entry:
|
|
* dispidMember = the DISPID of the member being requested
|
|
*
|
|
* riid = reference to the interface ID of the interface on this object
|
|
* that the requested member belongs to. IID_NULL means to interpret
|
|
* the member as belonging to the implementation defined "default"
|
|
* or "primary" interface.
|
|
*
|
|
* lcid = the caller's locale ID
|
|
*
|
|
* wFlags = flags indicating the type of access being requested
|
|
*
|
|
* pdispparams = pointer to the DISPPARAMS struct containing the
|
|
* requested members arguments (if any) and its named parameter
|
|
* DISPIDs (if any).
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
* see the IDispatch spec for a description of possible success codes.
|
|
*
|
|
* pvarResult = pointer to a caller allocated VARIANT containing
|
|
* the members return value (if any).
|
|
*
|
|
* pexcepinfo = caller allocated exception info structure, this will
|
|
* be filled in only if an exception was raised that must be passed
|
|
* up through Invoke to an enclosing handler.
|
|
*
|
|
* puArgErr = pointer to a caller allocated UINT, that will contain the
|
|
* index of the offending argument if a DISP_E_TYPEMISMATCH error
|
|
* was returned indicating that one of the arguments was of an
|
|
* incorrect type and/or could not be reasonably coerced to a proper
|
|
* type.
|
|
*
|
|
***********************************************************************/
|
|
STDMETHODIMP
|
|
CPoint::Invoke(
|
|
DISPID dispidMember,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
unsigned short wFlags,
|
|
DISPPARAMS FAR* pdispparams,
|
|
VARIANT FAR* pvarResult,
|
|
EXCEPINFO FAR* pexcepinfo,
|
|
unsigned int FAR* puArgErr)
|
|
{
|
|
unsigned int uArgErr;
|
|
HRESULT hresult;
|
|
VARIANTARG varg0;
|
|
VARIANT varResultDummy;
|
|
|
|
UNUSED(lcid);
|
|
UNUSED(pexcepinfo);
|
|
|
|
// make sure the wFlags are legal
|
|
if(wFlags & ~(DISPATCH_METHOD | DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
|
|
return ResultFromScode(E_INVALIDARG);
|
|
|
|
// this object only exposes a "default" interface.
|
|
//
|
|
if(!IsEqualIID(riid, IID_NULL))
|
|
return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
|
|
|
|
// this makes the following code a bit simpler
|
|
if(puArgErr == NULL)
|
|
puArgErr = &uArgErr;
|
|
if(pvarResult == NULL)
|
|
pvarResult = &varResultDummy;
|
|
|
|
VariantInit(&varg0);
|
|
|
|
// assume the return type is void, unless we find otherwise.
|
|
VariantInit(pvarResult);
|
|
|
|
switch(dispidMember){
|
|
case IDMEMBER_CPOINT_GETX:
|
|
V_VT(pvarResult) = VT_I2;
|
|
V_I2(pvarResult) = GetX();
|
|
break;
|
|
|
|
case IDMEMBER_CPOINT_SETX:
|
|
hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
|
|
if(hresult != NOERROR)
|
|
return hresult;
|
|
SetX(V_I2(&varg0));
|
|
break;
|
|
|
|
case IDMEMBER_CPOINT_GETY:
|
|
V_VT(pvarResult) = VT_I2;
|
|
V_I2(pvarResult) = GetY();
|
|
break;
|
|
|
|
case IDMEMBER_CPOINT_SETY:
|
|
hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
|
|
if(hresult != NOERROR)
|
|
return hresult;
|
|
SetY(V_I2(&varg0));
|
|
break;
|
|
|
|
default:
|
|
return ResultFromScode(DISP_E_MEMBERNOTFOUND);
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
short PASCAL
|
|
CPoint::GetX()
|
|
{
|
|
return m_x;
|
|
}
|
|
|
|
void PASCAL
|
|
CPoint::SetX(short x)
|
|
{
|
|
m_x = x;
|
|
}
|
|
|
|
short PASCAL
|
|
CPoint::GetY()
|
|
{
|
|
return m_y;
|
|
}
|
|
|
|
void PASCAL
|
|
CPoint::SetY(short y)
|
|
{
|
|
m_y = y;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// Implementation of the CPoint Class Factory
|
|
//---------------------------------------------------------------------
|
|
|
|
CPointCF::CPointCF()
|
|
{
|
|
m_refs = 0;
|
|
}
|
|
|
|
IClassFactory FAR*
|
|
CPointCF::Create()
|
|
{
|
|
CPointCF FAR* pCF;
|
|
|
|
if((pCF = new FAR CPointCF()) == NULL)
|
|
return NULL;
|
|
pCF->AddRef();
|
|
return pCF;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPointCF::QueryInterface(REFIID riid, void FAR* FAR* ppv)
|
|
{
|
|
|
|
if(!IsEqualIID(riid, IID_IUnknown))
|
|
if(!IsEqualIID(riid, IID_IClassFactory)) {
|
|
*ppv = NULL;
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
*ppv = this;
|
|
++m_refs;
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPointCF::AddRef(void)
|
|
{
|
|
return ++m_refs;
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPointCF::Release(void)
|
|
{
|
|
if(--m_refs == 0){
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_refs;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPointCF::CreateInstance(
|
|
IUnknown FAR* punkOuter,
|
|
REFIID riid,
|
|
void FAR* FAR* ppv)
|
|
{
|
|
HRESULT hresult;
|
|
CPoint FAR *ppoint;
|
|
|
|
UNUSED(punkOuter);
|
|
|
|
if((ppoint = CPoint::Create()) == NULL){
|
|
*ppv = NULL;
|
|
return ResultFromScode(E_OUTOFMEMORY);
|
|
}
|
|
hresult = ppoint->QueryInterface(riid, ppv);
|
|
ppoint->Release();
|
|
return hresult;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
#ifdef _MAC
|
|
CPointCF::LockServer(unsigned long fLock)
|
|
#else
|
|
CPointCF::LockServer(BOOL fLock)
|
|
#endif
|
|
{
|
|
UNUSED(fLock);
|
|
|
|
return NOERROR;
|
|
}
|
|
|