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

////////////////////////////////////////////////////
//
// Copyright (c) 1997 Microsoft Corporation
//
// Module Name: certmap.cpp
//
// Abstract: IIS privider cert mapper object methods
//
// Author: Philippe Choquier (phillich) 10-Apr-1997
//
// History: Zeyong Xu borrowed the source code from ADSI object
// (created by Philippe Choquier at 10-Apr-1997) at 20-Oct-1999
//
///////////////////////////////////////////////////
#include "iisprov.h"
#include "certmap.h"
const ULONG MAX_CERT_KEY_LEN = 32;
//
// CCertMapperMethod
//
CCertMapperMethod::CCertMapperMethod(LPCWSTR pszMetabasePathIn)
{
DBG_ASSERT(pszMetabasePathIn != NULL);
m_hmd = NULL;
HRESULT hr = CoCreateInstance(
CLSID_MSAdminBase,
NULL,
CLSCTX_ALL,
IID_IMSAdminBase,
(void**)&m_pIABase
);
THROW_ON_ERROR(hr);
hr = Init(pszMetabasePathIn);
THROW_ON_ERROR(hr);
}
CCertMapperMethod::~CCertMapperMethod()
{
if ( m_pszMetabasePath )
{
free( m_pszMetabasePath );
}
if(m_pIABase)
m_pIABase->Release();
}
//
// CreateMapping(): Create a mapping entry
//
// Arguments:
//
// vCert - X.509 certificate
// bstrNtAcct - NT acct to map to
// bstrNtPwd - NT pwd
// bstrName - friendly name for mapping entry
// lEnabled - 1 to enable mapping entry, 0 to disable it
//
HRESULT
CCertMapperMethod::CreateMapping(
VARIANT vCert,
BSTR bstrNtAcct,
BSTR bstrNtPwd,
BSTR bstrName,
LONG lEnabled
)
{
HRESULT hr;
LPBYTE pbCert = NULL;
DWORD cCert;
LPSTR pszNtAcct = NULL;
LPSTR pszNtPwd = NULL;
LPSTR pszName = NULL;
LPBYTE pRes;
DWORD cRes;
DWORD cName;
DWORD cNtAcct;
DWORD cNtPwd;
WCHAR achIndex[MAX_CERT_KEY_LEN];
VARIANT vOldAcct;
VARIANT vOldCert;
VARIANT vOldPwd;
VARIANT vOldName;
VARIANT vOldEnabledFlag;
PCCERT_CONTEXT pcCert = NULL;
//
// Do some sanity checks on the cert
//
if ( SUCCEEDED( hr = GetStringFromVariant( &vCert,
(LPSTR*)&pbCert,
&cCert,
FALSE ) ) )
{
//
// try to construct a cert context
//
if ( !( pcCert = CertCreateCertificateContext( X509_ASN_ENCODING,
pbCert,
cCert ) ) )
{
//
// If the decoding fails, GetLastError() returns an ASN1 decoding
// error that is obtained by subtracting CRYPT_E_OSS_ERROR from the returned
// error and looking in file asn1code.h for the actual error. To avoid the
// cryptic ASN1 errors, we'll just return a general "invalid arg" error
//
hr = RETURNCODETOHRESULT( E_INVALIDARG );
FreeString( (LPSTR) pbCert );
pbCert = NULL;
return hr;
}
CertFreeCertificateContext( pcCert );
}
else
{
DBG_ASSERT(pbCert == NULL);
return hr;
}
//
// check if we already have a mapping for this cert; if we do, we'll replace that mapping
// with the new one
//
if ( SUCCEEDED( hr = GetMapping( IISMAPPER_LOCATE_BY_CERT,
vCert,
&vOldCert,
&vOldAcct,
&vOldPwd,
&vOldName,
&vOldEnabledFlag ) ) )
{
if ( FAILED( hr = SetName( IISMAPPER_LOCATE_BY_CERT,
vCert,
bstrName ) ) ||
FAILED( hr = SetAcct( IISMAPPER_LOCATE_BY_CERT,
vCert,
bstrNtAcct ) ) ||
FAILED( hr = SetPwd( IISMAPPER_LOCATE_BY_CERT,
vCert,
bstrNtPwd ) ) ||
FAILED( hr = SetEnabled( IISMAPPER_LOCATE_BY_CERT,
vCert,
lEnabled ) ) )
{
hr; //NOP - Something failed
}
}
//
// New mapping
//
else if ( hr == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
{
//
// check mapping exists, create if not
//
hr = OpenMd( L"Cert11", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
if ( hr == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
{
if ( SUCCEEDED( hr = OpenMd( L"",
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
{
hr = CreateMdObject( L"Cert11" );
CloseMd( FALSE );
// Reopen to the correct node.
hr = OpenMd( L"Cert11", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
}
}
if ( FAILED( hr ) )
{
return hr;
}
//
// adding mapping cert "0" means add @ end of list
//
if ( SUCCEEDED( hr = CreateMdObject( L"mappings/0" ) ) )
{
if ( SUCCEEDED( hr = GetMdData( L"", MD_NSEPM_ACCESS_CERT, DWORD_METADATA, &
cRes, &pRes ) ) )
{
if ( cRes == sizeof(DWORD ) )
{
_snwprintf(
achIndex,
MAX_CERT_KEY_LEN,
L"mappings/%u",
*(LPDWORD)pRes );
if ( FAILED( hr = GetStringFromBSTR( bstrNtAcct, &pszNtAcct, &cNtAcct ) ) ||
FAILED( hr = GetStringFromBSTR( bstrNtPwd, &pszNtPwd, &cNtPwd ) ) ||
FAILED( hr = GetStringFromBSTR( bstrName, &pszName, &cName ) ) ||
FAILED( hr = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA,
sizeof(DWORD), (LPBYTE)&lEnabled ) ) ||
FAILED( hr = SetMdData( achIndex, MD_MAPNAME, STRING_METADATA,
cName, (LPBYTE)pszName ) ) ||
FAILED( hr = SetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA,
cNtPwd, (LPBYTE)pszNtPwd ) ) ||
FAILED( hr = SetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA,
cNtAcct, (LPBYTE)pszNtAcct ) ) ||
FAILED( hr = SetMdData( achIndex, MD_MAPCERT, BINARY_METADATA,
cCert, (LPBYTE)pbCert ) ) )
{
}
}
else
{
hr = E_FAIL;
}
}
}
}
CloseMd( SUCCEEDED( hr ) );
FreeString( (LPSTR)pbCert );
FreeString( pszNtAcct );
FreeString( pszNtPwd );
FreeString( pszName );
return hr;
}
//
// GetMapping: Get a mapping entry using key
//
// Arguments:
//
// lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
// vKey - key to use to locate mapping
// pvCert - X.509 certificate
// pbstrNtAcct - NT acct to map to
// pbstrNtPwd - NT pwd
// pbstrName - friendly name for mapping entry
// plEnabled - 1 to enable mapping entry, 0 to disable it
//
HRESULT
CCertMapperMethod::GetMapping(
LONG lMethod,
VARIANT vKey,
VARIANT* pvCert,
VARIANT* pbstrNtAcct,
VARIANT* pbstrNtPwd,
VARIANT* pbstrName,
VARIANT* plEnabled
)
{
WCHAR achIndex[MAX_CERT_KEY_LEN];
HRESULT hr;
DWORD dwLen;
LPBYTE pbData;
VariantInit( pvCert );
VariantInit( pbstrNtAcct );
VariantInit( pbstrNtPwd );
VariantInit( pbstrName );
VariantInit( plEnabled );
if ( SUCCEEDED( hr = OpenMd( L"Cert11",
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
{
if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
{
if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPCERT, BINARY_METADATA, &dwLen,
&pbData ) ) )
{
hr = SetVariantAsByteArray( pvCert, dwLen, pbData );
free( pbData );
}
else
{
CloseMd( FALSE );
return hr;
}
if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA, &dwLen,
&pbData ) ) )
{
hr = SetVariantAsBSTR( pbstrNtAcct, dwLen, pbData );
free( pbData );
}
else
{
CloseMd( FALSE );
return hr;
}
if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA, &dwLen,
&pbData ) ) )
{
hr = SetVariantAsBSTR( pbstrNtPwd, dwLen, pbData );
free( pbData );
}
else
{
CloseMd( FALSE );
return hr;
}
if ( SUCCEEDED( hr = GetMdData( achIndex, MD_MAPNAME, STRING_METADATA, &dwLen,
&pbData ) ) )
{
hr = SetVariantAsBSTR( pbstrName, dwLen, pbData );
free( pbData );
}
else
{
CloseMd( FALSE );
return hr;
}
if ( FAILED( hr = GetMdData( achIndex, MD_MAPENABLED, STRING_METADATA, &dwLen,
&pbData ) ) )
{
SetVariantAsLong( plEnabled, FALSE );
}
else
{
SetVariantAsLong( plEnabled, *(LPDWORD)pbData );
free( pbData );
}
}
CloseMd( FALSE );
}
return hr;
}
//
// Delete a mapping entry using key
//
HRESULT
CCertMapperMethod::DeleteMapping(
LONG lMethod,
VARIANT vKey
)
{
WCHAR achIndex[MAX_CERT_KEY_LEN];
HRESULT hr;
if ( SUCCEEDED( hr = OpenMd( L"Cert11",
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
{
if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
{
hr = DeleteMdObject( achIndex );
}
CloseMd( TRUE );
}
return hr;
}
//
// Set the enable flag on a mapping entry using key
//
HRESULT
CCertMapperMethod::SetEnabled(
LONG lMethod,
VARIANT vKey,
LONG lEnabled
)
{
WCHAR achIndex[MAX_CERT_KEY_LEN];
HRESULT hr;
if ( SUCCEEDED( hr = OpenMd( L"Cert11",
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
{
if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
{
hr = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA, sizeof(DWORD), (LPBYTE)&lEnabled );
}
CloseMd( TRUE );
}
return hr;
}
//
// Set the Name on a mapping entry using key
//
HRESULT CCertMapperMethod::SetName(
LONG lMethod,
VARIANT vKey,
BSTR bstrName
)
{
return SetString( lMethod, vKey, bstrName, MD_MAPNAME );
}
//
// Set a string property on a mapping entry using key
//
HRESULT CCertMapperMethod::SetString(
LONG lMethod,
VARIANT vKey,
BSTR bstrName,
DWORD dwProp
)
{
WCHAR achIndex[MAX_CERT_KEY_LEN];
LPSTR pszName = NULL;
HRESULT hr;
DWORD dwLen;
if ( FAILED( hr = GetStringFromBSTR( bstrName, &pszName, &dwLen, TRUE ) ) )
{
return hr;
}
if ( SUCCEEDED( hr = OpenMd( L"Cert11",
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
{
if ( SUCCEEDED(hr = Locate( lMethod, vKey, achIndex )) )
{
hr = SetMdData( achIndex, dwProp, STRING_METADATA, dwLen, (LPBYTE)pszName );
}
CloseMd( TRUE );
}
FreeString( pszName );
return hr;
}
//
// Set the Password on a mapping entry using key
//
HRESULT
CCertMapperMethod::SetPwd(
LONG lMethod,
VARIANT vKey,
BSTR bstrPwd
)
{
return SetString( lMethod, vKey, bstrPwd, MD_MAPNTPWD );
}
//
// Set the NT account name on a mapping entry using key
//
HRESULT
CCertMapperMethod::SetAcct(
LONG lMethod,
VARIANT vKey,
BSTR bstrAcct
)
{
return SetString( lMethod, vKey, bstrAcct, MD_MAPNTACCT );
}
HRESULT
CCertMapperMethod::OpenMd(
LPWSTR pszOpenPath,
DWORD dwPermission
)
{
HRESULT hr;
LPWSTR pszPath;
UINT cL = wcslen( m_pszMetabasePath );
pszPath = (LPWSTR)malloc( (wcslen(pszOpenPath) + 1 + cL + 1)*sizeof(WCHAR) );
if ( pszPath == NULL )
{
return E_OUTOFMEMORY;
}
memcpy( pszPath, m_pszMetabasePath, cL * sizeof(WCHAR) );
if ( cL && m_pszMetabasePath[cL-1] != L'/' && *pszOpenPath && *pszOpenPath != L'/' )
{
pszPath[cL++] = L'/';
}
wcscpy( pszPath + cL, pszOpenPath );
hr = OpenAdminBaseKey(
pszPath,
dwPermission
);
free( pszPath );
return hr;
}
HRESULT
CCertMapperMethod::CloseMd(
BOOL fSave
)
{
CloseAdminBaseKey();
m_hmd = NULL;
if ( m_pIABase && fSave )
{
m_pIABase->SaveData();
}
return S_OK;
}
HRESULT
CCertMapperMethod::DeleteMdObject(
LPWSTR pszKey
)
{
return m_pIABase->DeleteKey( m_hmd, pszKey );
}
HRESULT
CCertMapperMethod::CreateMdObject(
LPWSTR pszKey
)
{
return m_pIABase->AddKey( m_hmd, pszKey );
}
HRESULT
CCertMapperMethod::SetMdData(
LPWSTR achIndex,
DWORD dwProp,
DWORD dwDataType,
DWORD dwDataLen,
LPBYTE pbData
)
{
METADATA_RECORD md;
md.dwMDDataLen = dwDataLen;
md.dwMDDataType = dwDataType;
md.dwMDIdentifier = dwProp;
md.dwMDAttributes = (dwProp == MD_MAPPWD) ? METADATA_SECURE : 0;
md.pbMDData = pbData;
return m_pIABase->SetData( m_hmd, achIndex, &md );
}
HRESULT
CCertMapperMethod::GetMdData(
LPWSTR achIndex,
DWORD dwProp,
DWORD dwDataType,
LPDWORD pdwDataLen,
LPBYTE* ppbData
)
{
HRESULT hr;
METADATA_RECORD md;
DWORD dwRequired;
md.dwMDDataLen = 0;
md.dwMDDataType = dwDataType;
md.dwMDIdentifier = dwProp;
md.dwMDAttributes = 0;
md.pbMDData = NULL;
if ( FAILED(hr = m_pIABase->GetData( m_hmd, achIndex, &md, &dwRequired )) )
{
if ( hr == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER) )
{
if ( (*ppbData = (LPBYTE)malloc(dwRequired)) == NULL )
{
return E_OUTOFMEMORY;
}
md.pbMDData = *ppbData;
md.dwMDDataLen = dwRequired;
hr = m_pIABase->GetData( m_hmd, achIndex, &md, &dwRequired );
*pdwDataLen = md.dwMDDataLen;
}
}
else
{
*pdwDataLen = 0;
*ppbData = NULL;
}
return hr;
}
//
// Locate a mapping entry based on key
// OpenMd() must be called 1st
//
HRESULT
CCertMapperMethod::Locate(
LONG lMethod,
VARIANT vKey,
LPWSTR pszResKey
)
{
HRESULT hr;
LPSTR pV = NULL;
DWORD cV;
DWORD dwProp;
LPSTR pRes;
DWORD cRes;
BOOL fAddDelim = TRUE;
//
// determine method
//
switch ( lMethod )
{
case IISMAPPER_LOCATE_BY_CERT:
dwProp = MD_NSEPM_ACCESS_CERT;
fAddDelim = FALSE;
break;
case IISMAPPER_LOCATE_BY_NAME:
dwProp = MD_NSEPM_ACCESS_NAME;
break;
case IISMAPPER_LOCATE_BY_ACCT:
dwProp = MD_NSEPM_ACCESS_ACCOUNT;
break;
case IISMAPPER_LOCATE_BY_INDEX:
if ( SUCCEEDED( hr = GetStringFromVariant( &vKey, &pV, &cV, TRUE ) ) )
{
wsprintfW( pszResKey, L"mappings/%s", pV );
}
FreeString( pV );
return hr;
default:
return E_FAIL;
}
//
// get ptr to data
//
if ( SUCCEEDED( hr = GetStringFromVariant( &vKey, &pV, &cV, fAddDelim ) ) )
{
//
// set search prop, get result
//
if ( SUCCEEDED( hr = SetMdData( L"", dwProp, BINARY_METADATA, cV, (LPBYTE)pV ) ) )
{
if ( SUCCEEDED( hr = GetMdData( L"", dwProp, DWORD_METADATA, &cRes, (LPBYTE*)&pRes ) ) )
{
if ( cRes == sizeof(DWORD ) )
{
wsprintfW( pszResKey, L"mappings/%u", *(LPDWORD)pRes );
}
else
{
hr = E_FAIL;
}
free( pRes );
}
}
}
FreeString( pV );
return hr;
}
//
// GetStringFromBSTR: Allocate string buffer from BSTR
//
// Arguments:
//
// bstr - bstr to convert from
// psz - updated with ptr to buffer, to be freed with FreeString()
// pdwLen - updated with strlen(string), incremented by 1 if fAddDelimInCount is TRUE
// fAddDelimInCount - TRUE to increment *pdwLen
//
HRESULT CCertMapperMethod::GetStringFromBSTR(
BSTR bstr,
LPSTR* psz,
LPDWORD pdwLen,
BOOL fAddDelimInCount
)
{
UINT cch = SysStringLen(bstr);
UINT cchT;
// include NULL terminator
*pdwLen = cch + (fAddDelimInCount ? 1 : 0);
CHAR *szNew = (CHAR*)malloc((2 * cch) + 1); // * 2 for worst case DBCS string
if (szNew == NULL)
{
return E_OUTOFMEMORY;
}
cchT = WideCharToMultiByte(CP_ACP, 0, bstr, cch + 1, szNew, (2 * cch) + 1, NULL, NULL);
*psz = szNew;
return NOERROR;
}
//
// GetStringFromVariant: Allocate string buffer from BSTR
//
// Arguments:
//
// pVar - variant to convert from. Recognizes BSTR, VT_ARRAY|VT_UI1, ByRef or ByVal
// psz - updated with ptr to buffer, to be freed with FreeString()
// pdwLen - updated with size of input, incremented by 1 if fAddDelimInCount is TRUE
// fAddDelimInCount - TRUE to increment *pdwLen
//
HRESULT CCertMapperMethod::GetStringFromVariant(
VARIANT* pVar,
LPSTR* psz,
LPDWORD pdwLen,
BOOL fAddDelim
)
{
LPBYTE pbV = NULL;
UINT cV;
HRESULT hr;
WORD vt = V_VT(pVar);
BOOL fByRef = FALSE;
VARIANT vOut;
// Set out params to 0
*psz = NULL;
*pdwLen = 0;
VariantInit( &vOut );
if ( vt & VT_BYREF )
{
vt &= ~VT_BYREF;
fByRef = TRUE;
}
// if pVar is BSTR, convert to multibytes
if ( vt == VT_VARIANT )
{
pVar = (VARIANT*)V_BSTR(pVar);
vt = V_VT(pVar);
if ( fByRef = vt & VT_BYREF )
{
vt &= ~VT_BYREF;
}
}
if ( vt == VT_BSTR )
{
hr = GetStringFromBSTR(
fByRef ? *(BSTR*)V_BSTR(pVar) : V_BSTR(pVar),
psz,
pdwLen,
fAddDelim
);
}
else if( vt == (VT_ARRAY | VT_UI1) )
{
long lBound, uBound, lItem;
BYTE bValue;
SAFEARRAY* pSafeArray;
// array of VT_UI1 (probably OctetString)
pSafeArray = fByRef ? *(SAFEARRAY**)V_BSTR(pVar) : V_ARRAY( pVar );
hr = SafeArrayGetLBound(pSafeArray, 1, &lBound);
hr = SafeArrayGetUBound(pSafeArray, 1, &uBound);
cV = uBound - lBound + 1;
if ( !(pbV = (LPBYTE)malloc(cV)) )
{
hr = E_OUTOFMEMORY;
VariantClear( &vOut );
return hr;
}
hr = S_OK;
for( lItem = lBound; lItem <= uBound ; lItem++ )
{
hr = SafeArrayGetElement( pSafeArray, &lItem, &bValue );
if( FAILED( hr ) )
{
break;
}
pbV[lItem-lBound] = bValue;
}
*psz = (LPSTR)pbV;
*pdwLen = cV;
}
else if( vt == (VT_ARRAY | VT_VARIANT) )
{
long lBound, uBound, lItem;
VARIANT vValue;
BYTE bValue;
SAFEARRAY* pSafeArray;
// array of VT_VARIANT (probably VT_I4 )
pSafeArray = fByRef ? *(SAFEARRAY**)V_BSTR(pVar) : V_ARRAY( pVar );
hr = SafeArrayGetLBound(pSafeArray, 1, &lBound);
hr = SafeArrayGetUBound(pSafeArray, 1, &uBound);
cV = uBound - lBound + 1;
if ( !(pbV = (LPBYTE)malloc(cV)) )
{
hr = E_OUTOFMEMORY;
VariantClear( &vOut );
return hr;
}
hr = S_OK;
for( lItem = lBound; lItem <= uBound ; lItem++ )
{
hr = SafeArrayGetElement( pSafeArray, &lItem, &vValue );
if( FAILED( hr ) )
{
break;
}
if ( V_VT(&vValue) == VT_UI1 )
{
bValue = V_UI1(&vValue);
}
else if ( V_VT(&vValue) == VT_I2 )
{
bValue = (BYTE)V_I2(&vValue);
}
else if ( V_VT(&vValue) == VT_I4 )
{
bValue = (BYTE)V_I4(&vValue);
}
else
{
bValue = 0;
}
pbV[lItem-lBound] = bValue;
}
*psz = (LPSTR)pbV;
*pdwLen = cV;
}
else
{
hr = E_FAIL;
}
VariantClear( &vOut );
if(FAILED(hr))
{
*psz = NULL;
*pdwLen = 0;
free(pbV);
pbV = NULL;
}
return hr;
}
VOID CCertMapperMethod::FreeString(
LPSTR psz
)
{
if ( psz )
{
free( psz );
}
}
HRESULT CCertMapperMethod::SetBSTR(
BSTR* pbstrRet,
DWORD cch,
LPBYTE sz
)
{
BSTR bstrRet;
if (sz == NULL)
{
*pbstrRet = NULL;
return(NOERROR);
}
// Allocate a string of the desired length
// SysAllocStringLen allocates enough room for unicode characters plus a null
// Given a NULL string it will just allocate the space
bstrRet = SysAllocStringLen(NULL, cch);
if (bstrRet == NULL)
{
return(E_OUTOFMEMORY);
}
// If we were given "", we will have cch=0. return the empty bstr
// otherwise, really copy/convert the string
// NOTE we pass -1 as 4th parameter of MultiByteToWideChar for DBCS support
if (cch != 0)
{
UINT cchTemp = 0;
if (MultiByteToWideChar(CP_ACP, 0, (LPSTR)sz, -1, bstrRet, cch+1) == 0)
{
return(HRESULT_FROM_WIN32(GetLastError()));
}
// If there are some DBCS characters in the sz(Input), then, the character count of BSTR(DWORD) is
// already set to cch(strlen(sz)) in SysAllocStringLen(NULL, cch), we cannot change the count,
// and later call of SysStringLen(bstr) always returns the number of characters specified in the
// cch parameter at allocation time. Bad, because one DBCS character(2 bytes) will convert
// to one UNICODE character(2 bytes), not 2 UNICODE characters(4 bytes).
// Example: For input sz contains only one DBCS character, we want to see SysStringLen(bstr)
// = 1, not 2.
bstrRet[cch] = 0;
cchTemp = wcslen(bstrRet);
if (cchTemp < cch)
{
BSTR bstrTemp = SysAllocString(bstrRet);
SysFreeString(bstrRet);
bstrRet = bstrTemp;
cch = cchTemp;
}
}
bstrRet[cch] = 0;
*pbstrRet = bstrRet;
return(NOERROR);
}
HRESULT CCertMapperMethod::Init(
LPCWSTR pszMetabasePath
)
{
DBG_ASSERT(pszMetabasePath != NULL);
UINT cL;
cL = wcslen( pszMetabasePath );
while ( cL && pszMetabasePath[cL-1] != L'/' && pszMetabasePath[cL-1] != L'\\' )
{
--cL;
}
if ( m_pszMetabasePath = (LPWSTR)malloc( cL*sizeof(WCHAR) + sizeof(L"<nsepm>") ) )
{
memcpy( m_pszMetabasePath, pszMetabasePath, cL * sizeof(WCHAR) );
memcpy( m_pszMetabasePath + cL, L"<nsepm>", sizeof(L"<nsepm>") );
}
else
{
return E_OUTOFMEMORY;
}
return S_OK;
}
HRESULT CCertMapperMethod::SetVariantAsByteArray(
VARIANT* pvarReturn,
DWORD cbLen,
LPBYTE pbIn
)
{
SAFEARRAYBOUND rgsabound[1];
BYTE * pbData = NULL;
// Set the variant type of the output parameter
V_VT(pvarReturn) = VT_ARRAY|VT_UI1;
V_ARRAY(pvarReturn) = NULL;
// Allocate a SafeArray for the data
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = cbLen;
V_ARRAY(pvarReturn) = SafeArrayCreate(VT_UI1, 1, rgsabound);
if (V_ARRAY(pvarReturn) == NULL)
{
return E_OUTOFMEMORY;
}
if (FAILED(SafeArrayAccessData(V_ARRAY(pvarReturn), (void **) &pbData)))
{
return E_UNEXPECTED;
}
memcpy(pbData, pbIn, cbLen );
SafeArrayUnaccessData(V_ARRAY(pvarReturn));
return NOERROR;
}
HRESULT CCertMapperMethod::SetVariantAsBSTR(
VARIANT* pvarReturn,
DWORD cbLen,
LPBYTE pbIn
)
{
V_VT(pvarReturn) = VT_BSTR;
return SetBSTR( &V_BSTR(pvarReturn), cbLen, pbIn );
}
HRESULT CCertMapperMethod::SetVariantAsLong(
VARIANT* pvarReturn,
DWORD dwV
)
{
V_VT(pvarReturn) = VT_I4;
V_I4(pvarReturn) = dwV;
return S_OK;
}
HRESULT CCertMapperMethod::OpenAdminBaseKey(
LPWSTR pszPathName,
DWORD dwAccessType
)
{
if(m_hmd)
CloseAdminBaseKey();
HRESULT t_hr = m_pIABase->OpenKey(
METADATA_MASTER_ROOT_HANDLE,
pszPathName,
dwAccessType,
DEFAULT_TIMEOUT_VALUE, // 30 seconds
&m_hmd
);
if(FAILED(t_hr))
m_hmd = NULL;
return t_hr;
}
VOID CCertMapperMethod::CloseAdminBaseKey()
{
if(m_hmd && m_pIABase)
{
m_pIABase->CloseKey(m_hmd);
m_hmd = NULL;
}
}