Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

610 lines
12 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1993 - 1993.
//
// File: cbindctx.cxx
//
// Contents:
//
// Classes:
//
// Functions:
//
// History:
// 12-27-93 ErikGav Created
// 10-05-95 MikeHill Added 'dwRestricted' field to BIND_OPTS.
// 11-14-95 MikeHill Removed previous change (to BIND_OPTS).
// 12-06-95 MikeHill Fixed Get/SetBindOptions so they don't corrupt
// the cbStruct field.
//
//----------------------------------------------------------------------------
#include <ole2int.h>
#include "cbindctx.hxx"
#include "mnk.h"
/*
* Implementation of CBindCtx
*
*
*
*
*/
NAME_SEG(CBindCtx)
#ifdef NOTYET
// IEnumString implementation for EnumObjectParam call
class CEnumStringImpl : public IEnumString
{
public:
// *** IUnknown methods ***
STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj)
{
if (riid == IID_IEnumString || riid == IID_IUnknown)
{
*ppvObj = this;
AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHOD_(ULONG,AddRef) (THIS)
{
return ++m_refs;
}
STDMETHOD_(ULONG,Release) (THIS)
{
if (--m_refs == 0)
{
delete this;
return 0;
}
return m_refs;
}
// *** IEnumString methods ***
STDMETHOD(Next) (THIS_ ULONG celt,
LPWSTR FAR* reelt,
ULONG FAR* pceltFetched);
STDMETHOD(Skip) (THIS_ ULONG celt);
STDMETHOD(Reset) (THIS);
STDMETHOD(Clone) (THIS_ LPENUMSTRING FAR* ppenm);
//constructor/destructor
CEnumStringImpl( CMapStringToPtr FAR * pMap );
~CEnumStringImpl( void );
private:
class LI
{
public:
LI FAR * pliNext;
LPWSTR lpszKey;
LI( LPWSTR lpsz ) {
lpszKey = lpsz;
}
};
friend class LI;
LI FAR * pliHead;
LI FAR * pliCurrent;
ULONG m_refs;
};
#endif // NOTYET
CBindCtx::CBindCtx()
#ifdef _DEBUG
: m_Debug(this)
#endif
{
GET_A5();
m_refs = 1;
m_pFirstObj = NULL;
m_bindopts.cbStruct = sizeof(m_bindopts);
m_bindopts.grfFlags = 0;
m_bindopts.grfMode = STGM_READWRITE;
m_bindopts.dwTickCountDeadline = 0;
m_bindopts.dwTrackFlags = 0;
#ifdef WX86OLE
m_bindopts.dwClassContext = gcwx86.IsWx86Enabled() ?
CLSCTX_SERVER | CLSCTX_INPROC_SERVERX86 :
CLSCTX_SERVER;
#else
m_bindopts.dwClassContext = CLSCTX_SERVER;
#endif
m_bindopts.locale = GetThreadLocale();
m_bindopts.pServerInfo = 0;
m_pMap = NULL;
}
CBindCtx::~CBindCtx( void )
{
LPWSTR lpszKey;
LPVOID lpvoid;
M_PROLOG(this);
ReleaseBoundObjects();
if (m_pMap)
{
POSITION pos = m_pMap->GetStartPosition();
while (pos != NULL)
{
m_pMap->GetNextAssoc(pos, lpszKey, lpvoid);
if (lpvoid) ((LPUNKNOWN)lpvoid)->Release();
}
delete m_pMap;
}
}
NC(CBindCtx,CObjList)::~CObjList(void)
{
if (m_punk) m_punk->Release();
}
IBindCtx FAR *CBindCtx::Create()
{
return new FAR CBindCtx();
}
STDMETHODIMP CBindCtx::QueryInterface(REFIID iidInterface, void FAR* FAR* ppv)
{
HRESULT hr;
__try
{
//Parameter validation.
//An invalid parameter will throw an exception.
*ppv = 0;
if (IsEqualIID(iidInterface, IID_IUnknown)
|| IsEqualIID(iidInterface, IID_IBindCtx))
{
AddRef();
*ppv = this;
hr = S_OK;
}
#ifdef _DEBUG
else if(IsEqualIID(iidInterface,IID_IDebug))
{
*ppv = (void FAR *)&m_Debug;
hr = S_OK;
}
#endif
else
{
hr = E_NOINTERFACE;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//An exception occurred, probably because of a bad parameter.
hr = E_INVALIDARG;
}
return hr;
}
STDMETHODIMP_(ULONG) CBindCtx::AddRef( void )
{
InterlockedIncrement((long *)&m_refs);
return m_refs;
}
STDMETHODIMP_(ULONG) CBindCtx::Release( void )
{
ULONG count = m_refs - 1;
if(InterlockedDecrement((long *)&m_refs) == 0)
{
delete this;
count = 0;
}
return count;
}
STDMETHODIMP CBindCtx::RegisterObjectBound( LPUNKNOWN punk )
{
M_PROLOG(this);
if (punk == NULL) noError;
VDATEIFACE(punk);
CObjList FAR* pCOL = new CObjList( punk );
if (pCOL)
{
punk->AddRef();
AddToList(pCOL);
noError;
}
return ResultFromScode(S_OOM);
}
STDMETHODIMP CBindCtx::RevokeObjectBound
( LPUNKNOWN punk )
{
M_PROLOG(this);
VDATEIFACE(punk);
CObjList FAR * pCOL = m_pFirstObj;
CObjList FAR * pCOLPrev = NULL;
// look for entry which matches punk given
for (; pCOL && (pCOL->m_punk != punk);
pCOLPrev = pCOL, pCOL = pCOL->m_pNext)
{
// empty
}
// pCOL is null or pCOL->m_punk = punk
if (pCOL != NULL)
{
if (pCOLPrev == NULL) m_pFirstObj = pCOL->m_pNext;
else pCOLPrev->m_pNext = pCOL->m_pNext;
delete pCOL;
noError;
}
return ResultFromScode(MK_E_NOTBOUND);
}
STDMETHODIMP CBindCtx::ReleaseBoundObjects(THIS)
{
M_PROLOG(this);
CObjList FAR * pCOL = m_pFirstObj;
CObjList FAR * pCOLNext = NULL;
m_pFirstObj = NULL;
while (pCOL != NULL)
{
pCOLNext = pCOL->m_pNext;
delete pCOL; // calls Release on the object
pCOL = pCOLNext;
}
noError;
}
STDMETHODIMP CBindCtx::SetBindOptions (LPBIND_OPTS pbindopts)
{
HRESULT hr;
__try
{
if (pbindopts->cbStruct <= sizeof(m_bindopts))
{
//Set the bind options.
memcpy(&m_bindopts, pbindopts, (size_t)(pbindopts->cbStruct));
hr = S_OK;
}
else
{
//pbindopts is too large.
hr = E_INVALIDARG;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//An exception occurred, probably because of a bad parameter.
hr = E_INVALIDARG;
}
Assert(m_bindopts.cbStruct <= sizeof(m_bindopts));
return hr;
}
STDMETHODIMP CBindCtx::GetBindOptions (LPBIND_OPTS pbindopts)
{
HRESULT hr;
ULONG cbDest;
Assert(m_bindopts.cbStruct <= sizeof(m_bindopts));
__try
{
cbDest = pbindopts->cbStruct;
if(m_bindopts.cbStruct <= cbDest)
{
memcpy(pbindopts, &m_bindopts, m_bindopts.cbStruct);
}
else
{
BIND_OPTS2 bindopts = m_bindopts;
bindopts.cbStruct = cbDest;
memcpy(pbindopts, &bindopts, cbDest);
}
hr = S_OK;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//An exception occurred, probably because of a bad parameter.
hr = E_INVALIDARG;
}
return hr;
}
STDMETHODIMP CBindCtx::GetRunningObjectTable (THIS_ LPRUNNINGOBJECTTABLE FAR*
pprot)
{
M_PROLOG(this);
VDATEPTROUT(pprot, LPRUNNINGOBJECTTABLE);
return ::GetRunningObjectTable(0, pprot);
}
//+-------------------------------------------------------------------------
//
// Member: CBindCtx::RegisterObjectParam
//
// Synopsis: Registers object with key
//
// Effects: Adds object to bind context
//
// Arguments: [lpszKey] -- registration key
// [punk] -- object
//
// Returns: HRESULT
//
// Modifies:
//
// Derivation: IBindContext
//
// Algorithm:
//
// History: 03-Jun-94 AlexT Added header block; release previous
// object (if it exists)
//
// Notes: This function is not multithread safe!
//
//--------------------------------------------------------------------------
STDMETHODIMP CBindCtx::RegisterObjectParam (THIS_ LPWSTR lpszKey, LPUNKNOWN punk)
{
M_PROLOG(this);
VDATEPTRIN(lpszKey, WCHAR);
VDATEIFACE(punk);
if (m_pMap == NULL)
{
// We don't have a map yet; allocate one
m_pMap = new CMapStringToPtr();
if (NULL == m_pMap)
{
return ResultFromScode(E_OUTOFMEMORY);
}
}
else
{
LPVOID pv;
// We already have a map; if we have an existing entry for this
// key we release it here (we don't remove the key because we're
// about to assign a new value with the same key below
if (m_pMap->Lookup(lpszKey, pv))
{
((LPUNKNOWN)pv)->Release();
}
}
// SetAt is guaranteed not to fail if lpszKey is already in the map
if (m_pMap->SetAt(lpszKey, (LPVOID&)punk))
{
punk->AddRef();
return NOERROR;
}
return ResultFromScode(E_OUTOFMEMORY);
}
STDMETHODIMP CBindCtx::GetObjectParam (THIS_ LPWSTR lpszKey, LPUNKNOWN FAR* ppunk)
{
M_PROLOG(this);
VDATEPTROUT(ppunk, LPUNKNOWN);
*ppunk = NULL;
VDATEPTRIN(lpszKey, WCHAR);
LPVOID pNewValue = (LPVOID)(*ppunk);
if (m_pMap != NULL && m_pMap->Lookup(lpszKey, pNewValue))
{
*ppunk = (LPUNKNOWN)pNewValue;
(*ppunk)->AddRef();
return NOERROR;
}
return ResultFromScode(E_FAIL);
}
//BUGBUG: We should implement IBindCtx::EnumObjectParam.
STDMETHODIMP CBindCtx::EnumObjectParam
(THIS_ LPENUMSTRING FAR* ppenum)
{
M_PROLOG(this);
VDATEPTROUT(ppenum, LPENUMSTRING);
#ifdef NOTYET
*ppenum = new CEnumStringImpl( m_pMap );
if (*ppenum == NULL) return ResultFromScode(E_OUTOFMEMORY);
return NOERROR;
#else
*ppenum = NULL;
return ResultFromScode(E_NOTIMPL);
#endif
}
STDMETHODIMP CBindCtx::RevokeObjectParam
(THIS_ LPWSTR lpszKey)
{
M_PROLOG(this);
VDATEPTRIN(lpszKey, WCHAR);
LPVOID lpvoid;
if (m_pMap != NULL
&& (m_pMap->Lookup(lpszKey, lpvoid))
&& m_pMap->RemoveKey(lpszKey))
{
((LPUNKNOWN)lpvoid)->Release();
return NOERROR;
}
return ResultFromScode(E_FAIL);
}
#ifdef _DEBUG
STDMETHODIMP_(void) NC(CBindCtx,CDebug)::Dump( IDebugStream FAR * pdbstm)
{
VOID_VDATEIFACE(pdbstm);
NC(CBindCtx,CObjList) FAR * pCOL;
*pdbstm << "CBindCtx @" << (VOID FAR *)m_pBindCtx <<'\n';
pdbstm->Indent();
*pdbstm << "m_BindCtx is " << (VOID FAR *)&(m_pBindCtx)<<'\n';
*pdbstm << "Refcount is " << (int)(m_pBindCtx->m_refs) << '\n';
*pdbstm << "Registered objects: \n";
pdbstm->Indent();
for (pCOL = m_pBindCtx->m_pFirstObj; pCOL; pCOL = pCOL->m_pNext )
*pdbstm << (pCOL->m_punk);
pdbstm->UnIndent();
*pdbstm<<"End of registered objects \n";
pdbstm->UnIndent();
}
STDMETHODIMP_(BOOL) NC(CBindCtx,CDebug)::IsValid( BOOL fSuspicious )
{
return ((LONG)(m_pBindCtx->m_refs) > 0);
// add more later, maybe
}
#endif // _DEBUG
#ifdef NOTYET
NOTE: this code has to be fixed before used again: the ctor should
really fail if not enough memory is available and the next function
should copy the strings. An alternative implementation might be wise.
#pragma SEG(CEnumStringImpl_ctor)
CEnumStringImpl::CEnumStringImpl( CMapStringToPtr FAR * pMap )
{
LPWSTR lpsz;
LPWSTR lpszKey;
LPVOID lpvoid;
size_t n;
LI FAR * pli;
POSITION pos = pMap->GetStartPosition();
pliHead = NULL;
while (pos != NULL)
{
pMap->GetNextAssoc(pos, lpszKey, lpvoid );
lpsz = new FAR WCHAR[n = (1+_fstrlen(lpszKey))];
if (lpsz == NULL)
continue;
memcpy(lpsz, lpszKey, n * sizeof(WCHAR));
pli = new LI( lpsz );
if (pli)
{
pli->pliNext = pliHead;
pliHead = pli;
}
}
pliCurrent = pliHead;
m_refs = 1;
}
#pragma SEG(CEnumStringImpl_dtor)
CEnumStringImpl::~CEnumStringImpl( void )
{
LI FAR * pli = pliHead;
while (pli)
{
pliHead = pli->pliNext;
delete pli->lpszKey;
delete pli;
pli = pliHead;
}
}
#pragma SEG(CEnumStringImpl_Next)
STDMETHODIMP CEnumStringImpl::Next (ULONG celt,
LPWSTR FAR* reelt,
ULONG FAR* pceltFetched)
{
ULONG celtTemp = 0;
while (celtTemp < celt && pliCurrent)
{
reelt[celtTemp++] = pliCurrent->lpszKey;
pliCurrent = pliCurrent->pliNext;
}
if (pceltFetched) *pceltFetched = celtTemp;
return celtTemp == celt ? NOERROR : ResultFromScode(S_FALSE);
}
#pragma SEG(CEnumStringImpl_Skip)
STDMETHODIMP CEnumStringImpl::Skip (ULONG celt)
{
ULONG celtTemp = 0;
while (celtTemp < celt && pliCurrent)
pliCurrent = pliCurrent->pliNext;
return celtTemp == celt ? NOERROR : ResultFromScode(S_FALSE);
}
#pragma SEG(CEnumStringImpl_Reset)
STDMETHODIMP CEnumStringImpl::Reset (void)
{
pliCurrent = pliHead;
return NOERROR;
}
#pragma SEG(CEnumStringImpl_Clone)
STDMETHODIMP CEnumStringImpl::Clone (LPENUMSTRING FAR* ppenm)
{
// REVIEW : to be implemented
VDATEPTROUT(ppenm, LPENUMSTRING);
*ppenm = NULL;
return ResultFromScode(E_NOTIMPL);
}
#endif // NOTYET