414 lines
11 KiB
C++
414 lines
11 KiB
C++
|
//+------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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);
|
||
|
}
|
||
|
|