Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2846 lines
64 KiB

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