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.

2065 lines
47 KiB

  1. // AuthMM.cpp: implementation for the WMI class Nsp_MMAuthSettings
  2. //
  3. // Copyright (c)1997-2001 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "IPSecBase.h"
  8. #include "AuthMM.h"
  9. #include "NetSecProv.h"
  10. //extern CCriticalSection g_CS;
  11. const DWORD DefMMAuthMethodFlag = 1;
  12. const MM_AUTH_ENUM DefMMAuthMethod = IKE_SSPI;
  13. /*
  14. Routine Description:
  15. Name:
  16. CAuthMM::QueryInstance
  17. Functionality:
  18. Given the query, it returns to WMI (using pSink) all the instances that satisfy the query.
  19. Actually, what we give back to WMI may contain extra instances. WMI will do the final filtering.
  20. Virtual:
  21. Yes (part of IIPSecObjectImpl)
  22. Arguments:
  23. None.
  24. Return Value:
  25. Success:
  26. (1) WBEM_NO_ERROR if instances are returned;
  27. (2) WBEM_S_NO_MORE_DATA if no instances are returned.
  28. Failure:
  29. Various errors may occur. We return various error code to indicate such errors.
  30. Notes:
  31. */
  32. STDMETHODIMP
  33. CAuthMM::QueryInstance (
  34. IN LPCWSTR pszQuery,
  35. IN IWbemContext * pCtx,
  36. IN IWbemObjectSink * pSink
  37. )
  38. {
  39. //
  40. // get the authentication method name from the query
  41. // the given key chain doesn't know anything about where clause property
  42. // should be authenticaion, so make another one ourselves.
  43. //
  44. m_srpKeyChain.Release();
  45. HRESULT hr = CNetSecProv::GetKeyChainFromQuery(pszQuery, g_pszAuthMethodID, &m_srpKeyChain);
  46. if (FAILED(hr))
  47. {
  48. return hr;
  49. }
  50. CComVariant var;
  51. //
  52. // if the name is missing, it will return WBEM_S_FALSE, which is fine with us
  53. // because we are querying.
  54. //
  55. hr = m_srpKeyChain->GetKeyPropertyValue(g_pszAuthMethodID, &var);
  56. LPCWSTR pszID = (var.vt == VT_BSTR) ? var.bstrVal : NULL;
  57. var.Clear();
  58. DWORD dwResumeHandle = 0;
  59. PMM_AUTH_METHODS pMMAuth = NULL;
  60. //
  61. // let's enumerate all MM auth methods
  62. //
  63. hr = ::FindMMAuthMethodsByID(pszID, &pMMAuth, &dwResumeHandle);
  64. while (SUCCEEDED(hr) && pMMAuth)
  65. {
  66. CComPtr<IWbemClassObject> srpObj;
  67. hr = CreateWbemObjFromMMAuthMethods(pMMAuth, &srpObj);
  68. //
  69. // we created a method object, then give it to WMI
  70. //
  71. if (SUCCEEDED(hr))
  72. {
  73. pSink->Indicate(1, &srpObj);
  74. }
  75. ::SPDApiBufferFree(pMMAuth);
  76. pMMAuth = NULL;
  77. hr = ::FindMMAuthMethodsByID(pszID, &pMMAuth, &dwResumeHandle);
  78. }
  79. //
  80. // since we are querying, it's ok to return not found
  81. //
  82. if (WBEM_E_NOT_FOUND == hr)
  83. {
  84. hr = WBEM_S_NO_MORE_DATA;
  85. }
  86. else if (SUCCEEDED(hr))
  87. {
  88. hr = WBEM_NO_ERROR;
  89. }
  90. return hr;
  91. }
  92. /*
  93. Routine Description:
  94. Name:
  95. CAuthMM::DeleteInstance
  96. Functionality:
  97. Will delete the wbem object (which causes to delete the IPSec main mode auth method).
  98. Virtual:
  99. Yes (part of IIPSecObjectImpl)
  100. Arguments:
  101. pCtx - COM interface pointer given by WMI and needed for various WMI APIs.
  102. pSink - COM interface pointer to notify WMI of any created objects.
  103. Return Value:
  104. Success:
  105. Success code. Use SUCCEEDED(hr) to test.
  106. Failure:
  107. (1) WBEM_E_NOT_FOUND if the auth method can't be found. Depending on
  108. the context, this may not be an error
  109. (2) Other various errors indicated by the returned error codes.
  110. Notes:
  111. */
  112. STDMETHODIMP
  113. CAuthMM::DeleteInstance (
  114. IN IWbemContext * pCtx,
  115. IN IWbemObjectSink * pSink
  116. )
  117. {
  118. CComVariant varID;
  119. HRESULT hr = m_srpKeyChain->GetKeyPropertyValue(g_pszAuthMethodID, &varID);
  120. if (FAILED(hr))
  121. {
  122. return hr;
  123. }
  124. else if (varID.vt != VT_BSTR || varID.bstrVal == NULL || varID.bstrVal[0] == L'\0')
  125. {
  126. return WBEM_E_NOT_FOUND;
  127. }
  128. DWORD dwResumeHandle = 0;
  129. PMM_AUTH_METHODS pMMAuth = NULL;
  130. hr = ::FindMMAuthMethodsByID(varID.bstrVal, &pMMAuth, &dwResumeHandle);
  131. if (SUCCEEDED(hr))
  132. {
  133. //
  134. // currently, we don't do rollback for delete
  135. //
  136. hr = DeleteAuthMethods(pMMAuth->gMMAuthID);
  137. ::SPDApiBufferFree(pMMAuth);
  138. }
  139. return hr;
  140. }
  141. /*
  142. Routine Description:
  143. Name:
  144. CAuthMM::PutInstance
  145. Functionality:
  146. Put an authentication method into SPD whose properties are represented by the
  147. wbem object.
  148. Virtual:
  149. Yes (part of IIPSecObjectImpl)
  150. Arguments:
  151. pInst - The wbem object.
  152. pCtx - COM interface pointer given by WMI and needed for various WMI APIs.
  153. pSink - COM interface pointer to notify WMI of results.
  154. Return Value:
  155. Success:
  156. WBEM_NO_ERROR
  157. Failure:
  158. Various error codes specifying the error.
  159. Notes:
  160. */
  161. STDMETHODIMP
  162. CAuthMM::PutInstance (
  163. IN IWbemClassObject * pInst,
  164. IN IWbemContext * pCtx,
  165. IN IWbemObjectSink * pSink
  166. )
  167. {
  168. if (pInst == NULL || pSink == NULL)
  169. {
  170. return WBEM_E_INVALID_PARAMETER;
  171. }
  172. bool bPreExist = false;
  173. //
  174. // for those policies that are created by ourselves (bPreExist == true)
  175. // we have our own way of allocating the buffer, need to free it in our corresponding way
  176. //
  177. PMM_AUTH_METHODS pMMAuth = NULL;
  178. HRESULT hr = GetMMAuthMethodsFromWbemObj(pInst, &pMMAuth, &bPreExist);
  179. //
  180. // if policy is successfully returned, then use it
  181. //
  182. if (SUCCEEDED(hr))
  183. {
  184. hr = AddAuthMethods(bPreExist, pMMAuth);
  185. if (SUCCEEDED(hr))
  186. {
  187. //
  188. // release the auth method structure
  189. //
  190. hr = OnAfterAddMMAuthMethods(pMMAuth->gMMAuthID);
  191. }
  192. }
  193. if (pMMAuth != NULL)
  194. {
  195. //
  196. // do something to allow this action to be rollback
  197. //
  198. FreeAuthMethods(&pMMAuth, bPreExist);
  199. }
  200. return hr;
  201. }
  202. /*
  203. Routine Description:
  204. Name:
  205. CAuthMM::GetInstance
  206. Functionality:
  207. Create a wbem object by the given key properties (already captured by our key chain object)..
  208. Virtual:
  209. Yes (part of IIPSecObjectImpl)
  210. Arguments:
  211. pCtx - COM interface pointer given by WMI and needed for various WMI APIs.
  212. pSink - COM interface pointer to notify WMI of any created objects.
  213. Return Value:
  214. Success:
  215. WBEM_NO_ERROR.
  216. Failure:
  217. (1) WBEM_E_NOT_FOUND if the auth method can't be found. Depending on
  218. the context, this may not be an error
  219. (2) Other various errors indicated by the returned error codes.
  220. Notes:
  221. */
  222. STDMETHODIMP
  223. CAuthMM::GetInstance (
  224. IN IWbemContext * pCtx,
  225. IN IWbemObjectSink * pSink
  226. )
  227. {
  228. //
  229. // main mode auth method is uniquely identified by its ID
  230. //
  231. CComVariant varID;
  232. HRESULT hr = m_srpKeyChain->GetKeyPropertyValue(g_pszAuthMethodID, &varID);
  233. if (FAILED(hr))
  234. {
  235. return hr;
  236. }
  237. else if (varID.vt != VT_BSTR || varID.bstrVal == NULL || varID.bstrVal[0] == L'\0')
  238. {
  239. return WBEM_E_NOT_FOUND;
  240. }
  241. //
  242. // need to find the method by its ID. If found, then create a wbem object
  243. // to represent the method.
  244. //
  245. PMM_AUTH_METHODS pMMAuth = NULL;
  246. DWORD dwResumeHandle = 0;
  247. hr = ::FindMMAuthMethodsByID(varID.bstrVal, &pMMAuth, &dwResumeHandle);
  248. if (SUCCEEDED(hr))
  249. {
  250. CComPtr<IWbemClassObject> srpObj;
  251. hr = CreateWbemObjFromMMAuthMethods(pMMAuth, &srpObj);
  252. if (SUCCEEDED(hr))
  253. {
  254. hr = pSink->Indicate(1, &srpObj);
  255. }
  256. ::SPDApiBufferFree(pMMAuth);
  257. }
  258. return SUCCEEDED(hr) ? WBEM_NO_ERROR : hr;
  259. }
  260. /*
  261. Routine Description:
  262. Name:
  263. CAuthMM::OnAfterAddMMAuthMethods
  264. Functionality:
  265. Post-adding handler to be called after successfully added a main mode auth method to SPD.
  266. Virtual:
  267. No.
  268. Arguments:
  269. gMethodID - The newly added method's guid.
  270. Return Value:
  271. Success:
  272. (1) WBEM_NO_ERROR: if rollback object is successfully created.
  273. (2) WBEM_S_FALSE: if there is no rollback guid information.
  274. Failure:
  275. (1) various errors indicated by the returned error codes.
  276. Notes:
  277. (1) Currently, we don't require a rollback object to be created for each
  278. object added to SPD. Only a host that support rollback will deposit
  279. rollback guid information and only then can we create a rollback object.
  280. */
  281. HRESULT
  282. CAuthMM::OnAfterAddMMAuthMethods (
  283. IN GUID gMethodID
  284. )
  285. {
  286. //
  287. // will create an Nsp_RollbackMMAuth
  288. //
  289. CComPtr<IWbemClassObject> srpObj;
  290. HRESULT hr = SpawnRollbackInstance(pszNspRollbackMMAuth, &srpObj);
  291. if (FAILED(hr))
  292. {
  293. return hr;
  294. }
  295. //
  296. // convert the guid into a string version
  297. //
  298. CComBSTR bstrMethodGuid;
  299. bstrMethodGuid.m_str = ::SysAllocStringLen(NULL, GUID_STRING_LENGTH);
  300. if (bstrMethodGuid.m_str)
  301. {
  302. int iRet = ::StringFromGUID2(gMethodID, bstrMethodGuid.m_str, GUID_STRING_LENGTH);
  303. if (iRet == 0)
  304. {
  305. hr = WBEM_E_INVALID_PARAMETER;
  306. }
  307. }
  308. else
  309. {
  310. hr = WBEM_E_OUT_OF_MEMORY;
  311. }
  312. if (SUCCEEDED(hr))
  313. {
  314. //
  315. // get the rollback guid
  316. //
  317. //::UpdateGlobals(m_srpNamespace, m_srpCtx);
  318. //if (g_varRollbackGuid.vt != VT_NULL && g_varRollbackGuid.vt != VT_EMPTY)
  319. //{
  320. // hr = srpObj->Put(g_pszTokenGuid, 0, &g_varRollbackGuid, CIM_EMPTY);
  321. //}
  322. //else
  323. //{
  324. CComVariant varRollbackNull = pszEmptyRollbackToken;
  325. hr = srpObj->Put(g_pszTokenGuid, 0, &varRollbackNull, CIM_EMPTY);
  326. //}
  327. //
  328. // we can create a rollback object
  329. //
  330. if (SUCCEEDED(hr))
  331. {
  332. //
  333. // $undone:shawnwu, Currently, we only support rolling back added objects, not removed objects
  334. // Also, we don't cache the previous instance data yet.
  335. //
  336. VARIANT var;
  337. var.vt = VT_I4;
  338. var.lVal = Action_Add;
  339. hr = srpObj->Put(g_pszAction, 0, &var, CIM_EMPTY);
  340. if (SUCCEEDED(hr))
  341. {
  342. //
  343. // ******Warning******
  344. // don't clear this var. It's bstr will be released by bstrMethodGuid itself!
  345. //
  346. var.vt = VT_BSTR;
  347. var.bstrVal = bstrMethodGuid.m_str;
  348. hr = srpObj->Put(g_pszAuthMethodID, 0, &var, CIM_EMPTY);
  349. //
  350. // after this, I don't care what you do with the var any more.
  351. //
  352. var.vt = VT_EMPTY;
  353. }
  354. }
  355. }
  356. if (SUCCEEDED(hr))
  357. {
  358. hr = m_srpNamespace->PutInstance(srpObj, WBEM_FLAG_CREATE_OR_UPDATE, m_srpCtx, NULL);
  359. if (SUCCEEDED(hr))
  360. {
  361. hr = WBEM_NO_ERROR;
  362. }
  363. }
  364. else if (SUCCEEDED(hr))
  365. {
  366. //
  367. // we don't have rollback guid
  368. //
  369. hr = WBEM_S_FALSE;
  370. }
  371. return hr;
  372. }
  373. /*
  374. Routine Description:
  375. Name:
  376. CAuthMM::CreateWbemObjFromMMAuthMethods
  377. Functionality:
  378. Given a SPD's main mode auth method, we will create a wbem object representing it.
  379. Virtual:
  380. No.
  381. Arguments:
  382. pMMAuth - The SPD's main mode auth method object.
  383. ppObj - Receives the wbem object.
  384. Return Value:
  385. Success:
  386. WBEM_NO_ERROR
  387. Failure:
  388. (1) various errors indicated by the returned error codes.
  389. Notes:
  390. */
  391. HRESULT
  392. CAuthMM::CreateWbemObjFromMMAuthMethods (
  393. IN PMM_AUTH_METHODS pMMAuth,
  394. OUT IWbemClassObject ** ppObj
  395. )
  396. {
  397. if (pMMAuth == NULL || ppObj == NULL)
  398. {
  399. return WBEM_E_INVALID_PARAMETER;
  400. }
  401. *ppObj = NULL;
  402. HRESULT hr = SpawnObjectInstance(ppObj);
  403. if (SUCCEEDED(hr))
  404. {
  405. //
  406. // translate the ID guid into a bstr for the wbem object
  407. //
  408. CComVariant var;
  409. var.vt = VT_BSTR;
  410. var.bstrVal = ::SysAllocStringLen(NULL, Guid_Buffer_Size);
  411. if (var.bstrVal != NULL)
  412. {
  413. //
  414. // it's a key property, so, we must have this property set
  415. //
  416. if (::StringFromGUID2(pMMAuth->gMMAuthID, var.bstrVal, Guid_Buffer_Size) > 0)
  417. {
  418. hr = (*ppObj)->Put(g_pszAuthMethodID, 0, &var, CIM_EMPTY);
  419. }
  420. else
  421. {
  422. hr = WBEM_E_BUFFER_TOO_SMALL;
  423. }
  424. //
  425. // previous var is bstr, we have to clear it for re-use
  426. //
  427. var.Clear();
  428. var.vt = VT_I4;
  429. var.lVal = pMMAuth->dwNumAuthInfos;
  430. hr = (*ppObj)->Put(g_pszNumAuthInfos, 0, &var, CIM_EMPTY);
  431. }
  432. else
  433. {
  434. hr = WBEM_E_OUT_OF_MEMORY;
  435. }
  436. //
  437. // need to fill up the wbem object's properties (those safearray)
  438. //
  439. if (SUCCEEDED(hr))
  440. {
  441. //
  442. // prepare to create the safearrays
  443. //
  444. CComVariant varMethod, varInfo;
  445. varMethod.vt = VT_ARRAY | VT_I4;
  446. varInfo.vt = VT_ARRAY | VT_BSTR;
  447. SAFEARRAYBOUND rgsabound[1];
  448. rgsabound[0].lLbound = 0;
  449. rgsabound[0].cElements = pMMAuth->dwNumAuthInfos;
  450. varMethod.parray = ::SafeArrayCreate(VT_I4, 1, rgsabound);
  451. varInfo.parray = ::SafeArrayCreate(VT_BSTR, 1, rgsabound);
  452. //
  453. // for readability
  454. //
  455. PIPSEC_MM_AUTH_INFO pMMAuthInfo = pMMAuth->pAuthenticationInfo;
  456. long lIndecies[1];
  457. DWORD dwIndex;
  458. //
  459. // if arrays are successfully created, then, we are ready to populate the arrays
  460. //
  461. if (varMethod.parray == NULL || varInfo.parray == NULL)
  462. {
  463. hr = WBEM_E_OUT_OF_MEMORY;
  464. }
  465. else
  466. {
  467. //
  468. // put all the method values into the array. If everything is fine, give the var to the wbem object
  469. //
  470. for (dwIndex = 0; SUCCEEDED(hr) && dwIndex < pMMAuth->dwNumAuthInfos; dwIndex++)
  471. {
  472. //
  473. // the element of the safearray to put
  474. //
  475. lIndecies[0] = dwIndex;
  476. hr = ::SafeArrayPutElement(varMethod.parray, lIndecies, &(pMMAuthInfo[dwIndex].AuthMethod) );
  477. if (SUCCEEDED(hr))
  478. {
  479. //
  480. // now, we need to transform the pAuthInfo into a bstr
  481. //
  482. BSTR bstrInfo = NULL;
  483. DWORD dwLength = 0;
  484. switch (pMMAuthInfo[dwIndex].AuthMethod)
  485. {
  486. case IKE_PRESHARED_KEY:
  487. //
  488. // pAuthInfo is wchar array
  489. //
  490. dwLength = pMMAuthInfo[dwIndex].dwAuthInfoSize/sizeof(WCHAR);
  491. bstrInfo = ::SysAllocStringLen(NULL, dwLength + 1);
  492. if (bstrInfo)
  493. {
  494. //
  495. // convert it to a bstr from the wchar array (no 0 terminator!)
  496. //
  497. ::wcsncpy(bstrInfo, (LPCWSTR)(pMMAuthInfo[dwIndex].pAuthInfo), dwLength);
  498. bstrInfo[dwLength] = L'\0';
  499. }
  500. else
  501. {
  502. hr = WBEM_E_OUT_OF_MEMORY;
  503. }
  504. break;
  505. case IKE_RSA_SIGNATURE:
  506. //
  507. // pAuthInfo is ansi char array
  508. //
  509. dwLength = pMMAuthInfo[dwIndex].dwAuthInfoSize;
  510. bstrInfo = ::SysAllocStringLen(NULL, dwLength + 1);
  511. if (bstrInfo)
  512. {
  513. //
  514. // convert it to a bstr from the ansi char array.
  515. // remember, pAuthInfo has no 0 terminator!
  516. //
  517. for (DWORD d = 0; d < dwLength; d++)
  518. {
  519. bstrInfo[d] = (WCHAR)(char)(pMMAuthInfo[dwIndex].pAuthInfo[d]);
  520. }
  521. bstrInfo[dwLength] = L'\0';
  522. }
  523. else
  524. {
  525. hr = WBEM_E_OUT_OF_MEMORY;
  526. }
  527. break;
  528. case IKE_SSPI:
  529. //
  530. // pAuthInfo must be NULL
  531. //
  532. break;
  533. default:
  534. //
  535. // IPSec only supports these three values at this point
  536. //
  537. hr = WBEM_E_NOT_SUPPORTED;
  538. }
  539. if (SUCCEEDED(hr))
  540. {
  541. hr = ::SafeArrayPutElement(varInfo.parray, lIndecies, bstrInfo);
  542. if (bstrInfo)
  543. {
  544. ::SysFreeString(bstrInfo);
  545. }
  546. }
  547. }
  548. }
  549. //
  550. // every element has been successfully put
  551. //
  552. if (SUCCEEDED(hr))
  553. {
  554. hr = (*ppObj)->Put(g_pszAuthMethod, 0, &varMethod, CIM_EMPTY);
  555. hr = (*ppObj)->Put(g_pszAuthInfo, 0, &varInfo, CIM_EMPTY);
  556. }
  557. }
  558. }
  559. }
  560. //
  561. // we may have created the object, but some mid steps have failed,
  562. // so let's release the object.
  563. //
  564. if (FAILED(hr) && *ppObj != NULL)
  565. {
  566. (*ppObj)->Release();
  567. *ppObj = NULL;
  568. }
  569. return SUCCEEDED(hr) ? WBEM_NO_ERROR : hr;
  570. }
  571. /*
  572. Routine Description:
  573. Name:
  574. CAuthMM::GetMMAuthMethodsFromWbemObj
  575. Functionality:
  576. Will try to get the MM Auth methods if such method already exists.
  577. Otherwise, we will create a new one.
  578. Virtual:
  579. No.
  580. Arguments:
  581. pInst - The wbem object object.
  582. ppMMAuth - Receives the main mode auth method.
  583. pbPreExist - Receives the information whether this object memory is allocated by SPD or not.
  584. Return Value:
  585. Success:
  586. WBEM_NO_ERROR
  587. Failure:
  588. (1) various errors indicated by the returned error codes.
  589. Notes:
  590. */
  591. HRESULT
  592. CAuthMM::GetMMAuthMethodsFromWbemObj (
  593. IN IWbemClassObject * pInst,
  594. OUT PMM_AUTH_METHODS * ppMMAuth,
  595. OUT bool * pbPreExist
  596. )
  597. {
  598. if (pInst == NULL || ppMMAuth == NULL || pbPreExist == NULL)
  599. {
  600. return WBEM_E_INVALID_PARAMETER;
  601. }
  602. *ppMMAuth = NULL;
  603. *pbPreExist = false;
  604. //
  605. // we have to have method id.
  606. //
  607. CComVariant var;
  608. GUID gMMAuthID = GUID_NULL;
  609. HRESULT hr = pInst->Get(g_pszAuthMethodID, 0, &var, NULL, NULL);
  610. if (FAILED(hr) || var.vt != VT_BSTR || var.bstrVal == NULL)
  611. {
  612. hr = WBEM_E_INVALID_OBJECT;
  613. }
  614. else
  615. {
  616. hr = ::CLSIDFromString(var.bstrVal, &gMMAuthID);
  617. }
  618. //
  619. // Do we already have a method with this method ID?
  620. //
  621. if (SUCCEEDED(hr))
  622. {
  623. DWORD dwResumeHandle = 0;
  624. hr = ::FindMMAuthMethodsByID(var.bstrVal, ppMMAuth, &dwResumeHandle);
  625. }
  626. //
  627. // clear it for later use
  628. //
  629. var.Clear();
  630. //
  631. // if we have a method already,
  632. //
  633. if (SUCCEEDED(hr))
  634. {
  635. //
  636. // already exist
  637. //
  638. *pbPreExist = true;
  639. }
  640. else if (hr == WBEM_E_NOT_FOUND)
  641. {
  642. //
  643. // The method doesn't exist yet. We need to create one.
  644. // First, need to know the number of AuthMethodInfos, we must have this
  645. // to know how to allocate!
  646. //
  647. hr = pInst->Get(g_pszNumAuthInfos, 0, &var, NULL, NULL);
  648. if (SUCCEEDED(hr) && var.vt == VT_I4)
  649. {
  650. hr = AllocAuthMethods(var.lVal, ppMMAuth);
  651. }
  652. else if (SUCCEEDED(hr))
  653. {
  654. //
  655. // we don't want to overwrite other errors. That is why
  656. // we test it against success here!
  657. //
  658. hr = WBEM_E_INVALID_OBJECT;
  659. }
  660. if (SUCCEEDED(hr))
  661. {
  662. (*ppMMAuth)->gMMAuthID = gMMAuthID;
  663. }
  664. }
  665. //
  666. // put our properties (inside the wbem object) into the AUTH_INFOs
  667. //
  668. if (SUCCEEDED(hr))
  669. {
  670. //
  671. // set all elements of the pAuthenticationInfo array
  672. //
  673. CComVariant varMethods, varInfos;
  674. hr = pInst->Get(g_pszAuthMethod, 0, &varMethods, NULL, NULL);
  675. if (SUCCEEDED(hr))
  676. {
  677. hr = pInst->Get(g_pszAuthInfo, 0, &varInfos, NULL, NULL);
  678. }
  679. //
  680. // both must be arrays
  681. //
  682. if ( (varMethods.vt & VT_ARRAY) != VT_ARRAY || (varInfos.vt & VT_ARRAY) != VT_ARRAY)
  683. {
  684. hr = WBEM_E_INVALID_OBJECT;
  685. }
  686. if (SUCCEEDED(hr))
  687. {
  688. //
  689. // populate the method object using these arrays
  690. //
  691. hr = UpdateAuthInfos(pbPreExist, &varMethods, &varInfos, *ppMMAuth);
  692. }
  693. }
  694. if (FAILED(hr) && *ppMMAuth != NULL)
  695. {
  696. //
  697. // FreeAuthMethods will reset ppMMAuth to NULL.
  698. //
  699. FreeAuthMethods(ppMMAuth, (*pbPreExist == false));
  700. }
  701. return SUCCEEDED(hr) ? WBEM_NO_ERROR : hr;
  702. }
  703. /*
  704. Routine Description:
  705. Name:
  706. CAuthMM::UpdateAuthInfos
  707. Functionality:
  708. Private helper: will populate the pAuthMethods's pAuthenticationInfo
  709. using the in parameters.
  710. Virtual:
  711. No.
  712. Arguments:
  713. pbPreExist - The flag that indicates whether the method was allocated
  714. by ourselves or not. This flag may be changed when this function
  715. returns as a result of modifying IPSec allocated buffers.
  716. pVarMethods - the AuthMethod member of each IPSEC_MM_AUTH_INFO.
  717. pVarSizes - the dwAuthInfoSize member of each IPSEC_MM_AUTH_INFO.
  718. pAuthMethods - What is to be poluated. It must contain the correct dwNumAuthInfos value
  719. and valid and consistent pAuthenticationInfo.
  720. Return Value:
  721. Success:
  722. WBEM_NO_ERROR
  723. Failure:
  724. (1) various errors indicated by the returned error codes.
  725. Notes:
  726. (1) pAuthMethods contains information as it is passed in. Don't blindly
  727. overwrite it. Only update those that are present by the other parameters
  728. (2) IPSec only support the following methods (pVarMethods' values):
  729. IKE_PRESHARED_KEY=1,IKE_RSA_SIGNATURE=3, IKE_SSPI=5
  730. This leaves IKE_DSS_SIGNATURE=2 and IKE_RSA_ENCRYPTION=4 not supported
  731. For IKE_PRESHARED_KEY, pAuthInfo is a wchar array, but no null terminator, dwAuthInfoSize
  732. is the byte size (not the count of wchars)
  733. For IKE_RSA_SIGNATURE, pAuthInfo is a blob of ASNI chars encoded issuer name of root certs.
  734. dwAuthInfoSize is the byte size (in this case, the same as the count of chars)
  735. For IKE_SSPI, pAuthInfo = NULL, dwAuthInfoSize = 0
  736. Warning: at this point, we don't support modifying existing methods.
  737. */
  738. HRESULT
  739. CAuthMM::UpdateAuthInfos (
  740. IN OUT bool * pbPreExist,
  741. IN VARIANT * pVarMethods,
  742. IN VARIANT * pVarInfos,
  743. IN OUT PMM_AUTH_METHODS pAuthMethods
  744. )
  745. {
  746. if (NULL == pbPreExist ||
  747. NULL == pVarMethods ||
  748. NULL == pVarInfos ||
  749. NULL == pAuthMethods )
  750. {
  751. return WBEM_E_INVALID_PARAMETER;
  752. }
  753. //
  754. // do a defensive checking: all these safearrays must have the same size
  755. //
  756. //
  757. // lower bound and upper bound of the array
  758. //
  759. long lLB, lUB;
  760. HRESULT hr = ::CheckSafeArraySize(pVarMethods, pAuthMethods->dwNumAuthInfos, &lLB, &lUB);
  761. //
  762. // we don't need the bounds for methods, so OK to overwrite lLB and lUP for them
  763. //
  764. if (SUCCEEDED(hr))
  765. {
  766. hr = ::CheckSafeArraySize(pVarInfos, pAuthMethods->dwNumAuthInfos, &lLB, &lUB);
  767. }
  768. if (FAILED(hr))
  769. {
  770. return hr;
  771. }
  772. //
  773. // if a brand new method
  774. //
  775. if (*pbPreExist == false)
  776. {
  777. //
  778. // need to create the get the entire array from the parameters
  779. //
  780. DWORD* pdwMethods = new DWORD[pAuthMethods->dwNumAuthInfos];
  781. if (pdwMethods == NULL)
  782. {
  783. hr = WBEM_E_OUT_OF_MEMORY;
  784. }
  785. else
  786. {
  787. hr = ::GetDWORDSafeArrayElements(pVarMethods, pAuthMethods->dwNumAuthInfos, pdwMethods);
  788. }
  789. VARIANT varInfo;
  790. varInfo.vt = VT_BSTR;
  791. long lIndexes[1];
  792. //
  793. // Safearray's index is not necessarily 0-based. Pay attention to this.
  794. // For each method, we need to set the PIPSEC_MM_AUTH_INFO.
  795. //
  796. for (long l = lLB; SUCCEEDED(hr) && l <= lUB; l++)
  797. {
  798. lIndexes[0] = l;
  799. //
  800. // for IKE_PRESHARED_KEY=1, IKE_RSA_SIGNATURE=3, IKE_SSPI=5, set the appropriate blob pAuthInfo
  801. //
  802. if (pdwMethods[l - lLB] != IKE_PRESHARED_KEY &&
  803. pdwMethods[l - lLB] != IKE_RSA_SIGNATURE &&
  804. pdwMethods[l - lLB] != IKE_SSPI)
  805. {
  806. hr = WBEM_E_VALUE_OUT_OF_RANGE;
  807. break;
  808. }
  809. //
  810. // for readability
  811. //
  812. PIPSEC_MM_AUTH_INFO pTheInfo = &(pAuthMethods->pAuthenticationInfo[l - lLB]);
  813. //
  814. // set the AuthMethod
  815. //
  816. pTheInfo->AuthMethod = (MM_AUTH_ENUM)(pdwMethods[l - lLB]);
  817. //
  818. // IKE_SSPI, pAuthInfo must be NULL
  819. //
  820. if (IKE_SSPI == pTheInfo->AuthMethod)
  821. {
  822. pTheInfo->dwAuthInfoSize = 0;
  823. pTheInfo->pAuthInfo = NULL;
  824. }
  825. else
  826. {
  827. //
  828. // for other supported IKE (IKE_PRESHARED_KEY/IKE_RSA_SIGNATURE)
  829. // the pAuthInfo is a is a string (unicode/ansi).
  830. //
  831. hr = ::SafeArrayGetElement(pVarInfos->parray, lIndexes, &(varInfo.bstrVal));
  832. if (SUCCEEDED(hr) && varInfo.vt == VT_BSTR)
  833. {
  834. hr = SetAuthInfo(pTheInfo, varInfo.bstrVal);
  835. }
  836. ::VariantClear(&varInfo);
  837. varInfo.vt = VT_BSTR;
  838. }
  839. }
  840. delete [] pdwMethods;
  841. }
  842. return hr;
  843. }
  844. /*
  845. Routine Description:
  846. Name:
  847. CAuthMM::UpdateAuthInfos
  848. Functionality:
  849. Private helper: will populate the pAuthMethods's pAuthenticationInfo
  850. using the in parameters.
  851. Virtual:
  852. No.
  853. Arguments:
  854. pInfo - Receives the IPSEC_MM_AUTH_INFO information from the bstr
  855. bstrInfo - The string.
  856. Return Value:
  857. Success:
  858. WBEM_NO_ERROR
  859. Failure:
  860. (1) various errors indicated by the returned error codes.
  861. Notes:
  862. (1) This function is made so complicated to the fact that IPSEC_MM_AUTH_INFO's
  863. pAuthInfo is a string (unicode or ansi), but it doesn't have contain the
  864. 0 terminator. Pay close attention to that.
  865. Warning:
  866. (1) This only works for custom allocated auth info. Don't call this function
  867. with IPSec returned auth info. The reason for this limit is due the fact
  868. that we are not supporting modifying existing SPD objects at this time.
  869. (2) Only works for those two IKE enums that needs this conversion:
  870. IKE_PRESHARED_KEY and IKE_RSA_SIGNATURE
  871. */
  872. HRESULT
  873. CAuthMM::SetAuthInfo (
  874. IN OUT PIPSEC_MM_AUTH_INFO pInfo,
  875. IN BSTR bstrInfo
  876. )
  877. {
  878. if (pInfo == NULL || bstrInfo == NULL)
  879. {
  880. return WBEM_E_INVALID_PARAMETER;
  881. }
  882. HRESULT hr = WBEM_NO_ERROR;
  883. DWORD dwLength = wcslen(bstrInfo);
  884. if (IKE_PRESHARED_KEY == pInfo->AuthMethod)
  885. {
  886. //
  887. // IKE_PRESHARED_KEY, pAuthInfo will be an array of wchars (no 0 terminator)
  888. //
  889. //
  890. // size must not count the 0 terminator, pAuthInfo is an array of wchars
  891. //
  892. pInfo->dwAuthInfoSize = dwLength * sizeof(WCHAR);
  893. //
  894. // pAuthInfo must not have the 0 terminator
  895. //
  896. pInfo->pAuthInfo = new BYTE[pInfo->dwAuthInfoSize];
  897. if (pInfo->pAuthInfo)
  898. {
  899. ::wcsncpy((LPWSTR)(pInfo->pAuthInfo), bstrInfo, dwLength);
  900. }
  901. else
  902. {
  903. hr = WBEM_E_OUT_OF_MEMORY;
  904. }
  905. }
  906. else if (IKE_RSA_SIGNATURE == pInfo->AuthMethod)
  907. {
  908. //
  909. // IKE_RSA_SIGNATURE, pAuthInfo will be an array of ansi chars (no 0 terminator)
  910. //
  911. LPSTR pMultiBytes = NULL;
  912. //
  913. // convert bstr into an ansi char array
  914. //
  915. //
  916. // first, get the buffer size needed for the conversion
  917. //
  918. long lMultiByteSize = ::WideCharToMultiByte(CP_ACP,
  919. 0,
  920. bstrInfo,
  921. dwLength,
  922. pMultiBytes,
  923. 0,
  924. NULL,
  925. NULL);
  926. if (lMultiByteSize > 1)
  927. {
  928. //
  929. // convert to a temporary buffer because the conversion needs a null terminator
  930. // must release this memory
  931. //
  932. pMultiBytes = new char[lMultiByteSize];
  933. if (pMultiBytes)
  934. {
  935. lMultiByteSize = ::WideCharToMultiByte(CP_ACP,
  936. 0,
  937. bstrInfo,
  938. dwLength,
  939. pMultiBytes,
  940. lMultiByteSize,
  941. NULL, NULL);
  942. //
  943. // lMultiByteSize includes the null terminator
  944. //
  945. if (lMultiByteSize > 1)
  946. {
  947. //
  948. // size must not count the 0 terminator, pAuthInfo is an array of ansi chars
  949. //
  950. pInfo->dwAuthInfoSize = lMultiByteSize;
  951. //
  952. // pAuthInfo must not have the 0 terminator
  953. //
  954. pInfo->pAuthInfo = new BYTE[lMultiByteSize];
  955. if (pInfo->pAuthInfo)
  956. {
  957. //
  958. // copy the bytes
  959. //
  960. memcpy(pInfo->pAuthInfo, pMultiBytes, lMultiByteSize);
  961. }
  962. else
  963. {
  964. hr = WBEM_E_OUT_OF_MEMORY;
  965. }
  966. }
  967. else
  968. {
  969. //
  970. // $undone:shawnwu, should get system error (GetLastErr)
  971. //
  972. hr = WBEM_E_FAILED;
  973. }
  974. delete [] pMultiBytes;
  975. }
  976. else
  977. {
  978. hr = WBEM_E_OUT_OF_MEMORY;
  979. }
  980. }
  981. else
  982. {
  983. //
  984. // $undone:shawnwu, should get system error (GetLastErr)
  985. //
  986. hr = WBEM_E_FAILED;
  987. }
  988. }
  989. else
  990. {
  991. pInfo->pAuthInfo = NULL;
  992. hr = WBEM_E_NOT_SUPPORTED;
  993. }
  994. return hr;
  995. }
  996. /*
  997. Routine Description:
  998. Name:
  999. CAuthMM::AllocAuthMethods
  1000. Functionality:
  1001. Private helper: will allocate heap memory for a MM_AUTH_METHODS with
  1002. the given number of IPSEC_MM_AUTH_INFO.
  1003. Virtual:
  1004. No.
  1005. Arguments:
  1006. dwNumInfos - The count of IPSEC_MM_AUTH_INFO of the MM_AUTH_METHODS.
  1007. ppMMAuth - Receives the heap allocated MM_AUTH_METHODS.
  1008. Return Value:
  1009. Success:
  1010. WBEM_NO_ERROR
  1011. Failure:
  1012. (1) WBEM_E_INVALID_PARAMETER: if ppMMAuth == NULL.
  1013. (2) WBEM_E_OUT_OF_MEMORY.
  1014. Notes:
  1015. */
  1016. HRESULT
  1017. CAuthMM::AllocAuthMethods (
  1018. IN DWORD dwNumInfos,
  1019. IN PMM_AUTH_METHODS * ppMMAuth
  1020. )
  1021. {
  1022. if (ppMMAuth == NULL)
  1023. {
  1024. return WBEM_E_INVALID_PARAMETER;
  1025. }
  1026. HRESULT hr = WBEM_NO_ERROR;
  1027. *ppMMAuth = new MM_AUTH_METHODS;
  1028. if (*ppMMAuth != NULL)
  1029. {
  1030. //
  1031. // Set these members to default.
  1032. //
  1033. (*ppMMAuth)->gMMAuthID = GUID_NULL;
  1034. (*ppMMAuth)->dwFlags = DefMMAuthMethodFlag;
  1035. //
  1036. // We don't update this to the parameter value of dwNumInfos until we can allocate the IPSEC_MM_AUTH_INFO's
  1037. //
  1038. (*ppMMAuth)->dwNumAuthInfos = 0;
  1039. if (dwNumInfos > 0)
  1040. {
  1041. //
  1042. // IPSEC_MM_AUTH_INFO's are allocated by AllocAuthInfos function.
  1043. //
  1044. hr = AllocAuthInfos(dwNumInfos, &((*ppMMAuth)->pAuthenticationInfo));
  1045. if (SUCCEEDED(hr))
  1046. {
  1047. (*ppMMAuth)->dwNumAuthInfos = dwNumInfos;
  1048. }
  1049. }
  1050. else
  1051. {
  1052. (*ppMMAuth)->pAuthenticationInfo = NULL;
  1053. }
  1054. }
  1055. else
  1056. {
  1057. hr = WBEM_E_OUT_OF_MEMORY;
  1058. }
  1059. return hr;
  1060. }
  1061. /*
  1062. Routine Description:
  1063. Name:
  1064. CAuthMM::AllocAuthInfos
  1065. Functionality:
  1066. Private helper: will allocate heap buffer for the given count of IPSEC_MM_AUTH_INFO.
  1067. Virtual:
  1068. No.
  1069. Arguments:
  1070. dwNumInfos - The count of IPSEC_MM_AUTH_INFO.
  1071. ppAuthInfos - Receives the heap allocated PIPSEC_MM_AUTH_INFO.
  1072. Return Value:
  1073. Success:
  1074. WBEM_NO_ERROR
  1075. Failure:
  1076. (1) WBEM_E_INVALID_PARAMETER: if ppMMAuth == NULL.
  1077. (2) WBEM_E_OUT_OF_MEMORY.
  1078. Notes:
  1079. */
  1080. HRESULT
  1081. CAuthMM::AllocAuthInfos (
  1082. IN DWORD dwNumInfos,
  1083. OUT PIPSEC_MM_AUTH_INFO * ppAuthInfos
  1084. )
  1085. {
  1086. if (ppAuthInfos == NULL)
  1087. {
  1088. return WBEM_E_INVALID_PARAMETER;
  1089. }
  1090. HRESULT hr = WBEM_NO_ERROR;
  1091. *ppAuthInfos = new IPSEC_MM_AUTH_INFO[dwNumInfos];
  1092. if (*ppAuthInfos != NULL)
  1093. {
  1094. //
  1095. // set its members to defaults
  1096. //
  1097. (*ppAuthInfos)->AuthMethod = DefMMAuthMethod;
  1098. (*ppAuthInfos)->dwAuthInfoSize = 0;
  1099. (*ppAuthInfos)->pAuthInfo = NULL;
  1100. }
  1101. else
  1102. {
  1103. hr = WBEM_E_OUT_OF_MEMORY;
  1104. }
  1105. return hr;
  1106. }
  1107. /*
  1108. Routine Description:
  1109. Name:
  1110. CAuthMM::FreeAuthMethods
  1111. Functionality:
  1112. Private helper: will free memory allocated for the PMM_AUTH_METHODS.
  1113. Virtual:
  1114. No.
  1115. Arguments:
  1116. ppMMAuth - The heap buffer for PMM_AUTH_METHODS. Will be set to NULL upon return.
  1117. bCustomAlloc - Flag about who allocated the buffer. bCustomAlloc == true if we allocate it
  1118. and bCustomAlloc == false if SPD allocated it.
  1119. Return Value:
  1120. None.
  1121. Notes:
  1122. Don't use delete to free heap allocated MM_AUTH_METHODS. Our allocation method is totally
  1123. different from SPD's and SPD may change its allocation schema in the future.
  1124. */
  1125. void
  1126. CAuthMM::FreeAuthMethods (
  1127. IN OUT PMM_AUTH_METHODS * ppMMAuth,
  1128. IN bool bCustomAlloc
  1129. )
  1130. {
  1131. if (ppMMAuth == NULL || *ppMMAuth == NULL)
  1132. {
  1133. return;
  1134. }
  1135. if (bCustomAlloc == false)
  1136. {
  1137. ::SPDApiBufferFree(*ppMMAuth);
  1138. }
  1139. else
  1140. {
  1141. //
  1142. // we allocated IPSEC_MM_AUTH_INFO for pAuthenticationInfo in the standard C++ embedding
  1143. // pointer's allocation, i.e., we don't allocated a flat buffer. Instead, the pointers inside
  1144. // IPSEC_MM_AUTH_INFO are separately allocated.
  1145. //
  1146. FreeAuthInfos( (*ppMMAuth)->dwNumAuthInfos, &((*ppMMAuth)->pAuthenticationInfo) );
  1147. delete *ppMMAuth;
  1148. }
  1149. *ppMMAuth = NULL;
  1150. }
  1151. /*
  1152. Routine Description:
  1153. Name:
  1154. CAuthMM::FreeAuthInfos
  1155. Functionality:
  1156. Private helper: will free memory allocated for the array of IPSEC_MM_AUTH_INFO.
  1157. Virtual:
  1158. No.
  1159. Arguments:
  1160. dwNumInfos - The number of IPSEC_MM_AUTH_INFO of the given ppAuthInfos. Since ppAuthInfos
  1161. is an array, we need this count to know the count of the array.
  1162. ppAuthInfos - The array of IPSEC_MM_AUTH_INFO to free. Will be set to NULL upon return.
  1163. Return Value:
  1164. None.
  1165. Notes:
  1166. Use this method only to free those authentication methods allocated by our
  1167. own allocation method AllocAuthMethods. For SPD allocated IPSEC_MM_AUTH_INFO's,
  1168. don't use this function. Instead, use SPD's SPDApiBufferFree to free the entire
  1169. buffer and you should never need to worry about IPSEC_MM_AUTH_INFO.
  1170. */
  1171. void
  1172. CAuthMM::FreeAuthInfos (
  1173. IN DWORD dwNumInfos,
  1174. IN OUT PIPSEC_MM_AUTH_INFO * ppAuthInfos
  1175. )
  1176. {
  1177. if (ppAuthInfos == NULL || *ppAuthInfos == NULL)
  1178. {
  1179. return;
  1180. }
  1181. for (DWORD dwIndex = 0; dwIndex < dwNumInfos; ++dwIndex)
  1182. {
  1183. //
  1184. // this is LPBYTE, an array
  1185. //
  1186. delete [] (*ppAuthInfos)[dwIndex].pAuthInfo;
  1187. }
  1188. delete [] *ppAuthInfos;
  1189. *ppAuthInfos = NULL;
  1190. }
  1191. /*
  1192. Routine Description:
  1193. Name:
  1194. CAuthMM::Rollback
  1195. Functionality:
  1196. Static function to rollback those main mode auth methods added by us with
  1197. the given token.
  1198. Virtual:
  1199. No.
  1200. Arguments:
  1201. pNamespace - The namespace for ourselves.
  1202. pszRollbackToken - The token used to record our the action when we add
  1203. the methods.
  1204. bClearAll - Flag whether we should clear all auth methods. If it's true,
  1205. then we will delete all main mode auth methods regardless whether they
  1206. are added by us or not. This is a dangerous flag.
  1207. Return Value:
  1208. Success:
  1209. (1) WBEM_NO_ERROR: rollback objects are found and they are deleted.
  1210. (2) WBEM_S_FALSE: no rollback objects are found.
  1211. Failure:
  1212. Various error codes indicating the cause of the failure.
  1213. Notes:
  1214. We will continue the deletion even if some failure happens. That failure will be
  1215. returned, though.
  1216. $undone:shawnwu, should we really support ClearAll?
  1217. */
  1218. HRESULT
  1219. CAuthMM::Rollback (
  1220. IN IWbemServices * pNamespace,
  1221. IN LPCWSTR pszRollbackToken,
  1222. IN bool bClearAll
  1223. )
  1224. {
  1225. if (pNamespace == NULL || pszRollbackToken == NULL)
  1226. {
  1227. return WBEM_E_INVALID_PARAMETER;
  1228. }
  1229. //if (bClearAll)
  1230. //{
  1231. // return ClearAllAuthMethods(pNamespace);
  1232. //}
  1233. //
  1234. // we need to find all those main mode auth methods' rollback objects with matching token
  1235. //
  1236. CComPtr<IEnumWbemClassObject> srpEnum;
  1237. HRESULT hr = ::GetClassEnum(pNamespace, pszNspRollbackMMAuth, &srpEnum);
  1238. //
  1239. // go through all found classes. srpEnum->Next will return WBEM_S_FALSE if instance
  1240. // is not found.
  1241. //
  1242. CComPtr<IWbemClassObject> srpObj;
  1243. ULONG nEnum = 0;
  1244. hr = srpEnum->Next(WBEM_INFINITE, 1, &srpObj, &nEnum);
  1245. bool bHasInst = (SUCCEEDED(hr) && hr != WBEM_S_FALSE && srpObj != NULL);
  1246. DWORD dwStatus;
  1247. HRESULT hrError = WBEM_NO_ERROR;
  1248. while (SUCCEEDED(hr) && hr != WBEM_S_FALSE && srpObj)
  1249. {
  1250. //
  1251. // See if this obj has our matching token (guid).
  1252. //
  1253. // I tried a query with the given token as part of the where clause.
  1254. // that query doesn't return the properly screened objects. That might be a limitation
  1255. // of non-dynamic classes of WMI.
  1256. //
  1257. CComVariant varTokenGuid;
  1258. hr = srpObj->Get(g_pszTokenGuid, 0, &varTokenGuid, NULL, NULL);
  1259. //
  1260. // if we successfully got the token guid from the object, and
  1261. // if that token matches (case-insensitively) with our given token, then this is
  1262. // the right object we can use to delete a main mode auth method.
  1263. //
  1264. if (SUCCEEDED(hr) &&
  1265. varTokenGuid.vt == VT_BSTR &&
  1266. varTokenGuid.bstrVal != NULL &&
  1267. (_wcsicmp(pszRollbackToken, pszRollbackAll) == 0 || _wcsicmp(pszRollbackToken, varTokenGuid.bstrVal) == 0 )
  1268. )
  1269. {
  1270. CComVariant varAuthMethodID;
  1271. //
  1272. // Ask SPD to delete the main mode auth method using the method's ID.
  1273. //
  1274. hr = srpObj->Get(g_pszAuthMethodID, 0, &varAuthMethodID, NULL, NULL);
  1275. GUID guidAuthMethodGuid = GUID_NULL;
  1276. if (SUCCEEDED(hr) && varAuthMethodID.vt == VT_BSTR)
  1277. {
  1278. ::CLSIDFromString(varAuthMethodID.bstrVal, &guidAuthMethodGuid);
  1279. }
  1280. if (SUCCEEDED(hr))
  1281. {
  1282. hr = DeleteAuthMethods(guidAuthMethodGuid);
  1283. }
  1284. //
  1285. // Clear the rollback object itself if the main mode method has been deleted.
  1286. //
  1287. if (SUCCEEDED(hr))
  1288. {
  1289. CComVariant varPath;
  1290. if (SUCCEEDED(srpObj->Get(L"__RelPath", 0, &varPath, NULL, NULL)) && varPath.vt == VT_BSTR)
  1291. {
  1292. hr = pNamespace->DeleteInstance(varPath.bstrVal, 0, NULL, NULL);
  1293. }
  1294. }
  1295. //
  1296. // we are tracking the first error
  1297. //
  1298. if (FAILED(hr) && SUCCEEDED(hrError))
  1299. {
  1300. hrError = hr;
  1301. }
  1302. }
  1303. //
  1304. // ready it for re-use
  1305. //
  1306. srpObj.Release();
  1307. hr = srpEnum->Next(WBEM_INFINITE, 1, &srpObj, &nEnum);
  1308. }
  1309. if (!bHasInst)
  1310. {
  1311. return WBEM_S_FALSE;
  1312. }
  1313. else
  1314. {
  1315. //
  1316. // any failure code will be returned regardless of the final hr
  1317. //
  1318. if (FAILED(hrError))
  1319. {
  1320. return hrError;
  1321. }
  1322. else
  1323. {
  1324. return SUCCEEDED(hr) ? WBEM_NO_ERROR : hr;
  1325. }
  1326. }
  1327. }
  1328. /*
  1329. Routine Description:
  1330. Name:
  1331. CAuthMM::ClearAllAuthMethods
  1332. Functionality:
  1333. Static function to delete all auth methods in SPD. This is a very dangerous action!
  1334. Virtual:
  1335. No.
  1336. Arguments:
  1337. pNamespace - The namespace for ourselves.
  1338. Return Value:
  1339. Success:
  1340. WBEM_NO_ERROR.
  1341. Failure:
  1342. Various error codes indicating the cause of the failure.
  1343. Notes:
  1344. We will continue the deletion even if some failure happens. That failure will be
  1345. returned, though.
  1346. $undone:shawnwu, should we really support this?
  1347. */
  1348. HRESULT
  1349. CAuthMM::ClearAllAuthMethods (
  1350. IN IWbemServices * pNamespace
  1351. )
  1352. {
  1353. DWORD dwResumeHandle = 0;
  1354. DWORD dwReturned = 0;
  1355. DWORD dwStatus;
  1356. PMM_AUTH_METHODS *ppMMAuthMethods = NULL;
  1357. HRESULT hr = WBEM_NO_ERROR;
  1358. HRESULT hrError = WBEM_NO_ERROR;
  1359. //
  1360. // get each main mode auth method's ID, which is what deletion needs.
  1361. //
  1362. dwStatus = ::EnumMMAuthMethods(NULL, ppMMAuthMethods, 1, &dwReturned, &dwResumeHandle);
  1363. while (ERROR_SUCCESS == dwStatus && dwReturned > 0)
  1364. {
  1365. hr = DeleteAuthMethods((*ppMMAuthMethods)->gMMAuthID);
  1366. //
  1367. // we will track the first error
  1368. //
  1369. if (FAILED(hr) && SUCCEEDED(hrError))
  1370. {
  1371. hrError = hr;
  1372. }
  1373. FreeAuthMethods(ppMMAuthMethods, true);
  1374. *ppMMAuthMethods = NULL;
  1375. dwReturned = 0;
  1376. dwStatus = ::EnumMMAuthMethods(NULL, ppMMAuthMethods, 1, &dwReturned, &dwResumeHandle);
  1377. }
  1378. //
  1379. // Let's clear up all past action information for mm methods rollback objects deposited in the WMI depository
  1380. //
  1381. hr = ::DeleteRollbackObjects(pNamespace, pszNspRollbackMMAuth);
  1382. if (FAILED(hr) && SUCCEEDED(hrError))
  1383. {
  1384. hrError = hr;
  1385. }
  1386. return SUCCEEDED(hrError) ? WBEM_NO_ERROR : hrError;
  1387. }
  1388. /*
  1389. Routine Description:
  1390. Name:
  1391. CAuthMM::AddAuthMethods
  1392. Functionality:
  1393. Add the given main mode auth method.
  1394. Virtual:
  1395. No.
  1396. Arguments:
  1397. bPreExist - Flag whether the main mode auth method already exists in SPD
  1398. pMMAuth - The main mode method to add.
  1399. Return Value:
  1400. Success:
  1401. WBEM_NO_ERROR.
  1402. Failure:
  1403. WBEM_E_FAILED.
  1404. Notes:
  1405. */
  1406. HRESULT
  1407. CAuthMM::AddAuthMethods (
  1408. IN bool bPreExist,
  1409. IN PMM_AUTH_METHODS pMMAuth
  1410. )
  1411. {
  1412. DWORD dwResult;
  1413. if (!bPreExist)
  1414. {
  1415. dwResult = ::AddMMAuthMethods(NULL, 1, pMMAuth);
  1416. }
  1417. else
  1418. {
  1419. dwResult = ::SetMMAuthMethods(NULL, pMMAuth->gMMAuthID, pMMAuth);
  1420. }
  1421. //
  1422. // $undone:shawnwu, need better error code for failures.
  1423. //
  1424. return (dwResult == ERROR_SUCCESS) ? WBEM_NO_ERROR : WBEM_E_FAILED;
  1425. }
  1426. /*
  1427. Routine Description:
  1428. Name:
  1429. CAuthMM::AddAuthMethods
  1430. Functionality:
  1431. Add the given main mode auth method.
  1432. Virtual:
  1433. No.
  1434. Arguments:
  1435. pMMAuth - The main mode method to add.
  1436. Return Value:
  1437. Success:
  1438. WBEM_NO_ERROR.
  1439. Failure:
  1440. WBEM_E_VETO_DELETE.
  1441. Notes:
  1442. */
  1443. HRESULT
  1444. CAuthMM::DeleteAuthMethods (
  1445. IN GUID gMMAuthID
  1446. )
  1447. {
  1448. HRESULT hr = WBEM_NO_ERROR;
  1449. DWORD dwResult = ::DeleteMMAuthMethods(NULL, gMMAuthID);
  1450. if (ERROR_SUCCESS != dwResult)
  1451. {
  1452. hr = WBEM_E_VETO_DELETE;
  1453. }
  1454. //
  1455. // $undone:shawnwu, need better error code for failures.
  1456. //
  1457. return hr;
  1458. }