|
|
//+------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1997
//
// File: cclsto.cxx
//
// Contents: Class Factory and IUnknown methods for CAppContainer
//
// Author: DebiM
//
//-------------------------------------------------------------------------
#include "cstore.hxx"
//
// Constructor for App Container Class factory
//
unsigned long gulcappcon = 0;
extern CRITICAL_SECTION ClassStoreBindList; ClassStoreCacheType ClassStoreCache;
CAppContainerCF::CAppContainerCF() { m_uRefs = 1; InterlockedIncrement((long *) &gulcappcon );
ClassStoreCache.sz = 0; ClassStoreCache.start = 0; ClassStoreCache.end = 0; }
void ReleaseBindings(BindingsType *pbd) { CSDBGPrint((L"Cleaning up entry in Cache. %s", pbd->szStorePath)); if (pbd->pIClassAccess) { (pbd->pIClassAccess)->Release(); } CoTaskMemFree(pbd->Sid); CoTaskMemFree(pbd->szStorePath); }
//
// Destructor
//
CAppContainerCF::~CAppContainerCF() { //
// Cleanup the cache
//
for (UINT i=ClassStoreCache.start; i != ClassStoreCache.end; i = (i+1)%(MAXCLASSSTORES)) { ReleaseBindings(ClassStoreCache.Bindings+i); } InterlockedDecrement((long *) &gulcappcon ); }
HRESULT __stdcall CAppContainerCF::QueryInterface(REFIID riid, void * * ppvObject) { IUnknown *pUnkTemp = NULL; SCODE sc = S_OK; if( IsEqualIID( IID_IUnknown, riid ) ) { pUnkTemp = (IUnknown *)(ITypeLib *)this; } else if( IsEqualIID( IID_IClassFactory, riid ) ) { pUnkTemp = (IUnknown *)(IClassFactory *)this; } else if( IsEqualIID( IID_IParseDisplayName, riid ) ) { pUnkTemp = (IUnknown *)(IParseDisplayName *)this; } else { sc = (E_NOINTERFACE); }
if((pUnkTemp != NULL) && (SUCCEEDED(sc))) { *ppvObject = (void * )pUnkTemp; pUnkTemp->AddRef(); } return(sc); }
ULONG __stdcall CAppContainerCF::AddRef() { InterlockedIncrement(( long * )&m_uRefs ); return m_uRefs; }
ULONG __stdcall CAppContainerCF::Release() { unsigned long uTmp = InterlockedDecrement((long *)&m_uRefs); unsigned long cRef = m_uRefs;
// 0 is the only valid value to check
if (uTmp == 0) { delete this; }
return(cRef); }
//
// IClassFactory Overide
//
HRESULT __stdcall CAppContainerCF::CreateInstance(IUnknown * pUnkOuter, REFIID riid, void ** ppvObject) { CAppContainer * pIUnk = NULL; SCODE sc = S_OK;
if( pUnkOuter == NULL ) { if( (pIUnk = new CAppContainer()) != NULL) { sc = pIUnk->QueryInterface( riid , ppvObject ); if(FAILED(sc)) { sc = E_UNEXPECTED; } pIUnk->Release(); } else sc = E_OUTOFMEMORY; } else { return E_INVALIDARG; } return (sc); }
//---------------------------------------------------------------
//
// Function: CreateConnectedInstance
//
// Synopsis: Returns IClassAccess Pointer, given a class store
// path.
//
// Arguments:
// [in]
// pszPath Class Store Path without the leading ADCS:
//
// pUserSid
// Sid under which the calling thread is running.
// fCache
// Boolean that decides whether to use a cached pointer or
// not.
// [out]
// ppvObject
// IClassAccess Interface pointer
//
// Returns:
// S_OK, E_NOINTERFACE, E_OUTOFMEMORY, CS_E_XXX
//
// if (fCache)
// Looks in the cache to see if we have already tried to bind to the same
// ClassStore Path under the same SID. If it finds it, then we just QI for
// IClassAccess and return. o/w create a new class store pointer and caches it.
// else
// Just binds to a new ClassStore and returns.
//----------------------------------------------------------------
HRESULT __stdcall CAppContainerCF::CreateConnectedInstance(LPOLESTR pszPath, PSID pUserSid, BOOL fCache, void ** ppvObject) { CAppContainer * pIUnk = NULL; SCODE sc = S_OK; HRESULT hr = S_OK; BOOL fFound = FALSE;
if (fCache) { //
// Look in cache
//
EnterCriticalSection (&ClassStoreBindList); for (UINT i=ClassStoreCache.start; i != ClassStoreCache.end; i = (i+1)%(MAXCLASSSTORES)) { // compare cached sids and Class Store path
if ((wcscmp(pszPath, ClassStoreCache.Bindings[i].szStorePath) == 0) && (EqualSid(pUserSid, ClassStoreCache.Bindings[i].Sid))) { //
// Found in cache
//
CSDBGPrint((L"Found %s in Cache.", pszPath)); fFound = TRUE; if (ClassStoreCache.Bindings[i].pIClassAccess) { sc = (ClassStoreCache.Bindings[i].pIClassAccess)-> QueryInterface( IID_IClassAccess, ppvObject ); } else { sc = ClassStoreCache.Bindings[i].Hr; // return the same error code.
} break; } } LeaveCriticalSection (&ClassStoreBindList);
if (fFound) return sc; }
if ((pIUnk = new CAppContainer(pszPath, &sc)) != NULL) { if (SUCCEEDED(sc)) { sc = pIUnk->QueryInterface( IID_IClassAccess, ppvObject ); if(FAILED(sc)) { sc = E_UNEXPECTED; } } else CSDBGPrint((L"Connect to Store Failed. hr = 0x%x", sc));
pIUnk->Release(); } else sc = E_OUTOFMEMORY;
//
// Store the result in the cache
//
if (fCache) { //
// Should not cache situations out of network failures
// BUGBUG: For now we are only caching successes OR CS does not exist cases
//
if ((sc == S_OK) || (sc == CS_E_OBJECT_NOTFOUND)) { EnterCriticalSection (&ClassStoreBindList);
for (UINT i=ClassStoreCache.start; i != ClassStoreCache.end; i = (i+1)%(MAXCLASSSTORES)) { if ((wcscmp(pszPath, ClassStoreCache.Bindings[i].szStorePath) == 0) && (EqualSid(pUserSid, ClassStoreCache.Bindings[i].Sid))) { //
// Found in cache after bind attempt
//
CSDBGPrint((L"Found in Cache after binding !!!."));
//
// If we already got an existing object, release the one we grabbed
// above
//
if (*ppvObject) {
((IClassAccess *)(*ppvObject))->Release(); *ppvObject = NULL;
} else { ASSERT(CS_E_OBJECT_NOTFOUND == sc); }
//
// Now we can get the object from the cache to satisfy
// the caller's request
//
if (ClassStoreCache.Bindings[i].pIClassAccess) { sc = (ClassStoreCache.Bindings[i].pIClassAccess)-> QueryInterface( IID_IClassAccess, ppvObject ); } else { sc = ClassStoreCache.Bindings[i].Hr; // return the same error code.
} } }
if (i == ClassStoreCache.end) { if (ClassStoreCache.sz == (MAXCLASSSTORES-1)) { ReleaseBindings(ClassStoreCache.Bindings+ClassStoreCache.start); ClassStoreCache.start = (ClassStoreCache.start+1)%MAXCLASSSTORES; ClassStoreCache.sz--; }
// allocate space for the guid and the Class store path.
ClassStoreCache.Bindings[i].szStorePath = (LPOLESTR) CoTaskMemAlloc (sizeof(WCHAR) * (wcslen (pszPath) + 1)); UINT dwBytesRequired = GetLengthSid(pUserSid); ClassStoreCache.Bindings[i].Sid = CoTaskMemAlloc(dwBytesRequired); // if memory was allocated.
if ((ClassStoreCache.Bindings[i].szStorePath) && (ClassStoreCache.Bindings[i].Sid)) { // copy the class store path.
wcscpy (ClassStoreCache.Bindings[i].szStorePath, pszPath); ClassStoreCache.Bindings[i].pIClassAccess = NULL; // get the IClassAccess pointer and cache it.
if (sc == S_OK) { ((IClassAccess *)(*ppvObject))->QueryInterface( IID_IClassAccess, (void **)&ClassStoreCache.Bindings[i].pIClassAccess); } ClassStoreCache.Bindings[i].Hr = sc; // copy the SIDs
CopySid(dwBytesRequired, ClassStoreCache.Bindings[i].Sid, pUserSid); ClassStoreCache.sz++; ClassStoreCache.end = (ClassStoreCache.end + 1)% MAXCLASSSTORES; } } LeaveCriticalSection (&ClassStoreBindList); } }
return (sc); }
HRESULT __stdcall CAppContainerCF::LockServer(BOOL fLock) { if(fLock) { InterlockedIncrement((long *) &gulcappcon ); } else { InterlockedDecrement((long *) &gulcappcon ); } return(S_OK); }
//
// IUnknown methods for CAppContainer
//
//
HRESULT __stdcall CAppContainer::QueryInterface(REFIID riid, void * * ppvObject) { IUnknown *pUnkTemp = NULL; SCODE sc = S_OK; if( IsEqualIID( IID_IUnknown, riid ) ) { pUnkTemp = (IUnknown *)(IClassAccess *)this; } else if( IsEqualIID( IID_IClassAccess, riid ) ) { pUnkTemp = (IUnknown *)(IClassAccess *)this; } /*
else if( IsEqualIID( IID_IClassRefresh, riid ) ) { pUnkTemp = (IUnknown *)(IClassRefresh *)this; } else if( IsEqualIID( IID_ICatInformation, riid ) ) { pUnkTemp = (IUnknown *)(ICatInformation *)this; } */ else { sc = (E_NOINTERFACE); }
if((pUnkTemp != NULL) && (SUCCEEDED(sc))) { *ppvObject = (void * )pUnkTemp; pUnkTemp->AddRef(); } return(sc); }
ULONG __stdcall CAppContainer::AddRef() { InterlockedIncrement(( long * )&m_uRefs ); return m_uRefs; }
ULONG __stdcall CAppContainer::Release() { unsigned long uTmp = InterlockedDecrement((long *)&m_uRefs); unsigned long cRef = m_uRefs;
if (uTmp == 0) { delete this; }
return(cRef); }
|