mirror of https://github.com/lianthony/NT4.0
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.
1336 lines
34 KiB
1336 lines
34 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996.
|
|
//
|
|
// File: classmon.cxx
|
|
//
|
|
// Contents: Implementation of CClassMoniker
|
|
//
|
|
// Classes: CClassMoniker
|
|
//
|
|
// Functions: CreateClassMoniker
|
|
//
|
|
// History: 22-Feb-96 ShannonC Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include <ole2int.h>
|
|
#include "classmon.hxx"
|
|
#include "mnk.h"
|
|
|
|
#ifndef OLETRACEIN
|
|
#define OLETRACEIN(x)
|
|
#endif
|
|
|
|
#ifndef OLETRACEOUT
|
|
#define OLETRACEOUT(x)
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateClassMoniker
|
|
//
|
|
// Synopsis: Creates a class moniker for the specified CLSID.
|
|
//
|
|
// Arguments: [rclsid] - Supplies the CLSID of the class.
|
|
// [ppmk] - Returns interface pointer of the new moniker.
|
|
//
|
|
// Returns: S_OK
|
|
// E_INVALIDARG
|
|
// E_OUTOFMEMORY
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDAPI CreateClassMoniker(
|
|
REFCLSID rclsid,
|
|
IMoniker **ppmk)
|
|
{
|
|
HRESULT hr;
|
|
CLSID clsid;
|
|
IMoniker *pmk;
|
|
|
|
__try
|
|
{
|
|
OLETRACEIN((API_CreateClassMoniker,
|
|
PARAMFMT("rclsid= %I, ppmk= %p"),
|
|
&rclsid, ppmk));
|
|
|
|
//Validate parameters.
|
|
*ppmk = NULL;
|
|
clsid = rclsid;
|
|
|
|
pmk = new CClassMoniker(clsid);
|
|
|
|
if (pmk != NULL)
|
|
{
|
|
*ppmk = pmk;
|
|
hr = S_OK;
|
|
CALLHOOKOBJECTCREATE(hr,
|
|
CLSID_ClassMoniker,
|
|
IID_IMoniker,
|
|
(IUnknown **)ppmk);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
}
|
|
|
|
OLETRACEOUT((API_CreateFileMoniker, hr));
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::CClassMoniker
|
|
//
|
|
// Synopsis: Constructor for class moniker.
|
|
//
|
|
// Arguments: rclsid - Supplies the CLSID of the class.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CClassMoniker::CClassMoniker(REFCLSID rclsid)
|
|
: _cRefs(1), _pExtra(NULL)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::CClassMoniker(%x,%I)\n",
|
|
this, &rclsid));
|
|
|
|
_data.clsid = rclsid;
|
|
_data.cbExtra = 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::~CClassMoniker
|
|
//
|
|
// Synopsis: Constructor for class moniker.
|
|
//
|
|
// Arguments: rclsid - Supplies the CLSID of the class.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CClassMoniker::~CClassMoniker()
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::~CClassMoniker(%x)\n",
|
|
this));
|
|
|
|
if(_pExtra != NULL)
|
|
{
|
|
PrivMemFree(_pExtra);
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::SetParameters
|
|
//
|
|
// Synopsis: Set the parameters on the class moniker
|
|
//
|
|
// Arguments: pszName - Name of the parameter.
|
|
// pszValue - Value of the parameter.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CClassMoniker::SetParameters(
|
|
LPCWSTR pszParameters)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//Free the old data.
|
|
if(_pExtra != NULL)
|
|
{
|
|
PrivMemFree(_pExtra);
|
|
_pExtra = NULL;
|
|
}
|
|
|
|
if(pszParameters != NULL)
|
|
{
|
|
_data.cbExtra = lstrlenW(pszParameters) * sizeof(WCHAR) + sizeof(WCHAR);
|
|
|
|
//Allocate memory for the extra bytes.
|
|
_pExtra = PrivMemAlloc(_data.cbExtra);
|
|
|
|
if(_pExtra != 0)
|
|
{
|
|
memcpy(_pExtra, pszParameters, _data.cbExtra);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::QueryInterface
|
|
//
|
|
// Synopsis: Gets a pointer to the specified interface. The class
|
|
// moniker supports the IMarshal, IMoniker, IPersistStream,
|
|
// IPersist, IROTData, and IUnknown interfaces. The class
|
|
// moniker also supports CLSID_ClassMoniker so that the
|
|
// IsEqual method can directly access the data members.
|
|
//
|
|
// Arguments: [iid] -- the requested interface
|
|
// [ppv] -- where to put the interface pointer
|
|
//
|
|
// Returns: S_OK
|
|
// E_INVALIDARG
|
|
// E_NOINTERFACE
|
|
//
|
|
// Notes: Bad parameters will raise an exception. The exception
|
|
// handler catches exceptions and returns E_INVALIDARG.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::QueryInterface(
|
|
REFIID riid,
|
|
void **ppv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
__try
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::QueryInterface(%x,%I,%x)\n",
|
|
this, &riid, ppv));
|
|
|
|
//Parameter validation.
|
|
*ppv = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IMarshal))
|
|
{
|
|
AddRef();
|
|
*ppv = (IMarshal *) this;
|
|
hr = S_OK;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IUnknown)
|
|
|| IsEqualIID(riid, IID_IMoniker)
|
|
|| IsEqualIID(riid, IID_IPersistStream)
|
|
|| IsEqualIID(riid, IID_IPersist))
|
|
{
|
|
AddRef();
|
|
*ppv = (IMoniker *) this;
|
|
hr = S_OK;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IROTData))
|
|
{
|
|
AddRef();
|
|
*ppv = (IROTData *) this;
|
|
hr = S_OK;
|
|
}
|
|
else if (IsEqualIID(riid, CLSID_ClassMoniker))
|
|
{
|
|
AddRef();
|
|
*ppv = (CClassMoniker *) this;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::AddRef
|
|
//
|
|
// Synopsis: Increment the reference count.
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Returns: ULONG -- the new reference count
|
|
//
|
|
// Notes: Use InterlockedIncrement to make it multi-thread safe.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CClassMoniker::AddRef(void)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::AddRef(%x)\n",
|
|
this));
|
|
|
|
InterlockedIncrement(&_cRefs);
|
|
return _cRefs;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::Release
|
|
//
|
|
// Synopsis: Decrement the reference count.
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Returns: ULONG -- the remaining reference count
|
|
//
|
|
// Notes: Use InterlockedDecrement to make it multi-thread safe.
|
|
// We use a local variable so that we don't access
|
|
// a data member after decrementing the reference count.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CClassMoniker::Release(void)
|
|
{
|
|
ULONG count = _cRefs - 1;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::Release(%x)\n",
|
|
this));
|
|
|
|
if(0 == InterlockedDecrement(&_cRefs))
|
|
{
|
|
delete this;
|
|
count = 0;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::GetClassID
|
|
//
|
|
// Synopsis: Gets the class ID of the object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::GetClassID(
|
|
CLSID *pClassID)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::GetClassID(%x,%x)\n",
|
|
this, pClassID));
|
|
|
|
__try
|
|
{
|
|
|
|
*pClassID = CLSID_ClassMoniker;
|
|
hr = S_OK;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::IsDirty
|
|
//
|
|
// Synopsis: Checks the object for changes since it was last saved.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::IsDirty()
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::IsDirty(%x)\n",
|
|
this));
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::Load
|
|
//
|
|
// Synopsis: Loads a class moniker from a stream
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::Load(
|
|
IStream *pStream)
|
|
{
|
|
HRESULT hr;
|
|
ULONG cbRead;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::Load(%x,%x)\n",
|
|
this, pStream));
|
|
|
|
__try
|
|
{
|
|
hr = pStream->Read(&_data, sizeof(_data), &cbRead);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(sizeof(_data) == cbRead)
|
|
{
|
|
if(_data.cbExtra != 0)
|
|
{
|
|
//Free the old buffer if necessary.
|
|
if(_pExtra != NULL)
|
|
{
|
|
PrivMemFree(_pExtra);
|
|
}
|
|
|
|
//Allocate buffer and read the extra bytes.
|
|
_pExtra = PrivMemAlloc(_data.cbExtra);
|
|
if(_pExtra != NULL)
|
|
{
|
|
hr = pStream->Read(_pExtra,
|
|
_data.cbExtra,
|
|
&cbRead);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(cbRead == _data.cbExtra)
|
|
hr = S_OK;
|
|
else
|
|
hr = STG_E_READFAULT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = STG_E_READFAULT;
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::Save
|
|
//
|
|
// Synopsis: Save the class moniker to a stream
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::Save(
|
|
IStream *pStream,
|
|
BOOL fClearDirty)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::Save(%x,%x,%x)\n",
|
|
this, pStream, fClearDirty));
|
|
|
|
__try
|
|
{
|
|
hr = pStream->Write(&_data, sizeof(_data), NULL);
|
|
if(SUCCEEDED(hr) && _pExtra != NULL && _data.cbExtra > 0)
|
|
{
|
|
//Write the extra bytes.
|
|
hr = pStream->Write(_pExtra, _data.cbExtra, NULL);
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::GetSizeMax
|
|
//
|
|
// Synopsis: Get the maximum size required to serialize this moniker
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::GetSizeMax(
|
|
ULARGE_INTEGER * pcbSize)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::GetSizeMax(%x,%x)\n",
|
|
this, pcbSize));
|
|
|
|
__try
|
|
{
|
|
ULISet32(*pcbSize, sizeof(_data) + _data.cbExtra);
|
|
hr = S_OK;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::BindToObject
|
|
//
|
|
// Synopsis: Bind to the object named by this moniker.
|
|
//
|
|
// Notes: If pmkToLeft is zero, then the class moniker calls
|
|
// CoGetClassObject to get an interface pointer to the class object.
|
|
//
|
|
// If pmkToLeft is non-zero, then the class moniker binds to the
|
|
// IClassActivator interface and then calls
|
|
// IClassActivator::GetClassObject.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::BindToObject (
|
|
IBindCtx *pbc,
|
|
IMoniker *pmkToLeft,
|
|
REFIID iidResult,
|
|
void ** ppvResult)
|
|
{
|
|
HRESULT hr;
|
|
IID iid;
|
|
BIND_OPTS2 bindOpts;
|
|
|
|
__try
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::BindToObject(%x,%x,%x,%I,%x)\n",
|
|
this, pbc, pmkToLeft, &iidResult, ppvResult));
|
|
|
|
//Validate parameters
|
|
*ppvResult = NULL;
|
|
iid = iidResult;
|
|
|
|
bindOpts.cbStruct = sizeof(bindOpts);
|
|
hr = pbc->GetBindOptions(&bindOpts);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
//Get the class object.
|
|
if(NULL == pmkToLeft)
|
|
{
|
|
//Call the internal CoGetClassObject.
|
|
hr = ICoGetClassObject(_data.clsid,
|
|
bindOpts.dwClassContext,
|
|
NULL,
|
|
iid,
|
|
ppvResult);
|
|
}
|
|
else
|
|
{
|
|
IClassActivator *pActivate;
|
|
|
|
hr = pmkToLeft->BindToObject(pbc,
|
|
NULL,
|
|
IID_IClassActivator,
|
|
(void **) &pActivate);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pActivate->GetClassObject(_data.clsid,
|
|
bindOpts.dwClassContext,
|
|
bindOpts.locale,
|
|
iid,
|
|
ppvResult);
|
|
|
|
pActivate->Release();
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::BindToStorage
|
|
//
|
|
// Synopsis: Bind to the storage for the object named by the moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::BindToStorage(
|
|
IBindCtx *pbc,
|
|
IMoniker *pmkToLeft,
|
|
REFIID riid,
|
|
void ** ppv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::BindToStorage(%x,%x,%x,%I,%x)\n",
|
|
this, pbc, pmkToLeft, &riid, ppv));
|
|
|
|
hr = BindToObject(pbc, pmkToLeft, riid, ppv);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::Reduce
|
|
//
|
|
// Synopsis: Reduce the moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::Reduce(
|
|
IBindCtx * pbc,
|
|
DWORD dwReduceHowFar,
|
|
IMoniker ** ppmkToLeft,
|
|
IMoniker ** ppmkReduced)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::Reduce(%x,%x,%x,%x,%x)\n",
|
|
this, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced));
|
|
|
|
__try
|
|
{
|
|
//Validate parameters.
|
|
*ppmkReduced = NULL;
|
|
|
|
AddRef();
|
|
*ppmkReduced = (IMoniker *) this;
|
|
hr = MK_S_REDUCED_TO_SELF;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::ComposeWith
|
|
//
|
|
// Synopsis: Compose another moniker onto the end of this moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::ComposeWith(
|
|
IMoniker * pmkRight,
|
|
BOOL fOnlyIfNotGeneric,
|
|
IMoniker **ppmkComposite)
|
|
{
|
|
HRESULT hr;
|
|
IMoniker *pmk;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::ComposeWith(%x,%x,%x,%x)\n",
|
|
this, pmkRight, fOnlyIfNotGeneric, ppmkComposite));
|
|
|
|
__try
|
|
{
|
|
//Validate parameters.
|
|
*ppmkComposite = NULL;
|
|
|
|
//Check for an anti-moniker
|
|
hr = pmkRight->QueryInterface(CLSID_AntiMoniker, (void **)&pmk);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
//pmkRight is not an anti-moniker.
|
|
if (!fOnlyIfNotGeneric)
|
|
{
|
|
hr = CreateGenericComposite(this, pmkRight, ppmkComposite);
|
|
}
|
|
else
|
|
{
|
|
hr = MK_E_NEEDGENERIC;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//pmkRight is an anti-moniker.
|
|
pmk->Release();
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::Enum
|
|
//
|
|
// Synopsis: Enumerate the components of this moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::Enum(
|
|
BOOL fForward,
|
|
IEnumMoniker ** ppenumMoniker)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::Enum(%x,%x,%x)\n",
|
|
this, fForward, ppenumMoniker));
|
|
|
|
__try
|
|
{
|
|
*ppenumMoniker = NULL;
|
|
hr = S_OK;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::IsEqual
|
|
//
|
|
// Synopsis: Compares with another moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::IsEqual(
|
|
IMoniker *pmkOther)
|
|
{
|
|
HRESULT hr;
|
|
CClassMoniker *pClassMoniker;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::IsEqual(%x,%x)\n",
|
|
this, pmkOther));
|
|
|
|
__try
|
|
{
|
|
hr = pmkOther->QueryInterface(CLSID_ClassMoniker,
|
|
(void **) &pClassMoniker);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(IsEqualCLSID(_data.clsid,
|
|
pClassMoniker->_data.clsid))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
pClassMoniker->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::Hash
|
|
//
|
|
// Synopsis: Compute a hash value
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::Hash(
|
|
DWORD * pdwHash)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::Hash(%x,%x)\n",
|
|
this, pdwHash));
|
|
|
|
__try
|
|
{
|
|
*pdwHash = _data.clsid.Data1;
|
|
hr = S_OK;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::IsRunning
|
|
//
|
|
// Synopsis: Determines if the object identified by this moniker is
|
|
// running. Since we can't search the class table to determine
|
|
// if the object is running, we just return E_NOTIMPL.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::IsRunning(
|
|
IBindCtx * pbc,
|
|
IMoniker * pmkToLeft,
|
|
IMoniker * pmkNewlyRunning)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::IsRunning(%x,%x,%x,%x)\n",
|
|
this, pbc, pmkToLeft, pmkNewlyRunning));
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::GetTimeOfLastChange
|
|
//
|
|
// Synopsis: Returns the time when the object identified by this moniker
|
|
// was changed.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::GetTimeOfLastChange (
|
|
IBindCtx * pbc,
|
|
IMoniker * pmkToLeft,
|
|
FILETIME * pFileTime)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::GetTimeOfLastChange(%x,%x,%x,%x)\n",
|
|
this, pbc, pmkToLeft, pFileTime));
|
|
|
|
return MK_E_UNAVAILABLE;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::Inverse
|
|
//
|
|
// Synopsis: Returns the inverse of this moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::Inverse(
|
|
IMoniker ** ppmk)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::Inverse(%x,%x)\n",
|
|
this, ppmk));
|
|
|
|
return CreateAntiMoniker(ppmk);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::CommonPrefixWith
|
|
//
|
|
// Synopsis: Returns the common prefix shared by this moniker and the
|
|
// other moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::CommonPrefixWith(
|
|
IMoniker * pmkOther,
|
|
IMoniker ** ppmkPrefix)
|
|
{
|
|
HRESULT hr;
|
|
CClassMoniker *pClassMoniker;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::CommonPrefixWith(%x,%x,%x)\n",
|
|
this, pmkOther, ppmkPrefix));
|
|
|
|
__try
|
|
{
|
|
//Validate parameters.
|
|
*ppmkPrefix = NULL;
|
|
|
|
hr = pmkOther->QueryInterface(CLSID_ClassMoniker,
|
|
(void **) &pClassMoniker);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(IsEqualCLSID(_data.clsid,
|
|
pClassMoniker->_data.clsid))
|
|
{
|
|
AddRef();
|
|
*ppmkPrefix = (IMoniker *) this;
|
|
hr = MK_S_US;
|
|
}
|
|
else
|
|
{
|
|
hr = MK_E_NOPREFIX;
|
|
}
|
|
|
|
pClassMoniker->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = MonikerCommonPrefixWith(this, pmkOther, ppmkPrefix);
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::RelativePathTo
|
|
//
|
|
// Synopsis: Returns the relative path between this moniker and the
|
|
// other moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::RelativePathTo(
|
|
IMoniker * pmkOther,
|
|
IMoniker ** ppmkRelPath)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::RelativePathTo(%x,%x,%x)\n",
|
|
this, pmkOther, ppmkRelPath));
|
|
|
|
__try
|
|
{
|
|
*ppmkRelPath = NULL;
|
|
hr = MonikerRelativePathTo(this, pmkOther, ppmkRelPath, TRUE);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::GetDisplayName
|
|
//
|
|
// Synopsis: Get the display name of this moniker.
|
|
//
|
|
// Notes: Call ProgIDFromClassID to get the ProgID
|
|
// Append a ':' to the end of the string.
|
|
// If no ProgID is available, then use
|
|
// clsid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx;parameters:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::GetDisplayName(
|
|
IBindCtx * pbc,
|
|
IMoniker * pmkToLeft,
|
|
LPWSTR * lplpszDisplayName)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
LPWSTR pszDisplayName;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::GetDisplayName(%x,%x,%x,%x)\n",
|
|
this, pbc, pmkToLeft, lplpszDisplayName));
|
|
|
|
__try
|
|
{
|
|
LPWSTR pszPrefix;
|
|
WCHAR szClassID[37];
|
|
LPWSTR pszParameters = (LPWSTR) _pExtra;
|
|
|
|
//Validate parameters.
|
|
*lplpszDisplayName = NULL;
|
|
|
|
|
|
//Create a display name from the class ID.
|
|
//Get the class ID string.
|
|
wStringFromUUID(_data.clsid, szClassID);
|
|
|
|
//Get the prefix
|
|
hr = ProgIDFromCLSID(CLSID_ClassMoniker,
|
|
&pszPrefix);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
ULONG cName;
|
|
cName = lstrlenW(pszPrefix) + 1 + lstrlenW(szClassID);
|
|
if(pszParameters != NULL)
|
|
{
|
|
cName += lstrlenW(pszParameters);
|
|
}
|
|
cName += 2;
|
|
|
|
pszDisplayName = (LPWSTR) CoTaskMemAlloc(cName * sizeof(wchar_t));
|
|
if(pszDisplayName != NULL)
|
|
{
|
|
lstrcpyW(pszDisplayName, pszPrefix);
|
|
lstrcatW(pszDisplayName, L":");
|
|
lstrcatW(pszDisplayName, szClassID);
|
|
if(pszParameters != NULL)
|
|
{
|
|
lstrcatW(pszDisplayName, pszParameters);
|
|
}
|
|
|
|
lstrcatW(pszDisplayName, L":");
|
|
*lplpszDisplayName = pszDisplayName;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
CoTaskMemFree(pszPrefix);
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::ParseDisplayName
|
|
//
|
|
// Synopsis: Parse the display name.
|
|
//
|
|
// Algorithm: Call BindToObject to get an IParseDisplayName on the class
|
|
// object. Call IParseDisplayName::ParseDisplayName on the
|
|
// class object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::ParseDisplayName (
|
|
IBindCtx * pbc,
|
|
IMoniker * pmkToLeft,
|
|
LPWSTR lpszDisplayName,
|
|
ULONG * pchEaten,
|
|
IMoniker ** ppmkOut)
|
|
{
|
|
HRESULT hr;
|
|
IParseDisplayName *pPDN;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::ParseDisplayName(%x,%x,%x,%ws,%x,%x)\n",
|
|
this, pbc, pmkToLeft, lpszDisplayName, pchEaten, ppmkOut));
|
|
|
|
__try
|
|
{
|
|
//Validate parameters
|
|
*ppmkOut = NULL;
|
|
*pchEaten = 0;
|
|
|
|
hr = BindToObject(pbc,
|
|
pmkToLeft,
|
|
IID_IParseDisplayName,
|
|
(void **) &pPDN);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
//Register the object with the bind context.
|
|
hr = pbc->RegisterObjectBound(pPDN);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
//Parse the display name.
|
|
hr = pPDN->ParseDisplayName(pbc,
|
|
lpszDisplayName,
|
|
pchEaten,
|
|
ppmkOut);
|
|
}
|
|
pPDN->Release();
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::IsSystemMoniker
|
|
//
|
|
// Synopsis: Determines if this is one of the system supplied monikers.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::IsSystemMoniker(
|
|
DWORD * pdwType)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::IsSystemMoniker(%x,%x)\n",
|
|
this, pdwType));
|
|
|
|
__try
|
|
{
|
|
*pdwType = MKSYS_CLASSMONIKER;
|
|
hr = S_OK;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::GetComparisonData
|
|
//
|
|
// Synopsis: Get comparison data for registration in the ROT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::GetComparisonData(
|
|
byte * pbData,
|
|
ULONG cbMax,
|
|
DWORD *pcbData)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::GetComparisonData(%x,%x,%x,%x)\n",
|
|
this, pbData, cbMax, pcbData));
|
|
|
|
__try
|
|
{
|
|
*pcbData = 0;
|
|
if(cbMax >= sizeof(CLSID_ClassMoniker) + sizeof(_data.clsid))
|
|
{
|
|
memcpy(pbData, &CLSID_ClassMoniker, sizeof(CLSID_ClassMoniker));
|
|
pbData += sizeof(CLSID);
|
|
memcpy(pbData, &_data.clsid, sizeof(_data.clsid));
|
|
*pcbData = sizeof(CLSID_ClassMoniker) + sizeof(_data.clsid);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::GetUnmarshalClass
|
|
//
|
|
// Synopsis: Get the class ID.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::GetUnmarshalClass(
|
|
REFIID riid,
|
|
LPVOID pv,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags,
|
|
CLSID * pClassID)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::GetUnmarshalClass(%x,%I,%x,%x,%x,%x,%x)\n",
|
|
this, &riid, pv, dwDestContext, pvDestContext, mshlflags,
|
|
pClassID));
|
|
|
|
return GetClassID(pClassID);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::GetMarshalSizeMax
|
|
//
|
|
// Synopsis: Get maximum size of marshalled moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::GetMarshalSizeMax(
|
|
REFIID riid,
|
|
LPVOID pv,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags,
|
|
DWORD *pSize)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::GetMarshalSizeMax(%x,%I,%x,%x,%x,%x,%x)\n",
|
|
this, &riid, pv, dwDestContext, pvDestContext, mshlflags,
|
|
pSize));
|
|
|
|
__try
|
|
{
|
|
*pSize = sizeof(_data) + _data.cbExtra;
|
|
hr = S_OK;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::MarshalInterface
|
|
//
|
|
// Synopsis: Marshal moniker into a stream.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::MarshalInterface(
|
|
IStream * pStream,
|
|
REFIID riid,
|
|
void * pv,
|
|
DWORD dwDestContext,
|
|
LPVOID pvDestContext,
|
|
DWORD mshlflags)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::MarshalInterface(%x,%x,%I,%x,%x,%x,%x)\n",
|
|
this, pStream, &riid, pv, dwDestContext, pvDestContext,
|
|
mshlflags));
|
|
|
|
return Save(pStream, FALSE);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::UnmarshalInterface
|
|
//
|
|
// Synopsis: Unmarshal moniker from a stream.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::UnmarshalInterface(
|
|
IStream * pStream,
|
|
REFIID riid,
|
|
void ** ppv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::UnmarshalInterface(%x,%x,%I,%x)\n",
|
|
this, pStream, &riid, ppv));
|
|
|
|
__try
|
|
{
|
|
//Validate parameters.
|
|
*ppv = NULL;
|
|
|
|
hr = Load(pStream);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = QueryInterface(riid, ppv);
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::ReleaseMarshalData
|
|
//
|
|
// Synopsis: Release a marshalled class moniker.
|
|
// Just seek to the end of the marshalled class moniker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::ReleaseMarshalData(
|
|
IStream * pStream)
|
|
{
|
|
HRESULT hr;
|
|
LARGE_INTEGER liSize;
|
|
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::ReleaseMarshalData(%x,%x)\n",
|
|
this, pStream));
|
|
|
|
hr = GetSizeMax((ULARGE_INTEGER *) &liSize);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pStream->Seek(liSize, STREAM_SEEK_CUR, NULL);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CClassMoniker::DisconnectObject
|
|
//
|
|
// Synopsis: Disconnect the object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CClassMoniker::DisconnectObject(
|
|
DWORD dwReserved)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CClassMoniker::DisconnectObject(%x,%x)\n",
|
|
this, dwReserved));
|
|
|
|
return S_OK;
|
|
}
|
|
|