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.

2883 lines
65 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) Microsoft Corporation, 1996 - 1999
  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, 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 = 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,
  839. lpszProgID,
  840. REG_NONE,
  841. REG_OPTION_NON_VOLATILE,
  842. KEY_READ | KEY_WRITE,
  843. NULL, NULL);
  844. if (lRes == ERROR_SUCCESS)
  845. {
  846. keyProgID.SetValue(lpszUserDesc);
  847. keyProgID.SetKeyValue(_T("CLSID"), lpszCLSID);
  848. return S_OK;
  849. }
  850. return HRESULT_FROM_WIN32(lRes);
  851. }
  852. void CComModule::AddCreateWndData(_AtlCreateWndData* pData, void* pObject)
  853. {
  854. pData->m_pThis = pObject;
  855. pData->m_dwThreadID = ::GetCurrentThreadId();
  856. ::EnterCriticalSection(&m_csWindowCreate);
  857. pData->m_pNext = m_pCreateWndList;
  858. m_pCreateWndList = pData;
  859. ::LeaveCriticalSection(&m_csWindowCreate);
  860. }
  861. void* CComModule::ExtractCreateWndData()
  862. {
  863. ::EnterCriticalSection(&m_csWindowCreate);
  864. _AtlCreateWndData* pEntry = m_pCreateWndList;
  865. if(pEntry == NULL)
  866. {
  867. ::LeaveCriticalSection(&m_csWindowCreate);
  868. return NULL;
  869. }
  870. DWORD dwThreadID = ::GetCurrentThreadId();
  871. _AtlCreateWndData* pPrev = NULL;
  872. while(pEntry != NULL)
  873. {
  874. if(pEntry->m_dwThreadID == dwThreadID)
  875. {
  876. if(pPrev == NULL)
  877. m_pCreateWndList = pEntry->m_pNext;
  878. else
  879. pPrev->m_pNext = pEntry->m_pNext;
  880. ::LeaveCriticalSection(&m_csWindowCreate);
  881. return pEntry->m_pThis;
  882. }
  883. pPrev = pEntry;
  884. pEntry = pEntry->m_pNext;
  885. }
  886. ::LeaveCriticalSection(&m_csWindowCreate);
  887. return NULL;
  888. }
  889. #ifdef _ATL_STATIC_REGISTRY
  890. // Statically linking to Registry Ponent
  891. HRESULT WINAPI CComModule::UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister,
  892. struct _ATL_REGMAP_ENTRY* pMapEntries)
  893. {
  894. USES_CONVERSION;
  895. CRegObject ro;
  896. TCHAR szModule[_MAX_PATH];
  897. GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  898. LPOLESTR pszModule = T2OLE(szModule);
  899. ro.AddReplacement(OLESTR("Module"), pszModule);
  900. if (NULL != pMapEntries)
  901. {
  902. while (NULL != pMapEntries->szKey)
  903. {
  904. _ASSERTE(NULL != pMapEntries->szData);
  905. ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData);
  906. pMapEntries++;
  907. }
  908. }
  909. LPCOLESTR szType = OLESTR("REGISTRY");
  910. return (bRegister) ? ro.ResourceRegister(pszModule, nResID, szType) :
  911. ro.ResourceUnregister(pszModule, nResID, szType);
  912. }
  913. HRESULT WINAPI CComModule::UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister,
  914. struct _ATL_REGMAP_ENTRY* pMapEntries)
  915. {
  916. USES_CONVERSION;
  917. CRegObject ro;
  918. TCHAR szModule[_MAX_PATH];
  919. GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  920. LPOLESTR pszModule = T2OLE(szModule);
  921. ro.AddReplacement(OLESTR("Module"), pszModule);
  922. if (NULL != pMapEntries)
  923. {
  924. while (NULL != pMapEntries->szKey)
  925. {
  926. _ASSERTE(NULL != pMapEntries->szData);
  927. ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData);
  928. pMapEntries++;
  929. }
  930. }
  931. LPCOLESTR szType = OLESTR("REGISTRY");
  932. LPCOLESTR pszRes = T2COLE(lpszRes);
  933. return (bRegister) ? ro.ResourceRegisterSz(pszModule, pszRes, szType) :
  934. ro.ResourceUnregisterSz(pszModule, pszRes, szType);
  935. }
  936. #endif // _ATL_STATIC_REGISTRY
  937. HRESULT WINAPI CComModule::UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID,
  938. LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister)
  939. {
  940. if (bRegister)
  941. {
  942. return RegisterClassHelper(clsid, lpszProgID, lpszVerIndProgID, nDescID,
  943. dwFlags);
  944. }
  945. else
  946. return UnregisterClassHelper(clsid, lpszProgID, lpszVerIndProgID);
  947. }
  948. HRESULT WINAPI CComModule::RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID,
  949. LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags)
  950. {
  951. static const TCHAR szProgID[] = _T("ProgID");
  952. static const TCHAR szVIProgID[] = _T("VersionIndependentProgID");
  953. static const TCHAR szLS32[] = _T("LocalServer32");
  954. static const TCHAR szIPS32[] = _T("InprocServer32");
  955. static const TCHAR szThreadingModel[] = _T("ThreadingModel");
  956. static const TCHAR szAUTPRX32[] = _T("AUTPRX32.DLL");
  957. static const TCHAR szApartment[] = _T("Apartment");
  958. static const TCHAR szBoth[] = _T("both");
  959. USES_CONVERSION;
  960. HRESULT hRes = S_OK;
  961. TCHAR szDesc[256];
  962. LoadString(m_hInst, nDescID, szDesc, 256);
  963. TCHAR szModule[_MAX_PATH];
  964. GetModuleFileName(m_hInst, szModule, _MAX_PATH);
  965. LPOLESTR lpOleStr;
  966. StringFromCLSID(clsid, &lpOleStr);
  967. LPTSTR lpsz = OLE2T(lpOleStr);
  968. hRes = AtlRegisterProgID(lpsz, lpszProgID, szDesc);
  969. if (hRes == S_OK)
  970. hRes = AtlRegisterProgID(lpsz, lpszVerIndProgID, szDesc);
  971. LONG lRes = ERROR_SUCCESS;
  972. if (hRes == S_OK)
  973. {
  974. CRegKey key;
  975. LONG lRes = key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_WRITE | KEY_READ);
  976. if (lRes == ERROR_SUCCESS)
  977. {
  978. lRes = key.Create(key,
  979. lpsz,
  980. REG_NONE,
  981. REG_OPTION_NON_VOLATILE,
  982. KEY_WRITE,
  983. NULL, NULL);
  984. if (lRes == ERROR_SUCCESS)
  985. {
  986. key.SetValue(szDesc);
  987. key.SetKeyValue(szProgID, lpszProgID);
  988. key.SetKeyValue(szVIProgID, lpszVerIndProgID);
  989. if ((m_hInst == NULL) || (m_hInst == GetModuleHandle(NULL))) // register as EXE
  990. key.SetKeyValue(szLS32, szModule);
  991. else
  992. {
  993. key.SetKeyValue(szIPS32, (dwFlags & AUTPRXFLAG) ? szAUTPRX32 : szModule);
  994. LPCTSTR lpszModel = (dwFlags & THREADFLAGS_BOTH) ? szBoth :
  995. (dwFlags & THREADFLAGS_APARTMENT) ? szApartment : NULL;
  996. if (lpszModel != NULL)
  997. key.SetKeyValue(szIPS32, lpszModel, szThreadingModel);
  998. }
  999. }
  1000. }
  1001. }
  1002. CoTaskMemFree(lpOleStr);
  1003. if (lRes != ERROR_SUCCESS)
  1004. hRes = HRESULT_FROM_WIN32(lRes);
  1005. return hRes;
  1006. }
  1007. HRESULT WINAPI CComModule::UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID,
  1008. LPCTSTR lpszVerIndProgID)
  1009. {
  1010. USES_CONVERSION;
  1011. CRegKey key;
  1012. key.Attach(HKEY_CLASSES_ROOT);
  1013. if (lpszProgID != NULL && lstrcmpi(lpszProgID, _T("")))
  1014. key.RecurseDeleteKey(lpszProgID);
  1015. if (lpszVerIndProgID != NULL && lstrcmpi(lpszVerIndProgID, _T("")))
  1016. key.RecurseDeleteKey(lpszVerIndProgID);
  1017. LPOLESTR lpOleStr;
  1018. StringFromCLSID(clsid, &lpOleStr);
  1019. LPTSTR lpsz = OLE2T(lpOleStr);
  1020. if (key.Open(key, _T("CLSID"), KEY_WRITE | KEY_READ) == ERROR_SUCCESS)
  1021. key.RecurseDeleteKey(lpsz);
  1022. CoTaskMemFree(lpOleStr);
  1023. return S_OK;
  1024. }
  1025. /////////////////////////////////////////////////////////////////////////////
  1026. // CRegKey
  1027. LONG CRegKey::Close()
  1028. {
  1029. LONG lRes = ERROR_SUCCESS;
  1030. if (m_hKey != NULL)
  1031. {
  1032. lRes = RegCloseKey(m_hKey);
  1033. m_hKey = NULL;
  1034. }
  1035. return lRes;
  1036. }
  1037. LONG CRegKey::Create(HKEY hKeyParent, LPCTSTR lpszKeyName,
  1038. LPTSTR lpszClass, DWORD dwOptions, REGSAM samDesired,
  1039. LPSECURITY_ATTRIBUTES lpSecAttr, LPDWORD lpdwDisposition)
  1040. {
  1041. _ASSERTE(hKeyParent != NULL);
  1042. DWORD dw;
  1043. HKEY hKey = NULL;
  1044. LONG lRes = RegCreateKeyEx(hKeyParent, lpszKeyName, 0,
  1045. lpszClass, dwOptions, samDesired, lpSecAttr, &hKey, &dw);
  1046. if (lpdwDisposition != NULL)
  1047. *lpdwDisposition = dw;
  1048. if (lRes == ERROR_SUCCESS)
  1049. {
  1050. lRes = Close();
  1051. m_hKey = hKey;
  1052. }
  1053. return lRes;
  1054. }
  1055. LONG CRegKey::Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired)
  1056. {
  1057. _ASSERTE(hKeyParent != NULL);
  1058. HKEY hKey = NULL;
  1059. LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey);
  1060. if (lRes == ERROR_SUCCESS)
  1061. {
  1062. lRes = Close();
  1063. _ASSERTE(lRes == ERROR_SUCCESS);
  1064. m_hKey = hKey;
  1065. }
  1066. return lRes;
  1067. }
  1068. LONG CRegKey::QueryValue(DWORD& dwValue, LPCTSTR lpszValueName)
  1069. {
  1070. DWORD dwType = NULL;
  1071. DWORD dwCount = sizeof(DWORD);
  1072. LONG lRes = RegQueryValueEx(m_hKey, (LPTSTR)lpszValueName, NULL, &dwType,
  1073. (LPBYTE)&dwValue, &dwCount);
  1074. _ASSERTE((lRes!=ERROR_SUCCESS) || (dwType == REG_DWORD));
  1075. _ASSERTE((lRes!=ERROR_SUCCESS) || (dwCount == sizeof(DWORD)));
  1076. return lRes;
  1077. }
  1078. LONG CRegKey::QueryValue(LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount)
  1079. {
  1080. _ASSERTE(pdwCount != NULL);
  1081. DWORD dwType = NULL;
  1082. LONG lRes = RegQueryValueEx(m_hKey, (LPTSTR)lpszValueName, NULL, &dwType,
  1083. (LPBYTE)szValue, pdwCount);
  1084. _ASSERTE((lRes!=ERROR_SUCCESS) || (dwType == REG_SZ) ||
  1085. (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ));
  1086. return lRes;
  1087. }
  1088. LONG WINAPI CRegKey::SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName)
  1089. {
  1090. _ASSERTE(lpszValue != NULL);
  1091. CRegKey key;
  1092. LONG lRes = key.Create(hKeyParent,
  1093. lpszKeyName,
  1094. REG_NONE,
  1095. REG_OPTION_NON_VOLATILE,
  1096. KEY_WRITE,
  1097. NULL, NULL);
  1098. if (lRes == ERROR_SUCCESS)
  1099. lRes = key.SetValue(lpszValue, lpszValueName);
  1100. return lRes;
  1101. }
  1102. LONG CRegKey::SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName)
  1103. {
  1104. _ASSERTE(lpszValue != NULL);
  1105. CRegKey key;
  1106. LONG lRes = key.Create(m_hKey,
  1107. lpszKeyName,
  1108. REG_NONE,
  1109. REG_OPTION_NON_VOLATILE,
  1110. KEY_WRITE,
  1111. NULL, NULL);
  1112. if (lRes == ERROR_SUCCESS)
  1113. lRes = key.SetValue(lpszValue, lpszValueName);
  1114. return lRes;
  1115. }
  1116. LONG CRegKey::SetValue(DWORD dwValue, LPCTSTR lpszValueName)
  1117. {
  1118. _ASSERTE(m_hKey != NULL);
  1119. return RegSetValueEx(m_hKey, lpszValueName, NULL, REG_DWORD,
  1120. (BYTE * const)&dwValue, sizeof(DWORD));
  1121. }
  1122. HRESULT CRegKey::SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName)
  1123. {
  1124. _ASSERTE(lpszValue != NULL);
  1125. _ASSERTE(m_hKey != NULL);
  1126. return RegSetValueEx(m_hKey, lpszValueName, NULL, REG_SZ,
  1127. (BYTE * const)lpszValue, (lstrlen(lpszValue)+1)*sizeof(TCHAR));
  1128. }
  1129. //RecurseDeleteKey is necessary because on NT RegDeleteKey doesn't work if the
  1130. //specified key has subkeys
  1131. LONG CRegKey::RecurseDeleteKey(LPCTSTR lpszKey)
  1132. {
  1133. CRegKey key;
  1134. LONG lRes = key.Open(m_hKey, lpszKey, KEY_READ | KEY_WRITE);
  1135. if (lRes != ERROR_SUCCESS)
  1136. return lRes;
  1137. FILETIME time;
  1138. TCHAR szBuffer[256];
  1139. DWORD dwSize = 256;
  1140. while (RegEnumKeyEx(key.m_hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL,
  1141. &time)==ERROR_SUCCESS)
  1142. {
  1143. lRes = key.RecurseDeleteKey(szBuffer);
  1144. if (lRes != ERROR_SUCCESS)
  1145. return lRes;
  1146. dwSize = 256;
  1147. }
  1148. key.Close();
  1149. return DeleteSubKey(lpszKey);
  1150. }
  1151. #ifdef __ATLCOM_H__
  1152. #ifndef _ATL_NO_SECURITY
  1153. CSecurityDescriptor::CSecurityDescriptor()
  1154. {
  1155. m_pSD = NULL;
  1156. m_pOwner = NULL;
  1157. m_pGroup = NULL;
  1158. m_pDACL = NULL;
  1159. m_pSACL= NULL;
  1160. }
  1161. CSecurityDescriptor::~CSecurityDescriptor()
  1162. {
  1163. if (m_pSD)
  1164. delete m_pSD;
  1165. if (m_pOwner)
  1166. free(m_pOwner);
  1167. if (m_pGroup)
  1168. free(m_pGroup);
  1169. if (m_pDACL)
  1170. free(m_pDACL);
  1171. if (m_pSACL)
  1172. free(m_pSACL);
  1173. }
  1174. HRESULT CSecurityDescriptor::Initialize()
  1175. {
  1176. if (m_pSD)
  1177. {
  1178. delete m_pSD;
  1179. m_pSD = NULL;
  1180. }
  1181. if (m_pOwner)
  1182. {
  1183. free(m_pOwner);
  1184. m_pOwner = NULL;
  1185. }
  1186. if (m_pGroup)
  1187. {
  1188. free(m_pGroup);
  1189. m_pGroup = NULL;
  1190. }
  1191. if (m_pDACL)
  1192. {
  1193. free(m_pDACL);
  1194. m_pDACL = NULL;
  1195. }
  1196. if (m_pSACL)
  1197. {
  1198. free(m_pSACL);
  1199. m_pSACL = NULL;
  1200. }
  1201. ATLTRY(m_pSD = new SECURITY_DESCRIPTOR);
  1202. if (!m_pSD)
  1203. return E_OUTOFMEMORY;
  1204. if (!InitializeSecurityDescriptor(m_pSD, SECURITY_DESCRIPTOR_REVISION))
  1205. {
  1206. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1207. delete m_pSD;
  1208. m_pSD = NULL;
  1209. _ASSERTE(FALSE);
  1210. return hr;
  1211. }
  1212. // Set the DACL to allow EVERYONE
  1213. SetSecurityDescriptorDacl(m_pSD, TRUE, NULL, FALSE);
  1214. return S_OK;
  1215. }
  1216. HRESULT CSecurityDescriptor::InitializeFromProcessToken(BOOL bDefaulted)
  1217. {
  1218. PSID pUserSid;
  1219. PSID pGroupSid;
  1220. HRESULT hr;
  1221. Initialize();
  1222. hr = GetProcessSids(&pUserSid, &pGroupSid);
  1223. if (FAILED(hr))
  1224. return hr;
  1225. hr = SetOwner(pUserSid, bDefaulted);
  1226. if (FAILED(hr))
  1227. return hr;
  1228. hr = SetGroup(pGroupSid, bDefaulted);
  1229. if (FAILED(hr))
  1230. return hr;
  1231. return S_OK;
  1232. }
  1233. HRESULT CSecurityDescriptor::InitializeFromThreadToken(BOOL bDefaulted, BOOL bRevertToProcessToken)
  1234. {
  1235. PSID pUserSid;
  1236. PSID pGroupSid;
  1237. HRESULT hr;
  1238. Initialize();
  1239. hr = GetThreadSids(&pUserSid, &pGroupSid);
  1240. if (HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken)
  1241. hr = GetProcessSids(&pUserSid, &pGroupSid);
  1242. if (FAILED(hr))
  1243. return hr;
  1244. hr = SetOwner(pUserSid, bDefaulted);
  1245. if (FAILED(hr))
  1246. return hr;
  1247. hr = SetGroup(pGroupSid, bDefaulted);
  1248. if (FAILED(hr))
  1249. return hr;
  1250. return S_OK;
  1251. }
  1252. HRESULT CSecurityDescriptor::SetOwner(PSID pOwnerSid, BOOL bDefaulted)
  1253. {
  1254. _ASSERTE(m_pSD);
  1255. // Mark the SD as having no owner
  1256. if (!SetSecurityDescriptorOwner(m_pSD, NULL, bDefaulted))
  1257. {
  1258. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1259. _ASSERTE(FALSE);
  1260. return hr;
  1261. }
  1262. if (m_pOwner)
  1263. {
  1264. free(m_pOwner);
  1265. m_pOwner = NULL;
  1266. }
  1267. // If they asked for no owner don't do the copy
  1268. if (pOwnerSid == NULL)
  1269. return S_OK;
  1270. // Make a copy of the Sid for the return value
  1271. DWORD dwSize = GetLengthSid(pOwnerSid);
  1272. m_pOwner = (PSID) malloc(dwSize);
  1273. if (!m_pOwner)
  1274. {
  1275. // Insufficient memory to allocate Sid
  1276. _ASSERTE(FALSE);
  1277. return E_OUTOFMEMORY;
  1278. }
  1279. if (!CopySid(dwSize, m_pOwner, pOwnerSid))
  1280. {
  1281. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1282. _ASSERTE(FALSE);
  1283. free(m_pOwner);
  1284. m_pOwner = NULL;
  1285. return hr;
  1286. }
  1287. _ASSERTE(IsValidSid(m_pOwner));
  1288. if (!SetSecurityDescriptorOwner(m_pSD, m_pOwner, bDefaulted))
  1289. {
  1290. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1291. _ASSERTE(FALSE);
  1292. free(m_pOwner);
  1293. m_pOwner = NULL;
  1294. return hr;
  1295. }
  1296. return S_OK;
  1297. }
  1298. HRESULT CSecurityDescriptor::SetGroup(PSID pGroupSid, BOOL bDefaulted)
  1299. {
  1300. _ASSERTE(m_pSD);
  1301. // Mark the SD as having no Group
  1302. if (!SetSecurityDescriptorGroup(m_pSD, NULL, bDefaulted))
  1303. {
  1304. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1305. _ASSERTE(FALSE);
  1306. return hr;
  1307. }
  1308. if (m_pGroup)
  1309. {
  1310. free(m_pGroup);
  1311. m_pGroup = NULL;
  1312. }
  1313. // If they asked for no Group don't do the copy
  1314. if (pGroupSid == NULL)
  1315. return S_OK;
  1316. // Make a copy of the Sid for the return value
  1317. DWORD dwSize = GetLengthSid(pGroupSid);
  1318. m_pGroup = (PSID) malloc(dwSize);
  1319. if (!m_pGroup)
  1320. {
  1321. // Insufficient memory to allocate Sid
  1322. _ASSERTE(FALSE);
  1323. return E_OUTOFMEMORY;
  1324. }
  1325. if (!CopySid(dwSize, m_pGroup, pGroupSid))
  1326. {
  1327. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1328. _ASSERTE(FALSE);
  1329. free(m_pGroup);
  1330. m_pGroup = NULL;
  1331. return hr;
  1332. }
  1333. _ASSERTE(IsValidSid(m_pGroup));
  1334. if (!SetSecurityDescriptorGroup(m_pSD, m_pGroup, bDefaulted))
  1335. {
  1336. HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  1337. _ASSERTE(FALSE);
  1338. free(m_pGroup);
  1339. m_pGroup = NULL;
  1340. return hr;
  1341. }
  1342. return S_OK;
  1343. }
  1344. HRESULT CSecurityDescriptor::Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1345. {
  1346. HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask);
  1347. if (SUCCEEDED(hr))
  1348. SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE);
  1349. return hr;
  1350. }
  1351. HRESULT CSecurityDescriptor::Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1352. {
  1353. HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, pszPrincipal, dwAccessMask);
  1354. if (SUCCEEDED(hr))
  1355. SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE);
  1356. return hr;
  1357. }
  1358. HRESULT CSecurityDescriptor::Revoke(LPCTSTR pszPrincipal)
  1359. {
  1360. HRESULT hr = RemovePrincipalFromACL(m_pDACL, pszPrincipal);
  1361. if (SUCCEEDED(hr))
  1362. SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE);
  1363. return hr;
  1364. }
  1365. HRESULT CSecurityDescriptor::GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid)
  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 = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
  1375. if (!bRes)
  1376. {
  1377. // Couldn't open process token
  1378. hr = HRESULT_FROM_WIN32(GetLastError());
  1379. _ASSERTE(FALSE);
  1380. return hr;
  1381. }
  1382. hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
  1383. return hr;
  1384. }
  1385. HRESULT CSecurityDescriptor::GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid, BOOL bOpenAsSelf)
  1386. {
  1387. BOOL bRes;
  1388. HRESULT hr;
  1389. HANDLE hToken = NULL;
  1390. if (ppUserSid)
  1391. *ppUserSid = NULL;
  1392. if (ppGroupSid)
  1393. *ppGroupSid = NULL;
  1394. bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken);
  1395. if (!bRes)
  1396. {
  1397. // Couldn't open thread token
  1398. hr = HRESULT_FROM_WIN32(GetLastError());
  1399. return hr;
  1400. }
  1401. hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
  1402. return hr;
  1403. }
  1404. HRESULT CSecurityDescriptor::GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid)
  1405. {
  1406. DWORD dwSize;
  1407. HRESULT hr;
  1408. PTOKEN_USER ptkUser = NULL;
  1409. PTOKEN_PRIMARY_GROUP ptkGroup = NULL;
  1410. if (ppUserSid)
  1411. *ppUserSid = NULL;
  1412. if (ppGroupSid)
  1413. *ppGroupSid = NULL;
  1414. if (ppUserSid)
  1415. {
  1416. // Get length required for TokenUser by specifying buffer length of 0
  1417. GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
  1418. hr = GetLastError();
  1419. if (hr != ERROR_INSUFFICIENT_BUFFER)
  1420. {
  1421. // Expected ERROR_INSUFFICIENT_BUFFER
  1422. _ASSERTE(FALSE);
  1423. hr = HRESULT_FROM_WIN32(hr);
  1424. goto failed;
  1425. }
  1426. ptkUser = (TOKEN_USER*) malloc(dwSize);
  1427. if (!ptkUser)
  1428. {
  1429. // Insufficient memory to allocate TOKEN_USER
  1430. _ASSERTE(FALSE);
  1431. hr = E_OUTOFMEMORY;
  1432. goto failed;
  1433. }
  1434. // Get Sid of process token.
  1435. if (!GetTokenInformation(hToken, TokenUser, ptkUser, dwSize, &dwSize))
  1436. {
  1437. // Couldn't get user info
  1438. hr = HRESULT_FROM_WIN32(GetLastError());
  1439. _ASSERTE(FALSE);
  1440. goto failed;
  1441. }
  1442. // Make a copy of the Sid for the return value
  1443. dwSize = GetLengthSid(ptkUser->User.Sid);
  1444. PSID pSid = (PSID) malloc(dwSize);
  1445. if (!pSid)
  1446. {
  1447. // Insufficient memory to allocate Sid
  1448. _ASSERTE(FALSE);
  1449. hr = E_OUTOFMEMORY;
  1450. goto failed;
  1451. }
  1452. if (!CopySid(dwSize, pSid, ptkUser->User.Sid))
  1453. {
  1454. hr = HRESULT_FROM_WIN32(GetLastError());
  1455. _ASSERTE(FALSE);
  1456. free(pSid);
  1457. goto failed;
  1458. }
  1459. _ASSERTE(IsValidSid(pSid));
  1460. *ppUserSid = pSid;
  1461. free(ptkUser);
  1462. ptkUser = NULL;
  1463. }
  1464. if (ppGroupSid)
  1465. {
  1466. // Get length required for TokenPrimaryGroup by specifying buffer length of 0
  1467. GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize);
  1468. hr = GetLastError();
  1469. if (hr != ERROR_INSUFFICIENT_BUFFER)
  1470. {
  1471. // Expected ERROR_INSUFFICIENT_BUFFER
  1472. _ASSERTE(FALSE);
  1473. hr = HRESULT_FROM_WIN32(hr);
  1474. goto failed;
  1475. }
  1476. ptkGroup = (TOKEN_PRIMARY_GROUP*) malloc(dwSize);
  1477. if (!ptkGroup)
  1478. {
  1479. // Insufficient memory to allocate TOKEN_USER
  1480. _ASSERTE(FALSE);
  1481. hr = E_OUTOFMEMORY;
  1482. goto failed;
  1483. }
  1484. // Get Sid of process token.
  1485. if (!GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize))
  1486. {
  1487. // Couldn't get user info
  1488. hr = HRESULT_FROM_WIN32(GetLastError());
  1489. _ASSERTE(FALSE);
  1490. goto failed;
  1491. }
  1492. // Make a copy of the Sid for the return value
  1493. dwSize = GetLengthSid(ptkGroup->PrimaryGroup);
  1494. PSID pSid = (PSID) malloc(dwSize);
  1495. if (!pSid)
  1496. {
  1497. // Insufficient memory to allocate Sid
  1498. _ASSERTE(FALSE);
  1499. hr = E_OUTOFMEMORY;
  1500. goto failed;
  1501. }
  1502. if (!CopySid(dwSize, pSid, ptkGroup->PrimaryGroup))
  1503. {
  1504. hr = HRESULT_FROM_WIN32(GetLastError());
  1505. _ASSERTE(FALSE);
  1506. free(pSid);
  1507. goto failed;
  1508. }
  1509. _ASSERTE(IsValidSid(pSid));
  1510. *ppGroupSid = pSid;
  1511. free(ptkGroup);
  1512. }
  1513. return S_OK;
  1514. failed:
  1515. if (ptkUser)
  1516. free(ptkUser);
  1517. if (ptkGroup)
  1518. free (ptkGroup);
  1519. return hr;
  1520. }
  1521. HRESULT CSecurityDescriptor::GetCurrentUserSID(PSID *ppSid)
  1522. {
  1523. HANDLE tkHandle;
  1524. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle))
  1525. {
  1526. TOKEN_USER *tkUser;
  1527. DWORD tkSize;
  1528. DWORD sidLength;
  1529. // Call to get size information for alloc
  1530. GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize);
  1531. tkUser = (TOKEN_USER *) malloc(tkSize);
  1532. if (!tkUser) {
  1533. return E_OUTOFMEMORY;
  1534. }
  1535. // Now make the real call
  1536. if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize))
  1537. {
  1538. sidLength = GetLengthSid(tkUser->User.Sid);
  1539. *ppSid = (PSID) malloc(sidLength);
  1540. memcpy(*ppSid, tkUser->User.Sid, sidLength);
  1541. CloseHandle(tkHandle);
  1542. free(tkUser);
  1543. return S_OK;
  1544. }
  1545. else
  1546. {
  1547. free(tkUser);
  1548. return HRESULT_FROM_WIN32(GetLastError());
  1549. }
  1550. }
  1551. return HRESULT_FROM_WIN32(GetLastError());
  1552. }
  1553. HRESULT CSecurityDescriptor::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid)
  1554. {
  1555. HRESULT hr;
  1556. LPTSTR pszRefDomain = NULL;
  1557. DWORD dwDomainSize = 0;
  1558. DWORD dwSidSize = 0;
  1559. SID_NAME_USE snu;
  1560. // Call to get size info for alloc
  1561. LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu);
  1562. hr = GetLastError();
  1563. if (hr != ERROR_INSUFFICIENT_BUFFER)
  1564. return HRESULT_FROM_WIN32(hr);
  1565. ATLTRY(pszRefDomain = new TCHAR[dwDomainSize]);
  1566. if (pszRefDomain == NULL)
  1567. return E_OUTOFMEMORY;
  1568. *ppSid = (PSID) malloc(dwSidSize);
  1569. if (*ppSid != NULL)
  1570. {
  1571. if (!LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu))
  1572. {
  1573. free(*ppSid);
  1574. *ppSid = NULL;
  1575. delete[] pszRefDomain;
  1576. return HRESULT_FROM_WIN32(GetLastError());
  1577. }
  1578. delete[] pszRefDomain;
  1579. return S_OK;
  1580. }
  1581. delete[] pszRefDomain;
  1582. return E_OUTOFMEMORY;
  1583. }
  1584. HRESULT CSecurityDescriptor::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD)
  1585. {
  1586. PACL pDACL = NULL;
  1587. PACL pSACL = NULL;
  1588. BOOL bDACLPresent, bSACLPresent;
  1589. BOOL bDefaulted;
  1590. PACL m_pDACL = NULL;
  1591. ACCESS_ALLOWED_ACE* pACE;
  1592. HRESULT hr;
  1593. PSID pUserSid;
  1594. PSID pGroupSid;
  1595. hr = Initialize();
  1596. if(FAILED(hr))
  1597. return hr;
  1598. // get the existing DACL.
  1599. if (!GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted))
  1600. goto failed;
  1601. if (bDACLPresent)
  1602. {
  1603. if (pDACL)
  1604. {
  1605. // allocate new DACL.
  1606. m_pDACL = (PACL) malloc(pDACL->AclSize);
  1607. if (!m_pDACL)
  1608. goto failed;
  1609. // initialize the DACL
  1610. if (!InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION))
  1611. goto failed;
  1612. // copy the ACES
  1613. for (int i = 0; i < pDACL->AceCount; i++)
  1614. {
  1615. if (!GetAce(pDACL, i, (void **)&pACE))
  1616. goto failed;
  1617. if (!AddAccessAllowedAce(m_pDACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
  1618. goto failed;
  1619. }
  1620. if (!IsValidAcl(m_pDACL))
  1621. goto failed;
  1622. }
  1623. // set the DACL
  1624. if (!SetSecurityDescriptorDacl(m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, bDefaulted))
  1625. goto failed;
  1626. }
  1627. // get the existing SACL.
  1628. if (!GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted))
  1629. goto failed;
  1630. if (bSACLPresent)
  1631. {
  1632. if (pSACL)
  1633. {
  1634. // allocate new SACL.
  1635. m_pSACL = (PACL) malloc(pSACL->AclSize);
  1636. if (!m_pSACL)
  1637. goto failed;
  1638. // initialize the SACL
  1639. if (!InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION))
  1640. goto failed;
  1641. // copy the ACES
  1642. for (int i = 0; i < pSACL->AceCount; i++)
  1643. {
  1644. if (!GetAce(pSACL, i, (void **)&pACE))
  1645. goto failed;
  1646. if (!AddAccessAllowedAce(m_pSACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart)))
  1647. goto failed;
  1648. }
  1649. if (!IsValidAcl(m_pSACL))
  1650. goto failed;
  1651. }
  1652. // set the SACL
  1653. if (!SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, bDefaulted))
  1654. goto failed;
  1655. }
  1656. if (!GetSecurityDescriptorOwner(m_pSD, &pUserSid, &bDefaulted))
  1657. goto failed;
  1658. if (FAILED(SetOwner(pUserSid, bDefaulted)))
  1659. goto failed;
  1660. if (!GetSecurityDescriptorGroup(m_pSD, &pGroupSid, &bDefaulted))
  1661. goto failed;
  1662. if (FAILED(SetGroup(pGroupSid, bDefaulted)))
  1663. goto failed;
  1664. if (!IsValidSecurityDescriptor(m_pSD))
  1665. goto failed;
  1666. return hr;
  1667. failed:
  1668. if (m_pDACL)
  1669. free(m_pDACL);
  1670. if (m_pSD)
  1671. free(m_pSD);
  1672. return E_UNEXPECTED;
  1673. }
  1674. HRESULT CSecurityDescriptor::AttachObject(HANDLE hObject)
  1675. {
  1676. HRESULT hr;
  1677. DWORD dwSize = 0;
  1678. PSECURITY_DESCRIPTOR pSD = NULL;
  1679. GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  1680. DACL_SECURITY_INFORMATION, pSD, 0, &dwSize);
  1681. hr = GetLastError();
  1682. if (hr != ERROR_INSUFFICIENT_BUFFER)
  1683. return HRESULT_FROM_WIN32(hr);
  1684. pSD = (PSECURITY_DESCRIPTOR) malloc(dwSize);
  1685. if (!pSD) {
  1686. return E_OUTOFMEMORY;
  1687. }
  1688. if (!GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  1689. DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize))
  1690. {
  1691. hr = HRESULT_FROM_WIN32(GetLastError());
  1692. free(pSD);
  1693. return hr;
  1694. }
  1695. hr = Attach(pSD);
  1696. free(pSD);
  1697. return hr;
  1698. }
  1699. HRESULT CSecurityDescriptor::CopyACL(PACL pDest, PACL pSrc)
  1700. {
  1701. ACL_SIZE_INFORMATION aclSizeInfo;
  1702. LPVOID pAce;
  1703. ACE_HEADER *aceHeader;
  1704. if (pSrc == NULL)
  1705. return S_OK;
  1706. if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
  1707. return HRESULT_FROM_WIN32(GetLastError());
  1708. // Copy all of the ACEs to the new ACL
  1709. for (UINT i = 0; i < aclSizeInfo.AceCount; i++)
  1710. {
  1711. if (!GetAce(pSrc, i, &pAce))
  1712. return HRESULT_FROM_WIN32(GetLastError());
  1713. aceHeader = (ACE_HEADER *) pAce;
  1714. if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize))
  1715. return HRESULT_FROM_WIN32(GetLastError());
  1716. }
  1717. return S_OK;
  1718. }
  1719. HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1720. {
  1721. ACL_SIZE_INFORMATION aclSizeInfo;
  1722. int aclSize;
  1723. DWORD returnValue;
  1724. PSID principalSID;
  1725. PACL oldACL, newACL = NULL;
  1726. oldACL = *ppAcl;
  1727. returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  1728. if (FAILED(returnValue))
  1729. return returnValue;
  1730. aclSizeInfo.AclBytesInUse = 0;
  1731. if (*ppAcl != NULL)
  1732. GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  1733. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  1734. ATLTRY(newACL = (PACL) new BYTE[aclSize]);
  1735. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  1736. {
  1737. free(principalSID);
  1738. return HRESULT_FROM_WIN32(GetLastError());
  1739. }
  1740. if (!AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  1741. {
  1742. free(principalSID);
  1743. return HRESULT_FROM_WIN32(GetLastError());
  1744. }
  1745. returnValue = CopyACL(newACL, oldACL);
  1746. if (FAILED(returnValue))
  1747. {
  1748. free(principalSID);
  1749. return returnValue;
  1750. }
  1751. *ppAcl = newACL;
  1752. if (oldACL != NULL)
  1753. free(oldACL);
  1754. free(principalSID);
  1755. return S_OK;
  1756. }
  1757. HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1758. {
  1759. ACL_SIZE_INFORMATION aclSizeInfo;
  1760. int aclSize;
  1761. DWORD returnValue;
  1762. PSID principalSID;
  1763. PACL oldACL, newACL = NULL;
  1764. oldACL = *ppAcl;
  1765. returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  1766. if (FAILED(returnValue))
  1767. return returnValue;
  1768. aclSizeInfo.AclBytesInUse = 0;
  1769. if (*ppAcl != NULL)
  1770. GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  1771. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(principalSID) - sizeof(DWORD);
  1772. ATLTRY(newACL = (PACL) new BYTE[aclSize]);
  1773. if (!InitializeAcl(newACL, aclSize, ACL_REVISION))
  1774. {
  1775. free(principalSID);
  1776. return HRESULT_FROM_WIN32(GetLastError());
  1777. }
  1778. returnValue = CopyACL(newACL, oldACL);
  1779. if (FAILED(returnValue))
  1780. {
  1781. free(principalSID);
  1782. return returnValue;
  1783. }
  1784. if (!AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, principalSID))
  1785. {
  1786. free(principalSID);
  1787. return HRESULT_FROM_WIN32(GetLastError());
  1788. }
  1789. *ppAcl = newACL;
  1790. if (oldACL != NULL)
  1791. free(oldACL);
  1792. free(principalSID);
  1793. return S_OK;
  1794. }
  1795. HRESULT CSecurityDescriptor::RemovePrincipalFromACL(PACL pAcl, LPCTSTR pszPrincipal)
  1796. {
  1797. ACL_SIZE_INFORMATION aclSizeInfo;
  1798. ULONG i;
  1799. LPVOID ace;
  1800. ACCESS_ALLOWED_ACE *accessAllowedAce;
  1801. ACCESS_DENIED_ACE *accessDeniedAce;
  1802. SYSTEM_AUDIT_ACE *systemAuditAce;
  1803. PSID principalSID;
  1804. DWORD returnValue;
  1805. ACE_HEADER *aceHeader;
  1806. returnValue = GetPrincipalSID(pszPrincipal, &principalSID);
  1807. if (FAILED(returnValue))
  1808. return returnValue;
  1809. GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation);
  1810. for (i = 0; i < aclSizeInfo.AceCount; i++)
  1811. {
  1812. if (!GetAce(pAcl, i, &ace))
  1813. {
  1814. free(principalSID);
  1815. return HRESULT_FROM_WIN32(GetLastError());
  1816. }
  1817. aceHeader = (ACE_HEADER *) ace;
  1818. if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  1819. {
  1820. accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
  1821. if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart))
  1822. {
  1823. DeleteAce(pAcl, i);
  1824. free(principalSID);
  1825. return S_OK;
  1826. }
  1827. } else
  1828. if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  1829. {
  1830. accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
  1831. if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart))
  1832. {
  1833. DeleteAce(pAcl, i);
  1834. free(principalSID);
  1835. return S_OK;
  1836. }
  1837. } else
  1838. if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
  1839. {
  1840. systemAuditAce = (SYSTEM_AUDIT_ACE *) ace;
  1841. if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart))
  1842. {
  1843. DeleteAce(pAcl, i);
  1844. free(principalSID);
  1845. return S_OK;
  1846. }
  1847. }
  1848. }
  1849. free(principalSID);
  1850. return S_OK;
  1851. }
  1852. HRESULT CSecurityDescriptor::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken)
  1853. {
  1854. HRESULT hr;
  1855. TOKEN_PRIVILEGES tpPrevious;
  1856. TOKEN_PRIVILEGES tp;
  1857. DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
  1858. LUID luid;
  1859. // if no token specified open process token
  1860. if (hToken == 0)
  1861. {
  1862. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  1863. {
  1864. hr = HRESULT_FROM_WIN32(GetLastError());
  1865. _ASSERTE(FALSE);
  1866. return hr;
  1867. }
  1868. }
  1869. if (!LookupPrivilegeValue(NULL, privilege, &luid ))
  1870. {
  1871. hr = HRESULT_FROM_WIN32(GetLastError());
  1872. _ASSERTE(FALSE);
  1873. return hr;
  1874. }
  1875. tp.PrivilegeCount = 1;
  1876. tp.Privileges[0].Luid = luid;
  1877. tp.Privileges[0].Attributes = 0;
  1878. if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious))
  1879. {
  1880. hr = HRESULT_FROM_WIN32(GetLastError());
  1881. _ASSERTE(FALSE);
  1882. return hr;
  1883. }
  1884. tpPrevious.PrivilegeCount = 1;
  1885. tpPrevious.Privileges[0].Luid = luid;
  1886. if (bEnable)
  1887. tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
  1888. else
  1889. tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
  1890. if (!AdjustTokenPrivileges(hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL))
  1891. {
  1892. hr = HRESULT_FROM_WIN32(GetLastError());
  1893. _ASSERTE(FALSE);
  1894. return hr;
  1895. }
  1896. return S_OK;
  1897. }
  1898. #endif //_ATL_NO_SECURITY
  1899. #endif //__ATLCOM_H__
  1900. #ifdef _DEBUG
  1901. void _cdecl AtlTrace(LPCTSTR lpszFormat, ...)
  1902. {
  1903. va_list args;
  1904. va_start(args, lpszFormat);
  1905. int nBuf;
  1906. TCHAR szBuffer[512];
  1907. nBuf = _vstprintf(szBuffer, lpszFormat, args);
  1908. _ASSERTE(nBuf < sizeof(szBuffer));
  1909. OutputDebugString(szBuffer);
  1910. va_end(args);
  1911. }
  1912. #endif
  1913. #ifndef ATL_NO_NAMESPACE
  1914. }; //namespace ATL
  1915. #endif
  1916. ///////////////////////////////////////////////////////////////////////////////
  1917. //All Global stuff goes below this line
  1918. ///////////////////////////////////////////////////////////////////////////////
  1919. /////////////////////////////////////////////////////////////////////////////
  1920. // Minimize CRT
  1921. // Specify DllMain as EntryPoint
  1922. // Turn off exception handling
  1923. // Define _ATL_MIN_CRT
  1924. #ifdef _ATL_MIN_CRT
  1925. /////////////////////////////////////////////////////////////////////////////
  1926. // Startup Code
  1927. #if defined(_WINDLL) || defined(_USRDLL)
  1928. // Declare DllMain
  1929. extern "C" BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved);
  1930. extern "C" BOOL WINAPI _DllMainCRTStartup(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
  1931. {
  1932. return DllMain(hDllHandle, dwReason, lpReserved);
  1933. }
  1934. #else
  1935. // wWinMain is not defined in winbase.h.
  1936. extern "C" int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd);
  1937. #define SPACECHAR _T(' ')
  1938. #define DQUOTECHAR _T('\"')
  1939. #ifdef _UNICODE
  1940. extern "C" void wWinMainCRTStartup()
  1941. #else // _UNICODE
  1942. extern "C" void WinMainCRTStartup()
  1943. #endif // _UNICODE
  1944. {
  1945. LPTSTR lpszCommandLine = ::GetCommandLine();
  1946. if(lpszCommandLine == NULL)
  1947. ::ExitProcess((UINT)-1);
  1948. // Skip past program name (first token in command line).
  1949. // Check for and handle quoted program name.
  1950. if(*lpszCommandLine == DQUOTECHAR)
  1951. {
  1952. // Scan, and skip over, subsequent characters until
  1953. // another double-quote or a null is encountered.
  1954. do
  1955. {
  1956. lpszCommandLine = ::CharNext(lpszCommandLine);
  1957. }
  1958. while((*lpszCommandLine != DQUOTECHAR) && (*lpszCommandLine != _T('\0')));
  1959. // If we stopped on a double-quote (usual case), skip over it.
  1960. if(*lpszCommandLine == DQUOTECHAR)
  1961. lpszCommandLine = ::CharNext(lpszCommandLine);
  1962. }
  1963. else
  1964. {
  1965. while(*lpszCommandLine > SPACECHAR)
  1966. lpszCommandLine = ::CharNext(lpszCommandLine);
  1967. }
  1968. // Skip past any white space preceeding the second token.
  1969. while(*lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
  1970. lpszCommandLine = ::CharNext(lpszCommandLine);
  1971. STARTUPINFO StartupInfo;
  1972. StartupInfo.dwFlags = 0;
  1973. ::GetStartupInfo(&StartupInfo);
  1974. int nRet = _tWinMain(::GetModuleHandle(NULL), NULL, lpszCommandLine,
  1975. (StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ?
  1976. StartupInfo.wShowWindow : SW_SHOWDEFAULT);
  1977. ::ExitProcess((UINT)nRet);
  1978. }
  1979. #endif // defined(_WINDLL) | defined(_USRDLL)
  1980. /////////////////////////////////////////////////////////////////////////////
  1981. // Heap Allocation
  1982. #ifndef _DEBUG
  1983. #ifndef _MERGE_PROXYSTUB
  1984. //rpcproxy.h does the same thing as this
  1985. int __cdecl _purecall()
  1986. {
  1987. DebugBreak();
  1988. return 0;
  1989. }
  1990. #endif
  1991. #if !defined(_M_ALPHA) && !defined(_M_PPC)
  1992. //RISC always initializes floating point and always defines _fltused
  1993. extern "C" const int _fltused = 0;
  1994. #endif
  1995. void* __cdecl malloc(size_t n)
  1996. {
  1997. if (_Module.m_hHeap == NULL)
  1998. {
  1999. _Module.m_hHeap = HeapCreate(0, 0, 0);
  2000. if (_Module.m_hHeap == NULL)
  2001. return NULL;
  2002. }
  2003. _ASSERTE(_Module.m_hHeap != NULL);
  2004. #ifdef _MALLOC_ZEROINIT
  2005. return HeapAlloc(_Module.m_hHeap, HEAP_ZERO_MEMORY, n);
  2006. #else
  2007. return HeapAlloc(_Module.m_hHeap, 0, n);
  2008. #endif
  2009. }
  2010. void* __cdecl calloc(size_t n, size_t s)
  2011. {
  2012. return malloc(n * s);
  2013. }
  2014. void* __cdecl realloc(void* p, size_t n)
  2015. {
  2016. _ASSERTE(_Module.m_hHeap != NULL);
  2017. #ifdef _MALLOC_ZEROINIT
  2018. return (p == NULL) ? malloc(n) : HeapReAlloc(_Module.m_hHeap, HEAP_ZERO_MEMORY, p, n);
  2019. #else
  2020. return (p == NULL) ? malloc(n) : HeapReAlloc(_Module.m_hHeap, 0, p, n);
  2021. #endif
  2022. }
  2023. void __cdecl free(void* p)
  2024. {
  2025. _ASSERTE(_Module.m_hHeap != NULL);
  2026. HeapFree(_Module.m_hHeap, 0, p);
  2027. }
  2028. void* __cdecl operator new(size_t n)
  2029. {
  2030. return malloc(n);
  2031. }
  2032. void __cdecl operator delete(void* p)
  2033. {
  2034. free(p);
  2035. }
  2036. #endif //_DEBUG
  2037. #endif //_ATL_MIN_CRT
  2038. #ifndef _ATL_DLL
  2039. #ifndef ATL_NO_NAMESPACE
  2040. #ifndef _ATL_DLL_IMPL
  2041. namespace ATL
  2042. {
  2043. #endif
  2044. #endif
  2045. /////////////////////////////////////////////////////////////////////////////
  2046. // statics
  2047. static UINT WINAPI AtlGetDirLen(LPCOLESTR lpszPathName)
  2048. {
  2049. _ASSERTE(lpszPathName != NULL);
  2050. // always capture the complete file name including extension (if present)
  2051. LPCOLESTR lpszTemp = lpszPathName;
  2052. for (LPCOLESTR lpsz = lpszPathName; *lpsz != NULL; )
  2053. {
  2054. LPCOLESTR lp = CharNextO(lpsz);
  2055. // remember last directory/drive separator
  2056. if (*lpsz == OLESTR('\\') || *lpsz == OLESTR('/') || *lpsz == OLESTR(':'))
  2057. lpszTemp = lp;
  2058. lpsz = lp;
  2059. }
  2060. return UINT(lpszTemp-lpszPathName);
  2061. }
  2062. /////////////////////////////////////////////////////////////////////////////
  2063. // QI support
  2064. ATLAPI AtlInternalQueryInterface(void* pThis,
  2065. const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
  2066. {
  2067. _ASSERTE(pThis != NULL);
  2068. // First entry in the com map should be a simple map entry
  2069. _ASSERTE(pEntries->pFunc == _ATL_SIMPLEMAPENTRY);
  2070. if (ppvObject == NULL)
  2071. return E_POINTER;
  2072. *ppvObject = NULL;
  2073. if (InlineIsEqualUnknown(iid)) // use first interface
  2074. {
  2075. IUnknown* pUnk = (IUnknown*)((LONG_PTR)pThis+pEntries->dw);
  2076. pUnk->AddRef();
  2077. *ppvObject = pUnk;
  2078. return S_OK;
  2079. }
  2080. while (pEntries->pFunc != NULL)
  2081. {
  2082. BOOL bBlind = (pEntries->piid == NULL);
  2083. if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid))
  2084. {
  2085. if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset
  2086. {
  2087. _ASSERTE(!bBlind);
  2088. IUnknown* pUnk = (IUnknown*)((LONG_PTR)pThis+pEntries->dw);
  2089. pUnk->AddRef();
  2090. *ppvObject = pUnk;
  2091. return S_OK;
  2092. }
  2093. else //actual function call
  2094. {
  2095. HRESULT hRes = pEntries->pFunc(pThis,
  2096. iid, ppvObject, pEntries->dw);
  2097. if (hRes == S_OK || (!bBlind && FAILED(hRes)))
  2098. return hRes;
  2099. }
  2100. }
  2101. pEntries++;
  2102. }
  2103. return E_NOINTERFACE;
  2104. }
  2105. /////////////////////////////////////////////////////////////////////////////
  2106. // Smart Pointer helpers
  2107. ATLAPI_(IUnknown*) AtlComPtrAssign(IUnknown** pp, IUnknown* lp)
  2108. {
  2109. if (lp != NULL)
  2110. lp->AddRef();
  2111. if (*pp)
  2112. (*pp)->Release();
  2113. *pp = lp;
  2114. return lp;
  2115. }
  2116. ATLAPI_(IUnknown*) AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid)
  2117. {
  2118. IUnknown* pTemp = *pp;
  2119. *pp = NULL;
  2120. if (lp != NULL)
  2121. lp->QueryInterface(riid, (void**)pp);
  2122. if (pTemp)
  2123. pTemp->Release();
  2124. return *pp;
  2125. }
  2126. /////////////////////////////////////////////////////////////////////////////
  2127. // Inproc Marshaling helpers
  2128. ATLAPI AtlFreeMarshalStream(IStream* pStream)
  2129. {
  2130. if (pStream != NULL)
  2131. {
  2132. CoReleaseMarshalData(pStream);
  2133. pStream->Release();
  2134. }
  2135. return S_OK;
  2136. }
  2137. ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream)
  2138. {
  2139. HRESULT hRes = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
  2140. if (SUCCEEDED(hRes))
  2141. {
  2142. hRes = CoMarshalInterface(*ppStream, iid,
  2143. pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
  2144. if (FAILED(hRes))
  2145. {
  2146. (*ppStream)->Release();
  2147. *ppStream = NULL;
  2148. }
  2149. }
  2150. return hRes;
  2151. }
  2152. ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk)
  2153. {
  2154. *ppUnk = NULL;
  2155. HRESULT hRes = E_INVALIDARG;
  2156. if (pStream != NULL)
  2157. {
  2158. LARGE_INTEGER l;
  2159. l.QuadPart = 0;
  2160. pStream->Seek(l, STREAM_SEEK_SET, NULL);
  2161. hRes = CoUnmarshalInterface(pStream, iid, (void**)ppUnk);
  2162. }
  2163. return hRes;
  2164. }
  2165. ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent)
  2166. {
  2167. DWORD dwRet;
  2168. MSG msg;
  2169. while(1)
  2170. {
  2171. dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT);
  2172. if (dwRet == WAIT_OBJECT_0)
  2173. return TRUE; // The event was signaled
  2174. if (dwRet != WAIT_OBJECT_0 + 1)
  2175. break; // Something else happened
  2176. // There is one or more window message available. Dispatch them
  2177. while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
  2178. {
  2179. TranslateMessage(&msg);
  2180. DispatchMessage(&msg);
  2181. if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
  2182. return TRUE; // Event is now signaled.
  2183. }
  2184. }
  2185. return FALSE;
  2186. }
  2187. /////////////////////////////////////////////////////////////////////////////
  2188. // Connection Point Helpers
  2189. ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw)
  2190. {
  2191. CComPtr<IConnectionPointContainer> pCPC;
  2192. CComPtr<IConnectionPoint> pCP;
  2193. HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
  2194. if (SUCCEEDED(hRes))
  2195. hRes = pCPC->FindConnectionPoint(iid, &pCP);
  2196. if (SUCCEEDED(hRes))
  2197. hRes = pCP->Advise(pUnk, pdw);
  2198. return hRes;
  2199. }
  2200. ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw)
  2201. {
  2202. CComPtr<IConnectionPointContainer> pCPC;
  2203. CComPtr<IConnectionPoint> pCP;
  2204. HRESULT hRes = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
  2205. if (SUCCEEDED(hRes))
  2206. hRes = pCPC->FindConnectionPoint(iid, &pCP);
  2207. if (SUCCEEDED(hRes))
  2208. hRes = pCP->Unadvise(dw);
  2209. return hRes;
  2210. }
  2211. /////////////////////////////////////////////////////////////////////////////
  2212. // IDispatch Error handling
  2213. ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
  2214. LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst)
  2215. {
  2216. USES_CONVERSION;
  2217. TCHAR szDesc[1024];
  2218. szDesc[0] = NULL;
  2219. // For a valid HRESULT the id should be in the range [0x0200, 0xffff]
  2220. if (ULONG_PTR( lpszDesc ) < 0x10000) // id
  2221. {
  2222. UINT nID = LOWORD((ULONG_PTR)lpszDesc);
  2223. _ASSERTE((nID >= 0x0200 && nID <= 0xffff) || hRes != 0);
  2224. if (LoadString(hInst, nID, szDesc, 1024) == 0)
  2225. {
  2226. _ASSERTE(FALSE);
  2227. lstrcpy(szDesc, _T("Unknown Error"));
  2228. }
  2229. lpszDesc = T2OLE(szDesc);
  2230. if (hRes == 0)
  2231. hRes = MAKE_HRESULT(3, FACILITY_ITF, nID);
  2232. }
  2233. CComPtr<ICreateErrorInfo> pICEI;
  2234. if (SUCCEEDED(CreateErrorInfo(&pICEI)))
  2235. {
  2236. CComPtr<IErrorInfo> pErrorInfo;
  2237. pICEI->SetGUID(iid);
  2238. LPOLESTR lpsz;
  2239. ProgIDFromCLSID(clsid, &lpsz);
  2240. if (lpsz != NULL)
  2241. pICEI->SetSource(lpsz);
  2242. if (dwHelpID != 0 && lpszHelpFile != NULL)
  2243. {
  2244. pICEI->SetHelpContext(dwHelpID);
  2245. pICEI->SetHelpFile(const_cast<LPOLESTR>(lpszHelpFile));
  2246. }
  2247. CoTaskMemFree(lpsz);
  2248. pICEI->SetDescription((LPOLESTR)lpszDesc);
  2249. if (SUCCEEDED(pICEI->QueryInterface(IID_IErrorInfo, (void**)&pErrorInfo)))
  2250. SetErrorInfo(0, pErrorInfo);
  2251. }
  2252. //#ifdef _DEBUG
  2253. // USES_CONVERSION;
  2254. // ATLTRACE(_T("AtlReportError: Description=\"%s\" returning %x\n"), OLE2CT(lpszDesc), hRes);
  2255. //#endif
  2256. return (hRes == 0) ? DISP_E_EXCEPTION : hRes;
  2257. }
  2258. /////////////////////////////////////////////////////////////////////////////
  2259. // Module
  2260. //Although these functions are big, they are only used once in a module
  2261. //so we should make them inline.
  2262. ATLAPI AtlModuleInit(_ATL_MODULE* pM, _ATL_OBJMAP_ENTRY* p, HINSTANCE h)
  2263. {
  2264. _ASSERTE(pM != NULL);
  2265. if (pM == NULL)
  2266. return E_INVALIDARG;
  2267. if (pM->cbSize < sizeof(_ATL_MODULE))
  2268. return E_INVALIDARG;
  2269. pM->m_pObjMap = p;
  2270. pM->m_hInst = pM->m_hInstTypeLib = pM->m_hInstResource = h;
  2271. pM->m_nLockCnt=0L;
  2272. pM->m_hHeap = NULL;
  2273. InitializeCriticalSection(&pM->m_csTypeInfoHolder);
  2274. InitializeCriticalSection(&pM->m_csWindowCreate);
  2275. InitializeCriticalSection(&pM->m_csObjMap);
  2276. return S_OK;
  2277. }
  2278. ATLAPI AtlModuleRegisterClassObjects(_ATL_MODULE* pM, DWORD dwClsContext, DWORD dwFlags)
  2279. {
  2280. _ASSERTE(pM != NULL);
  2281. if (pM == NULL)
  2282. return E_INVALIDARG;
  2283. _ASSERTE(pM->m_pObjMap != NULL);
  2284. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2285. HRESULT hRes = S_OK;
  2286. while (pEntry->pclsid != NULL && hRes == S_OK)
  2287. {
  2288. hRes = pEntry->RegisterClassObject(dwClsContext, dwFlags);
  2289. pEntry++;
  2290. }
  2291. return hRes;
  2292. }
  2293. ATLAPI AtlModuleRevokeClassObjects(_ATL_MODULE* pM)
  2294. {
  2295. _ASSERTE(pM != NULL);
  2296. if (pM == NULL)
  2297. return E_INVALIDARG;
  2298. _ASSERTE(pM->m_pObjMap != NULL);
  2299. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2300. HRESULT hRes = S_OK;
  2301. while (pEntry->pclsid != NULL && hRes == S_OK)
  2302. {
  2303. hRes = pEntry->RevokeClassObject();
  2304. pEntry++;
  2305. }
  2306. return hRes;
  2307. }
  2308. ATLAPI AtlModuleGetClassObject(_ATL_MODULE* pM, REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  2309. {
  2310. _ASSERTE(pM != NULL);
  2311. if (pM == NULL)
  2312. return E_INVALIDARG;
  2313. _ASSERTE(pM->m_pObjMap != NULL);
  2314. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2315. HRESULT hRes = S_OK;
  2316. if (ppv == NULL)
  2317. return E_POINTER;
  2318. while (pEntry->pclsid != NULL)
  2319. {
  2320. if (InlineIsEqualGUID(rclsid, *pEntry->pclsid))
  2321. {
  2322. if (pEntry->pCF == NULL)
  2323. {
  2324. EnterCriticalSection(&pM->m_csObjMap);
  2325. if (pEntry->pCF == NULL)
  2326. hRes = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, IID_IUnknown, (LPVOID*)&pEntry->pCF);
  2327. LeaveCriticalSection(&pM->m_csObjMap);
  2328. }
  2329. if (pEntry->pCF != NULL)
  2330. hRes = pEntry->pCF->QueryInterface(riid, ppv);
  2331. break;
  2332. }
  2333. pEntry++;
  2334. }
  2335. if (*ppv == NULL && hRes == S_OK)
  2336. hRes = CLASS_E_CLASSNOTAVAILABLE;
  2337. return hRes;
  2338. }
  2339. ATLAPI AtlModuleTerm(_ATL_MODULE* pM)
  2340. {
  2341. _ASSERTE(pM != NULL);
  2342. if (pM == NULL)
  2343. return E_INVALIDARG;
  2344. _ASSERTE(pM->m_hInst != NULL);
  2345. if (pM->m_pObjMap != NULL)
  2346. {
  2347. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2348. while (pEntry->pclsid != NULL)
  2349. {
  2350. if (pEntry->pCF != NULL)
  2351. pEntry->pCF->Release();
  2352. pEntry->pCF = NULL;
  2353. pEntry++;
  2354. }
  2355. }
  2356. DeleteCriticalSection(&pM->m_csTypeInfoHolder);
  2357. DeleteCriticalSection(&pM->m_csWindowCreate);
  2358. DeleteCriticalSection(&pM->m_csObjMap);
  2359. if (pM->m_hHeap != NULL)
  2360. HeapDestroy(pM->m_hHeap);
  2361. return S_OK;
  2362. }
  2363. ATLAPI AtlModuleRegisterServer(_ATL_MODULE* pM, BOOL bRegTypeLib, const CLSID* pCLSID)
  2364. {
  2365. _ASSERTE(pM != NULL);
  2366. if (pM == NULL)
  2367. return E_INVALIDARG;
  2368. _ASSERTE(pM->m_hInst != NULL);
  2369. _ASSERTE(pM->m_pObjMap != NULL);
  2370. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2371. HRESULT hRes = S_OK;
  2372. for (;pEntry->pclsid != NULL; pEntry++)
  2373. {
  2374. if (pCLSID == NULL)
  2375. {
  2376. if (pEntry->pfnGetObjectDescription() != NULL)
  2377. continue;
  2378. }
  2379. else
  2380. {
  2381. if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
  2382. continue;
  2383. }
  2384. hRes = pEntry->pfnUpdateRegistry(TRUE);
  2385. if (FAILED(hRes))
  2386. break;
  2387. }
  2388. if (SUCCEEDED(hRes) && bRegTypeLib)
  2389. hRes = AtlModuleRegisterTypeLib(pM, 0);
  2390. return hRes;
  2391. }
  2392. ATLAPI AtlModuleUnregisterServer(_ATL_MODULE* pM, const CLSID* pCLSID)
  2393. {
  2394. _ASSERTE(pM != NULL);
  2395. if (pM == NULL)
  2396. return E_INVALIDARG;
  2397. _ASSERTE(pM->m_hInst != NULL);
  2398. _ASSERTE(pM->m_pObjMap != NULL);
  2399. _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  2400. for (;pEntry->pclsid != NULL; pEntry++)
  2401. {
  2402. if (pCLSID == NULL)
  2403. {
  2404. if (pEntry->pfnGetObjectDescription() != NULL)
  2405. continue;
  2406. }
  2407. else
  2408. {
  2409. if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
  2410. continue;
  2411. }
  2412. pEntry->pfnUpdateRegistry(FALSE); //unregister
  2413. }
  2414. return S_OK;
  2415. }
  2416. ATLAPI AtlModuleUpdateRegistryFromResourceD(_ATL_MODULE* pM, LPCOLESTR lpszRes,
  2417. BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg)
  2418. {
  2419. USES_CONVERSION;
  2420. _ASSERTE(pM != NULL);
  2421. HRESULT hRes = S_OK;
  2422. CComPtr<IRegistrar> p;
  2423. if (pReg != NULL)
  2424. p = pReg;
  2425. else
  2426. {
  2427. hRes = CoCreateInstance(CLSID_Registrar, NULL,
  2428. CLSCTX_INPROC_SERVER, IID_IRegistrar, (void**)&p);
  2429. }
  2430. if (SUCCEEDED(hRes))
  2431. {
  2432. TCHAR szModule[_MAX_PATH];
  2433. GetModuleFileName(pM->m_hInst, szModule, _MAX_PATH);
  2434. p->AddReplacement(OLESTR("Module"), T2OLE(szModule));
  2435. if (NULL != pMapEntries)
  2436. {
  2437. while (NULL != pMapEntries->szKey)
  2438. {
  2439. _ASSERTE(NULL != pMapEntries->szData);
  2440. p->AddReplacement((LPOLESTR)pMapEntries->szKey, (LPOLESTR)pMapEntries->szData);
  2441. pMapEntries++;
  2442. }
  2443. }
  2444. LPCOLESTR szType = OLESTR("REGISTRY");
  2445. GetModuleFileName(pM->m_hInstResource, szModule, _MAX_PATH);
  2446. LPOLESTR pszModule = T2OLE(szModule);
  2447. if (ULONG_PTR(lpszRes) < 0x10000)
  2448. {
  2449. if (bRegister)
  2450. hRes = p->ResourceRegister(pszModule, ((UINT)LOWORD((ULONG_PTR)lpszRes)), szType);
  2451. else
  2452. hRes = p->ResourceUnregister(pszModule, ((UINT)LOWORD((ULONG_PTR)lpszRes)), szType);
  2453. }
  2454. else
  2455. {
  2456. if (bRegister)
  2457. hRes = p->ResourceRegisterSz(pszModule, lpszRes, szType);
  2458. else
  2459. hRes = p->ResourceUnregisterSz(pszModule, lpszRes, szType);
  2460. }
  2461. }
  2462. return hRes;
  2463. }
  2464. /////////////////////////////////////////////////////////////////////////////
  2465. // TypeLib Support
  2466. ATLAPI AtlModuleRegisterTypeLib(_ATL_MODULE* pM, LPCOLESTR lpszIndex)
  2467. {
  2468. _ASSERTE(pM != NULL);
  2469. USES_CONVERSION;
  2470. _ASSERTE(pM->m_hInstTypeLib != NULL);
  2471. TCHAR szModule[_MAX_PATH+10];
  2472. OLECHAR szDir[_MAX_PATH];
  2473. DWORD rv;
  2474. rv = GetModuleFileName(pM->m_hInstTypeLib, szModule, _MAX_PATH);
  2475. if ( rv == 0 ) {
  2476. return HRESULT_FROM_WIN32(GetLastError());
  2477. }
  2478. if (lpszIndex != NULL)
  2479. lstrcat(szModule, OLE2CT(lpszIndex));
  2480. ITypeLib* pTypeLib;
  2481. LPOLESTR lpszModule = T2OLE(szModule);
  2482. HRESULT hr = LoadTypeLib(lpszModule, &pTypeLib);
  2483. if (!SUCCEEDED(hr))
  2484. {
  2485. // typelib not in module, try <module>.tlb instead
  2486. LPTSTR lpszExt = NULL;
  2487. LPTSTR lpsz;
  2488. for (lpsz = szModule; *lpsz != NULL; lpsz = CharNext(lpsz))
  2489. {
  2490. if (*lpsz == _T('.'))
  2491. lpszExt = lpsz;
  2492. }
  2493. if (lpszExt == NULL)
  2494. lpszExt = lpsz;
  2495. lstrcpy(lpszExt, _T(".tlb"));
  2496. lpszModule = T2OLE(szModule);
  2497. hr = LoadTypeLib(lpszModule, &pTypeLib);
  2498. }
  2499. if (SUCCEEDED(hr))
  2500. {
  2501. ocscpy(szDir, lpszModule);
  2502. szDir[AtlGetDirLen(szDir)] = 0;
  2503. hr = ::RegisterTypeLib(pTypeLib, lpszModule, szDir);
  2504. }
  2505. if (pTypeLib != NULL)
  2506. pTypeLib->Release();
  2507. return hr;
  2508. }
  2509. #ifndef ATL_NO_NAMESPACE
  2510. #ifndef _ATL_DLL_IMPL
  2511. }; //namespace ATL
  2512. #endif
  2513. #endif
  2514. #endif //!_ATL_DLL