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.

695 lines
17 KiB

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Microsoft Windows, Copyright (C) Microsoft Corporation, 2000.
  3. File: OIDs.cpp
  4. Content: Implementation of COIDs.
  5. History: 06-15-2001 dsie created
  6. ------------------------------------------------------------------------------*/
  7. #include "StdAfx.h"
  8. #include "CAPICOM.h"
  9. #include "OIDs.h"
  10. ////////////////////////////////////////////////////////////////////////////////
  11. //
  12. // Exported functions.
  13. //
  14. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  15. Function : CreateOIDsObject
  16. Synopsis : Create and initialize an IOIDs collection object.
  17. Parameter: PCERT_ENHKEY_USAGE pUsages - Pointer to CERT_ENHKEY_USAGE used to
  18. initialize the OIDs collection.
  19. BOOL bCertPolicies - TRUE for certificate policies, else
  20. application policies is assumed.
  21. IOIDs ** ppIOIDs - Pointer to pointer to IOIDs to receive the
  22. interface pointer.
  23. Remark :
  24. ------------------------------------------------------------------------------*/
  25. HRESULT CreateOIDsObject (PCERT_ENHKEY_USAGE pUsages,
  26. BOOL bCertPolicies,
  27. IOIDs ** ppIOIDs)
  28. {
  29. HRESULT hr = S_OK;
  30. CComObject<COIDs> * pCOIDs = NULL;
  31. DebugTrace("Entering CreateOIDsObject().\n");
  32. //
  33. // Sanity check.
  34. //
  35. ATLASSERT(ppIOIDs);
  36. try
  37. {
  38. //
  39. // Create the object. Note that the ref count will still be 0
  40. // after the object is created.
  41. //
  42. if (FAILED(hr = CComObject<COIDs>::CreateInstance(&pCOIDs)))
  43. {
  44. DebugTrace("Error [%#x]: CComObject<COIDs>::CreateInstance() failed.\n", hr);
  45. goto ErrorExit;
  46. }
  47. //
  48. // Initialize object.
  49. //
  50. if (FAILED(hr = pCOIDs->Init(pUsages, bCertPolicies)))
  51. {
  52. DebugTrace("Error [%#x]: pCOIDs->Init() failed.\n", hr);
  53. goto ErrorExit;
  54. }
  55. //
  56. // Return IOIDs pointer to caller.
  57. //
  58. if (FAILED(hr = pCOIDs->QueryInterface(ppIOIDs)))
  59. {
  60. DebugTrace("Error [%#x]: pCOIDs->QueryInterface() failed.\n", hr);
  61. goto ErrorExit;
  62. }
  63. }
  64. catch(...)
  65. {
  66. hr = E_POINTER;
  67. DebugTrace("Exception: invalid parameter.\n");
  68. goto ErrorExit;
  69. }
  70. CommonExit:
  71. DebugTrace("Leaving CreateOIDsObject().\n");
  72. return hr;
  73. ErrorExit:
  74. //
  75. // Sanity check.
  76. //
  77. ATLASSERT(FAILED(hr));
  78. //
  79. // Free resource.
  80. //
  81. if (pCOIDs)
  82. {
  83. delete pCOIDs;
  84. }
  85. goto CommonExit;
  86. }
  87. ////////////////////////////////////////////////////////////////////////////////
  88. //
  89. // COIDs
  90. //
  91. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  92. Function : COIDs::get_Item
  93. Synopsis : Return item in the collection.
  94. Parameter: VARIANT Index - Numeric index or string OID.
  95. VARIANT * pVal - Pointer to VARIANT to receive the IDispatch.
  96. Remark :
  97. ------------------------------------------------------------------------------*/
  98. STDMETHODIMP COIDs::get_Item (VARIANT Index, VARIANT * pVal)
  99. {
  100. HRESULT hr = S_OK;
  101. CComPtr<IOID> pIOID = NULL;
  102. DebugTrace("Entering COIDs::get_Item().\n");
  103. try
  104. {
  105. //
  106. // Lock access to this object.
  107. //
  108. m_Lock.Lock();
  109. //
  110. // Check parameters.
  111. //
  112. if (NULL == pVal)
  113. {
  114. hr = E_INVALIDARG;
  115. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  116. goto ErrorExit;
  117. }
  118. //
  119. // Intialize.
  120. //
  121. ::VariantInit(pVal);
  122. //
  123. // Numeric or string?
  124. //
  125. if (VT_BSTR == V_VT(&Index))
  126. {
  127. //
  128. // Index by OID string.
  129. //
  130. OIDMap::iterator it;
  131. //
  132. // Find the item with this OID.
  133. //
  134. it = m_coll.find(Index.bstrVal);
  135. if (it == m_coll.end())
  136. {
  137. DebugTrace("Info: OID (%ls) not found in the collection.\n", Index.bstrVal);
  138. goto CommonExit;
  139. }
  140. //
  141. // Point to found item.
  142. //
  143. pIOID = (*it).second;
  144. //
  145. // Return to caller.
  146. //
  147. pVal->vt = VT_DISPATCH;
  148. if (FAILED(hr = pIOID->QueryInterface(IID_IDispatch, (void **) &(pVal->pdispVal))))
  149. {
  150. DebugTrace("Error [%#x]: pIOID->QueryInterface() failed.\n", hr);
  151. goto ErrorExit;
  152. }
  153. }
  154. else
  155. {
  156. //
  157. // Coerce to integer.
  158. //
  159. if (FAILED(hr = ::VariantChangeType(&Index, &Index, 0, VT_I4)))
  160. {
  161. DebugTrace("Error [%#x]: VariantChangeType() failed.\n", hr);
  162. goto ErrorExit;
  163. }
  164. //
  165. // Use the base class implemented by ATL.
  166. //
  167. if (FAILED(hr = IOIDsCollection::get_Item(Index.lVal, pVal)))
  168. {
  169. DebugTrace("Error [%#x]: IOIDsCollection::get_Item() failed.\n", hr);
  170. goto ErrorExit;
  171. }
  172. }
  173. }
  174. catch(...)
  175. {
  176. hr = CAPICOM_E_INTERNAL;
  177. DebugTrace("Exception: internal error.\n");
  178. goto ErrorExit;
  179. }
  180. CommonExit:
  181. //
  182. // Unlock access to this object.
  183. //
  184. m_Lock.Unlock();
  185. DebugTrace("Leaving COIDs::get_Item().\n");
  186. return hr;
  187. ErrorExit:
  188. //
  189. // Sanity check.
  190. //
  191. ATLASSERT(FAILED(hr));
  192. ReportError(hr);
  193. goto CommonExit;
  194. }
  195. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  196. Function : COIDs::Add
  197. Synopsis : Add an OID to the collection.
  198. Parameter: IOID * pVal - OID to be added.
  199. Remark :
  200. ------------------------------------------------------------------------------*/
  201. STDMETHODIMP COIDs::Add (IOID * pVal)
  202. {
  203. HRESULT hr = S_OK;
  204. CComBSTR bstrIndex;
  205. CComPtr<IOID> pIOID = NULL;
  206. DebugTrace("Entering COIDs::Add().\n");
  207. try
  208. {
  209. //
  210. // Lock access to this object.
  211. //
  212. m_Lock.Lock();
  213. //
  214. // Check parameters.
  215. //
  216. if (NULL == pVal)
  217. {
  218. hr = E_INVALIDARG;
  219. DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
  220. goto ErrorExit;
  221. }
  222. //
  223. // Make sure we have a valid OID.
  224. //
  225. if (FAILED(hr = pVal->QueryInterface(__uuidof(IOID), (void **) &pIOID.p)))
  226. {
  227. hr = E_NOINTERFACE;
  228. DebugTrace("Error [%#x]: pVal is not an OID object.\n", hr);
  229. goto ErrorExit;
  230. }
  231. //
  232. // Get OID string.
  233. //
  234. if (FAILED(hr = pIOID->get_Value(&bstrIndex.m_str)))
  235. {
  236. DebugTrace("Error [%#x]: pIOID->get_Value() failed.\n", hr);
  237. goto ErrorExit;
  238. }
  239. //
  240. // Now add object to collection map.
  241. //
  242. // Note that the overloaded = operator for CComPtr will
  243. // automatically AddRef to the object. Also, when the CComPtr
  244. // is deleted (happens when the Remove or map destructor is called),
  245. // the CComPtr destructor will automatically Release the object.
  246. //
  247. m_coll[bstrIndex] = pIOID;
  248. }
  249. catch(...)
  250. {
  251. hr = E_POINTER;
  252. DebugTrace("Exception: invalid parameter.\n");
  253. goto ErrorExit;
  254. }
  255. UnlockExit:
  256. //
  257. // Unlock access to this object.
  258. //
  259. m_Lock.Unlock();
  260. DebugTrace("Leaving COIDs::Add().\n");
  261. return hr;
  262. ErrorExit:
  263. //
  264. // Sanity check.
  265. //
  266. ATLASSERT(FAILED(hr));
  267. ReportError(hr);
  268. goto UnlockExit;
  269. }
  270. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  271. Function : COIDs::Remove
  272. Synopsis : Remove a OID from the collection.
  273. Parameter: VARIANT Index - OID string or index (1-based).
  274. Remark :
  275. ------------------------------------------------------------------------------*/
  276. STDMETHODIMP COIDs::Remove (VARIANT Index)
  277. {
  278. HRESULT hr = S_OK;
  279. OIDMap::iterator it;
  280. DebugTrace("Entering COIDs::Remove().\n");
  281. try
  282. {
  283. //
  284. // Lock access to this object.
  285. //
  286. m_Lock.Lock();
  287. //
  288. // Numeric or string?
  289. //
  290. if (VT_BSTR == V_VT(&Index))
  291. {
  292. //
  293. // Find the item with this OID.
  294. //
  295. it = m_coll.find(Index.bstrVal);
  296. if (it == m_coll.end())
  297. {
  298. //
  299. // Not found.
  300. //
  301. hr = E_INVALIDARG;
  302. DebugTrace("Error [%#x]: OID (%ls) not found in the collection.\n", hr, Index.bstrVal);
  303. goto ErrorExit;
  304. }
  305. }
  306. else
  307. {
  308. DWORD iIndex = 0;
  309. //
  310. // Coerce to integer.
  311. //
  312. if (FAILED(hr = ::VariantChangeType(&Index, &Index, 0, VT_I4)))
  313. {
  314. DebugTrace("Error [%#x]: VariantChangeType() failed.\n", hr);
  315. goto ErrorExit;
  316. }
  317. //
  318. // Force to 1 based.
  319. //
  320. iIndex = V_I4(&Index) < 0 ? 1 : (DWORD) V_I4(&Index);
  321. //
  322. // Make sure parameter is valid.
  323. //
  324. if (iIndex > m_coll.size())
  325. {
  326. hr = E_INVALIDARG;
  327. DebugTrace("Error [%#x]: Index %d is out of range.\n", hr, iIndex);
  328. goto ErrorExit;
  329. }
  330. //
  331. // Find object in map.
  332. //
  333. iIndex--;
  334. it = m_coll.begin();
  335. while (it != m_coll.end() && iIndex > 0)
  336. {
  337. it++;
  338. iIndex--;
  339. }
  340. }
  341. //
  342. // This should not happen.
  343. //
  344. if (it == m_coll.end())
  345. {
  346. hr = CAPICOM_E_INTERNAL;
  347. DebugTrace("Unexpected internal error [%#x]: iterator went pass end of map.\n", hr);
  348. goto ErrorExit;
  349. }
  350. //
  351. // Now remove object in map.
  352. //
  353. m_coll.erase(it);
  354. }
  355. catch(...)
  356. {
  357. hr = E_POINTER;
  358. DebugTrace("Exception: invalid parameter.\n");
  359. goto ErrorExit;
  360. }
  361. UnlockExit:
  362. //
  363. // Unlock access to this object.
  364. //
  365. m_Lock.Unlock();
  366. DebugTrace("Leaving COIDs::Remove().\n");
  367. return hr;
  368. ErrorExit:
  369. //
  370. // Sanity check.
  371. //
  372. ATLASSERT(FAILED(hr));
  373. ReportError(hr);
  374. goto UnlockExit;
  375. }
  376. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  377. Function : COIDs::Clear
  378. Synopsis : Remove all OIDs from the collection.
  379. Parameter: None.
  380. Remark :
  381. ------------------------------------------------------------------------------*/
  382. STDMETHODIMP COIDs::Clear (void)
  383. {
  384. HRESULT hr = S_OK;
  385. DebugTrace("Entering COIDs::Clear().\n");
  386. try
  387. {
  388. //
  389. // Lock access to this object.
  390. //
  391. m_Lock.Lock();
  392. //
  393. // Clear it.
  394. //
  395. m_coll.clear();
  396. }
  397. catch(...)
  398. {
  399. hr = E_POINTER;
  400. DebugTrace("Exception: invalid parameter.\n");
  401. goto ErrorExit;
  402. }
  403. UnlockExit:
  404. //
  405. // Unlock access to this object.
  406. //
  407. m_Lock.Unlock();
  408. DebugTrace("Leaving COIDs::Clear().\n");
  409. return hr;
  410. ErrorExit:
  411. //
  412. // Sanity check.
  413. //
  414. ATLASSERT(FAILED(hr));
  415. ReportError(hr);
  416. goto UnlockExit;
  417. }
  418. ////////////////////////////////////////////////////////////////////////////////
  419. //
  420. // Private methods.
  421. //
  422. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  423. Function : COIDs::Init
  424. Synopsis : Initialize the object.
  425. Parameter: PCERT_ENHKEY_USAGE pUsages - Pointer to CERT_ENHKEY_USAGE used to
  426. initialize the OIDs collection.
  427. BOOL bCertPolicies - TRUE for certificate policies, else
  428. application policies is assumed.
  429. Remark : This method is not part of the COM interface (it is a normal C++
  430. member function). We need it to initialize the object created
  431. internally by us.
  432. Since it is only a normal C++ member function, this function can
  433. only be called from a C++ class pointer, not an interface pointer.
  434. ------------------------------------------------------------------------------*/
  435. STDMETHODIMP COIDs::Init (PCERT_ENHKEY_USAGE pUsages, BOOL bCertPolicies)
  436. {
  437. HRESULT hr = S_OK;
  438. CComBSTR bstrOid;
  439. DebugTrace("Entering COIDs::Init().\n");
  440. try
  441. {
  442. //
  443. // pUsages can be NULL.
  444. //
  445. if (pUsages)
  446. {
  447. //
  448. // Make sure we have room to add.
  449. //
  450. if ((m_coll.size() + pUsages->cUsageIdentifier) > m_coll.max_size())
  451. {
  452. hr = CAPICOM_E_OUT_OF_RESOURCE;
  453. DebugTrace("Error [%#x]: Maximum entries (%#x) reached for OIDs collection.\n",
  454. hr, pUsages->cUsageIdentifier);
  455. goto ErrorExit;
  456. }
  457. //
  458. // Add all OIDs to collection.
  459. //
  460. for (DWORD i = 0; i < pUsages->cUsageIdentifier; i++)
  461. {
  462. CComPtr<IOID> pIOID = NULL;
  463. //
  464. // Create the OID object.
  465. //
  466. if (FAILED(hr = ::CreateOIDObject(pUsages->rgpszUsageIdentifier[i], TRUE, &pIOID)))
  467. {
  468. DebugTrace("Error [%#x]: CreateOIDObject() failed.\n", hr);
  469. goto ErrorExit;
  470. }
  471. //
  472. // BSTR index of OID.
  473. //
  474. if (!(bstrOid = pUsages->rgpszUsageIdentifier[i]))
  475. {
  476. hr = E_OUTOFMEMORY;
  477. DebugTrace("Error [%#x]: bstrOid = pUsages->rgpszUsageIdentifier[i] failed.\n", hr);
  478. goto ErrorExit;
  479. }
  480. //
  481. // Now add object to collection map.
  482. //
  483. // Note that the overloaded = operator for CComPtr will
  484. // automatically AddRef to the object. Also, when the CComPtr
  485. // is deleted (happens when the Remove or map destructor is called),
  486. // the CComPtr destructor will automatically Release the object.
  487. //
  488. m_coll[bstrOid] = pIOID;
  489. }
  490. }
  491. else
  492. {
  493. //
  494. // No usage, meaning good for all.
  495. //
  496. CComPtr<IOID> pIOID = NULL;
  497. LPSTR pszOid = bCertPolicies ? szOID_ANY_CERT_POLICY : szOID_ANY_APPLICATION_POLICY;
  498. if (FAILED(hr = ::CreateOIDObject(pszOid, TRUE, &pIOID)))
  499. {
  500. DebugTrace("Error [%#x]: CreateOIDObject() failed.\n", hr);
  501. goto ErrorExit;
  502. }
  503. //
  504. // BSTR index of OID.
  505. //
  506. if (!(bstrOid = pszOid))
  507. {
  508. hr = E_OUTOFMEMORY;
  509. DebugTrace("Error [%#x]: bstrOid = pszOid failed.\n", hr);
  510. goto ErrorExit;
  511. }
  512. //
  513. // Now add object to collection map.
  514. //
  515. // Note that the overloaded = operator for CComPtr will
  516. // automatically AddRef to the object. Also, when the CComPtr
  517. // is deleted (happens when the Remove or map destructor is called),
  518. // the CComPtr destructor will automatically Release the object.
  519. //
  520. m_coll[bstrOid] = pIOID;
  521. }
  522. }
  523. catch(...)
  524. {
  525. hr = E_POINTER;
  526. DebugTrace("Exception: invalid parameter.\n");
  527. goto ErrorExit;
  528. }
  529. CommonExit:
  530. DebugTrace("Leaving COIDs::Init().\n");
  531. return hr;
  532. ErrorExit:
  533. //
  534. // Sanity check.
  535. //
  536. ATLASSERT(FAILED(hr));
  537. goto CommonExit;
  538. }