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.

1988 lines
40 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. crmap.cxx
  5. Abstract:
  6. ADSIIS cert mapper object
  7. Author:
  8. Philippe Choquier (phillich) 10-Apr-1997
  9. --*/
  10. #include "iisext.hxx"
  11. #pragma hdrstop
  12. #include <nsepname.hxx>
  13. #include <dbgutil.h>
  14. DEFINE_IPrivateDispatch_Implementation(CIISDsCrMap)
  15. DEFINE_DELEGATING_IDispatch_Implementation(CIISDsCrMap)
  16. DEFINE_CONTAINED_IADs_Implementation(CIISDsCrMap)
  17. DEFINE_IADsExtension_Implementation(CIISDsCrMap)
  18. #define LOCAL_MAX_SIZE 32
  19. //
  20. // Local functions
  21. //
  22. HRESULT
  23. GetStringFromBSTR(
  24. BSTR bstr,
  25. LPSTR* psz,
  26. LPDWORD pdwLen,
  27. BOOL fAddDelimInCount = TRUE
  28. );
  29. HRESULT
  30. GetStringFromVariant(
  31. VARIANT* pVar,
  32. LPSTR* psz,
  33. LPDWORD pdwLen,
  34. BOOL fAddDelimInCount = TRUE
  35. );
  36. VOID
  37. FreeString(
  38. LPSTR psz
  39. );
  40. HRESULT
  41. SetBSTR(
  42. BSTR* pbstrRet,
  43. DWORD cch,
  44. LPBYTE sz
  45. );
  46. HRESULT
  47. SetVariantAsByteArray(
  48. VARIANT* pvarReturn,
  49. DWORD cbLen,
  50. LPBYTE pbIn
  51. );
  52. HRESULT
  53. SetVariantAsBSTR(
  54. VARIANT* pvarReturn,
  55. DWORD cbLen,
  56. LPBYTE pbIn
  57. );
  58. HRESULT
  59. SetVariantAsLong(
  60. VARIANT* pvarReturn,
  61. DWORD dwV
  62. );
  63. HRESULT
  64. VariantResolveDispatch(
  65. VARIANT * pVarOut,
  66. VARIANT * pVarIn
  67. );
  68. //
  69. //
  70. //
  71. HRESULT
  72. CIISDsCrMap::CreateMapping(
  73. VARIANT vCert,
  74. BSTR bstrNtAcct,
  75. BSTR bstrNtPwd,
  76. BSTR bstrName,
  77. LONG lEnabled
  78. )
  79. /*++
  80. Routine Description:
  81. Create a mapping entry
  82. Arguments:
  83. vCert - X.509 certificate
  84. bstrNtAcct - NT acct to map to
  85. bstrNtPwd - NT pwd
  86. bstrName - friendly name for mapping entry
  87. lEnabled - 1 to enable mapping entry, 0 to disable it
  88. Returns:
  89. COM status
  90. --*/
  91. {
  92. HRESULT hres;
  93. LPBYTE pbCert = NULL;
  94. DWORD cCert;
  95. LPSTR pszNtAcct = NULL;
  96. LPSTR pszNtPwd = NULL;
  97. LPSTR pszName = NULL;
  98. LPBYTE pRes;
  99. DWORD cRes;
  100. DWORD cName;
  101. DWORD cNtAcct;
  102. DWORD cNtPwd;
  103. WCHAR achIndex[LOCAL_MAX_SIZE];
  104. VARIANT vOldAcct;
  105. VARIANT vOldCert;
  106. VARIANT vOldPwd;
  107. VARIANT vOldName;
  108. VARIANT vOldEnabledFlag;
  109. PCCERT_CONTEXT pcCert = NULL;
  110. //
  111. // Do some sanity checks on the cert
  112. //
  113. if ( SUCCEEDED( hres = GetStringFromVariant( &vCert,
  114. (LPSTR*)&pbCert,
  115. &cCert,
  116. FALSE ) ) )
  117. {
  118. //
  119. // try to construct a cert context
  120. //
  121. if ( !( pcCert = CertCreateCertificateContext( X509_ASN_ENCODING,
  122. pbCert,
  123. cCert ) ) )
  124. {
  125. DBGPRINTF((DBG_CONTEXT,
  126. "Invalid cert passed to CreateMapping()\n"));
  127. //
  128. // If the decoding fails, GetLastError() returns an ASN1 decoding
  129. // error that is obtained by subtracting CRYPT_E_OSS_ERROR from the returned
  130. // error and looking in file asn1code.h for the actual error. To avoid the
  131. // cryptic ASN1 errors, we'll just return a general "invalid arg" error
  132. //
  133. hres = RETURNCODETOHRESULT( E_INVALIDARG );
  134. FreeString( (LPSTR) pbCert );
  135. goto Exit;
  136. }
  137. CertFreeCertificateContext( pcCert );
  138. }
  139. else
  140. {
  141. goto Exit;
  142. }
  143. //
  144. // check if we already have a mapping for this cert; if we do, we'll replace that mapping
  145. // with the new one
  146. //
  147. if ( SUCCEEDED( hres = GetMapping( IISMAPPER_LOCATE_BY_CERT,
  148. vCert,
  149. &vOldCert,
  150. &vOldAcct,
  151. &vOldPwd,
  152. &vOldName,
  153. &vOldEnabledFlag ) ) )
  154. {
  155. DBGPRINTF((DBG_CONTEXT,
  156. "Replacing old 1-1 cert mapping with new mapping\n"));
  157. if ( FAILED( hres = SetName( IISMAPPER_LOCATE_BY_CERT,
  158. vCert,
  159. bstrName ) ) ||
  160. FAILED( hres = SetAcct( IISMAPPER_LOCATE_BY_CERT,
  161. vCert,
  162. bstrNtAcct ) ) ||
  163. FAILED( hres = SetPwd( IISMAPPER_LOCATE_BY_CERT,
  164. vCert,
  165. bstrNtPwd ) ) ||
  166. FAILED( hres = SetEnabled( IISMAPPER_LOCATE_BY_CERT,
  167. vCert,
  168. lEnabled ) ) )
  169. {
  170. hres; //NOP - Something failed
  171. }
  172. }
  173. //
  174. // New mapping
  175. //
  176. else if ( hres == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
  177. {
  178. //
  179. // check mapping exists, create if not
  180. //
  181. hres = OpenMd( L"Cert11", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
  182. if ( hres == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
  183. {
  184. if ( SUCCEEDED( hres = OpenMd( L"",
  185. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  186. {
  187. hres = CreateMdObject( L"Cert11" );
  188. CloseMd( FALSE );
  189. // Reopen to the correct node.
  190. hres = OpenMd( L"Cert11", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
  191. }
  192. }
  193. if ( FAILED( hres ) )
  194. {
  195. goto Exit;
  196. }
  197. //
  198. // adding mapping cert "0" means add @ end of list
  199. //
  200. if ( SUCCEEDED( hres = CreateMdObject( L"mappings/0" ) ) )
  201. {
  202. if ( SUCCEEDED( hres = GetMdData( L"", MD_NSEPM_ACCESS_CERT, DWORD_METADATA, &
  203. cRes, &pRes ) ) )
  204. {
  205. if ( cRes == sizeof(DWORD ) )
  206. {
  207. wsprintfW( achIndex, L"mappings/%u", *(LPDWORD)pRes );
  208. if ( FAILED( hres = GetStringFromBSTR( bstrNtAcct, &pszNtAcct, &cNtAcct ) ) ||
  209. FAILED( hres = GetStringFromBSTR( bstrNtPwd, &pszNtPwd, &cNtPwd ) ) ||
  210. FAILED( hres = GetStringFromBSTR( bstrName, &pszName, &cName ) ) ||
  211. FAILED( hres = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA,
  212. sizeof(DWORD), (LPBYTE)&lEnabled ) ) ||
  213. FAILED( hres = SetMdData( achIndex, MD_MAPNAME, STRING_METADATA,
  214. cName, (LPBYTE)pszName ) ) ||
  215. FAILED( hres = SetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA,
  216. cNtPwd, (LPBYTE)pszNtPwd ) ) ||
  217. FAILED( hres = SetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA,
  218. cNtAcct, (LPBYTE)pszNtAcct ) ) ||
  219. FAILED( hres = SetMdData( achIndex, MD_MAPCERT, BINARY_METADATA,
  220. cCert, (LPBYTE)pbCert ) ) )
  221. {
  222. }
  223. }
  224. else
  225. {
  226. hres = E_FAIL;
  227. }
  228. }
  229. }
  230. }
  231. CloseMd( SUCCEEDED( hres ) );
  232. FreeString( (LPSTR)pbCert );
  233. FreeString( pszNtAcct );
  234. FreeString( pszNtPwd );
  235. FreeString( pszName );
  236. Exit:
  237. return hres;
  238. }
  239. HRESULT
  240. CIISDsCrMap::GetMapping(
  241. LONG lMethod,
  242. VARIANT vKey,
  243. VARIANT* pvCert,
  244. VARIANT* pbstrNtAcct,
  245. VARIANT* pbstrNtPwd,
  246. VARIANT* pbstrName,
  247. VARIANT* plEnabled
  248. )
  249. /*++
  250. Routine Description:
  251. Get a mapping entry using key
  252. Arguments:
  253. lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  254. vKey - key to use to locate mapping
  255. pvCert - X.509 certificate
  256. pbstrNtAcct - NT acct to map to
  257. pbstrNtPwd - NT pwd
  258. pbstrName - friendly name for mapping entry
  259. plEnabled - 1 to enable mapping entry, 0 to disable it
  260. Returns:
  261. COM status
  262. --*/
  263. {
  264. WCHAR achIndex[LOCAL_MAX_SIZE];
  265. HRESULT hres;
  266. DWORD dwLen;
  267. LPBYTE pbData;
  268. VariantInit( pvCert );
  269. VariantInit( pbstrNtAcct );
  270. VariantInit( pbstrNtPwd );
  271. VariantInit( pbstrName );
  272. VariantInit( plEnabled );
  273. if ( SUCCEEDED( hres = OpenMd( L"Cert11",
  274. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  275. {
  276. if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
  277. {
  278. if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPCERT, BINARY_METADATA, &dwLen,
  279. &pbData ) ) )
  280. {
  281. hres = SetVariantAsByteArray( pvCert, dwLen, pbData );
  282. LocalFree( pbData );
  283. }
  284. else
  285. {
  286. goto Done;
  287. }
  288. if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA, &dwLen,
  289. &pbData ) ) )
  290. {
  291. hres = SetVariantAsBSTR( pbstrNtAcct, dwLen, pbData );
  292. LocalFree( pbData );
  293. }
  294. else
  295. {
  296. goto Done;
  297. }
  298. if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA, &dwLen,
  299. &pbData ) ) )
  300. {
  301. hres = SetVariantAsBSTR( pbstrNtPwd, dwLen, pbData );
  302. LocalFree( pbData );
  303. }
  304. else
  305. {
  306. goto Done;
  307. }
  308. if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPNAME, STRING_METADATA, &dwLen,
  309. &pbData ) ) )
  310. {
  311. hres = SetVariantAsBSTR( pbstrName, dwLen, pbData );
  312. LocalFree( pbData );
  313. }
  314. else
  315. {
  316. goto Done;
  317. }
  318. if ( FAILED( hres = GetMdData( achIndex, MD_MAPENABLED, STRING_METADATA, &dwLen,
  319. &pbData ) ) )
  320. {
  321. SetVariantAsLong( plEnabled, FALSE );
  322. }
  323. else
  324. {
  325. SetVariantAsLong( plEnabled, *(LPDWORD)pbData );
  326. LocalFree( pbData );
  327. }
  328. }
  329. Done:
  330. CloseMd( FALSE );
  331. }
  332. return hres;
  333. }
  334. HRESULT
  335. CIISDsCrMap::DeleteMapping(
  336. LONG lMethod,
  337. VARIANT vKey
  338. )
  339. /*++
  340. Routine Description:
  341. Delete a mapping entry using key
  342. Arguments:
  343. lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  344. vKey - key to use to locate mapping
  345. Returns:
  346. COM status
  347. --*/
  348. {
  349. WCHAR achIndex[LOCAL_MAX_SIZE];
  350. HRESULT hres;
  351. if ( SUCCEEDED( hres = OpenMd( L"Cert11",
  352. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  353. {
  354. if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
  355. {
  356. hres = DeleteMdObject( achIndex );
  357. }
  358. CloseMd( TRUE );
  359. }
  360. return hres;
  361. }
  362. HRESULT
  363. CIISDsCrMap::SetEnabled(
  364. LONG lMethod,
  365. VARIANT vKey,
  366. LONG lEnabled
  367. )
  368. /*++
  369. Routine Description:
  370. Set the enable flag on a mapping entry using key
  371. Arguments:
  372. lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  373. vKey - key to use to locate mapping
  374. lEnabled - 1 to enable, 0 to disable
  375. Returns:
  376. COM status
  377. --*/
  378. {
  379. WCHAR achIndex[LOCAL_MAX_SIZE];
  380. HRESULT hres;
  381. if ( SUCCEEDED( hres = OpenMd( L"Cert11",
  382. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  383. {
  384. if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
  385. {
  386. hres = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA, sizeof(DWORD), (LPBYTE)&lEnabled );
  387. }
  388. CloseMd( TRUE );
  389. }
  390. return hres;
  391. }
  392. HRESULT
  393. CIISDsCrMap::SetName(
  394. LONG lMethod,
  395. VARIANT vKey,
  396. BSTR bstrName
  397. )
  398. /*++
  399. Routine Description:
  400. Set the Name on a mapping entry using key
  401. Arguments:
  402. lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  403. vKey - key to use to locate mapping
  404. bstrName - name to assign to mapping entry
  405. Returns:
  406. COM status
  407. --*/
  408. {
  409. return SetString( lMethod, vKey, bstrName, MD_MAPNAME );
  410. }
  411. HRESULT
  412. CIISDsCrMap::SetString(
  413. LONG lMethod,
  414. VARIANT vKey,
  415. BSTR bstrName,
  416. DWORD dwProp
  417. )
  418. /*++
  419. Routine Description:
  420. Set a string property on a mapping entry using key
  421. Arguments:
  422. lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  423. vKey - key to use to locate mapping
  424. bstrName - string content to assign to mapping entry
  425. dwProp - property ID to assign to
  426. Returns:
  427. COM status
  428. --*/
  429. {
  430. WCHAR achIndex[LOCAL_MAX_SIZE];
  431. LPSTR pszName = NULL;
  432. HRESULT hres;
  433. DWORD dwLen;
  434. if ( FAILED( hres = GetStringFromBSTR( bstrName, &pszName, &dwLen, TRUE ) ) )
  435. {
  436. return hres;
  437. }
  438. if ( SUCCEEDED( hres = OpenMd( L"Cert11",
  439. METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
  440. {
  441. if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
  442. {
  443. hres = SetMdData( achIndex, dwProp, STRING_METADATA, dwLen, (LPBYTE)pszName );
  444. }
  445. CloseMd( TRUE );
  446. }
  447. FreeString( pszName );
  448. return hres;
  449. }
  450. HRESULT
  451. CIISDsCrMap::SetPwd(
  452. LONG lMethod,
  453. VARIANT vKey,
  454. BSTR bstrPwd
  455. )
  456. /*++
  457. Routine Description:
  458. Set the Password on a mapping entry using key
  459. Arguments:
  460. lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  461. vKey - key to use to locate mapping
  462. bstrPwd - password to assign to mapping entry
  463. Returns:
  464. COM status
  465. --*/
  466. {
  467. return SetString( lMethod, vKey, bstrPwd, MD_MAPNTPWD );
  468. }
  469. HRESULT
  470. CIISDsCrMap::SetAcct(
  471. LONG lMethod,
  472. VARIANT vKey,
  473. BSTR bstrAcct
  474. )
  475. /*++
  476. Routine Description:
  477. Set the NT account name on a mapping entry using key
  478. Arguments:
  479. lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  480. vKey - key to use to locate mapping
  481. bstrAcct - NT account name to assign to mapping entry
  482. Returns:
  483. COM status
  484. --*/
  485. {
  486. return SetString( lMethod, vKey, bstrAcct, MD_MAPNTACCT );
  487. }
  488. ////
  489. HRESULT
  490. CIISDsCrMap::OpenMd(
  491. LPWSTR pszOpenPath,
  492. DWORD dwPermission
  493. )
  494. /*++
  495. Routine Description:
  496. Open metabase using path & permission
  497. path is relative to the top of the name space extension ( i.e. /.../<nsepm> )
  498. Arguments:
  499. pszOpenPath - path to open inside name space extension
  500. dwPermission - metabase permission ( read/write )
  501. Returns:
  502. COM status
  503. --*/
  504. {
  505. HRESULT hres;
  506. LPWSTR pszPath;
  507. UINT cL = wcslen( m_pszMetabasePath );
  508. pszPath = (LPWSTR)LocalAlloc( LMEM_FIXED, (wcslen(pszOpenPath) + 1 + cL + 1)*sizeof(WCHAR) );
  509. if ( pszPath == NULL )
  510. {
  511. return E_OUTOFMEMORY;
  512. }
  513. memcpy( pszPath, m_pszMetabasePath, cL * sizeof(WCHAR) );
  514. if ( cL && m_pszMetabasePath[cL-1] != L'/' && *pszOpenPath && *pszOpenPath != L'/' )
  515. {
  516. pszPath[cL++] = L'/';
  517. }
  518. wcscpy( pszPath + cL, pszOpenPath );
  519. hres = OpenAdminBaseKey(
  520. m_pszServerName,
  521. pszPath,
  522. dwPermission,
  523. &m_pcAdmCom,
  524. &m_hmd
  525. );
  526. LocalFree( pszPath );
  527. if ( FAILED(hres) )
  528. {
  529. m_hmd = NULL;
  530. }
  531. return hres;
  532. }
  533. HRESULT
  534. CIISDsCrMap::CloseMd(
  535. BOOL fSave
  536. )
  537. /*++
  538. Routine Description:
  539. close metabase
  540. Arguments:
  541. fSave - TRUE to save data immediatly
  542. Returns:
  543. COM status
  544. --*/
  545. {
  546. CloseAdminBaseKey( m_pcAdmCom, m_hmd );
  547. m_hmd = NULL;
  548. if ( m_pcAdmCom && fSave )
  549. {
  550. m_pcAdmCom->SaveData();
  551. }
  552. return S_OK;
  553. }
  554. HRESULT
  555. CIISDsCrMap::DeleteMdObject(
  556. LPWSTR pszKey
  557. )
  558. /*++
  559. Routine Description:
  560. Delete metabase object in an opened tree
  561. OpenMd() must be called 1st
  562. Arguments:
  563. pszKey - key to delete in opened metabase
  564. Returns:
  565. COM status
  566. --*/
  567. {
  568. return m_pcAdmCom->DeleteKey( m_hmd, pszKey );
  569. }
  570. HRESULT
  571. CIISDsCrMap::CreateMdObject(
  572. LPWSTR pszKey
  573. )
  574. /*++
  575. Routine Description:
  576. Create metabase object in an opened tree
  577. OpenMd() must be called 1st
  578. Arguments:
  579. pszKey - key to create in opened metabase
  580. Returns:
  581. COM status
  582. --*/
  583. {
  584. return m_pcAdmCom->AddKey( m_hmd, pszKey );
  585. }
  586. HRESULT
  587. CIISDsCrMap::SetMdData(
  588. LPWSTR achIndex,
  589. DWORD dwProp,
  590. DWORD dwDataType,
  591. DWORD dwDataLen,
  592. LPBYTE pbData
  593. )
  594. /*++
  595. Routine Description:
  596. Set a metabase property
  597. OpenMd() must be called 1st
  598. Property will be stored with NULL attribute, except for MD_MAPPWD
  599. which will be stored with METADATA_SECURE
  600. Arguments:
  601. achIndex - key name where to store property
  602. dwProp - property ID
  603. dwDataType - property data type
  604. dwDataLen - property length
  605. pbData - property value
  606. Returns:
  607. COM status
  608. --*/
  609. {
  610. METADATA_RECORD md;
  611. md.dwMDDataLen = dwDataLen;
  612. md.dwMDDataType = dwDataType;
  613. md.dwMDIdentifier = dwProp;
  614. md.dwMDAttributes = (dwProp == MD_MAPPWD) ? METADATA_SECURE : 0;
  615. md.pbMDData = pbData;
  616. return m_pcAdmCom->SetData( m_hmd, achIndex, &md );
  617. }
  618. HRESULT
  619. CIISDsCrMap::GetMdData(
  620. LPWSTR achIndex,
  621. DWORD dwProp,
  622. DWORD dwDataType,
  623. LPDWORD pdwDataLen,
  624. LPBYTE* ppbData
  625. )
  626. /*++
  627. Routine Description:
  628. Get a metabase property
  629. OpenMd() must be called 1st
  630. Arguments:
  631. achIndex - key name where to get property
  632. dwProp - property ID
  633. dwDataType - property data type
  634. pdwDataLen - property length
  635. ppData - property value, to be freed using LocalFree() on successfull return
  636. Returns:
  637. COM status
  638. --*/
  639. {
  640. HRESULT hres;
  641. METADATA_RECORD md;
  642. DWORD dwRequired;
  643. md.dwMDDataLen = 0;
  644. md.dwMDDataType = dwDataType;
  645. md.dwMDIdentifier = dwProp;
  646. md.dwMDAttributes = 0;
  647. md.pbMDData = NULL;
  648. if ( FAILED(hres = m_pcAdmCom->GetData( m_hmd, achIndex, &md, &dwRequired )) )
  649. {
  650. if ( hres == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER) )
  651. {
  652. if ( (*ppbData = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired )) == NULL )
  653. {
  654. return E_OUTOFMEMORY;
  655. }
  656. md.pbMDData = *ppbData;
  657. md.dwMDDataLen = dwRequired;
  658. hres = m_pcAdmCom->GetData( m_hmd, achIndex, &md, &dwRequired );
  659. *pdwDataLen = md.dwMDDataLen;
  660. }
  661. }
  662. else
  663. {
  664. *pdwDataLen = 0;
  665. *ppbData = NULL;
  666. }
  667. return hres;
  668. }
  669. //////
  670. HRESULT
  671. CIISDsCrMap::Locate(
  672. LONG lMethod,
  673. VARIANT vKey,
  674. LPWSTR pszResKey
  675. )
  676. /*++
  677. Routine Description:
  678. Locate a mapping entry based on key
  679. OpenMd() must be called 1st
  680. Arguments:
  681. lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
  682. vKey - key to use to locate mapping
  683. pszResKey -
  684. Returns:
  685. COM status
  686. --*/
  687. {
  688. HRESULT hres;
  689. LPSTR pV = NULL;
  690. DWORD cV;
  691. DWORD dwProp;
  692. LPSTR pRes;
  693. DWORD cRes;
  694. BOOL fAddDelim = TRUE;
  695. //
  696. // determine method
  697. //
  698. switch ( lMethod )
  699. {
  700. case IISMAPPER_LOCATE_BY_CERT:
  701. dwProp = MD_NSEPM_ACCESS_CERT;
  702. fAddDelim = FALSE;
  703. break;
  704. case IISMAPPER_LOCATE_BY_NAME:
  705. dwProp = MD_NSEPM_ACCESS_NAME;
  706. break;
  707. case IISMAPPER_LOCATE_BY_ACCT:
  708. dwProp = MD_NSEPM_ACCESS_ACCOUNT;
  709. break;
  710. case IISMAPPER_LOCATE_BY_INDEX:
  711. if ( SUCCEEDED( hres = GetStringFromVariant( &vKey, &pV, &cV, TRUE ) ) )
  712. {
  713. WCHAR pwV[LOCAL_MAX_SIZE];
  714. int i = MultiByteToWideChar(CP_ACP, 0, pV, cV, pwV, LOCAL_MAX_SIZE);
  715. if (i ==0)
  716. return E_FAIL; // MultiByteToWideChar failure
  717. if (i >= (int)(LOCAL_MAX_SIZE - wcslen(L"mappings/")))
  718. return E_FAIL; //pwV is too big for pszResKey
  719. wsprintfW( pszResKey, L"mappings/%s", pwV );
  720. }
  721. goto Exit;
  722. default:
  723. return E_FAIL;
  724. }
  725. //
  726. // get ptr to data
  727. //
  728. if ( SUCCEEDED( hres = GetStringFromVariant( &vKey, &pV, &cV, fAddDelim ) ) )
  729. {
  730. //
  731. // set search prop, get result
  732. //
  733. if ( SUCCEEDED( hres = SetMdData( L"", dwProp, BINARY_METADATA, cV, (LPBYTE)pV ) ) )
  734. {
  735. if ( SUCCEEDED( hres = GetMdData( L"", dwProp, DWORD_METADATA, &cRes, (LPBYTE*)&pRes ) ) )
  736. {
  737. if ( cRes == sizeof(DWORD ) )
  738. {
  739. wsprintfW( pszResKey, L"mappings/%u", *(LPDWORD)pRes );
  740. }
  741. else
  742. {
  743. hres = E_FAIL;
  744. }
  745. LocalFree( pRes );
  746. }
  747. }
  748. }
  749. Exit:
  750. FreeString( pV );
  751. return hres;
  752. }
  753. HRESULT
  754. GetStringFromBSTR(
  755. BSTR bstr,
  756. LPSTR* psz,
  757. LPDWORD pdwLen,
  758. BOOL fAddDelimInCount
  759. )
  760. /*++
  761. Routine Description:
  762. Allocate string buffer from BSTR
  763. Arguments:
  764. bstr - bstr to convert from
  765. psz - updated with ptr to buffer, to be freed with FreeString()
  766. pdwLen - updated with strlen(string), incremented by 1 if fAddDelimInCount is TRUE
  767. fAddDelimInCount - TRUE to increment *pdwLen
  768. Returns:
  769. COM status
  770. --*/
  771. {
  772. UINT cch = SysStringLen(bstr);
  773. UINT cchT;
  774. // include NULL terminator
  775. *pdwLen = cch + (fAddDelimInCount ? 1 : 0);
  776. CHAR *szNew = (CHAR*)LocalAlloc( LMEM_FIXED, (2 * cch) + 1); // * 2 for worst case DBCS string
  777. if (szNew == NULL)
  778. {
  779. return E_OUTOFMEMORY;
  780. }
  781. cchT = WideCharToMultiByte(CP_ACP, 0, bstr, cch + 1, szNew, (2 * cch) + 1, NULL, NULL);
  782. *psz = szNew;
  783. return NOERROR;
  784. }
  785. HRESULT
  786. GetStringFromVariant(
  787. VARIANT* pVar,
  788. LPSTR* psz,
  789. LPDWORD pdwLen,
  790. BOOL fAddDelim
  791. )
  792. /*++
  793. Routine Description:
  794. Allocate string buffer from BSTR
  795. Arguments:
  796. pVar - variant to convert from. Recognizes BSTR, VT_ARRAY|VT_UI1, ByRef or ByVal
  797. psz - updated with ptr to buffer, to be freed with FreeString()
  798. pdwLen - updated with size of input, incremented by 1 if fAddDelimInCount is TRUE
  799. fAddDelimInCount - TRUE to increment *pdwLen
  800. Returns:
  801. COM status
  802. --*/
  803. {
  804. LPBYTE pbV;
  805. UINT cV;
  806. HRESULT hres;
  807. WORD vt = V_VT(pVar);
  808. BOOL fByRef = FALSE;
  809. VARIANT vOut;
  810. VariantInit( &vOut );
  811. if ( vt & VT_BYREF )
  812. {
  813. vt &= ~VT_BYREF;
  814. fByRef = TRUE;
  815. }
  816. if ( vt == VT_DISPATCH )
  817. {
  818. if ( FAILED(hres = VariantResolveDispatch( &vOut, pVar )) )
  819. {
  820. return hres;
  821. }
  822. pVar = &vOut;
  823. vt = V_VT(pVar);
  824. if ( fByRef = vt & VT_BYREF )
  825. {
  826. vt &= ~VT_BYREF;
  827. }
  828. }
  829. // if pVar is BSTR, convert to multibytes
  830. if ( vt == VT_VARIANT )
  831. {
  832. pVar = (VARIANT*)V_BSTR(pVar);
  833. vt = V_VT(pVar);
  834. if ( fByRef = vt & VT_BYREF )
  835. {
  836. vt &= ~VT_BYREF;
  837. }
  838. }
  839. if ( vt == VT_BSTR )
  840. {
  841. hres = GetStringFromBSTR( fByRef ?
  842. *(BSTR*)V_BSTR(pVar) :
  843. V_BSTR(pVar),
  844. psz,
  845. pdwLen,
  846. fAddDelim );
  847. }
  848. else if( vt == (VT_ARRAY | VT_UI1) )
  849. {
  850. long lBound, uBound, lItem;
  851. BYTE bValue;
  852. SAFEARRAY* pSafeArray;
  853. // array of VT_UI1 (probably OctetString)
  854. pSafeArray = fByRef ? *(SAFEARRAY**)V_BSTR(pVar) : V_ARRAY( pVar );
  855. hres = SafeArrayGetLBound(pSafeArray, 1, &lBound);
  856. hres = SafeArrayGetUBound(pSafeArray, 1, &uBound);
  857. cV = uBound - lBound + 1;
  858. if ( !(pbV = (LPBYTE)LocalAlloc( LMEM_FIXED, cV )) )
  859. {
  860. hres = E_OUTOFMEMORY;
  861. goto Exit;
  862. }
  863. hres = S_OK;
  864. for( lItem = lBound; lItem <= uBound ; lItem++ )
  865. {
  866. hres = SafeArrayGetElement( pSafeArray, &lItem, &bValue );
  867. if( FAILED( hres ) )
  868. {
  869. break;
  870. }
  871. pbV[lItem-lBound] = bValue;
  872. }
  873. *psz = (LPSTR)pbV;
  874. *pdwLen = cV;
  875. }
  876. else if( vt == (VT_ARRAY | VT_VARIANT) )
  877. {
  878. long lBound, uBound, lItem;
  879. VARIANT vValue;
  880. BYTE bValue;
  881. SAFEARRAY* pSafeArray;
  882. // array of VT_VARIANT (probably VT_I4 )
  883. pSafeArray = fByRef ? *(SAFEARRAY**)V_BSTR(pVar) : V_ARRAY( pVar );
  884. hres = SafeArrayGetLBound(pSafeArray, 1, &lBound);
  885. hres = SafeArrayGetUBound(pSafeArray, 1, &uBound);
  886. cV = uBound - lBound + 1;
  887. if ( !(pbV = (LPBYTE)LocalAlloc( LMEM_FIXED, cV )) )
  888. {
  889. hres = E_OUTOFMEMORY;
  890. goto Exit;
  891. }
  892. hres = S_OK;
  893. for( lItem = lBound; lItem <= uBound ; lItem++ )
  894. {
  895. hres = SafeArrayGetElement( pSafeArray, &lItem, &vValue );
  896. if( FAILED( hres ) )
  897. {
  898. break;
  899. }
  900. if ( V_VT(&vValue) == VT_UI1 )
  901. {
  902. bValue = V_UI1(&vValue);
  903. }
  904. else if ( V_VT(&vValue) == VT_I2 )
  905. {
  906. bValue = (BYTE)V_I2(&vValue);
  907. }
  908. else if ( V_VT(&vValue) == VT_I4 )
  909. {
  910. bValue = (BYTE)V_I4(&vValue);
  911. }
  912. else
  913. {
  914. bValue = 0;
  915. }
  916. pbV[lItem-lBound] = bValue;
  917. }
  918. *psz = (LPSTR)pbV;
  919. *pdwLen = cV;
  920. }
  921. else
  922. {
  923. hres = E_FAIL;
  924. }
  925. Exit:
  926. VariantClear( &vOut );
  927. return hres;
  928. }
  929. VOID
  930. FreeString(
  931. LPSTR psz
  932. )
  933. /*++
  934. Routine Description:
  935. Free a string returned by GetStringFromVariant() or GetStringFromBTR()
  936. can be NULL
  937. Arguments:
  938. psz - string to free, can be NULL
  939. Returns:
  940. Nothing
  941. --*/
  942. {
  943. if ( psz )
  944. {
  945. LocalFree( psz );
  946. }
  947. }
  948. HRESULT
  949. SetBSTR(
  950. BSTR* pbstrRet,
  951. DWORD cch,
  952. LPBYTE sz
  953. )
  954. /*++
  955. Routine Description:
  956. Build a BSTR from byte array
  957. Arguments:
  958. pbstrRet - updated with BSTR
  959. cch - byte count in sz
  960. sz - byte array
  961. Returns:
  962. COM status
  963. --*/
  964. {
  965. BSTR bstrRet;
  966. if (sz == NULL)
  967. {
  968. *pbstrRet = NULL;
  969. return(NOERROR);
  970. }
  971. // Allocate a string of the desired length
  972. // SysAllocStringLen allocates enough room for unicode characters plus a null
  973. // Given a NULL string it will just allocate the space
  974. bstrRet = SysAllocStringLen(NULL, cch);
  975. if (bstrRet == NULL)
  976. {
  977. return(E_OUTOFMEMORY);
  978. }
  979. // If we were given "", we will have cch=0. return the empty bstr
  980. // otherwise, really copy/convert the string
  981. // NOTE we pass -1 as 4th parameter of MultiByteToWideChar for DBCS support
  982. if (cch != 0)
  983. {
  984. UINT cchTemp = 0;
  985. if (MultiByteToWideChar(CP_ACP, 0, (LPSTR)sz, -1, bstrRet, cch+1) == 0)
  986. {
  987. return(HRESULT_FROM_WIN32(GetLastError()));
  988. }
  989. // If there are some DBCS characters in the sz(Input), then, the character count of BSTR(DWORD) is
  990. // already set to cch(strlen(sz)) in SysAllocStringLen(NULL, cch), we cannot change the count,
  991. // and later call of SysStringLen(bstr) always returns the number of characters specified in the
  992. // cch parameter at allocation time. Bad, because one DBCS character(2 bytes) will convert
  993. // to one UNICODE character(2 bytes), not 2 UNICODE characters(4 bytes).
  994. // Example: For input sz contains only one DBCS character, we want to see SysStringLen(bstr)
  995. // = 1, not 2.
  996. bstrRet[cch] = 0;
  997. cchTemp = wcslen(bstrRet);
  998. if (cchTemp < cch)
  999. {
  1000. BSTR bstrTemp = SysAllocString(bstrRet);
  1001. SysFreeString(bstrRet);
  1002. bstrRet = bstrTemp;
  1003. cch = cchTemp;
  1004. }
  1005. }
  1006. if (bstrRet != NULL)
  1007. bstrRet[cch] = 0;
  1008. *pbstrRet = bstrRet;
  1009. return(NOERROR);
  1010. }
  1011. HRESULT
  1012. CIISDsCrMap::Create(
  1013. IUnknown *pUnkOuter,
  1014. REFIID riid,
  1015. void **ppvObj
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. Create a CIISDsCrMap
  1020. Arguments:
  1021. pUnkOuter - ptr to iunknown
  1022. riid - requested IID
  1023. ppvObj - updated with ptr to requested IID
  1024. Returns:
  1025. COM status
  1026. --*/
  1027. {
  1028. CCredentials Credentials;
  1029. CIISDsCrMap FAR * pMap = NULL;
  1030. HRESULT hr = S_OK;
  1031. BSTR bstrAdsPath = NULL;
  1032. OBJECTINFO ObjectInfo;
  1033. POBJECTINFO pObjectInfo = &ObjectInfo;
  1034. CLexer * pLexer = NULL;
  1035. LPWSTR pszIISPathName = NULL;
  1036. hr = AllocateObject(pUnkOuter, Credentials, &pMap);
  1037. BAIL_ON_FAILURE(hr);
  1038. //
  1039. // get ServerName and pszPath
  1040. //
  1041. hr = pMap->_pADs->get_ADsPath(&bstrAdsPath);
  1042. BAIL_ON_FAILURE(hr);
  1043. pLexer = new CLexer();
  1044. hr = pLexer->Initialize(bstrAdsPath);
  1045. BAIL_ON_FAILURE(hr);
  1046. //
  1047. // Parse the pathname
  1048. //
  1049. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  1050. hr = ADsObject(pLexer, pObjectInfo);
  1051. BAIL_ON_FAILURE(hr);
  1052. pszIISPathName = AllocADsStr(bstrAdsPath);
  1053. if (!pszIISPathName) {
  1054. hr = E_OUTOFMEMORY;
  1055. BAIL_ON_FAILURE(hr);
  1056. }
  1057. *pszIISPathName = L'\0';
  1058. hr = BuildIISPathFromADsPath(
  1059. pObjectInfo,
  1060. pszIISPathName
  1061. );
  1062. BAIL_ON_FAILURE(hr);
  1063. hr = pMap->Init( pObjectInfo->TreeName,
  1064. pszIISPathName );
  1065. BAIL_ON_FAILURE(hr);
  1066. //
  1067. // pass non-delegating IUnknown back to the aggregator
  1068. //
  1069. *ppvObj = (INonDelegatingUnknown FAR *) pMap;
  1070. if (bstrAdsPath) {
  1071. ADsFreeString(bstrAdsPath);
  1072. }
  1073. if (pLexer) {
  1074. delete pLexer;
  1075. }
  1076. if (pszIISPathName ) {
  1077. FreeADsStr( pszIISPathName );
  1078. }
  1079. FreeObjectInfo( &ObjectInfo );
  1080. RRETURN(hr);
  1081. error:
  1082. if (bstrAdsPath) {
  1083. ADsFreeString(bstrAdsPath);
  1084. }
  1085. if (pLexer) {
  1086. delete pLexer;
  1087. }
  1088. if (pszIISPathName ) {
  1089. FreeADsStr( pszIISPathName );
  1090. }
  1091. FreeObjectInfo( &ObjectInfo );
  1092. *ppvObj = NULL;
  1093. delete pMap;
  1094. RRETURN(hr);
  1095. }
  1096. STDMETHODIMP
  1097. CIISDsCrMap::QueryInterface(
  1098. REFIID iid,
  1099. LPVOID FAR* ppv
  1100. )
  1101. /*++
  1102. Routine Description:
  1103. Query interface to CIISDsCrMap
  1104. Arguments:
  1105. iid - requested IID
  1106. ppv - updated with ptr to requested IID
  1107. Returns:
  1108. COM status
  1109. --*/
  1110. {
  1111. HRESULT hr = S_OK;
  1112. hr = _pUnkOuter->QueryInterface(iid,ppv);
  1113. RRETURN(hr);
  1114. }
  1115. CIISDsCrMap::CIISDsCrMap(
  1116. )
  1117. /*++
  1118. Routine Description:
  1119. CIISDsCrMap constructor
  1120. Arguments:
  1121. pADs - ptr to contained ADs
  1122. Credentials - credential
  1123. pDispMgr - ptr to dispatch manager
  1124. Returns:
  1125. Nothing
  1126. --*/
  1127. {
  1128. m_pcAdmCom = NULL;
  1129. m_hmd = NULL;
  1130. m_pszServerName = NULL;
  1131. m_pszMetabasePath = NULL;
  1132. m_ADsPath = NULL;
  1133. _pADs = NULL;
  1134. _pDispMgr = NULL;
  1135. ENLIST_TRACKING(CIISDsCrMap);
  1136. }
  1137. CIISDsCrMap::~CIISDsCrMap(
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. CIISDsCrMap destructor
  1142. Arguments:
  1143. None
  1144. Returns:
  1145. Nothing
  1146. --*/
  1147. {
  1148. if ( m_ADsPath )
  1149. {
  1150. ADsFreeString( m_ADsPath );
  1151. }
  1152. if ( m_pszServerName )
  1153. {
  1154. LocalFree( m_pszServerName );
  1155. }
  1156. if ( m_pszMetabasePath )
  1157. {
  1158. LocalFree( m_pszMetabasePath );
  1159. }
  1160. if ( _pDispMgr )
  1161. {
  1162. delete _pDispMgr;
  1163. }
  1164. }
  1165. HRESULT
  1166. CIISDsCrMap::AllocateObject(
  1167. IUnknown *pUnkOuter,
  1168. CCredentials& Credentials,
  1169. CIISDsCrMap ** ppMap
  1170. )
  1171. /*++
  1172. Routine Description:
  1173. Allocate CIISDsCrMap
  1174. Arguments:
  1175. pUnkOuter - ptr to iunknown
  1176. Credentials - credential
  1177. ppMap - updated with ptr to IUnknown to Allocated object
  1178. Returns:
  1179. COM status
  1180. --*/
  1181. {
  1182. CIISDsCrMap FAR * pMap = NULL;
  1183. IADs FAR * pADs = NULL;
  1184. CAggregateeDispMgr FAR * pDispMgr = NULL;
  1185. HRESULT hr = S_OK;
  1186. pDispMgr = new CAggregateeDispMgr;
  1187. if (pDispMgr == NULL) {
  1188. hr = E_OUTOFMEMORY;
  1189. }
  1190. BAIL_ON_FAILURE(hr);
  1191. pMap = new CIISDsCrMap();
  1192. if (pMap == NULL) {
  1193. hr = E_OUTOFMEMORY;
  1194. }
  1195. BAIL_ON_FAILURE(hr);
  1196. hr = pDispMgr->LoadTypeInfoEntry(
  1197. LIBID_IISExt, //LIBID_ADs,
  1198. IID_IISDsCrMap,
  1199. (IISDsCrMap *)pMap,
  1200. DISPID_REGULAR
  1201. );
  1202. BAIL_ON_FAILURE(hr);
  1203. //
  1204. // Store the IADs Pointer, but again do NOT ref-count
  1205. // this pointer - we keep the pointer around, but do
  1206. // a release immediately.
  1207. //
  1208. hr = pUnkOuter->QueryInterface(IID_IADs, (void **)&pADs);
  1209. pADs->Release();
  1210. pMap->_pADs = pADs;
  1211. //
  1212. // Store the pointer to the pUnkOuter object
  1213. // AND DO NOT add ref this pointer
  1214. //
  1215. pMap->_pUnkOuter = pUnkOuter;
  1216. pMap->m_Credentials = Credentials;
  1217. pMap->_pDispMgr = pDispMgr;
  1218. *ppMap = pMap;
  1219. RRETURN(hr);
  1220. error:
  1221. delete pDispMgr;
  1222. delete pMap;
  1223. RRETURN(hr);
  1224. }
  1225. HRESULT
  1226. CIISDsCrMap::Init(
  1227. LPWSTR pszServerName,
  1228. LPWSTR pszMetabasePath
  1229. )
  1230. /*++
  1231. Routine Description:
  1232. Initialize CIISDsCrMap
  1233. Arguments:
  1234. pszServerName - target computer name for metabase access
  1235. pszParent - metabase path to IisMapper object
  1236. Returns:
  1237. COM status
  1238. --*/
  1239. {
  1240. UINT cL;
  1241. cL = wcslen( pszServerName );
  1242. if ( m_pszServerName = (LPWSTR)LocalAlloc( LMEM_FIXED, ( cL + 1 )*sizeof(WCHAR) ) )
  1243. {
  1244. memcpy( m_pszServerName, pszServerName, ( cL + 1 )*sizeof(WCHAR) );
  1245. }
  1246. else
  1247. {
  1248. return E_OUTOFMEMORY;
  1249. }
  1250. cL = wcslen( pszMetabasePath );
  1251. while ( cL && pszMetabasePath[cL-1] != L'/' && pszMetabasePath[cL-1] != L'\\' )
  1252. {
  1253. --cL;
  1254. }
  1255. if ( m_pszMetabasePath = (LPWSTR)LocalAlloc( LMEM_FIXED, ( cL*sizeof(WCHAR) + sizeof(L"<nsepm>") )) )
  1256. {
  1257. memcpy( m_pszMetabasePath, pszMetabasePath, cL * sizeof(WCHAR) );
  1258. memcpy( m_pszMetabasePath + cL, L"<nsepm>", sizeof(L"<nsepm>") );
  1259. }
  1260. else
  1261. {
  1262. return E_OUTOFMEMORY;
  1263. }
  1264. return InitServerInfo(pszServerName, &m_pcAdmCom);
  1265. }
  1266. HRESULT
  1267. SetVariantAsByteArray(
  1268. VARIANT* pvarReturn,
  1269. DWORD cbLen,
  1270. LPBYTE pbIn
  1271. )
  1272. /*++
  1273. Routine Description:
  1274. Create variant as byte array
  1275. Arguments:
  1276. pVarReturn - ptr to created variant
  1277. cbLen - byte count
  1278. pbIn - byte array
  1279. Returns:
  1280. COM status
  1281. --*/
  1282. {
  1283. HRESULT hr;
  1284. SAFEARRAYBOUND rgsabound[1];
  1285. BYTE * pbData = NULL;
  1286. // Set the variant type of the output parameter
  1287. V_VT(pvarReturn) = VT_ARRAY|VT_UI1;
  1288. V_ARRAY(pvarReturn) = NULL;
  1289. // Allocate a SafeArray for the data
  1290. rgsabound[0].lLbound = 0;
  1291. rgsabound[0].cElements = cbLen;
  1292. V_ARRAY(pvarReturn) = SafeArrayCreate(VT_UI1, 1, rgsabound);
  1293. if (V_ARRAY(pvarReturn) == NULL)
  1294. {
  1295. return E_OUTOFMEMORY;
  1296. }
  1297. if (FAILED(SafeArrayAccessData(V_ARRAY(pvarReturn), (void **) &pbData)))
  1298. {
  1299. return E_UNEXPECTED;
  1300. }
  1301. memcpy(pbData, pbIn, cbLen );
  1302. SafeArrayUnaccessData(V_ARRAY(pvarReturn));
  1303. return NOERROR;
  1304. }
  1305. HRESULT
  1306. SetVariantAsBSTR(
  1307. VARIANT* pvarReturn,
  1308. DWORD cbLen,
  1309. LPBYTE pbIn
  1310. )
  1311. /*++
  1312. Routine Description:
  1313. Create variant BSTR
  1314. Arguments:
  1315. pVarReturn - ptr to created variant
  1316. cbLen - byte count
  1317. pbIn - byte array
  1318. Returns:
  1319. COM status
  1320. --*/
  1321. {
  1322. HRESULT hr;
  1323. V_VT(pvarReturn) = VT_BSTR;
  1324. return SetBSTR( &V_BSTR(pvarReturn), cbLen, pbIn );
  1325. }
  1326. HRESULT
  1327. SetVariantAsLong(
  1328. VARIANT* pvarReturn,
  1329. DWORD dwV
  1330. )
  1331. /*++
  1332. Routine Description:
  1333. Create variant as long
  1334. Arguments:
  1335. pVarReturn - ptr to created variant
  1336. dwV - value
  1337. Returns:
  1338. COM status
  1339. --*/
  1340. {
  1341. HRESULT hr;
  1342. V_VT(pvarReturn) = VT_I4;
  1343. V_I4(pvarReturn) = dwV;
  1344. return S_OK;
  1345. }
  1346. HRESULT
  1347. VariantResolveDispatch(
  1348. VARIANT * pVarOut,
  1349. VARIANT * pVarIn
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. Extract value from IDispatch default property
  1354. Arguments:
  1355. pVarOut - ptr to created variant
  1356. pVarIn - ptr to IDispatch variant to resolve
  1357. Returns:
  1358. COM status
  1359. --*/
  1360. {
  1361. VARIANT varResolved; // value of IDispatch::Invoke
  1362. DISPPARAMS dispParamsNoArgs = {NULL, NULL, 0, 0};
  1363. EXCEPINFO ExcepInfo;
  1364. HRESULT hrCopy;
  1365. VariantInit(pVarOut);
  1366. hrCopy = VariantCopy(pVarOut, pVarIn);
  1367. if (FAILED(hrCopy))
  1368. {
  1369. return hrCopy;
  1370. }
  1371. // follow the IDispatch chain.
  1372. //
  1373. while (V_VT(pVarOut) == VT_DISPATCH)
  1374. {
  1375. HRESULT hrInvoke = S_OK;
  1376. // If the variant is equal to Nothing, then it can be argued
  1377. // with certainty that it does not have a default property!
  1378. // hence we return DISP_E_MEMBERNOTFOUND for this case.
  1379. //
  1380. if (V_DISPATCH(pVarOut) == NULL)
  1381. {
  1382. hrInvoke = DISP_E_MEMBERNOTFOUND;
  1383. }
  1384. else
  1385. {
  1386. VariantInit(&varResolved);
  1387. hrInvoke = V_DISPATCH(pVarOut)->Invoke(
  1388. DISPID_VALUE,
  1389. IID_NULL,
  1390. LOCALE_SYSTEM_DEFAULT,
  1391. DISPATCH_PROPERTYGET | DISPATCH_METHOD,
  1392. &dispParamsNoArgs,
  1393. &varResolved,
  1394. &ExcepInfo,
  1395. NULL);
  1396. }
  1397. if (FAILED(hrInvoke))
  1398. {
  1399. if (hrInvoke == DISP_E_EXCEPTION)
  1400. {
  1401. //
  1402. // forward the ExcepInfo from Invoke to caller's ExcepInfo
  1403. //
  1404. SysFreeString(ExcepInfo.bstrHelpFile);
  1405. }
  1406. VariantClear(pVarOut);
  1407. return hrInvoke;
  1408. }
  1409. // The correct code to restart the loop is:
  1410. //
  1411. // VariantClear(pVar)
  1412. // VariantCopy(pVar, &varResolved);
  1413. // VariantClear(&varResolved);
  1414. //
  1415. // however, the same affect can be achieved by:
  1416. //
  1417. // VariantClear(pVar)
  1418. // *pVar = varResolved;
  1419. // VariantInit(&varResolved)
  1420. //
  1421. // this avoids a copy. The equivalence rests in the fact that
  1422. // *pVar will contain the pointers of varResolved, after we
  1423. // trash varResolved (WITHOUT releasing strings or dispatch
  1424. // pointers), so the net ref count is unchanged. For strings,
  1425. // there is still only one pointer to the string.
  1426. //
  1427. // NOTE: the next interation of the loop will do the VariantInit.
  1428. //
  1429. VariantClear(pVarOut);
  1430. *pVarOut = varResolved;
  1431. }
  1432. return S_OK;
  1433. }
  1434. STDMETHODIMP
  1435. CIISDsCrMap::NonDelegatingQueryInterface(
  1436. REFIID iid,
  1437. LPVOID FAR* ppv
  1438. )
  1439. {
  1440. ASSERT(ppv);
  1441. if (IsEqualIID(iid, IID_IISDsCrMap)) {
  1442. *ppv = (IADsUser FAR *) this;
  1443. } else if (IsEqualIID(iid, IID_IADsExtension)) {
  1444. *ppv = (IADsExtension FAR *) this;
  1445. } else if (IsEqualIID(iid, IID_IUnknown)) {
  1446. //
  1447. // probably not needed since our 3rd party extension does not stand
  1448. // alone and provider does not ask for this, but to be safe
  1449. //
  1450. *ppv = (INonDelegatingUnknown FAR *) this;
  1451. } else {
  1452. *ppv = NULL;
  1453. return E_NOINTERFACE;
  1454. }
  1455. //
  1456. // Delegating AddRef to aggregator for IADsExtesnion and IISDsCrMap.
  1457. // AddRef on itself for IPrivateUnknown. (both tested.)
  1458. //
  1459. ((IUnknown *) (*ppv)) -> AddRef();
  1460. return S_OK;
  1461. }
  1462. //
  1463. // IADsExtension::Operate()
  1464. //
  1465. STDMETHODIMP
  1466. CIISDsCrMap::Operate(
  1467. THIS_ DWORD dwCode,
  1468. VARIANT varUserName,
  1469. VARIANT varPassword,
  1470. VARIANT varFlags
  1471. )
  1472. {
  1473. RRETURN(E_NOTIMPL);
  1474. }
  1475. STDMETHODIMP
  1476. CIISDsCrMap::ADSIInitializeDispatchManager(
  1477. long dwExtensionId
  1478. )
  1479. {
  1480. HRESULT hr = S_OK;
  1481. if (_fDispInitialized) {
  1482. RRETURN(E_FAIL);
  1483. }
  1484. hr = _pDispMgr->InitializeDispMgr(dwExtensionId);
  1485. if (SUCCEEDED(hr)) {
  1486. _fDispInitialized = TRUE;
  1487. }
  1488. RRETURN(hr);
  1489. }
  1490. STDMETHODIMP
  1491. CIISDsCrMap::ADSIInitializeObject(
  1492. THIS_ BSTR lpszUserName,
  1493. BSTR lpszPassword,
  1494. long lnReserved
  1495. )
  1496. {
  1497. CCredentials NewCredentials(lpszUserName, lpszPassword, lnReserved);
  1498. m_Credentials = NewCredentials;
  1499. RRETURN(S_OK);
  1500. }
  1501. STDMETHODIMP
  1502. CIISDsCrMap::ADSIReleaseObject()
  1503. {
  1504. delete this;
  1505. RRETURN(S_OK);
  1506. }