Leaked source code of windows server 2003
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.
 
 
 
 
 
 

437 lines
14 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
gmoniker.cpp
Abstract:
This module contains the implementation of the
CSEOGenericMoniker object.
Author:
Andy Jacobs ([email protected])
Revision History:
andyj 04/11/97 created
--*/
// GMONIKER.cpp : Implementation of CSEOGenericMoniker
#include "stdafx.h"
#include "seodefs.h"
#include "GMONIKER.h"
#ifndef CSTR_EQUAL
#define CSTR_EQUAL (2)
#endif
LPCOLESTR szObjectType = OLESTR("MonikerType");
const WCHAR QUOTE_CHAR = L'\\';
const WCHAR NAME_SEP = L'=';
const WCHAR ENTRY_SEP = L' ';
const WCHAR PROGID_PREFIX = L'@';
const WCHAR PROGID_POSTFIX = L':';
IsPrefix(LPCOLESTR psPrefix, LPCOLESTR psString, int iLen) {
return (CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
psPrefix, iLen, psString, iLen));
}
/////////////////////////////////////////////////////////////////////////////
// CSEOGenericMoniker
// IPersist Members
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::GetClassID(/* [out] */ CLSID __RPC_FAR *pClassID) {
if(!pClassID) return E_POINTER;
memcpy(pClassID, &CLSID_CSEOGenericMoniker, sizeof(CLSID));
_ASSERT(IsEqualCLSID(*pClassID, CLSID_CSEOGenericMoniker));
return S_OK;
}
// IPersistStream Members
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::IsDirty(void) {
return S_FALSE; // Shallow binding representation hasn't changed
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Load(
/* [unique][in] */ IStream __RPC_FAR *pStm) {
return m_bstrMoniker.ReadFromStream(pStm);
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Save(
/* [unique][in] */ IStream __RPC_FAR *pStm,
/* [in] */ BOOL fClearDirty) {
return m_bstrMoniker.WriteToStream(pStm);
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::GetSizeMax(
/* [out] */ ULARGE_INTEGER __RPC_FAR *pcbSize) {
if(!pcbSize) return E_POINTER;
// Conservitive size estimate of bytes needed to save object
pcbSize->QuadPart = m_bstrMoniker.Length() * sizeof(WCHAR) * 2;
return S_OK;
}
// IMoniker Members
/* [local] */ HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::BindToObject(
/* [unique][in] */ IBindCtx __RPC_FAR *pbc,
/* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
/* [in] */ REFIID riidResult,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvResult) {
if(!pbc || !ppvResult) return E_POINTER;
*ppvResult = NULL;
// First, get the Running Object Table
BOOL bFoundInTable = TRUE;
CComPtr<IRunningObjectTable> pROT;
CComPtr<IUnknown> punkObject;
HRESULT hRes = pbc->GetRunningObjectTable(&pROT);
if(FAILED(hRes)) return hRes;
_ASSERT(!!pROT); // operator!() is defined, so use !! to test for existance.
if(!pROT) return E_UNEXPECTED; // GetRunningObjectTable() didn't work
// Try to find in Running Object Table
hRes = pROT->GetObject((IMoniker *) this, &punkObject);
// If not currently running then create it
if(FAILED(hRes) || !punkObject) {
bFoundInTable = FALSE;
CComPtr<IPropertyBag> pBag;
hRes = CoCreateInstance(CLSID_CSEOMemDictionary, NULL, CLSCTX_ALL,
IID_IPropertyBag, (LPVOID *) &pBag);
if(FAILED(hRes)) return hRes;
_ASSERT(!!pBag); // operator!() is defined, so use !! to test for existance.
SetPropertyBag(pBag);
CComPtr<ISEOInitObject> pInitObject;
hRes = CreateBoundObject(pBag, &pInitObject);
if(FAILED(hRes)) return hRes;
_ASSERT(!!pInitObject); // operator!() is defined, so use !! to test for existance.
if(!pInitObject) return E_UNEXPECTED; // CreateBoundObject returned S_OK, but didn't Create an object
hRes = pInitObject->Load(pBag, NULL);
punkObject = pInitObject; // Save copy of pointer
/* TBD: Register with the Running Object Table
DWORD dwRegister;
if(SUCCEEDED(hRes)) pROT->Register(0, pInitObject, (IMoniker *) this, &dwRegister);
*/
}
// punkObject should have been set by one of the code paths before this
_ASSERT(!!punkObject); // operator!() is defined, so use !! to test for existance.
if(!punkObject) return E_UNEXPECTED;
return punkObject->QueryInterface(riidResult, ppvResult);
}
/* [local] */ HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::BindToStorage(
/* [unique][in] */ IBindCtx __RPC_FAR *pbc,
/* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObj) {
return MK_E_NOSTORAGE; // The object identified by this moniker does not have its own storage.
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Reduce(
/* [unique][in] */ IBindCtx __RPC_FAR *pbc,
/* [in] */ DWORD dwReduceHowFar,
/* [unique][out][in] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkToLeft,
/* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkReduced) {
if(!ppmkReduced) return E_POINTER;
*ppmkReduced = (IMoniker *) this;
_ASSERT(!!*ppmkReduced); // operator!() is defined, so use !! to test for existance.
if(!*ppmkReduced) return E_UNEXPECTED; // "this" not set...
HRESULT hRes = (*ppmkReduced)->AddRef(); // Do this for self (the object being returned)
if(SUCCEEDED(hRes)) hRes = MK_S_REDUCED_TO_SELF; // This moniker could not be reduced any further, so ppmkReduced indicates this moniker.
return hRes;
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::ComposeWith(
/* [unique][in] */ IMoniker __RPC_FAR *pmkRight,
/* [in] */ BOOL fOnlyIfNotGeneric,
/* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkComposite) {
ATLTRACENOTIMPL(_T("CSEOGenericMoniker::ComposeWith"));
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Enum(
/* [in] */ BOOL fForward,
/* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenumMoniker) {
if(!ppenumMoniker) return E_POINTER;
*ppenumMoniker = NULL;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::IsEqual(
/* [unique][in] */ IMoniker __RPC_FAR *pmkOtherMoniker) {
ATLTRACENOTIMPL(_T("CSEOGenericMoniker::IsEqual"));
// Return S_OK vs. S_FALSE
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Hash(
/* [out] */ DWORD __RPC_FAR *pdwHash) {
if(!pdwHash) return E_POINTER;
*pdwHash = 0; // ATLTRACENOTIMPL(_T("CSEOGenericMoniker::Hash"));
return S_OK;
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::IsRunning(
/* [unique][in] */ IBindCtx __RPC_FAR *pbc,
/* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
/* [unique][in] */ IMoniker __RPC_FAR *pmkNewlyRunning) {
HRESULT hRes = E_UNEXPECTED; // hRes not set to something else
if(pmkToLeft) { // If something on the left, pass it to them
hRes = pmkToLeft->IsRunning(pbc, NULL, pmkNewlyRunning);
} else if(pbc) { // No Moniker to left, but have a BindCtx
CComPtr<IRunningObjectTable> pROT;
hRes = pbc->GetRunningObjectTable(&pROT);
if(FAILED(hRes)) return hRes;
if(pROT) { // Try to find in Running Object Table
hRes = pROT->IsRunning((IMoniker *) this);
}
} else {
hRes = E_POINTER; // No BindCtx
}
return hRes;
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::GetTimeOfLastChange(
/* [unique][in] */ IBindCtx __RPC_FAR *pbc,
/* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
/* [out] */ FILETIME __RPC_FAR *pFileTime) {
return MK_E_UNAVAILABLE;
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Inverse(
/* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk) {
return MK_E_NOINVERSE;
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::CommonPrefixWith(
/* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
/* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkPrefix) {
return MK_E_NOPREFIX;
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::RelativePathTo(
/* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
/* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkRelPath) {
ATLTRACENOTIMPL(_T("CSEOGenericMoniker::RelativePathTo"));
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::GetDisplayName(
/* [unique][in] */ IBindCtx __RPC_FAR *pbc,
/* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
/* [out] */ LPOLESTR __RPC_FAR *ppszDisplayName) {
if(!ppszDisplayName) return E_POINTER;
*ppszDisplayName = NULL;
CComPtr<IMalloc> pMalloc;
HRESULT hRes = CoGetMalloc(1, &pMalloc);
if(SUCCEEDED(hRes)) {
_ASSERT(!!pMalloc); // operator!() is defined, so use !! to test for existance.
hRes = E_OUTOFMEMORY;
int iSize = 5 + m_bstrMoniker.Length() + lstrlenW(GENERIC_MONIKER_VERPROGID);
*ppszDisplayName = (LPOLESTR) pMalloc->Alloc(iSize * sizeof(WCHAR));
if(*ppszDisplayName) {
**ppszDisplayName = 0; // Terminate string
lstrcatW(*ppszDisplayName, L"@");
lstrcatW(*ppszDisplayName, GENERIC_MONIKER_VERPROGID); // Build the display name
lstrcatW(*ppszDisplayName, L": ");
lstrcatW(*ppszDisplayName, m_bstrMoniker);
hRes = S_OK;
}
}
return hRes;
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::ParseDisplayName(
/* [unique][in] */ IBindCtx __RPC_FAR *pbc,
/* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
/* [in] */ LPOLESTR pszDisplayName,
/* [out] */ ULONG __RPC_FAR *pchEaten,
/* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut) {
// Deligate!!!
return ParseDisplayName(pbc, pszDisplayName, pchEaten, ppmkOut);
}
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::IsSystemMoniker(
/* [out] */ DWORD __RPC_FAR *pdwMksys) {
if(!pdwMksys) return E_POINTER;
*pdwMksys = MKSYS_NONE;
return S_FALSE; // Not a system moniker
}
// IParseDisplayName Members
HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::ParseDisplayName(
/* [unique][in] */ IBindCtx __RPC_FAR *pbc,
/* [in] */ LPOLESTR pszDisplayName,
/* [out] */ ULONG __RPC_FAR *pchEaten,
/* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut) {
if(!pszDisplayName || !pchEaten || !ppmkOut) return E_POINTER;
*pchEaten = 0; // Nothing parsed so far
CComBSTR bstrMoniker;
CComBSTR bstrProgID(GENERIC_MONIKER_PROGID);
CComBSTR bstrVerProgID(GENERIC_MONIKER_VERPROGID);
// The Ver string should completely contain the non-Ver string
_ASSERT(bstrProgID.Length() > 0); // Something should be there
_ASSERT(bstrProgID.Length() <= bstrVerProgID.Length());
_ASSERT(IsPrefix(bstrProgID, bstrVerProgID, bstrProgID.Length()));
if(PROGID_PREFIX == pszDisplayName[*pchEaten]) {
++(*pchEaten);
}
if(IsPrefix(bstrProgID, pszDisplayName + *pchEaten, bstrProgID.Length())) {
if(IsPrefix(bstrVerProgID, pszDisplayName + *pchEaten, bstrVerProgID.Length())) {
*pchEaten += bstrVerProgID.Length();
} else { // Non-version string matched
*pchEaten += bstrProgID.Length();
}
if(pszDisplayName[*pchEaten] &&
(PROGID_POSTFIX == pszDisplayName[*pchEaten])) {
++(*pchEaten);
}
while(pszDisplayName[*pchEaten] &&
(pszDisplayName[*pchEaten] == ENTRY_SEP)) {
++(*pchEaten);
}
if(pszDisplayName[*pchEaten]) { // If still something left
bstrMoniker = &pszDisplayName[*pchEaten];
*pchEaten += bstrMoniker.Length();
}
}
CComObject<CSEOGenericMoniker> *pMoniker;
HRESULT hRes = CComObject<CSEOGenericMoniker>::CreateInstance(&pMoniker);
if(FAILED(hRes)) return hRes;
_ASSERT(!!pMoniker); // operator!() is defined, so use !! to test for existance.
if(!pMoniker) return E_UNEXPECTED; // CreateInstance failed (but returned S_OK)
pMoniker->SetMonikerString(bstrMoniker);
*ppmkOut = (IMoniker *) pMoniker;
return pMoniker->AddRef();
}
HRESULT CSEOGenericMoniker::FinalConstruct() {
HRESULT hrRes;
hrRes = CoCreateFreeThreadedMarshaler(GetControllingUnknown(),&m_pUnkMarshaler.p);
_ASSERTE(!SUCCEEDED(hrRes)||m_pUnkMarshaler);
return (SUCCEEDED(hrRes)?S_OK:hrRes);
}
void CSEOGenericMoniker::FinalRelease() {
m_pUnkMarshaler.Release();
}
void CSEOGenericMoniker::SetPropertyBag(IPropertyBag *pBag) {
if(!pBag) return;
int iStringLength = m_bstrMoniker.Length();
int iCurrentPos = 0;
while(iCurrentPos < iStringLength) {
CComBSTR bstrName;
CComBSTR bstrValue;
// Eat up multiple spaces for entry separators
while((iCurrentPos < iStringLength) &&
(m_bstrMoniker.m_str[iCurrentPos] == ENTRY_SEP)) {
++iCurrentPos;
}
// Read in the Name
while((iCurrentPos < iStringLength) &&
(m_bstrMoniker.m_str[iCurrentPos] != NAME_SEP)) {
if((iCurrentPos < iStringLength - 1) &&
(m_bstrMoniker.m_str[iCurrentPos] == QUOTE_CHAR)) {
++iCurrentPos;
}
bstrName.Append(&m_bstrMoniker.m_str[iCurrentPos], 1);
++iCurrentPos;
}
BOOL bFoundSep = FALSE;
if((iCurrentPos < iStringLength) &&
(m_bstrMoniker.m_str[iCurrentPos] == NAME_SEP)) {
bFoundSep = TRUE;
++iCurrentPos;
}
// Read in the value
while((iCurrentPos < iStringLength) &&
(m_bstrMoniker.m_str[iCurrentPos] != ENTRY_SEP)) {
if((iCurrentPos < iStringLength - 1) &&
(m_bstrMoniker.m_str[iCurrentPos] == QUOTE_CHAR)) {
++iCurrentPos;
}
bstrValue.Append(&m_bstrMoniker.m_str[iCurrentPos], 1);
++iCurrentPos;
}
if(bFoundSep) { // If it's a real entry
CComVariant varValue = bstrValue; // Convert BSTR to Variant
pBag->Write(bstrName, &varValue);
// Even if error occurs in Write(), continue processing
}
// Eat up multiple spaces for entry separators
while((iCurrentPos < iStringLength) &&
(m_bstrMoniker.m_str[iCurrentPos] == ENTRY_SEP)) {
++iCurrentPos;
}
}
}
HRESULT CSEOGenericMoniker::CreateBoundObject(IPropertyBag *pBag, ISEOInitObject **ppResult) {
_ASSERT(ppResult);
*ppResult = NULL;
if(!pBag) return E_POINTER;
CComVariant varPROGID;
CLSID clsid;
varPROGID.vt = VT_BSTR; // Request type from Read()
varPROGID.bstrVal = NULL;
HRESULT hRes = pBag->Read(szObjectType, &varPROGID, NULL);
if(SUCCEEDED(hRes)) {
_ASSERT(varPROGID.vt == VT_BSTR);
hRes = CLSIDFromProgID(varPROGID.bstrVal, &clsid);
}
if(SUCCEEDED(hRes)) {
hRes = CoCreateInstance(clsid, NULL, CLSCTX_ALL,
IID_ISEOInitObject, (LPVOID *) ppResult);
}
return hRes;
}