Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1074 lines
26 KiB

  1. ////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997 Microsoft Corporation
  4. //
  5. // Module Name: certmap.cpp
  6. //
  7. // Abstract: IIS privider cert mapper object methods
  8. //
  9. // Author: Philippe Choquier (phillich) 10-Apr-1997
  10. //
  11. // History: Zeyong Xu borrowed the source code from ADSI object
  12. // (created by Philippe Choquier at 10-Apr-1997) at 20-Oct-1999
  13. //
  14. ///////////////////////////////////////////////////
  15. #include "iisprov.h"
  16. #include "certmap.h"
  17. const ULONG MAX_CERT_KEY_LEN = 32;
  18. //
  19. // CCertMapperMethod
  20. //
  21. CCertMapperMethod::CCertMapperMethod(LPCWSTR pszMetabasePathIn)
  22. {
  23. DBG_ASSERT(pszMetabasePathIn != NULL);
  24. m_hmd = NULL;
  25. HRESULT hr = CoCreateInstance(
  26. CLSID_MSAdminBase,
  27. NULL,
  28. CLSCTX_ALL,
  29. IID_IMSAdminBase,
  30. (void**)&m_pIABase
  31. );
  32. THROW_ON_ERROR(hr);
  33. hr = Init(pszMetabasePathIn);
  34. THROW_ON_ERROR(hr);
  35. }
  36. CCertMapperMethod::~CCertMapperMethod()
  37. {
  38. if ( m_pszMetabasePath )
  39. {
  40. free( m_pszMetabasePath );
  41. }
  42. if(m_pIABase)
  43. m_pIABase->Release();
  44. }
  45. //
  46. // CreateMapping(): Create a mapping entry
  47. //
  48. // Arguments:
  49. //
  50. // vCert - X.509 certificate
  51. // bstrNtAcct - NT acct to map to
  52. // bstrNtPwd - NT pwd
  53. // bstrName - friendly name for mapping entry
  54. // lEnabled - 1 to enable mapping entry, 0 to disable it
  55. //
  56. HRESULT
  57. CCertMapperMethod::CreateMapping(
  58. VARIANT vCert,
  59. BSTR bstrNtAcct,
  60. BSTR bstrNtPwd,
  61. BSTR bstrName,
  62. LONG lEnabled
  63. )
  64. {
  65. HRESULT hr;
  66. LPBYTE pbCert = NULL;
  67. DWORD cCert;
  68. LPSTR pszNtAcct = NULL;
  69. LPSTR pszNtPwd = NULL;
  70. LPSTR pszName = NULL;
  71. LPBYTE pRes;
  72. DWORD cRes;
  73. DWORD cName;
  74. DWORD cNtAcct;
  75. DWORD cNtPwd;
  76. WCHAR achIndex[MAX_CERT_KEY_LEN];
  77. VARIANT vOldAcct;
  78. VARIANT vOldCert;
  79. VARIANT vOldPwd;
  80. VARIANT vOldName;
  81. VARIANT vOldEnabledFlag;
  82. PCCERT_CONTEXT pcCert = NULL;
  83. //
  84. // Do some sanity checks on the cert
  85. //
  86. if ( SUCCEEDED( hr = GetStringFromVariant( &vCert,
  87. (LPSTR*)&pbCert,
  88. &cCert,
  89. FALSE ) ) )
  90. {
  91. //
  92. // try to construct a cert context
  93. //
  94. if ( !( pcCert = CertCreateCertificateContext( X509_ASN_ENCODING,
  95. pbCert,
  96. cCert ) ) )
  97. {
  98. //
  99. // If the decoding fails, GetLastError() returns an ASN1 decoding
  100. // error that is obtained by subtracting CRYPT_E_OSS_ERROR from the returned
  101. // error and looking in file asn1code.h for the actual error. To avoid the
  102. // cryptic ASN1 errors, we'll just return a general "invalid arg" error
  103. //
  104. hr = RETURNCODETOHRESULT( E_INVALIDARG );
  105. FreeString( (LPSTR) pbCert );
  106. pbCert = NULL;
  107. return hr;
  108. }
  109. CertFreeCertificateContext( pcCert );
  110. }
  111. else
  112. {
  113. DBG_ASSERT(pbCert == NULL);
  114. return hr;
  115. }
  116. //
  117. // check if we already have a mapping for this cert; if we do, we'll replace that mapping
  118. // with the new one
  119. //
  120. if ( SUCCEEDED( hr = GetMapping( IISMAPPER_LOCATE_BY_CERT,
  121. vCert,
  122. &vOldCert,
  123. &vOldAcct,
  124. &vOldPwd,
  125. &vOldName,
  126. &vOldEnabledFlag ) ) )
  127. {
  128. if ( FAILED( hr = SetName( IISMAPPER_LOCATE_BY_CERT,
  129. vCert,
  130. bstrName ) ) ||
  131. FAILED( hr = SetAcct( IISMAPPER_LOCATE_BY_CERT,
  132. vCert,
  133. bstrNtAcct ) ) ||
  134. FAILED( hr = SetPwd( IISMAPPER_LOCATE_BY_CERT,
  135. vCert,
  136. bstrNtPwd ) ) ||
  137. FAILED( hr = SetEnabled( IISMAPPER_LOCATE_BY_CERT,
  138. vCert,
  139. lEnabled ) ) )
  140. {
  141. hr; //NOP - Something failed
  142. }
  143. }
  144. //
  145. // New mapping
  146. //
  147. else if ( hr == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
  148. {
  149. //
  150. // check mapping exists, create if not
  151. //
  152. hr = OpenMd( L"Cert11", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
  153. if ( hr == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
  154. {
  155. if ( SUCCEEDED( hr = OpenMd( L"",
  156. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  157. {
  158. hr = CreateMdObject( L"Cert11" );
  159. CloseMd( FALSE );
  160. // Reopen to the correct node.
  161. hr = OpenMd( L"Cert11", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
  162. }
  163. }
  164. if ( FAILED( hr ) )
  165. {
  166. return hr;
  167. }
  168. //
  169. // adding mapping cert "0" means add @ end of list
  170. //
  171. if ( SUCCEEDED( hr = CreateMdObject( L"mappings/0" ) ) )
  172. {
  173. if ( SUCCEEDED( hr = GetMdData( L"", MD_NSEPM_ACCESS_CERT, DWORD_METADATA, &
  174. cRes, &pRes ) ) )
  175. {
  176. if ( cRes == sizeof(DWORD ) )
  177. {
  178. _snwprintf(
  179. achIndex,
  180. MAX_CERT_KEY_LEN,
  181. L"mappings/%u",
  182. *(LPDWORD)pRes );
  183. if ( FAILED( hr = GetStringFromBSTR( bstrNtAcct, &pszNtAcct, &cNtAcct ) ) ||
  184. FAILED( hr = GetStringFromBSTR( bstrNtPwd, &pszNtPwd, &cNtPwd ) ) ||
  185. FAILED( hr = GetStringFromBSTR( bstrName, &pszName, &cName ) ) ||
  186. FAILED( hr = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA,
  187. sizeof(DWORD), (LPBYTE)&lEnabled ) ) ||
  188. FAILED( hr = SetMdData( achIndex, MD_MAPNAME, STRING_METADATA,
  189. cName, (LPBYTE)pszName ) ) ||
  190. FAILED( hr = SetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA,
  191. cNtPwd, (LPBYTE)pszNtPwd ) ) ||
  192. FAILED( hr = SetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA,
  193. cNtAcct, (LPBYTE)pszNtAcct ) ) ||
  194. FAILED( hr = SetMdData( achIndex, MD_MAPCERT, BINARY_METADATA,
  195. cCert, (LPBYTE)pbCert ) ) )
  196. {
  197. }
  198. }
  199. else
  200. {
  201. hr = E_FAIL;
  202. }
  203. }
  204. }
  205. }
  206. CloseMd( SUCCEEDED( hr ) );
  207. FreeString( (LPSTR)pbCert );
  208. FreeString( pszNtAcct );
  209. FreeString( pszNtPwd );
  210. FreeString( pszName );
  211. return hr;
  212. }
  213. //
  214. // GetMapping: Get a mapping entry using key
  215. //
  216. // Arguments:
  217. //
  218. // lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  219. // vKey - key to use to locate mapping
  220. // pvCert - X.509 certificate
  221. // pbstrNtAcct - NT acct to map to
  222. // pbstrNtPwd - NT pwd
  223. // pbstrName - friendly name for mapping entry
  224. // plEnabled - 1 to enable mapping entry, 0 to disable it
  225. //
  226. HRESULT
  227. CCertMapperMethod::GetMapping(
  228. LONG lMethod,
  229. VARIANT vKey,
  230. VARIANT* pvCert,
  231. VARIANT* pbstrNtAcct,
  232. VARIANT* pbstrNtPwd,
  233. VARIANT* pbstrName,
  234. VARIANT* plEnabled
  235. )
  236. {
  237. WCHAR achIndex[MAX_CERT_KEY_LEN];
  238. HRESULT hr;
  239. DWORD dwLen;
  240. LPBYTE pbData;
  241. VariantInit( pvCert );
  242. VariantInit( pbstrNtAcct );
  243. VariantInit( pbstrNtPwd );
  244. VariantInit( pbstrName );
  245. VariantInit( plEnabled );
  246. if ( SUCCEEDED( hr = OpenMd( L"Cert11",
  247. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  248. {
  249. if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
  250. {
  251. if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPCERT, BINARY_METADATA, &dwLen,
  252. &pbData ) ) )
  253. {
  254. hr = SetVariantAsByteArray( pvCert, dwLen, pbData );
  255. free( pbData );
  256. }
  257. else
  258. {
  259. CloseMd( FALSE );
  260. return hr;
  261. }
  262. if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA, &dwLen,
  263. &pbData ) ) )
  264. {
  265. hr = SetVariantAsBSTR( pbstrNtAcct, dwLen, pbData );
  266. free( pbData );
  267. }
  268. else
  269. {
  270. CloseMd( FALSE );
  271. return hr;
  272. }
  273. if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA, &dwLen,
  274. &pbData ) ) )
  275. {
  276. hr = SetVariantAsBSTR( pbstrNtPwd, dwLen, pbData );
  277. free( pbData );
  278. }
  279. else
  280. {
  281. CloseMd( FALSE );
  282. return hr;
  283. }
  284. if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPNAME, STRING_METADATA, &dwLen,
  285. &pbData ) ) )
  286. {
  287. hr = SetVariantAsBSTR( pbstrName, dwLen, pbData );
  288. free( pbData );
  289. }
  290. else
  291. {
  292. CloseMd( FALSE );
  293. return hr;
  294. }
  295. if ( FAILED( hr = GetMdData( achIndex, MD_MAPENABLED, STRING_METADATA, &dwLen,
  296. &pbData ) ) )
  297. {
  298. SetVariantAsLong( plEnabled, FALSE );
  299. }
  300. else
  301. {
  302. SetVariantAsLong( plEnabled, *(LPDWORD)pbData );
  303. free( pbData );
  304. }
  305. }
  306. CloseMd( FALSE );
  307. }
  308. return hr;
  309. }
  310. //
  311. // Delete a mapping entry using key
  312. //
  313. HRESULT
  314. CCertMapperMethod::DeleteMapping(
  315. LONG lMethod,
  316. VARIANT vKey
  317. )
  318. {
  319. WCHAR achIndex[MAX_CERT_KEY_LEN];
  320. HRESULT hr;
  321. if ( SUCCEEDED( hr = OpenMd( L"Cert11",
  322. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  323. {
  324. if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
  325. {
  326. hr = DeleteMdObject( achIndex );
  327. }
  328. CloseMd( TRUE );
  329. }
  330. return hr;
  331. }
  332. //
  333. // Set the enable flag on a mapping entry using key
  334. //
  335. HRESULT
  336. CCertMapperMethod::SetEnabled(
  337. LONG lMethod,
  338. VARIANT vKey,
  339. LONG lEnabled
  340. )
  341. {
  342. WCHAR achIndex[MAX_CERT_KEY_LEN];
  343. HRESULT hr;
  344. if ( SUCCEEDED( hr = OpenMd( L"Cert11",
  345. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  346. {
  347. if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
  348. {
  349. hr = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA, sizeof(DWORD), (LPBYTE)&lEnabled );
  350. }
  351. CloseMd( TRUE );
  352. }
  353. return hr;
  354. }
  355. //
  356. // Set the Name on a mapping entry using key
  357. //
  358. HRESULT CCertMapperMethod::SetName(
  359. LONG lMethod,
  360. VARIANT vKey,
  361. BSTR bstrName
  362. )
  363. {
  364. return SetString( lMethod, vKey, bstrName, MD_MAPNAME );
  365. }
  366. //
  367. // Set a string property on a mapping entry using key
  368. //
  369. HRESULT CCertMapperMethod::SetString(
  370. LONG lMethod,
  371. VARIANT vKey,
  372. BSTR bstrName,
  373. DWORD dwProp
  374. )
  375. {
  376. WCHAR achIndex[MAX_CERT_KEY_LEN];
  377. LPSTR pszName = NULL;
  378. HRESULT hr;
  379. DWORD dwLen;
  380. if ( FAILED( hr = GetStringFromBSTR( bstrName, &pszName, &dwLen, TRUE ) ) )
  381. {
  382. return hr;
  383. }
  384. if ( SUCCEEDED( hr = OpenMd( L"Cert11",
  385. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  386. {
  387. if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
  388. {
  389. hr = SetMdData( achIndex, dwProp, STRING_METADATA, dwLen, (LPBYTE)pszName );
  390. }
  391. CloseMd( TRUE );
  392. }
  393. FreeString( pszName );
  394. return hr;
  395. }
  396. //
  397. // Set the Password on a mapping entry using key
  398. //
  399. HRESULT
  400. CCertMapperMethod::SetPwd(
  401. LONG lMethod,
  402. VARIANT vKey,
  403. BSTR bstrPwd
  404. )
  405. {
  406. return SetString( lMethod, vKey, bstrPwd, MD_MAPNTPWD );
  407. }
  408. //
  409. // Set the NT account name on a mapping entry using key
  410. //
  411. HRESULT
  412. CCertMapperMethod::SetAcct(
  413. LONG lMethod,
  414. VARIANT vKey,
  415. BSTR bstrAcct
  416. )
  417. {
  418. return SetString( lMethod, vKey, bstrAcct, MD_MAPNTACCT );
  419. }
  420. HRESULT
  421. CCertMapperMethod::OpenMd(
  422. LPWSTR pszOpenPath,
  423. DWORD dwPermission
  424. )
  425. {
  426. HRESULT hr;
  427. LPWSTR pszPath;
  428. UINT cL = wcslen( m_pszMetabasePath );
  429. pszPath = (LPWSTR)malloc( (wcslen(pszOpenPath) + 1 + cL + 1)*sizeof(WCHAR) );
  430. if ( pszPath == NULL )
  431. {
  432. return E_OUTOFMEMORY;
  433. }
  434. memcpy( pszPath, m_pszMetabasePath, cL * sizeof(WCHAR) );
  435. if ( cL && m_pszMetabasePath[cL-1] != L'/' && *pszOpenPath && *pszOpenPath != L'/' )
  436. {
  437. pszPath[cL++] = L'/';
  438. }
  439. wcscpy( pszPath + cL, pszOpenPath );
  440. hr = OpenAdminBaseKey(
  441. pszPath,
  442. dwPermission
  443. );
  444. free( pszPath );
  445. return hr;
  446. }
  447. HRESULT
  448. CCertMapperMethod::CloseMd(
  449. BOOL fSave
  450. )
  451. {
  452. CloseAdminBaseKey();
  453. m_hmd = NULL;
  454. if ( m_pIABase && fSave )
  455. {
  456. m_pIABase->SaveData();
  457. }
  458. return S_OK;
  459. }
  460. HRESULT
  461. CCertMapperMethod::DeleteMdObject(
  462. LPWSTR pszKey
  463. )
  464. {
  465. return m_pIABase->DeleteKey( m_hmd, pszKey );
  466. }
  467. HRESULT
  468. CCertMapperMethod::CreateMdObject(
  469. LPWSTR pszKey
  470. )
  471. {
  472. return m_pIABase->AddKey( m_hmd, pszKey );
  473. }
  474. HRESULT
  475. CCertMapperMethod::SetMdData(
  476. LPWSTR achIndex,
  477. DWORD dwProp,
  478. DWORD dwDataType,
  479. DWORD dwDataLen,
  480. LPBYTE pbData
  481. )
  482. {
  483. METADATA_RECORD md;
  484. md.dwMDDataLen = dwDataLen;
  485. md.dwMDDataType = dwDataType;
  486. md.dwMDIdentifier = dwProp;
  487. md.dwMDAttributes = (dwProp == MD_MAPPWD) ? METADATA_SECURE : 0;
  488. md.pbMDData = pbData;
  489. return m_pIABase->SetData( m_hmd, achIndex, &md );
  490. }
  491. HRESULT
  492. CCertMapperMethod::GetMdData(
  493. LPWSTR achIndex,
  494. DWORD dwProp,
  495. DWORD dwDataType,
  496. LPDWORD pdwDataLen,
  497. LPBYTE* ppbData
  498. )
  499. {
  500. HRESULT hr;
  501. METADATA_RECORD md;
  502. DWORD dwRequired;
  503. md.dwMDDataLen = 0;
  504. md.dwMDDataType = dwDataType;
  505. md.dwMDIdentifier = dwProp;
  506. md.dwMDAttributes = 0;
  507. md.pbMDData = NULL;
  508. if ( FAILED(hr = m_pIABase->GetData( m_hmd, achIndex, &md, &dwRequired )) )
  509. {
  510. if ( hr == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER) )
  511. {
  512. if ( (*ppbData = (LPBYTE)malloc(dwRequired)) == NULL )
  513. {
  514. return E_OUTOFMEMORY;
  515. }
  516. md.pbMDData = *ppbData;
  517. md.dwMDDataLen = dwRequired;
  518. hr = m_pIABase->GetData( m_hmd, achIndex, &md, &dwRequired );
  519. *pdwDataLen = md.dwMDDataLen;
  520. }
  521. }
  522. else
  523. {
  524. *pdwDataLen = 0;
  525. *ppbData = NULL;
  526. }
  527. return hr;
  528. }
  529. //
  530. // Locate a mapping entry based on key
  531. // OpenMd() must be called 1st
  532. //
  533. HRESULT
  534. CCertMapperMethod::Locate(
  535. LONG lMethod,
  536. VARIANT vKey,
  537. LPWSTR pszResKey
  538. )
  539. {
  540. HRESULT hr;
  541. LPSTR pV = NULL;
  542. DWORD cV;
  543. DWORD dwProp;
  544. LPSTR pRes;
  545. DWORD cRes;
  546. BOOL fAddDelim = TRUE;
  547. //
  548. // determine method
  549. //
  550. switch ( lMethod )
  551. {
  552. case IISMAPPER_LOCATE_BY_CERT:
  553. dwProp = MD_NSEPM_ACCESS_CERT;
  554. fAddDelim = FALSE;
  555. break;
  556. case IISMAPPER_LOCATE_BY_NAME:
  557. dwProp = MD_NSEPM_ACCESS_NAME;
  558. break;
  559. case IISMAPPER_LOCATE_BY_ACCT:
  560. dwProp = MD_NSEPM_ACCESS_ACCOUNT;
  561. break;
  562. case IISMAPPER_LOCATE_BY_INDEX:
  563. if ( SUCCEEDED( hr = GetStringFromVariant( &vKey, &pV, &cV, TRUE ) ) )
  564. {
  565. wsprintfW( pszResKey, L"mappings/%s", pV );
  566. }
  567. FreeString( pV );
  568. return hr;
  569. default:
  570. return E_FAIL;
  571. }
  572. //
  573. // get ptr to data
  574. //
  575. if ( SUCCEEDED( hr = GetStringFromVariant( &vKey, &pV, &cV, fAddDelim ) ) )
  576. {
  577. //
  578. // set search prop, get result
  579. //
  580. if ( SUCCEEDED( hr = SetMdData( L"", dwProp, BINARY_METADATA, cV, (LPBYTE)pV ) ) )
  581. {
  582. if ( SUCCEEDED( hr = GetMdData( L"", dwProp, DWORD_METADATA, &cRes, (LPBYTE*)&pRes ) ) )
  583. {
  584. if ( cRes == sizeof(DWORD ) )
  585. {
  586. wsprintfW( pszResKey, L"mappings/%u", *(LPDWORD)pRes );
  587. }
  588. else
  589. {
  590. hr = E_FAIL;
  591. }
  592. free( pRes );
  593. }
  594. }
  595. }
  596. FreeString( pV );
  597. return hr;
  598. }
  599. //
  600. // GetStringFromBSTR: Allocate string buffer from BSTR
  601. //
  602. // Arguments:
  603. //
  604. // bstr - bstr to convert from
  605. // psz - updated with ptr to buffer, to be freed with FreeString()
  606. // pdwLen - updated with strlen(string), incremented by 1 if fAddDelimInCount is TRUE
  607. // fAddDelimInCount - TRUE to increment *pdwLen
  608. //
  609. HRESULT CCertMapperMethod::GetStringFromBSTR(
  610. BSTR bstr,
  611. LPSTR* psz,
  612. LPDWORD pdwLen,
  613. BOOL fAddDelimInCount
  614. )
  615. {
  616. UINT cch = SysStringLen(bstr);
  617. UINT cchT;
  618. // include NULL terminator
  619. *pdwLen = cch + (fAddDelimInCount ? 1 : 0);
  620. CHAR *szNew = (CHAR*)malloc((2 * cch) + 1); // * 2 for worst case DBCS string
  621. if (szNew == NULL)
  622. {
  623. return E_OUTOFMEMORY;
  624. }
  625. cchT = WideCharToMultiByte(CP_ACP, 0, bstr, cch + 1, szNew, (2 * cch) + 1, NULL, NULL);
  626. *psz = szNew;
  627. return NOERROR;
  628. }
  629. //
  630. // GetStringFromVariant: Allocate string buffer from BSTR
  631. //
  632. // Arguments:
  633. //
  634. // pVar - variant to convert from. Recognizes BSTR, VT_ARRAY|VT_UI1, ByRef or ByVal
  635. // psz - updated with ptr to buffer, to be freed with FreeString()
  636. // pdwLen - updated with size of input, incremented by 1 if fAddDelimInCount is TRUE
  637. // fAddDelimInCount - TRUE to increment *pdwLen
  638. //
  639. HRESULT CCertMapperMethod::GetStringFromVariant(
  640. VARIANT* pVar,
  641. LPSTR* psz,
  642. LPDWORD pdwLen,
  643. BOOL fAddDelim
  644. )
  645. {
  646. LPBYTE pbV = NULL;
  647. UINT cV;
  648. HRESULT hr;
  649. WORD vt = V_VT(pVar);
  650. BOOL fByRef = FALSE;
  651. VARIANT vOut;
  652. // Set out params to 0
  653. *psz = NULL;
  654. *pdwLen = 0;
  655. VariantInit( &vOut );
  656. if ( vt & VT_BYREF )
  657. {
  658. vt &= ~VT_BYREF;
  659. fByRef = TRUE;
  660. }
  661. // if pVar is BSTR, convert to multibytes
  662. if ( vt == VT_VARIANT )
  663. {
  664. pVar = (VARIANT*)V_BSTR(pVar);
  665. vt = V_VT(pVar);
  666. if ( fByRef = vt & VT_BYREF )
  667. {
  668. vt &= ~VT_BYREF;
  669. }
  670. }
  671. if ( vt == VT_BSTR )
  672. {
  673. hr = GetStringFromBSTR(
  674. fByRef ? *(BSTR*)V_BSTR(pVar) : V_BSTR(pVar),
  675. psz,
  676. pdwLen,
  677. fAddDelim
  678. );
  679. }
  680. else if( vt == (VT_ARRAY | VT_UI1) )
  681. {
  682. long lBound, uBound, lItem;
  683. BYTE bValue;
  684. SAFEARRAY* pSafeArray;
  685. // array of VT_UI1 (probably OctetString)
  686. pSafeArray = fByRef ? *(SAFEARRAY**)V_BSTR(pVar) : V_ARRAY( pVar );
  687. hr = SafeArrayGetLBound(pSafeArray, 1, &lBound);
  688. hr = SafeArrayGetUBound(pSafeArray, 1, &uBound);
  689. cV = uBound - lBound + 1;
  690. if ( !(pbV = (LPBYTE)malloc(cV)) )
  691. {
  692. hr = E_OUTOFMEMORY;
  693. VariantClear( &vOut );
  694. return hr;
  695. }
  696. hr = S_OK;
  697. for( lItem = lBound; lItem <= uBound ; lItem++ )
  698. {
  699. hr = SafeArrayGetElement( pSafeArray, &lItem, &bValue );
  700. if( FAILED( hr ) )
  701. {
  702. break;
  703. }
  704. pbV[lItem-lBound] = bValue;
  705. }
  706. *psz = (LPSTR)pbV;
  707. *pdwLen = cV;
  708. }
  709. else if( vt == (VT_ARRAY | VT_VARIANT) )
  710. {
  711. long lBound, uBound, lItem;
  712. VARIANT vValue;
  713. BYTE bValue;
  714. SAFEARRAY* pSafeArray;
  715. // array of VT_VARIANT (probably VT_I4 )
  716. pSafeArray = fByRef ? *(SAFEARRAY**)V_BSTR(pVar) : V_ARRAY( pVar );
  717. hr = SafeArrayGetLBound(pSafeArray, 1, &lBound);
  718. hr = SafeArrayGetUBound(pSafeArray, 1, &uBound);
  719. cV = uBound - lBound + 1;
  720. if ( !(pbV = (LPBYTE)malloc(cV)) )
  721. {
  722. hr = E_OUTOFMEMORY;
  723. VariantClear( &vOut );
  724. return hr;
  725. }
  726. hr = S_OK;
  727. for( lItem = lBound; lItem <= uBound ; lItem++ )
  728. {
  729. hr = SafeArrayGetElement( pSafeArray, &lItem, &vValue );
  730. if( FAILED( hr ) )
  731. {
  732. break;
  733. }
  734. if ( V_VT(&vValue) == VT_UI1 )
  735. {
  736. bValue = V_UI1(&vValue);
  737. }
  738. else if ( V_VT(&vValue) == VT_I2 )
  739. {
  740. bValue = (BYTE)V_I2(&vValue);
  741. }
  742. else if ( V_VT(&vValue) == VT_I4 )
  743. {
  744. bValue = (BYTE)V_I4(&vValue);
  745. }
  746. else
  747. {
  748. bValue = 0;
  749. }
  750. pbV[lItem-lBound] = bValue;
  751. }
  752. *psz = (LPSTR)pbV;
  753. *pdwLen = cV;
  754. }
  755. else
  756. {
  757. hr = E_FAIL;
  758. }
  759. VariantClear( &vOut );
  760. if(FAILED(hr))
  761. {
  762. *psz = NULL;
  763. *pdwLen = 0;
  764. free(pbV);
  765. pbV = NULL;
  766. }
  767. return hr;
  768. }
  769. VOID CCertMapperMethod::FreeString(
  770. LPSTR psz
  771. )
  772. {
  773. if ( psz )
  774. {
  775. free( psz );
  776. }
  777. }
  778. HRESULT CCertMapperMethod::SetBSTR(
  779. BSTR* pbstrRet,
  780. DWORD cch,
  781. LPBYTE sz
  782. )
  783. {
  784. BSTR bstrRet;
  785. if (sz == NULL)
  786. {
  787. *pbstrRet = NULL;
  788. return(NOERROR);
  789. }
  790. // Allocate a string of the desired length
  791. // SysAllocStringLen allocates enough room for unicode characters plus a null
  792. // Given a NULL string it will just allocate the space
  793. bstrRet = SysAllocStringLen(NULL, cch);
  794. if (bstrRet == NULL)
  795. {
  796. return(E_OUTOFMEMORY);
  797. }
  798. // If we were given "", we will have cch=0. return the empty bstr
  799. // otherwise, really copy/convert the string
  800. // NOTE we pass -1 as 4th parameter of MultiByteToWideChar for DBCS support
  801. if (cch != 0)
  802. {
  803. UINT cchTemp = 0;
  804. if (MultiByteToWideChar(CP_ACP, 0, (LPSTR)sz, -1, bstrRet, cch+1) == 0)
  805. {
  806. return(HRESULT_FROM_WIN32(GetLastError()));
  807. }
  808. // If there are some DBCS characters in the sz(Input), then, the character count of BSTR(DWORD) is
  809. // already set to cch(strlen(sz)) in SysAllocStringLen(NULL, cch), we cannot change the count,
  810. // and later call of SysStringLen(bstr) always returns the number of characters specified in the
  811. // cch parameter at allocation time. Bad, because one DBCS character(2 bytes) will convert
  812. // to one UNICODE character(2 bytes), not 2 UNICODE characters(4 bytes).
  813. // Example: For input sz contains only one DBCS character, we want to see SysStringLen(bstr)
  814. // = 1, not 2.
  815. bstrRet[cch] = 0;
  816. cchTemp = wcslen(bstrRet);
  817. if (cchTemp < cch)
  818. {
  819. BSTR bstrTemp = SysAllocString(bstrRet);
  820. SysFreeString(bstrRet);
  821. bstrRet = bstrTemp;
  822. cch = cchTemp;
  823. }
  824. }
  825. bstrRet[cch] = 0;
  826. *pbstrRet = bstrRet;
  827. return(NOERROR);
  828. }
  829. HRESULT CCertMapperMethod::Init(
  830. LPCWSTR pszMetabasePath
  831. )
  832. {
  833. DBG_ASSERT(pszMetabasePath != NULL);
  834. UINT cL;
  835. cL = wcslen( pszMetabasePath );
  836. while ( cL && pszMetabasePath[cL-1] != L'/' && pszMetabasePath[cL-1] != L'\\' )
  837. {
  838. --cL;
  839. }
  840. if ( m_pszMetabasePath = (LPWSTR)malloc( cL*sizeof(WCHAR) + sizeof(L"<nsepm>") ) )
  841. {
  842. memcpy( m_pszMetabasePath, pszMetabasePath, cL * sizeof(WCHAR) );
  843. memcpy( m_pszMetabasePath + cL, L"<nsepm>", sizeof(L"<nsepm>") );
  844. }
  845. else
  846. {
  847. return E_OUTOFMEMORY;
  848. }
  849. return S_OK;
  850. }
  851. HRESULT CCertMapperMethod::SetVariantAsByteArray(
  852. VARIANT* pvarReturn,
  853. DWORD cbLen,
  854. LPBYTE pbIn
  855. )
  856. {
  857. SAFEARRAYBOUND rgsabound[1];
  858. BYTE * pbData = NULL;
  859. // Set the variant type of the output parameter
  860. V_VT(pvarReturn) = VT_ARRAY|VT_UI1;
  861. V_ARRAY(pvarReturn) = NULL;
  862. // Allocate a SafeArray for the data
  863. rgsabound[0].lLbound = 0;
  864. rgsabound[0].cElements = cbLen;
  865. V_ARRAY(pvarReturn) = SafeArrayCreate(VT_UI1, 1, rgsabound);
  866. if (V_ARRAY(pvarReturn) == NULL)
  867. {
  868. return E_OUTOFMEMORY;
  869. }
  870. if (FAILED(SafeArrayAccessData(V_ARRAY(pvarReturn), (void **) &pbData)))
  871. {
  872. return E_UNEXPECTED;
  873. }
  874. memcpy(pbData, pbIn, cbLen );
  875. SafeArrayUnaccessData(V_ARRAY(pvarReturn));
  876. return NOERROR;
  877. }
  878. HRESULT CCertMapperMethod::SetVariantAsBSTR(
  879. VARIANT* pvarReturn,
  880. DWORD cbLen,
  881. LPBYTE pbIn
  882. )
  883. {
  884. V_VT(pvarReturn) = VT_BSTR;
  885. return SetBSTR( &V_BSTR(pvarReturn), cbLen, pbIn );
  886. }
  887. HRESULT CCertMapperMethod::SetVariantAsLong(
  888. VARIANT* pvarReturn,
  889. DWORD dwV
  890. )
  891. {
  892. V_VT(pvarReturn) = VT_I4;
  893. V_I4(pvarReturn) = dwV;
  894. return S_OK;
  895. }
  896. HRESULT CCertMapperMethod::OpenAdminBaseKey(
  897. LPWSTR pszPathName,
  898. DWORD dwAccessType
  899. )
  900. {
  901. if(m_hmd)
  902. CloseAdminBaseKey();
  903. HRESULT t_hr = m_pIABase->OpenKey(
  904. METADATA_MASTER_ROOT_HANDLE,
  905. pszPathName,
  906. dwAccessType,
  907. DEFAULT_TIMEOUT_VALUE, // 30 seconds
  908. &m_hmd
  909. );
  910. if(FAILED(t_hr))
  911. m_hmd = NULL;
  912. return t_hr;
  913. }
  914. VOID CCertMapperMethod::CloseAdminBaseKey()
  915. {
  916. if(m_hmd && m_pIABase)
  917. {
  918. m_pIABase->CloseKey(m_hmd);
  919. m_hmd = NULL;
  920. }
  921. }