mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
686 lines
16 KiB
686 lines
16 KiB
/*++
|
|
|
|
Copyright (C) 1993-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ioleobj.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of the IOleObject interface for Polyline. Some of
|
|
these just pass through to the default handler which does default
|
|
implementations.
|
|
|
|
--*/
|
|
|
|
#include "polyline.h"
|
|
#include "unkhlpr.h"
|
|
#include "utils.h"
|
|
#include "unihelpr.h"
|
|
|
|
void RegisterAsRunning(IUnknown *pUnk, IMoniker *pmk,
|
|
DWORD dwFlags, LPDWORD pdwReg);
|
|
|
|
/*
|
|
* CImpIOleObject interface implementation
|
|
*/
|
|
|
|
IMPLEMENT_CONTAINED_CONSTRUCTOR(CPolyline, CImpIOleObject)
|
|
IMPLEMENT_CONTAINED_DESTRUCTOR(CImpIOleObject)
|
|
|
|
IMPLEMENT_CONTAINED_QUERYINTERFACE(CImpIOleObject)
|
|
IMPLEMENT_CONTAINED_ADDREF(CImpIOleObject)
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CImpIOleObject::Release(
|
|
void
|
|
)
|
|
{
|
|
--m_cRef;
|
|
|
|
#if 0
|
|
// Release cached site related interfaces
|
|
if (m_cRef == 0) {
|
|
ReleaseInterface(m_pObj->m_pIOleClientSite);
|
|
ReleaseInterface(m_pObj->m_pIOleControlSite);
|
|
ReleaseInterface(m_pObj->m_pIDispatchAmbients);
|
|
}
|
|
#endif
|
|
|
|
return m_pUnkOuter->Release();
|
|
}
|
|
|
|
/*
|
|
* CImpIOleObject::SetClientSite
|
|
* CImpIOleObject::GetClientSite
|
|
*
|
|
* Purpose:
|
|
* Manages the IOleClientSite pointer of our container.
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::SetClientSite (LPOLECLIENTSITE pIOleClientSite)
|
|
{
|
|
ReleaseInterface(m_pObj->m_pIOleClientSite);
|
|
ReleaseInterface(m_pObj->m_pIOleControlSite);
|
|
ReleaseInterface(m_pObj->m_pIDispatchAmbients);
|
|
|
|
m_pObj->m_pIOleClientSite = pIOleClientSite;
|
|
|
|
if (NULL != m_pObj->m_pIOleClientSite) {
|
|
HRESULT hr;
|
|
LPMONIKER pmk;
|
|
LPOLECONTAINER pIOleCont;
|
|
|
|
m_pObj->m_pIOleClientSite->AddRef();
|
|
|
|
/*
|
|
* Within IRunnableObject::Run we're supposed to register
|
|
* ourselves as running...however, the moniker has to come
|
|
* from the container's IOleClientSite::GetMoniker. But
|
|
* Run is called before SetClientSite here, so we have to
|
|
* register now that we do have the client site as well
|
|
* as lock the container.
|
|
*/
|
|
|
|
hr = m_pObj->m_pIOleClientSite->GetMoniker
|
|
(OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL, &pmk);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
RegisterAsRunning(m_pUnkOuter, pmk, 0, &m_pObj->m_dwRegROT);
|
|
pmk->Release();
|
|
}
|
|
|
|
hr = m_pObj->m_pIOleClientSite->GetContainer(&pIOleCont);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
m_pObj->m_fLockContainer=TRUE;
|
|
pIOleCont->LockContainer(TRUE);
|
|
pIOleCont->Release();
|
|
}
|
|
|
|
/*
|
|
* Go get the container's IDispatch for ambient
|
|
* properties if it has one, and initilize ourself
|
|
* with those properties.
|
|
*/
|
|
hr = m_pObj->m_pIOleClientSite->QueryInterface(IID_IDispatch
|
|
, (void **)&m_pObj->m_pIDispatchAmbients);
|
|
|
|
if (SUCCEEDED(hr))
|
|
m_pObj->AmbientsInitialize((ULONG)INITAMBIENT_ALL);
|
|
/*
|
|
* Get the control site
|
|
*/
|
|
hr = m_pObj->m_pIOleClientSite->QueryInterface(IID_IOleControlSite, (void **)&m_pObj->m_pIOleControlSite);
|
|
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CImpIOleObject::GetClientSite(LPOLECLIENTSITE *ppSite)
|
|
{
|
|
//Be sure to AddRef the new pointer you are giving away.
|
|
*ppSite=m_pObj->m_pIOleClientSite;
|
|
m_pObj->m_pIOleClientSite->AddRef();
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CImpIOleObject::SetHostNames
|
|
*
|
|
* Purpose:
|
|
* Provides the object with names of the container application and
|
|
* the object in the container to use in object user interface.
|
|
*
|
|
* Parameters:
|
|
* pszApp LPCOLESTR of the container application.
|
|
* pszObj LPCOLESTR of some name that is useful in window
|
|
* titles.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::SetHostNames(LPCOLESTR /* pszApp */
|
|
, LPCOLESTR /* pszObj */)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CImpIOleObject::Close
|
|
*
|
|
* Purpose:
|
|
* Forces the object to close down its user interface and unload.
|
|
*
|
|
* Parameters:
|
|
* dwSaveOption DWORD describing the circumstances under which
|
|
* the object is being saved and closed.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR or a general error value.
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::Close(DWORD dwSaveOption)
|
|
{
|
|
BOOL fSave=FALSE;
|
|
|
|
//If object is dirty and we're asked to save, save it and close.
|
|
if (OLECLOSE_SAVEIFDIRTY==dwSaveOption && m_pObj->m_fDirty)
|
|
fSave=TRUE;
|
|
|
|
/*
|
|
* If asked to prompt, only do so if dirty, then if we get a
|
|
* YES, save as usual and close. On NO, just close. On
|
|
* CANCEL return OLE_E_PROMPTSAVECANCELLED.
|
|
*/
|
|
if (OLECLOSE_PROMPTSAVE==dwSaveOption && m_pObj->m_fDirty) {
|
|
UINT uRet;
|
|
|
|
uRet = MessageBox(NULL, ResourceString(IDS_CLOSEPROMPT),
|
|
ResourceString(IDS_CLOSECAPTION), MB_YESNOCANCEL);
|
|
|
|
if (IDCANCEL==uRet)
|
|
return ResultFromScode(OLE_E_PROMPTSAVECANCELLED);
|
|
|
|
if (IDYES==uRet)
|
|
fSave=TRUE;
|
|
}
|
|
|
|
if (fSave) {
|
|
m_pObj->SendAdvise(OBJECTCODE_SAVEOBJECT);
|
|
m_pObj->SendAdvise(OBJECTCODE_SAVED);
|
|
}
|
|
|
|
//We get directly here on OLECLOSE_NOSAVE.
|
|
if ( m_pObj->m_fLockContainer && ( NULL != m_pObj->m_pIOleClientSite ) ) {
|
|
|
|
//Match LockContainer call from SetClientSite
|
|
LPOLECONTAINER pIOleCont;
|
|
|
|
if (SUCCEEDED(m_pObj->m_pIOleClientSite->GetContainer(&pIOleCont))) {
|
|
pIOleCont->LockContainer(FALSE);
|
|
pIOleCont->Release();
|
|
}
|
|
}
|
|
|
|
// Deactivate
|
|
m_pObj->InPlaceDeactivate();
|
|
|
|
// Revoke registration in ROT
|
|
if (m_pObj->m_dwRegROT != 0) {
|
|
|
|
IRunningObjectTable *pROT;
|
|
|
|
if (!FAILED(GetRunningObjectTable(0, &pROT))) {
|
|
pROT->Revoke(m_pObj->m_dwRegROT);
|
|
pROT->Release();
|
|
m_pObj->m_dwRegROT = 0;
|
|
}
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CImpIOleObject::DoVerb
|
|
*
|
|
* Purpose:
|
|
* Executes an object-defined action.
|
|
*
|
|
* Parameters:
|
|
* iVerb LONG index of the verb to execute.
|
|
* pMSG LPMSG describing the event causing the
|
|
* activation.
|
|
* pActiveSite LPOLECLIENTSITE to the site involved.
|
|
* lIndex LONG the piece on which execution is happening.
|
|
* hWndParent HWND of the window in which the object can play
|
|
* in-place.
|
|
* pRectPos LPRECT of the object in hWndParent where the
|
|
* object can play in-place if desired.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR or a general error value.
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::DoVerb(LONG iVerb, LPMSG /* pMSG */
|
|
, LPOLECLIENTSITE pActiveSite, LONG /* lIndex */, HWND /* hWndParent */
|
|
, LPCRECT /* pRectPos */)
|
|
{
|
|
HRESULT hr;
|
|
CAUUID caGUID;
|
|
|
|
USES_CONVERSION
|
|
|
|
switch (iVerb)
|
|
{
|
|
case OLEIVERB_HIDE:
|
|
if (NULL != m_pObj->m_pIOleIPSite) {
|
|
m_pObj->UIDeactivate();
|
|
ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE);
|
|
}
|
|
else {
|
|
|
|
ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE);
|
|
m_pObj->SendAdvise(OBJECTCODE_HIDEWINDOW);
|
|
}
|
|
break;
|
|
|
|
case OLEIVERB_PRIMARY:
|
|
case OLEIVERB_SHOW:
|
|
if (NULL != m_pObj->m_pIOleIPSite) {
|
|
ShowWindow(m_pObj->m_pHW->Window(), SW_SHOW);
|
|
return NOERROR; //Already active
|
|
}
|
|
|
|
if (m_pObj->m_fAllowInPlace) {
|
|
return m_pObj->InPlaceActivate(pActiveSite ,TRUE);
|
|
}
|
|
|
|
return ResultFromScode(OLEOBJ_S_INVALIDVERB);
|
|
break;
|
|
|
|
case OLEIVERB_INPLACEACTIVATE:
|
|
if (NULL != m_pObj->m_pHW) {
|
|
HWND hWndHW=m_pObj->m_pHW->Window();
|
|
|
|
ShowWindow(hWndHW, SW_SHOW);
|
|
SetFocus(hWndHW);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
/*
|
|
* Only inside-out supporting containers will use
|
|
* this verb.
|
|
*/
|
|
m_pObj->m_fContainerKnowsInsideOut=TRUE;
|
|
m_pObj->InPlaceActivate(pActiveSite, FALSE);
|
|
break;
|
|
|
|
case OLEIVERB_UIACTIVATE:
|
|
m_pObj->InPlaceActivate(pActiveSite, TRUE);
|
|
break;
|
|
|
|
case OLEIVERB_PROPERTIES:
|
|
case POLYLINEVERB_PROPERTIES:
|
|
|
|
/*
|
|
* Let the container try first if there are
|
|
* extended controls. Otherwise we'll display
|
|
* our own pages.
|
|
*/
|
|
if (NULL!=m_pObj->m_pIOleControlSite) {
|
|
hr=m_pObj->m_pIOleControlSite->ShowPropertyFrame();
|
|
|
|
if (NOERROR==hr)
|
|
break; //All done
|
|
}
|
|
|
|
|
|
//Put up our property pages.
|
|
hr=m_pObj->m_pImpISpecifyPP->GetPages(&caGUID);
|
|
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
|
|
hr=OleCreatePropertyFrame(m_pObj->m_pCtrl->Window(), 10, 10
|
|
, T2W(ResourceString(IDS_PROPFRM_TITLE)), 1, (IUnknown **)&m_pObj
|
|
, caGUID.cElems, caGUID.pElems
|
|
, LOCALE_USER_DEFAULT, 0L, NULL);
|
|
|
|
//Free the GUIDs
|
|
CoTaskMemFree((void *)caGUID.pElems);
|
|
break;
|
|
|
|
default:
|
|
return ResultFromScode(OLEOBJ_S_INVALIDVERB);
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CImpIOleObject::GetUserClassID
|
|
*
|
|
* Purpose:
|
|
* Used for linked objects, this returns the class ID of what end
|
|
* users think they are editing.
|
|
*
|
|
* Parameters:
|
|
* pClsID LPCLSID in which to store the CLSID.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR or a general error value.
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::GetUserClassID(LPCLSID pClsID)
|
|
{
|
|
/*
|
|
* If you are not registered to handle data other than yourself,
|
|
* then you can just return your class ID here. If you are
|
|
* registered as usable from Treat-As dialogs, then you need to
|
|
* return the CLSID of what you are really editing.
|
|
*/
|
|
|
|
*pClsID=CLSID_SystemMonitor;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CImpIOleObject::SetExtent
|
|
*
|
|
* Purpose:
|
|
* Sets the size of the object in HIMETRIC units.
|
|
*
|
|
* Parameters:
|
|
* dwAspect DWORD of the aspect affected.
|
|
* pszl LPSIZEL containing the new size.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR or a general error value.
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::SetExtent(
|
|
DWORD dwAspect,
|
|
LPSIZEL pszl )
|
|
{
|
|
|
|
RECT rectExt;
|
|
|
|
if (dwAspect == DVASPECT_CONTENT) {
|
|
// convert from HIMETRIC to device coord
|
|
SetRect(&rectExt, 0, 0, pszl->cx, pszl->cy);
|
|
m_pObj->RectConvertMappings(&rectExt,TRUE);
|
|
|
|
// If changed and non-zero, store as new extent
|
|
|
|
if ( !EqualRect ( &m_pObj->m_RectExt, &rectExt )
|
|
&& !IsRectEmpty( &rectExt ) ) {
|
|
m_pObj->m_RectExt = rectExt;
|
|
|
|
m_pObj->m_pImpIPolyline->SizeSet(&rectExt, TRUE);
|
|
// Notify container of change to force metafile update
|
|
//m_pObj->SendAdvise(OBJECTCODE_DATACHANGED);
|
|
}
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
/*
|
|
* CImpIOleObject::GetExtent
|
|
*
|
|
* Purpose:
|
|
* Retrieves the size of the object in HIMETRIC units.
|
|
*
|
|
* Parameters:
|
|
* dwAspect DWORD of the aspect requested
|
|
* pszl LPSIZEL into which to store the size.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR or a general error value.
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::GetExtent(DWORD dwAspect, LPSIZEL pszl)
|
|
{
|
|
//Delegate directly to IViewObject2::GetExtent
|
|
return m_pObj->m_pImpIViewObject->GetExtent(dwAspect, -1
|
|
, NULL, pszl);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CImpIOleObject::Advise
|
|
* CImpIOleObject::Unadvise
|
|
* CImpIOleObject::EnumAdvise
|
|
*
|
|
* Purpose:
|
|
* Advisory connection functions.
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::Advise(
|
|
LPADVISESINK pIAdviseSink,
|
|
LPDWORD pdwConn
|
|
)
|
|
{
|
|
if (NULL==m_pObj->m_pIOleAdviseHolder)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr=CreateOleAdviseHolder(&m_pObj->m_pIOleAdviseHolder);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
|
|
return m_pObj->m_pIOleAdviseHolder->Advise(pIAdviseSink, pdwConn);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CImpIOleObject::Unadvise(DWORD dwConn)
|
|
{
|
|
if (NULL!=m_pObj->m_pIOleAdviseHolder)
|
|
return m_pObj->m_pIOleAdviseHolder->Unadvise(dwConn);
|
|
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CImpIOleObject::EnumAdvise(LPENUMSTATDATA *ppEnum)
|
|
{
|
|
if (NULL!=m_pObj->m_pIOleAdviseHolder)
|
|
return m_pObj->m_pIOleAdviseHolder->EnumAdvise(ppEnum);
|
|
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* CImpIOleObject::SetMoniker
|
|
*
|
|
* Purpose:
|
|
* Informs the object of its moniker or its container's moniker
|
|
* depending on dwWhich.
|
|
*
|
|
* Parameters:
|
|
* dwWhich DWORD describing whether the moniker is the
|
|
* object's or the container's.
|
|
* pmk LPMONIKER with the name.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR or a general error value.
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::SetMoniker(DWORD /* dwWhich */
|
|
, LPMONIKER /* pmk */)
|
|
{
|
|
LPMONIKER pmkFull;
|
|
HRESULT hr = ResultFromScode(E_FAIL);
|
|
HRESULT hrTmp;
|
|
LPBC pbc;
|
|
|
|
if (NULL!=m_pObj->m_pIOleClientSite) {
|
|
hr = m_pObj->m_pIOleClientSite->GetMoniker
|
|
(OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL
|
|
, &pmkFull);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hrTmp = CreateBindCtx(0,&pbc);
|
|
|
|
if (SUCCEEDED(hrTmp)) {
|
|
hrTmp = pmkFull->IsRunning(pbc, NULL, NULL);
|
|
pbc->Release();
|
|
|
|
if (hrTmp == NOERROR) {
|
|
pmkFull->Release();
|
|
return NOERROR;
|
|
}
|
|
}
|
|
|
|
//This will revoke the old one if m_dwRegROT is nonzero.
|
|
RegisterAsRunning(m_pUnkOuter, pmkFull, 0, &m_pObj->m_dwRegROT);
|
|
|
|
//Inform clients of the new moniker
|
|
if (NULL!=m_pObj->m_pIOleAdviseHolder)
|
|
m_pObj->m_pIOleAdviseHolder->SendOnRename(pmkFull);
|
|
|
|
pmkFull->Release();
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* CImpIOleObject::GetMoniker
|
|
*
|
|
* Purpose:
|
|
* Asks the object for a moniker that can later be used to
|
|
* reconnect to it.
|
|
*
|
|
* Parameters:
|
|
* dwAssign DWORD determining how to assign the moniker to
|
|
* to the object.
|
|
* dwWhich DWORD describing which moniker the caller wants.
|
|
* ppmk LPMONIKER * into which to store the moniker.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR or a general error value.
|
|
*/
|
|
|
|
STDMETHODIMP CImpIOleObject::GetMoniker(DWORD /* dwAssign */
|
|
, DWORD /* dwWhich */, LPMONIKER *ppmk)
|
|
{
|
|
HRESULT hr=ResultFromScode(E_FAIL);
|
|
|
|
*ppmk=NULL;
|
|
|
|
/*
|
|
* Since we only support embedded objects, our moniker
|
|
* is always the full moniker from the contianer.
|
|
*/
|
|
|
|
if (NULL!=m_pObj->m_pIOleClientSite)
|
|
{
|
|
hr=m_pObj->m_pIOleClientSite->GetMoniker
|
|
(OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL, ppmk);
|
|
}
|
|
|
|
return (NULL!=*ppmk) ? NOERROR : hr;
|
|
}
|
|
|
|
|
|
|
|
//Methods not implemented or trivial
|
|
STDMETHODIMP CImpIOleObject::InitFromData(
|
|
LPDATAOBJECT /* pIDataObject */
|
|
, BOOL /* fCreation */, DWORD /* dw */)
|
|
{
|
|
return ResultFromScode(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP CImpIOleObject::GetClipboardData(DWORD /* dwReserved */
|
|
, LPDATAOBJECT * /* ppIDataObj */)
|
|
{
|
|
return ResultFromScode(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP CImpIOleObject::Update(void)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CImpIOleObject::IsUpToDate(void)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CImpIOleObject::SetColorScheme(LPLOGPALETTE /* pLP */)
|
|
{
|
|
return ResultFromScode(E_NOTIMPL);
|
|
}
|
|
|
|
|
|
|
|
//Methods implemented using registry helper functions in OLE.
|
|
|
|
STDMETHODIMP CImpIOleObject::EnumVerbs(LPENUMOLEVERB *ppEnum)
|
|
{
|
|
return OleRegEnumVerbs(m_pObj->m_clsID, ppEnum);
|
|
}
|
|
|
|
STDMETHODIMP CImpIOleObject::GetUserType(
|
|
DWORD dwForm,
|
|
LPOLESTR *ppszType
|
|
)
|
|
{
|
|
return OleRegGetUserType(m_pObj->m_clsID, dwForm, ppszType);
|
|
}
|
|
|
|
STDMETHODIMP CImpIOleObject::GetMiscStatus(
|
|
DWORD dwAspect,
|
|
LPDWORD pdwStatus
|
|
)
|
|
{
|
|
return OleRegGetMiscStatus(m_pObj->m_clsID, dwAspect, pdwStatus);
|
|
}
|
|
|
|
|
|
void RegisterAsRunning(
|
|
IUnknown *pUnk,
|
|
IMoniker *pmk,
|
|
DWORD dwFlags,
|
|
LPDWORD pdwReg
|
|
)
|
|
{
|
|
IRunningObjectTable *pROT;
|
|
HRESULT hr;
|
|
DWORD dwReg = *pdwReg;
|
|
|
|
dwReg=*pdwReg;
|
|
|
|
if (FAILED(GetRunningObjectTable(0, &pROT)))
|
|
return;
|
|
|
|
hr = pROT->Register(dwFlags, pUnk, pmk, pdwReg);
|
|
|
|
if (MK_S_MONIKERALREADYREGISTERED == GetScode(hr))
|
|
{
|
|
if (0 != dwReg)
|
|
pROT->Revoke(dwReg);
|
|
}
|
|
|
|
pROT->Release();
|
|
|
|
return;
|
|
}
|
|
|