home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 May / PCP163A.iso / Runimage / Cbuilder4 / Include / Atl / ATLIMPL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-26  |  66.2 KB  |  2,841 lines

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef __ATLBASE_H__
  12.     #error atlimpl.cpp requires atlbase.h to be included first
  13. #endif
  14.  
  15. extern "C" const IID IID_IRegistrar = {0x44EC053B,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}};
  16. #ifndef _ATL_DLL_IMPL
  17. extern "C" const CLSID CLSID_Registrar = {0x44EC053A,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}};
  18. #endif
  19.  
  20. #include "atlconv.cpp"
  21. #ifdef _DEBUG
  22. #include <stdio.h>
  23. #include <stdarg.h>
  24. #endif
  25.  
  26. #ifndef ATL_NO_NAMESPACE
  27. namespace ATL
  28. {
  29. #endif
  30.  
  31. // used in thread pooling
  32. UINT CComApartment::ATL_CREATE_OBJECT = 0;
  33.  
  34. #ifdef __ATLCOM_H__
  35.  
  36. /////////////////////////////////////////////////////////////////////////////
  37. // AtlReportError
  38.  
  39. HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, const IID& iid,
  40.     HRESULT hRes, HINSTANCE hInst)
  41. {
  42.     return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), 0, NULL, iid, hRes, hInst);
  43. }
  44.  
  45. HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, DWORD dwHelpID,
  46.     LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst)
  47. {
  48.     return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), dwHelpID,
  49.         lpszHelpFile, iid, hRes, hInst);
  50. }
  51.  
  52. #ifndef OLE2ANSI
  53. HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc,
  54.     DWORD dwHelpID, LPCSTR lpszHelpFile, const IID& iid, HRESULT hRes)
  55. {
  56.     _ASSERTE(lpszDesc != NULL);
  57.     USES_CONVERSION;
  58.     return AtlSetErrorInfo(clsid, A2COLE(lpszDesc), dwHelpID, A2CW(lpszHelpFile),
  59.         iid, hRes, NULL);
  60. }
  61.  
  62. HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc,
  63.     const IID& iid, HRESULT hRes)
  64. {
  65.     _ASSERTE(lpszDesc != NULL);
  66.     USES_CONVERSION;
  67.     return AtlSetErrorInfo(clsid, A2COLE(lpszDesc), 0, NULL, iid, hRes, NULL);
  68. }
  69. #endif
  70.  
  71. HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc,
  72.     const IID& iid, HRESULT hRes)
  73. {
  74.     return AtlSetErrorInfo(clsid, lpszDesc, 0, NULL, iid, hRes, NULL);
  75. }
  76.  
  77. HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
  78.     LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes)
  79. {
  80.     return AtlSetErrorInfo(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes, NULL);
  81. }
  82.  
  83. #endif //__ATLCOM_H__
  84.  
  85. /////////////////////////////////////////////////////////////////////////////
  86. // CComBSTR
  87.  
  88. CComBSTR& CComBSTR::operator=(const CComBSTR& src)
  89. {
  90.     if (m_str != src.m_str)
  91.     {
  92.         if (m_str)
  93.             ::SysFreeString(m_str);
  94.         m_str = src.Copy();
  95.     }
  96.     return *this;
  97. }
  98.  
  99. CComBSTR& CComBSTR::operator=(LPCOLESTR pSrc)
  100. {
  101.     ::SysFreeString(m_str);
  102.     m_str = ::SysAllocString(pSrc);
  103.     return *this;
  104. }
  105.  
  106. void CComBSTR::Append(LPCOLESTR lpsz, int nLen)
  107. {
  108.     int n1 = Length();
  109.     BSTR b = SysAllocStringLen(NULL, n1+nLen);
  110.     memcpy(b, m_str, n1*sizeof(OLECHAR));
  111.     memcpy(b+n1, lpsz, nLen*sizeof(OLECHAR));
  112.     b[n1+nLen] = NULL;
  113.     SysFreeString(m_str);
  114.     m_str = b;
  115. }
  116.  
  117. #ifndef OLE2ANSI
  118. void CComBSTR::Append(LPCSTR lpsz)
  119. {
  120.     USES_CONVERSION;
  121.     LPCOLESTR lpo = A2COLE(lpsz);
  122.     Append(lpo, ocslen(lpo));
  123. }
  124.  
  125. CComBSTR::CComBSTR(LPCSTR pSrc)
  126. {
  127.     USES_CONVERSION;
  128.     m_str = ::SysAllocString(A2COLE(pSrc));
  129. }
  130.  
  131. CComBSTR::CComBSTR(int nSize, LPCSTR sz)
  132. {
  133.     USES_CONVERSION;
  134.     m_str = ::SysAllocStringLen(A2COLE(sz), nSize);
  135. }
  136.  
  137. CComBSTR& CComBSTR::operator=(LPCSTR pSrc)
  138. {
  139.     USES_CONVERSION;
  140.     ::SysFreeString(m_str);
  141.     m_str = ::SysAllocString(A2COLE(pSrc));
  142.     return *this;
  143. }
  144. #endif
  145.  
  146. HRESULT CComBSTR::ReadFromStream(IStream* pStream)
  147. {
  148.     _ASSERTE(pStream != NULL);
  149.     _ASSERTE(m_str == NULL); // should be empty
  150.     ULONG cb;
  151.     ULONG cbStrLen;
  152.     HRESULT hr = pStream->Read((void*) &cbStrLen, sizeof(cbStrLen), &cb);
  153.     if (FAILED(hr))
  154.         return hr;
  155.     if (cbStrLen != 0)
  156.     {
  157.         //subtract size for terminating NULL which we wrote out
  158.         //since SysAllocStringByteLen overallocates for the NULL
  159.         m_str = SysAllocStringByteLen(NULL, cbStrLen-sizeof(OLECHAR));
  160.         if (m_str == NULL)
  161.             hr = E_OUTOFMEMORY;
  162.         else
  163.             hr = pStream->Read((void*) m_str, cbStrLen, &cb);
  164.     }
  165.     return hr;
  166. }
  167.  
  168. HRESULT CComBSTR::WriteToStream(IStream* pStream)
  169. {
  170.     _ASSERTE(pStream != NULL);
  171.     ULONG cb;
  172.     ULONG cbStrLen = m_str ? SysStringByteLen(m_str)+sizeof(OLECHAR) : 0;
  173.     HRESULT hr = pStream->Write((void*) &cbStrLen, sizeof(cbStrLen), &cb);
  174.     if (FAILED(hr))
  175.         return hr;
  176.     return cbStrLen ? pStream->Write((void*) m_str, cbStrLen, &cb) : S_OK;
  177. }
  178.  
  179. /////////////////////////////////////////////////////////////////////////////
  180. // CComVariant
  181.  
  182. CComVariant& CComVariant::operator=(BSTR bstrSrc)
  183. {
  184.     InternalClear();
  185.     vt = VT_BSTR;
  186.     bstrVal = ::SysAllocString(bstrSrc);
  187.     if (bstrVal == NULL && bstrSrc != NULL)
  188.     {
  189.         vt = VT_ERROR;
  190.         scode = E_OUTOFMEMORY;
  191.     }
  192.     return *this;
  193. }
  194.  
  195. CComVariant& CComVariant::operator=(LPCOLESTR lpszSrc)
  196. {
  197.     InternalClear();
  198.     vt = VT_BSTR;
  199.     bstrVal = ::SysAllocString(lpszSrc);
  200.  
  201.     if (bstrVal == NULL && lpszSrc != NULL)
  202.     {
  203.         vt = VT_ERROR;
  204.         scode = E_OUTOFMEMORY;
  205.     }
  206.     return *this;
  207. }
  208.  
  209. #ifndef OLE2ANSI
  210. CComVariant& CComVariant::operator=(LPCSTR lpszSrc)
  211. {
  212.     USES_CONVERSION;
  213.     InternalClear();
  214.     vt = VT_BSTR;
  215.     bstrVal = ::SysAllocString(A2COLE(lpszSrc));
  216.  
  217.     if (bstrVal == NULL && lpszSrc != NULL)
  218.     {
  219.         vt = VT_ERROR;
  220.         scode = E_OUTOFMEMORY;
  221.     }
  222.     return *this;
  223. }
  224. #endif
  225.  
  226. #if _MSC_VER>1020
  227. CComVariant& CComVariant::operator=(bool bSrc)
  228. {
  229.     if (vt != VT_BOOL)
  230.     {
  231.         InternalClear();
  232.         vt = VT_BOOL;
  233.     }
  234. #pragma warning(disable: 4310) // cast truncates constant value
  235.     boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
  236. #pragma warning(default: 4310) // cast truncates constant value
  237.     return *this;
  238. }
  239. #endif
  240.  
  241. CComVariant& CComVariant::operator=(int nSrc)
  242. {
  243.     if (vt != VT_I4)
  244.     {
  245.         InternalClear();
  246.         vt = VT_I4;
  247.     }
  248.     lVal = nSrc;
  249.  
  250.     return *this;
  251. }
  252.  
  253. CComVariant& CComVariant::operator=(BYTE nSrc)
  254. {
  255.     if (vt != VT_UI1)
  256.     {
  257.         InternalClear();
  258.         vt = VT_UI1;
  259.     }
  260.     bVal = nSrc;
  261.     return *this;
  262. }
  263.  
  264. CComVariant& CComVariant::operator=(short nSrc)
  265. {
  266.     if (vt != VT_I2)
  267.     {
  268.         InternalClear();
  269.         vt = VT_I2;
  270.     }
  271.     iVal = nSrc;
  272.     return *this;
  273. }
  274.  
  275. CComVariant& CComVariant::operator=(long nSrc)
  276. {
  277.     if (vt != VT_I4)
  278.     {
  279.         InternalClear();
  280.         vt = VT_I4;
  281.     }
  282.     lVal = nSrc;
  283.     return *this;
  284. }
  285.  
  286. CComVariant& CComVariant::operator=(float fltSrc)
  287. {
  288.     if (vt != VT_R4)
  289.     {
  290.         InternalClear();
  291.         vt = VT_R4;
  292.     }
  293.     fltVal = fltSrc;
  294.     return *this;
  295. }
  296.  
  297. CComVariant& CComVariant::operator=(double dblSrc)
  298. {
  299.     if (vt != VT_R8)
  300.     {
  301.         InternalClear();
  302.         vt = VT_R8;
  303.     }
  304.     dblVal = dblSrc;
  305.     return *this;
  306. }
  307.  
  308. CComVariant& CComVariant::operator=(CY cySrc)
  309. {
  310.     if (vt != VT_CY)
  311.     {
  312.         InternalClear();
  313.         vt = VT_CY;
  314.     }
  315.     cyVal.Hi = cySrc.Hi;
  316.     cyVal.Lo = cySrc.Lo;
  317.     return *this;
  318. }
  319.  
  320. CComVariant& CComVariant::operator=(IDispatch* pSrc)
  321. {
  322.     InternalClear();
  323.     vt = VT_DISPATCH;
  324.     pdispVal = pSrc;
  325.     // Need to AddRef as VariantClear will Release
  326.     if (pdispVal != NULL)
  327.         pdispVal->AddRef();
  328.     return *this;
  329. }
  330.  
  331. CComVariant& CComVariant::operator=(IUnknown* pSrc)
  332. {
  333.     InternalClear();
  334.     vt = VT_UNKNOWN;
  335.     punkVal = pSrc;
  336.  
  337.     // Need to AddRef as VariantClear will Release
  338.     if (punkVal != NULL)
  339.         punkVal->AddRef();
  340.     return *this;
  341. }
  342.  
  343. #if _MSC_VER>1020
  344. bool CComVariant::operator==(const VARIANT& varSrc)
  345. {
  346.     if (this == &varSrc)
  347.         return true;
  348.  
  349.     // Variants not equal if types don't match
  350.     if (vt != varSrc.vt)
  351.         return false;
  352.  
  353.     // Check type specific values
  354.     switch (vt)
  355.     {
  356.         case VT_EMPTY:
  357.         case VT_NULL:
  358.             return true;
  359.  
  360.         case VT_BOOL:
  361.             return boolVal == varSrc.boolVal;
  362.  
  363.         case VT_UI1:
  364.             return bVal == varSrc.bVal;
  365.  
  366.         case VT_I2:
  367.             return iVal == varSrc.iVal;
  368.  
  369.         case VT_I4:
  370.             return lVal == varSrc.lVal;
  371.  
  372.         case VT_R4:
  373.             return fltVal == varSrc.fltVal;
  374.  
  375.         case VT_R8:
  376.             return dblVal == varSrc.dblVal;
  377.  
  378.         case VT_BSTR:
  379.             return (::SysStringByteLen(bstrVal) == ::SysStringByteLen(varSrc.bstrVal)) &&
  380.                     (::memcmp(bstrVal, varSrc.bstrVal, ::SysStringByteLen(bstrVal)) == 0);
  381.  
  382.         case VT_ERROR:
  383.             return scode == varSrc.scode;
  384.  
  385.         case VT_DISPATCH:
  386.             return pdispVal == varSrc.pdispVal;
  387.  
  388.         case VT_UNKNOWN:
  389.             return punkVal == varSrc.punkVal;
  390.  
  391.         default:
  392.             _ASSERTE(false);
  393.             // fall through
  394.     }
  395.  
  396.     return false;
  397. }
  398. #else
  399. BOOL CComVariant::operator==(const VARIANT& varSrc)
  400. {
  401.     if (this == &varSrc)
  402.         return TRUE;
  403.  
  404.     // Variants not equal if types don't match
  405.     if (vt != varSrc.vt)
  406.         return FALSE;
  407.  
  408.     // Check type specific values
  409.     switch (vt)
  410.     {
  411.         case VT_EMPTY:
  412.         case VT_NULL:
  413.             return TRUE;
  414.  
  415.         case VT_BOOL:
  416.             return boolVal == varSrc.boolVal;
  417.  
  418.         case VT_UI1:
  419.             return bVal == varSrc.bVal;
  420.  
  421.         case VT_I2:
  422.             return iVal == varSrc.iVal;
  423.  
  424.         case VT_I4:
  425.             return lVal == varSrc.lVal;
  426.  
  427.         case VT_R4:
  428.             return fltVal == varSrc.fltVal;
  429.  
  430.         case VT_R8:
  431.             return dblVal == varSrc.dblVal;
  432.  
  433.         case VT_BSTR:
  434.             return (::SysStringByteLen(bstrVal) == ::SysStringByteLen(varSrc.bstrVal)) &&
  435.                     (::memcmp(bstrVal, varSrc.bstrVal, ::SysStringByteLen(bstrVal)) == 0);
  436.  
  437.         case VT_ERROR:
  438.             return scode == varSrc.scode;
  439.  
  440.         case VT_DISPATCH:
  441.             return pdispVal == varSrc.pdispVal;
  442.  
  443.         case VT_UNKNOWN:
  444.             return punkVal == varSrc.punkVal;
  445.  
  446.         default:
  447.             _ASSERTE(FALSE);
  448.             // fall through
  449.     }
  450.  
  451.     return FALSE;
  452. }
  453. #endif
  454.  
  455. HRESULT CComVariant::Attach(VARIANT* pSrc)
  456. {
  457.     // Clear out the variant
  458.     HRESULT hr = Clear();
  459.     if (!FAILED(hr))
  460.     {
  461.         // Copy the contents and give control to CComVariant
  462.         memcpy(this, pSrc, sizeof(VARIANT));
  463.         VariantInit(pSrc);
  464.         hr = S_OK;
  465.     }
  466.     return hr;
  467. }
  468.  
  469. HRESULT CComVariant::Detach(VARIANT* pDest)
  470. {
  471.     // Clear out the variant
  472.     HRESULT hr = ::VariantClear(pDest);
  473.     if (!FAILED(hr))
  474.     {
  475.         // Copy the contents and remove control from CComVariant
  476.         memcpy(pDest, this, sizeof(VARIANT));
  477.         vt = VT_EMPTY;
  478.         hr = S_OK;
  479.     }
  480.     return hr;
  481. }
  482.  
  483. HRESULT CComVariant::ChangeType(VARTYPE vtNew, const VARIANT* pSrc)
  484. {
  485.     VARIANT* pVar = const_cast<VARIANT*>(pSrc);
  486.     // Convert in place if pSrc is NULL
  487.     if (pVar == NULL)
  488.         pVar = this;
  489.     // Do nothing if doing in place convert and vts not different
  490.     return ::VariantChangeType(this, pVar, 0, vtNew);
  491. }
  492.  
  493. HRESULT CComVariant::InternalClear()
  494. {
  495.     HRESULT hr = Clear();
  496.     _ASSERTE(SUCCEEDED(hr));
  497.     if (FAILED(hr))
  498.     {
  499.         vt = VT_ERROR;
  500.         scode = hr;
  501.     }
  502.     return hr;
  503. }
  504.  
  505. void CComVariant::InternalCopy(const VARIANT* pSrc)
  506. {
  507.     HRESULT hr = Copy(pSrc);
  508.     if (FAILED(hr))
  509.     {
  510.         vt = VT_ERROR;
  511.         scode = hr;
  512.     }
  513. }
  514.  
  515.  
  516. HRESULT CComVariant::WriteToStream(IStream* pStream)
  517. {
  518.     HRESULT hr = pStream->Write(&vt, sizeof(VARTYPE), NULL);
  519.     if (FAILED(hr))
  520.         return hr;
  521.  
  522.     int cbWrite = 0;
  523.     switch (vt)
  524.     {
  525.     case VT_UNKNOWN:
  526.     case VT_DISPATCH:
  527.         {
  528.             CComPtr<IPersistStream> spStream;
  529.             if (punkVal != NULL)
  530.             {
  531.                 hr = punkVal->QueryInterface(IID_IPersistStream, (void**)&spStream);
  532.                 if (FAILED(hr))
  533.                     return hr;
  534.             }
  535.             if (spStream != NULL)
  536.                 return OleSaveToStream(spStream, pStream);
  537.             else
  538.                 return WriteClassStm(pStream, CLSID_NULL);
  539.         }
  540.     case VT_UI1:
  541.     case VT_I1:
  542.         cbWrite = sizeof(BYTE);
  543.         break;
  544.     case VT_I2:
  545.     case VT_UI2:
  546.     case VT_BOOL:
  547.         cbWrite = sizeof(short);
  548.         break;
  549.     case VT_I4:
  550.     case VT_UI4:
  551.     case VT_R4:
  552.     case VT_INT:
  553.     case VT_UINT:
  554.     case VT_ERROR:
  555.         cbWrite = sizeof(long);
  556.         break;
  557.     case VT_R8:
  558.     case VT_CY:
  559.     case VT_DATE:
  560.         cbWrite = sizeof(double);
  561.         break;
  562.     default:
  563.         break;
  564.     }
  565.     if (cbWrite != 0)
  566.         return pStream->Write((void*) &bVal, cbWrite, NULL);
  567.  
  568.     CComBSTR bstrWrite;
  569.     CComVariant varBSTR;
  570.     if (vt != VT_BSTR)
  571.     {
  572.         hr = VariantChangeType(&varBSTR, this, VARIANT_NOVALUEPROP, VT_BSTR);
  573.         if (FAILED(hr))
  574.             return hr;
  575.         bstrWrite = varBSTR.bstrVal;
  576.     }
  577.     else
  578.         bstrWrite = bstrVal;
  579.  
  580.     return bstrWrite.WriteToStream(pStream);
  581. }
  582.  
  583. HRESULT CComVariant::ReadFromStream(IStream* pStream)
  584. {
  585.     _ASSERTE(pStream != NULL);
  586.     HRESULT hr;
  587.     hr = VariantClear(this);
  588.     if (FAILED(hr))
  589.         return hr;
  590.     VARTYPE vtRead;
  591.     hr = pStream->Read(&vtRead, sizeof(VARTYPE), NULL);
  592.     if (FAILED(hr))
  593.         return hr;
  594.  
  595.     vt = vtRead;
  596.     int cbRead = 0;
  597.     switch (vtRead)
  598.     {
  599.     case VT_UNKNOWN:
  600.     case VT_DISPATCH:
  601.         {
  602.             punkVal = NULL;
  603.             hr = OleLoadFromStream(pStream, 
  604.                 (vtRead == VT_UNKNOWN) ? IID_IUnknown : IID_IDispatch, 
  605.                 (void**)&punkVal);
  606.             if (hr == REGDB_E_CLASSNOTREG)
  607.                 hr = S_OK;
  608.             return S_OK;
  609.         }
  610.     case VT_UI1:
  611.     case VT_I1:
  612.         cbRead = sizeof(BYTE);
  613.         break;
  614.     case VT_I2:
  615.     case VT_UI2:
  616.     case VT_BOOL:
  617.         cbRead = sizeof(short);
  618.         break;
  619.     case VT_I4:
  620.     case VT_UI4:
  621.     case VT_R4:
  622.     case VT_INT:
  623.     case VT_UINT:
  624.     case VT_ERROR:
  625.         cbRead = sizeof(long);
  626.         break;
  627.     case VT_R8:
  628.     case VT_CY:
  629.     case VT_DATE:
  630.         cbRead = sizeof(double);
  631.         break;
  632.     default:
  633.         break;
  634.     }
  635.     if (cbRead != 0)
  636.         return pStream->Read((void*) &bVal, cbRead, NULL);
  637.     CComBSTR bstrRead;
  638.  
  639.     hr = bstrRead.ReadFromStream(pStream);
  640.     if (FAILED(hr))
  641.         return hr;
  642.     vt = VT_BSTR;
  643.     bstrVal = bstrRead.Detach();
  644.     if (vtRead != VT_BSTR)
  645.         hr = ChangeType(vtRead);
  646.     return hr;
  647. }
  648.  
  649. #ifdef __ATLCOM_H__
  650.  
  651. /////////////////////////////////////////////////////////////////////////////
  652. // CComTypeInfoHolder
  653.  
  654. void CComTypeInfoHolder::AddRef()
  655. {
  656.     EnterCriticalSection(&_Module.m_csTypeInfoHolder);
  657.     m_dwRef++;
  658.     LeaveCriticalSection(&_Module.m_csTypeInfoHolder);
  659. }
  660.  
  661. void CComTypeInfoHolder::Release()
  662. {
  663.     EnterCriticalSection(&_Module.m_csTypeInfoHolder);
  664.     if (--m_dwRef == 0)
  665.     {
  666.         if (m_pInfo != NULL)
  667.             m_pInfo->Release();
  668.         m_pInfo = NULL;
  669.     }
  670.     LeaveCriticalSection(&_Module.m_csTypeInfoHolder);
  671. }
  672.  
  673. HRESULT CComTypeInfoHolder::GetTI(LCID lcid, ITypeInfo** ppInfo)
  674. {
  675.     //If this assert occurs then most likely didn't initialize properly
  676.     _ASSERTE(m_plibid != NULL && m_pguid != NULL);
  677.     _ASSERTE(ppInfo != NULL);
  678.     *ppInfo = NULL;
  679.  
  680.     HRESULT hRes = E_FAIL;
  681.     EnterCriticalSection(&_Module.m_csTypeInfoHolder);
  682.     if (m_pInfo == NULL)
  683.     {
  684.         ITypeLib* pTypeLib;
  685.         hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib);
  686.         if (SUCCEEDED(hRes))
  687.         {
  688.             ITypeInfo* pTypeInfo;
  689.             hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &pTypeInfo);
  690.             if (SUCCEEDED(hRes))
  691.                 m_pInfo = pTypeInfo;
  692.             pTypeLib->Release();
  693.         }
  694.     }
  695.     *ppInfo = m_pInfo;
  696.     if (m_pInfo != NULL)
  697.     {
  698.         m_pInfo->AddRef();
  699.         hRes = S_OK;
  700.     }
  701.     LeaveCriticalSection(&_Module.m_csTypeInfoHolder);
  702.     return hRes;
  703. }
  704.  
  705. HRESULT CComTypeInfoHolder::GetTypeInfo(UINT /*itinfo*/, LCID lcid,
  706.     ITypeInfo** pptinfo)
  707. {
  708.     HRESULT hRes = E_POINTER;
  709.     if (pptinfo != NULL)
  710.         hRes = GetTI(lcid, pptinfo);
  711.     return hRes;
  712. }
  713.  
  714. HRESULT CComTypeInfoHolder::GetIDsOfNames(REFIID /*riid*/, LPOLESTR* rgszNames,
  715.     UINT cNames, LCID lcid, DISPID* rgdispid)
  716. {
  717.     ITypeInfo* pInfo;
  718.     HRESULT hRes = GetTI(lcid, &pInfo);
  719.     if (pInfo != NULL)
  720.     {
  721.         hRes = pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
  722.         pInfo->Release();
  723.     }
  724.     return hRes;
  725. }
  726.  
  727. HRESULT CComTypeInfoHolder::Invoke(IDispatch* p, DISPID dispidMember, REFIID /*riid*/,
  728.     LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
  729.     EXCEPINFO* pexcepinfo, UINT* puArgErr)
  730. {
  731.     SetErrorInfo(0, NULL);
  732.     ITypeInfo* pInfo;
  733.     HRESULT hRes = GetTI(lcid, &pInfo);
  734.     if (pInfo != NULL)
  735.     {
  736.         hRes = pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  737.         pInfo->Release();
  738.     }
  739.     return hRes;
  740. }
  741.  
  742. /////////////////////////////////////////////////////////////////////////////
  743. // QI implementation
  744.  
  745. #ifdef _ATL_DEBUG_QI
  746. HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr)
  747. {
  748.     USES_CONVERSION;
  749.     CRegKey key;
  750.     TCHAR szName[100];
  751.     DWORD dwType,dw = sizeof(szName);
  752.  
  753.     LPOLESTR pszGUID = NULL;
  754.     StringFromCLSID(iid, &pszGUID);
  755.     OutputDebugString(pszClassName);
  756.     OutputDebugString(_T(" - "));
  757.  
  758.     // Attempt to find it in the interfaces section
  759.     key.Open(HKEY_CLASSES_ROOT, _T("Interface"));
  760.     if (key.Open(key, OLE2T(pszGUID)) == S_OK)
  761.     {
  762.         *szName = 0;
  763.         RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw);
  764.         OutputDebugString(szName);
  765.         goto cleanup;
  766.     }
  767.     // Attempt to find it in the clsid section
  768.     key.Open(HKEY_CLASSES_ROOT, _T("CLSID"));
  769.     if (key.Open(key, OLE2T(pszGUID)) == S_OK)
  770.     {
  771.         *szName = 0;
  772.         RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw);
  773.         OutputDebugString(_T("(CLSID\?\?\?) "));
  774.         OutputDebugString(szName);
  775.         goto cleanup;
  776.     }
  777.     OutputDebugString(OLE2T(pszGUID));
  778. cleanup:
  779.     if (hr != S_OK)
  780.         OutputDebugString(_T(" - failed"));
  781.     OutputDebugString(_T("\n"));
  782.     CoTaskMemFree(pszGUID);
  783.     return hr;
  784. }
  785. #endif
  786.  
  787. HRESULT WINAPI CComObjectRootBase::_Break(void* /* pv */, REFIID iid, void** /* ppvObject */, DWORD /* dw */)
  788. {
  789.     iid;
  790.     _ATLDUMPIID(iid, _T("Break due to QI for interface "), S_OK);
  791.     DebugBreak();
  792.     return S_FALSE;
  793. }
  794.  
  795. HRESULT WINAPI CComObjectRootBase::_NoInterface(void* /* pv */, REFIID /* iid */, void** /* ppvObject */, DWORD /* dw */)
  796. {
  797.     return E_NOINTERFACE;
  798. }
  799.  
  800. HRESULT WINAPI CComObjectRootBase::_Creator(void* pv, REFIID iid, void** ppvObject, DWORD dw)
  801. {
  802.     _ATL_CREATORDATA* pcd = (_ATL_CREATORDATA*)dw;
  803.     return pcd->pFunc(pv, iid, ppvObject);
  804. }
  805.  
  806. HRESULT WINAPI CComObjectRootBase::_Delegate(void* pv, REFIID iid, void** ppvObject, DWORD dw)
  807. {
  808.     HRESULT hRes = E_NOINTERFACE;
  809.     IUnknown* p = *(IUnknown**)((DWORD)pv + dw);
  810.     if (p != NULL)
  811.         hRes = p->QueryInterface(iid, ppvObject);
  812.     return hRes;
  813. }
  814.  
  815. HRESULT WINAPI CComObjectRootBase::_Chain(void* pv, REFIID iid, void** ppvObject, DWORD dw)
  816. {
  817.     _ATL_CHAINDATA* pcd = (_ATL_CHAINDATA*)dw;
  818.     void* p = (void*)((DWORD)pv + pcd->dwOffset);
  819.     return InternalQueryInterface(p, pcd->pFunc(), iid, ppvObject);
  820. }
  821.  
  822. HRESULT WINAPI CComObjectRootBase::_Cache(void* pv, REFIID iid, void** ppvObject, DWORD dw)
  823. {
  824.     HRESULT hRes = E_NOINTERFACE;
  825.     _ATL_CACHEDATA* pcd = (_ATL_CACHEDATA*)dw;
  826.     IUnknown** pp = (IUnknown**)((DWORD)pv + pcd->dwOffsetVar);
  827.     if (*pp == NULL)
  828.         hRes = pcd->pFunc(pv, IID_IUnknown, (void**)pp);
  829.     if (*pp != NULL)
  830.         hRes = (*pp)->QueryInterface(iid, ppvObject);
  831.     return hRes;
  832. }
  833.  
  834. /////////////////////////////////////////////////////////////////////////////
  835. // CComClassFactory
  836.  
  837. STDMETHODIMP CComClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
  838.     REFIID riid, void** ppvObj)
  839. {
  840.     _ASSERTE(m_pfnCreateInstance != NULL);
  841.     HRESULT hRes = E_POINTER;
  842.     if (ppvObj != NULL)
  843.     {
  844.         *ppvObj = NULL;
  845.         // can't ask for anything other than IUnknown when aggregating
  846.         _ASSERTE((pUnkOuter == NULL) || InlineIsEqualUnknown(riid));
  847.         if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid))
  848.             hRes = CLASS_E_NOAGGREGATION;
  849.         else
  850.             hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
  851.     }
  852.     return hRes;
  853. }
  854.  
  855. STDMETHODIMP CComClassFactory::LockServer(BOOL fLock)
  856. {
  857.     if (fLock)
  858.         _Module.Lock();
  859.     else
  860.         _Module.Unlock();
  861.     return S_OK;
  862. }
  863.  
  864. STDMETHODIMP CComClassFactory2Base::LockServer(BOOL fLock)
  865. {
  866.     if (fLock)
  867.         _Module.Lock();
  868.     else
  869.         _Module.Unlock();
  870.     return S_OK;
  871. }
  872.  
  873. #ifndef _ATL_NO_CONNECTION_POINTS
  874. /////////////////////////////////////////////////////////////////////////////
  875. // Connection Points
  876.  
  877. DWORD CComDynamicUnkArray::Add(IUnknown* pUnk)
  878. {
  879.     IUnknown** pp = NULL;
  880.     if (m_nSize == 0) // no connections
  881.     {
  882.         m_pUnk = pUnk;
  883.         m_nSize = 1;
  884.         return (DWORD)m_pUnk;
  885.     }
  886.     else if (m_nSize == 1)
  887.     {
  888.         //create array
  889.         pp = (IUnknown**)malloc(sizeof(IUnknown*)*_DEFAULT_VECTORLENGTH);
  890.         if (pp == NULL)
  891.             return 0;
  892.         memset(pp, 0, sizeof(IUnknown*)*_DEFAULT_VECTORLENGTH);
  893.         *pp = m_pUnk;
  894.         m_ppUnk = pp;
  895.         m_nSize = _DEFAULT_VECTORLENGTH;
  896.     }
  897.     for (pp = begin();pp<end();pp++)
  898.     {
  899.         if (*pp == NULL)
  900.         {
  901.             *pp = pUnk;
  902.             return (DWORD)pUnk;
  903.         }
  904.     }
  905.     int nAlloc = m_nSize*2;
  906.     pp = (IUnknown**)realloc(m_ppUnk, sizeof(IUnknown*)*nAlloc);
  907.     if (pp == NULL)
  908.         return 0;
  909.     m_ppUnk = pp;
  910.     memset(&m_ppUnk[m_nSize], 0, sizeof(IUnknown*)*m_nSize);
  911.     m_ppUnk[m_nSize] = pUnk;
  912.     m_nSize = nAlloc;
  913.     return (DWORD)pUnk;
  914. }
  915.  
  916. BOOL CComDynamicUnkArray::Remove(DWORD dwCookie)
  917. {
  918.     IUnknown** pp;
  919.     if (dwCookie == NULL)
  920.         return FALSE;
  921.     if (m_nSize == 0)
  922.         return FALSE;
  923.     if (m_nSize == 1)
  924.     {
  925.         if ((DWORD)m_pUnk == dwCookie)
  926.         {
  927.             m_nSize = 0;
  928.             return TRUE;
  929.         }
  930.         return FALSE;
  931.     }
  932.     for (pp=begin();pp<end();pp++)
  933.     {
  934.         if ((DWORD)*pp == dwCookie)
  935.         {
  936.             *pp = NULL;
  937.             return TRUE;
  938.         }
  939.     }
  940.     return FALSE;
  941. }
  942.  
  943. #endif //!_ATL_NO_CONNECTION_POINTS
  944.  
  945. #endif //__ATLCOM_H__
  946.  
  947. /////////////////////////////////////////////////////////////////////////////
  948. // Object Registry Support
  949.  
  950. static HRESULT WINAPI AtlRegisterProgID(LPCTSTR lpszCLSID, LPCTSTR lpszProgID, LPCTSTR lpszUserDesc)
  951. {
  952.     CRegKey keyProgID;
  953.     LONG lRes = keyProgID.Create(HKEY_CLASSES_ROOT, lpszProgID);
  954.     if (lRes == ERROR_SUCCESS)
  955.     {
  956.         keyProgID.SetValue(lpszUserDesc);
  957.         keyProgID.SetKeyValue(_T("CLSID"), lpszCLSID);
  958.         return S_OK;
  959.     }
  960.     return HRESULT_FROM_WIN32(lRes);
  961. }
  962.  
  963. void CComModule::AddCreateWndData(_AtlCreateWndData* pData, void* pObject)
  964. {
  965.     pData->m_pThis = pObject;
  966.     pData->m_dwThreadID = ::GetCurrentThreadId();
  967.     ::EnterCriticalSection(&m_csWindowCreate);
  968.     pData->m_pNext = m_pCreateWndList;
  969.     m_pCreateWndList = pData;
  970.     ::LeaveCriticalSection(&m_csWindowCreate);
  971. }
  972.  
  973. void* CComModule::ExtractCreateWndData()
  974. {
  975.     ::EnterCriticalSection(&m_csWindowCreate);
  976.     _AtlCreateWndData* pEntry = m_pCreateWndList;
  977.     if(pEntry == NULL)
  978.     {
  979.         ::LeaveCriticalSection(&m_csWindowCreate);
  980.         return NULL;
  981.     }
  982.  
  983.     DWORD dwThreadID = ::GetCurrentThreadId();
  984.     _AtlCreateWndData* pPrev = NULL;
  985.     while(pEntry != NULL)
  986.     {
  987.         if(pEntry->m_dwThreadID == dwThreadID)
  988.         {
  989.             if(pPrev == NULL)
  990.                 m_pCreateWndList = pEntry->m_pNext;
  991.             else
  992.                 pPrev->m_pNext = pEntry->m_pNext;
  993.             ::LeaveCriticalSection(&m_csWindowCreate);
  994.             return pEntry->m_pThis;
  995.         }
  996.         pPrev = pEntry;
  997.         pEntry = pEntry->m_pNext;
  998.     }
  999.  
  1000.     ::LeaveCriticalSection(&m_csWindowCreate);
  1001.     return NULL;
  1002. }
  1003.  
  1004. #ifdef _ATL_STATIC_REGISTRY
  1005. // Statically linking to Registry Ponent
  1006. HRESULT WINAPI CComModule::UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister,
  1007.     struct _ATL_REGMAP_ENTRY* pMapEntries)
  1008. {
  1009.     USES_CONVERSION;
  1010.     CRegObject ro;
  1011.     TCHAR szModule[_MAX_PATH];
  1012.     GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  1013.     LPOLESTR pszModule = T2OLE(szModule);
  1014.     ro.AddReplacement(OLESTR("Module"), pszModule);
  1015.     if (NULL != pMapEntries)
  1016.     {
  1017.         while (NULL != pMapEntries->szKey)
  1018.         {
  1019.             _ASSERTE(NULL != pMapEntries->szData);
  1020.             ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData);
  1021.             pMapEntries++;
  1022.         }
  1023.     }
  1024.  
  1025.     LPCOLESTR szType = OLESTR("REGISTRY");
  1026.     return (bRegister) ? ro.ResourceRegister(pszModule, nResID, szType) :
  1027.             ro.ResourceUnregister(pszModule, nResID, szType);
  1028. }
  1029.  
  1030. HRESULT WINAPI CComModule::UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister,
  1031.     struct _ATL_REGMAP_ENTRY* pMapEntries)
  1032. {
  1033.     USES_CONVERSION;
  1034.     CRegObject ro;
  1035.     TCHAR szModule[_MAX_PATH];
  1036.     GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  1037.     LPOLESTR pszModule = T2OLE(szModule);
  1038.     ro.AddReplacement(OLESTR("Module"), pszModule);
  1039.     if (NULL != pMapEntries)
  1040.     {
  1041.         while (NULL != pMapEntries->szKey)
  1042.         {
  1043.             _ASSERTE(NULL != pMapEntries->szData);
  1044.             ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData);
  1045.             pMapEntries++;
  1046.         }
  1047.     }
  1048.  
  1049.     LPCOLESTR szType = OLESTR("REGISTRY");
  1050.     LPCOLESTR pszRes = T2COLE(lpszRes);
  1051.     return (bRegister) ? ro.ResourceRegisterSz(pszModule, pszRes, szType) :
  1052.             ro.ResourceUnregisterSz(pszModule, pszRes, szType);
  1053. }
  1054. #endif // _ATL_STATIC_REGISTRY
  1055.  
  1056. HRESULT WINAPI CComModule::UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID,
  1057.     LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister)
  1058. {
  1059.     if (bRegister)
  1060.     {
  1061.         return RegisterClassHelper(clsid, lpszProgID, lpszVerIndProgID, nDescID,
  1062.             dwFlags);
  1063.     }
  1064.     else
  1065.         return UnregisterClassHelper(clsid, lpszProgID, lpszVerIndProgID);
  1066. }
  1067.  
  1068. HRESULT WINAPI CComModule::RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID,
  1069.     LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags)
  1070. {
  1071.     static const TCHAR szProgID[] = _T("ProgID");
  1072.     static const TCHAR szVIProgID[] = _T("VersionIndependentProgID");
  1073.     static const TCHAR szLS32[] = _T("LocalServer32");
  1074.     static const TCHAR szIPS32[] = _T("InprocServer32");
  1075.     static const TCHAR szThreadingModel[] = _T("ThreadingModel");
  1076.     static const TCHAR szAUTPRX32[] = _T("AUTPRX32.DLL");
  1077.     static const TCHAR szApartment[] = _T("Apartment");
  1078.     static const TCHAR szBoth[] = _T("both");
  1079.     USES_CONVERSION;
  1080.     HRESULT hRes = S_OK;
  1081.     TCHAR szDesc[256];
  1082.     LoadString(m_hInst, nDescID, szDesc, 256);
  1083.     TCHAR szModule[_MAX_PATH];
  1084.     GetModuleFileName(m_hInst, szModule, _MAX_PATH);
  1085.  
  1086.     LPOLESTR lpOleStr;
  1087.     StringFromCLSID(clsid, &lpOleStr);
  1088.     LPTSTR lpsz = OLE2T(lpOleStr);
  1089.  
  1090.     hRes = AtlRegisterProgID(lpsz, lpszProgID, szDesc);
  1091.     if (hRes == S_OK)
  1092.         hRes = AtlRegisterProgID(lpsz, lpszVerIndProgID, szDesc);
  1093.     LONG lRes = ERROR_SUCCESS;
  1094.     if (hRes == S_OK)
  1095.     {
  1096.         CRegKey key;
  1097.         LONG lRes = key.Open(HKEY_CLASSES_ROOT, _T("CLSID"));
  1098.         if (lRes == ERROR_SUCCESS)
  1099.         {
  1100.             lRes = key.Create(key, lpsz);
  1101.             if (lRes == ERROR_SUCCESS)
  1102.             {
  1103.                 key.SetValue(szDesc);
  1104.                 key.SetKeyValue(szProgID, lpszProgID);
  1105.                 key.SetKeyValue(szVIProgID, lpszVerIndProgID);
  1106.  
  1107.                 if ((m_hInst == NULL) || (m_hInst == GetModuleHandle(NULL))) // register as EXE
  1108.                     key.SetKeyValue(szLS32, szModule);
  1109.                 else
  1110.                 {
  1111.                     key.SetKeyValue(szIPS32, (dwFlags & AUTPRXFLAG) ? szAUTPRX32 : szModule);
  1112.                     LPCTSTR lpszModel = (dwFlags & THREADFLAGS_BOTH) ? szBoth :
  1113.                         (dwFlags & THREADFLAGS_APARTMENT) ? szApartment : NULL;
  1114.                     if (lpszModel != NULL)
  1115.                         key.SetKeyValue(szIPS32, lpszModel, szThreadingModel);
  1116.                 }
  1117.             }
  1118.         }
  1119.     }
  1120.     CoTaskMemFree(lpOleStr);
  1121.     if (lRes != ERROR_SUCCESS)
  1122.         hRes = HRESULT_FROM_WIN32(lRes);
  1123.     return hRes;
  1124. }
  1125.  
  1126. HRESULT WINAPI CComModule::UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID,
  1127.     LPCTSTR lpszVerIndProgID)
  1128. {
  1129.     USES_CONVERSION;
  1130.     CRegKey key;
  1131.  
  1132.     key.Attach(HKEY_CLASSES_ROOT);
  1133.     if (lpszProgID != NULL && lstrcmpi(lpszProgID, _T("")))
  1134.         key.RecurseDeleteKey(lpszProgID);
  1135.     if (lpszVerIndProgID != NULL && lstrcmpi(lpszVerIndProgID, _T("")))
  1136.         key.RecurseDeleteKey(lpszVerIndProgID);
  1137.     LPOLESTR lpOleStr;
  1138.     StringFromCLSID(clsid, &lpOleStr);
  1139.     LPTSTR lpsz = OLE2T(lpOleStr);
  1140.     if (key.Open(key, _T("CLSID")) == ERROR_SUCCESS)
  1141.         key.RecurseDeleteKey(lpsz);
  1142.     CoTaskMemFree(lpOleStr);
  1143.     return S_OK;
  1144. }
  1145.  
  1146.  
  1147. /////////////////////////////////////////////////////////////////////////////
  1148. // CRegKey
  1149.  
  1150. LONG CRegKey::Close()
  1151. {
  1152.     LONG lRes = ERROR_SUCCESS;
  1153.     if (m_hKey != NULL)
  1154.     {
  1155.         lRes = RegCloseKey(m_hKey);
  1156.         m_hKey = NULL;
  1157.     }
  1158.     return lRes;
  1159. }
  1160.  
  1161. LONG CRegKey::Create(HKEY hKeyParent, LPCTSTR lpszKeyName,
  1162.     LPTSTR lpszClass, DWORD dwOptions, REGSAM samDesired,
  1163.     LPSECURITY_ATTRIBUTES lpSecAttr, LPDWORD lpdwDisposition)
  1164. {
  1165.     _ASSERTE(hKeyParent != NULL);
  1166.     DWORD dw;
  1167.     HKEY hKey = NULL;
  1168.     LONG lRes = RegCreateKeyEx(hKeyParent, lpszKeyName, 0,
  1169.         lpszClass, dwOptions, samDesired, lpSecAttr, &hKey, &dw);
  1170.     if (lpdwDisposition != NULL)
  1171.         *lpdwDisposition = dw;
  1172.     if (lRes == ERROR_SUCCESS)
  1173.     {
  1174.         lRes = Close();
  1175.         m_hKey = hKey;
  1176.     }
  1177.     return lRes;
  1178. }
  1179.  
  1180. LONG CRegKey::Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired)
  1181. {
  1182.     _ASSERTE(hKeyParent != NULL);
  1183.     HKEY hKey = NULL;
  1184.     LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey);
  1185.     if (lRes == ERROR_SUCCESS)
  1186.     {
  1187.         lRes = Close();
  1188.         _ASSERTE(lRes == ERROR_SUCCESS);
  1189.         m_hKey = hKey;
  1190.     }
  1191.     return lRes;
  1192. }
  1193.  
  1194. LONG CRegKey::QueryValue(DWORD& dwValue, LPCTSTR lpszValueName)
  1195. {
  1196.     DWORD dwType = NULL;
  1197.     DWORD dwCount = sizeof(DWORD);
  1198.     LONG lRes = RegQueryValueEx(m_hKey, (LPTSTR)lpszValueName, NULL, &dwType,
  1199.         (LPBYTE)&dwValue, &dwCount);
  1200.     _ASSERTE((lRes!=ERROR_SUCCESS) || (dwType == REG_DWORD));
  1201.     _ASSERTE((lRes!=ERROR_SUCCESS) || (dwCount == sizeof(DWORD)));
  1202.     return lRes;
  1203. }
  1204.  
  1205. LONG CRegKey::QueryValue(LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount)
  1206. {
  1207.     _ASSERTE(pdwCount != NULL);
  1208.     DWORD dwType = NULL;
  1209.     LONG lRes = RegQueryValueEx(m_hKey, (LPTSTR)lpszValueName, NULL, &dwType,
  1210.         (LPBYTE)szValue, pdwCount);
  1211.     _ASSERTE((lRes!=ERROR_SUCCESS) || (dwType == REG_SZ) ||
  1212.              (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ));
  1213.     return lRes;
  1214. }
  1215.  
  1216. LONG WINAPI CRegKey::SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName)
  1217. {
  1218.     _ASSERTE(lpszValue != NULL);
  1219.     CRegKey key;
  1220.     LONG lRes = key.Create(hKeyParent, lpszKeyName);
  1221.     if (lRes == ERROR_SUCCESS)
  1222.         lRes = key.SetValue(lpszValue, lpszValueName);
  1223.     return lRes;
  1224. }
  1225.  
  1226. LONG CRegKey::SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName)
  1227. {
  1228.     _ASSERTE(lpszValue != NULL);
  1229.     CRegKey key;
  1230.     LONG lRes = key.Create(m_hKey, lpszKeyName);
  1231.     if (lRes == ERROR_SUCCESS)
  1232.         lRes = key.SetValue(lpszValue, lpszValueName);
  1233.     return lRes;
  1234. }
  1235.  
  1236. LONG CRegKey::SetValue(DWORD dwValue, LPCTSTR lpszValueName)
  1237. {
  1238.     _ASSERTE(m_hKey != NULL);
  1239.     return RegSetValueEx(m_hKey, lpszValueName, NULL, REG_DWORD,
  1240.         (BYTE * const)&dwValue, sizeof(DWORD));
  1241. }
  1242.  
  1243. HRESULT CRegKey::SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName)
  1244. {
  1245.     _ASSERTE(lpszValue != NULL);
  1246.     _ASSERTE(m_hKey != NULL);
  1247.     return RegSetValueEx(m_hKey, lpszValueName, NULL, REG_SZ,
  1248.         (BYTE * const)lpszValue, (lstrlen(lpszValue)+1)*sizeof(TCHAR));
  1249. }
  1250.  
  1251. //RecurseDeleteKey is necessary because on NT RegDeleteKey doesn't work if the
  1252. //specified key has subkeys
  1253. LONG CRegKey::RecurseDeleteKey(LPCTSTR lpszKey)
  1254. {
  1255.     CRegKey key;
  1256.     LONG lRes = key.Open(m_hKey, lpszKey);
  1257.     if (lRes != ERROR_SUCCESS)
  1258.         return lRes;
  1259.     FILETIME time;
  1260.     TCHAR szBuffer[256];
  1261.     DWORD dwSize = 256;
  1262.     while (RegEnumKeyEx(key.m_hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL,
  1263.         &time)==ERROR_SUCCESS)
  1264.     {
  1265.         lRes = key.RecurseDeleteKey(szBuffer);
  1266.         if (lRes != ERROR_SUCCESS)
  1267.             return lRes;
  1268.         dwSize = 256;
  1269.     }
  1270.     key.Close();
  1271.     return DeleteSubKey(lpszKey);
  1272. }
  1273.  
  1274. #ifdef __ATLCOM_H__
  1275. #ifndef _ATL_NO_SECURITY
  1276.  
  1277. CSecurityDescriptor::CSecurityDescriptor()
  1278. {
  1279.     m_pSD = NULL;
  1280.     m_pOwner = NULL;
  1281.     m_pGroup = NULL;
  1282.     m_pDACL = NULL;
  1283.     m_pSACL= NULL;
  1284. }
  1285.  
  1286. CSecurityDescriptor::~CSecurityDescriptor()
  1287. {
  1288.     if (m_pSD)
  1289.         delete m_pSD;
  1290.     if (m_pOwner)
  1291.         free(m_pOwner);
  1292.     if (m_pGroup)
  1293.         free(m_pGroup);
  1294.     if (m_pDACL)
  1295.         free(m_pDACL);
  1296.     if (m_pSACL)
  1297.         free(m_pSACL);
  1298. }
  1299.  
  1300. HRESULT CSecurityDescriptor::Initialize()
  1301. {
  1302.     if (m_pSD)
  1303.     {
  1304.         delete m_pSD;
  1305.         m_pSD = NULL;
  1306.     }
  1307.     if (m_pOwner)
  1308.     {
  1309.         free(m_pOwner);
  1310.         m_pOwner = NULL;
  1311.     }
  1312.     if (m_pGroup)
  1313.     {
  1314.         free(m_pGroup);
  1315.         m_pGroup = NULL;
  1316.     }
  1317.     if (m_pDACL)
  1318.     {
  1319.         free(m_pDACL);
  1320.         m_pDACL = NULL;
  1321.     }
  1322.     if (m_pSACL)
  1323.     {
  1324.         free(m_pSACL);
  1325.         m_pSACL = NULL;
  1326.     }
  1327.  
  1328.     ATLTRY(m_pSD = new SECURITY_DESCRIPTOR);
  1329.     if (!m_pSD)
  1330.         return E_OUTOFMEMORY;
  1331.     if (!InitializeSecurityDescriptor(m_pSD, SECURITY_DESCRIPTOR_REVISION))
  1332.     {
  1333.         HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1334.         delete m_pSD;
  1335.         m_pSD = NULL;
  1336.         _ASSERTE(FALSE);
  1337.         return hr;
  1338.     }
  1339.     // Set the DACL to allow EVERYONE
  1340.     SetSecurityDescriptorDacl(m_pSD, TRUE, NULL, FALSE);
  1341.     return S_OK;
  1342. }
  1343.  
  1344. HRESULT CSecurityDescriptor::InitializeFromProcessToken(BOOL bDefaulted)
  1345. {
  1346.     PSID pUserSid;
  1347.     PSID pGroupSid;
  1348.     HRESULT hr;
  1349.  
  1350.     Initialize();
  1351.     hr = GetProcessSids(&pUserSid, &pGroupSid);
  1352.     if (FAILED(hr))
  1353.         return hr;
  1354.     hr = SetOwner(pUserSid, bDefaulted);
  1355.     if (FAILED(hr))
  1356.         return hr;
  1357.     hr = SetGroup(pGroupSid, bDefaulted);
  1358.     if (FAILED(hr))
  1359.         return hr;
  1360.     return S_OK;
  1361. }
  1362.  
  1363. HRESULT CSecurityDescriptor::InitializeFromThreadToken(BOOL bDefaulted, BOOL bRevertToProcessToken)
  1364. {
  1365.     PSID pUserSid;
  1366.     PSID pGroupSid;
  1367.     HRESULT hr;
  1368.  
  1369.     Initialize();
  1370.     hr = GetThreadSids(&pUserSid, &pGroupSid);
  1371.     if (HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken)
  1372.         hr = GetProcessSids(&pUserSid, &pGroupSid);
  1373.     if (FAILED(hr))
  1374.         return hr;
  1375.     hr = SetOwner(pUserSid, bDefaulted);
  1376.     if (FAILED(hr))
  1377.         return hr;
  1378.     hr = SetGroup(pGroupSid, bDefaulted);
  1379.     if (FAILED(hr))
  1380.         return hr;
  1381.     return S_OK;
  1382. }
  1383.  
  1384. HRESULT CSecurityDescriptor::SetOwner(PSID pOwnerSid, BOOL bDefaulted)
  1385. {
  1386.     _ASSERTE(m_pSD);
  1387.  
  1388.     // Mark the SD as having no owner
  1389.     if (!SetSecurityDescriptorOwner(m_pSD, NULL, bDefaulted))
  1390.     {
  1391.         HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1392.         _ASSERTE(FALSE);
  1393.         return hr;
  1394.     }
  1395.  
  1396.     if (m_pOwner)
  1397.     {
  1398.         free(m_pOwner);
  1399.         m_pOwner = NULL;
  1400.     }
  1401.  
  1402.     // If they asked for no owner don't do the copy
  1403.     if (pOwnerSid == NULL)
  1404.         return S_OK;
  1405.  
  1406.     // Make a copy of the Sid for the return value
  1407.     DWORD dwSize = GetLengthSid(pOwnerSid);
  1408.  
  1409.     m_pOwner = (PSID) malloc(dwSize);
  1410.     if (!m_pOwner)
  1411.     {
  1412.         // Insufficient memory to allocate Sid
  1413.         _ASSERTE(FALSE);
  1414.         return E_OUTOFMEMORY;
  1415.     }
  1416.     if (!CopySid(dwSize, m_pOwner, pOwnerSid))
  1417.     {
  1418.         HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1419.         _ASSERTE(FALSE);
  1420.         free(m_pOwner);
  1421.         m_pOwner = NULL;
  1422.         return hr;
  1423.     }
  1424.  
  1425.     _ASSERTE(IsValidSid(m_pOwner));
  1426.  
  1427.     if (!SetSecurityDescriptorOwner(m_pSD, m_pOwner, bDefaulted))
  1428.     {
  1429.         HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1430.         _ASSERTE(FALSE);
  1431.         free(m_pOwner);
  1432.         m_pOwner = NULL;
  1433.         return hr;
  1434.     }
  1435.  
  1436.     return S_OK;
  1437. }
  1438.  
  1439. HRESULT CSecurityDescriptor::SetGroup(PSID pGroupSid, BOOL bDefaulted)
  1440. {
  1441.     _ASSERTE(m_pSD);
  1442.  
  1443.     // Mark the SD as having no Group
  1444.     if (!SetSecurityDescriptorGroup(m_pSD, NULL, bDefaulted))
  1445.     {
  1446.         HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1447.         _ASSERTE(FALSE);
  1448.         return hr;
  1449.     }
  1450.  
  1451.     if (m_pGroup)
  1452.     {
  1453.         free(m_pGroup);
  1454.         m_pGroup = NULL;
  1455.     }
  1456.  
  1457.     // If they asked for no Group don't do the copy
  1458.     if (pGroupSid == NULL)
  1459.         return S_OK;
  1460.  
  1461.     // Make a copy of the Sid for the return value
  1462.     DWORD dwSize = GetLengthSid(pGroupSid);
  1463.  
  1464.     m_pGroup = (PSID) malloc(dwSize);
  1465.     if (!m_pGroup)
  1466.     {
  1467.         // Insufficient memory to allocate Sid
  1468.         _ASSERTE(FALSE);
  1469.         return E_OUTOFMEMORY;
  1470.     }
  1471.     if (!CopySid(dwSize, m_pGroup, pGroupSid))
  1472.     {
  1473.         HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1474.         _ASSERTE(FALSE);
  1475.         free(m_pGroup);
  1476.         m_pGroup = NULL;
  1477.         return hr;
  1478.     }
  1479.  
  1480.     _ASSERTE(IsValidSid(m_pGroup));
  1481.  
  1482.     if (!SetSecurityDescriptorGroup(m_pSD, m_pGroup, bDefaulted))
  1483.     {
  1484.         HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1485.         _ASSERTE(FALSE);
  1486.         free(m_pGroup);
  1487.         m_pGroup = NULL;
  1488.         return hr;
  1489.     }
  1490.  
  1491.     return S_OK;
  1492. }
  1493.  
  1494. HRESULT CSecurityDescriptor::Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1495. {
  1496.     HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask);
  1497.     if (SUCCEEDED(hr))
  1498.         SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE);
  1499.     return hr;
  1500. }
  1501.  
  1502. HRESULT CSecurityDescriptor::Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1503. {
  1504.     HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask);
  1505.     if (SUCCEEDED(hr))
  1506.         SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE);
  1507.     return hr;
  1508. }
  1509.  
  1510. HRESULT CSecurityDescriptor::Revoke(LPCTSTR pszPrincipal)
  1511. {
  1512.     HRESULT hr = RemovePrincipalFromACL(m_pDACL, pszPrincipal);
  1513.     if (SUCCEEDED(hr))
  1514.         SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE);
  1515.     return hr;
  1516. }
  1517.  
  1518. HRESULT CSecurityDescriptor::GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid)
  1519. {
  1520.     BOOL bRes;
  1521.     HRESULT hr;
  1522.     HANDLE hToken = NULL;
  1523.     if (ppUserSid)
  1524.         *ppUserSid = NULL;
  1525.     if (ppGroupSid)
  1526.         *ppGroupSid = NULL;
  1527.     bRes = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
  1528.     if (!bRes)
  1529.     {
  1530.         // Couldn't open process token
  1531.         hr = HRESULT_FROM_WIN32(GetLastError());
  1532.         _ASSERTE(FALSE);
  1533.         return hr;
  1534.     }
  1535.     hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
  1536.     return hr;
  1537. }
  1538.  
  1539. HRESULT CSecurityDescriptor::GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid, BOOL bOpenAsSelf)
  1540. {
  1541.     BOOL bRes;
  1542.     HRESULT hr;
  1543.     HANDLE hToken = NULL;
  1544.     if (ppUserSid)
  1545.         *ppUserSid = NULL;
  1546.     if (ppGroupSid)
  1547.         *ppGroupSid = NULL;
  1548.     bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken);
  1549.     if (!bRes)
  1550.     {
  1551.         // Couldn't open thread token
  1552.         hr = HRESULT_FROM_WIN32(GetLastError());
  1553.         return hr;
  1554.     }
  1555.     hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
  1556.     return hr;
  1557. }
  1558.  
  1559.  
  1560. HRESULT CSecurityDescriptor::GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid)
  1561. {
  1562.     DWORD dwSize;
  1563.     HRESULT hr;
  1564.     PTOKEN_USER ptkUser = NULL;
  1565.     PTOKEN_PRIMARY_GROUP ptkGroup = NULL;
  1566.  
  1567.     if (ppUserSid)
  1568.         *ppUserSid = NULL;
  1569.     if (ppGroupSid)
  1570.         *ppGroupSid = NULL;
  1571.  
  1572.     if (ppUserSid)
  1573.     {
  1574.         // Get length required for TokenUser by specifying buffer length of 0
  1575.         GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
  1576.         hr = GetLastError();
  1577.         if (hr != ERROR_INSUFFICIENT_BUFFER)
  1578.         {
  1579.             // Expected ERROR_INSUFFICIENT_BUFFER
  1580.             _ASSERTE(FALSE);
  1581.             hr = HRESULT_FROM_WIN32(hr);
  1582.             goto failed;
  1583.         }
  1584.  
  1585.         ptkUser = (TOKEN_USER*) malloc(dwSize);
  1586.         if (!ptkUser)
  1587.         {
  1588.             // Insufficient memory to allocate TOKEN_USER
  1589.             _ASSERTE(FALSE);
  1590.             hr = E_OUTOFMEMORY;
  1591.             goto failed;
  1592.         }
  1593.         // Get Sid of process token.
  1594.         if (!GetTokenInformation(hToken, TokenUser, ptkUser, dwSize, &dwSize))
  1595.         {
  1596.             // Couldn't get user info
  1597.             hr = HRESULT_FROM_WIN32(GetLastError());
  1598.             _ASSERTE(FALSE);
  1599.             goto failed;
  1600.         }
  1601.  
  1602.         // Make a copy of the Sid for the return value
  1603.         dwSize = GetLengthSid(ptkUser->User.Sid);
  1604.  
  1605.         PSID pSid = (PSID) malloc(dwSize);
  1606.         if (!pSid)
  1607.         {
  1608.             // Insufficient memory to allocate Sid
  1609.             _ASSERTE(FALSE);
  1610.             hr = E_OUTOFMEMORY;
  1611.             goto failed;
  1612.         }
  1613.         if (!CopySid(dwSize, pSid, ptkUser->User.Sid))
  1614.         {
  1615.             hr = HRESULT_FROM_WIN32(GetLastError());
  1616.             _ASSERTE(FALSE);
  1617.             goto failed;
  1618.         }
  1619.  
  1620.         _ASSERTE(IsValidSid(pSid));
  1621.         *ppUserSid = pSid;
  1622.         free(ptkUser);
  1623.     }
  1624.     if (ppGroupSid)
  1625.     {
  1626.         // Get length required for TokenPrimaryGroup by specifying buffer length of 0
  1627.         GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize);
  1628.         hr = GetLastError();
  1629.         if (hr != ERROR_INSUFFICIENT_BUFFER)
  1630.         {
  1631.             // Expected ERROR_INSUFFICIENT_BUFFER
  1632.             _ASSERTE(FALSE);
  1633.             hr = HRESULT_FROM_WIN32(hr);
  1634.             goto failed;
  1635.         }
  1636.  
  1637.         ptkGroup = (TOKEN_PRIMARY_GROUP*) malloc(dwSize);
  1638.         if (!ptkGroup)
  1639.         {
  1640.             // Insufficient memory to allocate TOKEN_USER
  1641.             _ASSERTE(FALSE);
  1642.             hr = E_OUTOFMEMORY;
  1643.             goto failed;
  1644.         }
  1645.         // Get Sid of process token.
  1646.         if (!GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize))
  1647.         {
  1648.             // Couldn't get user info
  1649.             hr = HRESULT_FROM_WIN32(GetLastError());
  1650.             _ASSERTE(FALSE);
  1651.             goto failed;
  1652.         }
  1653.  
  1654.         // Make a copy of the Sid for the return value
  1655.         dwSize = GetLengthSid(ptkGroup->PrimaryGroup);
  1656.  
  1657.         PSID pSid = (PSID) malloc(dwSize);
  1658.         if (!pSid)
  1659.         {
  1660.             // Insufficient memory to allocate Sid
  1661.             _ASSERTE(FALSE);
  1662.             hr = E_OUTOFMEMORY;
  1663.             goto failed;
  1664.         }
  1665.         if (!CopySid(dwSize, pSid, ptkGroup->PrimaryGroup))
  1666.         {
  1667.             hr = HRESULT_FROM_WIN32(GetLastError());
  1668.             _ASSERTE(FALSE);
  1669.             goto failed;
  1670.         }
  1671.  
  1672.         _ASSERTE(IsValidSid(pSid));
  1673.  
  1674.         *ppGroupSid = pSid;
  1675.         free(ptkGroup);
  1676.     }
  1677.  
  1678.     return S_OK;
  1679.  
  1680. failed:
  1681.     if (ptkUser)
  1682.         free(ptkUser);
  1683.     if (ptkGroup)
  1684.         free (ptkGroup);
  1685.     return hr;
  1686. }
  1687.  
  1688.  
  1689. HRESULT CSecurityDescriptor::GetCurrentUserSID(PSID *ppSid)
  1690. {
  1691.     HANDLE tkHandle;
  1692.  
  1693.     if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle))
  1694.     {
  1695.         TOKEN_USER *tkUser;
  1696.         DWORD tkSize;
  1697.         DWORD sidLength;
  1698.  
  1699.         // Call to get size information for alloc
  1700.         GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize);
  1701.         tkUser = (TOKEN_USER *) malloc(tkSize);
  1702.  
  1703.         // Now make the real call
  1704.         if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize))
  1705.         {
  1706.             sidLength = GetLengthSid(tkUser->User.Sid);
  1707.             *ppSid = (PSID) malloc(sidLength);
  1708.  
  1709.             memcpy(*ppSid, tkUser->User.Sid, sidLength);
  1710.             CloseHandle(tkHandle);
  1711.  
  1712.             free(tkUser);
  1713.             return S_OK;
  1714.         }
  1715.         else
  1716.         {
  1717.             free(tkUser);
  1718.             return HRESULT_FROM_WIN32(GetLastError());
  1719.         }
  1720.     }
  1721.     return HRESULT_FROM_WIN32(GetLastError());
  1722. }
  1723.  
  1724.  
  1725. HRESULT CSecurityDescriptor::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid)
  1726. {
  1727.     HRESULT hr;
  1728.     LPTSTR pszRefDomain = NULL;
  1729.     DWORD dwDomainSize = 0;
  1730.     DWORD dwSidSize = 0;
  1731.     SID_NAME_USE snu;
  1732.  
  1733.     // Call to get size info for alloc
  1734.     LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu);
  1735.  
  1736.     hr = GetLastError();
  1737.     if (hr != ERROR_INSUFFICIENT_BUFFER)
  1738.         return HRESULT_FROM_WIN32(hr);
  1739.  
  1740.     ATLTRY(pszRefDomain = new TCHAR[dwDomainSize]);
  1741.     if (pszRefDomain == NULL)
  1742.         return E_OUTOFMEMORY;
  1743.  
  1744.     *ppSid = (PSID) malloc(dwSidSize);
  1745.     if (*ppSid != NULL)
  1746.     {
  1747.         if (!LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu))
  1748.         {
  1749.             free(*ppSid);
  1750.             *ppSid = NULL;
  1751.             delete[] pszRefDomain;
  1752.             return HRESULT_FROM_WIN32(GetLastError());
  1753.         }
  1754.         delete[] pszRefDomain;
  1755.         return S_OK;
  1756.     }
  1757.     delete[] pszRefDomain;
  1758.     return E_OUTOFMEMORY;
  1759. }
  1760.  
  1761.  
  1762. HRESULT CSecurityDescriptor::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD)
  1763. {
  1764.     PACL    pDACL = NULL;
  1765.     PACL    pSACL = NULL;
  1766.     BOOL    bDACLPresent, bSACLPresent;
  1767.     BOOL    bDefaulted;
  1768.     PACL    m_pDACL = NULL;
  1769.     ACCESS_ALLOWED_ACE* pACE;
  1770.     HRESULT hr;
  1771.     PSID    pUserSid;
  1772.     PSID    pGroupSid;
  1773.  
  1774.     hr = Initialize();
  1775.     if(FAILED(hr))
  1776.         return hr;
  1777.  
  1778.     // get the existing DACL.
  1779.     if (!GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted))
  1780.         goto failed;
  1781.  
  1782.     if (bDACLPresent)
  1783.     {
  1784.         if (pDACL)
  1785.         {
  1786.             // allocate new DACL.
  1787.             m_pDACL = (PACL) malloc(pDACL->AclSize);
  1788.             if (!m_pDACL)
  1789.                 goto failed;
  1790.  
  1791.             // initialize the DACL
  1792.             if (!InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION))
  1793.                 goto failed;
  1794.  
  1795.             // copy the ACES
  1796.             for (int i = 0; i < pDACL->AceCount; i++)
  1797.             {
  1798.                 if (!GetAce(pDACL, i, (void **)&pACE))
  1799.                     goto failed;
  1800.  
  1801.                 if (!AddAccessAllowedAce(m_pDACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
  1802.                     goto failed;
  1803.             }
  1804.  
  1805.             if (!IsValidAcl(m_pDACL))
  1806.                 goto failed;
  1807.         }
  1808.  
  1809.         // set the DACL
  1810.         if (!SetSecurityDescriptorDacl(m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, bDefaulted))
  1811.             goto failed;
  1812.     }
  1813.  
  1814.     // get the existing SACL.
  1815.     if (!GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted))
  1816.         goto failed;
  1817.  
  1818.     if (bSACLPresent)
  1819.     {
  1820.         if (pSACL)
  1821.         {
  1822.             // allocate new SACL.
  1823.             m_pSACL = (PACL) malloc(pSACL->AclSize);
  1824.             if (!m_pSACL)
  1825.                 goto failed;
  1826.  
  1827.             // initialize the SACL
  1828.             if (!InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION))
  1829.                 goto failed;
  1830.  
  1831.             // copy the ACES
  1832.             for (int i = 0; i < pSACL->AceCount; i++)
  1833.             {
  1834.                 if (!GetAce(pSACL, i, (void **)&pACE))
  1835.                     goto failed;
  1836.  
  1837.                 if (!AddAccessAllowedAce(m_pSACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
  1838.                     goto failed;
  1839.             }
  1840.  
  1841.             if (!IsValidAcl(m_pSACL))
  1842.                 goto failed;
  1843.         }
  1844.  
  1845.         // set the SACL
  1846.         if (!SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, bDefaulted))
  1847.             goto failed;
  1848.     }
  1849.  
  1850.     if (!GetSecurityDescriptorOwner(m_pSD, &pUserSid, &bDefaulted))
  1851.         goto failed;
  1852.  
  1853.     if (FAILED(SetOwner(pUserSid, bDefaulted)))
  1854.         goto failed;
  1855.  
  1856.     if (!GetSecurityDescriptorGroup(m_pSD, &pGroupSid, &bDefaulted))
  1857.         goto failed;
  1858.  
  1859.     if (FAILED(SetGroup(pGroupSid, bDefaulted)))
  1860.         goto failed;
  1861.  
  1862.     if (!IsValidSecurityDescriptor(m_pSD))
  1863.         goto failed;
  1864.  
  1865.     return hr;
  1866.  
  1867. failed:
  1868.     if (m_pDACL)
  1869.         free(m_pDACL);
  1870.     if (m_pSD)
  1871.         free(m_pSD);
  1872.     return E_UNEXPECTED;
  1873. }
  1874.  
  1875. HRESULT CSecurityDescriptor::AttachObject(HANDLE hObject)
  1876. {
  1877.     HRESULT hr;
  1878.     DWORD dwSize = 0;
  1879.     PSECURITY_DESCRIPTOR pSD = NULL;
  1880.  
  1881.     GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  1882.         DACL_SECURITY_INFORMATION, pSD, 0, &dwSize);
  1883.  
  1884.     hr = GetLastError();
  1885.     if (hr != ERROR_INSUFFICIENT_BUFFER)
  1886.         return HRESULT_FROM_WIN32(hr);
  1887.  
  1888.     pSD = (PSECURITY_DESCRIPTOR) malloc(dwSize);
  1889.  
  1890.     if (!GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  1891.         DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize))
  1892.     {
  1893.         hr = HRESULT_FROM_WIN32(GetLastError());
  1894.         free(pSD);
  1895.         return hr;
  1896.     }
  1897.  
  1898.     hr = Attach(pSD);
  1899.     free(pSD);
  1900.     return hr;
  1901. }
  1902.  
  1903.  
  1904. HRESULT CSecurityDescriptor::CopyACL(PACL pDest, PACL pSrc)
  1905. {
  1906.     ACL_SIZE_INFORMATION aclSizeInfo;
  1907.     LPVOID pAce;
  1908.     ACE_HEADER *aceHeader;
  1909.  
  1910.     if (pSrc == NULL)
  1911.         return S_OK;
  1912.  
  1913.     if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
  1914.         return HRESULT_FROM_WIN32(GetLastError());
  1915.  
  1916.     // Copy all of the ACEs to the new ACL
  1917.     for (UINT i = 0; i < aclSizeInfo.AceCount; i++)
  1918.     {
  1919.         if (!GetAce(pSrc, i, &pAce))
  1920.             return HRESULT_FROM_WIN32(GetLastError());
  1921.  
  1922.         aceHeader = (ACE_HEADER *) pAce;
  1923.  
  1924.         if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize))
  1925.             return HRESULT_FROM_WIN32(GetLastError());
  1926.     }
  1927.  
  1928.     return S_OK;
  1929. }
  1930.  
  1931. HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1932. {
  1933.     ACL_SIZE_INFORMATION aclSizeInfo;
  1934.     int aclSize;
  1935.     DWORD returnValue;
  1936.     PSID principalSID;
  1937.     PACL oldACL, newACL;
  1938.  
  1939.     oldACL = *ppAcl;
  1940.  
  1941.     returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  1942.     if (FAILED(returnValue))
  1943.         return returnValue;
  1944.  
  1945.     aclSizeInfo.AclBytesInUse = 0;
  1946.     if (*ppAcl != NULL)
  1947.         GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  1948.  
  1949.     aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  1950.  
  1951.     ATLTRY(newACL = (PACL) new BYTE[aclSize]);
  1952.  
  1953.     if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  1954.     {
  1955.         free(principalSID);
  1956.         return HRESULT_FROM_WIN32(GetLastError());
  1957.     }
  1958.  
  1959.     if (!AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  1960.     {
  1961.         free(principalSID);
  1962.         return HRESULT_FROM_WIN32(GetLastError());
  1963.     }
  1964.  
  1965.     returnValue = CopyACL(newACL, oldACL);
  1966.     if (FAILED(returnValue))
  1967.     {
  1968.         free(principalSID);
  1969.         return returnValue;
  1970.     }
  1971.  
  1972.     *ppAcl = newACL;
  1973.  
  1974.     if (oldACL != NULL)
  1975.         free(oldACL);
  1976.     free(principalSID);
  1977.     return S_OK;
  1978. }
  1979.  
  1980.  
  1981. HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1982. {
  1983.     ACL_SIZE_INFORMATION aclSizeInfo;
  1984.     int aclSize;
  1985.     DWORD returnValue;
  1986.     PSID principalSID;
  1987.     PACL oldACL, newACL;
  1988.  
  1989.     oldACL = *ppAcl;
  1990.  
  1991.     returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  1992.     if (FAILED(returnValue))
  1993.         return returnValue;
  1994.  
  1995.     aclSizeInfo.AclBytesInUse = 0;
  1996.     if (*ppAcl != NULL)
  1997.         GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  1998.  
  1999.     aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  2000.  
  2001.     ATLTRY(newACL = (PACL) new BYTE[aclSize]);
  2002.  
  2003.     if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  2004.     {
  2005.         free(principalSID);
  2006.         return HRESULT_FROM_WIN32(GetLastError());
  2007.     }
  2008.  
  2009.     returnValue = CopyACL(newACL, oldACL);
  2010.     if (FAILED(returnValue))
  2011.     {
  2012.         free(principalSID);
  2013.         return returnValue;
  2014.     }
  2015.  
  2016.     if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  2017.     {
  2018.         free(principalSID);
  2019.         return HRESULT_FROM_WIN32(GetLastError());
  2020.     }
  2021.  
  2022.     *ppAcl = newACL;
  2023.  
  2024.     if (oldACL != NULL)
  2025.         free(oldACL);
  2026.     free(principalSID);
  2027.     return S_OK;
  2028. }
  2029.  
  2030.  
  2031. HRESULT CSecurityDescriptor::RemovePrincipalFromACL(PACL pAcl, LPCTSTR pszPrincipal)
  2032. {
  2033.     ACL_SIZE_INFORMATION aclSizeInfo;
  2034.     ULONG i;
  2035.     LPVOID ace;
  2036.     ACCESS_ALLOWED_ACE *accessAllowedAce;
  2037.     ACCESS_DENIED_ACE *accessDeniedAce;
  2038.     SYSTEM_AUDIT_ACE *systemAuditAce;
  2039.     PSID principalSID;
  2040.     DWORD returnValue;
  2041.     ACE_HEADER *aceHeader;
  2042.  
  2043.     returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  2044.     if (FAILED(returnValue))
  2045.         return returnValue;
  2046.  
  2047.     GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  2048.  
  2049.     for (i = 0; i < aclSizeInfo.AceCount; i++)
  2050.     {
  2051.         if (!GetAce(pAcl, i, &ace))
  2052.         {
  2053.             free(principalSID);
  2054.             return HRESULT_FROM_WIN32(GetLastError());
  2055.         }
  2056.  
  2057.         aceHeader = (ACE_HEADER *) ace;
  2058.  
  2059.         if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2060.         {
  2061.             accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
  2062.  
  2063.             if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart))
  2064.             {
  2065.                 DeleteAce(pAcl, i);
  2066.                 free(principalSID);
  2067.                 return S_OK;
  2068.             }
  2069.         } else
  2070.  
  2071.         if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  2072.         {
  2073.             accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
  2074.  
  2075.             if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart))
  2076.             {
  2077.                 DeleteAce(pAcl, i);
  2078.                 free(principalSID);
  2079.                 return S_OK;
  2080.             }
  2081.         } else
  2082.  
  2083.         if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
  2084.         {
  2085.             systemAuditAce = (SYSTEM_AUDIT_ACE *) ace;
  2086.  
  2087.             if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart))
  2088.             {
  2089.                 DeleteAce(pAcl, i);
  2090.                 free(principalSID);
  2091.                 return S_OK;
  2092.             }
  2093.         }
  2094.     }
  2095.     free(principalSID);
  2096.     return S_OK;
  2097. }
  2098.  
  2099.  
  2100. HRESULT CSecurityDescriptor::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken)
  2101. {
  2102.     HRESULT hr;
  2103.     TOKEN_PRIVILEGES tpPrevious;
  2104.     TOKEN_PRIVILEGES tp;
  2105.     DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
  2106.     LUID luid;
  2107.  
  2108.     // if no token specified open process token
  2109.     if (hToken == 0)
  2110.     {
  2111.         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  2112.         {
  2113.             hr = HRESULT_FROM_WIN32(GetLastError());
  2114.             _ASSERTE(FALSE);
  2115.             return hr;
  2116.         }
  2117.     }
  2118.  
  2119.     if (!LookupPrivilegeValue(NULL, privilege, &luid ))
  2120.     {
  2121.         hr = HRESULT_FROM_WIN32(GetLastError());
  2122.         _ASSERTE(FALSE);
  2123.         return hr;
  2124.     }
  2125.  
  2126.     tp.PrivilegeCount = 1;
  2127.     tp.Privileges[0].Luid = luid;
  2128.     tp.Privileges[0].Attributes = 0;
  2129.  
  2130.     if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious))
  2131.     {
  2132.         hr = HRESULT_FROM_WIN32(GetLastError());
  2133.         _ASSERTE(FALSE);
  2134.         return hr;
  2135.     }
  2136.  
  2137.     tpPrevious.PrivilegeCount = 1;
  2138.     tpPrevious.Privileges[0].Luid = luid;
  2139.  
  2140.     if (bEnable)
  2141.         tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
  2142.     else
  2143.         tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
  2144.  
  2145.     if (!AdjustTokenPrivileges(hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL))
  2146.     {
  2147.         hr = HRESULT_FROM_WIN32(GetLastError());
  2148.         _ASSERTE(FALSE);
  2149.         return hr;
  2150.     }
  2151.     return S_OK;
  2152. }
  2153.  
  2154. #endif //_ATL_NO_SECURITY
  2155. #endif //__ATLCOM_H__
  2156.  
  2157. #ifdef _DEBUG
  2158.  
  2159. void _cdecl AtlTrace(LPCTSTR lpszFormat, ...)
  2160. {
  2161.     va_list args;
  2162.     va_start(args, lpszFormat);
  2163.  
  2164.     int nBuf;
  2165.     TCHAR szBuffer[512];
  2166.  
  2167.     nBuf = _vstprintf(szBuffer, lpszFormat, args);
  2168.     _ASSERTE(nBuf < sizeof(szBuffer));
  2169.  
  2170.     OutputDebugString(szBuffer);
  2171.     va_end(args);
  2172. }
  2173. #endif
  2174.  
  2175. #ifndef ATL_NO_NAMESPACE
  2176. }; //namespace ATL
  2177. #endif
  2178.  
  2179. ///////////////////////////////////////////////////////////////////////////////
  2180. //All Global stuff goes below this line
  2181. ///////////////////////////////////////////////////////////////////////////////
  2182.  
  2183. /////////////////////////////////////////////////////////////////////////////
  2184. // Minimize CRT
  2185. // Specify DllMain as EntryPoint
  2186. // Turn off exception handling
  2187. // Define _ATL_MIN_CRT
  2188.  
  2189. #ifdef _ATL_MIN_CRT
  2190. /////////////////////////////////////////////////////////////////////////////
  2191. // Startup Code
  2192.  
  2193. #if defined(_WINDLL) || defined(_USRDLL)
  2194.  
  2195. // Declare DllMain
  2196. extern "C" BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved);
  2197.  
  2198. extern "C" BOOL WINAPI _DllMainCRTStartup(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
  2199. {
  2200.     return DllMain(hDllHandle, dwReason, lpReserved);
  2201. }
  2202.  
  2203. #else
  2204.  
  2205. // wWinMain is not defined in winbase.h.
  2206. extern "C" int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd);
  2207.  
  2208. #define SPACECHAR   _T(' ')
  2209. #define DQUOTECHAR  _T('\"')
  2210.  
  2211.  
  2212. #ifdef _UNICODE
  2213. extern "C" void wWinMainCRTStartup()
  2214. #else // _UNICODE
  2215. extern "C" void WinMainCRTStartup()
  2216. #endif // _UNICODE
  2217. {
  2218.     LPTSTR lpszCommandLine = ::GetCommandLine();
  2219.     if(lpszCommandLine == NULL)
  2220.         ::ExitProcess((UINT)-1);
  2221.  
  2222.     // Skip past program name (first token in command line).
  2223.     // Check for and handle quoted program name.
  2224.     if(*lpszCommandLine == DQUOTECHAR)
  2225.     {
  2226.         // Scan, and skip over, subsequent characters until
  2227.         // another double-quote or a null is encountered.
  2228.         do
  2229.         {
  2230.             lpszCommandLine = ::CharNext(lpszCommandLine);
  2231.         }
  2232.         while((*lpszCommandLine != DQUOTECHAR) && (*lpszCommandLine != _T('\0')));
  2233.  
  2234.         // If we stopped on a double-quote (usual case), skip over it.
  2235.         if(*lpszCommandLine == DQUOTECHAR)
  2236.             lpszCommandLine = ::CharNext(lpszCommandLine);
  2237.     }
  2238.     else
  2239.     {
  2240.         while(*lpszCommandLine > SPACECHAR)
  2241.             lpszCommandLine = ::CharNext(lpszCommandLine);
  2242.     }
  2243.  
  2244.     // Skip past any white space preceeding the second token.
  2245.     while(*lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
  2246.         lpszCommandLine = ::CharNext(lpszCommandLine);
  2247.  
  2248.     STARTUPINFO StartupInfo;
  2249.     StartupInfo.dwFlags = 0;
  2250.     ::GetStartupInfo(&StartupInfo);
  2251.  
  2252.     int nRet = _tWinMain(::GetModuleHandle(NULL), NULL, lpszCommandLine,
  2253.         (StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ?
  2254.         StartupInfo.wShowWindow : SW_SHOWDEFAULT);
  2255.  
  2256.     ::ExitProcess((UINT)nRet);
  2257. }
  2258.  
  2259. #endif // defined(_WINDLL) | defined(_USRDLL)
  2260.  
  2261. /////////////////////////////////////////////////////////////////////////////
  2262. // Heap Allocation
  2263.  
  2264. #ifndef _DEBUG
  2265.  
  2266. #ifndef _MERGE_PROXYSTUB
  2267. //rpcproxy.h does the same thing as this
  2268. int __cdecl _purecall()
  2269. {
  2270.     DebugBreak();
  2271.     return 0;
  2272. }
  2273. #endif
  2274.  
  2275. extern "C" const int _fltused = 0;
  2276.  
  2277. void* __cdecl malloc(size_t n)
  2278. {
  2279.     if (_Module.m_hHeap == NULL)
  2280.     {
  2281.         _Module.m_hHeap = HeapCreate(0, 0, 0);
  2282.         if (_Module.m_hHeap == NULL)
  2283.             return NULL;
  2284.     }
  2285.     _ASSERTE(_Module.m_hHeap != NULL);
  2286.  
  2287. #ifdef _MALLOC_ZEROINIT
  2288.     return HeapAlloc(_Module.m_hHeap, HEAP_ZERO_MEMORY, n);
  2289. #else
  2290.     return HeapAlloc(_Module.m_hHeap, 0, n);
  2291. #endif
  2292. }
  2293.  
  2294. void* __cdecl calloc(size_t n, size_t s)
  2295. {
  2296.     return malloc(n * s);
  2297. }
  2298.  
  2299. void* __cdecl realloc(void* p, size_t n)
  2300. {
  2301.     _ASSERTE(_Module.m_hHeap != NULL);
  2302. #ifdef _MALLOC_ZEROINIT
  2303.     return (p == NULL) ? malloc(n) : HeapReAlloc(_Module.m_hHeap, HEAP_ZERO_MEMORY, p, n);
  2304. #else
  2305.     return (p == NULL) ? malloc(n) : HeapReAlloc(_Module.m_hHeap, 0, p, n);
  2306. #endif
  2307. }
  2308.  
  2309. void __cdecl free(void* p)
  2310. {
  2311.     _ASSERTE(_Module.m_hHeap != NULL);
  2312.     HeapFree(_Module.m_hHeap, 0, p);
  2313. }
  2314.  
  2315. void* __cdecl operator new(size_t n)
  2316. {
  2317.     return malloc(n);
  2318. }
  2319.  
  2320. void __cdecl operator delete(void* p)
  2321. {
  2322.     free(p);
  2323. }
  2324.  
  2325. #endif  //_DEBUG
  2326.  
  2327. #endif //_ATL_MIN_CRT
  2328.  
  2329. #ifndef _ATL_DLL
  2330.  
  2331. #ifndef ATL_NO_NAMESPACE
  2332. #ifndef _ATL_DLL_IMPL
  2333. namespace ATL
  2334. {
  2335. #endif
  2336. #endif
  2337.  
  2338. /////////////////////////////////////////////////////////////////////////////
  2339. // statics
  2340.  
  2341. static UINT WINAPI AtlGetDirLen(LPCOLESTR lpszPathName)
  2342. {
  2343.     _ASSERTE(lpszPathName != NULL);
  2344.  
  2345.     // always capture the complete file name including extension (if present)
  2346.     LPCOLESTR lpszTemp = lpszPathName;
  2347.     for (LPCOLESTR lpsz = lpszPathName; *lpsz != NULL; )
  2348.     {
  2349.         LPCOLESTR lp = CharNextO(lpsz);
  2350.         // remember last directory/drive separator
  2351.         if (*lpsz == OLESTR('\\') || *lpsz == OLESTR('/') || *lpsz == OLESTR(':'))
  2352.             lpszTemp = lp;
  2353.         lpsz = lp;
  2354.     }
  2355.  
  2356.     return lpszTemp-lpszPathName;
  2357. }
  2358.  
  2359. /////////////////////////////////////////////////////////////////////////////
  2360. // QI support
  2361.  
  2362. ATLAPI AtlInternalQueryInterface(void* pThis,
  2363.     const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
  2364. {
  2365.     _ASSERTE(pThis != NULL);
  2366.     // First entry in the com map should be a simple map entry
  2367.     _ASSERTE(pEntries->pFunc == _ATL_SIMPLEMAPENTRY);
  2368.     if (ppvObject == NULL)
  2369.         return E_POINTER;
  2370.     *ppvObject = NULL;
  2371.     if (InlineIsEqualUnknown(iid)) // use first interface
  2372.     {
  2373.             IUnknown* pUnk = (IUnknown*)((int)pThis+pEntries->dw);
  2374.             pUnk->AddRef();
  2375.             *ppvObject = pUnk;
  2376.             return S_OK;
  2377.     }
  2378.     while (pEntries->pFunc != NULL)
  2379.     {
  2380.         BOOL bBlind = (pEntries->piid == NULL);
  2381.         if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid))
  2382.         {
  2383.             if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset
  2384.             {
  2385.                 _ASSERTE(!bBlind);
  2386.                 IUnknown* pUnk = (IUnknown*)((int)pThis+pEntries->dw);
  2387.                 pUnk->AddRef();
  2388.                 *ppvObject = pUnk;
  2389.                 return S_OK;
  2390.             }
  2391.             else //actual function call
  2392.             {
  2393.                 HRESULT hRes = pEntries->pFunc(pThis,
  2394.                     iid, ppvObject, pEntries->dw);
  2395.                 if (hRes == S_OK || (!bBlind && FAILED(hRes)))
  2396.                     return hRes;
  2397.             }
  2398.         }
  2399.         pEntries++;
  2400.     }
  2401.     return E_NOINTERFACE;
  2402. }
  2403.  
  2404. /////////////////////////////////////////////////////////////////////////////
  2405. // Smart Pointer helpers
  2406.  
  2407. ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp)
  2408. {
  2409.     if (lp != NULL)
  2410.         lp->AddRef();
  2411.     if (*pp)
  2412.         (*pp)->Release();
  2413.     *pp = lp;
  2414.     return lp;
  2415. }
  2416.  
  2417. ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid)
  2418. {
  2419.     IUnknown* pTemp = *pp;
  2420.     lp->QueryInterface(riid, (void**)pp);
  2421.     if (pTemp)
  2422.         pTemp->Release();
  2423.     return *pp;
  2424. }
  2425.  
  2426. /////////////////////////////////////////////////////////////////////////////
  2427. // Inproc Marshaling helpers
  2428.  
  2429. ATLAPI AtlFreeMarshalStream(IStream* pStream)
  2430. {
  2431.     if (pStream != NULL)
  2432.     {
  2433.         CoReleaseMarshalData(pStream);
  2434.         pStream->Release();
  2435.     }
  2436.     return S_OK;
  2437. }
  2438.  
  2439. ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream)
  2440. {
  2441.     HRESULT hRes = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
  2442.     if (SUCCEEDED(hRes))
  2443.     {
  2444.         hRes = CoMarshalInterface(*ppStream, iid,
  2445.             pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
  2446.         if (FAILED(hRes))
  2447.         {
  2448.             (*ppStream)->Release();
  2449.             *ppStream = NULL;
  2450.         }
  2451.     }
  2452.     return hRes;
  2453. }
  2454.  
  2455. ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk)
  2456. {
  2457.     *ppUnk = NULL;
  2458.     HRESULT hRes = E_INVALIDARG;
  2459.     if (pStream != NULL)
  2460.     {
  2461.         LARGE_INTEGER l;
  2462.         l.QuadPart = 0;
  2463.         pStream->Seek(l, STREAM_SEEK_SET, NULL);
  2464.         hRes = CoUnmarshalInterface(pStream, iid, (void**)ppUnk);
  2465.     }
  2466.     return hRes;
  2467. }
  2468.  
  2469. ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent)
  2470. {
  2471.     DWORD dwRet;
  2472.     MSG msg;
  2473.  
  2474.     while(1)
  2475.     {
  2476.         dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT);
  2477.  
  2478.         if (dwRet == WAIT_OBJECT_0)
  2479.             return TRUE;    // The event was signaled
  2480.  
  2481.         if (dwRet != WAIT_OBJECT_0 + 1)
  2482.             break;          // Something else happened
  2483.  
  2484.         // There is one or more window message available. Dispatch them
  2485.         while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
  2486.         {
  2487.             TranslateMessage(&msg);
  2488.             DispatchMessage(&msg);
  2489.             if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
  2490.                 return TRUE; // Event is now signaled.
  2491.         }
  2492.     }
  2493.     return FALSE;
  2494. }
  2495.  
  2496. /////////////////////////////////////////////////////////////////////////////
  2497. // Connection Point Helpers
  2498.  
  2499. ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw)
  2500. {
  2501.     CComPtr<IConnectionPointContainer> pCPC;
  2502.     CComPtr<IConnectionPoint> pCP;
  2503.     HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
  2504.     if (SUCCEEDED(hRes))
  2505.         hRes = pCPC->FindConnectionPoint(iid, &pCP);
  2506.     if (SUCCEEDED(hRes))
  2507.         hRes = pCP->Advise(pUnk, pdw);
  2508.     return hRes;
  2509. }
  2510.  
  2511. ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw)
  2512. {
  2513.     CComPtr<IConnectionPointContainer> pCPC;
  2514.     CComPtr<IConnectionPoint> pCP;
  2515.     HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
  2516.     if (SUCCEEDED(hRes))
  2517.         hRes = pCPC->FindConnectionPoint(iid, &pCP);
  2518.     if (SUCCEEDED(hRes))
  2519.         hRes = pCP->Unadvise(dw);
  2520.     return hRes;
  2521. }
  2522.  
  2523. /////////////////////////////////////////////////////////////////////////////
  2524. // IDispatch Error handling
  2525.  
  2526. ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
  2527.     LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst)
  2528. {
  2529.     USES_CONVERSION;
  2530.     TCHAR szDesc[1024];
  2531.     szDesc[0] = NULL;
  2532.     // For a valid HRESULT the id should be in the range [0x0200, 0xffff]
  2533.     if (HIWORD(lpszDesc) == 0) //id
  2534.     {
  2535.         UINT nID = LOWORD((DWORD)lpszDesc);
  2536.         _ASSERTE((nID >= 0x0200 && nID <= 0xffff) || hRes != 0);
  2537.         if (LoadString(hInst, nID, szDesc, 1024) == 0)
  2538.         {
  2539.             _ASSERTE(FALSE);
  2540.             lstrcpy(szDesc, _T("Unknown Error"));
  2541.         }
  2542.         lpszDesc = T2OLE(szDesc);
  2543.         if (hRes == 0)
  2544.             hRes = MAKE_HRESULT(3, FACILITY_ITF, nID);
  2545.     }
  2546.  
  2547.     CComPtr<ICreateErrorInfo> pICEI;
  2548.     if (SUCCEEDED(CreateErrorInfo(&pICEI)))
  2549.     {
  2550.         CComPtr<IErrorInfo> pErrorInfo;
  2551.         pICEI->SetGUID(iid);
  2552.         LPOLESTR lpsz;
  2553.         ProgIDFromCLSID(clsid, &lpsz);
  2554.         if (lpsz != NULL)
  2555.             pICEI->SetSource(lpsz);
  2556.         if (dwHelpID != 0 && lpszHelpFile != NULL)
  2557.         {
  2558.             pICEI->SetHelpContext(dwHelpID);
  2559.             pICEI->SetHelpFile(const_cast<LPOLESTR>(lpszHelpFile));
  2560.         }
  2561.         CoTaskMemFree(lpsz);
  2562.         pICEI->SetDescription((LPOLESTR)lpszDesc);
  2563.         if (SUCCEEDED(pICEI->QueryInterface(IID_IErrorInfo, (void**)&pErrorInfo)))
  2564.             SetErrorInfo(0, pErrorInfo);
  2565.     }
  2566. //#ifdef _DEBUG
  2567. //  USES_CONVERSION;
  2568. //  ATLTRACE(_T("AtlReportError: Description=\"%s\" returning %x\n"), OLE2CT(lpszDesc), hRes);
  2569. //#endif
  2570.     return (hRes == 0) ? DISP_E_EXCEPTION : hRes;
  2571. }
  2572.  
  2573. /////////////////////////////////////////////////////////////////////////////
  2574. // Module
  2575.  
  2576. //Although these functions are big, they are only used once in a module
  2577. //so we should make them inline.
  2578.  
  2579. ATLAPI AtlModuleInit(_ATL_MODULE* pM, _ATL_OBJMAP_ENTRY* p, HINSTANCE h)
  2580. {
  2581.     _ASSERTE(pM != NULL);
  2582.     if (pM == NULL)
  2583.         return E_INVALIDARG;
  2584.     if (pM->cbSize < sizeof(_ATL_MODULE))
  2585.         return E_INVALIDARG;
  2586.     pM->m_pObjMap = p;
  2587.     pM->m_hInst = pM->m_hInstTypeLib = pM->m_hInstResource = h;
  2588.     pM->m_nLockCnt=0L;
  2589.     pM->m_hHeap = NULL;
  2590.     InitializeCriticalSection(&pM->m_csTypeInfoHolder);
  2591.     InitializeCriticalSection(&pM->m_csWindowCreate);
  2592.     InitializeCriticalSection(&pM->m_csObjMap);
  2593.     return S_OK;
  2594. }
  2595.  
  2596. ATLAPI AtlModuleRegisterClassObjects(_ATL_MODULE* pM, DWORD dwClsContext, DWORD dwFlags)
  2597. {
  2598.     _ASSERTE(pM != NULL);
  2599.     if (pM == NULL)
  2600.         return E_INVALIDARG;
  2601.     _ASSERTE(pM->m_pObjMap != NULL);
  2602.     _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2603.     HRESULT hRes = S_OK;
  2604.     while (pEntry->pclsid != NULL && hRes == S_OK)
  2605.     {
  2606.         hRes = pEntry->RegisterClassObject(dwClsContext, dwFlags);
  2607.         pEntry++;
  2608.     }
  2609.     return hRes;
  2610. }
  2611.  
  2612. ATLAPI AtlModuleRevokeClassObjects(_ATL_MODULE* pM)
  2613. {
  2614.     _ASSERTE(pM != NULL);
  2615.     if (pM == NULL)
  2616.         return E_INVALIDARG;
  2617.     _ASSERTE(pM->m_pObjMap != NULL);
  2618.     _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2619.     HRESULT hRes = S_OK;
  2620.     while (pEntry->pclsid != NULL && hRes == S_OK)
  2621.     {
  2622.         hRes = pEntry->RevokeClassObject();
  2623.         pEntry++;
  2624.     }
  2625.     return hRes;
  2626. }
  2627.  
  2628. ATLAPI AtlModuleGetClassObject(_ATL_MODULE* pM, REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  2629. {
  2630.     _ASSERTE(pM != NULL);
  2631.     if (pM == NULL)
  2632.         return E_INVALIDARG;
  2633.     _ASSERTE(pM->m_pObjMap != NULL);
  2634.     _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2635.     HRESULT hRes = S_OK;
  2636.     if (ppv == NULL)
  2637.         return E_POINTER;
  2638.     while (pEntry->pclsid != NULL)
  2639.     {
  2640.         if (InlineIsEqualGUID(rclsid, *pEntry->pclsid))
  2641.         {
  2642.             if (pEntry->pCF == NULL)
  2643.             {
  2644.                 EnterCriticalSection(&pM->m_csObjMap);
  2645.                 if (pEntry->pCF == NULL)
  2646.                     hRes = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, IID_IUnknown, (LPVOID*)&pEntry->pCF);
  2647.                 LeaveCriticalSection(&pM->m_csObjMap);
  2648.             }
  2649.             if (pEntry->pCF != NULL)
  2650.                 hRes = pEntry->pCF->QueryInterface(riid, ppv);
  2651.             break;
  2652.         }
  2653.         pEntry++;
  2654.     }
  2655.     if (*ppv == NULL && hRes == S_OK)
  2656.         hRes = CLASS_E_CLASSNOTAVAILABLE;
  2657.     return hRes;
  2658. }
  2659.  
  2660. ATLAPI AtlModuleTerm(_ATL_MODULE* pM)
  2661. {
  2662.     _ASSERTE(pM != NULL);
  2663.     if (pM == NULL)
  2664.         return E_INVALIDARG;
  2665.     _ASSERTE(pM->m_hInst != NULL);
  2666.     if (pM->m_pObjMap != NULL)
  2667.     {
  2668.         _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2669.         while (pEntry->pclsid != NULL)
  2670.         {
  2671.             if (pEntry->pCF != NULL)
  2672.                 pEntry->pCF->Release();
  2673.             pEntry->pCF = NULL;
  2674.             pEntry++;
  2675.         }
  2676.     }
  2677.     DeleteCriticalSection(&pM->m_csTypeInfoHolder);
  2678.     DeleteCriticalSection(&pM->m_csWindowCreate);
  2679.     DeleteCriticalSection(&pM->m_csObjMap);
  2680.     if (pM->m_hHeap != NULL)
  2681.         HeapDestroy(pM->m_hHeap);
  2682.     return S_OK;
  2683. }
  2684.  
  2685. ATLAPI AtlModuleRegisterServer(_ATL_MODULE* pM, BOOL bRegTypeLib, const CLSID* pCLSID)
  2686. {
  2687.     _ASSERTE(pM != NULL);
  2688.     if (pM == NULL)
  2689.         return E_INVALIDARG;
  2690.     _ASSERTE(pM->m_hInst != NULL);
  2691.     _ASSERTE(pM->m_pObjMap != NULL);
  2692.     _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2693.     HRESULT hRes = S_OK;
  2694.     for (;pEntry->pclsid != NULL; pEntry++)
  2695.     {
  2696.         if (pCLSID == NULL)
  2697.         {
  2698.             if (pEntry->pfnGetObjectDescription() != NULL)
  2699.                 continue;
  2700.         }
  2701.         else
  2702.         {
  2703.             if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
  2704.                 continue;
  2705.         }
  2706.         hRes = pEntry->pfnUpdateRegistry(TRUE);
  2707.         if (FAILED(hRes))
  2708.             break;
  2709.     }
  2710.     if (SUCCEEDED(hRes) && bRegTypeLib)
  2711.         hRes = AtlModuleRegisterTypeLib(pM, 0);
  2712.     return hRes;
  2713. }
  2714.  
  2715. ATLAPI AtlModuleUnregisterServer(_ATL_MODULE* pM, const CLSID* pCLSID)
  2716. {
  2717.     _ASSERTE(pM != NULL);
  2718.     if (pM == NULL)
  2719.         return E_INVALIDARG;
  2720.     _ASSERTE(pM->m_hInst != NULL);
  2721.     _ASSERTE(pM->m_pObjMap != NULL);
  2722.     _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2723.     for (;pEntry->pclsid != NULL; pEntry++)
  2724.     {
  2725.         if (pCLSID == NULL)
  2726.         {
  2727.             if (pEntry->pfnGetObjectDescription() != NULL)
  2728.                 continue;
  2729.         }
  2730.         else
  2731.         {
  2732.             if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
  2733.                 continue;
  2734.         }
  2735.         pEntry->pfnUpdateRegistry(FALSE); //unregister
  2736.     }
  2737.     return S_OK;
  2738. }
  2739.  
  2740. ATLAPI AtlModuleUpdateRegistryFromResourceD(_ATL_MODULE* pM, LPCOLESTR lpszRes,
  2741.     BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg)
  2742. {
  2743.     USES_CONVERSION;
  2744.     _ASSERTE(pM != NULL);
  2745.     HRESULT hRes = S_OK;
  2746.     CComPtr<IRegistrar> p;
  2747.     if (pReg != NULL)
  2748.         p = pReg;
  2749.     else
  2750.     {
  2751.         hRes = CoCreateInstance(CLSID_Registrar, NULL,
  2752.             CLSCTX_INPROC_SERVER, IID_IRegistrar, (void**)&p);
  2753.     }
  2754.     if (SUCCEEDED(hRes))
  2755.     {
  2756.         TCHAR szModule[_MAX_PATH];
  2757.         GetModuleFileName(pM->m_hInst, szModule, _MAX_PATH);
  2758.         p->AddReplacement(OLESTR("Module"), T2OLE(szModule));
  2759.  
  2760.         if (NULL != pMapEntries)
  2761.         {
  2762.             while (NULL != pMapEntries->szKey)
  2763.             {
  2764.                 _ASSERTE(NULL != pMapEntries->szData);
  2765.                 p->AddReplacement((LPOLESTR)pMapEntries->szKey, (LPOLESTR)pMapEntries->szData);
  2766.                 pMapEntries++;
  2767.             }
  2768.         }
  2769.         LPCOLESTR szType = OLESTR("REGISTRY");
  2770.         GetModuleFileName(pM->m_hInstResource, szModule, _MAX_PATH);
  2771.         LPOLESTR pszModule = T2OLE(szModule);
  2772.         if (HIWORD(lpszRes)==0)
  2773.         {
  2774.             if (bRegister)
  2775.                 hRes = p->ResourceRegister(pszModule, ((UINT)LOWORD((DWORD)lpszRes)), szType);
  2776.             else
  2777.                 hRes = p->ResourceUnregister(pszModule, ((UINT)LOWORD((DWORD)lpszRes)), szType);
  2778.         }
  2779.         else
  2780.         {
  2781.             if (bRegister)
  2782.                 hRes = p->ResourceRegisterSz(pszModule, lpszRes, szType);
  2783.             else
  2784.                 hRes = p->ResourceUnregisterSz(pszModule, lpszRes, szType);
  2785.         }
  2786.  
  2787.     }
  2788.     return hRes;
  2789. }
  2790.  
  2791. /////////////////////////////////////////////////////////////////////////////
  2792. // TypeLib Support
  2793.  
  2794. ATLAPI AtlModuleRegisterTypeLib(_ATL_MODULE* pM, LPCOLESTR lpszIndex)
  2795. {
  2796.     _ASSERTE(pM != NULL);
  2797.     USES_CONVERSION;
  2798.     _ASSERTE(pM->m_hInstTypeLib != NULL);
  2799.     TCHAR szModule[_MAX_PATH+10];
  2800.     OLECHAR szDir[_MAX_PATH];
  2801.     GetModuleFileName(pM->m_hInstTypeLib, szModule, _MAX_PATH);
  2802.     if (lpszIndex != NULL)
  2803.         lstrcat(szModule, OLE2CT(lpszIndex));
  2804.     ITypeLib* pTypeLib;
  2805.     LPOLESTR lpszModule = T2OLE(szModule);
  2806.     HRESULT hr = LoadTypeLib(lpszModule, &pTypeLib);
  2807.     if (!SUCCEEDED(hr))
  2808.     {
  2809.         // typelib not in module, try <module>.tlb instead
  2810.         LPTSTR lpszExt = NULL;
  2811.         LPTSTR lpsz;
  2812.         for (lpsz = szModule; *lpsz != NULL; lpsz = CharNext(lpsz))
  2813.         {
  2814.             if (*lpsz == _T('.'))
  2815.                 lpszExt = lpsz;
  2816.         }
  2817.         if (lpszExt == NULL)
  2818.             lpszExt = lpsz;
  2819.         lstrcpy(lpszExt, _T(".tlb"));
  2820.         lpszModule = T2OLE(szModule);
  2821.         hr = LoadTypeLib(lpszModule, &pTypeLib);
  2822.     }
  2823.     if (SUCCEEDED(hr))
  2824.     {
  2825.         ocscpy(szDir, lpszModule);
  2826.         szDir[AtlGetDirLen(szDir)] = 0;
  2827.         hr = ::RegisterTypeLib(pTypeLib, lpszModule, szDir);
  2828.     }
  2829.     if (pTypeLib != NULL)
  2830.         pTypeLib->Release();
  2831.     return hr;
  2832. }
  2833.  
  2834. #ifndef ATL_NO_NAMESPACE
  2835. #ifndef _ATL_DLL_IMPL
  2836. }; //namespace ATL
  2837. #endif
  2838. #endif
  2839.  
  2840. #endif //!_ATL_DLL
  2841.