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.

2857 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 DECLSPEC_SELECTANY IID IID_IRegistrar = {0x44EC053B,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}};
  14. #ifndef _ATL_DLL_IMPL
  15. extern "C" const DECLSPEC_SELECTANY 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. DECLSPEC_SELECTANY UINT CComApartment::ATL_CREATE_OBJECT = 0;
  28. #if _MSC_VER < 1200
  29. #pragma comment(linker, "/merge:.CRT=.data")
  30. #endif
  31. #ifdef __ATLCOM_H__
  32. /////////////////////////////////////////////////////////////////////////////
  33. // AtlReportError
  34. HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, const IID& iid,
  35. HRESULT hRes, HINSTANCE hInst)
  36. {
  37. return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), 0, NULL, iid, hRes, hInst);
  38. }
  39. HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, DWORD dwHelpID,
  40. LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst)
  41. {
  42. return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), dwHelpID,
  43. lpszHelpFile, iid, hRes, hInst);
  44. }
  45. #ifndef OLE2ANSI
  46. HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc,
  47. DWORD dwHelpID, LPCSTR lpszHelpFile, const IID& iid, HRESULT hRes)
  48. {
  49. _ASSERTE(lpszDesc != NULL);
  50. USES_CONVERSION;
  51. return AtlSetErrorInfo(clsid, A2COLE(lpszDesc), dwHelpID, A2CW(lpszHelpFile),
  52. iid, hRes, NULL);
  53. }
  54. HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc,
  55. const IID& iid, HRESULT hRes)
  56. {
  57. _ASSERTE(lpszDesc != NULL);
  58. USES_CONVERSION;
  59. return AtlSetErrorInfo(clsid, A2COLE(lpszDesc), 0, NULL, iid, hRes, NULL);
  60. }
  61. #endif
  62. HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc,
  63. const IID& iid, HRESULT hRes)
  64. {
  65. return AtlSetErrorInfo(clsid, lpszDesc, 0, NULL, iid, hRes, NULL);
  66. }
  67. HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
  68. LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes)
  69. {
  70. return AtlSetErrorInfo(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes, NULL);
  71. }
  72. #endif //__ATLCOM_H__
  73. /////////////////////////////////////////////////////////////////////////////
  74. // CComBSTR
  75. CComBSTR& CComBSTR::operator=(const CComBSTR& src)
  76. {
  77. if (m_str != src.m_str)
  78. {
  79. if (m_str)
  80. ::SysFreeString(m_str);
  81. m_str = src.Copy();
  82. }
  83. return *this;
  84. }
  85. CComBSTR& CComBSTR::operator=(LPCOLESTR pSrc)
  86. {
  87. ::SysFreeString(m_str);
  88. m_str = ::SysAllocString(pSrc);
  89. return *this;
  90. }
  91. void CComBSTR::Append(LPCOLESTR lpsz, int nLen)
  92. {
  93. int n1 = Length();
  94. BSTR b = SysAllocStringLen(NULL, n1+nLen);
  95. memcpy(b, m_str, n1*sizeof(OLECHAR));
  96. memcpy(b+n1, lpsz, nLen*sizeof(OLECHAR));
  97. b[n1+nLen] = NULL;
  98. SysFreeString(m_str);
  99. m_str = b;
  100. }
  101. #ifndef OLE2ANSI
  102. void CComBSTR::Append(LPCSTR lpsz)
  103. {
  104. USES_CONVERSION;
  105. LPCOLESTR lpo = A2COLE(lpsz);
  106. Append(lpo, (int) ocslen(lpo));
  107. }
  108. CComBSTR::CComBSTR(LPCSTR pSrc)
  109. {
  110. USES_CONVERSION;
  111. m_str = ::SysAllocString(A2COLE(pSrc));
  112. }
  113. CComBSTR::CComBSTR(int nSize, LPCSTR sz)
  114. {
  115. USES_CONVERSION;
  116. m_str = ::SysAllocStringLen(A2COLE(sz), nSize);
  117. }
  118. CComBSTR& CComBSTR::operator=(LPCSTR pSrc)
  119. {
  120. USES_CONVERSION;
  121. ::SysFreeString(m_str);
  122. m_str = ::SysAllocString(A2COLE(pSrc));
  123. return *this;
  124. }
  125. #endif
  126. HRESULT CComBSTR::ReadFromStream(IStream* pStream)
  127. {
  128. _ASSERTE(pStream != NULL);
  129. _ASSERTE(m_str == NULL); // should be empty
  130. ULONG cb;
  131. ULONG cbStrLen;
  132. HRESULT hr = pStream->Read((void*) &cbStrLen, sizeof(cbStrLen), &cb);
  133. if (FAILED(hr))
  134. return hr;
  135. if (cbStrLen != 0)
  136. {
  137. //subtract size for terminating NULL which we wrote out
  138. //since SysAllocStringByteLen overallocates for the NULL
  139. m_str = SysAllocStringByteLen(NULL, cbStrLen-sizeof(OLECHAR));
  140. if (m_str == NULL)
  141. hr = E_OUTOFMEMORY;
  142. else
  143. hr = pStream->Read((void*) m_str, cbStrLen, &cb);
  144. }
  145. return hr;
  146. }
  147. HRESULT CComBSTR::WriteToStream(IStream* pStream)
  148. {
  149. _ASSERTE(pStream != NULL);
  150. ULONG cb;
  151. ULONG cbStrLen = (ULONG)(m_str ? SysStringByteLen(m_str)+sizeof(OLECHAR) : 0);
  152. HRESULT hr = pStream->Write((void*) &cbStrLen, sizeof(cbStrLen), &cb);
  153. if (FAILED(hr))
  154. return hr;
  155. return cbStrLen ? pStream->Write((void*) m_str, cbStrLen, &cb) : S_OK;
  156. }
  157. /////////////////////////////////////////////////////////////////////////////
  158. // CComVariant
  159. CComVariant& CComVariant::operator=(BSTR bstrSrc)
  160. {
  161. InternalClear();
  162. vt = VT_BSTR;
  163. bstrVal = ::SysAllocString(bstrSrc);
  164. if (bstrVal == NULL && bstrSrc != NULL)
  165. {
  166. vt = VT_ERROR;
  167. scode = E_OUTOFMEMORY;
  168. }
  169. return *this;
  170. }
  171. CComVariant& CComVariant::operator=(LPCOLESTR lpszSrc)
  172. {
  173. InternalClear();
  174. vt = VT_BSTR;
  175. bstrVal = ::SysAllocString(lpszSrc);
  176. if (bstrVal == NULL && lpszSrc != NULL)
  177. {
  178. vt = VT_ERROR;
  179. scode = E_OUTOFMEMORY;
  180. }
  181. return *this;
  182. }
  183. #ifndef OLE2ANSI
  184. CComVariant& CComVariant::operator=(LPCSTR lpszSrc)
  185. {
  186. USES_CONVERSION;
  187. InternalClear();
  188. vt = VT_BSTR;
  189. bstrVal = ::SysAllocString(A2COLE(lpszSrc));
  190. if (bstrVal == NULL && lpszSrc != NULL)
  191. {
  192. vt = VT_ERROR;
  193. scode = E_OUTOFMEMORY;
  194. }
  195. return *this;
  196. }
  197. #endif
  198. #if _MSC_VER>1020
  199. CComVariant& CComVariant::operator=(bool bSrc)
  200. {
  201. if (vt != VT_BOOL)
  202. {
  203. InternalClear();
  204. vt = VT_BOOL;
  205. }
  206. #pragma warning(disable: 4310) // cast truncates constant value
  207. boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
  208. #pragma warning(default: 4310) // cast truncates constant value
  209. return *this;
  210. }
  211. #endif
  212. CComVariant& CComVariant::operator=(int nSrc)
  213. {
  214. if (vt != VT_I4)
  215. {
  216. InternalClear();
  217. vt = VT_I4;
  218. }
  219. lVal = nSrc;
  220. return *this;
  221. }
  222. CComVariant& CComVariant::operator=(BYTE nSrc)
  223. {
  224. if (vt != VT_UI1)
  225. {
  226. InternalClear();
  227. vt = VT_UI1;
  228. }
  229. bVal = nSrc;
  230. return *this;
  231. }
  232. CComVariant& CComVariant::operator=(short nSrc)
  233. {
  234. if (vt != VT_I2)
  235. {
  236. InternalClear();
  237. vt = VT_I2;
  238. }
  239. iVal = nSrc;
  240. return *this;
  241. }
  242. CComVariant& CComVariant::operator=(long nSrc)
  243. {
  244. if (vt != VT_I4)
  245. {
  246. InternalClear();
  247. vt = VT_I4;
  248. }
  249. lVal = nSrc;
  250. return *this;
  251. }
  252. CComVariant& CComVariant::operator=(float fltSrc)
  253. {
  254. if (vt != VT_R4)
  255. {
  256. InternalClear();
  257. vt = VT_R4;
  258. }
  259. fltVal = fltSrc;
  260. return *this;
  261. }
  262. CComVariant& CComVariant::operator=(double dblSrc)
  263. {
  264. if (vt != VT_R8)
  265. {
  266. InternalClear();
  267. vt = VT_R8;
  268. }
  269. dblVal = dblSrc;
  270. return *this;
  271. }
  272. CComVariant& CComVariant::operator=(CY cySrc)
  273. {
  274. if (vt != VT_CY)
  275. {
  276. InternalClear();
  277. vt = VT_CY;
  278. }
  279. cyVal.Hi = cySrc.Hi;
  280. cyVal.Lo = cySrc.Lo;
  281. return *this;
  282. }
  283. CComVariant& CComVariant::operator=(IDispatch* pSrc)
  284. {
  285. InternalClear();
  286. vt = VT_DISPATCH;
  287. pdispVal = pSrc;
  288. // Need to AddRef as VariantClear will Release
  289. if (pdispVal != NULL)
  290. pdispVal->AddRef();
  291. return *this;
  292. }
  293. CComVariant& CComVariant::operator=(IUnknown* pSrc)
  294. {
  295. InternalClear();
  296. vt = VT_UNKNOWN;
  297. punkVal = pSrc;
  298. // Need to AddRef as VariantClear will Release
  299. if (punkVal != NULL)
  300. punkVal->AddRef();
  301. return *this;
  302. }
  303. #if _MSC_VER>1020
  304. bool CComVariant::operator==(const VARIANT& varSrc)
  305. {
  306. if (this == &varSrc)
  307. return true;
  308. // Variants not equal if types don't match
  309. if (vt != varSrc.vt)
  310. return false;
  311. // Check type specific values
  312. switch (vt)
  313. {
  314. case VT_EMPTY:
  315. case VT_NULL:
  316. return true;
  317. case VT_BOOL:
  318. return boolVal == varSrc.boolVal;
  319. case VT_UI1:
  320. return bVal == varSrc.bVal;
  321. case VT_I2:
  322. return iVal == varSrc.iVal;
  323. case VT_I4:
  324. return lVal == varSrc.lVal;
  325. case VT_R4:
  326. return fltVal == varSrc.fltVal;
  327. case VT_R8:
  328. return dblVal == varSrc.dblVal;
  329. case VT_BSTR:
  330. return (::SysStringByteLen(bstrVal) == ::SysStringByteLen(varSrc.bstrVal)) &&
  331. (::memcmp(bstrVal, varSrc.bstrVal, ::SysStringByteLen(bstrVal)) == 0);
  332. case VT_ERROR:
  333. return scode == varSrc.scode;
  334. case VT_DISPATCH:
  335. return pdispVal == varSrc.pdispVal;
  336. case VT_UNKNOWN:
  337. return punkVal == varSrc.punkVal;
  338. default:
  339. _ASSERTE(false);
  340. // fall through
  341. }
  342. return false;
  343. }
  344. #else
  345. BOOL CComVariant::operator==(const VARIANT& varSrc)
  346. {
  347. if (this == &varSrc)
  348. return TRUE;
  349. // Variants not equal if types don't match
  350. if (vt != varSrc.vt)
  351. return FALSE;
  352. // Check type specific values
  353. switch (vt)
  354. {
  355. case VT_EMPTY:
  356. case VT_NULL:
  357. return TRUE;
  358. case VT_BOOL:
  359. return boolVal == varSrc.boolVal;
  360. case VT_UI1:
  361. return bVal == varSrc.bVal;
  362. case VT_I2:
  363. return iVal == varSrc.iVal;
  364. case VT_I4:
  365. return lVal == varSrc.lVal;
  366. case VT_R4:
  367. return fltVal == varSrc.fltVal;
  368. case VT_R8:
  369. return dblVal == varSrc.dblVal;
  370. case VT_BSTR:
  371. return (::SysStringByteLen(bstrVal) == ::SysStringByteLen(varSrc.bstrVal)) &&
  372. (::memcmp(bstrVal, varSrc.bstrVal, ::SysStringByteLen(bstrVal)) == 0);
  373. case VT_ERROR:
  374. return scode == varSrc.scode;
  375. case VT_DISPATCH:
  376. return pdispVal == varSrc.pdispVal;
  377. case VT_UNKNOWN:
  378. return punkVal == varSrc.punkVal;
  379. default:
  380. _ASSERTE(FALSE);
  381. // fall through
  382. }
  383. return FALSE;
  384. }
  385. #endif
  386. HRESULT CComVariant::Attach(VARIANT* pSrc)
  387. {
  388. // Clear out the variant
  389. HRESULT hr = Clear();
  390. if (!FAILED(hr))
  391. {
  392. // Copy the contents and give control to CComVariant
  393. memcpy(this, pSrc, sizeof(VARIANT));
  394. VariantInit(pSrc);
  395. hr = S_OK;
  396. }
  397. return hr;
  398. }
  399. HRESULT CComVariant::Detach(VARIANT* pDest)
  400. {
  401. // Clear out the variant
  402. HRESULT hr = ::VariantClear(pDest);
  403. if (!FAILED(hr))
  404. {
  405. // Copy the contents and remove control from CComVariant
  406. memcpy(pDest, this, sizeof(VARIANT));
  407. vt = VT_EMPTY;
  408. hr = S_OK;
  409. }
  410. return hr;
  411. }
  412. HRESULT CComVariant::ChangeType(VARTYPE vtNew, const VARIANT* pSrc)
  413. {
  414. VARIANT* pVar = const_cast<VARIANT*>(pSrc);
  415. // Convert in place if pSrc is NULL
  416. if (pVar == NULL)
  417. pVar = this;
  418. // Do nothing if doing in place convert and vts not different
  419. return ::VariantChangeType(this, pVar, 0, vtNew);
  420. }
  421. HRESULT CComVariant::InternalClear()
  422. {
  423. HRESULT hr = Clear();
  424. _ASSERTE(SUCCEEDED(hr));
  425. if (FAILED(hr))
  426. {
  427. vt = VT_ERROR;
  428. scode = hr;
  429. }
  430. return hr;
  431. }
  432. void CComVariant::InternalCopy(const VARIANT* pSrc)
  433. {
  434. HRESULT hr = Copy(pSrc);
  435. if (FAILED(hr))
  436. {
  437. vt = VT_ERROR;
  438. scode = hr;
  439. }
  440. }
  441. HRESULT CComVariant::WriteToStream(IStream* pStream)
  442. {
  443. HRESULT hr = pStream->Write(&vt, sizeof(VARTYPE), NULL);
  444. if (FAILED(hr))
  445. return hr;
  446. int cbWrite = 0;
  447. switch (vt)
  448. {
  449. case VT_UNKNOWN:
  450. case VT_DISPATCH:
  451. {
  452. CComPtr<IPersistStream> spStream;
  453. if (punkVal != NULL)
  454. {
  455. hr = punkVal->QueryInterface(IID_IPersistStream, (void**)&spStream);
  456. if (FAILED(hr))
  457. return hr;
  458. }
  459. if (spStream != NULL)
  460. return OleSaveToStream(spStream, pStream);
  461. else
  462. return WriteClassStm(pStream, CLSID_NULL);
  463. }
  464. case VT_UI1:
  465. case VT_I1:
  466. cbWrite = sizeof(BYTE);
  467. break;
  468. case VT_I2:
  469. case VT_UI2:
  470. case VT_BOOL:
  471. cbWrite = sizeof(short);
  472. break;
  473. case VT_I4:
  474. case VT_UI4:
  475. case VT_R4:
  476. case VT_INT:
  477. case VT_UINT:
  478. case VT_ERROR:
  479. cbWrite = sizeof(long);
  480. break;
  481. case VT_R8:
  482. case VT_CY:
  483. case VT_DATE:
  484. cbWrite = sizeof(double);
  485. break;
  486. default:
  487. break;
  488. }
  489. if (cbWrite != 0)
  490. return pStream->Write((void*) &bVal, cbWrite, NULL);
  491. CComBSTR bstrWrite;
  492. CComVariant varBSTR;
  493. if (vt != VT_BSTR)
  494. {
  495. hr = VariantChangeType(&varBSTR, this, VARIANT_NOVALUEPROP, VT_BSTR);
  496. if (FAILED(hr))
  497. return hr;
  498. bstrWrite = varBSTR.bstrVal;
  499. }
  500. else
  501. bstrWrite = bstrVal;
  502. return bstrWrite.WriteToStream(pStream);
  503. }
  504. HRESULT CComVariant::ReadFromStream(IStream* pStream)
  505. {
  506. _ASSERTE(pStream != NULL);
  507. HRESULT hr;
  508. hr = VariantClear(this);
  509. if (FAILED(hr))
  510. return hr;
  511. VARTYPE vtRead;
  512. hr = pStream->Read(&vtRead, sizeof(VARTYPE), NULL);
  513. if (FAILED(hr))
  514. return hr;
  515. vt = vtRead;
  516. int cbRead = 0;
  517. switch (vtRead)
  518. {
  519. case VT_UNKNOWN:
  520. case VT_DISPATCH:
  521. {
  522. punkVal = NULL;
  523. hr = OleLoadFromStream(pStream,
  524. (vtRead == VT_UNKNOWN) ? IID_IUnknown : IID_IDispatch,
  525. (void**)&punkVal);
  526. if (hr == REGDB_E_CLASSNOTREG)
  527. hr = S_OK;
  528. return S_OK;
  529. }
  530. case VT_UI1:
  531. case VT_I1:
  532. cbRead = sizeof(BYTE);
  533. break;
  534. case VT_I2:
  535. case VT_UI2:
  536. case VT_BOOL:
  537. cbRead = sizeof(short);
  538. break;
  539. case VT_I4:
  540. case VT_UI4:
  541. case VT_R4:
  542. case VT_INT:
  543. case VT_UINT:
  544. case VT_ERROR:
  545. cbRead = sizeof(long);
  546. break;
  547. case VT_R8:
  548. case VT_CY:
  549. case VT_DATE:
  550. cbRead = sizeof(double);
  551. break;
  552. default:
  553. break;
  554. }
  555. if (cbRead != 0)
  556. return pStream->Read((void*) &bVal, cbRead, NULL);
  557. CComBSTR bstrRead;
  558. hr = bstrRead.ReadFromStream(pStream);
  559. if (FAILED(hr))
  560. return hr;
  561. vt = VT_BSTR;
  562. bstrVal = bstrRead.Detach();
  563. if (vtRead != VT_BSTR)
  564. hr = ChangeType(vtRead);
  565. return hr;
  566. }
  567. #ifdef __ATLCOM_H__
  568. /////////////////////////////////////////////////////////////////////////////
  569. // CComTypeInfoHolder
  570. void CComTypeInfoHolder::AddRef()
  571. {
  572. EnterCriticalSection(&_Module.m_csTypeInfoHolder);
  573. m_dwRef++;
  574. LeaveCriticalSection(&_Module.m_csTypeInfoHolder);
  575. }
  576. void CComTypeInfoHolder::Release()
  577. {
  578. EnterCriticalSection(&_Module.m_csTypeInfoHolder);
  579. if (--m_dwRef == 0)
  580. {
  581. if (m_pInfo != NULL)
  582. m_pInfo->Release();
  583. m_pInfo = NULL;
  584. }
  585. LeaveCriticalSection(&_Module.m_csTypeInfoHolder);
  586. }
  587. HRESULT CComTypeInfoHolder::GetTI(LCID lcid, ITypeInfo** ppInfo)
  588. {
  589. //If this assert occurs then most likely didn't initialize properly
  590. _ASSERTE(m_plibid != NULL && m_pguid != NULL);
  591. _ASSERTE(ppInfo != NULL);
  592. *ppInfo = NULL;
  593. HRESULT hRes = E_FAIL;
  594. EnterCriticalSection(&_Module.m_csTypeInfoHolder);
  595. if (m_pInfo == NULL)
  596. {
  597. ITypeLib* pTypeLib;
  598. hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib);
  599. if (SUCCEEDED(hRes))
  600. {
  601. ITypeInfo* pTypeInfo;
  602. hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &pTypeInfo);
  603. if (SUCCEEDED(hRes))
  604. m_pInfo = pTypeInfo;
  605. pTypeLib->Release();
  606. }
  607. }
  608. *ppInfo = m_pInfo;
  609. if (m_pInfo != NULL)
  610. {
  611. m_pInfo->AddRef();
  612. hRes = S_OK;
  613. }
  614. LeaveCriticalSection(&_Module.m_csTypeInfoHolder);
  615. return hRes;
  616. }
  617. HRESULT CComTypeInfoHolder::GetTypeInfo(UINT /*itinfo*/, LCID lcid,
  618. ITypeInfo** pptinfo)
  619. {
  620. HRESULT hRes = E_POINTER;
  621. if (pptinfo != NULL)
  622. hRes = GetTI(lcid, pptinfo);
  623. return hRes;
  624. }
  625. HRESULT CComTypeInfoHolder::GetIDsOfNames(REFIID /*riid*/, LPOLESTR* rgszNames,
  626. UINT cNames, LCID lcid, DISPID* rgdispid)
  627. {
  628. ITypeInfo* pInfo;
  629. HRESULT hRes = GetTI(lcid, &pInfo);
  630. if (pInfo != NULL)
  631. {
  632. hRes = pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
  633. pInfo->Release();
  634. }
  635. return hRes;
  636. }
  637. HRESULT CComTypeInfoHolder::Invoke(IDispatch* p, DISPID dispidMember, REFIID /*riid*/,
  638. LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
  639. EXCEPINFO* pexcepinfo, UINT* puArgErr)
  640. {
  641. SetErrorInfo(0, NULL);
  642. ITypeInfo* pInfo;
  643. HRESULT hRes = GetTI(lcid, &pInfo);
  644. if (pInfo != NULL)
  645. {
  646. hRes = pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  647. pInfo->Release();
  648. }
  649. return hRes;
  650. }
  651. /////////////////////////////////////////////////////////////////////////////
  652. // QI implementation
  653. #ifdef _ATL_DEBUG_QI
  654. HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr)
  655. {
  656. USES_CONVERSION;
  657. CRegKey key;
  658. TCHAR szName[100];
  659. DWORD dwType,dw = sizeof(szName);
  660. LPOLESTR pszGUID = NULL;
  661. StringFromCLSID(iid, &pszGUID);
  662. OutputDebugString(pszClassName);
  663. OutputDebugString(_T(" - "));
  664. // Attempt to find it in the interfaces section
  665. key.Open(HKEY_CLASSES_ROOT, _T("Interface"));
  666. if (key.Open(key, OLE2T(pszGUID)) == S_OK)
  667. {
  668. *szName = 0;
  669. RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw);
  670. OutputDebugString(szName);
  671. goto cleanup;
  672. }
  673. // Attempt to find it in the clsid section
  674. key.Open(HKEY_CLASSES_ROOT, _T("CLSID"));
  675. if (key.Open(key, OLE2T(pszGUID)) == S_OK)
  676. {
  677. *szName = 0;
  678. RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw);
  679. OutputDebugString(_T("(CLSID\?\?\?) "));
  680. OutputDebugString(szName);
  681. goto cleanup;
  682. }
  683. OutputDebugString(OLE2T(pszGUID));
  684. cleanup:
  685. if (hr != S_OK)
  686. OutputDebugString(_T(" - failed"));
  687. OutputDebugString(_T("\n"));
  688. CoTaskMemFree(pszGUID);
  689. return hr;
  690. }
  691. #endif
  692. HRESULT WINAPI CComObjectRootBase::_Break(void* /* pv */, REFIID iid, void** /* ppvObject */, DWORD_PTR /* dw */)
  693. {
  694. iid;
  695. _ATLDUMPIID(iid, _T("Break due to QI for interface "), S_OK);
  696. DebugBreak();
  697. return S_FALSE;
  698. }
  699. HRESULT WINAPI CComObjectRootBase::_NoInterface(void* /* pv */, REFIID /* iid */, void** /* ppvObject */, DWORD_PTR /* dw */)
  700. {
  701. return E_NOINTERFACE;
  702. }
  703. HRESULT WINAPI CComObjectRootBase::_Creator(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  704. {
  705. _ATL_CREATORDATA* pcd = (_ATL_CREATORDATA*)dw;
  706. return pcd->pFunc(pv, iid, ppvObject);
  707. }
  708. HRESULT WINAPI CComObjectRootBase::_Delegate(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  709. {
  710. HRESULT hRes = E_NOINTERFACE;
  711. IUnknown* p = *(IUnknown**)((ULONG_PTR)pv + dw);
  712. if (p != NULL)
  713. hRes = p->QueryInterface(iid, ppvObject);
  714. return hRes;
  715. }
  716. HRESULT WINAPI CComObjectRootBase::_Chain(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  717. {
  718. _ATL_CHAINDATA* pcd = (_ATL_CHAINDATA*)dw;
  719. void* p = (void*)((ULONG_PTR)pv + pcd->dwOffset);
  720. return InternalQueryInterface(p, pcd->pFunc(), iid, ppvObject);
  721. }
  722. HRESULT WINAPI CComObjectRootBase::_Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  723. {
  724. HRESULT hRes = E_NOINTERFACE;
  725. _ATL_CACHEDATA* pcd = (_ATL_CACHEDATA*)dw;
  726. IUnknown** pp = (IUnknown**)((ULONG_PTR)pv + pcd->dwOffsetVar);
  727. if (*pp == NULL)
  728. hRes = pcd->pFunc(pv, IID_IUnknown, (void**)pp);
  729. if (*pp != NULL)
  730. hRes = (*pp)->QueryInterface(iid, ppvObject);
  731. return hRes;
  732. }
  733. /////////////////////////////////////////////////////////////////////////////
  734. // CComClassFactory
  735. STDMETHODIMP CComClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
  736. REFIID riid, void** ppvObj)
  737. {
  738. _ASSERTE(m_pfnCreateInstance != NULL);
  739. HRESULT hRes = E_POINTER;
  740. if (ppvObj != NULL)
  741. {
  742. *ppvObj = NULL;
  743. // can't ask for anything other than IUnknown when aggregating
  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] = {0};
  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] = {0};
  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. 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. free(pSid);
  1437. goto failed;
  1438. }
  1439. _ASSERTE(IsValidSid(pSid));
  1440. *ppUserSid = pSid;
  1441. free(ptkUser);
  1442. ptkUser = NULL;
  1443. }
  1444. if (ppGroupSid)
  1445. {
  1446. // Get length required for TokenPrimaryGroup by specifying buffer length of 0
  1447. GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize);
  1448. hr = GetLastError();
  1449. if (hr != ERROR_INSUFFICIENT_BUFFER)
  1450. {
  1451. // Expected ERROR_INSUFFICIENT_BUFFER
  1452. _ASSERTE(FALSE);
  1453. hr = HRESULT_FROM_WIN32(hr);
  1454. goto failed;
  1455. }
  1456. ptkGroup = (TOKEN_PRIMARY_GROUP*) malloc(dwSize);
  1457. if (!ptkGroup)
  1458. {
  1459. // Insufficient memory to allocate TOKEN_USER
  1460. _ASSERTE(FALSE);
  1461. hr = E_OUTOFMEMORY;
  1462. goto failed;
  1463. }
  1464. // Get Sid of process token.
  1465. if (!GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize))
  1466. {
  1467. // Couldn't get user info
  1468. hr = HRESULT_FROM_WIN32(GetLastError());
  1469. _ASSERTE(FALSE);
  1470. goto failed;
  1471. }
  1472. // Make a copy of the Sid for the return value
  1473. dwSize = GetLengthSid(ptkGroup->PrimaryGroup);
  1474. PSID pSid = (PSID) malloc(dwSize);
  1475. if (!pSid)
  1476. {
  1477. // Insufficient memory to allocate Sid
  1478. _ASSERTE(FALSE);
  1479. hr = E_OUTOFMEMORY;
  1480. goto failed;
  1481. }
  1482. if (!CopySid(dwSize, pSid, ptkGroup->PrimaryGroup))
  1483. {
  1484. hr = HRESULT_FROM_WIN32(GetLastError());
  1485. _ASSERTE(FALSE);
  1486. free(pSid);
  1487. goto failed;
  1488. }
  1489. _ASSERTE(IsValidSid(pSid));
  1490. *ppGroupSid = pSid;
  1491. free(ptkGroup);
  1492. }
  1493. return S_OK;
  1494. failed:
  1495. if (ptkUser)
  1496. free(ptkUser);
  1497. if (ptkGroup)
  1498. free (ptkGroup);
  1499. return hr;
  1500. }
  1501. HRESULT CSecurityDescriptor::GetCurrentUserSID(PSID *ppSid)
  1502. {
  1503. HANDLE tkHandle;
  1504. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle))
  1505. {
  1506. TOKEN_USER *tkUser;
  1507. DWORD tkSize;
  1508. DWORD sidLength;
  1509. // Call to get size information for alloc
  1510. GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize);
  1511. tkUser = (TOKEN_USER *) malloc(tkSize);
  1512. if (!tkUser) {
  1513. return E_OUTOFMEMORY;
  1514. }
  1515. // Now make the real call
  1516. if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize))
  1517. {
  1518. sidLength = GetLengthSid(tkUser->User.Sid);
  1519. *ppSid = (PSID) malloc(sidLength);
  1520. if (!ppSid) {
  1521. return E_OUTOFMEMORY;
  1522. }
  1523. memcpy(*ppSid, tkUser->User.Sid, sidLength);
  1524. CloseHandle(tkHandle);
  1525. free(tkUser);
  1526. return S_OK;
  1527. }
  1528. else
  1529. {
  1530. free(tkUser);
  1531. return HRESULT_FROM_WIN32(GetLastError());
  1532. }
  1533. }
  1534. return HRESULT_FROM_WIN32(GetLastError());
  1535. }
  1536. HRESULT CSecurityDescriptor::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid)
  1537. {
  1538. HRESULT hr;
  1539. LPTSTR pszRefDomain = NULL;
  1540. DWORD dwDomainSize = 0;
  1541. DWORD dwSidSize = 0;
  1542. SID_NAME_USE snu;
  1543. // Call to get size info for alloc
  1544. LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu);
  1545. hr = GetLastError();
  1546. if (hr != ERROR_INSUFFICIENT_BUFFER)
  1547. return HRESULT_FROM_WIN32(hr);
  1548. ATLTRY(pszRefDomain = new TCHAR[dwDomainSize]);
  1549. if (pszRefDomain == NULL)
  1550. return E_OUTOFMEMORY;
  1551. *ppSid = (PSID) malloc(dwSidSize);
  1552. if (*ppSid != NULL)
  1553. {
  1554. if (!LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu))
  1555. {
  1556. free(*ppSid);
  1557. *ppSid = NULL;
  1558. delete[] pszRefDomain;
  1559. return HRESULT_FROM_WIN32(GetLastError());
  1560. }
  1561. delete[] pszRefDomain;
  1562. return S_OK;
  1563. }
  1564. delete[] pszRefDomain;
  1565. return E_OUTOFMEMORY;
  1566. }
  1567. HRESULT CSecurityDescriptor::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD)
  1568. {
  1569. PACL pDACL = NULL;
  1570. PACL pSACL = NULL;
  1571. BOOL bDACLPresent, bSACLPresent;
  1572. BOOL bDefaulted;
  1573. PACL m_pDACL = NULL;
  1574. ACCESS_ALLOWED_ACE* pACE;
  1575. HRESULT hr;
  1576. PSID pUserSid;
  1577. PSID pGroupSid;
  1578. hr = Initialize();
  1579. if(FAILED(hr))
  1580. return hr;
  1581. // get the existing DACL.
  1582. if (!GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted))
  1583. goto failed;
  1584. if (bDACLPresent)
  1585. {
  1586. if (pDACL)
  1587. {
  1588. // allocate new DACL.
  1589. m_pDACL = (PACL) malloc(pDACL->AclSize);
  1590. if (!m_pDACL)
  1591. goto failed;
  1592. // initialize the DACL
  1593. if (!InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION))
  1594. goto failed;
  1595. // copy the ACES
  1596. for (int i = 0; i < pDACL->AceCount; i++)
  1597. {
  1598. if (!GetAce(pDACL, i, (void **)&pACE))
  1599. goto failed;
  1600. if (!AddAccessAllowedAce(m_pDACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
  1601. goto failed;
  1602. }
  1603. if (!IsValidAcl(m_pDACL))
  1604. goto failed;
  1605. }
  1606. // set the DACL
  1607. if (!SetSecurityDescriptorDacl(m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, bDefaulted))
  1608. goto failed;
  1609. }
  1610. // get the existing SACL.
  1611. if (!GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted))
  1612. goto failed;
  1613. if (bSACLPresent)
  1614. {
  1615. if (pSACL)
  1616. {
  1617. // allocate new SACL.
  1618. m_pSACL = (PACL) malloc(pSACL->AclSize);
  1619. if (!m_pSACL)
  1620. goto failed;
  1621. // initialize the SACL
  1622. if (!InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION))
  1623. goto failed;
  1624. // copy the ACES
  1625. for (int i = 0; i < pSACL->AceCount; i++)
  1626. {
  1627. if (!GetAce(pSACL, i, (void **)&pACE))
  1628. goto failed;
  1629. if (!AddAccessAllowedAce(m_pSACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
  1630. goto failed;
  1631. }
  1632. if (!IsValidAcl(m_pSACL))
  1633. goto failed;
  1634. }
  1635. // set the SACL
  1636. if (!SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, bDefaulted))
  1637. goto failed;
  1638. }
  1639. if (!GetSecurityDescriptorOwner(m_pSD, &pUserSid, &bDefaulted))
  1640. goto failed;
  1641. if (FAILED(SetOwner(pUserSid, bDefaulted)))
  1642. goto failed;
  1643. if (!GetSecurityDescriptorGroup(m_pSD, &pGroupSid, &bDefaulted))
  1644. goto failed;
  1645. if (FAILED(SetGroup(pGroupSid, bDefaulted)))
  1646. goto failed;
  1647. if (!IsValidSecurityDescriptor(m_pSD))
  1648. goto failed;
  1649. return hr;
  1650. failed:
  1651. if (m_pDACL)
  1652. free(m_pDACL);
  1653. if (m_pSD)
  1654. free(m_pSD);
  1655. return E_UNEXPECTED;
  1656. }
  1657. HRESULT CSecurityDescriptor::AttachObject(HANDLE hObject)
  1658. {
  1659. HRESULT hr;
  1660. DWORD dwSize = 0;
  1661. PSECURITY_DESCRIPTOR pSD = NULL;
  1662. GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  1663. DACL_SECURITY_INFORMATION, pSD, 0, &dwSize);
  1664. hr = GetLastError();
  1665. if (hr != ERROR_INSUFFICIENT_BUFFER)
  1666. return HRESULT_FROM_WIN32(hr);
  1667. pSD = (PSECURITY_DESCRIPTOR) malloc(dwSize);
  1668. if (!pSD) {
  1669. return E_OUTOFMEMORY;
  1670. }
  1671. if (!GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  1672. DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize))
  1673. {
  1674. hr = HRESULT_FROM_WIN32(GetLastError());
  1675. free(pSD);
  1676. return hr;
  1677. }
  1678. hr = Attach(pSD);
  1679. free(pSD);
  1680. return hr;
  1681. }
  1682. HRESULT CSecurityDescriptor::CopyACL(PACL pDest, PACL pSrc)
  1683. {
  1684. ACL_SIZE_INFORMATION aclSizeInfo;
  1685. LPVOID pAce;
  1686. ACE_HEADER *aceHeader;
  1687. if (pSrc == NULL)
  1688. return S_OK;
  1689. if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
  1690. return HRESULT_FROM_WIN32(GetLastError());
  1691. // Copy all of the ACEs to the new ACL
  1692. for (UINT i = 0; i < aclSizeInfo.AceCount; i++)
  1693. {
  1694. if (!GetAce(pSrc, i, &pAce))
  1695. return HRESULT_FROM_WIN32(GetLastError());
  1696. aceHeader = (ACE_HEADER *) pAce;
  1697. if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize))
  1698. return HRESULT_FROM_WIN32(GetLastError());
  1699. }
  1700. return S_OK;
  1701. }
  1702. HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1703. {
  1704. ACL_SIZE_INFORMATION aclSizeInfo;
  1705. int aclSize;
  1706. DWORD returnValue;
  1707. PSID principalSID;
  1708. PACL oldACL, newACL = NULL;
  1709. oldACL = *ppAcl;
  1710. returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  1711. if (FAILED(returnValue))
  1712. return returnValue;
  1713. aclSizeInfo.AclBytesInUse = 0;
  1714. if (*ppAcl != NULL)
  1715. GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  1716. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  1717. ATLTRY(newACL = (PACL) new BYTE[aclSize]);
  1718. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  1719. {
  1720. free(principalSID);
  1721. return HRESULT_FROM_WIN32(GetLastError());
  1722. }
  1723. if (!AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  1724. {
  1725. free(principalSID);
  1726. return HRESULT_FROM_WIN32(GetLastError());
  1727. }
  1728. returnValue = CopyACL(newACL, oldACL);
  1729. if (FAILED(returnValue))
  1730. {
  1731. free(principalSID);
  1732. return returnValue;
  1733. }
  1734. *ppAcl = newACL;
  1735. if (oldACL != NULL)
  1736. free(oldACL);
  1737. free(principalSID);
  1738. return S_OK;
  1739. }
  1740. HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1741. {
  1742. ACL_SIZE_INFORMATION aclSizeInfo;
  1743. int aclSize;
  1744. DWORD returnValue;
  1745. PSID principalSID;
  1746. PACL oldACL, newACL = NULL;
  1747. oldACL = *ppAcl;
  1748. returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  1749. if (FAILED(returnValue))
  1750. return returnValue;
  1751. aclSizeInfo.AclBytesInUse = 0;
  1752. if (*ppAcl != NULL)
  1753. GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  1754. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  1755. ATLTRY(newACL = (PACL) new BYTE[aclSize]);
  1756. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  1757. {
  1758. free(principalSID);
  1759. return HRESULT_FROM_WIN32(GetLastError());
  1760. }
  1761. returnValue = CopyACL(newACL, oldACL);
  1762. if (FAILED(returnValue))
  1763. {
  1764. free(principalSID);
  1765. return returnValue;
  1766. }
  1767. if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  1768. {
  1769. free(principalSID);
  1770. return HRESULT_FROM_WIN32(GetLastError());
  1771. }
  1772. *ppAcl = newACL;
  1773. if (oldACL != NULL)
  1774. free(oldACL);
  1775. free(principalSID);
  1776. return S_OK;
  1777. }
  1778. HRESULT CSecurityDescriptor::RemovePrincipalFromACL(PACL pAcl, LPCTSTR pszPrincipal)
  1779. {
  1780. ACL_SIZE_INFORMATION aclSizeInfo;
  1781. ULONG i;
  1782. LPVOID ace;
  1783. ACCESS_ALLOWED_ACE *accessAllowedAce;
  1784. ACCESS_DENIED_ACE *accessDeniedAce;
  1785. SYSTEM_AUDIT_ACE *systemAuditAce;
  1786. PSID principalSID;
  1787. DWORD returnValue;
  1788. ACE_HEADER *aceHeader;
  1789. returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  1790. if (FAILED(returnValue))
  1791. return returnValue;
  1792. GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  1793. for (i = 0; i < aclSizeInfo.AceCount; i++)
  1794. {
  1795. if (!GetAce(pAcl, i, &ace))
  1796. {
  1797. free(principalSID);
  1798. return HRESULT_FROM_WIN32(GetLastError());
  1799. }
  1800. aceHeader = (ACE_HEADER *) ace;
  1801. if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  1802. {
  1803. accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
  1804. if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart))
  1805. {
  1806. DeleteAce(pAcl, i);
  1807. free(principalSID);
  1808. return S_OK;
  1809. }
  1810. } else
  1811. if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  1812. {
  1813. accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
  1814. if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart))
  1815. {
  1816. DeleteAce(pAcl, i);
  1817. free(principalSID);
  1818. return S_OK;
  1819. }
  1820. } else
  1821. if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
  1822. {
  1823. systemAuditAce = (SYSTEM_AUDIT_ACE *) ace;
  1824. if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart))
  1825. {
  1826. DeleteAce(pAcl, i);
  1827. free(principalSID);
  1828. return S_OK;
  1829. }
  1830. }
  1831. }
  1832. free(principalSID);
  1833. return S_OK;
  1834. }
  1835. HRESULT CSecurityDescriptor::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken)
  1836. {
  1837. HRESULT hr;
  1838. TOKEN_PRIVILEGES tpPrevious;
  1839. TOKEN_PRIVILEGES tp;
  1840. DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
  1841. LUID luid;
  1842. // if no token specified open process token
  1843. if (hToken == 0)
  1844. {
  1845. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  1846. {
  1847. hr = HRESULT_FROM_WIN32(GetLastError());
  1848. _ASSERTE(FALSE);
  1849. return hr;
  1850. }
  1851. }
  1852. if (!LookupPrivilegeValue(NULL, privilege, &luid ))
  1853. {
  1854. hr = HRESULT_FROM_WIN32(GetLastError());
  1855. _ASSERTE(FALSE);
  1856. return hr;
  1857. }
  1858. tp.PrivilegeCount = 1;
  1859. tp.Privileges[0].Luid = luid;
  1860. tp.Privileges[0].Attributes = 0;
  1861. if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious))
  1862. {
  1863. hr = HRESULT_FROM_WIN32(GetLastError());
  1864. _ASSERTE(FALSE);
  1865. return hr;
  1866. }
  1867. tpPrevious.PrivilegeCount = 1;
  1868. tpPrevious.Privileges[0].Luid = luid;
  1869. if (bEnable)
  1870. tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
  1871. else
  1872. tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
  1873. if (!AdjustTokenPrivileges(hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL))
  1874. {
  1875. hr = HRESULT_FROM_WIN32(GetLastError());
  1876. _ASSERTE(FALSE);
  1877. return hr;
  1878. }
  1879. return S_OK;
  1880. }
  1881. #endif //_ATL_NO_SECURITY
  1882. #endif //__ATLCOM_H__
  1883. #ifdef _DEBUG
  1884. void _cdecl AtlTrace(LPCTSTR lpszFormat, ...)
  1885. {
  1886. va_list args;
  1887. va_start(args, lpszFormat);
  1888. int nBuf;
  1889. TCHAR szBuffer[512];
  1890. nBuf = _vstprintf(szBuffer, lpszFormat, args);
  1891. _ASSERTE(nBuf < sizeof(szBuffer));
  1892. OutputDebugString(szBuffer);
  1893. va_end(args);
  1894. }
  1895. #endif
  1896. #ifndef ATL_NO_NAMESPACE
  1897. }; //namespace ATL
  1898. #endif
  1899. ///////////////////////////////////////////////////////////////////////////////
  1900. //All Global stuff goes below this line
  1901. ///////////////////////////////////////////////////////////////////////////////
  1902. /////////////////////////////////////////////////////////////////////////////
  1903. // Minimize CRT
  1904. // Specify DllMain as EntryPoint
  1905. // Turn off exception handling
  1906. // Define _ATL_MIN_CRT
  1907. #ifdef _ATL_MIN_CRT
  1908. /////////////////////////////////////////////////////////////////////////////
  1909. // Startup Code
  1910. #if defined(_WINDLL) || defined(_USRDLL)
  1911. // Declare DllMain
  1912. extern "C" BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved);
  1913. extern "C" BOOL WINAPI _DllMainCRTStartup(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
  1914. {
  1915. return DllMain(hDllHandle, dwReason, lpReserved);
  1916. }
  1917. #else
  1918. // wWinMain is not defined in winbase.h.
  1919. extern "C" int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd);
  1920. #define SPACECHAR _T(' ')
  1921. #define DQUOTECHAR _T('\"')
  1922. #ifdef _UNICODE
  1923. extern "C" void wWinMainCRTStartup()
  1924. #else // _UNICODE
  1925. extern "C" void WinMainCRTStartup()
  1926. #endif // _UNICODE
  1927. {
  1928. LPTSTR lpszCommandLine = ::GetCommandLine();
  1929. if(lpszCommandLine == NULL)
  1930. ::ExitProcess((UINT)-1);
  1931. // Skip past program name (first token in command line).
  1932. // Check for and handle quoted program name.
  1933. if(*lpszCommandLine == DQUOTECHAR)
  1934. {
  1935. // Scan, and skip over, subsequent characters until
  1936. // another double-quote or a null is encountered.
  1937. do
  1938. {
  1939. lpszCommandLine = ::CharNext(lpszCommandLine);
  1940. }
  1941. while((*lpszCommandLine != DQUOTECHAR) && (*lpszCommandLine != _T('\0')));
  1942. // If we stopped on a double-quote (usual case), skip over it.
  1943. if(*lpszCommandLine == DQUOTECHAR)
  1944. lpszCommandLine = ::CharNext(lpszCommandLine);
  1945. }
  1946. else
  1947. {
  1948. while(*lpszCommandLine > SPACECHAR)
  1949. lpszCommandLine = ::CharNext(lpszCommandLine);
  1950. }
  1951. // Skip past any white space preceeding the second token.
  1952. while(*lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
  1953. lpszCommandLine = ::CharNext(lpszCommandLine);
  1954. STARTUPINFO StartupInfo;
  1955. StartupInfo.dwFlags = 0;
  1956. ::GetStartupInfo(&StartupInfo);
  1957. int nRet = _tWinMain(::GetModuleHandle(NULL), NULL, lpszCommandLine,
  1958. (StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ?
  1959. StartupInfo.wShowWindow : SW_SHOWDEFAULT);
  1960. ::ExitProcess((UINT)nRet);
  1961. }
  1962. #endif // defined(_WINDLL) | defined(_USRDLL)
  1963. /////////////////////////////////////////////////////////////////////////////
  1964. // Heap Allocation
  1965. #ifndef _DEBUG
  1966. #ifndef _MERGE_PROXYSTUB
  1967. //rpcproxy.h does the same thing as this
  1968. int __cdecl _purecall()
  1969. {
  1970. DebugBreak();
  1971. return 0;
  1972. }
  1973. #endif
  1974. #if !defined(_M_ALPHA) && !defined(_M_PPC)
  1975. //RISC always initializes floating point and always defines _fltused
  1976. extern "C" const int _fltused = 0;
  1977. #endif
  1978. void* __cdecl malloc(size_t n)
  1979. {
  1980. if (_Module.m_hHeap == NULL)
  1981. {
  1982. _Module.m_hHeap = HeapCreate(0, 0, 0);
  1983. if (_Module.m_hHeap == NULL)
  1984. return NULL;
  1985. }
  1986. _ASSERTE(_Module.m_hHeap != NULL);
  1987. #ifdef _MALLOC_ZEROINIT
  1988. return HeapAlloc(_Module.m_hHeap, HEAP_ZERO_MEMORY, n);
  1989. #else
  1990. return HeapAlloc(_Module.m_hHeap, 0, n);
  1991. #endif
  1992. }
  1993. void* __cdecl calloc(size_t n, size_t s)
  1994. {
  1995. return malloc(n * s);
  1996. }
  1997. void* __cdecl realloc(void* p, size_t n)
  1998. {
  1999. _ASSERTE(_Module.m_hHeap != NULL);
  2000. #ifdef _MALLOC_ZEROINIT
  2001. return (p == NULL) ? malloc(n) : HeapReAlloc(_Module.m_hHeap, HEAP_ZERO_MEMORY, p, n);
  2002. #else
  2003. return (p == NULL) ? malloc(n) : HeapReAlloc(_Module.m_hHeap, 0, p, n);
  2004. #endif
  2005. }
  2006. void __cdecl free(void* p)
  2007. {
  2008. _ASSERTE(_Module.m_hHeap != NULL);
  2009. HeapFree(_Module.m_hHeap, 0, p);
  2010. }
  2011. void* __cdecl operator new(size_t n)
  2012. {
  2013. return malloc(n);
  2014. }
  2015. void __cdecl operator delete(void* p)
  2016. {
  2017. free(p);
  2018. }
  2019. #endif //_DEBUG
  2020. #endif //_ATL_MIN_CRT
  2021. #ifndef _ATL_DLL
  2022. #ifndef ATL_NO_NAMESPACE
  2023. #ifndef _ATL_DLL_IMPL
  2024. namespace ATL
  2025. {
  2026. #endif
  2027. #endif
  2028. /////////////////////////////////////////////////////////////////////////////
  2029. // statics
  2030. static UINT WINAPI AtlGetDirLen(LPCOLESTR lpszPathName)
  2031. {
  2032. _ASSERTE(lpszPathName != NULL);
  2033. // always capture the complete file name including extension (if present)
  2034. LPCOLESTR lpszTemp = lpszPathName;
  2035. for (LPCOLESTR lpsz = lpszPathName; *lpsz != NULL; )
  2036. {
  2037. LPCOLESTR lp = CharNextO(lpsz);
  2038. // remember last directory/drive separator
  2039. if (*lpsz == OLESTR('\\') || *lpsz == OLESTR('/') || *lpsz == OLESTR(':'))
  2040. lpszTemp = lp;
  2041. lpsz = lp;
  2042. }
  2043. return UINT(lpszTemp-lpszPathName);
  2044. }
  2045. /////////////////////////////////////////////////////////////////////////////
  2046. // QI support
  2047. ATLAPI AtlInternalQueryInterface(void* pThis,
  2048. const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
  2049. {
  2050. _ASSERTE(pThis != NULL);
  2051. // First entry in the com map should be a simple map entry
  2052. _ASSERTE(pEntries->pFunc == _ATL_SIMPLEMAPENTRY);
  2053. if (ppvObject == NULL)
  2054. return E_POINTER;
  2055. *ppvObject = NULL;
  2056. if (InlineIsEqualUnknown(iid)) // use first interface
  2057. {
  2058. IUnknown* pUnk = (IUnknown*)((LONG_PTR)pThis+pEntries->dw);
  2059. pUnk->AddRef();
  2060. *ppvObject = pUnk;
  2061. return S_OK;
  2062. }
  2063. while (pEntries->pFunc != NULL)
  2064. {
  2065. BOOL bBlind = (pEntries->piid == NULL);
  2066. if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid))
  2067. {
  2068. if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset
  2069. {
  2070. _ASSERTE(!bBlind);
  2071. IUnknown* pUnk = (IUnknown*)((LONG_PTR)pThis+pEntries->dw);
  2072. pUnk->AddRef();
  2073. *ppvObject = pUnk;
  2074. return S_OK;
  2075. }
  2076. else //actual function call
  2077. {
  2078. HRESULT hRes = pEntries->pFunc(pThis,
  2079. iid, ppvObject, pEntries->dw);
  2080. if (hRes == S_OK || (!bBlind && FAILED(hRes)))
  2081. return hRes;
  2082. }
  2083. }
  2084. pEntries++;
  2085. }
  2086. return E_NOINTERFACE;
  2087. }
  2088. /////////////////////////////////////////////////////////////////////////////
  2089. // Smart Pointer helpers
  2090. ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp)
  2091. {
  2092. if (lp != NULL)
  2093. lp->AddRef();
  2094. if (*pp)
  2095. (*pp)->Release();
  2096. *pp = lp;
  2097. return lp;
  2098. }
  2099. ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid)
  2100. {
  2101. IUnknown* pTemp = *pp;
  2102. *pp = NULL;
  2103. if (lp != NULL)
  2104. lp->QueryInterface(riid, (void**)pp);
  2105. if (pTemp)
  2106. pTemp->Release();
  2107. return *pp;
  2108. }
  2109. /////////////////////////////////////////////////////////////////////////////
  2110. // Inproc Marshaling helpers
  2111. ATLAPI AtlFreeMarshalStream(IStream* pStream)
  2112. {
  2113. if (pStream != NULL)
  2114. {
  2115. CoReleaseMarshalData(pStream);
  2116. pStream->Release();
  2117. }
  2118. return S_OK;
  2119. }
  2120. ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream)
  2121. {
  2122. HRESULT hRes = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
  2123. if (SUCCEEDED(hRes))
  2124. {
  2125. hRes = CoMarshalInterface(*ppStream, iid,
  2126. pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
  2127. if (FAILED(hRes))
  2128. {
  2129. (*ppStream)->Release();
  2130. *ppStream = NULL;
  2131. }
  2132. }
  2133. return hRes;
  2134. }
  2135. ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk)
  2136. {
  2137. *ppUnk = NULL;
  2138. HRESULT hRes = E_INVALIDARG;
  2139. if (pStream != NULL)
  2140. {
  2141. LARGE_INTEGER l;
  2142. l.QuadPart = 0;
  2143. pStream->Seek(l, STREAM_SEEK_SET, NULL);
  2144. hRes = CoUnmarshalInterface(pStream, iid, (void**)ppUnk);
  2145. }
  2146. return hRes;
  2147. }
  2148. ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent)
  2149. {
  2150. DWORD dwRet;
  2151. MSG msg;
  2152. while(1)
  2153. {
  2154. dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT);
  2155. if (dwRet == WAIT_OBJECT_0)
  2156. return TRUE; // The event was signaled
  2157. if (dwRet != WAIT_OBJECT_0 + 1)
  2158. break; // Something else happened
  2159. // There is one or more window message available. Dispatch them
  2160. while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
  2161. {
  2162. TranslateMessage(&msg);
  2163. DispatchMessage(&msg);
  2164. if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
  2165. return TRUE; // Event is now signaled.
  2166. }
  2167. }
  2168. return FALSE;
  2169. }
  2170. /////////////////////////////////////////////////////////////////////////////
  2171. // Connection Point Helpers
  2172. ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw)
  2173. {
  2174. CComPtr<IConnectionPointContainer> pCPC;
  2175. CComPtr<IConnectionPoint> pCP;
  2176. HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
  2177. if (SUCCEEDED(hRes))
  2178. hRes = pCPC->FindConnectionPoint(iid, &pCP);
  2179. if (SUCCEEDED(hRes))
  2180. hRes = pCP->Advise(pUnk, pdw);
  2181. return hRes;
  2182. }
  2183. ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw)
  2184. {
  2185. CComPtr<IConnectionPointContainer> pCPC;
  2186. CComPtr<IConnectionPoint> pCP;
  2187. HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
  2188. if (SUCCEEDED(hRes))
  2189. hRes = pCPC->FindConnectionPoint(iid, &pCP);
  2190. if (SUCCEEDED(hRes))
  2191. hRes = pCP->Unadvise(dw);
  2192. return hRes;
  2193. }
  2194. /////////////////////////////////////////////////////////////////////////////
  2195. // IDispatch Error handling
  2196. ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
  2197. LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst)
  2198. {
  2199. USES_CONVERSION;
  2200. TCHAR szDesc[1024];
  2201. szDesc[0] = NULL;
  2202. // For a valid HRESULT the id should be in the range [0x0200, 0xffff]
  2203. if (ULONG_PTR( lpszDesc ) < 0x10000) // id
  2204. {
  2205. UINT nID = LOWORD((ULONG_PTR)lpszDesc);
  2206. _ASSERTE((nID >= 0x0200 && nID <= 0xffff) || hRes != 0);
  2207. if (LoadString(hInst, nID, szDesc, 1024) == 0)
  2208. {
  2209. _ASSERTE(FALSE);
  2210. lstrcpy(szDesc, _T("Unknown Error"));
  2211. }
  2212. lpszDesc = T2OLE(szDesc);
  2213. if (hRes == 0)
  2214. hRes = MAKE_HRESULT(3, FACILITY_ITF, nID);
  2215. }
  2216. CComPtr<ICreateErrorInfo> pICEI;
  2217. if (SUCCEEDED(CreateErrorInfo(&pICEI)))
  2218. {
  2219. CComPtr<IErrorInfo> pErrorInfo;
  2220. pICEI->SetGUID(iid);
  2221. LPOLESTR lpsz;
  2222. ProgIDFromCLSID(clsid, &lpsz);
  2223. if (lpsz != NULL)
  2224. pICEI->SetSource(lpsz);
  2225. if (dwHelpID != 0 && lpszHelpFile != NULL)
  2226. {
  2227. pICEI->SetHelpContext(dwHelpID);
  2228. pICEI->SetHelpFile(const_cast<LPOLESTR>(lpszHelpFile));
  2229. }
  2230. CoTaskMemFree(lpsz);
  2231. pICEI->SetDescription((LPOLESTR)lpszDesc);
  2232. if (SUCCEEDED(pICEI->QueryInterface(IID_IErrorInfo, (void**)&pErrorInfo)))
  2233. SetErrorInfo(0, pErrorInfo);
  2234. }
  2235. //#ifdef _DEBUG
  2236. // USES_CONVERSION;
  2237. // ATLTRACE(_T("AtlReportError: Description=\"%s\" returning %x\n"), OLE2CT(lpszDesc), hRes);
  2238. //#endif
  2239. return (hRes == 0) ? DISP_E_EXCEPTION : hRes;
  2240. }
  2241. /////////////////////////////////////////////////////////////////////////////
  2242. // Module
  2243. //Although these functions are big, they are only used once in a module
  2244. //so we should make them inline.
  2245. ATLAPI AtlModuleInit(_ATL_MODULE* pM, _ATL_OBJMAP_ENTRY* p, HINSTANCE h)
  2246. {
  2247. _ASSERTE(pM != NULL);
  2248. if (pM == NULL)
  2249. return E_INVALIDARG;
  2250. if (pM->cbSize < sizeof(_ATL_MODULE))
  2251. return E_INVALIDARG;
  2252. pM->m_pObjMap = p;
  2253. pM->m_hInst = pM->m_hInstTypeLib = pM->m_hInstResource = h;
  2254. pM->m_nLockCnt=0L;
  2255. pM->m_hHeap = NULL;
  2256. InitializeCriticalSection(&pM->m_csTypeInfoHolder);
  2257. InitializeCriticalSection(&pM->m_csWindowCreate);
  2258. InitializeCriticalSection(&pM->m_csObjMap);
  2259. return S_OK;
  2260. }
  2261. ATLAPI AtlModuleRegisterClassObjects(_ATL_MODULE* pM, DWORD dwClsContext, DWORD dwFlags)
  2262. {
  2263. _ASSERTE(pM != NULL);
  2264. if (pM == NULL)
  2265. return E_INVALIDARG;
  2266. _ASSERTE(pM->m_pObjMap != NULL);
  2267. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2268. HRESULT hRes = S_OK;
  2269. while (pEntry->pclsid != NULL && hRes == S_OK)
  2270. {
  2271. hRes = pEntry->RegisterClassObject(dwClsContext, dwFlags);
  2272. pEntry++;
  2273. }
  2274. return hRes;
  2275. }
  2276. ATLAPI AtlModuleRevokeClassObjects(_ATL_MODULE* pM)
  2277. {
  2278. _ASSERTE(pM != NULL);
  2279. if (pM == NULL)
  2280. return E_INVALIDARG;
  2281. _ASSERTE(pM->m_pObjMap != NULL);
  2282. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2283. HRESULT hRes = S_OK;
  2284. while (pEntry->pclsid != NULL && hRes == S_OK)
  2285. {
  2286. hRes = pEntry->RevokeClassObject();
  2287. pEntry++;
  2288. }
  2289. return hRes;
  2290. }
  2291. ATLAPI AtlModuleGetClassObject(_ATL_MODULE* pM, REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  2292. {
  2293. _ASSERTE(pM != NULL);
  2294. if (pM == NULL)
  2295. return E_INVALIDARG;
  2296. _ASSERTE(pM->m_pObjMap != NULL);
  2297. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2298. HRESULT hRes = S_OK;
  2299. if (ppv == NULL)
  2300. return E_POINTER;
  2301. while (pEntry->pclsid != NULL)
  2302. {
  2303. if (InlineIsEqualGUID(rclsid, *pEntry->pclsid))
  2304. {
  2305. if (pEntry->pCF == NULL)
  2306. {
  2307. EnterCriticalSection(&pM->m_csObjMap);
  2308. if (pEntry->pCF == NULL)
  2309. hRes = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, IID_IUnknown, (LPVOID*)&pEntry->pCF);
  2310. LeaveCriticalSection(&pM->m_csObjMap);
  2311. }
  2312. if (pEntry->pCF != NULL)
  2313. hRes = pEntry->pCF->QueryInterface(riid, ppv);
  2314. break;
  2315. }
  2316. pEntry++;
  2317. }
  2318. if (*ppv == NULL && hRes == S_OK)
  2319. hRes = CLASS_E_CLASSNOTAVAILABLE;
  2320. return hRes;
  2321. }
  2322. ATLAPI AtlModuleTerm(_ATL_MODULE* pM)
  2323. {
  2324. _ASSERTE(pM != NULL);
  2325. if (pM == NULL)
  2326. return E_INVALIDARG;
  2327. _ASSERTE(pM->m_hInst != NULL);
  2328. if (pM->m_pObjMap != NULL)
  2329. {
  2330. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2331. while (pEntry->pclsid != NULL)
  2332. {
  2333. if (pEntry->pCF != NULL)
  2334. pEntry->pCF->Release();
  2335. pEntry->pCF = NULL;
  2336. pEntry++;
  2337. }
  2338. }
  2339. DeleteCriticalSection(&pM->m_csTypeInfoHolder);
  2340. DeleteCriticalSection(&pM->m_csWindowCreate);
  2341. DeleteCriticalSection(&pM->m_csObjMap);
  2342. if (pM->m_hHeap != NULL)
  2343. HeapDestroy(pM->m_hHeap);
  2344. return S_OK;
  2345. }
  2346. ATLAPI AtlModuleRegisterServer(_ATL_MODULE* pM, BOOL bRegTypeLib, const CLSID* pCLSID)
  2347. {
  2348. _ASSERTE(pM != NULL);
  2349. if (pM == NULL)
  2350. return E_INVALIDARG;
  2351. _ASSERTE(pM->m_hInst != NULL);
  2352. _ASSERTE(pM->m_pObjMap != NULL);
  2353. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2354. HRESULT hRes = S_OK;
  2355. for (;pEntry->pclsid != NULL; pEntry++)
  2356. {
  2357. if (pCLSID == NULL)
  2358. {
  2359. if (pEntry->pfnGetObjectDescription() != NULL)
  2360. continue;
  2361. }
  2362. else
  2363. {
  2364. if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
  2365. continue;
  2366. }
  2367. hRes = pEntry->pfnUpdateRegistry(TRUE);
  2368. if (FAILED(hRes))
  2369. break;
  2370. }
  2371. if (SUCCEEDED(hRes) && bRegTypeLib)
  2372. hRes = AtlModuleRegisterTypeLib(pM, 0);
  2373. return hRes;
  2374. }
  2375. ATLAPI AtlModuleUnregisterServer(_ATL_MODULE* pM, const CLSID* pCLSID)
  2376. {
  2377. _ASSERTE(pM != NULL);
  2378. if (pM == NULL)
  2379. return E_INVALIDARG;
  2380. _ASSERTE(pM->m_hInst != NULL);
  2381. _ASSERTE(pM->m_pObjMap != NULL);
  2382. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2383. for (;pEntry->pclsid != NULL; pEntry++)
  2384. {
  2385. if (pCLSID == NULL)
  2386. {
  2387. if (pEntry->pfnGetObjectDescription() != NULL)
  2388. continue;
  2389. }
  2390. else
  2391. {
  2392. if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
  2393. continue;
  2394. }
  2395. pEntry->pfnUpdateRegistry(FALSE); //unregister
  2396. }
  2397. return S_OK;
  2398. }
  2399. ATLAPI AtlModuleUpdateRegistryFromResourceD(_ATL_MODULE* pM, LPCOLESTR lpszRes,
  2400. BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg)
  2401. {
  2402. USES_CONVERSION;
  2403. _ASSERTE(pM != NULL);
  2404. HRESULT hRes = S_OK;
  2405. CComPtr<IRegistrar> p;
  2406. if (pReg != NULL)
  2407. p = pReg;
  2408. else
  2409. {
  2410. hRes = CoCreateInstance(CLSID_Registrar, NULL,
  2411. CLSCTX_INPROC_SERVER, IID_IRegistrar, (void**)&p);
  2412. }
  2413. if (SUCCEEDED(hRes))
  2414. {
  2415. TCHAR szModule[_MAX_PATH];
  2416. GetModuleFileName(pM->m_hInst, szModule, _MAX_PATH);
  2417. p->AddReplacement(OLESTR("Module"), T2OLE(szModule));
  2418. if (NULL != pMapEntries)
  2419. {
  2420. while (NULL != pMapEntries->szKey)
  2421. {
  2422. _ASSERTE(NULL != pMapEntries->szData);
  2423. p->AddReplacement((LPOLESTR)pMapEntries->szKey, (LPOLESTR)pMapEntries->szData);
  2424. pMapEntries++;
  2425. }
  2426. }
  2427. LPCOLESTR szType = OLESTR("REGISTRY");
  2428. GetModuleFileName(pM->m_hInstResource, szModule, _MAX_PATH);
  2429. LPOLESTR pszModule = T2OLE(szModule);
  2430. if (ULONG_PTR(lpszRes) < 0x10000)
  2431. {
  2432. if (bRegister)
  2433. hRes = p->ResourceRegister(pszModule, ((UINT)LOWORD((ULONG_PTR)lpszRes)), szType);
  2434. else
  2435. hRes = p->ResourceUnregister(pszModule, ((UINT)LOWORD((ULONG_PTR)lpszRes)), szType);
  2436. }
  2437. else
  2438. {
  2439. if (bRegister)
  2440. hRes = p->ResourceRegisterSz(pszModule, lpszRes, szType);
  2441. else
  2442. hRes = p->ResourceUnregisterSz(pszModule, lpszRes, szType);
  2443. }
  2444. }
  2445. return hRes;
  2446. }
  2447. /////////////////////////////////////////////////////////////////////////////
  2448. // TypeLib Support
  2449. ATLAPI AtlModuleRegisterTypeLib(_ATL_MODULE* pM, LPCOLESTR lpszIndex)
  2450. {
  2451. _ASSERTE(pM != NULL);
  2452. USES_CONVERSION;
  2453. _ASSERTE(pM->m_hInstTypeLib != NULL);
  2454. TCHAR szModule[_MAX_PATH+10] = {0};
  2455. OLECHAR szDir[_MAX_PATH];
  2456. GetModuleFileName(pM->m_hInstTypeLib, szModule, _MAX_PATH);
  2457. if (lpszIndex != NULL)
  2458. lstrcat(szModule, OLE2CT(lpszIndex));
  2459. ITypeLib* pTypeLib;
  2460. LPOLESTR lpszModule = T2OLE(szModule);
  2461. HRESULT hr = LoadTypeLib(lpszModule, &pTypeLib);
  2462. if (!SUCCEEDED(hr))
  2463. {
  2464. // typelib not in module, try <module>.tlb instead
  2465. LPTSTR lpszExt = NULL;
  2466. LPTSTR lpsz;
  2467. for (lpsz = szModule; *lpsz != NULL; lpsz = CharNext(lpsz))
  2468. {
  2469. if (*lpsz == _T('.'))
  2470. lpszExt = lpsz;
  2471. }
  2472. if (lpszExt == NULL)
  2473. lpszExt = lpsz;
  2474. lstrcpy(lpszExt, _T(".tlb"));
  2475. lpszModule = T2OLE(szModule);
  2476. hr = LoadTypeLib(lpszModule, &pTypeLib);
  2477. }
  2478. if (SUCCEEDED(hr))
  2479. {
  2480. ocscpy(szDir, lpszModule);
  2481. szDir[AtlGetDirLen(szDir)] = 0;
  2482. hr = ::RegisterTypeLib(pTypeLib, lpszModule, szDir);
  2483. }
  2484. if (pTypeLib != NULL)
  2485. pTypeLib->Release();
  2486. return hr;
  2487. }
  2488. #ifndef ATL_NO_NAMESPACE
  2489. #ifndef _ATL_DLL_IMPL
  2490. }; //namespace ATL
  2491. #endif
  2492. #endif
  2493. #endif //!_ATL_DLL