windows-nt/Source/XPSP1/NT/com/oleutest/letest/outline/svrpsobj.c
2020-09-26 16:20:57 +08:00

1539 lines
41 KiB
C

/*************************************************************************
**
** OLE 2 Server Sample Code
**
** svrpsobj.c
**
** This file contains all PseudoObj methods and related support
** functions.
**
** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
**
*************************************************************************/
#include "outline.h"
OLEDBGDATA
extern LPOUTLINEAPP g_lpApp;
extern IUnknownVtbl g_PseudoObj_UnknownVtbl;
extern IOleObjectVtbl g_PseudoObj_OleObjectVtbl;
extern IDataObjectVtbl g_PseudoObj_DataObjectVtbl;
/* PseudoObj_Init
** --------------
** Initialize fields in a newly constructed PseudoObj.
** NOTE: ref cnt of PseudoObj initialized to 0
*/
void PseudoObj_Init(
LPPSEUDOOBJ lpPseudoObj,
LPSERVERNAME lpServerName,
LPSERVERDOC lpServerDoc
)
{
OleDbgOut2("++PseudoObj Created\r\n");
lpPseudoObj->m_cRef = 0;
lpPseudoObj->m_lpName = lpServerName;
lpPseudoObj->m_lpDoc = lpServerDoc;
lpPseudoObj->m_lpOleAdviseHldr = NULL;
lpPseudoObj->m_lpDataAdviseHldr = NULL;
lpPseudoObj->m_fObjIsClosing = FALSE;
INIT_INTERFACEIMPL(
&lpPseudoObj->m_Unknown,
&g_PseudoObj_UnknownVtbl,
lpPseudoObj
);
INIT_INTERFACEIMPL(
&lpPseudoObj->m_OleObject,
&g_PseudoObj_OleObjectVtbl,
lpPseudoObj
);
INIT_INTERFACEIMPL(
&lpPseudoObj->m_DataObject,
&g_PseudoObj_DataObjectVtbl,
lpPseudoObj
);
/* OLE2NOTE: Increment the refcnt of the Doc on behalf of the
** PseudoObj. the Document should not shut down unless all
** pseudo objects are closed. when a pseudo object is destroyed,
** it calls ServerDoc_PseudoObjUnlockDoc to release this hold on
** the document.
*/
ServerDoc_PseudoObjLockDoc(lpServerDoc);
}
/* PseudoObj_AddRef
** ----------------
**
** increment the ref count of the PseudoObj object.
**
** Returns the new ref count on the object
*/
ULONG PseudoObj_AddRef(LPPSEUDOOBJ lpPseudoObj)
{
++lpPseudoObj->m_cRef;
#if defined( _DEBUG )
OleDbgOutRefCnt4(
"PseudoObj_AddRef: cRef++\r\n",
lpPseudoObj,
lpPseudoObj->m_cRef
);
#endif
return lpPseudoObj->m_cRef;
}
/* PseudoObj_Release
** -----------------
**
** decrement the ref count of the PseudoObj object.
** if the ref count goes to 0, then the PseudoObj is destroyed.
**
** Returns the remaining ref count on the object
*/
ULONG PseudoObj_Release(LPPSEUDOOBJ lpPseudoObj)
{
ULONG cRef;
/*********************************************************************
** OLE2NOTE: when the obj refcnt == 0, then destroy the object. **
** otherwise the object is still in use. **
*********************************************************************/
cRef = --lpPseudoObj->m_cRef;
#if defined( _DEBUG )
OleDbgAssertSz(lpPseudoObj->m_cRef >= 0,"Release called with cRef == 0");
OleDbgOutRefCnt4(
"PseudoObj_Release: cRef--\r\n", lpPseudoObj,cRef);
#endif
if (cRef == 0)
PseudoObj_Destroy(lpPseudoObj);
return cRef;
}
/* PseudoObj_QueryInterface
** ------------------------
**
** Retrieve a pointer to an interface on the PseudoObj object.
**
** Returns S_OK if interface is successfully retrieved.
** E_NOINTERFACE if the interface is not supported
*/
HRESULT PseudoObj_QueryInterface(
LPPSEUDOOBJ lpPseudoObj,
REFIID riid,
LPVOID FAR* lplpvObj
)
{
SCODE sc = E_NOINTERFACE;
/* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
*lplpvObj = NULL;
if (IsEqualIID(riid, &IID_IUnknown)) {
OleDbgOut4("PseudoObj_QueryInterface: IUnknown* RETURNED\r\n");
*lplpvObj = (LPVOID) &lpPseudoObj->m_Unknown;
PseudoObj_AddRef(lpPseudoObj);
sc = S_OK;
}
else if (IsEqualIID(riid, &IID_IOleObject)) {
OleDbgOut4("PseudoObj_QueryInterface: IOleObject* RETURNED\r\n");
*lplpvObj = (LPVOID) &lpPseudoObj->m_OleObject;
PseudoObj_AddRef(lpPseudoObj);
sc = S_OK;
}
else if (IsEqualIID(riid, &IID_IDataObject)) {
OleDbgOut4("PseudoObj_QueryInterface: IDataObject* RETURNED\r\n");
*lplpvObj = (LPVOID) &lpPseudoObj->m_DataObject;
PseudoObj_AddRef(lpPseudoObj);
sc = S_OK;
}
OleDbgQueryInterfaceMethod(*lplpvObj);
return ResultFromScode(sc);
}
/* PseudoObj_Close
* ---------------
*
* Close the pseudo object. Force all external connections to close
* down. This causes link clients to release this PseudoObj. when
* the refcount actually reaches 0, then the PseudoObj will be
* destroyed.
*
* Returns:
* FALSE -- user canceled the closing of the doc.
* TRUE -- the doc was successfully closed
*/
BOOL PseudoObj_Close(LPPSEUDOOBJ lpPseudoObj)
{
LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpPseudoObj->m_lpDoc;
LPSERVERNAME lpServerName = (LPSERVERNAME)lpPseudoObj->m_lpName;
LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
BOOL fStatus = TRUE;
if (lpPseudoObj->m_fObjIsClosing)
return TRUE; // Closing is already in progress
lpPseudoObj->m_fObjIsClosing = TRUE; // guard against recursive call
OLEDBG_BEGIN3("PseudoObj_Close\r\n")
/* OLE2NOTE: in order to have a stable App, Doc, AND pseudo object
** during the process of closing, we intially AddRef the App,
** Doc, and PseudoObj ref counts and later Release them. These
** initial AddRefs are artificial; they are simply done to
** guarantee that these objects do not get destroyed until the
** end of this routine.
*/
OleApp_AddRef(lpOleApp);
OleDoc_AddRef(lpOleDoc);
PseudoObj_AddRef(lpPseudoObj);
if (lpPseudoObj->m_lpDataAdviseHldr) {
/* OLE2NOTE: send last OnDataChange notification to clients
** that have registered for data notifications when object
** stops running (ADVF_DATAONSTOP)
*/
PseudoObj_SendAdvise(
lpPseudoObj,
OLE_ONDATACHANGE,
NULL, /* lpmkObj -- not relevant here */
ADVF_DATAONSTOP
);
/* OLE2NOTE: we just sent the last data notification that we
** need to send; release our DataAdviseHolder. we SHOULD be
** the only one using it.
*/
OleStdVerifyRelease(
(LPUNKNOWN)lpPseudoObj->m_lpDataAdviseHldr,
"DataAdviseHldr not released properly"
);
lpPseudoObj->m_lpDataAdviseHldr = NULL;
}
if (lpPseudoObj->m_lpOleAdviseHldr) {
// OLE2NOTE: inform all of our linking clients that we are closing.
PseudoObj_SendAdvise(
lpPseudoObj,
OLE_ONCLOSE,
NULL, /* lpmkObj -- not relevant here */
0 /* advf -- not relevant here */
);
/* OLE2NOTE: OnClose is the last notification that we need to
** send; release our OleAdviseHolder. we SHOULD be the only
** one using it. this will make our destructor realize that
** OnClose notification has already been sent.
*/
OleStdVerifyRelease(
(LPUNKNOWN)lpPseudoObj->m_lpOleAdviseHldr,
"OleAdviseHldr not released properly"
);
lpPseudoObj->m_lpOleAdviseHldr = NULL;
}
/* OLE2NOTE: this call forces all external connections to our
** object to close down and therefore guarantees that we receive
** all releases associated with those external connections.
*/
OLEDBG_BEGIN2("CoDisconnectObject called\r\n")
CoDisconnectObject((LPUNKNOWN)&lpPseudoObj->m_Unknown, 0);
OLEDBG_END2
PseudoObj_Release(lpPseudoObj); // release artificial AddRef above
OleDoc_Release(lpOleDoc); // release artificial AddRef above
OleApp_Release(lpOleApp); // release artificial AddRef above
OLEDBG_END3
return fStatus;
}
/* PseudoObj_Destroy
** -----------------
** Destroy (Free) the memory used by a PseudoObj structure.
** This function is called when the ref count of the PseudoObj goes
** to zero. the ref cnt goes to zero after PseudoObj_Delete forces
** the OleObject to unload and release its pointers to the
** PseudoObj IOleClientSite and IAdviseSink interfaces.
*/
void PseudoObj_Destroy(LPPSEUDOOBJ lpPseudoObj)
{
LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
OLEDBG_BEGIN3("PseudoObj_Destroy\r\n")
/* OLE2NOTE: in order to have a stable App, Doc, AND pseudo object
** during the process of closing, we intially AddRef the App,
** Doc ref counts and later Release them. These
** initial AddRefs are artificial; they are simply done to
** guarantee that these objects do not get destroyed until the
** end of this routine.
*/
OleApp_AddRef(lpOleApp);
OleDoc_AddRef(lpOleDoc);
/******************************************************************
** OLE2NOTE: we no longer need the advise and enum holder objects,
** so release them.
******************************************************************/
if (lpPseudoObj->m_lpDataAdviseHldr) {
/* release DataAdviseHldr; we SHOULD be the only one using it. */
OleStdVerifyRelease(
(LPUNKNOWN)lpPseudoObj->m_lpDataAdviseHldr,
"DataAdviseHldr not released properly"
);
lpPseudoObj->m_lpDataAdviseHldr = NULL;
}
if (lpPseudoObj->m_lpOleAdviseHldr) {
/* release OleAdviseHldr; we SHOULD be the only one using it. */
OleStdVerifyRelease(
(LPUNKNOWN)lpPseudoObj->m_lpOleAdviseHldr,
"OleAdviseHldr not released properly"
);
lpPseudoObj->m_lpOleAdviseHldr = NULL;
}
/* forget the pointer to destroyed PseudoObj in NameTable */
if (lpPseudoObj->m_lpName)
lpPseudoObj->m_lpName->m_lpPseudoObj = NULL;
/* OLE2NOTE: release the lock on the Doc held on behalf of the
** PseudoObj. the Document should not shut down unless all
** pseudo objects are closed. when a pseudo object is first
** created, it calls ServerDoc_PseudoObjLockDoc to guarantee
** that the document stays alive (called from PseudoObj_Init).
*/
ServerDoc_PseudoObjUnlockDoc(lpServerDoc, lpPseudoObj);
Delete(lpPseudoObj); // Free the memory for the structure itself
OleDoc_Release(lpOleDoc); // release artificial AddRef above
OleApp_Release(lpOleApp); // release artificial AddRef above
OLEDBG_END3
}
/* PseudoObj_GetSel
** ----------------
** Return the line range for the pseudo object
*/
void PseudoObj_GetSel(LPPSEUDOOBJ lpPseudoObj, LPLINERANGE lplrSel)
{
LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpPseudoObj->m_lpName;
lplrSel->m_nStartLine = lpOutlineName->m_nStartLine;
lplrSel->m_nEndLine = lpOutlineName->m_nEndLine;
}
/* PseudoObj_GetExtent
* -------------------
*
* Get the extent (width, height) of the entire document.
*/
void PseudoObj_GetExtent(LPPSEUDOOBJ lpPseudoObj, LPSIZEL lpsizel)
{
LPOLEDOC lpOleDoc = (LPOLEDOC)lpPseudoObj->m_lpDoc;
LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
LINERANGE lrSel;
PseudoObj_GetSel(lpPseudoObj, (LPLINERANGE)&lrSel);
LineList_CalcSelExtentInHimetric(lpLL, (LPLINERANGE)&lrSel, lpsizel);
}
/* PseudoObj_SendAdvise
* --------------------
*
* This function sends an advise notification on behalf of a specific
* doc object to all its clients.
*/
void PseudoObj_SendAdvise(
LPPSEUDOOBJ lpPseudoObj,
WORD wAdvise,
LPMONIKER lpmkObj,
DWORD dwAdvf
)
{
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpPseudoObj->m_lpDoc;
switch (wAdvise) {
case OLE_ONDATACHANGE:
// inform clients that the data of the object has changed
if (lpOutlineDoc->m_nDisableDraw == 0) {
/* drawing is currently enabled. inform clients that
** the data of the object has changed
*/
lpPseudoObj->m_fDataChanged = FALSE;
if (lpPseudoObj->m_lpDataAdviseHldr) {
OLEDBG_BEGIN2("IDataAdviseHolder::SendOnDataChange called\r\n");
lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->SendOnDataChange(
lpPseudoObj->m_lpDataAdviseHldr,
(LPDATAOBJECT)&lpPseudoObj->m_DataObject,
0,
dwAdvf
);
OLEDBG_END2
}
} else {
/* drawing is currently disabled. do not send
** notifications until drawing is re-enabled.
*/
lpPseudoObj->m_fDataChanged = TRUE;
}
break;
case OLE_ONCLOSE:
// inform clients that the object is shutting down
if (lpPseudoObj->m_lpOleAdviseHldr) {
OLEDBG_BEGIN2("IOleAdviseHolder::SendOnClose called\r\n");
lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->SendOnClose(
lpPseudoObj->m_lpOleAdviseHldr
);
OLEDBG_END2
}
break;
case OLE_ONSAVE:
// inform clients that the object has been saved
if (lpPseudoObj->m_lpOleAdviseHldr) {
OLEDBG_BEGIN2("IOleAdviseHolder::SendOnClose called\r\n");
lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->SendOnSave(
lpPseudoObj->m_lpOleAdviseHldr
);
OLEDBG_END2
}
break;
case OLE_ONRENAME:
// inform clients that the object's name has changed
if (lpmkObj && lpPseudoObj->m_lpOleAdviseHldr) {
OLEDBG_BEGIN2("IOleAdviseHolder::SendOnRename called\r\n");
if (lpPseudoObj->m_lpOleAdviseHldr)
lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->SendOnRename(
lpPseudoObj->m_lpOleAdviseHldr,
lpmkObj
);
OLEDBG_END2
}
break;
}
}
/* PseudoObj_GetFullMoniker
* ------------------------
*
* Returns the Full, absolute Moniker which identifies this pseudo object.
*/
LPMONIKER PseudoObj_GetFullMoniker(LPPSEUDOOBJ lpPseudoObj, LPMONIKER lpmkDoc)
{
LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpPseudoObj->m_lpName;
LPMONIKER lpmkItem = NULL;
LPMONIKER lpmkPseudoObj = NULL;
if (lpmkDoc != NULL) {
CreateItemMonikerA(OLESTDDELIM,lpOutlineName->m_szName,&lpmkItem);
/* OLE2NOTE: create an absolute moniker which identifies the
** pseudo object. this moniker is created as a composite of
** the absolute moniker for the entire document appended
** with an item moniker which identifies the selection of
** the pseudo object relative to the document.
*/
CreateGenericComposite(lpmkDoc, lpmkItem, &lpmkPseudoObj);
if (lpmkItem)
OleStdRelease((LPUNKNOWN)lpmkItem);
return lpmkPseudoObj;
} else {
return NULL;
}
}
/*************************************************************************
** PseudoObj::IUnknown interface implementation
*************************************************************************/
STDMETHODIMP PseudoObj_Unk_QueryInterface(
LPUNKNOWN lpThis,
REFIID riid,
LPVOID FAR* lplpvObj
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjUnknownImpl FAR*)lpThis)->lpPseudoObj;
return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObj);
}
STDMETHODIMP_(ULONG) PseudoObj_Unk_AddRef(LPUNKNOWN lpThis)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjUnknownImpl FAR*)lpThis)->lpPseudoObj;
OleDbgAddRefMethod(lpThis, "IUnknown");
return PseudoObj_AddRef(lpPseudoObj);
}
STDMETHODIMP_(ULONG) PseudoObj_Unk_Release (LPUNKNOWN lpThis)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjUnknownImpl FAR*)lpThis)->lpPseudoObj;
OleDbgReleaseMethod(lpThis, "IUnknown");
return PseudoObj_Release(lpPseudoObj);
}
/*************************************************************************
** PseudoObj::IOleObject interface implementation
*************************************************************************/
STDMETHODIMP PseudoObj_OleObj_QueryInterface(
LPOLEOBJECT lpThis,
REFIID riid,
LPVOID FAR* lplpvObj
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObj);
}
STDMETHODIMP_(ULONG) PseudoObj_OleObj_AddRef(LPOLEOBJECT lpThis)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
OleDbgAddRefMethod(lpThis, "IOleObject");
return PseudoObj_AddRef((LPPSEUDOOBJ)lpPseudoObj);
}
STDMETHODIMP_(ULONG) PseudoObj_OleObj_Release(LPOLEOBJECT lpThis)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
OleDbgReleaseMethod(lpThis, "IOleObject");
return PseudoObj_Release((LPPSEUDOOBJ)lpPseudoObj);
}
STDMETHODIMP PseudoObj_OleObj_SetClientSite(
LPOLEOBJECT lpThis,
LPOLECLIENTSITE lpClientSite
)
{
OleDbgOut2("PseudoObj_OleObj_SetClientSite\r\n");
// OLE2NOTE: a pseudo object does NOT support SetExtent
return ResultFromScode(E_FAIL);
}
STDMETHODIMP PseudoObj_OleObj_GetClientSite(
LPOLEOBJECT lpThis,
LPOLECLIENTSITE FAR* lplpClientSite
)
{
OleDbgOut2("PseudoObj_OleObj_GetClientSite\r\n");
*lplpClientSite = NULL;
// OLE2NOTE: a pseudo object does NOT support SetExtent
return ResultFromScode(E_FAIL);
}
STDMETHODIMP PseudoObj_OleObj_SetHostNamesA(
LPOLEOBJECT lpThis,
LPCSTR szContainerApp,
LPCSTR szContainerObj
)
{
OleDbgOut2("PseudoObj_OleObj_SetHostNamesA\r\n");
// OLE2NOTE: a pseudo object does NOT support SetExtent
return ResultFromScode(E_FAIL);
}
STDMETHODIMP PseudoObj_OleObj_SetHostNames(
LPOLEOBJECT lpThis,
LPCOLESTR szContainerApp,
LPCOLESTR szContainerObj
)
{
OleDbgOut2("PseudoObj_OleObj_SetHostNames\r\n");
// OLE2NOTE: a pseudo object does NOT support SetExtent
return ResultFromScode(E_FAIL);
}
STDMETHODIMP PseudoObj_OleObj_Close(
LPOLEOBJECT lpThis,
DWORD dwSaveOption
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
BOOL fStatus;
OLEDBG_BEGIN2("PseudoObj_OleObj_Close\r\n")
/* OLE2NOTE: a pseudo object's implementation of IOleObject::Close
** should ignore the dwSaveOption parameter. it is NOT
** applicable to pseudo objects.
*/
fStatus = PseudoObj_Close(lpPseudoObj);
OleDbgAssertSz(fStatus == TRUE, "PseudoObj_OleObj_Close failed\r\n");
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP PseudoObj_OleObj_SetMoniker(
LPOLEOBJECT lpThis,
DWORD dwWhichMoniker,
LPMONIKER lpmk
)
{
OleDbgOut2("PseudoObj_OleObj_SetMoniker\r\n");
// OLE2NOTE: a pseudo object does NOT support SetMoniker
return ResultFromScode(E_FAIL);
}
STDMETHODIMP PseudoObj_OleObj_GetMoniker(
LPOLEOBJECT lpThis,
DWORD dwAssign,
DWORD dwWhichMoniker,
LPMONIKER FAR* lplpmk
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
LPOLEDOC lpOleDoc = (LPOLEDOC)lpPseudoObj->m_lpDoc;
LPMONIKER lpmkDoc;
OLEDBG_BEGIN2("PseudoObj_OleObj_GetMoniker\r\n")
lpmkDoc = OleDoc_GetFullMoniker(lpOleDoc, GETMONIKER_ONLYIFTHERE);
*lplpmk = PseudoObj_GetFullMoniker(lpPseudoObj, lpmkDoc);
OLEDBG_END2
if (*lplpmk != NULL)
return NOERROR;
else
return ResultFromScode(E_FAIL);
}
STDMETHODIMP PseudoObj_OleObj_InitFromData(
LPOLEOBJECT lpThis,
LPDATAOBJECT lpDataObject,
BOOL fCreation,
DWORD reserved
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
OleDbgOut2("PseudoObj_OleObj_InitFromData\r\n");
// REVIEW: NOT YET IMPLEMENTED
return ResultFromScode(E_NOTIMPL);
}
STDMETHODIMP PseudoObj_OleObj_GetClipboardData(
LPOLEOBJECT lpThis,
DWORD reserved,
LPDATAOBJECT FAR* lplpDataObject
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
OleDbgOut2("PseudoObj_OleObj_GetClipboardData\r\n");
// REVIEW: NOT YET IMPLEMENTED
return ResultFromScode(E_NOTIMPL);
}
STDMETHODIMP PseudoObj_OleObj_DoVerb(
LPOLEOBJECT lpThis,
LONG lVerb,
LPMSG lpmsg,
LPOLECLIENTSITE lpActiveSite,
LONG lindex,
HWND hwndParent,
LPCRECT lprcPosRect
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpPseudoObj->m_lpDoc;
LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
LINERANGE lrSel;
HRESULT hrErr;
OLEDBG_BEGIN2("PseudoObj_OleObj_DoVerb\r\n");
/* OLE2NOTE: we must first ask our Document to perform the same
** verb. then if the verb is NOT OLEIVERB_HIDE we should also
** select the range of our pseudo object.
** however, we must give our document its own embedding site as
** its active site.
*/
hrErr = SvrDoc_OleObj_DoVerb(
(LPOLEOBJECT)&lpServerDoc->m_OleObject,
lVerb,
lpmsg,
lpServerDoc->m_lpOleClientSite,
lindex,
NULL, /* we have no hwndParent to give */
NULL /* we have no lprcPosRect to give */
);
if (FAILED(hrErr)) {
OLEDBG_END2
return hrErr;
}
if (lVerb != OLEIVERB_HIDE) {
PseudoObj_GetSel(lpPseudoObj, &lrSel);
OutlineDoc_SetSel(lpOutlineDoc, &lrSel);
}
OLEDBG_END2
return NOERROR;
}
STDMETHODIMP PseudoObj_OleObj_EnumVerbs(
LPOLEOBJECT lpThis,
LPENUMOLEVERB FAR* lplpenumOleVerb
)
{
OleDbgOut2("PseudoObj_OleObj_EnumVerbs\r\n");
/* OLE2NOTE: we must make sure to set all out parameters to NULL. */
*lplpenumOleVerb = NULL;
/* A pseudo object may NOT return OLE_S_USEREG; they must call the
** OleReg* API or provide their own implementation. Because this
** pseudo object does NOT implement IPersist, simply a low-level
** remoting handler (ProxyManager) object as opposed to a
** DefHandler object is used as the handler for the pseudo
** object in a clients process space. The ProxyManager does NOT
** handle the OLE_S_USEREG return values.
*/
return OleRegEnumVerbs((REFCLSID)&CLSID_APP, lplpenumOleVerb);
}
STDMETHODIMP PseudoObj_OleObj_Update(LPOLEOBJECT lpThis)
{
OleDbgOut2("PseudoObj_OleObj_Update\r\n");
/* OLE2NOTE: a server-only app is always "up-to-date".
** a container-app which contains links where the link source
** has changed since the last update of the link would be
** considered "out-of-date". the "Update" method instructs the
** object to get an update from any out-of-date links.
*/
return NOERROR;
}
STDMETHODIMP PseudoObj_OleObj_IsUpToDate(LPOLEOBJECT lpThis)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
OleDbgOut2("PseudoObj_OleObj_IsUpToDate\r\n");
/* OLE2NOTE: a server-only app is always "up-to-date".
** a container-app which contains links where the link source
** has changed since the last update of the link would be
** considered "out-of-date".
*/
return NOERROR;
}
STDMETHODIMP PseudoObj_OleObj_GetUserClassID(
LPOLEOBJECT lpThis,
LPCLSID lpclsid
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpPseudoObj->m_lpDoc;
OleDbgOut2("PseudoObj_OleObj_GetUserClassID\r\n");
/* OLE2NOTE: we must be carefull to return the correct CLSID here.
** if we are currently preforming a "TreatAs (aka. ActivateAs)"
** operation then we need to return the class of the object
** written in the storage of the object. otherwise we would
** return our own class id.
*/
return ServerDoc_GetClassID(lpServerDoc, lpclsid);
}
STDMETHODIMP PseudoObj_OleObj_GetUserTypeA(
LPOLEOBJECT lpThis,
DWORD dwFormOfType,
LPSTR FAR* lpszUserType
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpPseudoObj->m_lpDoc;
OleDbgOut2("PseudoObj_OleObj_GetUserType\r\n");
/* OLE2NOTE: we must make sure to set all out parameters to NULL. */
*lpszUserType = NULL;
/* OLE2NOTE: we must be carefull to return the correct user type here.
** if we are currently preforming a "TreatAs (aka. ActivateAs)"
** operation then we need to return the user type name that
** corresponds to the class of the object we are currently
** emmulating. otherwise we should return our normal user type
** name corresponding to our own class. This routine determines
** the current clsid in effect.
**
** A pseudo object may NOT return OLE_S_USEREG; they must call the
** OleReg* API or provide their own implementation. Because this
** pseudo object does NOT implement IPersist, simply a low-level
** remoting handler (ProxyManager) object as opposed to a
** DefHandler object is used as the handler for the pseudo
** object in a clients process space. The ProxyManager does NOT
** handle the OLE_S_USEREG return values.
*/
#if defined( SVR_TREATAS )
if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL) )
return OleRegGetUserTypeA(
&lpServerDoc->m_clsidTreatAs,dwFormOfType,lpszUserType);
else
#endif // SVR_TREATAS
return OleRegGetUserTypeA(&CLSID_APP, dwFormOfType, lpszUserType);
}
STDMETHODIMP PseudoObj_OleObj_GetUserType(
LPOLEOBJECT lpThis,
DWORD dwFormOfType,
LPOLESTR FAR* lpszUserType
)
{
LPSTR pstr;
HRESULT hr = PseudoObj_OleObj_GetUserTypeA(lpThis, dwFormOfType, &pstr);
CopyAndFreeSTR(pstr, lpszUserType);
return hr;
}
STDMETHODIMP PseudoObj_OleObj_SetExtent(
LPOLEOBJECT lpThis,
DWORD dwDrawAspect,
LPSIZEL lplgrc
)
{
OleDbgOut2("PseudoObj_OleObj_SetExtent\r\n");
// OLE2NOTE: a pseudo object does NOT support SetExtent
return ResultFromScode(E_FAIL);
}
STDMETHODIMP PseudoObj_OleObj_GetExtent(
LPOLEOBJECT lpThis,
DWORD dwDrawAspect,
LPSIZEL lpsizel
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
OleDbgOut2("PseudoObj_OleObj_GetExtent\r\n");
/* OLE2NOTE: it is VERY important to check which aspect the caller
** is asking about. an object implemented by a server EXE MAY
** fail to return extents when asked for DVASPECT_ICON.
*/
if (dwDrawAspect == DVASPECT_CONTENT) {
PseudoObj_GetExtent(lpPseudoObj, lpsizel);
return NOERROR;
}
else
{
return ResultFromScode(E_FAIL);
}
}
STDMETHODIMP PseudoObj_OleObj_Advise(
LPOLEOBJECT lpThis,
LPADVISESINK lpAdvSink,
LPDWORD lpdwConnection
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
HRESULT hrErr;
SCODE sc;
OLEDBG_BEGIN2("PseudoObj_OleObj_Advise\r\n");
if (lpPseudoObj->m_lpOleAdviseHldr == NULL &&
CreateOleAdviseHolder(&lpPseudoObj->m_lpOleAdviseHldr) != NOERROR) {
sc = E_OUTOFMEMORY;
goto error;
}
OLEDBG_BEGIN2("IOleAdviseHolder::Advise called\r\n")
hrErr = lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->Advise(
lpPseudoObj->m_lpOleAdviseHldr,
lpAdvSink,
lpdwConnection
);
OLEDBG_END2
OLEDBG_END2
return hrErr;
error:
OLEDBG_END2
return ResultFromScode(sc);
}
STDMETHODIMP PseudoObj_OleObj_Unadvise(LPOLEOBJECT lpThis, DWORD dwConnection)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
HRESULT hrErr;
SCODE sc;
OLEDBG_BEGIN2("PseudoObj_OleObj_Unadvise\r\n");
if (lpPseudoObj->m_lpOleAdviseHldr == NULL) {
sc = E_FAIL;
goto error;
}
OLEDBG_BEGIN2("IOleAdviseHolder::Unadvise called\r\n")
hrErr = lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->Unadvise(
lpPseudoObj->m_lpOleAdviseHldr,
dwConnection
);
OLEDBG_END2
OLEDBG_END2
return hrErr;
error:
OLEDBG_END2
return ResultFromScode(sc);
}
STDMETHODIMP PseudoObj_OleObj_EnumAdvise(
LPOLEOBJECT lpThis,
LPENUMSTATDATA FAR* lplpenumAdvise
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
HRESULT hrErr;
SCODE sc;
OLEDBG_BEGIN2("PseudoObj_OleObj_EnumAdvise\r\n");
/* OLE2NOTE: we must make sure to set all out parameters to NULL. */
*lplpenumAdvise = NULL;
if (lpPseudoObj->m_lpOleAdviseHldr == NULL) {
sc = E_FAIL;
goto error;
}
OLEDBG_BEGIN2("IOleAdviseHolder::EnumAdvise called\r\n")
hrErr = lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->EnumAdvise(
lpPseudoObj->m_lpOleAdviseHldr,
lplpenumAdvise
);
OLEDBG_END2
OLEDBG_END2
return hrErr;
error:
OLEDBG_END2
return ResultFromScode(sc);
}
STDMETHODIMP PseudoObj_OleObj_GetMiscStatus(
LPOLEOBJECT lpThis,
DWORD dwAspect,
DWORD FAR* lpdwStatus
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpPseudoObj->m_lpDoc;
OleDbgOut2("PseudoObj_OleObj_GetMiscStatus\r\n");
/* Get our default MiscStatus for the given Aspect. this
** information is registered in the RegDB. We query the RegDB
** here to guarantee that the value returned from this method
** agrees with the values in RegDB. in this way we only have to
** maintain the info in one place (in the RegDB). Alternatively
** we could have the values hard coded here.
**
** OLE2NOTE: A pseudo object may NOT return OLE_S_USEREG; they must
** call the
** OleReg* API or provide their own implementation. Because this
** pseudo object does NOT implement IPersist, simply a low-level
** remoting handler (ProxyManager) object as opposed to a
** DefHandler object is used as the handler for the pseudo
** object in a clients process space. The ProxyManager does NOT
** handle the OLE_S_USEREG return values.
*/
OleRegGetMiscStatus((REFCLSID)&CLSID_APP, dwAspect, lpdwStatus);
/* OLE2NOTE: check if the pseudo object is compatible to be
** linked by an OLE 1.0 container. it is compatible if
** either the pseudo object is an untitled document or a
** file-based document. if the pseudo object is part of
** an embedded object, then it is NOT compatible to be
** linked by an OLE 1.0 container. if it is compatible then
** we should include OLEMISC_CANLINKBYOLE1 as part of the
** dwStatus flags.
*/
if (lpOutlineDoc->m_docInitType == DOCTYPE_NEW ||
lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE)
*lpdwStatus |= OLEMISC_CANLINKBYOLE1;
return NOERROR;
}
STDMETHODIMP PseudoObj_OleObj_SetColorScheme(
LPOLEOBJECT lpThis,
LPLOGPALETTE lpLogpal
)
{
OleDbgOut2("PseudoObj_OleObj_SetColorScheme\r\n");
// REVIEW: NOT YET IMPLEMENTED
return ResultFromScode(E_NOTIMPL);
}
/*************************************************************************
** PseudoObj::IDataObject interface implementation
*************************************************************************/
STDMETHODIMP PseudoObj_DataObj_QueryInterface (
LPDATAOBJECT lpThis,
REFIID riid,
LPVOID FAR* lplpvObj
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObj);
}
STDMETHODIMP_(ULONG) PseudoObj_DataObj_AddRef(LPDATAOBJECT lpThis)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
OleDbgAddRefMethod(lpThis, "IDataObject");
return PseudoObj_AddRef((LPPSEUDOOBJ)lpPseudoObj);
}
STDMETHODIMP_(ULONG) PseudoObj_DataObj_Release (LPDATAOBJECT lpThis)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
OleDbgReleaseMethod(lpThis, "IDataObject");
return PseudoObj_Release((LPPSEUDOOBJ)lpPseudoObj);
}
STDMETHODIMP PseudoObj_DataObj_GetData (
LPDATAOBJECT lpThis,
LPFORMATETC lpformatetc,
LPSTGMEDIUM lpMedium
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
LINERANGE lrSel;
SCODE sc = S_OK;
OLEDBG_BEGIN2("PseudoObj_DataObj_GetData\r\n")
PseudoObj_GetSel(lpPseudoObj, &lrSel);
/* OLE2NOTE: we must make sure to set all out parameters to NULL. */
lpMedium->tymed = TYMED_NULL;
lpMedium->pUnkForRelease = NULL; // we transfer ownership to caller
lpMedium->hGlobal = NULL;
if (lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) {
// Verify caller asked for correct medium
if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
sc = DATA_E_FORMATETC;
goto error;
}
lpMedium->hGlobal = OutlineDoc_GetOutlineData (lpOutlineDoc,&lrSel);
if (! lpMedium->hGlobal) return ResultFromScode(E_OUTOFMEMORY);
lpMedium->tymed = TYMED_HGLOBAL;
OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_OUTLINE\r\n");
} else if(lpformatetc->cfFormat == CF_METAFILEPICT &&
(lpformatetc->dwAspect & DVASPECT_CONTENT) ) {
// Verify caller asked for correct medium
if (!(lpformatetc->tymed & TYMED_MFPICT)) {
sc = DATA_E_FORMATETC;
goto error;
}
lpMedium->hGlobal=ServerDoc_GetMetafilePictData(lpServerDoc,&lrSel);
if (! lpMedium->hGlobal) {
sc = E_OUTOFMEMORY;
goto error;
}
lpMedium->tymed = TYMED_MFPICT;
OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_METAFILEPICT\r\n");
} else if (lpformatetc->cfFormat == CF_METAFILEPICT &&
(lpformatetc->dwAspect & DVASPECT_ICON) ) {
CLSID clsid;
// Verify caller asked for correct medium
if (!(lpformatetc->tymed & TYMED_MFPICT)) {
sc = DATA_E_FORMATETC;
goto error;
}
/* OLE2NOTE: we should return the default icon for our class.
** we must be carefull to use the correct CLSID here.
** if we are currently preforming a "TreatAs (aka. ActivateAs)"
** operation then we need to use the class of the object
** written in the storage of the object. otherwise we would
** use our own class id.
*/
if (ServerDoc_GetClassID(lpServerDoc, (LPCLSID)&clsid) != NOERROR) {
sc = DATA_E_FORMATETC;
goto error;
}
lpMedium->hGlobal=GetIconOfClass(
g_lpApp->m_hInst,(REFCLSID)&clsid, NULL, FALSE);
if (! lpMedium->hGlobal) {
sc = E_OUTOFMEMORY;
goto error;
}
lpMedium->tymed = TYMED_MFPICT;
OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_METAFILEPICT (icon)\r\n");
return NOERROR;
} else if (lpformatetc->cfFormat == CF_TEXT) {
// Verify caller asked for correct medium
if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
sc = DATA_E_FORMATETC;
goto error;
}
lpMedium->hGlobal = OutlineDoc_GetTextData (lpOutlineDoc, &lrSel);
if (! lpMedium->hGlobal) {
sc = E_OUTOFMEMORY;
goto error;
}
lpMedium->tymed = TYMED_HGLOBAL;
OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_TEXT\r\n");
} else {
sc = DATA_E_FORMATETC;
goto error;
}
OLEDBG_END2
return NOERROR;
error:
OLEDBG_END2
return ResultFromScode(sc);
}
STDMETHODIMP PseudoObj_DataObj_GetDataHere (
LPDATAOBJECT lpThis,
LPFORMATETC lpformatetc,
LPSTGMEDIUM lpMedium
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
OleDbgOut("PseudoObj_DataObj_GetDataHere\r\n");
/* Caller is requesting data to be returned in Caller allocated
** medium, but we do NOT support this. we only support
** global memory blocks that WE allocate for the caller.
*/
return ResultFromScode(DATA_E_FORMATETC);
}
STDMETHODIMP PseudoObj_DataObj_QueryGetData (
LPDATAOBJECT lpThis,
LPFORMATETC lpformatetc
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
OleDbgOut2("PseudoObj_DataObj_QueryGetData\r\n");
/* Caller is querying if we support certain format but does not
** want any data actually returned.
*/
if (lpformatetc->cfFormat == CF_METAFILEPICT &&
(lpformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON)) ) {
return OleStdQueryFormatMedium(lpformatetc, TYMED_MFPICT);
} else if (lpformatetc->cfFormat == (lpOutlineApp)->m_cfOutline ||
lpformatetc->cfFormat == CF_TEXT) {
return OleStdQueryFormatMedium(lpformatetc, TYMED_HGLOBAL);
}
return ResultFromScode(DATA_E_FORMATETC);
}
STDMETHODIMP PseudoObj_DataObj_GetCanonicalFormatEtc(
LPDATAOBJECT lpThis,
LPFORMATETC lpformatetc,
LPFORMATETC lpformatetcOut
)
{
HRESULT hrErr;
OleDbgOut2("PseudoObj_DataObj_GetCanonicalFormatEtc\r\n");
if (!lpformatetcOut)
return ResultFromScode(E_INVALIDARG);
/* OLE2NOTE: we must make sure to set all out parameters to NULL. */
lpformatetcOut->ptd = NULL;
if (!lpformatetc)
return ResultFromScode(E_INVALIDARG);
// OLE2NOTE: we must validate that the format requested is supported
if ((hrErr=lpThis->lpVtbl->QueryGetData(lpThis,lpformatetc)) != NOERROR)
return hrErr;
/* OLE2NOTE: an app that is insensitive to target device (as the
** Outline Sample is) should fill in the lpformatOut parameter
** but NULL out the "ptd" field; it should return NOERROR if the
** input formatetc->ptd what non-NULL. this tells the caller
** that it is NOT necessary to maintain a separate screen
** rendering and printer rendering. if should return
** DATA_S_SAMEFORMATETC if the input and output formatetc's are
** identical.
*/
*lpformatetcOut = *lpformatetc;
if (lpformatetc->ptd == NULL)
return ResultFromScode(DATA_S_SAMEFORMATETC);
else {
lpformatetcOut->ptd = NULL;
return NOERROR;
}
}
STDMETHODIMP PseudoObj_DataObj_SetData (
LPDATAOBJECT lpThis,
LPFORMATETC lpformatetc,
LPSTGMEDIUM lpmedium,
BOOL fRelease
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
OleDbgOut2("PseudoObj_DataObj_SetData\r\n");
// REVIEW: NOT-YET-IMPLEMENTED
return ResultFromScode(E_NOTIMPL);
}
STDMETHODIMP PseudoObj_DataObj_EnumFormatEtc(
LPDATAOBJECT lpThis,
DWORD dwDirection,
LPENUMFORMATETC FAR* lplpenumFormatEtc
)
{
SCODE sc;
OleDbgOut2("PseudoObj_DataObj_EnumFormatEtc\r\n");
/* OLE2NOTE: a pseudo object only needs to enumerate the static list
** of formats that are registered for our app in the
** registration database. it is NOT
** required that a pseudo object (ie. non-DataTransferDoc)
** enumerate the OLE formats: CF_LINKSOURCE, CF_EMBEDSOURCE, or
** CF_EMBEDDEDOBJECT. we do NOT use pseudo objects for data
** transfers.
**
** A pseudo object may NOT return OLE_S_USEREG; they must call the
** OleReg* API or provide their own implementation. Because this
** pseudo object does NOT implement IPersist, simply a low-level
** remoting handler (ProxyManager) object as opposed to a
** DefHandler object is used as the handler for the pseudo
** object in a clients process space. The ProxyManager does NOT
** handle the OLE_S_USEREG return values.
*/
if (dwDirection == DATADIR_GET)
return OleRegEnumFormatEtc(
(REFCLSID)&CLSID_APP, dwDirection, lplpenumFormatEtc);
else if (dwDirection == DATADIR_SET)
sc = E_NOTIMPL;
else
sc = E_INVALIDARG;
return ResultFromScode(sc);
}
STDMETHODIMP PseudoObj_DataObj_DAdvise(
LPDATAOBJECT lpThis,
FORMATETC FAR* lpFormatetc,
DWORD advf,
LPADVISESINK lpAdvSink,
DWORD FAR* lpdwConnection
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
HRESULT hrErr;
SCODE sc;
OLEDBG_BEGIN2("PseudoObj_DataObj_DAdvise\r\n")
/* OLE2NOTE: we must make sure to set all out parameters to NULL. */
*lpdwConnection = 0;
/* OLE2NOTE: we should validate if the caller is setting up an
** Advise for a data type that we support. we must
** explicitly allow an advise for the "wildcard" advise.
*/
if ( !( lpFormatetc->cfFormat == 0 &&
lpFormatetc->ptd == NULL &&
lpFormatetc->dwAspect == -1L &&
lpFormatetc->lindex == -1L &&
lpFormatetc->tymed == -1L) &&
(hrErr = PseudoObj_DataObj_QueryGetData(lpThis, lpFormatetc))
!= NOERROR) {
sc = GetScode(hrErr);
goto error;
}
if (lpPseudoObj->m_lpDataAdviseHldr == NULL &&
CreateDataAdviseHolder(&lpPseudoObj->m_lpDataAdviseHldr) != NOERROR) {
sc = E_OUTOFMEMORY;
goto error;
}
OLEDBG_BEGIN2("IOleAdviseHolder::Advise called\r\n")
hrErr = lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->Advise(
lpPseudoObj->m_lpDataAdviseHldr,
(LPDATAOBJECT)&lpPseudoObj->m_DataObject,
lpFormatetc,
advf,
lpAdvSink,
lpdwConnection
);
OLEDBG_END2
OLEDBG_END2
return hrErr;
error:
OLEDBG_END2
return ResultFromScode(sc);
}
STDMETHODIMP PseudoObj_DataObj_DUnadvise(LPDATAOBJECT lpThis, DWORD dwConnection)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
HRESULT hrErr;
SCODE sc;
OLEDBG_BEGIN2("PseudoObj_DataObj_Unadvise\r\n");
// no one registered
if (lpPseudoObj->m_lpDataAdviseHldr == NULL) {
sc = E_FAIL;
goto error;
}
OLEDBG_BEGIN2("IOleAdviseHolder::DUnadvise called\r\n")
hrErr = lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->Unadvise(
lpPseudoObj->m_lpDataAdviseHldr,
dwConnection
);
OLEDBG_END2
OLEDBG_END2
return hrErr;
error:
OLEDBG_END2
return ResultFromScode(sc);
}
STDMETHODIMP PseudoObj_DataObj_EnumAdvise(
LPDATAOBJECT lpThis,
LPENUMSTATDATA FAR* lplpenumAdvise
)
{
LPPSEUDOOBJ lpPseudoObj =
((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
HRESULT hrErr;
SCODE sc;
OLEDBG_BEGIN2("PseudoObj_DataObj_EnumAdvise\r\n");
/* OLE2NOTE: we must make sure to set all out parameters to NULL. */
*lplpenumAdvise = NULL;
if (lpPseudoObj->m_lpDataAdviseHldr == NULL) {
sc = E_FAIL;
goto error;
}
OLEDBG_BEGIN2("IOleAdviseHolder::EnumAdvise called\r\n")
hrErr = lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->EnumAdvise(
lpPseudoObj->m_lpDataAdviseHldr,
lplpenumAdvise
);
OLEDBG_END2
OLEDBG_END2
return hrErr;
error:
OLEDBG_END2
return ResultFromScode(sc);
}