|
|
// This is a part of the Active Template Library.
// Copyright (C) 1996-1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.
#ifndef __ATLBASE_H__
#error atlimpl.cpp requires atlbase.h to be included first
#endif
extern "C" const IID IID_IRegistrar = {0x44EC053B,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; #ifndef _ATL_DLL_IMPL
extern "C" const CLSID CLSID_Registrar = {0x44EC053A,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; #endif
#include <atlconv.cpp>
#ifdef _DEBUG
#include <stdio.h>
#include <stdarg.h>
#endif
#ifndef ATL_NO_NAMESPACE
namespace ATL { #endif
// used in thread pooling
UINT CComApartment::ATL_CREATE_OBJECT = 0;
#ifdef __ATLCOM_H__
/////////////////////////////////////////////////////////////////////////////
// AtlReportError
HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, const IID& iid, HRESULT hRes, HINSTANCE hInst) { return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), 0, NULL, iid, hRes, hInst); }
HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst) { return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), dwHelpID, lpszHelpFile, iid, hRes, hInst); }
#ifndef OLE2ANSI
HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc, DWORD dwHelpID, LPCSTR lpszHelpFile, const IID& iid, HRESULT hRes) { _ASSERTE(lpszDesc != NULL); USES_CONVERSION; return AtlSetErrorInfo(clsid, A2COLE(lpszDesc), dwHelpID, A2CW(lpszHelpFile), iid, hRes, NULL); }
HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc, const IID& iid, HRESULT hRes) { _ASSERTE(lpszDesc != NULL); USES_CONVERSION; return AtlSetErrorInfo(clsid, A2COLE(lpszDesc), 0, NULL, iid, hRes, NULL); } #endif
HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, const IID& iid, HRESULT hRes) { return AtlSetErrorInfo(clsid, lpszDesc, 0, NULL, iid, hRes, NULL); }
HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes) { return AtlSetErrorInfo(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes, NULL); }
#endif //__ATLCOM_H__
/////////////////////////////////////////////////////////////////////////////
// CComBSTR
CComBSTR& CComBSTR::operator=(const CComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.Copy(); } return *this; }
CComBSTR& CComBSTR::operator=(LPCOLESTR pSrc) { ::SysFreeString(m_str); m_str = ::SysAllocString(pSrc); return *this; }
void CComBSTR::Append(LPCOLESTR lpsz, int nLen) { int n1 = Length(); BSTR b = SysAllocStringLen(NULL, n1+nLen); memcpy(b, m_str, n1*sizeof(OLECHAR)); memcpy(b+n1, lpsz, nLen*sizeof(OLECHAR)); b[n1+nLen] = NULL; SysFreeString(m_str); m_str = b; }
#ifndef OLE2ANSI
void CComBSTR::Append(LPCSTR lpsz) { USES_CONVERSION; LPCOLESTR lpo = A2COLE(lpsz); Append(lpo, ocslen(lpo)); }
CComBSTR::CComBSTR(LPCSTR pSrc) { USES_CONVERSION; m_str = ::SysAllocString(A2COLE(pSrc)); }
CComBSTR::CComBSTR(int nSize, LPCSTR sz) { USES_CONVERSION; m_str = ::SysAllocStringLen(A2COLE(sz), nSize); }
CComBSTR& CComBSTR::operator=(LPCSTR pSrc) { USES_CONVERSION; ::SysFreeString(m_str); m_str = ::SysAllocString(A2COLE(pSrc)); return *this; } #endif
HRESULT CComBSTR::ReadFromStream(IStream* pStream) { _ASSERTE(pStream != NULL); _ASSERTE(m_str == NULL); // should be empty
ULONG cb; ULONG cbStrLen; HRESULT hr = pStream->Read((void*) &cbStrLen, sizeof(cbStrLen), &cb); if (FAILED(hr)) return hr; if (cbStrLen != 0) { //subtract size for terminating NULL which we wrote out
//since SysAllocStringByteLen overallocates for the NULL
m_str = SysAllocStringByteLen(NULL, cbStrLen-sizeof(OLECHAR)); if (m_str == NULL) hr = E_OUTOFMEMORY; else hr = pStream->Read((void*) m_str, cbStrLen, &cb); } return hr; }
HRESULT CComBSTR::WriteToStream(IStream* pStream) { _ASSERTE(pStream != NULL); ULONG cb; ULONG cbStrLen = m_str ? SysStringByteLen(m_str)+sizeof(OLECHAR) : 0; HRESULT hr = pStream->Write((void*) &cbStrLen, sizeof(cbStrLen), &cb); if (FAILED(hr)) return hr; return cbStrLen ? pStream->Write((void*) m_str, cbStrLen, &cb) : S_OK; }
/////////////////////////////////////////////////////////////////////////////
// CComVariant
CComVariant& CComVariant::operator=(BSTR bstrSrc) { InternalClear(); vt = VT_BSTR; bstrVal = ::SysAllocString(bstrSrc); if (bstrVal == NULL && bstrSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; }
CComVariant& CComVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; bstrVal = ::SysAllocString(lpszSrc);
if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; }
#ifndef OLE2ANSI
CComVariant& CComVariant::operator=(LPCSTR lpszSrc) { USES_CONVERSION; InternalClear(); vt = VT_BSTR; bstrVal = ::SysAllocString(A2COLE(lpszSrc));
if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; } #endif
#if _MSC_VER>1020
CComVariant& CComVariant::operator=(bool bSrc) { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } #pragma warning(disable: 4310) // cast truncates constant value
boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; #pragma warning(default: 4310) // cast truncates constant value
return *this; } #endif
CComVariant& CComVariant::operator=(int nSrc) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = nSrc;
return *this; }
CComVariant& CComVariant::operator=(BYTE nSrc) { if (vt != VT_UI1) { InternalClear(); vt = VT_UI1; } bVal = nSrc; return *this; }
CComVariant& CComVariant::operator=(short nSrc) { if (vt != VT_I2) { InternalClear(); vt = VT_I2; } iVal = nSrc; return *this; }
CComVariant& CComVariant::operator=(long nSrc) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = nSrc; return *this; }
CComVariant& CComVariant::operator=(float fltSrc) { if (vt != VT_R4) { InternalClear(); vt = VT_R4; } fltVal = fltSrc; return *this; }
CComVariant& CComVariant::operator=(double dblSrc) { if (vt != VT_R8) { InternalClear(); vt = VT_R8; } dblVal = dblSrc; return *this; }
CComVariant& CComVariant::operator=(CY cySrc) { if (vt != VT_CY) { InternalClear(); vt = VT_CY; } cyVal.Hi = cySrc.Hi; cyVal.Lo = cySrc.Lo; return *this; }
CComVariant& CComVariant::operator=(IDispatch* pSrc) { InternalClear(); vt = VT_DISPATCH; pdispVal = pSrc; // Need to AddRef as VariantClear will Release
if (pdispVal != NULL) pdispVal->AddRef(); return *this; }
CComVariant& CComVariant::operator=(IUnknown* pSrc) { InternalClear(); vt = VT_UNKNOWN; punkVal = pSrc;
// Need to AddRef as VariantClear will Release
if (punkVal != NULL) punkVal->AddRef(); return *this; }
#if _MSC_VER>1020
bool CComVariant::operator==(const VARIANT& varSrc) { if (this == &varSrc) return true;
// Variants not equal if types don't match
if (vt != varSrc.vt) return false;
// Check type specific values
switch (vt) { case VT_EMPTY: case VT_NULL: return true;
case VT_BOOL: return boolVal == varSrc.boolVal;
case VT_UI1: return bVal == varSrc.bVal;
case VT_I2: return iVal == varSrc.iVal;
case VT_I4: return lVal == varSrc.lVal;
case VT_R4: return fltVal == varSrc.fltVal;
case VT_R8: return dblVal == varSrc.dblVal;
case VT_BSTR: return (::SysStringByteLen(bstrVal) == ::SysStringByteLen(varSrc.bstrVal)) && (::memcmp(bstrVal, varSrc.bstrVal, ::SysStringByteLen(bstrVal)) == 0);
case VT_ERROR: return scode == varSrc.scode;
case VT_DISPATCH: return pdispVal == varSrc.pdispVal;
case VT_UNKNOWN: return punkVal == varSrc.punkVal;
default: _ASSERTE(false); // fall through
}
return false; } #else
BOOL CComVariant::operator==(const VARIANT& varSrc) { if (this == &varSrc) return TRUE;
// Variants not equal if types don't match
if (vt != varSrc.vt) return FALSE;
// Check type specific values
switch (vt) { case VT_EMPTY: case VT_NULL: return TRUE;
case VT_BOOL: return boolVal == varSrc.boolVal;
case VT_UI1: return bVal == varSrc.bVal;
case VT_I2: return iVal == varSrc.iVal;
case VT_I4: return lVal == varSrc.lVal;
case VT_R4: return fltVal == varSrc.fltVal;
case VT_R8: return dblVal == varSrc.dblVal;
case VT_BSTR: return (::SysStringByteLen(bstrVal) == ::SysStringByteLen(varSrc.bstrVal)) && (::memcmp(bstrVal, varSrc.bstrVal, ::SysStringByteLen(bstrVal)) == 0);
case VT_ERROR: return scode == varSrc.scode;
case VT_DISPATCH: return pdispVal == varSrc.pdispVal;
case VT_UNKNOWN: return punkVal == varSrc.punkVal;
default: _ASSERTE(FALSE); // fall through
}
return FALSE; } #endif
HRESULT CComVariant::Attach(VARIANT* pSrc) { // Clear out the variant
HRESULT hr = Clear(); if (!FAILED(hr)) { // Copy the contents and give control to CComVariant
memcpy(this, pSrc, sizeof(VARIANT)); VariantInit(pSrc); hr = S_OK; } return hr; }
HRESULT CComVariant::Detach(VARIANT* pDest) { // Clear out the variant
HRESULT hr = ::VariantClear(pDest); if (!FAILED(hr)) { // Copy the contents and remove control from CComVariant
memcpy(pDest, this, sizeof(VARIANT)); vt = VT_EMPTY; hr = S_OK; } return hr; }
HRESULT CComVariant::ChangeType(VARTYPE vtNew, const VARIANT* pSrc) { VARIANT* pVar = const_cast<VARIANT*>(pSrc); // Convert in place if pSrc is NULL
if (pVar == NULL) pVar = this; // Do nothing if doing in place convert and vts not different
return ::VariantChangeType(this, pVar, 0, vtNew); }
HRESULT CComVariant::InternalClear() { HRESULT hr = Clear(); _ASSERTE(SUCCEEDED(hr)); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; }
void CComVariant::InternalCopy(const VARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } }
HRESULT CComVariant::WriteToStream(IStream* pStream) { HRESULT hr = pStream->Write(&vt, sizeof(VARTYPE), NULL); if (FAILED(hr)) return hr;
int cbWrite = 0; switch (vt) { case VT_UNKNOWN: case VT_DISPATCH: { CComPtr<IPersistStream> spStream; if (punkVal != NULL) { hr = punkVal->QueryInterface(IID_IPersistStream, (void**)&spStream); if (FAILED(hr)) return hr; } if (spStream != NULL) return OleSaveToStream(spStream, pStream); else return WriteClassStm(pStream, CLSID_NULL); } case VT_UI1: case VT_I1: cbWrite = sizeof(BYTE); break; case VT_I2: case VT_UI2: case VT_BOOL: cbWrite = sizeof(short); break; case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: cbWrite = sizeof(long); break; case VT_R8: case VT_CY: case VT_DATE: cbWrite = sizeof(double); break; default: break; } if (cbWrite != 0) return pStream->Write((void*) &bVal, cbWrite, NULL);
CComBSTR bstrWrite; CComVariant varBSTR; if (vt != VT_BSTR) { hr = VariantChangeType(&varBSTR, this, VARIANT_NOVALUEPROP, VT_BSTR); if (FAILED(hr)) return hr; bstrWrite = varBSTR.bstrVal; } else bstrWrite = bstrVal;
return bstrWrite.WriteToStream(pStream); }
HRESULT CComVariant::ReadFromStream(IStream* pStream) { _ASSERTE(pStream != NULL); HRESULT hr; hr = VariantClear(this); if (FAILED(hr)) return hr; VARTYPE vtRead; hr = pStream->Read(&vtRead, sizeof(VARTYPE), NULL); if (FAILED(hr)) return hr;
vt = vtRead; int cbRead = 0; switch (vtRead) { case VT_UNKNOWN: case VT_DISPATCH: { punkVal = NULL; hr = OleLoadFromStream(pStream, (vtRead == VT_UNKNOWN) ? IID_IUnknown : IID_IDispatch, (void**)&punkVal); if (hr == REGDB_E_CLASSNOTREG) hr = S_OK; return S_OK; } case VT_UI1: case VT_I1: cbRead = sizeof(BYTE); break; case VT_I2: case VT_UI2: case VT_BOOL: cbRead = sizeof(short); break; case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: cbRead = sizeof(long); break; case VT_R8: case VT_CY: case VT_DATE: cbRead = sizeof(double); break; default: break; } if (cbRead != 0) return pStream->Read((void*) &bVal, cbRead, NULL); CComBSTR bstrRead;
hr = bstrRead.ReadFromStream(pStream); if (FAILED(hr)) return hr; vt = VT_BSTR; bstrVal = bstrRead.Detach(); if (vtRead != VT_BSTR) hr = ChangeType(vtRead); return hr; }
#ifdef __ATLCOM_H__
/////////////////////////////////////////////////////////////////////////////
// CComTypeInfoHolder
void CComTypeInfoHolder::AddRef() { EnterCriticalSection(&_Module.m_csTypeInfoHolder); m_dwRef++; LeaveCriticalSection(&_Module.m_csTypeInfoHolder); }
void CComTypeInfoHolder::Release() { EnterCriticalSection(&_Module.m_csTypeInfoHolder); if (--m_dwRef == 0) { if (m_pInfo != NULL) m_pInfo->Release(); m_pInfo = NULL; } LeaveCriticalSection(&_Module.m_csTypeInfoHolder); }
HRESULT CComTypeInfoHolder::GetTI(LCID lcid, ITypeInfo** ppInfo) { //If this assert occurs then most likely didn't initialize properly
_ASSERTE(m_plibid != NULL && m_pguid != NULL); _ASSERTE(ppInfo != NULL); *ppInfo = NULL;
HRESULT hRes = E_FAIL; EnterCriticalSection(&_Module.m_csTypeInfoHolder); if (m_pInfo == NULL) { ITypeLib* pTypeLib; hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib); if (SUCCEEDED(hRes)) { ITypeInfo* pTypeInfo; hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &pTypeInfo); if (SUCCEEDED(hRes)) m_pInfo = pTypeInfo; pTypeLib->Release(); } } *ppInfo = m_pInfo; if (m_pInfo != NULL) { m_pInfo->AddRef(); hRes = S_OK; } LeaveCriticalSection(&_Module.m_csTypeInfoHolder); return hRes; }
HRESULT CComTypeInfoHolder::GetTypeInfo(UINT /*itinfo*/, LCID lcid, ITypeInfo** pptinfo) { HRESULT hRes = E_POINTER; if (pptinfo != NULL) hRes = GetTI(lcid, pptinfo); return hRes; }
HRESULT CComTypeInfoHolder::GetIDsOfNames(REFIID /*riid*/, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid) { ITypeInfo* pInfo; HRESULT hRes = GetTI(lcid, &pInfo); if (pInfo != NULL) { hRes = pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid); pInfo->Release(); } return hRes; }
HRESULT CComTypeInfoHolder::Invoke(IDispatch* p, DISPID dispidMember, REFIID /*riid*/, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr) { SetErrorInfo(0, NULL); ITypeInfo* pInfo; HRESULT hRes = GetTI(lcid, &pInfo); if (pInfo != NULL) { hRes = pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); pInfo->Release(); } return hRes; }
/////////////////////////////////////////////////////////////////////////////
// QI implementation
#ifdef _ATL_DEBUG_QI
HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr) { USES_CONVERSION; CRegKey key; TCHAR szName[100]; DWORD dwType,dw = sizeof(szName);
LPOLESTR pszGUID = NULL; StringFromCLSID(iid, &pszGUID); OutputDebugString(pszClassName); OutputDebugString(_T(" - "));
// Attempt to find it in the interfaces section
key.Open(HKEY_CLASSES_ROOT, _T("Interface")); if (key.Open(key, OLE2T(pszGUID)) == S_OK) { *szName = 0; RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw); OutputDebugString(szName); goto cleanup; } // Attempt to find it in the clsid section
key.Open(HKEY_CLASSES_ROOT, _T("CLSID")); if (key.Open(key, OLE2T(pszGUID)) == S_OK) { *szName = 0; RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw); OutputDebugString(_T("(CLSID\?\?\?) ")); OutputDebugString(szName); goto cleanup; } OutputDebugString(OLE2T(pszGUID)); cleanup: if (hr != S_OK) OutputDebugString(_T(" - failed")); OutputDebugString(_T("\n")); CoTaskMemFree(pszGUID); return hr; } #endif
HRESULT WINAPI CComObjectRootBase::_Break(void* /* pv */, REFIID iid, void** /* ppvObject */, DWORD_PTR /* dw */) { iid; _ATLDUMPIID(iid, _T("Break due to QI for interface "), S_OK); #ifdef _DEBUG
DebugBreak(); #endif
return S_FALSE; }
HRESULT WINAPI CComObjectRootBase::_NoInterface(void* /* pv */, REFIID /* iid */, void** /* ppvObject */, DWORD_PTR /* dw */) { return E_NOINTERFACE; }
HRESULT WINAPI CComObjectRootBase::_Creator(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) { _ATL_CREATORDATA* pcd = (_ATL_CREATORDATA*)dw; return pcd->pFunc(pv, iid, ppvObject); }
HRESULT WINAPI CComObjectRootBase::_Delegate(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) { HRESULT hRes = E_NOINTERFACE; IUnknown* p = *(IUnknown**)((DWORD_PTR)pv + dw); if (p != NULL) hRes = p->QueryInterface(iid, ppvObject); return hRes; }
HRESULT WINAPI CComObjectRootBase::_Chain(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) { _ATL_CHAINDATA* pcd = (_ATL_CHAINDATA*)dw; void* p = (void*)((DWORD_PTR)pv + pcd->dwOffset); return InternalQueryInterface(p, pcd->pFunc(), iid, ppvObject); }
HRESULT WINAPI CComObjectRootBase::_Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) { HRESULT hRes = E_NOINTERFACE; _ATL_CACHEDATA* pcd = (_ATL_CACHEDATA*)dw; IUnknown** pp = (IUnknown**)((DWORD_PTR)pv + pcd->dwOffsetVar); if (*pp == NULL) hRes = pcd->pFunc(pv, IID_IUnknown, (void**)pp); if (*pp != NULL) hRes = (*pp)->QueryInterface(iid, ppvObject); return hRes; }
/////////////////////////////////////////////////////////////////////////////
// CComClassFactory
STDMETHODIMP CComClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) { _ASSERTE(m_pfnCreateInstance != NULL); HRESULT hRes = E_POINTER; if (ppvObj != NULL) { *ppvObj = NULL; // can't ask for anything other than IUnknown when aggregating
_ASSERTE((pUnkOuter == NULL) || InlineIsEqualUnknown(riid)); if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid)) hRes = CLASS_E_NOAGGREGATION; else hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj); } return hRes; }
STDMETHODIMP CComClassFactory::LockServer(BOOL fLock) { if (fLock) _Module.Lock(); else _Module.Unlock(); return S_OK; }
STDMETHODIMP CComClassFactory2Base::LockServer(BOOL fLock) { if (fLock) _Module.Lock(); else _Module.Unlock(); return S_OK; }
#ifndef _ATL_NO_CONNECTION_POINTS
/////////////////////////////////////////////////////////////////////////////
// Connection Points
DWORD CComDynamicUnkArray::Add(IUnknown* pUnk) { ULONG iIndex; IUnknown** pp = NULL; if (m_nSize == 0) // no connections
{ m_pUnk = pUnk; m_nSize = 1; return 1; } else if (m_nSize == 1) { //create array
pp = (IUnknown**)malloc(sizeof(IUnknown*)*_DEFAULT_VECTORLENGTH); if (pp == NULL) return 0; memset(pp, 0, sizeof(IUnknown*)*_DEFAULT_VECTORLENGTH); *pp = m_pUnk; m_ppUnk = pp; m_nSize = _DEFAULT_VECTORLENGTH; } for (pp = begin();pp<end();pp++) { if (*pp == NULL) { *pp = pUnk; iIndex = ULONG((pp-begin())); return iIndex+1; } } int nAlloc = m_nSize*2; pp = (IUnknown**)realloc(m_ppUnk, sizeof(IUnknown*)*nAlloc); if (pp == NULL) return 0; m_ppUnk = pp; memset(&m_ppUnk[m_nSize], 0, sizeof(IUnknown*)*m_nSize); m_ppUnk[m_nSize] = pUnk; iIndex = m_nSize; m_nSize = nAlloc; return iIndex+1; }
BOOL CComDynamicUnkArray::Remove(DWORD dwCookie) { ULONG iIndex; if (dwCookie == NULL) return FALSE; if (m_nSize == 0) return FALSE; iIndex = dwCookie-1; if (iIndex >= (ULONG)m_nSize) { return FALSE; } if (m_nSize == 1) { m_nSize = 0; return TRUE; } begin()[iIndex] = NULL; return TRUE; }
#endif //!_ATL_NO_CONNECTION_POINTS
#endif //__ATLCOM_H__
/////////////////////////////////////////////////////////////////////////////
// Object Registry Support
static HRESULT WINAPI AtlRegisterProgID(LPCTSTR lpszCLSID, LPCTSTR lpszProgID, LPCTSTR lpszUserDesc) { CRegKey keyProgID; LONG lRes = keyProgID.Create(HKEY_CLASSES_ROOT, lpszProgID); if (lRes == ERROR_SUCCESS) { keyProgID.SetValue(lpszUserDesc); keyProgID.SetKeyValue(_T("CLSID"), lpszCLSID); return S_OK; } return HRESULT_FROM_WIN32(lRes); }
void CComModule::AddCreateWndData(_AtlCreateWndData* pData, void* pObject) { pData->m_pThis = pObject; pData->m_dwThreadID = ::GetCurrentThreadId(); ::EnterCriticalSection(&m_csWindowCreate); pData->m_pNext = m_pCreateWndList; m_pCreateWndList = pData; ::LeaveCriticalSection(&m_csWindowCreate); }
void* CComModule::ExtractCreateWndData() { ::EnterCriticalSection(&m_csWindowCreate); _AtlCreateWndData* pEntry = m_pCreateWndList; if(pEntry == NULL) { ::LeaveCriticalSection(&m_csWindowCreate); return NULL; }
DWORD dwThreadID = ::GetCurrentThreadId(); _AtlCreateWndData* pPrev = NULL; while(pEntry != NULL) { if(pEntry->m_dwThreadID == dwThreadID) { if(pPrev == NULL) m_pCreateWndList = pEntry->m_pNext; else pPrev->m_pNext = pEntry->m_pNext; ::LeaveCriticalSection(&m_csWindowCreate); return pEntry->m_pThis; } pPrev = pEntry; pEntry = pEntry->m_pNext; }
::LeaveCriticalSection(&m_csWindowCreate); return NULL; }
#ifdef _ATL_STATIC_REGISTRY
// Statically linking to Registry Ponent
HRESULT WINAPI CComModule::UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries) { USES_CONVERSION; CRegObject ro; TCHAR szModule[_MAX_PATH]; GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH); LPOLESTR pszModule = T2OLE(szModule); ro.AddReplacement(OLESTR("Module"), pszModule); if (NULL != pMapEntries) { while (NULL != pMapEntries->szKey) { _ASSERTE(NULL != pMapEntries->szData); ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData); pMapEntries++; } }
LPCOLESTR szType = OLESTR("REGISTRY"); return (bRegister) ? ro.ResourceRegister(pszModule, nResID, szType) : ro.ResourceUnregister(pszModule, nResID, szType); }
HRESULT WINAPI CComModule::UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries) { USES_CONVERSION; CRegObject ro; TCHAR szModule[_MAX_PATH]; GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH); LPOLESTR pszModule = T2OLE(szModule); ro.AddReplacement(OLESTR("Module"), pszModule); if (NULL != pMapEntries) { while (NULL != pMapEntries->szKey) { _ASSERTE(NULL != pMapEntries->szData); ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData); pMapEntries++; } }
LPCOLESTR szType = OLESTR("REGISTRY"); LPCOLESTR pszRes = T2COLE(lpszRes); return (bRegister) ? ro.ResourceRegisterSz(pszModule, pszRes, szType) : ro.ResourceUnregisterSz(pszModule, pszRes, szType); } #endif // _ATL_STATIC_REGISTRY
HRESULT WINAPI CComModule::UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister) { if (bRegister) { return RegisterClassHelper(clsid, lpszProgID, lpszVerIndProgID, nDescID, dwFlags); } else return UnregisterClassHelper(clsid, lpszProgID, lpszVerIndProgID); }
HRESULT WINAPI CComModule::RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags) { static const TCHAR szProgID[] = _T("ProgID"); static const TCHAR szVIProgID[] = _T("VersionIndependentProgID"); static const TCHAR szLS32[] = _T("LocalServer32"); static const TCHAR szIPS32[] = _T("InprocServer32"); static const TCHAR szThreadingModel[] = _T("ThreadingModel"); static const TCHAR szAUTPRX32[] = _T("AUTPRX32.DLL"); static const TCHAR szApartment[] = _T("Apartment"); static const TCHAR szBoth[] = _T("both"); USES_CONVERSION; HRESULT hRes = S_OK; TCHAR szDesc[256]; LoadString(m_hInst, nDescID, szDesc, 256); TCHAR szModule[_MAX_PATH]; GetModuleFileName(m_hInst, szModule, _MAX_PATH);
LPOLESTR lpOleStr; StringFromCLSID(clsid, &lpOleStr); LPTSTR lpsz = OLE2T(lpOleStr);
hRes = AtlRegisterProgID(lpsz, lpszProgID, szDesc); if (hRes == S_OK) hRes = AtlRegisterProgID(lpsz, lpszVerIndProgID, szDesc); LONG lRes = ERROR_SUCCESS; if (hRes == S_OK) { CRegKey key; LONG lRes = key.Open(HKEY_CLASSES_ROOT, _T("CLSID")); if (lRes == ERROR_SUCCESS) { lRes = key.Create(key, lpsz); if (lRes == ERROR_SUCCESS) { key.SetValue(szDesc); key.SetKeyValue(szProgID, lpszProgID); key.SetKeyValue(szVIProgID, lpszVerIndProgID);
if ((m_hInst == NULL) || (m_hInst == GetModuleHandle(NULL))) // register as EXE
key.SetKeyValue(szLS32, szModule); else { key.SetKeyValue(szIPS32, (dwFlags & AUTPRXFLAG) ? szAUTPRX32 : szModule); LPCTSTR lpszModel = (dwFlags & THREADFLAGS_BOTH) ? szBoth : (dwFlags & THREADFLAGS_APARTMENT) ? szApartment : NULL; if (lpszModel != NULL) key.SetKeyValue(szIPS32, lpszModel, szThreadingModel); } } } } CoTaskMemFree(lpOleStr); if (lRes != ERROR_SUCCESS) hRes = HRESULT_FROM_WIN32(lRes); return hRes; }
HRESULT WINAPI CComModule::UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID) { USES_CONVERSION; CRegKey key;
key.Attach(HKEY_CLASSES_ROOT); if (lpszProgID != NULL && lstrcmpi(lpszProgID, _T(""))) key.RecurseDeleteKey(lpszProgID); if (lpszVerIndProgID != NULL && lstrcmpi(lpszVerIndProgID, _T(""))) key.RecurseDeleteKey(lpszVerIndProgID); LPOLESTR lpOleStr; StringFromCLSID(clsid, &lpOleStr); LPTSTR lpsz = OLE2T(lpOleStr); if (key.Open(key, _T("CLSID")) == ERROR_SUCCESS) key.RecurseDeleteKey(lpsz); CoTaskMemFree(lpOleStr); return S_OK; }
/////////////////////////////////////////////////////////////////////////////
// CRegKey
LONG CRegKey::Close() { LONG lRes = ERROR_SUCCESS; if (m_hKey != NULL) { lRes = RegCloseKey(m_hKey); m_hKey = NULL; } return lRes; }
LONG CRegKey::Create(HKEY hKeyParent, LPCTSTR lpszKeyName, LPTSTR lpszClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecAttr, LPDWORD lpdwDisposition) { _ASSERTE(hKeyParent != NULL); DWORD dw; HKEY hKey = NULL; LONG lRes = RegCreateKeyEx(hKeyParent, lpszKeyName, 0, lpszClass, dwOptions, samDesired, lpSecAttr, &hKey, &dw); if (lpdwDisposition != NULL) *lpdwDisposition = dw; if (lRes == ERROR_SUCCESS) { lRes = Close(); m_hKey = hKey; } return lRes; }
LONG CRegKey::Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired) { _ASSERTE(hKeyParent != NULL); HKEY hKey = NULL; LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey); if (lRes == ERROR_SUCCESS) { lRes = Close(); _ASSERTE(lRes == ERROR_SUCCESS); m_hKey = hKey; } return lRes; }
LONG CRegKey::QueryValue(DWORD& dwValue, LPCTSTR lpszValueName) { DWORD dwType = NULL; DWORD dwCount = sizeof(DWORD); LONG lRes = RegQueryValueEx(m_hKey, (LPTSTR)lpszValueName, NULL, &dwType, (LPBYTE)&dwValue, &dwCount); _ASSERTE((lRes!=ERROR_SUCCESS) || (dwType == REG_DWORD)); _ASSERTE((lRes!=ERROR_SUCCESS) || (dwCount == sizeof(DWORD))); return lRes; }
LONG CRegKey::QueryValue(LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount) { _ASSERTE(pdwCount != NULL); DWORD dwType = NULL; LONG lRes = RegQueryValueEx(m_hKey, (LPTSTR)lpszValueName, NULL, &dwType, (LPBYTE)szValue, pdwCount); _ASSERTE((lRes!=ERROR_SUCCESS) || (dwType == REG_SZ) || (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ)); return lRes; }
LONG WINAPI CRegKey::SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName) { _ASSERTE(lpszValue != NULL); CRegKey key; LONG lRes = key.Create(hKeyParent, lpszKeyName); if (lRes == ERROR_SUCCESS) lRes = key.SetValue(lpszValue, lpszValueName); return lRes; }
LONG CRegKey::SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName) { _ASSERTE(lpszValue != NULL); CRegKey key; LONG lRes = key.Create(m_hKey, lpszKeyName); if (lRes == ERROR_SUCCESS) lRes = key.SetValue(lpszValue, lpszValueName); return lRes; }
LONG CRegKey::SetValue(DWORD dwValue, LPCTSTR lpszValueName) { _ASSERTE(m_hKey != NULL); return RegSetValueEx(m_hKey, lpszValueName, NULL, REG_DWORD, (BYTE * const)&dwValue, sizeof(DWORD)); }
HRESULT CRegKey::SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName) { _ASSERTE(lpszValue != NULL); _ASSERTE(m_hKey != NULL); return RegSetValueEx(m_hKey, lpszValueName, NULL, REG_SZ, (BYTE * const)lpszValue, (lstrlen(lpszValue)+1)*sizeof(TCHAR)); }
//RecurseDeleteKey is necessary because on NT RegDeleteKey doesn't work if the
//specified key has subkeys
LONG CRegKey::RecurseDeleteKey(LPCTSTR lpszKey) { CRegKey key; LONG lRes = key.Open(m_hKey, lpszKey); if (lRes != ERROR_SUCCESS) return lRes; FILETIME time; TCHAR szBuffer[256]; DWORD dwSize = 256; while (RegEnumKeyEx(key.m_hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time)==ERROR_SUCCESS) { lRes = key.RecurseDeleteKey(szBuffer); if (lRes != ERROR_SUCCESS) return lRes; dwSize = 256; } key.Close(); return DeleteSubKey(lpszKey); }
#ifdef __ATLCOM_H__
#ifndef _ATL_NO_SECURITY
CSecurityDescriptor::CSecurityDescriptor() { m_pSD = NULL; m_pOwner = NULL; m_pGroup = NULL; m_pDACL = NULL; m_pSACL= NULL; }
CSecurityDescriptor::~CSecurityDescriptor() { if (m_pSD) delete m_pSD; if (m_pOwner) free(m_pOwner); if (m_pGroup) free(m_pGroup); if (m_pDACL) free(m_pDACL); if (m_pSACL) free(m_pSACL); }
HRESULT CSecurityDescriptor::Initialize() { if (m_pSD) { delete m_pSD; m_pSD = NULL; } if (m_pOwner) { free(m_pOwner); m_pOwner = NULL; } if (m_pGroup) { free(m_pGroup); m_pGroup = NULL; } if (m_pDACL) { free(m_pDACL); m_pDACL = NULL; } if (m_pSACL) { free(m_pSACL); m_pSACL = NULL; }
ATLTRY(m_pSD = new SECURITY_DESCRIPTOR); if (!m_pSD) return E_OUTOFMEMORY; if (!InitializeSecurityDescriptor(m_pSD, SECURITY_DESCRIPTOR_REVISION)) { HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); delete m_pSD; m_pSD = NULL; _ASSERTE(FALSE); return hr; } // Set the DACL to allow EVERYONE
SetSecurityDescriptorDacl(m_pSD, TRUE, NULL, FALSE); return S_OK; }
HRESULT CSecurityDescriptor::InitializeFromProcessToken(BOOL bDefaulted) { PSID pUserSid; PSID pGroupSid; HRESULT hr;
Initialize(); hr = GetProcessSids(&pUserSid, &pGroupSid); if (FAILED(hr)) return hr; hr = SetOwner(pUserSid, bDefaulted); if (FAILED(hr)) return hr; hr = SetGroup(pGroupSid, bDefaulted); if (FAILED(hr)) return hr; return S_OK; }
HRESULT CSecurityDescriptor::InitializeFromThreadToken(BOOL bDefaulted, BOOL bRevertToProcessToken) { PSID pUserSid; PSID pGroupSid; HRESULT hr;
Initialize(); hr = GetThreadSids(&pUserSid, &pGroupSid); if (HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken) hr = GetProcessSids(&pUserSid, &pGroupSid); if (FAILED(hr)) return hr; hr = SetOwner(pUserSid, bDefaulted); if (FAILED(hr)) return hr; hr = SetGroup(pGroupSid, bDefaulted); if (FAILED(hr)) return hr; return S_OK; }
HRESULT CSecurityDescriptor::SetOwner(PSID pOwnerSid, BOOL bDefaulted) { _ASSERTE(m_pSD);
// Mark the SD as having no owner
if (!SetSecurityDescriptorOwner(m_pSD, NULL, bDefaulted)) { HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); return hr; }
if (m_pOwner) { free(m_pOwner); m_pOwner = NULL; }
// If they asked for no owner don't do the copy
if (pOwnerSid == NULL) return S_OK;
// Make a copy of the Sid for the return value
DWORD dwSize = GetLengthSid(pOwnerSid);
m_pOwner = (PSID) malloc(dwSize); if (!m_pOwner) { // Insufficient memory to allocate Sid
_ASSERTE(FALSE); return E_OUTOFMEMORY; } if (!CopySid(dwSize, m_pOwner, pOwnerSid)) { HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); free(m_pOwner); m_pOwner = NULL; return hr; }
_ASSERTE(IsValidSid(m_pOwner));
if (!SetSecurityDescriptorOwner(m_pSD, m_pOwner, bDefaulted)) { HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); free(m_pOwner); m_pOwner = NULL; return hr; }
return S_OK; }
HRESULT CSecurityDescriptor::SetGroup(PSID pGroupSid, BOOL bDefaulted) { _ASSERTE(m_pSD);
// Mark the SD as having no Group
if (!SetSecurityDescriptorGroup(m_pSD, NULL, bDefaulted)) { HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); return hr; }
if (m_pGroup) { free(m_pGroup); m_pGroup = NULL; }
// If they asked for no Group don't do the copy
if (pGroupSid == NULL) return S_OK;
// Make a copy of the Sid for the return value
DWORD dwSize = GetLengthSid(pGroupSid);
m_pGroup = (PSID) malloc(dwSize); if (!m_pGroup) { // Insufficient memory to allocate Sid
_ASSERTE(FALSE); return E_OUTOFMEMORY; } if (!CopySid(dwSize, m_pGroup, pGroupSid)) { HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); free(m_pGroup); m_pGroup = NULL; return hr; }
_ASSERTE(IsValidSid(m_pGroup));
if (!SetSecurityDescriptorGroup(m_pSD, m_pGroup, bDefaulted)) { HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); free(m_pGroup); m_pGroup = NULL; return hr; }
return S_OK; }
HRESULT CSecurityDescriptor::Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask) { HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask); if (SUCCEEDED(hr)) SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE); return hr; }
HRESULT CSecurityDescriptor::Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask) { HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask); if (SUCCEEDED(hr)) SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE); return hr; }
HRESULT CSecurityDescriptor::Revoke(LPCTSTR pszPrincipal) { HRESULT hr = RemovePrincipalFromACL(m_pDACL, pszPrincipal); if (SUCCEEDED(hr)) SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE); return hr; }
HRESULT CSecurityDescriptor::GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid) { BOOL bRes; HRESULT hr; HANDLE hToken = NULL; if (ppUserSid) *ppUserSid = NULL; if (ppGroupSid) *ppGroupSid = NULL; bRes = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); if (!bRes) { // Couldn't open process token
hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); return hr; } hr = GetTokenSids(hToken, ppUserSid, ppGroupSid); return hr; }
HRESULT CSecurityDescriptor::GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid, BOOL bOpenAsSelf) { BOOL bRes; HRESULT hr; HANDLE hToken = NULL; if (ppUserSid) *ppUserSid = NULL; if (ppGroupSid) *ppGroupSid = NULL; bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken); if (!bRes) { // Couldn't open thread token
hr = HRESULT_FROM_WIN32(GetLastError()); return hr; } hr = GetTokenSids(hToken, ppUserSid, ppGroupSid); return hr; }
HRESULT CSecurityDescriptor::GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid) { DWORD dwSize; HRESULT hr; PTOKEN_USER ptkUser = NULL; PTOKEN_PRIMARY_GROUP ptkGroup = NULL;
if (ppUserSid) *ppUserSid = NULL; if (ppGroupSid) *ppGroupSid = NULL;
if (ppUserSid) { // Get length required for TokenUser by specifying buffer length of 0
GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize); hr = GetLastError(); if (hr != ERROR_INSUFFICIENT_BUFFER) { // Expected ERROR_INSUFFICIENT_BUFFER
_ASSERTE(FALSE); hr = HRESULT_FROM_WIN32(hr); goto failed; }
ptkUser = (TOKEN_USER*) malloc(dwSize); if (!ptkUser) { // Insufficient memory to allocate TOKEN_USER
_ASSERTE(FALSE); hr = E_OUTOFMEMORY; goto failed; } // Get Sid of process token.
if (!GetTokenInformation(hToken, TokenUser, ptkUser, dwSize, &dwSize)) { // Couldn't get user info
hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); goto failed; }
// Make a copy of the Sid for the return value
dwSize = GetLengthSid(ptkUser->User.Sid);
PSID pSid = (PSID) malloc(dwSize); if (!pSid) { // Insufficient memory to allocate Sid
_ASSERTE(FALSE); hr = E_OUTOFMEMORY; goto failed; } if (!CopySid(dwSize, pSid, ptkUser->User.Sid)) { hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); goto failed; }
_ASSERTE(IsValidSid(pSid)); *ppUserSid = pSid; free(ptkUser); } if (ppGroupSid) { // Get length required for TokenPrimaryGroup by specifying buffer length of 0
GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize); hr = GetLastError(); if (hr != ERROR_INSUFFICIENT_BUFFER) { // Expected ERROR_INSUFFICIENT_BUFFER
_ASSERTE(FALSE); hr = HRESULT_FROM_WIN32(hr); goto failed; }
ptkGroup = (TOKEN_PRIMARY_GROUP*) malloc(dwSize); if (!ptkGroup) { // Insufficient memory to allocate TOKEN_USER
_ASSERTE(FALSE); hr = E_OUTOFMEMORY; goto failed; } // Get Sid of process token.
if (!GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize)) { // Couldn't get user info
hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); goto failed; }
// Make a copy of the Sid for the return value
dwSize = GetLengthSid(ptkGroup->PrimaryGroup);
PSID pSid = (PSID) malloc(dwSize); if (!pSid) { // Insufficient memory to allocate Sid
_ASSERTE(FALSE); hr = E_OUTOFMEMORY; goto failed; } if (!CopySid(dwSize, pSid, ptkGroup->PrimaryGroup)) { hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); goto failed; }
_ASSERTE(IsValidSid(pSid));
*ppGroupSid = pSid; free(ptkGroup); }
return S_OK;
failed: if (ptkUser) free(ptkUser); if (ptkGroup) free (ptkGroup); return hr; }
HRESULT CSecurityDescriptor::GetCurrentUserSID(PSID *ppSid) { HANDLE tkHandle;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle)) { TOKEN_USER *tkUser; DWORD tkSize; DWORD sidLength;
// Call to get size information for alloc
GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize); tkUser = (TOKEN_USER *) malloc(tkSize);
// Now make the real call
if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize)) { sidLength = GetLengthSid(tkUser->User.Sid); *ppSid = (PSID) malloc(sidLength);
memcpy(*ppSid, tkUser->User.Sid, sidLength); CloseHandle(tkHandle);
free(tkUser); return S_OK; } else { free(tkUser); return HRESULT_FROM_WIN32(GetLastError()); } } return HRESULT_FROM_WIN32(GetLastError()); }
HRESULT CSecurityDescriptor::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid) { HRESULT hr; LPTSTR pszRefDomain = NULL; DWORD dwDomainSize = 0; DWORD dwSidSize = 0; SID_NAME_USE snu;
// Call to get size info for alloc
LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu);
hr = GetLastError(); if (hr != ERROR_INSUFFICIENT_BUFFER) return HRESULT_FROM_WIN32(hr);
ATLTRY(pszRefDomain = new TCHAR[dwDomainSize]); if (pszRefDomain == NULL) return E_OUTOFMEMORY;
*ppSid = (PSID) malloc(dwSidSize); if (*ppSid != NULL) { if (!LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu)) { free(*ppSid); *ppSid = NULL; delete[] pszRefDomain; return HRESULT_FROM_WIN32(GetLastError()); } delete[] pszRefDomain; return S_OK; } delete[] pszRefDomain; return E_OUTOFMEMORY; }
HRESULT CSecurityDescriptor::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD) { PACL pDACL = NULL; PACL pSACL = NULL; BOOL bDACLPresent, bSACLPresent; BOOL bDefaulted; PACL m_pDACL = NULL; ACCESS_ALLOWED_ACE* pACE; HRESULT hr; PSID pUserSid; PSID pGroupSid;
hr = Initialize(); if(FAILED(hr)) return hr;
// get the existing DACL.
if (!GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted)) goto failed;
if (bDACLPresent) { if (pDACL) { // allocate new DACL.
m_pDACL = (PACL) malloc(pDACL->AclSize); if (!m_pDACL) goto failed;
// initialize the DACL
if (!InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION)) goto failed;
// copy the ACES
for (int i = 0; i < pDACL->AceCount; i++) { if (!GetAce(pDACL, i, (void **)&pACE)) goto failed;
if (!AddAccessAllowedAce(m_pDACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart))) goto failed; }
if (!IsValidAcl(m_pDACL)) goto failed; }
// set the DACL
if (!SetSecurityDescriptorDacl(m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, bDefaulted)) goto failed; }
// get the existing SACL.
if (!GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted)) goto failed;
if (bSACLPresent) { if (pSACL) { // allocate new SACL.
m_pSACL = (PACL) malloc(pSACL->AclSize); if (!m_pSACL) goto failed;
// initialize the SACL
if (!InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION)) goto failed;
// copy the ACES
for (int i = 0; i < pSACL->AceCount; i++) { if (!GetAce(pSACL, i, (void **)&pACE)) goto failed;
if (!AddAccessAllowedAce(m_pSACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart))) goto failed; }
if (!IsValidAcl(m_pSACL)) goto failed; }
// set the SACL
if (!SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, bDefaulted)) goto failed; }
if (!GetSecurityDescriptorOwner(m_pSD, &pUserSid, &bDefaulted)) goto failed;
if (FAILED(SetOwner(pUserSid, bDefaulted))) goto failed;
if (!GetSecurityDescriptorGroup(m_pSD, &pGroupSid, &bDefaulted)) goto failed;
if (FAILED(SetGroup(pGroupSid, bDefaulted))) goto failed;
if (!IsValidSecurityDescriptor(m_pSD)) goto failed;
return hr;
failed: if (m_pDACL) free(m_pDACL); if (m_pSD) free(m_pSD); return E_UNEXPECTED; }
HRESULT CSecurityDescriptor::AttachObject(HANDLE hObject) { HRESULT hr; DWORD dwSize = 0; PSECURITY_DESCRIPTOR pSD = NULL;
GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, pSD, 0, &dwSize);
hr = GetLastError(); if (hr != ERROR_INSUFFICIENT_BUFFER) return HRESULT_FROM_WIN32(hr);
pSD = (PSECURITY_DESCRIPTOR) malloc(dwSize);
if (!GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize)) { hr = HRESULT_FROM_WIN32(GetLastError()); free(pSD); return hr; }
hr = Attach(pSD); free(pSD); return hr; }
HRESULT CSecurityDescriptor::CopyACL(PACL pDest, PACL pSrc) { ACL_SIZE_INFORMATION aclSizeInfo; LPVOID pAce; ACE_HEADER *aceHeader;
if (pSrc == NULL) return S_OK;
if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) return HRESULT_FROM_WIN32(GetLastError());
// Copy all of the ACEs to the new ACL
for (UINT i = 0; i < aclSizeInfo.AceCount; i++) { if (!GetAce(pSrc, i, &pAce)) return HRESULT_FROM_WIN32(GetLastError());
aceHeader = (ACE_HEADER *) pAce;
if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize)) return HRESULT_FROM_WIN32(GetLastError()); }
return S_OK; }
HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask) { ACL_SIZE_INFORMATION aclSizeInfo; int aclSize; DWORD returnValue; PSID principalSID; PACL oldACL, newACL;
oldACL = *ppAcl;
returnValue = GetPrincipalSID(pszPrincipal, &principalSID); if (FAILED(returnValue)) return returnValue;
aclSizeInfo.AclBytesInUse = 0; if (*ppAcl != NULL) GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
ATLTRY(newACL = (PACL) new BYTE[aclSize]);
if (!InitializeAcl(newACL, aclSize, ACL_REVISION)) { free(principalSID); return HRESULT_FROM_WIN32(GetLastError()); }
if (!AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID)) { free(principalSID); return HRESULT_FROM_WIN32(GetLastError()); }
returnValue = CopyACL(newACL, oldACL); if (FAILED(returnValue)) { free(principalSID); return returnValue; }
*ppAcl = newACL;
if (oldACL != NULL) free(oldACL); free(principalSID); return S_OK; }
HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask) { ACL_SIZE_INFORMATION aclSizeInfo; int aclSize; DWORD returnValue; PSID principalSID; PACL oldACL, newACL;
oldACL = *ppAcl;
returnValue = GetPrincipalSID(pszPrincipal, &principalSID); if (FAILED(returnValue)) return returnValue;
aclSizeInfo.AclBytesInUse = 0; if (*ppAcl != NULL) GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
ATLTRY(newACL = (PACL) new BYTE[aclSize]);
if (!InitializeAcl(newACL, aclSize, ACL_REVISION)) { free(principalSID); return HRESULT_FROM_WIN32(GetLastError()); }
returnValue = CopyACL(newACL, oldACL); if (FAILED(returnValue)) { free(principalSID); return returnValue; }
if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID)) { free(principalSID); return HRESULT_FROM_WIN32(GetLastError()); }
*ppAcl = newACL;
if (oldACL != NULL) free(oldACL); free(principalSID); return S_OK; }
HRESULT CSecurityDescriptor::RemovePrincipalFromACL(PACL pAcl, LPCTSTR pszPrincipal) { ACL_SIZE_INFORMATION aclSizeInfo; ULONG i; LPVOID ace; ACCESS_ALLOWED_ACE *accessAllowedAce; ACCESS_DENIED_ACE *accessDeniedAce; SYSTEM_AUDIT_ACE *systemAuditAce; PSID principalSID; DWORD returnValue; ACE_HEADER *aceHeader;
returnValue = GetPrincipalSID(pszPrincipal, &principalSID); if (FAILED(returnValue)) return returnValue;
GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
for (i = 0; i < aclSizeInfo.AceCount; i++) { if (!GetAce(pAcl, i, &ace)) { free(principalSID); return HRESULT_FROM_WIN32(GetLastError()); }
aceHeader = (ACE_HEADER *) ace;
if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart)) { DeleteAce(pAcl, i); free(principalSID); return S_OK; } } else
if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE) { accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart)) { DeleteAce(pAcl, i); free(principalSID); return S_OK; } } else
if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE) { systemAuditAce = (SYSTEM_AUDIT_ACE *) ace;
if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart)) { DeleteAce(pAcl, i); free(principalSID); return S_OK; } } } free(principalSID); return S_OK; }
HRESULT CSecurityDescriptor::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken) { HRESULT hr; TOKEN_PRIVILEGES tpPrevious; TOKEN_PRIVILEGES tp; DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); LUID luid;
// if no token specified open process token
if (hToken == 0) { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); return hr; } }
if (!LookupPrivilegeValue(NULL, privilege, &luid )) { hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); return hr; }
tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0;
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)) { hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); return hr; }
tpPrevious.PrivilegeCount = 1; tpPrevious.Privileges[0].Luid = luid;
if (bEnable) tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); else tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
if (!AdjustTokenPrivileges(hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL)) { hr = HRESULT_FROM_WIN32(GetLastError()); _ASSERTE(FALSE); return hr; } return S_OK; }
#endif //_ATL_NO_SECURITY
#endif //__ATLCOM_H__
#ifdef _DEBUG
void _cdecl AtlTrace(LPCTSTR lpszFormat, ...) { va_list args; va_start(args, lpszFormat);
int nBuf; TCHAR szBuffer[512];
nBuf = _vstprintf(szBuffer, lpszFormat, args); _ASSERTE(nBuf < sizeof(szBuffer));
OutputDebugString(szBuffer); va_end(args); } #endif
#ifndef ATL_NO_NAMESPACE
}; //namespace ATL
#endif
///////////////////////////////////////////////////////////////////////////////
//All Global stuff goes below this line
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Minimize CRT
// Specify DllMain as EntryPoint
// Turn off exception handling
// Define _ATL_MIN_CRT
#ifdef _ATL_MIN_CRT
/////////////////////////////////////////////////////////////////////////////
// Startup Code
#if defined(_WINDLL) || defined(_USRDLL)
// Declare DllMain
extern "C" BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved);
extern "C" BOOL WINAPI _DllMainCRTStartup(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved) { return DllMain(hDllHandle, dwReason, lpReserved); }
#else
// wWinMain is not defined in winbase.h.
extern "C" int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd);
#define SPACECHAR _T(' ')
#define DQUOTECHAR _T('\"')
#ifdef _UNICODE
extern "C" void wWinMainCRTStartup() #else // _UNICODE
extern "C" void WinMainCRTStartup() #endif // _UNICODE
{ LPTSTR lpszCommandLine = ::GetCommandLine(); if(lpszCommandLine == NULL) ::ExitProcess((UINT)-1);
// Skip past program name (first token in command line).
// Check for and handle quoted program name.
if(*lpszCommandLine == DQUOTECHAR) { // Scan, and skip over, subsequent characters until
// another double-quote or a null is encountered.
do { lpszCommandLine = ::CharNext(lpszCommandLine); } while((*lpszCommandLine != DQUOTECHAR) && (*lpszCommandLine != _T('\0')));
// If we stopped on a double-quote (usual case), skip over it.
if(*lpszCommandLine == DQUOTECHAR) lpszCommandLine = ::CharNext(lpszCommandLine); } else { while(*lpszCommandLine > SPACECHAR) lpszCommandLine = ::CharNext(lpszCommandLine); }
// Skip past any white space preceeding the second token.
while(*lpszCommandLine && (*lpszCommandLine <= SPACECHAR)) lpszCommandLine = ::CharNext(lpszCommandLine);
STARTUPINFO StartupInfo; StartupInfo.dwFlags = 0; ::GetStartupInfo(&StartupInfo);
int nRet = _tWinMain(::GetModuleHandle(NULL), NULL, lpszCommandLine, (StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ? StartupInfo.wShowWindow : SW_SHOWDEFAULT);
::ExitProcess((UINT)nRet); }
#endif // defined(_WINDLL) | defined(_USRDLL)
/////////////////////////////////////////////////////////////////////////////
// Heap Allocation
#ifndef _DEBUG
#ifndef _MERGE_PROXYSTUB
//rpcproxy.h does the same thing as this
int __cdecl _purecall() { #ifdef _DEBUG
DebugBreak(); #endif
return 0; } #endif
#if !defined(_M_ALPHA) && !defined(_M_PPC)
//RISC always initializes floating point and always defines _fltused
extern "C" const int _fltused = 0; #endif
void* __cdecl malloc(size_t n) { if (_Module.m_hHeap == NULL) { _Module.m_hHeap = HeapCreate(0, 0, 0); if (_Module.m_hHeap == NULL) return NULL; } _ASSERTE(_Module.m_hHeap != NULL);
#ifdef _MALLOC_ZEROINIT
return HeapAlloc(_Module.m_hHeap, HEAP_ZERO_MEMORY, n); #else
return HeapAlloc(_Module.m_hHeap, 0, n); #endif
}
void* __cdecl calloc(size_t n, size_t s) { return malloc(n * s); }
void* __cdecl realloc(void* p, size_t n) { _ASSERTE(_Module.m_hHeap != NULL); #ifdef _MALLOC_ZEROINIT
return (p == NULL) ? malloc(n) : HeapReAlloc(_Module.m_hHeap, HEAP_ZERO_MEMORY, p, n); #else
return (p == NULL) ? malloc(n) : HeapReAlloc(_Module.m_hHeap, 0, p, n); #endif
}
void __cdecl free(void* p) { _ASSERTE(_Module.m_hHeap != NULL); HeapFree(_Module.m_hHeap, 0, p); }
void* __cdecl operator new(size_t n) { return malloc(n); }
void __cdecl operator delete(void* p) { free(p); }
#endif //_DEBUG
#endif //_ATL_MIN_CRT
#ifndef _ATL_DLL
#ifndef ATL_NO_NAMESPACE
#ifndef _ATL_DLL_IMPL
namespace ATL { #endif
#endif
/////////////////////////////////////////////////////////////////////////////
// statics
static UINT WINAPI AtlGetDirLen(LPCOLESTR lpszPathName) { _ASSERTE(lpszPathName != NULL);
// always capture the complete file name including extension (if present)
LPCOLESTR lpszTemp = lpszPathName; for (LPCOLESTR lpsz = lpszPathName; *lpsz != NULL; ) { LPCOLESTR lp = CharNextO(lpsz); // remember last directory/drive separator
if (*lpsz == OLESTR('\\') || *lpsz == OLESTR('/') || *lpsz == OLESTR(':')) lpszTemp = lp; lpsz = lp; }
return lpszTemp-lpszPathName; }
/////////////////////////////////////////////////////////////////////////////
// QI support
ATLAPI AtlInternalQueryInterface(void* pThis, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject) { _ASSERTE(pThis != NULL); // First entry in the com map should be a simple map entry
_ASSERTE(pEntries->pFunc == _ATL_SIMPLEMAPENTRY); if (ppvObject == NULL) return E_POINTER; *ppvObject = NULL; if (InlineIsEqualUnknown(iid)) // use first interface
{ IUnknown* pUnk = (IUnknown*)((int)pThis+pEntries->dw); pUnk->AddRef(); *ppvObject = pUnk; return S_OK; } while (pEntries->pFunc != NULL) { BOOL bBlind = (pEntries->piid == NULL); if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid)) { if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset
{ _ASSERTE(!bBlind); IUnknown* pUnk = (IUnknown*)((int)pThis+pEntries->dw); pUnk->AddRef(); *ppvObject = pUnk; return S_OK; } else //actual function call
{ HRESULT hRes = pEntries->pFunc(pThis, iid, ppvObject, pEntries->dw); if (hRes == S_OK || (!bBlind && FAILED(hRes))) return hRes; } } pEntries++; } return E_NOINTERFACE; }
/////////////////////////////////////////////////////////////////////////////
// Smart Pointer helpers
ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp) { if (lp != NULL) lp->AddRef(); if (*pp) (*pp)->Release(); *pp = lp; return lp; }
ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid) { IUnknown* pTemp = *pp; *pp = NULL; if (lp != NULL) lp->QueryInterface(riid, (void**)pp); if (pTemp) pTemp->Release(); return *pp; }
/////////////////////////////////////////////////////////////////////////////
// Inproc Marshaling helpers
ATLAPI AtlFreeMarshalStream(IStream* pStream) { if (pStream != NULL) { CoReleaseMarshalData(pStream); pStream->Release(); } return S_OK; }
ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream) { HRESULT hRes = CreateStreamOnHGlobal(NULL, TRUE, ppStream); if (SUCCEEDED(hRes)) { hRes = CoMarshalInterface(*ppStream, iid, pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG); if (FAILED(hRes)) { (*ppStream)->Release(); *ppStream = NULL; } } return hRes; }
ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk) { *ppUnk = NULL; HRESULT hRes = E_INVALIDARG; if (pStream != NULL) { LARGE_INTEGER l; l.QuadPart = 0; pStream->Seek(l, STREAM_SEEK_SET, NULL); hRes = CoUnmarshalInterface(pStream, iid, (void**)ppUnk); } return hRes; }
ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent) { DWORD dwRet; MSG msg;
while(1) { dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT);
if (dwRet == WAIT_OBJECT_0) return TRUE; // The event was signaled
if (dwRet != WAIT_OBJECT_0 + 1) break; // Something else happened
// There is one or more window message available. Dispatch them
while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) return TRUE; // Event is now signaled.
} } return FALSE; }
/////////////////////////////////////////////////////////////////////////////
// Connection Point Helpers
ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw) { CComPtr<IConnectionPointContainer> pCPC; CComPtr<IConnectionPoint> pCP; HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC); if (SUCCEEDED(hRes)) hRes = pCPC->FindConnectionPoint(iid, &pCP); if (SUCCEEDED(hRes)) hRes = pCP->Advise(pUnk, pdw); return hRes; }
ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw) { CComPtr<IConnectionPointContainer> pCPC; CComPtr<IConnectionPoint> pCP; HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC); if (SUCCEEDED(hRes)) hRes = pCPC->FindConnectionPoint(iid, &pCP); if (SUCCEEDED(hRes)) hRes = pCP->Unadvise(dw); return hRes; }
/////////////////////////////////////////////////////////////////////////////
// IDispatch Error handling
ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst) { USES_CONVERSION; TCHAR szDesc[1024]; szDesc[0] = NULL; // For a valid HRESULT the id should be in the range [0x0200, 0xffff]
if (HIWORD(lpszDesc) == 0) //id
{ UINT nID = LOWORD((DWORD)lpszDesc); _ASSERTE((nID >= 0x0200 && nID <= 0xffff) || hRes != 0); if (LoadString(hInst, nID, szDesc, 1024) == 0) { _ASSERTE(FALSE); lstrcpy(szDesc, _T("Unknown Error")); } lpszDesc = T2OLE(szDesc); if (hRes == 0) hRes = MAKE_HRESULT(3, FACILITY_ITF, nID); }
CComPtr<ICreateErrorInfo> pICEI; if (SUCCEEDED(CreateErrorInfo(&pICEI))) { CComPtr<IErrorInfo> pErrorInfo; pICEI->SetGUID(iid); LPOLESTR lpsz; ProgIDFromCLSID(clsid, &lpsz); if (lpsz != NULL) pICEI->SetSource(lpsz); if (dwHelpID != 0 && lpszHelpFile != NULL) { pICEI->SetHelpContext(dwHelpID); pICEI->SetHelpFile(const_cast<LPOLESTR>(lpszHelpFile)); } CoTaskMemFree(lpsz); pICEI->SetDescription((LPOLESTR)lpszDesc); if (SUCCEEDED(pICEI->QueryInterface(IID_IErrorInfo, (void**)&pErrorInfo))) SetErrorInfo(0, pErrorInfo); } //#ifdef _DEBUG
// USES_CONVERSION;
// ATLTRACE(_T("AtlReportError: Description=\"%s\" returning %x\n"), OLE2CT(lpszDesc), hRes);
//#endif
return (hRes == 0) ? DISP_E_EXCEPTION : hRes; }
/////////////////////////////////////////////////////////////////////////////
// Module
//Although these functions are big, they are only used once in a module
//so we should make them inline.
ATLAPI AtlModuleInit(_ATL_MODULE* pM, _ATL_OBJMAP_ENTRY* p, HINSTANCE h) { _ASSERTE(pM != NULL); if (pM == NULL) return E_INVALIDARG; if (pM->cbSize < sizeof(_ATL_MODULE)) return E_INVALIDARG; pM->m_pObjMap = p; pM->m_hInst = pM->m_hInstTypeLib = pM->m_hInstResource = h; pM->m_nLockCnt=0L; pM->m_hHeap = NULL; InitializeCriticalSection(&pM->m_csTypeInfoHolder); InitializeCriticalSection(&pM->m_csWindowCreate); InitializeCriticalSection(&pM->m_csObjMap); return S_OK; }
ATLAPI AtlModuleRegisterClassObjects(_ATL_MODULE* pM, DWORD dwClsContext, DWORD dwFlags) { _ASSERTE(pM != NULL); if (pM == NULL) return E_INVALIDARG; _ASSERTE(pM->m_pObjMap != NULL); _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap; HRESULT hRes = S_OK; while (pEntry->pclsid != NULL && hRes == S_OK) { hRes = pEntry->RegisterClassObject(dwClsContext, dwFlags); pEntry++; } return hRes; }
ATLAPI AtlModuleRevokeClassObjects(_ATL_MODULE* pM) { _ASSERTE(pM != NULL); if (pM == NULL) return E_INVALIDARG; _ASSERTE(pM->m_pObjMap != NULL); _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap; HRESULT hRes = S_OK; while (pEntry->pclsid != NULL && hRes == S_OK) { hRes = pEntry->RevokeClassObject(); pEntry++; } return hRes; }
ATLAPI AtlModuleGetClassObject(_ATL_MODULE* pM, REFCLSID rclsid, REFIID riid, LPVOID* ppv) { _ASSERTE(pM != NULL); if (pM == NULL) return E_INVALIDARG; _ASSERTE(pM->m_pObjMap != NULL); _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap; HRESULT hRes = S_OK; if (ppv == NULL) return E_POINTER; while (pEntry->pclsid != NULL) { if (InlineIsEqualGUID(rclsid, *pEntry->pclsid)) { if (pEntry->pCF == NULL) { EnterCriticalSection(&pM->m_csObjMap); if (pEntry->pCF == NULL) hRes = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, IID_IUnknown, (LPVOID*)&pEntry->pCF); LeaveCriticalSection(&pM->m_csObjMap); } if (pEntry->pCF != NULL) hRes = pEntry->pCF->QueryInterface(riid, ppv); break; } pEntry++; } if (*ppv == NULL && hRes == S_OK) hRes = CLASS_E_CLASSNOTAVAILABLE; return hRes; }
ATLAPI AtlModuleTerm(_ATL_MODULE* pM) { _ASSERTE(pM != NULL); if (pM == NULL) return E_INVALIDARG; _ASSERTE(pM->m_hInst != NULL); if (pM->m_pObjMap != NULL) { _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap; while (pEntry->pclsid != NULL) { if (pEntry->pCF != NULL) pEntry->pCF->Release(); pEntry->pCF = NULL; pEntry++; } } DeleteCriticalSection(&pM->m_csTypeInfoHolder); DeleteCriticalSection(&pM->m_csWindowCreate); DeleteCriticalSection(&pM->m_csObjMap); if (pM->m_hHeap != NULL) HeapDestroy(pM->m_hHeap); return S_OK; }
ATLAPI AtlModuleRegisterServer(_ATL_MODULE* pM, BOOL bRegTypeLib, const CLSID* pCLSID) { _ASSERTE(pM != NULL); if (pM == NULL) return E_INVALIDARG; _ASSERTE(pM->m_hInst != NULL); _ASSERTE(pM->m_pObjMap != NULL); _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap; HRESULT hRes = S_OK; for (;pEntry->pclsid != NULL; pEntry++) { if (pCLSID == NULL) { if (pEntry->pfnGetObjectDescription() != NULL) continue; } else { if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) continue; } hRes = pEntry->pfnUpdateRegistry(TRUE); if (FAILED(hRes)) break; } if (SUCCEEDED(hRes) && bRegTypeLib) hRes = AtlModuleRegisterTypeLib(pM, 0); return hRes; }
ATLAPI AtlModuleUnregisterServer(_ATL_MODULE* pM, const CLSID* pCLSID) { _ASSERTE(pM != NULL); if (pM == NULL) return E_INVALIDARG; _ASSERTE(pM->m_hInst != NULL); _ASSERTE(pM->m_pObjMap != NULL); _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap; for (;pEntry->pclsid != NULL; pEntry++) { if (pCLSID == NULL) { if (pEntry->pfnGetObjectDescription() != NULL) continue; } else { if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) continue; } pEntry->pfnUpdateRegistry(FALSE); //unregister
} return S_OK; }
ATLAPI AtlModuleUpdateRegistryFromResourceD(_ATL_MODULE* pM, LPCOLESTR lpszRes, BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg) { USES_CONVERSION; _ASSERTE(pM != NULL); HRESULT hRes = S_OK; CComPtr<IRegistrar> p; if (pReg != NULL) p = pReg; else { hRes = CoCreateInstance(CLSID_Registrar, NULL, CLSCTX_INPROC_SERVER, IID_IRegistrar, (void**)&p); } if (SUCCEEDED(hRes)) { TCHAR szModule[_MAX_PATH]; GetModuleFileName(pM->m_hInst, szModule, _MAX_PATH); p->AddReplacement(OLESTR("Module"), T2OLE(szModule));
if (NULL != pMapEntries) { while (NULL != pMapEntries->szKey) { _ASSERTE(NULL != pMapEntries->szData); p->AddReplacement((LPOLESTR)pMapEntries->szKey, (LPOLESTR)pMapEntries->szData); pMapEntries++; } } LPCOLESTR szType = OLESTR("REGISTRY"); GetModuleFileName(pM->m_hInstResource, szModule, _MAX_PATH); LPOLESTR pszModule = T2OLE(szModule); if (HIWORD(lpszRes)==0) { if (bRegister) hRes = p->ResourceRegister(pszModule, ((UINT)LOWORD((DWORD)lpszRes)), szType); else hRes = p->ResourceUnregister(pszModule, ((UINT)LOWORD((DWORD)lpszRes)), szType); } else { if (bRegister) hRes = p->ResourceRegisterSz(pszModule, lpszRes, szType); else hRes = p->ResourceUnregisterSz(pszModule, lpszRes, szType); }
} return hRes; }
/////////////////////////////////////////////////////////////////////////////
// TypeLib Support
ATLAPI AtlModuleRegisterTypeLib(_ATL_MODULE* pM, LPCOLESTR lpszIndex) { _ASSERTE(pM != NULL); USES_CONVERSION; _ASSERTE(pM->m_hInstTypeLib != NULL); TCHAR szModule[_MAX_PATH+10]; OLECHAR szDir[_MAX_PATH]; GetModuleFileName(pM->m_hInstTypeLib, szModule, _MAX_PATH); if (lpszIndex != NULL) lstrcat(szModule, OLE2CT(lpszIndex)); ITypeLib* pTypeLib; LPOLESTR lpszModule = T2OLE(szModule); HRESULT hr = LoadTypeLib(lpszModule, &pTypeLib); if (!SUCCEEDED(hr)) { // typelib not in module, try <module>.tlb instead
LPTSTR lpszExt = NULL; LPTSTR lpsz; for (lpsz = szModule; *lpsz != NULL; lpsz = CharNext(lpsz)) { if (*lpsz == _T('.')) lpszExt = lpsz; } if (lpszExt == NULL) lpszExt = lpsz; lstrcpy(lpszExt, _T(".tlb")); lpszModule = T2OLE(szModule); hr = LoadTypeLib(lpszModule, &pTypeLib); } if (SUCCEEDED(hr)) { ocscpy(szDir, lpszModule); szDir[AtlGetDirLen(szDir)] = 0; hr = ::RegisterTypeLib(pTypeLib, lpszModule, szDir); } if (pTypeLib != NULL) pTypeLib->Release(); return hr; }
#ifndef ATL_NO_NAMESPACE
#ifndef _ATL_DLL_IMPL
}; //namespace ATL
#endif
#endif
#endif //!_ATL_DLL
|