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.

665 lines
17 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. membag.cpp
  5. Abstract:
  6. This module contains the implementation for the Server
  7. Extension Object Memory Property Bag.
  8. Author:
  9. Andy Jacobs (andyj@microsoft.com)
  10. Revision History:
  11. andyj 02/10/97 created
  12. andyj 02/12/97 Converted PropertyBag's to Dictonary's
  13. --*/
  14. // MEMBAG.cpp : Implementation of CSEOMemDictionary
  15. #include "stdafx.h"
  16. #include "seodefs.h"
  17. #include "String"
  18. #include "MEMBAG.h"
  19. HRESULT ResolveVariant(IEventPropertyBag *pBag, VARIANT *pvarPropDesired, CComVariant &varResult) {
  20. if (!pvarPropDesired) {
  21. return (E_POINTER);
  22. }
  23. varResult.Clear();
  24. HRESULT hrRes = S_OK;
  25. CComVariant varIndex; // Hold the I4 type
  26. switch (pvarPropDesired->vt & VT_TYPEMASK) {
  27. case VT_I1: case VT_I2: case VT_I4: case VT_I8:
  28. case VT_UI1: case VT_UI2: case VT_UI4: case VT_UI8:
  29. case VT_R4: case VT_R8:
  30. case VT_INT: case VT_UINT: // Any type of number
  31. hrRes = VariantChangeType(&varIndex, pvarPropDesired, 0, VT_I4);
  32. varResult.vt = VT_BSTR;
  33. varResult.bstrVal = NULL;
  34. if (SUCCEEDED(hrRes)) {
  35. hrRes = pBag->Name(varIndex.lVal, &varResult.bstrVal);
  36. }
  37. break;
  38. default: // Otherwise, convert to a string
  39. hrRes = VariantChangeType(&varResult, pvarPropDesired, 0, VT_BSTR);
  40. break;
  41. }
  42. return (hrRes);
  43. }
  44. HRESULT DataItem::AsVARIANT(VARIANT *pvarResult) const {
  45. if(!pvarResult) return E_POINTER;
  46. CComVariant varResult;
  47. if(IsDWORD()) varResult = (long) dword;
  48. else if(IsString()) varResult = pStr;
  49. else if(IsInterface()) varResult = pUnk;
  50. else varResult.Clear();
  51. return varResult.Detach(pvarResult);
  52. }
  53. DataItem::DataItem(VARIANT *pVar) {
  54. eType = Empty;
  55. if(!pVar) return;
  56. switch (pVar->vt) {
  57. case VT_EMPTY:
  58. // Already set to Empty
  59. break;
  60. case VT_I4:
  61. eType = DWord;
  62. dword = pVar->lVal;
  63. break;
  64. case VT_UNKNOWN:
  65. case VT_DISPATCH:
  66. eType = Interface;
  67. pUnk = pVar->punkVal;
  68. if(pUnk) pUnk->AddRef();
  69. break;
  70. default:
  71. eType = String;
  72. CComVariant vNew;
  73. vNew.ChangeType(VT_BSTR, pVar);
  74. iStringSize = SysStringLen(vNew.bstrVal) + 1;
  75. pStr = (LPSTR) MyMalloc(iStringSize * sizeof(WCHAR));
  76. if (pStr) {
  77. ATLW2AHELPER(pStr, vNew.bstrVal, iStringSize * sizeof(WCHAR));
  78. }
  79. break;
  80. }
  81. m_pszKey = NULL;
  82. }
  83. /////////////////////////////////////////////////////////////////////////////
  84. // CSEOMemDictionaryEnum
  85. class CSEOMemDictionaryEnum :
  86. public CComObjectRootEx<CComMultiThreadModelNoCS>,
  87. public IDispatchImpl<IEnumVARIANT, &IID_IEnumVARIANT, &LIBID_SEOLib>
  88. {
  89. public:
  90. CSEOMemDictionaryEnum() : m_iIterator(&m_dummylist) {}
  91. HRESULT FinalConstruct();
  92. void FinalRelease();
  93. HRESULT STDMETHODCALLTYPE Next(DWORD, LPVARIANT, LPDWORD);
  94. HRESULT STDMETHODCALLTYPE Skip(DWORD);
  95. HRESULT STDMETHODCALLTYPE Reset(void);
  96. HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **);
  97. // Not Exported
  98. HRESULT STDMETHODCALLTYPE Init(CSEOMemDictionary *, OurMap::iterator * = NULL);
  99. BEGIN_COM_MAP(CSEOMemDictionaryEnum)
  100. COM_INTERFACE_ENTRY(IEnumVARIANT)
  101. END_COM_MAP()
  102. private: // Data members
  103. OurMap::iterator m_iIterator;
  104. OurList m_dummylist;
  105. CSEOMemDictionary *m_dictionary;
  106. CShareLockNH *m_pLock;
  107. };
  108. HRESULT CSEOMemDictionaryEnum::FinalConstruct() {
  109. m_dictionary = NULL;
  110. return S_OK;
  111. }
  112. void CSEOMemDictionaryEnum::FinalRelease() {
  113. if(m_dictionary) {
  114. m_dictionary->m_lock.ShareUnlock();
  115. m_dictionary->GetControllingUnknown()->Release();
  116. }
  117. m_dictionary = NULL;
  118. }
  119. STDMETHODIMP CSEOMemDictionaryEnum::Init(CSEOMemDictionary *pDict, OurMap::iterator *omi) {
  120. if(m_dictionary) {
  121. m_dictionary->m_lock.ShareUnlock();
  122. m_dictionary->GetControllingUnknown()->Release();
  123. }
  124. m_dictionary = pDict;
  125. if(m_dictionary) {
  126. m_dictionary->GetControllingUnknown()->AddRef();
  127. m_dictionary->m_lock.ShareLock();
  128. if (omi) {
  129. m_iIterator = *omi;
  130. } else {
  131. m_iIterator.SetList(&(m_dictionary->m_mData));
  132. }
  133. }
  134. return S_OK;
  135. }
  136. STDMETHODIMP CSEOMemDictionaryEnum::Next(DWORD dwCount, LPVARIANT varDest,
  137. LPDWORD pdwResultParam) {
  138. if(!m_dictionary) return E_FAIL; // Hasn't been properly initialized
  139. if(!varDest) return E_POINTER;
  140. DWORD dwDummy = 0;
  141. LPDWORD pdwResult = (pdwResultParam ? pdwResultParam : &dwDummy);
  142. *pdwResult = 0; // Nothing done so far
  143. HRESULT hrRes = S_OK; // So far, so good
  144. _ASSERT(m_iIterator.GetHead() != &m_dummylist);
  145. while(SUCCEEDED(hrRes) && (*pdwResult < dwCount) &&
  146. (!(m_iIterator.AtEnd()))) {
  147. // Must have succeeded to get here, so OK to overwrite hrRes
  148. CComVariant varResult(m_iIterator.GetKey());
  149. if (varResult.vt == VT_ERROR) {
  150. if (hrRes == S_OK) hrRes = varResult.scode;
  151. while (*pdwResult) {
  152. --(*pdwResult);
  153. VariantClear(&varDest[*pdwResult]);
  154. }
  155. break;
  156. }
  157. VariantInit(&varDest[*pdwResult]);
  158. hrRes = varResult.Detach(&varDest[*pdwResult]);
  159. ++(*pdwResult); // Increment successful count for caller
  160. ++m_iIterator; // Point to the next one
  161. }
  162. return (FAILED(hrRes) ? hrRes : ((*pdwResult < dwCount) ? S_FALSE : S_OK));
  163. }
  164. STDMETHODIMP CSEOMemDictionaryEnum::Skip(DWORD dwCount) {
  165. _ASSERT(m_iIterator.GetHead() != &m_dummylist);
  166. for(DWORD i = 0; i < dwCount; ++i) ++m_iIterator;
  167. return ((!(m_iIterator.AtEnd())) ? S_OK : S_FALSE);
  168. }
  169. STDMETHODIMP CSEOMemDictionaryEnum::Reset(void) {
  170. _ASSERT(m_iIterator.GetHead() != &m_dummylist);
  171. m_iIterator.Front();
  172. return S_OK;
  173. }
  174. STDMETHODIMP CSEOMemDictionaryEnum::Clone(IEnumVARIANT **ppunkResult) {
  175. // Based on Samples\ATL\circcoll\objects.cpp (see also ATL\beeper\beeper.*
  176. if (ppunkResult == NULL) return E_POINTER;
  177. *ppunkResult = NULL;
  178. CComObject<CSEOMemDictionaryEnum> *p;
  179. HRESULT hrRes = CComObject<CSEOMemDictionaryEnum>::CreateInstance(&p);
  180. if (!SUCCEEDED(hrRes)) return (hrRes);
  181. hrRes = p->Init(m_dictionary, &m_iIterator);
  182. if (SUCCEEDED(hrRes)) hrRes = p->QueryInterface(IID_IEnumVARIANT, (void**)ppunkResult);
  183. if (FAILED(hrRes)) delete p;
  184. return hrRes;
  185. }
  186. /////////////////////////////////////////////////////////////////////////////
  187. // CSEOMemDictionary
  188. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::get_Item(
  189. /* [in] */ VARIANT __RPC_FAR *pvarName,
  190. /* [retval][out] */ VARIANT __RPC_FAR *pvarResult)
  191. {
  192. if(!pvarName || !pvarResult) return E_INVALIDARG;
  193. USES_CONVERSION; // Needed for W2A(), etc.
  194. CComVariant vNew;
  195. HRESULT hrRes = E_INVALIDARG;
  196. if(SUCCEEDED(vNew.ChangeType(VT_BSTR, pvarName))) {
  197. hrRes = GetVariantA(W2A(vNew.bstrVal), pvarResult);
  198. // Convert SEO_E_NOTPRESENT to VT_EMPTY
  199. if(hrRes == SEO_E_NOTPRESENT) {
  200. VariantClear(pvarResult);
  201. hrRes = S_OK;
  202. }
  203. }
  204. return hrRes;
  205. }
  206. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::put_Item(
  207. /* [in] */ VARIANT __RPC_FAR *pvarName,
  208. /* [in] */ VARIANT __RPC_FAR *pvarValue)
  209. {
  210. if(!pvarName || !pvarValue) return E_INVALIDARG;
  211. USES_CONVERSION; // Needed for W2A(), etc.
  212. CComVariant vNew;
  213. if(SUCCEEDED(vNew.ChangeType(VT_BSTR, pvarName))) {
  214. return SetVariantA(W2A(vNew.bstrVal), pvarValue);
  215. } else {
  216. return E_INVALIDARG;
  217. }
  218. }
  219. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::get__NewEnum(
  220. /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult)
  221. {
  222. // Based on Samples\ATL\circcoll\objects.cpp (see also ATL\beeper\beeper.*
  223. if (ppunkResult == NULL) return E_POINTER;
  224. *ppunkResult = NULL;
  225. CComObject<CSEOMemDictionaryEnum> *p;
  226. HRESULT hrRes = CComObject<CSEOMemDictionaryEnum>::CreateInstance(&p);
  227. if (!SUCCEEDED(hrRes)) return (hrRes);
  228. hrRes = p->Init(this);
  229. if (SUCCEEDED(hrRes)) hrRes = p->QueryInterface(IID_IEnumVARIANT, (void**)ppunkResult);
  230. if (FAILED(hrRes)) delete p;
  231. return hrRes;
  232. }
  233. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::GetVariantA(
  234. /* [in] */ LPCSTR pszName,
  235. /* [retval][out] */ VARIANT __RPC_FAR *pvarResult)
  236. {
  237. if(!pvarResult) return E_POINTER;
  238. OurMap::iterator theIterator = m_mData.find(pszName);
  239. VariantInit(pvarResult);
  240. if(theIterator.Found()) { // Found
  241. return (*theIterator)->AsVARIANT(pvarResult);
  242. } else {
  243. return SEO_E_NOTPRESENT; // Didn't find it
  244. }
  245. }
  246. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::GetVariantW(
  247. /* [in] */ LPCWSTR pszName,
  248. /* [retval][out] */ VARIANT __RPC_FAR *pvarResult)
  249. {
  250. if(!pvarResult) return E_INVALIDARG;
  251. USES_CONVERSION; // Needed for W2A(), etc.
  252. return GetVariantA(W2A(pszName), pvarResult);
  253. }
  254. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::SetVariantA(
  255. /* [in] */ LPCSTR pszName,
  256. /* [in] */ VARIANT __RPC_FAR *pvarValue)
  257. {
  258. if(!pvarValue) return E_POINTER;
  259. DataItem diItem(pvarValue);
  260. return Insert(pszName, diItem);
  261. }
  262. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::SetVariantW(
  263. /* [in] */ LPCWSTR pszName,
  264. /* [in] */ VARIANT __RPC_FAR *pvarValue)
  265. {
  266. if(!pvarValue) return E_POINTER;
  267. USES_CONVERSION; // Needed for W2A(), etc.
  268. DataItem diItem(pvarValue);
  269. return Insert(W2A(pszName), diItem);
  270. }
  271. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::GetStringA(
  272. /* [in] */ LPCSTR pszName,
  273. /* [out][in] */ DWORD __RPC_FAR *pchCount,
  274. /* [retval][size_is][out] */ LPSTR pszResult)
  275. {
  276. if(!pszResult) return E_POINTER;
  277. OurMap::iterator theIterator = m_mData.find(pszName);
  278. if(theIterator.Found()) { // Found
  279. if((*theIterator)->IsString()) {
  280. strncpy(pszResult, *(theIterator.GetData()), *pchCount);
  281. return (*pchCount >= (DWORD) (*theIterator)->StringSize()) ?
  282. S_OK : SEO_S_MOREDATA;
  283. }
  284. }
  285. return SEO_E_NOTPRESENT; // Didn't find it
  286. }
  287. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::GetStringW(
  288. /* [in] */ LPCWSTR pszName,
  289. /* [out][in] */ DWORD __RPC_FAR *pchCount,
  290. /* [retval][size_is][out] */ LPWSTR pszResult)
  291. {
  292. if(!pszResult) return E_POINTER;
  293. USES_CONVERSION;
  294. OurMap::iterator theIterator = m_mData.find(W2A(pszName));
  295. if(theIterator.Found()) { // Found
  296. if((*theIterator)->IsString()) {
  297. int iSize = min((int) *pchCount, (*theIterator)->StringSize());
  298. ATLA2WHELPER(pszResult, *(theIterator.GetData()), iSize);
  299. return (*pchCount >= (DWORD) (*theIterator)->StringSize()) ?
  300. S_OK : SEO_S_MOREDATA;
  301. }
  302. }
  303. return SEO_E_NOTPRESENT; // Didn't find it
  304. }
  305. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::SetStringA(
  306. /* [in] */ LPCSTR pszName,
  307. /* [in] */ DWORD chCount,
  308. /* [size_is][in] */ LPCSTR pszValue)
  309. {
  310. if(!pszValue) return E_POINTER;
  311. DataItem diItem(pszValue, chCount);
  312. return Insert(pszName, diItem);
  313. }
  314. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::SetStringW(
  315. /* [in] */ LPCWSTR pszName,
  316. /* [in] */ DWORD chCount,
  317. /* [size_is][in] */ LPCWSTR pszValue)
  318. {
  319. if(!pszValue) return E_POINTER;
  320. USES_CONVERSION;
  321. DataItem diItem(pszValue, chCount);
  322. return Insert(W2A(pszName), diItem);
  323. }
  324. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::GetDWordA(
  325. /* [in] */ LPCSTR pszName,
  326. /* [retval][out] */ DWORD __RPC_FAR *pdwResult)
  327. {
  328. if(!pdwResult) return E_POINTER;
  329. OurMap::iterator theIterator = m_mData.find(pszName);
  330. if(theIterator.Found()) { // Found
  331. if((*theIterator)->IsDWORD()) {
  332. *pdwResult = *(*theIterator);
  333. return S_OK;
  334. }
  335. }
  336. return SEO_E_NOTPRESENT; // Didn't find it
  337. }
  338. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::GetDWordW(
  339. /* [in] */ LPCWSTR pszName,
  340. /* [retval][out] */ DWORD __RPC_FAR *pdwResult)
  341. {
  342. USES_CONVERSION; // Needed for W2A(), etc.
  343. return GetDWordA(W2A(pszName), pdwResult);
  344. }
  345. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::SetDWordA(
  346. /* [in] */ LPCSTR pszName,
  347. /* [in] */ DWORD dwValue)
  348. {
  349. DataItem diItem(dwValue);
  350. return Insert(pszName, diItem);
  351. }
  352. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::SetDWordW(
  353. /* [in] */ LPCWSTR pszName,
  354. /* [in] */ DWORD dwValue)
  355. {
  356. USES_CONVERSION; // Needed for W2A(), etc.
  357. DataItem diItem(dwValue);
  358. return Insert(W2A(pszName), diItem);
  359. }
  360. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::GetInterfaceA(
  361. /* [in] */ LPCSTR pszName,
  362. /* [in] */ REFIID iidDesired,
  363. /* [retval][iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult)
  364. {
  365. if(!ppunkResult) return E_POINTER;
  366. OurMap::iterator theIterator = m_mData.find(pszName);
  367. if(theIterator.Found()) { // Found
  368. if((*theIterator)->IsInterface()) {
  369. LPUNKNOWN pObj = *(*theIterator);
  370. return pObj->QueryInterface(iidDesired, (LPVOID *) ppunkResult);
  371. }
  372. }
  373. return SEO_E_NOTPRESENT; // Didn't find it
  374. }
  375. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::GetInterfaceW(
  376. /* [in] */ LPCWSTR pszName,
  377. /* [in] */ REFIID iidDesired,
  378. /* [retval][iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkResult)
  379. {
  380. USES_CONVERSION; // Needed for W2A(), etc.
  381. return GetInterfaceA(W2A(pszName), iidDesired, ppunkResult);
  382. }
  383. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::SetInterfaceA(
  384. /* [in] */ LPCSTR pszName,
  385. /* [in] */ IUnknown __RPC_FAR *punkValue)
  386. {
  387. DataItem diItem(punkValue);
  388. return Insert(pszName, diItem);
  389. }
  390. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::SetInterfaceW(
  391. /* [in] */ LPCWSTR pszName,
  392. /* [in] */ IUnknown __RPC_FAR *punkValue)
  393. {
  394. USES_CONVERSION; // Needed for W2A(), etc.
  395. DataItem diItem(punkValue);
  396. return Insert(W2A(pszName), diItem);
  397. }
  398. HRESULT CSEOMemDictionary::FinalConstruct() {
  399. HRESULT hrRes;
  400. hrRes = CoCreateFreeThreadedMarshaler(GetControllingUnknown(),&m_pUnkMarshaler.p);
  401. _ASSERTE(!SUCCEEDED(hrRes)||m_pUnkMarshaler);
  402. return (SUCCEEDED(hrRes)?S_OK:hrRes);
  403. }
  404. void CSEOMemDictionary::FinalRelease() {
  405. m_pUnkMarshaler.Release();
  406. }
  407. // Four cases: (exists/not) x (Good/Empty item)
  408. HRESULT CSEOMemDictionary::Insert(LPCSTR pszName, const DataItem &diItem) {
  409. HRESULT hrRes = S_OK;
  410. m_lock.ExclusiveLock();
  411. OurMap::iterator iThisItem = m_mData.find(pszName);
  412. // If the item was found, remove it
  413. if(iThisItem.Found()) m_mData.erase(iThisItem);
  414. // If not an empty item, try to insert it
  415. if(!diItem.IsEmpty() &&
  416. !m_mData.insert(pszName, diItem)) {
  417. hrRes = E_FAIL;
  418. }
  419. m_lock.ExclusiveUnlock();
  420. return hrRes;
  421. }
  422. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) {
  423. HRESULT hrRes;
  424. VARTYPE vtType;
  425. if (!pszPropName || !pVar) {
  426. return (E_POINTER);
  427. }
  428. m_lock.ShareLock();
  429. vtType = pVar->vt;
  430. // VariantClear(pVar);
  431. hrRes = GetVariantW(pszPropName,pVar);
  432. if (SUCCEEDED(hrRes) && (vtType != VT_EMPTY)) {
  433. hrRes = VariantChangeType(pVar,pVar,0,vtType);
  434. }
  435. if (!SUCCEEDED(hrRes)) {
  436. VariantClear(pVar);
  437. }
  438. m_lock.ShareUnlock();
  439. return (hrRes);
  440. }
  441. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::Write(LPCOLESTR pszPropName, VARIANT *pVar) {
  442. return (SetVariantW(pszPropName,pVar));
  443. }
  444. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::Item(VARIANT *pvarPropDesired, VARIANT *pvarPropValue) {
  445. if (!pvarPropValue) {
  446. return (E_POINTER);
  447. }
  448. VariantInit(pvarPropValue);
  449. if (!pvarPropDesired) {
  450. return (E_POINTER);
  451. }
  452. CComVariant varResolved;
  453. HRESULT hrRes = ResolveVariant(this, pvarPropDesired, varResolved);
  454. if (S_OK != hrRes) { // Don't continue if S_FALSE, of FAILED(), etc.
  455. return (hrRes);
  456. }
  457. m_lock.ShareLock();
  458. hrRes = GetVariantW(varResolved.bstrVal, pvarPropValue);
  459. if (hrRes == SEO_E_NOTPRESENT) {
  460. m_lock.ShareUnlock();
  461. return (S_FALSE);
  462. }
  463. if (SUCCEEDED(hrRes)) {
  464. VariantChangeType(pvarPropValue,pvarPropValue,0,VT_DISPATCH);
  465. _ASSERTE(pvarPropValue->vt!=VT_UNKNOWN);
  466. }
  467. m_lock.ShareUnlock();
  468. return (hrRes);
  469. }
  470. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::Name(long lPropIndex, BSTR *pbstrPropName) {
  471. m_lock.ShareLock();
  472. OurMap::iterator iIterator = m_mData.begin();
  473. CComBSTR bstrName;
  474. if (!pbstrPropName) {
  475. m_lock.ShareUnlock();
  476. return (E_POINTER);
  477. }
  478. *pbstrPropName = NULL;
  479. if (lPropIndex < 1) {
  480. m_lock.ShareUnlock();
  481. return (S_FALSE);
  482. }
  483. while ((--lPropIndex > 0) && (!iIterator.AtEnd())) {
  484. ++iIterator;
  485. }
  486. if (iIterator.AtEnd()) {
  487. m_lock.ShareUnlock();
  488. return (S_FALSE);
  489. }
  490. bstrName = iIterator.GetKey();
  491. *pbstrPropName = bstrName.Detach();
  492. m_lock.ShareUnlock();
  493. return (S_OK);
  494. }
  495. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::Add(BSTR pszPropName, VARIANT *pvarPropValue) {
  496. return (SetVariantW(pszPropName,pvarPropValue));
  497. }
  498. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::Remove(VARIANT *pvarPropDesired) {
  499. CComVariant varResolved;
  500. HRESULT hrRes = ResolveVariant(this, pvarPropDesired, varResolved);
  501. if (S_OK != hrRes) { // Don't continue if S_FALSE, of FAILED(), etc.
  502. return (hrRes);
  503. }
  504. m_lock.ExclusiveLock();
  505. USES_CONVERSION;
  506. OurMap::iterator iThisItem = m_mData.find(W2A(varResolved.bstrVal));
  507. // If the item was found, remove it
  508. if(iThisItem.Found()) {
  509. m_mData.erase(iThisItem);
  510. } else {
  511. // _ASSERT(FALSE); // ResolveVariant should have returned something for find() to find
  512. hrRes = S_FALSE; // Not found
  513. }
  514. m_lock.ExclusiveUnlock();
  515. return hrRes;
  516. }
  517. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::get_Count(long *plCount) {
  518. if (!plCount) {
  519. return (E_POINTER);
  520. }
  521. m_lock.ShareLock();
  522. *plCount = m_mData.size();
  523. m_lock.ShareUnlock();
  524. return (S_OK);
  525. }
  526. /* Just use get__NewEnum from ISEODictionary
  527. HRESULT STDMETHODCALLTYPE CSEOMemDictionary::get__NewEnum(IUnknown **ppUnkEnum) {
  528. return (E_NOTIMPL);
  529. } */