Leaked source code of windows server 2003
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.

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