NT4/private/oleauto/tests/common/crempoly.cpp
2020-09-30 17:12:29 +02:00

611 lines
13 KiB
C++

/***
*crempoly.cpp
*
* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
* Information Contained Herein Is Proprietary and Confidential.
*
*Purpose:
* This file contains the implementation of CRemPoly, the remote polygon
* class. This class presents a standard C++ vtable interface to the
* rest of the application, and hides the details of talking to the
* actual remote CPoly class exposed by the SPoly server. Each of
* the introduced methods is simply a cover for an IDispatch invocation
* of the actual method on the remote object.
*
*Implementation Notes:
*
* NOTE: this is a derivative of crempoly.cpp from the sample dispdemo,
* but has been modified to for use in our test apps. This is no longer
* a legit sample because it contains references to private definitions
* from src/dispatch.
*
*****************************************************************************/
#include "common.h"
#include "crempoly.h"
// method names on the CPoly class.
//
OLECHAR FAR* CRemPoly::m_rgszMethods[] = {
OLESTR("draw"),
OLESTR("dump"),
OLESTR("reset"),
OLESTR("addpoint"),
OLESTR("enumpoints"),
OLESTR("getxorigin"),
OLESTR("setxorigin"),
OLESTR("getyorigin"),
OLESTR("setyorigin"),
OLESTR("getwidth"),
OLESTR("setwidth"),
OLESTR("get_red"),
OLESTR("set_red"),
OLESTR("get_green"),
OLESTR("set_green"),
OLESTR("get_blue"),
OLESTR("set_blue")
};
CRemPoly::CRemPoly()
{
m_refs = 0;
m_pdisp = (IDispatch FAR*)NULL;
}
// A useful pre-initialized DISPATCHPARAMS, used on all the methods that
// take 0 arguments.
//
DISPPARAMS g_dispparamsNoArgs = {NULL, NULL, 0, 0};
/***
*HRESULT CRemPoly::Create(OLECHAR*, CRemPoly**)
*
*Purpose:
* This function creates an instance of the CRemPoly class, connects
* it to the IDispatch interface of the remote CPoly class, and learns
* the DISPIDs for the members (that we know about) exposed by that
* class.
*
*Entry:
* clsid = The CLSID of the CPoly we are to create. (taking this as a
* param is a bit weird, but allows us to connect to several remote
* versions.
*
*Exit:
* return value = HRESULT
*
* *pprempoly = pointer to the newly created CRemPoly, if successfyl.
*
***********************************************************************/
HRESULT
CRemPoly::Create(OLECHAR FAR* szProgID, CRemPoly FAR* FAR* pprempoly)
{
int i;
HRESULT hresult;
CRemPoly FAR* prempoly;
prempoly = new FAR CRemPoly();
if(prempoly == (CRemPoly FAR*)NULL){
hresult = ResultFromScode(E_OUTOFMEMORY);
goto LError;
}
prempoly->AddRef();
hresult = CreateObject(szProgID, &prempoly->m_pdisp);
if(hresult != NOERROR)
goto LFreeCRemPoly;
// We learn *all* the member IDs up front. A more sophisticated
// implementation might defer learning about the IDs for a given
// method until the first time the method is invoked, thereby
// amortizing the creation costs.
//
for(i = 0; i < IMETH_CREMPOLY_MAX; ++i){
hresult = prempoly->m_pdisp->GetIDsOfNames(
IID_NULL,
&prempoly->m_rgszMethods[i],
1, LOCALE_SYSTEM_DEFAULT,
&prempoly->m_rgdispid[i]);
if(hresult != NOERROR)
goto LFreeCRemPoly;
}
*pprempoly = prempoly;
return NOERROR;
LFreeCRemPoly:;
prempoly->Release();
LError:;
return hresult;
}
//---------------------------------------------------------------------
// IUnknown methods
//---------------------------------------------------------------------
/***
*HRESULT CRemPoly::QueryInterface(REFIID, void**)
*
*Purpose:
* Standard Ole2 implementation of QueryInterface. This class
* supports the IUnknown interface, and introduces a number of
* nonvirtual members.
*
*Entry:
* riid = reference to the requested interface id
*
*Exit:
* return value = HRESULT
* *ppv = pointer to the requested interface, if successful.
*
***********************************************************************/
STDMETHODIMP
CRemPoly::QueryInterface(REFIID riid, void FAR* FAR* ppv)
{
if(IsEqualIID(riid, IID_IUnknown)){
*ppv = this;
AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
/***
*unsigned long CRemPoly::AddRef(void)
*
*Purpose:
* Add a reference to the instance.
*
*Entry:
* None
*
*Exit:
* return value = unsigned long. The resulting reference count.
*
***********************************************************************/
STDMETHODIMP_(unsigned long)
CRemPoly::AddRef(void)
{
return ++m_refs;
}
/***
*unsigned long CRemPoly::Release(void)
*
*Purpose:
* Release a reference to the instance. If the reference count goes
* to zero, delete the instance.
*
*Entry:
* None
*
*Exit:
* return value = unsigned long. The resulting reference count.
*
***********************************************************************/
STDMETHODIMP_(unsigned long)
CRemPoly::Release(void)
{
if(--m_refs == 0){
if(m_pdisp != (IDispatch FAR*)NULL){
m_pdisp->Release();
}
delete this;
return 0;
}
return m_refs;
}
//---------------------------------------------------------------------
// Introduced methods
//---------------------------------------------------------------------
/*
* Each of these methods is simply a cover for an IDispatch Invocation
* of the actual method on the remote CPoly class. This allows CRemPoly
* to present an interface that looks and acts just like the CPoly
* object, even though the actual work is being done in another process.
*
*/
/***
*HRESULT CRemPoly::Draw(void)
*
*Purpose:
* Invoke the Draw method on the remote CPoly instance.
*
*Entry:
* None
*
*Exit:
* return value = HRESULT
*
***********************************************************************/
HRESULT
CRemPoly::Draw()
{
return m_pdisp->Invoke(
m_rgdispid[IMETH_CREMPOLY_DRAW],
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&g_dispparamsNoArgs, NULL, NULL, NULL);
}
/***
*HRESULT CRemPoly::Dump(void)
*
*Purpose:
* Invoke the Dump() method on the remote CPoly instance. This method
* dumps the contained CPoints and writes the properties of the remote
* CPoly instance to the debug window.
*
*Entry:
* None
*
*Exit:
* return value = HRESULT
*
***********************************************************************/
HRESULT
CRemPoly::Dump()
{
return m_pdisp->Invoke(
m_rgdispid[IMETH_CREMPOLY_DUMP],
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&g_dispparamsNoArgs, NULL, NULL, NULL);
}
/***
*HRESULT CRemPoly::Reset(void)
*
*Purpose:
* Invoke the Reset() method on the remote CPoly instance. The Reset()
* method causes the remote CPoly to release all contained CPoints.
*
*Entry:
* None
*
*Exit:
* return value = HRESULT
*
***********************************************************************/
HRESULT
CRemPoly::Reset()
{
return m_pdisp->Invoke(
m_rgdispid[IMETH_CREMPOLY_RESET],
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&g_dispparamsNoArgs, NULL, NULL, NULL);
}
/***
*HRESULT CRemPoly::AddPoint(short, short)
*
*Purpose:
* Invoke the AddPoint method in the remote CPoly object to add a
* new point with the given coordinates to this instance.
*
*Entry:
* x,y = the x and y coordinates of the new point.
*
*Exit:
* return value = HRESULT
*
***********************************************************************/
HRESULT
CRemPoly::AddPoint(short x, short y)
{
HRESULT hresult;
VARIANTARG rgvarg[2];
DISPPARAMS dispparams;
V_VT(&rgvarg[0]) = VT_I2;
V_I2(&rgvarg[0]) = y;
V_VT(&rgvarg[1]) = VT_I2;
V_I2(&rgvarg[1]) = x;
dispparams.cArgs = 2;
dispparams.rgvarg = rgvarg;
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
hresult = m_pdisp->Invoke(
m_rgdispid[IMETH_CREMPOLY_ADDPOINT],
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&dispparams, NULL, NULL, NULL);
return hresult;
}
/***
*HRESULT CRemPoly::EnumPoints(IEnumVARIANT**)
*Purpose:
* Inoke the EnumPoints() method in the remote object to
* get a enumerator for the points contained in the current poly.
*
*Entry:
* None
*
*Exit:
* return value = HRESULT
*
* *ppenum = pointer to the point enumerator
*
***********************************************************************/
HRESULT
CRemPoly::EnumPoints(IEnumVARIANT FAR* FAR* ppenum)
{
HRESULT hresult;
IEnumVARIANT FAR* penum;
VARIANT varResult, FAR* pvarResult;
pvarResult = &varResult;
VariantInit(pvarResult);
hresult = m_pdisp->Invoke(
m_rgdispid[IMETH_CREMPOLY_ENUMPOINTS],
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&g_dispparamsNoArgs, pvarResult, NULL, NULL);
if(hresult != NOERROR)
return hresult;
if(V_VT(pvarResult) != VT_UNKNOWN)
return ResultFromScode(E_FAIL);
hresult = V_UNKNOWN(pvarResult)->QueryInterface(
IID_IEnumVARIANT, (void FAR* FAR*)&penum);
if(hresult == NOERROR)
*ppenum = penum;
VariantClear(pvarResult);
return NOERROR;
}
/***
*HRESULT CRemPoly::GetXOrigin(short*)
*
*Purpose:
* Invoke the GetXOrigin() method on the remote object to extract
* the current value of the XOrigin property.
*
*Entry:
* None
*
*Exit:
* return value = HRESULT
*
* *pxorg = the current X origin of the polygon.
*
***********************************************************************/
HRESULT
CRemPoly::GetXOrigin(short FAR* pxorg)
{
return get_i2(m_rgdispid[IMETH_CREMPOLY_GETXORIGIN], pxorg);
}
/***
*HRESULT CRemPoly::SetXOrigin(short)
*
*Purpose:
* Invoke the SetXOrigin method on the remote object to set the
* XOrigin property of the polygon to the given value.
*
*Entry:
* xorg = the new X origin
*
*Exit:
* return value = HRESULT
*
***********************************************************************/
HRESULT
CRemPoly::SetXOrigin(short xorg)
{
return set_i2(m_rgdispid[IMETH_CREMPOLY_SETXORIGIN], xorg);
}
/***
*HRESULT CRemPoly::GetYOrigin(short*)
*
*Purpose:
* Invoke the GetYOrigin() method on the remote object to extract
* the current value of the YOrigin property.
*
*Entry:
* None
*
*Exit:
* return value = HRESULT
*
* *pyorg = the current Y origin of the polygon
*
***********************************************************************/
HRESULT
CRemPoly::GetYOrigin(short FAR* pyorg)
{
return get_i2(m_rgdispid[IMETH_CREMPOLY_GETYORIGIN], pyorg);
}
/***
*HRESULT CRemPoly::SetYOrigin(short)
*
*Purpose:
* Invoke the SetYOrigin method on the remote object to set the
* YOrigin property of the polygon to the given value.
*
*Entry:
* yorg = the new Y origin
*
*Exit:
* return value = HRESULT
*
***********************************************************************/
HRESULT
CRemPoly::SetYOrigin(short yorg)
{
return set_i2(m_rgdispid[IMETH_CREMPOLY_SETYORIGIN], yorg);
}
/***
*HRESULT CRemPoly::GetWidth(short*)
*
*Purpose:
* Invoke the GetWidth() method on the remote object to extract
* the current value of the line width property.
*
*Entry:
* None
*
*Exit:
* return value = HRESULT
*
* *pwidth = short, the current line width of the polygon
*
***********************************************************************/
HRESULT
CRemPoly::GetWidth(short FAR* pwidth)
{
return get_i2(m_rgdispid[IMETH_CREMPOLY_GETWIDTH], pwidth);
}
/***
*HRESULT CRemPoly::SetWidth(short)
*
*Purpose:
* Invoke the SetWidth method on the remote object to set the
* line width property of the polygon to the given value.
*
*Entry:
* width = the new value for the line width property.
*
*Exit:
* return value = HRESULT
*
***********************************************************************/
HRESULT
CRemPoly::SetWidth(short width)
{
return set_i2(m_rgdispid[IMETH_CREMPOLY_SETWIDTH], width);
}
HRESULT CRemPoly::get_red(short FAR* psRed)
{
return get_i2(m_rgdispid[IMETH_CREMPOLY_GETRED], psRed);
}
HRESULT CRemPoly::set_red(short sRed)
{
return set_i2(m_rgdispid[IMETH_CREMPOLY_SETRED], sRed);
}
HRESULT CRemPoly::get_green(short FAR* psGreen)
{
return get_i2(m_rgdispid[IMETH_CREMPOLY_GETGREEN], psGreen);
}
HRESULT CRemPoly::set_green(short sGreen)
{
return set_i2(m_rgdispid[IMETH_CREMPOLY_SETGREEN], sGreen);
}
HRESULT CRemPoly::get_blue(short FAR* psBlue)
{
return get_i2(m_rgdispid[IMETH_CREMPOLY_GETBLUE], psBlue);
}
HRESULT CRemPoly::set_blue(short sBlue)
{
return set_i2(m_rgdispid[IMETH_CREMPOLY_SETBLUE], sBlue);
}
HRESULT
CRemPoly::get_i2(DISPID dispid, short FAR* ps)
{
HRESULT hresult;
VARIANT varResult;
VariantInit(&varResult);
hresult = m_pdisp->Invoke(
dispid,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&g_dispparamsNoArgs,
&varResult, NULL, NULL);
if(hresult != NOERROR)
return hresult;
hresult = VariantChangeType(&varResult, &varResult, 0, VT_I2);
if(hresult != NOERROR){
VariantClear(&varResult);
return hresult;
}
*ps = V_I2(&varResult);
return NOERROR;
}
HRESULT
CRemPoly::set_i2(DISPID dispid, short s)
{
VARIANTARG varg;
DISPPARAMS dispparams;
V_VT(&varg) = VT_I2;
V_I2(&varg) = s;
dispparams.cArgs = 1;
dispparams.cNamedArgs = 0;
dispparams.rgvarg = &varg;
return m_pdisp->Invoke(
dispid,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&dispparams, NULL, NULL, NULL);
}