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.
3402 lines
78 KiB
3402 lines
78 KiB
/*++
|
|
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
crmap.cxx
|
|
|
|
Abstract:
|
|
|
|
ADSIIS cert mapper object
|
|
Certificate mappings storage has changed for IIS6.
|
|
ADSI however has to support downlevel admin of
|
|
IIS5, IIS5.1
|
|
|
|
NSEPM support was removed from IIS6 and 1to1 client certificate
|
|
mapping information is now stored under <site>/Cert11/Mappings
|
|
node directly in the metabase
|
|
Functions with IIS6 postfix access new location
|
|
for 1to1 client certificate mappings storage
|
|
|
|
Author:
|
|
|
|
Philippe Choquier (phillich) 10-Apr-1997
|
|
|
|
--*/
|
|
|
|
#include "iisext.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include <nsepname.hxx>
|
|
#include <dbgutil.h>
|
|
|
|
DEFINE_IPrivateDispatch_Implementation(CIISDsCrMap)
|
|
DEFINE_DELEGATING_IDispatch_Implementation(CIISDsCrMap)
|
|
DEFINE_CONTAINED_IADs_Implementation(CIISDsCrMap)
|
|
DEFINE_IADsExtension_Implementation(CIISDsCrMap)
|
|
|
|
#define LOCAL_MAX_SIZE METADATA_MAX_NAME_LEN + 1
|
|
|
|
const int SHA1_HASH_SIZE = 20;
|
|
|
|
|
|
//Local functions used only for IIS6
|
|
|
|
HRESULT
|
|
GetStringAFromBSTR(
|
|
BSTR bstr,
|
|
LPSTR* psz,
|
|
LPDWORD pdwLen,
|
|
BOOL fAddDelimInCount = TRUE
|
|
);
|
|
|
|
HRESULT
|
|
GetBlobFromVariant(
|
|
VARIANT* pVar,
|
|
PBYTE* ppbOut,
|
|
LPDWORD pcbOut
|
|
);
|
|
|
|
HRESULT
|
|
SetVariantAsBSTRFromStringW(
|
|
VARIANT* pvarReturn,
|
|
DWORD cbLen,
|
|
LPBYTE pbIn
|
|
);
|
|
|
|
HRESULT
|
|
SetBSTRFromStringW(
|
|
BSTR* pbstrRet,
|
|
DWORD cb,
|
|
LPBYTE sz
|
|
);
|
|
|
|
//
|
|
// Local functions used for IIS5 and IIS6
|
|
//
|
|
|
|
HRESULT
|
|
GetStringFromBSTR(
|
|
BSTR bstr,
|
|
LPSTR* psz,
|
|
LPDWORD pdwLen,
|
|
BOOL fAddDelimInCount = TRUE
|
|
);
|
|
|
|
HRESULT
|
|
GetStringFromVariant(
|
|
VARIANT* pVar,
|
|
LPSTR* psz,
|
|
LPDWORD pdwLen,
|
|
BOOL fAddDelimInCount = TRUE
|
|
);
|
|
|
|
VOID
|
|
FreeString(
|
|
LPSTR psz
|
|
);
|
|
|
|
HRESULT
|
|
SetBSTR(
|
|
BSTR* pbstrRet,
|
|
DWORD cch,
|
|
LPBYTE sz
|
|
);
|
|
|
|
HRESULT
|
|
SetVariantAsByteArray(
|
|
VARIANT* pvarReturn,
|
|
DWORD cbLen,
|
|
LPBYTE pbIn
|
|
);
|
|
|
|
HRESULT
|
|
SetVariantAsBSTR(
|
|
VARIANT* pvarReturn,
|
|
DWORD cbLen,
|
|
LPBYTE pbIn
|
|
);
|
|
|
|
HRESULT
|
|
SetVariantAsLong(
|
|
VARIANT* pvarReturn,
|
|
DWORD dwV
|
|
);
|
|
|
|
HRESULT
|
|
VariantResolveDispatch(
|
|
VARIANT * pVarOut,
|
|
VARIANT * pVarIn
|
|
);
|
|
|
|
|
|
HRESULT
|
|
GetCertificateHashString(
|
|
PBYTE pbCert,
|
|
DWORD cbCert,
|
|
WCHAR *pwszCertHash,
|
|
DWORD cchCertHashBuffer)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
verifies validity of cert blob by creating cert context
|
|
and retrieves SHA1 hash and converts it to WCHAR *
|
|
|
|
Used for IIS6 only
|
|
|
|
Arguments:
|
|
|
|
pbCert - X.509 certificate blob
|
|
cbCert - size of the cert blob in bytes
|
|
pwszCertHash - buffer must be big enough to fit SHA1 hash in hex string form
|
|
(40 WCHAR + terminating 0 )
|
|
cchCertHashBuffer - size of the CertHash buffer in WCHARS (includes terminating 0)
|
|
Returns:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
BYTE rgbHash[ SHA1_HASH_SIZE ];
|
|
DWORD cbSize = SHA1_HASH_SIZE;
|
|
|
|
#ifndef HEX_DIGIT
|
|
#define HEX_DIGIT( nDigit ) \
|
|
(WCHAR)((nDigit) > 9 ? \
|
|
(nDigit) - 10 + L'a' \
|
|
: (nDigit) + L'0')
|
|
#endif
|
|
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
pCertContext = CertCreateCertificateContext(
|
|
X509_ASN_ENCODING,
|
|
(const BYTE *)pbCert,
|
|
cbCert );
|
|
|
|
if ( pCertContext == NULL )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// get hash of the certificate to be verified
|
|
//
|
|
if ( !CertGetCertificateContextProperty( pCertContext,
|
|
CERT_SHA1_HASH_PROP_ID,
|
|
rgbHash,
|
|
&cbSize ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
CertFreeCertificateContext( pCertContext );
|
|
pCertContext=NULL;
|
|
return hr;
|
|
}
|
|
|
|
CertFreeCertificateContext( pCertContext );
|
|
pCertContext = NULL;
|
|
|
|
if ( cchCertHashBuffer < SHA1_HASH_SIZE * 2 + 1 )
|
|
{
|
|
// we don't have big enough buffer to store
|
|
// hex string of the SHA1 hash each byte takes 2 chars + terminating 0
|
|
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
DBG_ASSERT( FALSE );
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// convert to text
|
|
//
|
|
for (int i = 0; i < sizeof(rgbHash); i ++ )
|
|
{
|
|
*(pwszCertHash++) = HEX_DIGIT( ( rgbHash[ i ] >> 4 ) );
|
|
*(pwszCertHash++) = HEX_DIGIT( ( rgbHash[ i ] & 0x0F ) );
|
|
}
|
|
*(pwszCertHash) = L'\0';
|
|
#undef HEX_DIGIT
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Mapping functins for IIS6
|
|
//
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::CreateMappingIIS6(
|
|
VARIANT vCert,
|
|
BSTR bstrNtAcct,
|
|
BSTR bstrNtPwd,
|
|
BSTR bstrName,
|
|
LONG lEnabled
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
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
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
HRESULT hres;
|
|
LPBYTE pbCert = NULL;
|
|
DWORD cbCert;
|
|
LPBYTE pRes;
|
|
DWORD cRes;
|
|
VARIANT vOldAcct;
|
|
VARIANT vOldCert;
|
|
VARIANT vOldPwd;
|
|
VARIANT vOldName;
|
|
VARIANT vOldEnabledFlag;
|
|
PCCERT_CONTEXT pcCert = NULL;
|
|
WCHAR wszCertHash[ 2*SHA1_HASH_SIZE + 1];
|
|
BOOL fFoundExisting = FALSE;
|
|
|
|
//
|
|
// Do some sanity checks on the cert
|
|
//
|
|
if ( SUCCEEDED( hres = GetBlobFromVariant( &vCert,
|
|
&pbCert,
|
|
&cbCert ) ) )
|
|
{
|
|
//
|
|
// verify validity of certificate blob
|
|
// and retrieve certificate hash
|
|
//
|
|
|
|
if ( FAILED( hres = GetCertificateHashString(
|
|
pbCert,
|
|
cbCert,
|
|
wszCertHash,
|
|
sizeof( wszCertHash )/sizeof( WCHAR ) ) ) )
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"Invalid cert passed to CreateMapping() 0x%x\n", hres));
|
|
//
|
|
// 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
|
|
//
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// check if we already have a mapping for this cert; if we do, we'll replace that mapping
|
|
// with the new one
|
|
//
|
|
|
|
WCHAR achIndex[METADATA_MAX_NAME_LEN + 1];
|
|
|
|
if ( SUCCEEDED( hres = OpenMd( L"Cert11/Mappings",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
if ( SUCCEEDED(hres = Locate( IISMAPPER_LOCATE_BY_CERT,
|
|
vCert,
|
|
achIndex )) )
|
|
{
|
|
fFoundExisting = TRUE;
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"Replacing old 1-1 cert mapping with new mapping\n"));
|
|
|
|
|
|
if ( FAILED( hres = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA,
|
|
sizeof(DWORD), (LPBYTE)&lEnabled ) ) ||
|
|
FAILED( hres = SetMdData( achIndex, MD_MAPNAME, STRING_METADATA,
|
|
sizeof(WCHAR) * (SysStringLen(bstrName) + 1 ),
|
|
(LPBYTE)bstrName ) ) ||
|
|
FAILED( hres = SetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA,
|
|
sizeof(WCHAR) * (SysStringLen(bstrNtPwd) + 1 ),
|
|
(LPBYTE)bstrNtPwd ) ) ||
|
|
FAILED( hres = SetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA,
|
|
sizeof(WCHAR) * (SysStringLen(bstrNtAcct) + 1 ),
|
|
(LPBYTE)bstrNtAcct ) ) ||
|
|
FAILED( hres = SetMdData( achIndex, MD_MAPCERT, BINARY_METADATA,
|
|
cbCert, (LPBYTE)pbCert ) ) )
|
|
{
|
|
//NOP - Something failed
|
|
}
|
|
}
|
|
CloseMd( SUCCEEDED( hres ) );
|
|
}
|
|
|
|
//
|
|
// New mapping
|
|
//
|
|
if ( !fFoundExisting )
|
|
{
|
|
//
|
|
// check mapping exists, create if not
|
|
//
|
|
hres = OpenMd( L"Cert11/Mappings", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
|
|
|
|
if ( hres == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
|
|
{
|
|
if ( SUCCEEDED( hres = OpenMd( L"",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
hres = CreateMdObject( L"Cert11/Mappings" );
|
|
CloseMd( FALSE );
|
|
|
|
// Reopen to the correct node.
|
|
hres = OpenMd( L"Cert11/Mappings", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
|
|
}
|
|
}
|
|
|
|
// failed to open metabase
|
|
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// adding the new mapping under it's CertHash node
|
|
//
|
|
|
|
if ( SUCCEEDED( hres = CreateMdObject( wszCertHash ) ) )
|
|
{
|
|
|
|
if ( FAILED( hres = SetMdData( wszCertHash, MD_MAPENABLED, DWORD_METADATA,
|
|
sizeof(DWORD), (LPBYTE)&lEnabled ) ) ||
|
|
FAILED( hres = SetMdData( wszCertHash, MD_MAPNAME, STRING_METADATA,
|
|
sizeof(WCHAR) * (SysStringLen(bstrName) + 1 ),
|
|
(LPBYTE)bstrName ) ) ||
|
|
FAILED( hres = SetMdData( wszCertHash, MD_MAPNTPWD, STRING_METADATA,
|
|
sizeof(WCHAR) * (SysStringLen(bstrNtPwd) + 1 ),
|
|
(LPBYTE)bstrNtPwd ) ) ||
|
|
FAILED( hres = SetMdData( wszCertHash, MD_MAPNTACCT, STRING_METADATA,
|
|
sizeof(WCHAR) * (SysStringLen(bstrNtAcct) + 1 ),
|
|
(LPBYTE)bstrNtAcct ) ) ||
|
|
FAILED( hres = SetMdData( wszCertHash, MD_MAPCERT, BINARY_METADATA,
|
|
cbCert, (LPBYTE)pbCert ) ) )
|
|
{
|
|
}
|
|
}
|
|
CloseMd( SUCCEEDED( hres ) );
|
|
}
|
|
|
|
Exit:
|
|
if( pbCert != NULL )
|
|
{
|
|
LocalFree( pbCert );
|
|
pbCert = NULL;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::GetMappingIIS6(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
VARIANT* pvCert,
|
|
VARIANT* pbstrNtAcct,
|
|
VARIANT* pbstrNtPwd,
|
|
VARIANT* pbstrName,
|
|
VARIANT* plEnabled
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
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
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
WCHAR achIndex[METADATA_MAX_NAME_LEN + 1];
|
|
HRESULT hres;
|
|
DWORD dwLen;
|
|
LPBYTE pbData = NULL;
|
|
|
|
VariantInit( pvCert );
|
|
VariantInit( pbstrNtAcct );
|
|
VariantInit( pbstrNtPwd );
|
|
VariantInit( pbstrName );
|
|
VariantInit( plEnabled );
|
|
|
|
if ( SUCCEEDED( hres = OpenMd( L"Cert11/Mappings",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
|
|
{
|
|
if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPCERT, BINARY_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
if ( FAILED( hres = SetVariantAsByteArray( pvCert, dwLen, pbData ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
LocalFree( pbData );
|
|
}
|
|
else
|
|
{
|
|
if ( hres != MD_ERROR_DATA_NOT_FOUND ||
|
|
FAILED( hres = SetVariantAsByteArray( pvCert, 0, (PBYTE)"" ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
if ( FAILED( hres = SetVariantAsBSTRFromStringW(
|
|
pbstrNtAcct,
|
|
dwLen, pbData ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
LocalFree( pbData );
|
|
pbData = NULL;
|
|
}
|
|
else
|
|
{
|
|
if ( hres != MD_ERROR_DATA_NOT_FOUND ||
|
|
FAILED ( hres = SetVariantAsBSTRFromStringW(
|
|
pbstrNtAcct,
|
|
sizeof(L""), (LPBYTE)L"" ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
if ( FAILED( hres = SetVariantAsBSTRFromStringW(
|
|
pbstrNtPwd,
|
|
dwLen, pbData ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
LocalFree( pbData );
|
|
pbData = NULL;
|
|
}
|
|
else
|
|
{
|
|
if ( hres != MD_ERROR_DATA_NOT_FOUND ||
|
|
FAILED( hres = SetVariantAsBSTRFromStringW(
|
|
pbstrNtPwd,
|
|
sizeof(L""), (LPBYTE)L"" ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPNAME, STRING_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
if ( FAILED( hres = SetVariantAsBSTRFromStringW(
|
|
pbstrName,
|
|
dwLen, pbData ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
LocalFree( pbData );
|
|
pbData = NULL;
|
|
}
|
|
else
|
|
{
|
|
if ( hres != MD_ERROR_DATA_NOT_FOUND ||
|
|
FAILED( hres = SetVariantAsBSTRFromStringW(
|
|
pbstrName,
|
|
sizeof(L""), (LPBYTE)L"" ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
if ( FAILED( hres = SetVariantAsLong( plEnabled, *(LPDWORD)pbData ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
LocalFree( pbData );
|
|
pbData = NULL;
|
|
}
|
|
else
|
|
{
|
|
if ( hres != MD_ERROR_DATA_NOT_FOUND ||
|
|
FAILED( hres = SetVariantAsLong( plEnabled, FALSE ) ) )
|
|
{
|
|
goto Done;
|
|
}
|
|
hres = S_OK;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
Done:
|
|
if ( pbData != NULL )
|
|
{
|
|
LocalFree( pbData );
|
|
pbData = NULL;
|
|
}
|
|
CloseMd( FALSE );
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::DeleteMappingIIS6(
|
|
LONG lMethod,
|
|
VARIANT vKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
WCHAR achIndex[METADATA_MAX_NAME_LEN + 1];
|
|
HRESULT hres;
|
|
|
|
if ( SUCCEEDED( hres = OpenMd( L"Cert11/Mappings",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
|
|
{
|
|
hres = DeleteMdObject( achIndex );
|
|
}
|
|
CloseMd( TRUE );
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetEnabledIIS6(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
LONG lEnabled
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the enable flag on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
lEnabled - 1 to enable, 0 to disable
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
WCHAR achIndex[METADATA_MAX_NAME_LEN + 1];
|
|
HRESULT hres;
|
|
|
|
if ( SUCCEEDED( hres = OpenMd( L"Cert11/Mappings",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
|
|
{
|
|
hres = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA, sizeof(DWORD), (LPBYTE)&lEnabled );
|
|
}
|
|
CloseMd( TRUE );
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetNameIIS6(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
BSTR bstrName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the Name on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
bstrName - name to assign to mapping entry
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
return SetStringIIS6( lMethod, vKey, bstrName, MD_MAPNAME );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetStringIIS6(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
BSTR bstrName,
|
|
DWORD dwProp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set a string property on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
bstrName - string content to assign to mapping entry
|
|
dwProp - property ID to assign to
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
WCHAR achIndex[METADATA_MAX_NAME_LEN + 1];
|
|
LPSTR pszName = NULL;
|
|
HRESULT hres;
|
|
DWORD dwLen;
|
|
|
|
|
|
if ( SUCCEEDED( hres = OpenMd( L"Cert11/Mappings",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
|
|
{
|
|
hres = SetMdData( achIndex, dwProp, STRING_METADATA,
|
|
sizeof(WCHAR) * (SysStringLen(bstrName) + 1 ),
|
|
(LPBYTE)bstrName );
|
|
}
|
|
CloseMd( TRUE );
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetPwdIIS6(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
BSTR bstrPwd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the Password on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
bstrPwd - password to assign to mapping entry
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
// Password must be saved with METADATA_SECURE flag
|
|
// SetMdData() is used by SetStringIIS6() and it will take care of it
|
|
//
|
|
return SetStringIIS6( lMethod, vKey, bstrPwd, MD_MAPNTPWD );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetAcctIIS6(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
BSTR bstrAcct
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the NT account name on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
bstrAcct - NT account name to assign to mapping entry
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
return SetStringIIS6( lMethod, vKey, bstrAcct, MD_MAPNTACCT );
|
|
}
|
|
|
|
|
|
|
|
//////
|
|
|
|
HRESULT
|
|
CIISDsCrMap::LocateIIS6(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
LPWSTR pszResKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locate a mapping entry based on key
|
|
OpenMd() must be called 1st
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
pszResKey - must be METADATA_MAX_NAME_LEN + 1 WCHARs long
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
HRESULT hres;
|
|
PBYTE pbKeyData = NULL;
|
|
DWORD cbKeyData =0;
|
|
PBYTE pbCert = NULL;
|
|
DWORD cbCert =0;
|
|
DWORD dwProp;
|
|
LPSTR pRes;
|
|
DWORD cRes;
|
|
BOOL fAddDelim = TRUE;
|
|
VARIANT vKeyUI4;
|
|
VARIANT vKeyBSTR;
|
|
|
|
WCHAR achIndex[ METADATA_MAX_NAME_LEN + 1 ];
|
|
DWORD dwIndex = 0;
|
|
DWORD cbData = 0;
|
|
PBYTE pbData = NULL;
|
|
|
|
|
|
VariantInit( &vKeyUI4 );
|
|
VariantInit( &vKeyBSTR );
|
|
if ( lMethod == IISMAPPER_LOCATE_BY_INDEX )
|
|
{
|
|
//
|
|
// Convert index to numeric value VT_UI4 (within variant)
|
|
//
|
|
|
|
if ( FAILED( hres = VariantChangeType( &vKeyUI4, &vKey, 0, VT_UI4 ) ) )
|
|
{
|
|
goto Exit;
|
|
}
|
|
if ( V_UI4( &vKeyUI4 ) == 0 )
|
|
{
|
|
// Error PATH_NOT_FOUND chosen for backward compatibility
|
|
// with version IIS5.1 and older
|
|
//
|
|
hres = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND );
|
|
goto Exit;
|
|
}
|
|
hres = m_pcAdmCom->EnumKeys( m_hmd,
|
|
L"",
|
|
achIndex,
|
|
V_UI4( &vKeyUI4 ) - 1
|
|
);
|
|
if ( hres == HRESULT_FROM_WIN32( ERROR_NO_MORE_ITEMS ) )
|
|
{
|
|
// Error PATH_NOT_FOUND chosen for backward compatibility
|
|
// with version IIS5.1 and older
|
|
//
|
|
hres = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND );
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// get ptr to data
|
|
//
|
|
|
|
|
|
|
|
if ( lMethod == IISMAPPER_LOCATE_BY_CERT )
|
|
{
|
|
// Now this is really wacky. Because of the legacy of the bad
|
|
// decision in the past the CERT is not enforced to be byte array
|
|
// It can be passed as string. That causes problems with
|
|
// conversions between byte array and UNICODE and back
|
|
// but we got to stick with it for compatibility with previous versions.
|
|
//
|
|
|
|
if ( FAILED( hres = GetBlobFromVariant( &vKey, &pbCert, &cbCert ) ) )
|
|
{
|
|
goto Exit;
|
|
}
|
|
pbKeyData = pbCert;
|
|
cbKeyData = cbCert;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// the rest of the lookups (by mapping, name or by account name)
|
|
// assumes string
|
|
//
|
|
if ( FAILED( hres = VariantChangeType( &vKeyBSTR, &vKey, 0, VT_BSTR ) ) )
|
|
{
|
|
goto Exit;
|
|
}
|
|
pbKeyData = (PBYTE) V_BSTR( &vKeyBSTR );
|
|
cbKeyData = ( SysStringLen(V_BSTR( &vKeyBSTR )) + 1 ) * sizeof(WCHAR);
|
|
}
|
|
|
|
|
|
//
|
|
// enumerate all entries to find match
|
|
// Now this is really slooow if many mappings are configured
|
|
//
|
|
for(;;)
|
|
{
|
|
hres = m_pcAdmCom->EnumKeys( m_hmd,
|
|
L"",
|
|
achIndex,
|
|
dwIndex
|
|
);
|
|
if ( FAILED( hres ) )
|
|
{
|
|
if ( hres == HRESULT_FROM_WIN32( ERROR_NO_MORE_ITEMS ) )
|
|
{
|
|
// Error PATH_NOT_FOUND chosen for backward compatibility
|
|
// with version IIS5.1 and older
|
|
//
|
|
hres = HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND );
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
switch ( lMethod )
|
|
{
|
|
case IISMAPPER_LOCATE_BY_CERT:
|
|
hres = GetMdData( achIndex, MD_MAPCERT, BINARY_METADATA, &cbData,
|
|
&pbData );
|
|
if ( hres == MD_ERROR_DATA_NOT_FOUND )
|
|
{
|
|
cbData = 0;
|
|
pbData = NULL;
|
|
}
|
|
else if ( FAILED( hres ) )
|
|
{
|
|
// goto next entry
|
|
break;
|
|
}
|
|
//
|
|
// compare if key is matching value read from metabase
|
|
//
|
|
|
|
if ( cbData == cbKeyData )
|
|
{
|
|
if ( ( cbData == 0 ) ||
|
|
memcmp( pbKeyData, pbData, cbData ) == 0 )
|
|
{
|
|
// we found match
|
|
hres = S_OK;
|
|
goto Exit;
|
|
}
|
|
}
|
|
break;
|
|
case IISMAPPER_LOCATE_BY_ACCT:
|
|
hres = GetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA, &cbData,
|
|
&pbData );
|
|
if ( hres == MD_ERROR_DATA_NOT_FOUND )
|
|
{
|
|
cbData = sizeof(L"");
|
|
pbData = (PBYTE) L"";
|
|
}
|
|
else if ( FAILED( hres ) )
|
|
{
|
|
// goto next entry
|
|
break;
|
|
}
|
|
|
|
if ( cbData == cbKeyData )
|
|
{
|
|
if ( _wcsicmp( (WCHAR *) pbKeyData, (WCHAR *) pbData ) == 0 )
|
|
{
|
|
// we found match
|
|
hres = S_OK;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case IISMAPPER_LOCATE_BY_NAME:
|
|
hres = GetMdData( achIndex, MD_MAPNAME, STRING_METADATA, &cbData,
|
|
&pbData );
|
|
if ( hres == MD_ERROR_DATA_NOT_FOUND )
|
|
{
|
|
cbData = sizeof(L"");
|
|
pbData = (PBYTE) L"";
|
|
}
|
|
else if ( FAILED( hres ) )
|
|
{
|
|
// goto next entry
|
|
break;
|
|
}
|
|
|
|
if ( cbData == cbKeyData )
|
|
{
|
|
if ( _wcsicmp( (WCHAR *) pbKeyData, (WCHAR *) pbData ) == 0 )
|
|
{
|
|
// we found match
|
|
hres = S_OK;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if ( pbData != NULL )
|
|
{
|
|
LocalFree( pbData );
|
|
pbData = NULL;
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if ( pbData != NULL )
|
|
{
|
|
LocalFree( pbData );
|
|
pbData = NULL;
|
|
}
|
|
|
|
if ( pbCert != NULL )
|
|
{
|
|
LocalFree( pbCert );
|
|
pbCert = NULL;
|
|
}
|
|
|
|
if ( SUCCEEDED( hres ) )
|
|
{
|
|
wcsncpy( pszResKey, achIndex, METADATA_MAX_NAME_LEN + 1 );
|
|
pszResKey[ METADATA_MAX_NAME_LEN ] ='\0';
|
|
}
|
|
VariantClear( &vKeyUI4 );
|
|
VariantClear( &vKeyBSTR );
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
//
|
|
// IIS5, IIS51 mapping functions
|
|
// They call IIS6 mapping function when connecting to IIS6 box
|
|
//
|
|
|
|
HRESULT
|
|
CIISDsCrMap::CreateMapping(
|
|
VARIANT vCert,
|
|
BSTR bstrNtAcct,
|
|
BSTR bstrNtPwd,
|
|
BSTR bstrName,
|
|
LONG lEnabled
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
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
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
if ( m_fIsIIS6 )
|
|
{
|
|
return CreateMappingIIS6( vCert,
|
|
bstrNtAcct,
|
|
bstrNtPwd,
|
|
bstrName,
|
|
lEnabled );
|
|
}
|
|
|
|
HRESULT hres;
|
|
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[LOCAL_MAX_SIZE];
|
|
VARIANT vOldAcct;
|
|
VARIANT vOldCert;
|
|
VARIANT vOldPwd;
|
|
VARIANT vOldName;
|
|
VARIANT vOldEnabledFlag;
|
|
PCCERT_CONTEXT pcCert = NULL;
|
|
|
|
//
|
|
// Do some sanity checks on the cert
|
|
//
|
|
if ( SUCCEEDED( hres = GetStringFromVariant( &vCert,
|
|
(LPSTR*)&pbCert,
|
|
&cCert,
|
|
FALSE ) ) )
|
|
{
|
|
//
|
|
// try to construct a cert context
|
|
//
|
|
if ( !( pcCert = CertCreateCertificateContext( X509_ASN_ENCODING,
|
|
pbCert,
|
|
cCert ) ) )
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"Invalid cert passed to CreateMapping()\n"));
|
|
//
|
|
// 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
|
|
//
|
|
hres = RETURNCODETOHRESULT( E_INVALIDARG );
|
|
FreeString( (LPSTR) pbCert );
|
|
goto Exit;
|
|
}
|
|
|
|
CertFreeCertificateContext( pcCert );
|
|
}
|
|
else
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// check if we already have a mapping for this cert; if we do, we'll replace that mapping
|
|
// with the new one
|
|
//
|
|
if ( SUCCEEDED( hres = GetMapping( IISMAPPER_LOCATE_BY_CERT,
|
|
vCert,
|
|
&vOldCert,
|
|
&vOldAcct,
|
|
&vOldPwd,
|
|
&vOldName,
|
|
&vOldEnabledFlag ) ) )
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT,
|
|
"Replacing old 1-1 cert mapping with new mapping\n"));
|
|
|
|
if ( FAILED( hres = SetName( IISMAPPER_LOCATE_BY_CERT,
|
|
vCert,
|
|
bstrName ) ) ||
|
|
FAILED( hres = SetAcct( IISMAPPER_LOCATE_BY_CERT,
|
|
vCert,
|
|
bstrNtAcct ) ) ||
|
|
FAILED( hres = SetPwd( IISMAPPER_LOCATE_BY_CERT,
|
|
vCert,
|
|
bstrNtPwd ) ) ||
|
|
FAILED( hres = SetEnabled( IISMAPPER_LOCATE_BY_CERT,
|
|
vCert,
|
|
lEnabled ) ) )
|
|
{
|
|
hres; //NOP - Something failed
|
|
}
|
|
}
|
|
//
|
|
// New mapping
|
|
//
|
|
else if ( hres == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
|
|
{
|
|
//
|
|
// check mapping exists, create if not
|
|
//
|
|
hres = OpenMd( L"Cert11", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
|
|
|
|
if ( hres == RETURNCODETOHRESULT( ERROR_PATH_NOT_FOUND ) )
|
|
{
|
|
if ( SUCCEEDED( hres = OpenMd( L"",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
hres = CreateMdObject( L"Cert11" );
|
|
CloseMd( FALSE );
|
|
|
|
// Reopen to the correct node.
|
|
hres = OpenMd( L"Cert11", METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ );
|
|
}
|
|
}
|
|
|
|
if ( FAILED( hres ) )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// adding mapping cert "0" means add @ end of list
|
|
//
|
|
|
|
if ( SUCCEEDED( hres = CreateMdObject( L"mappings/0" ) ) )
|
|
{
|
|
if ( SUCCEEDED( hres = GetMdData( L"", MD_NSEPM_ACCESS_CERT, DWORD_METADATA, &
|
|
cRes, &pRes ) ) )
|
|
{
|
|
if ( cRes == sizeof(DWORD ) )
|
|
{
|
|
wsprintfW( achIndex, L"mappings/%u", *(LPDWORD)pRes );
|
|
|
|
if ( FAILED( hres = GetStringFromBSTR( bstrNtAcct, &pszNtAcct, &cNtAcct ) ) ||
|
|
FAILED( hres = GetStringFromBSTR( bstrNtPwd, &pszNtPwd, &cNtPwd ) ) ||
|
|
FAILED( hres = GetStringFromBSTR( bstrName, &pszName, &cName ) ) ||
|
|
FAILED( hres = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA,
|
|
sizeof(DWORD), (LPBYTE)&lEnabled ) ) ||
|
|
FAILED( hres = SetMdData( achIndex, MD_MAPNAME, STRING_METADATA,
|
|
cName, (LPBYTE)pszName ) ) ||
|
|
FAILED( hres = SetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA,
|
|
cNtPwd, (LPBYTE)pszNtPwd ) ) ||
|
|
FAILED( hres = SetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA,
|
|
cNtAcct, (LPBYTE)pszNtAcct ) ) ||
|
|
FAILED( hres = SetMdData( achIndex, MD_MAPCERT, BINARY_METADATA,
|
|
cCert, (LPBYTE)pbCert ) ) )
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hres = E_FAIL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseMd( SUCCEEDED( hres ) );
|
|
|
|
FreeString( (LPSTR)pbCert );
|
|
FreeString( pszNtAcct );
|
|
FreeString( pszNtPwd );
|
|
FreeString( pszName );
|
|
|
|
Exit:
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::GetMapping(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
VARIANT* pvCert,
|
|
VARIANT* pbstrNtAcct,
|
|
VARIANT* pbstrNtPwd,
|
|
VARIANT* pbstrName,
|
|
VARIANT* plEnabled
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
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
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
if ( m_fIsIIS6 )
|
|
{
|
|
return GetMappingIIS6( lMethod,
|
|
vKey,
|
|
pvCert,
|
|
pbstrNtAcct,
|
|
pbstrNtPwd,
|
|
pbstrName,
|
|
plEnabled );
|
|
}
|
|
|
|
WCHAR achIndex[LOCAL_MAX_SIZE];
|
|
HRESULT hres;
|
|
DWORD dwLen;
|
|
LPBYTE pbData;
|
|
|
|
VariantInit( pvCert );
|
|
VariantInit( pbstrNtAcct );
|
|
VariantInit( pbstrNtPwd );
|
|
VariantInit( pbstrName );
|
|
VariantInit( plEnabled );
|
|
|
|
if ( SUCCEEDED( hres = OpenMd( L"Cert11",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
|
|
{
|
|
if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPCERT, BINARY_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
hres = SetVariantAsByteArray( pvCert, dwLen, pbData );
|
|
LocalFree( pbData );
|
|
}
|
|
else
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPNTACCT, STRING_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
hres = SetVariantAsBSTR( pbstrNtAcct, dwLen, pbData );
|
|
LocalFree( pbData );
|
|
}
|
|
else
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPNTPWD, STRING_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
hres = SetVariantAsBSTR( pbstrNtPwd, dwLen, pbData );
|
|
LocalFree( pbData );
|
|
}
|
|
else
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
if ( SUCCEEDED( hres = GetMdData( achIndex, MD_MAPNAME, STRING_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
hres = SetVariantAsBSTR( pbstrName, dwLen, pbData );
|
|
LocalFree( pbData );
|
|
}
|
|
else
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
if ( FAILED( hres = GetMdData( achIndex, MD_MAPENABLED, STRING_METADATA, &dwLen,
|
|
&pbData ) ) )
|
|
{
|
|
SetVariantAsLong( plEnabled, FALSE );
|
|
}
|
|
else
|
|
{
|
|
SetVariantAsLong( plEnabled, *(LPDWORD)pbData );
|
|
LocalFree( pbData );
|
|
}
|
|
}
|
|
|
|
Done:
|
|
CloseMd( FALSE );
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::DeleteMapping(
|
|
LONG lMethod,
|
|
VARIANT vKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
if ( m_fIsIIS6 )
|
|
{
|
|
return DeleteMappingIIS6( lMethod,
|
|
vKey );
|
|
}
|
|
WCHAR achIndex[LOCAL_MAX_SIZE];
|
|
HRESULT hres;
|
|
|
|
if ( SUCCEEDED( hres = OpenMd( L"Cert11",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
|
|
{
|
|
hres = DeleteMdObject( achIndex );
|
|
}
|
|
CloseMd( TRUE );
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetEnabled(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
LONG lEnabled
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the enable flag on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
lEnabled - 1 to enable, 0 to disable
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
if ( m_fIsIIS6 )
|
|
{
|
|
return SetEnabledIIS6( lMethod,
|
|
vKey,
|
|
lEnabled );
|
|
}
|
|
|
|
WCHAR achIndex[LOCAL_MAX_SIZE];
|
|
HRESULT hres;
|
|
|
|
if ( SUCCEEDED( hres = OpenMd( L"Cert11",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
|
|
{
|
|
hres = SetMdData( achIndex, MD_MAPENABLED, DWORD_METADATA, sizeof(DWORD), (LPBYTE)&lEnabled );
|
|
}
|
|
CloseMd( TRUE );
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetName(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
BSTR bstrName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the Name on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
bstrName - name to assign to mapping entry
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
if ( m_fIsIIS6 )
|
|
{
|
|
return SetNameIIS6( lMethod,
|
|
vKey,
|
|
bstrName );
|
|
}
|
|
|
|
return SetString( lMethod, vKey, bstrName, MD_MAPNAME );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetString(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
BSTR bstrName,
|
|
DWORD dwProp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set a string property on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
bstrName - string content to assign to mapping entry
|
|
dwProp - property ID to assign to
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
WCHAR achIndex[LOCAL_MAX_SIZE];
|
|
LPSTR pszName = NULL;
|
|
HRESULT hres;
|
|
DWORD dwLen;
|
|
|
|
|
|
if ( FAILED( hres = GetStringFromBSTR( bstrName, &pszName, &dwLen, TRUE ) ) )
|
|
{
|
|
return hres;
|
|
}
|
|
|
|
if ( SUCCEEDED( hres = OpenMd( L"Cert11",
|
|
METADATA_PERMISSION_WRITE|METADATA_PERMISSION_READ ) ) )
|
|
{
|
|
if ( SUCCEEDED(hres = Locate( lMethod, vKey, achIndex )) )
|
|
{
|
|
hres = SetMdData( achIndex, dwProp, STRING_METADATA, dwLen, (LPBYTE)pszName );
|
|
}
|
|
CloseMd( TRUE );
|
|
}
|
|
|
|
FreeString( pszName );
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetPwd(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
BSTR bstrPwd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the Password on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
bstrPwd - password to assign to mapping entry
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
if ( m_fIsIIS6 )
|
|
{
|
|
return SetPwdIIS6( lMethod,
|
|
vKey,
|
|
bstrPwd );
|
|
}
|
|
|
|
return SetString( lMethod, vKey, bstrPwd, MD_MAPNTPWD );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetAcct(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
BSTR bstrAcct
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the NT account name on a mapping entry using key
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
bstrAcct - NT account name to assign to mapping entry
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
if ( m_fIsIIS6 )
|
|
{
|
|
return SetAcctIIS6( lMethod,
|
|
vKey,
|
|
bstrAcct );
|
|
}
|
|
|
|
return SetString( lMethod, vKey, bstrAcct, MD_MAPNTACCT );
|
|
}
|
|
|
|
|
|
|
|
////
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::OpenMd(
|
|
LPWSTR pszOpenPath,
|
|
DWORD dwPermission
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Open metabase using path & permission
|
|
path is relative to the top of the name space extension ( i.e. /.../<nsepm> )
|
|
|
|
Arguments:
|
|
|
|
pszOpenPath - path to open inside name space extension
|
|
dwPermission - metabase permission ( read/write )
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
HRESULT hres;
|
|
LPWSTR pszPath;
|
|
UINT cL = wcslen( m_pszMetabasePath );
|
|
|
|
pszPath = (LPWSTR)LocalAlloc( LMEM_FIXED, (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 );
|
|
|
|
hres = OpenAdminBaseKey(
|
|
m_pszServerName,
|
|
pszPath,
|
|
dwPermission,
|
|
&m_pcAdmCom,
|
|
&m_hmd
|
|
);
|
|
|
|
LocalFree( pszPath );
|
|
|
|
if ( FAILED(hres) )
|
|
{
|
|
m_hmd = NULL;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::CloseMd(
|
|
BOOL fSave
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
close metabase
|
|
|
|
Arguments:
|
|
|
|
fSave - TRUE to save data immediatly
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
CloseAdminBaseKey( m_pcAdmCom, m_hmd );
|
|
m_hmd = NULL;
|
|
|
|
if ( m_pcAdmCom && fSave )
|
|
{
|
|
m_pcAdmCom->SaveData();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::DeleteMdObject(
|
|
LPWSTR pszKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete metabase object in an opened tree
|
|
OpenMd() must be called 1st
|
|
|
|
Arguments:
|
|
|
|
pszKey - key to delete in opened metabase
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
return m_pcAdmCom->DeleteKey( m_hmd, pszKey );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::CreateMdObject(
|
|
LPWSTR pszKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create metabase object in an opened tree
|
|
OpenMd() must be called 1st
|
|
|
|
Arguments:
|
|
|
|
pszKey - key to create in opened metabase
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
return m_pcAdmCom->AddKey( m_hmd, pszKey );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::SetMdData(
|
|
LPWSTR achIndex,
|
|
DWORD dwProp,
|
|
DWORD dwDataType,
|
|
DWORD dwDataLen,
|
|
LPBYTE pbData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set a metabase property
|
|
OpenMd() must be called 1st
|
|
Property will be stored with NULL attribute, except for MD_MAPPWD
|
|
which will be stored with METADATA_SECURE
|
|
|
|
Arguments:
|
|
|
|
achIndex - key name where to store property
|
|
dwProp - property ID
|
|
dwDataType - property data type
|
|
dwDataLen - property length
|
|
pbData - property value
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
METADATA_RECORD md;
|
|
|
|
md.dwMDDataLen = dwDataLen;
|
|
md.dwMDDataType = dwDataType;
|
|
md.dwMDIdentifier = dwProp;
|
|
md.dwMDAttributes = (dwProp == MD_MAPNTPWD) ? METADATA_SECURE : 0;
|
|
md.pbMDData = pbData;
|
|
|
|
return m_pcAdmCom->SetData( m_hmd, achIndex, &md );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::GetMdData(
|
|
LPWSTR achIndex,
|
|
DWORD dwProp,
|
|
DWORD dwDataType,
|
|
LPDWORD pdwDataLen,
|
|
LPBYTE* ppbData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get a metabase property
|
|
OpenMd() must be called 1st
|
|
|
|
Arguments:
|
|
|
|
achIndex - key name where to get property
|
|
dwProp - property ID
|
|
dwDataType - property data type
|
|
pdwDataLen - property length
|
|
ppData - property value, to be freed using LocalFree() on successfull return
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
HRESULT hres;
|
|
METADATA_RECORD md;
|
|
DWORD dwRequired;
|
|
|
|
md.dwMDDataLen = 0;
|
|
md.dwMDDataType = dwDataType;
|
|
md.dwMDIdentifier = dwProp;
|
|
md.dwMDAttributes = 0;
|
|
md.pbMDData = NULL;
|
|
|
|
if ( FAILED(hres = m_pcAdmCom->GetData( m_hmd, achIndex, &md, &dwRequired )) )
|
|
{
|
|
if ( hres == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER) )
|
|
{
|
|
if ( (*ppbData = (LPBYTE)LocalAlloc( LMEM_FIXED, dwRequired )) == NULL )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
md.pbMDData = *ppbData;
|
|
md.dwMDDataLen = dwRequired;
|
|
hres = m_pcAdmCom->GetData( m_hmd, achIndex, &md, &dwRequired );
|
|
*pdwDataLen = md.dwMDDataLen;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pdwDataLen = 0;
|
|
*ppbData = NULL;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
//////
|
|
|
|
HRESULT
|
|
CIISDsCrMap::Locate(
|
|
LONG lMethod,
|
|
VARIANT vKey,
|
|
LPWSTR pszResKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locate a mapping entry based on key
|
|
OpenMd() must be called 1st
|
|
|
|
Arguments:
|
|
|
|
lMethod - method to use for access ( IISMAPPER_LOCATE_BY_* )
|
|
vKey - key to use to locate mapping
|
|
pszResKey -
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
if ( m_fIsIIS6 )
|
|
{
|
|
return LocateIIS6( lMethod,
|
|
vKey,
|
|
pszResKey );
|
|
}
|
|
|
|
HRESULT hres;
|
|
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( hres = GetStringFromVariant( &vKey, &pV, &cV, TRUE ) ) )
|
|
{
|
|
WCHAR pwV[LOCAL_MAX_SIZE];
|
|
int i = MultiByteToWideChar(CP_ACP, 0, pV, cV, pwV, LOCAL_MAX_SIZE);
|
|
|
|
if (i ==0)
|
|
return E_FAIL; // MultiByteToWideChar failure
|
|
if (i >= (int)(LOCAL_MAX_SIZE - wcslen(L"mappings/")))
|
|
return E_FAIL; //pwV is too big for pszResKey
|
|
|
|
wsprintfW( pszResKey, L"mappings/%s", pwV );
|
|
}
|
|
goto Exit;
|
|
|
|
default:
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// get ptr to data
|
|
//
|
|
|
|
if ( SUCCEEDED( hres = GetStringFromVariant( &vKey, &pV, &cV, fAddDelim ) ) )
|
|
{
|
|
//
|
|
// set search prop, get result
|
|
//
|
|
|
|
if ( SUCCEEDED( hres = SetMdData( L"", dwProp, BINARY_METADATA, cV, (LPBYTE)pV ) ) )
|
|
{
|
|
if ( SUCCEEDED( hres = GetMdData( L"", dwProp, DWORD_METADATA, &cRes, (LPBYTE*)&pRes ) ) )
|
|
{
|
|
if ( cRes == sizeof(DWORD ) )
|
|
{
|
|
wsprintfW( pszResKey, L"mappings/%u", *(LPDWORD)pRes );
|
|
}
|
|
else
|
|
{
|
|
hres = E_FAIL;
|
|
}
|
|
LocalFree( pRes );
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
FreeString( pV );
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetStringFromBSTR(
|
|
BSTR bstr,
|
|
LPSTR* psz,
|
|
LPDWORD pdwLen,
|
|
BOOL fAddDelimInCount
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
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
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
UINT cch = SysStringLen(bstr);
|
|
UINT cchT;
|
|
|
|
// include NULL terminator
|
|
|
|
*pdwLen = cch + (fAddDelimInCount ? 1 : 0);
|
|
|
|
CHAR *szNew = (CHAR*)LocalAlloc( LMEM_FIXED, (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;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetStringFromVariant(
|
|
VARIANT* pVar,
|
|
LPSTR* psz,
|
|
LPDWORD pdwLen,
|
|
BOOL fAddDelim
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
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
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
LPBYTE pbV;
|
|
UINT cV;
|
|
HRESULT hres;
|
|
WORD vt = V_VT(pVar);
|
|
BOOL fByRef = FALSE;
|
|
VARIANT vOut;
|
|
|
|
VariantInit( &vOut );
|
|
|
|
if ( vt & VT_BYREF )
|
|
{
|
|
vt &= ~VT_BYREF;
|
|
fByRef = TRUE;
|
|
}
|
|
|
|
if ( vt == VT_DISPATCH )
|
|
{
|
|
if ( FAILED(hres = VariantResolveDispatch( &vOut, pVar )) )
|
|
{
|
|
return hres;
|
|
}
|
|
pVar = &vOut;
|
|
vt = V_VT(pVar);
|
|
if ( fByRef = vt & VT_BYREF )
|
|
{
|
|
vt &= ~VT_BYREF;
|
|
}
|
|
}
|
|
|
|
// 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 )
|
|
{
|
|
hres = 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 );
|
|
|
|
hres = SafeArrayGetLBound(pSafeArray, 1, &lBound);
|
|
hres = SafeArrayGetUBound(pSafeArray, 1, &uBound);
|
|
|
|
cV = uBound - lBound + 1;
|
|
|
|
if ( !(pbV = (LPBYTE)LocalAlloc( LMEM_FIXED, cV )) )
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
hres = S_OK;
|
|
|
|
for( lItem = lBound; lItem <= uBound ; lItem++ )
|
|
{
|
|
hres = SafeArrayGetElement( pSafeArray, &lItem, &bValue );
|
|
if( FAILED( hres ) )
|
|
{
|
|
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 );
|
|
|
|
hres = SafeArrayGetLBound(pSafeArray, 1, &lBound);
|
|
hres = SafeArrayGetUBound(pSafeArray, 1, &uBound);
|
|
|
|
cV = uBound - lBound + 1;
|
|
|
|
if ( !(pbV = (LPBYTE)LocalAlloc( LMEM_FIXED, cV )) )
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
hres = S_OK;
|
|
|
|
for( lItem = lBound; lItem <= uBound ; lItem++ )
|
|
{
|
|
hres = SafeArrayGetElement( pSafeArray, &lItem, &vValue );
|
|
if( FAILED( hres ) )
|
|
{
|
|
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
|
|
{
|
|
hres = E_FAIL;
|
|
}
|
|
|
|
Exit:
|
|
VariantClear( &vOut );
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
GetStringAFromBSTR(
|
|
BSTR bstr,
|
|
LPSTR* psz,
|
|
LPDWORD pdwLen,
|
|
BOOL fAddDelimInCount
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocate string buffer from BSTR - for IIS6 only
|
|
|
|
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
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
UINT cch = SysStringLen(bstr);
|
|
UINT cchT;
|
|
|
|
// include NULL terminator
|
|
|
|
*pdwLen = cch + (fAddDelimInCount ? 1 : 0);
|
|
|
|
CHAR *szNew = (CHAR*)LocalAlloc( LMEM_FIXED, (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;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
GetBlobFromVariant(
|
|
VARIANT* pVar,
|
|
PBYTE* ppbOut,
|
|
LPDWORD pcbOut
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocate string buffer from BSTR - for IIS6 only
|
|
|
|
Arguments:
|
|
|
|
pVar - variant to convert from. Recognizes BSTR, VT_ARRAY|VT_UI1, ByRef or ByVal
|
|
ppbOut - updated with ptr to buffer, to be freed with LocalFree()
|
|
pcbOut - updated with size of input
|
|
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
LPBYTE pbV;
|
|
UINT cV;
|
|
HRESULT hres;
|
|
WORD vt = V_VT(pVar);
|
|
BOOL fByRef = FALSE;
|
|
VARIANT vOut;
|
|
|
|
VariantInit( &vOut );
|
|
|
|
if ( vt & VT_BYREF )
|
|
{
|
|
vt &= ~VT_BYREF;
|
|
fByRef = TRUE;
|
|
}
|
|
|
|
if ( vt == VT_DISPATCH )
|
|
{
|
|
if ( FAILED(hres = VariantResolveDispatch( &vOut, pVar )) )
|
|
{
|
|
return hres;
|
|
}
|
|
pVar = &vOut;
|
|
vt = V_VT(pVar);
|
|
if ( fByRef = vt & VT_BYREF )
|
|
{
|
|
vt &= ~VT_BYREF;
|
|
}
|
|
}
|
|
|
|
// 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 )
|
|
{
|
|
hres = GetStringAFromBSTR( fByRef ?
|
|
*(BSTR*)V_BSTR(pVar) :
|
|
V_BSTR(pVar),
|
|
(LPSTR *)ppbOut,
|
|
pcbOut,
|
|
FALSE );
|
|
}
|
|
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 );
|
|
|
|
hres = SafeArrayGetLBound(pSafeArray, 1, &lBound);
|
|
hres = SafeArrayGetUBound(pSafeArray, 1, &uBound);
|
|
|
|
cV = uBound - lBound + 1;
|
|
|
|
if ( !(pbV = (LPBYTE)LocalAlloc( LMEM_FIXED, cV )) )
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
hres = S_OK;
|
|
|
|
for( lItem = lBound; lItem <= uBound ; lItem++ )
|
|
{
|
|
hres = SafeArrayGetElement( pSafeArray, &lItem, &bValue );
|
|
if( FAILED( hres ) )
|
|
{
|
|
break;
|
|
}
|
|
pbV[lItem-lBound] = bValue;
|
|
}
|
|
|
|
*ppbOut = pbV;
|
|
*pcbOut = 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 );
|
|
|
|
hres = SafeArrayGetLBound(pSafeArray, 1, &lBound);
|
|
hres = SafeArrayGetUBound(pSafeArray, 1, &uBound);
|
|
|
|
cV = uBound - lBound + 1;
|
|
|
|
if ( !(pbV = (LPBYTE)LocalAlloc( LMEM_FIXED, cV )) )
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
hres = S_OK;
|
|
|
|
for( lItem = lBound; lItem <= uBound ; lItem++ )
|
|
{
|
|
hres = SafeArrayGetElement( pSafeArray, &lItem, &vValue );
|
|
if( FAILED( hres ) )
|
|
{
|
|
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;
|
|
}
|
|
|
|
*ppbOut = pbV;
|
|
*pcbOut = cV;
|
|
}
|
|
else
|
|
{
|
|
hres = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
Exit:
|
|
VariantClear( &vOut );
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
FreeString(
|
|
LPSTR psz
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free a string returned by GetStringFromVariant() or GetStringFromBTR()
|
|
can be NULL
|
|
|
|
Arguments:
|
|
|
|
psz - string to free, can be NULL
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
if ( psz )
|
|
{
|
|
LocalFree( psz );
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
SetBSTR(
|
|
BSTR* pbstrRet,
|
|
DWORD cch,
|
|
LPBYTE sz
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build a BSTR from byte array - for IIS5, IIS5.1 assumes ansi string on input
|
|
|
|
Arguments:
|
|
|
|
pbstrRet - updated with BSTR
|
|
cch - byte count in sz
|
|
sz - byte array
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
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)
|
|
{
|
|
SysFreeString(bstrRet);
|
|
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;
|
|
}
|
|
}
|
|
|
|
if (bstrRet != NULL)
|
|
bstrRet[cch] = 0;
|
|
*pbstrRet = bstrRet;
|
|
|
|
return(NOERROR);
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
SetBSTRFromStringW(
|
|
BSTR* pbstrRet,
|
|
DWORD cb,
|
|
LPBYTE sz
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build a BSTR from byte array (that is actually WCHAR string)
|
|
|
|
Arguments:
|
|
|
|
pbstrRet - updated with BSTR
|
|
cb - byte count
|
|
sz - byte array (we assume WCHAR string)
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
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, cb/sizeof(WCHAR));
|
|
if (bstrRet == NULL)
|
|
{
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
wcsncpy( bstrRet, (WCHAR *) sz, cb/sizeof(WCHAR) );
|
|
|
|
*pbstrRet = bstrRet;
|
|
|
|
return(NOERROR);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::Create(
|
|
IUnknown *pUnkOuter,
|
|
REFIID riid,
|
|
void **ppvObj
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a CIISDsCrMap
|
|
|
|
Arguments:
|
|
|
|
pUnkOuter - ptr to iunknown
|
|
riid - requested IID
|
|
ppvObj - updated with ptr to requested IID
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
CCredentials Credentials;
|
|
CIISDsCrMap FAR * pMap = NULL;
|
|
HRESULT hr = S_OK;
|
|
BSTR bstrAdsPath = NULL;
|
|
OBJECTINFO ObjectInfo;
|
|
POBJECTINFO pObjectInfo = &ObjectInfo;
|
|
CLexer * pLexer = NULL;
|
|
LPWSTR pszIISPathName = NULL;
|
|
|
|
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
|
|
|
|
hr = AllocateObject(pUnkOuter, Credentials, &pMap);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// get ServerName and pszPath
|
|
//
|
|
|
|
hr = pMap->_pADs->get_ADsPath(&bstrAdsPath);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pLexer = new CLexer();
|
|
hr = pLexer->Initialize(bstrAdsPath);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Parse the pathname
|
|
//
|
|
|
|
hr = ADsObject(pLexer, pObjectInfo);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pszIISPathName = AllocADsStr(bstrAdsPath);
|
|
if (!pszIISPathName) {
|
|
hr = E_OUTOFMEMORY;
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
*pszIISPathName = L'\0';
|
|
hr = BuildIISPathFromADsPath(
|
|
pObjectInfo,
|
|
pszIISPathName
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pMap->Init( pObjectInfo->TreeName,
|
|
pszIISPathName );
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// pass non-delegating IUnknown back to the aggregator
|
|
//
|
|
|
|
*ppvObj = (INonDelegatingUnknown FAR *) pMap;
|
|
|
|
if (bstrAdsPath) {
|
|
ADsFreeString(bstrAdsPath);
|
|
}
|
|
|
|
if (pLexer) {
|
|
delete pLexer;
|
|
}
|
|
|
|
if (pszIISPathName ) {
|
|
FreeADsStr( pszIISPathName );
|
|
}
|
|
|
|
FreeObjectInfo( &ObjectInfo );
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
if (bstrAdsPath) {
|
|
ADsFreeString(bstrAdsPath);
|
|
}
|
|
|
|
if (pLexer) {
|
|
delete pLexer;
|
|
}
|
|
|
|
if (pszIISPathName ) {
|
|
FreeADsStr( pszIISPathName );
|
|
}
|
|
|
|
FreeObjectInfo( &ObjectInfo );
|
|
|
|
*ppvObj = NULL;
|
|
|
|
delete pMap;
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CIISDsCrMap::QueryInterface(
|
|
REFIID iid,
|
|
LPVOID FAR* ppv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Query interface to CIISDsCrMap
|
|
|
|
Arguments:
|
|
|
|
iid - requested IID
|
|
ppv - updated with ptr to requested IID
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = _pUnkOuter->QueryInterface(iid,ppv);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
CIISDsCrMap::CIISDsCrMap(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
CIISDsCrMap constructor
|
|
|
|
Arguments:
|
|
|
|
pADs - ptr to contained ADs
|
|
Credentials - credential
|
|
pDispMgr - ptr to dispatch manager
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pcAdmCom = NULL;
|
|
m_hmd = NULL;
|
|
m_pszServerName = NULL;
|
|
m_pszMetabasePath = NULL;
|
|
m_ADsPath = NULL;
|
|
_pADs = NULL;
|
|
_pDispMgr = NULL;
|
|
m_fIsIIS6 = TRUE;
|
|
ENLIST_TRACKING(CIISDsCrMap);
|
|
}
|
|
|
|
|
|
CIISDsCrMap::~CIISDsCrMap(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
CIISDsCrMap destructor
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
if ( m_ADsPath )
|
|
{
|
|
ADsFreeString( m_ADsPath );
|
|
}
|
|
|
|
if ( m_pszServerName )
|
|
{
|
|
LocalFree( m_pszServerName );
|
|
}
|
|
|
|
if ( m_pszMetabasePath )
|
|
{
|
|
LocalFree( m_pszMetabasePath );
|
|
}
|
|
|
|
if ( _pDispMgr )
|
|
{
|
|
delete _pDispMgr;
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::AllocateObject(
|
|
IUnknown *pUnkOuter,
|
|
CCredentials& Credentials,
|
|
CIISDsCrMap ** ppMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocate CIISDsCrMap
|
|
|
|
Arguments:
|
|
|
|
pUnkOuter - ptr to iunknown
|
|
Credentials - credential
|
|
ppMap - updated with ptr to IUnknown to Allocated object
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
CIISDsCrMap FAR * pMap = NULL;
|
|
IADs FAR * pADs = NULL;
|
|
CAggregateeDispMgr FAR * pDispMgr = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
pDispMgr = new CAggregateeDispMgr;
|
|
if (pDispMgr == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pMap = new CIISDsCrMap();
|
|
if (pMap == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = pDispMgr->LoadTypeInfoEntry(
|
|
LIBID_IISExt, //LIBID_ADs,
|
|
IID_IISDsCrMap,
|
|
(IISDsCrMap *)pMap,
|
|
DISPID_REGULAR
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Store the IADs Pointer, but again do NOT ref-count
|
|
// this pointer - we keep the pointer around, but do
|
|
// a release immediately.
|
|
//
|
|
|
|
hr = pUnkOuter->QueryInterface(IID_IADs, (void **)&pADs);
|
|
pADs->Release();
|
|
pMap->_pADs = pADs;
|
|
|
|
//
|
|
// Store the pointer to the pUnkOuter object
|
|
// AND DO NOT add ref this pointer
|
|
//
|
|
|
|
pMap->_pUnkOuter = pUnkOuter;
|
|
|
|
pMap->m_Credentials = Credentials;
|
|
pMap->_pDispMgr = pDispMgr;
|
|
*ppMap = pMap;
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
delete pDispMgr;
|
|
delete pMap;
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CIISDsCrMap::Init(
|
|
LPWSTR pszServerName,
|
|
LPWSTR pszMetabasePath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize CIISDsCrMap
|
|
|
|
Arguments:
|
|
|
|
pszServerName - target computer name for metabase access
|
|
pszParent - metabase path to IisMapper object
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
UINT cL;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwMajVer = 0;
|
|
DWORD dwLen = 0;
|
|
METADATA_RECORD mr = {
|
|
MD_SERVER_VERSION_MAJOR,
|
|
METADATA_NO_ATTRIBUTES,
|
|
IIS_MD_UT_SERVER,
|
|
DWORD_METADATA,
|
|
sizeof(DWORD),
|
|
(unsigned char*)&dwMajVer,
|
|
0
|
|
};
|
|
|
|
hr = InitServerInfo(pszServerName, &m_pcAdmCom);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
// need to set m_fIsIIS6
|
|
METADATA_HANDLE MDataHandle;
|
|
hr = OpenAdminBaseKey(pszServerName,
|
|
L"/LM/W3SVC/Info",
|
|
METADATA_PERMISSION_READ,
|
|
&m_pcAdmCom,
|
|
&MDataHandle);
|
|
|
|
if (HRESULTTOWIN32(hr) == ERROR_PATH_NOT_FOUND)
|
|
{
|
|
m_fIsIIS6 = FALSE;
|
|
}
|
|
else
|
|
{
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
hr = m_pcAdmCom->GetData(
|
|
MDataHandle,
|
|
L"",
|
|
&mr,
|
|
&dwLen);
|
|
|
|
if(hr == MD_ERROR_DATA_NOT_FOUND)
|
|
{
|
|
m_fIsIIS6 = FALSE;
|
|
}
|
|
else
|
|
{
|
|
BAIL_ON_FAILURE(hr);
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
if (dwMajVer >= 6)
|
|
{
|
|
m_fIsIIS6 = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_fIsIIS6 = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
cL = wcslen( pszServerName );
|
|
if ( m_pszServerName = (LPWSTR)LocalAlloc( LMEM_FIXED, ( cL + 1 )*sizeof(WCHAR) ) )
|
|
{
|
|
memcpy( m_pszServerName, pszServerName, ( cL + 1 )*sizeof(WCHAR) );
|
|
}
|
|
else
|
|
{
|
|
BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
|
|
}
|
|
|
|
cL = wcslen( pszMetabasePath );
|
|
while ( cL && pszMetabasePath[cL-1] != L'/' && pszMetabasePath[cL-1] != L'\\' )
|
|
{
|
|
--cL;
|
|
}
|
|
if ( m_fIsIIS6 && ( m_pszMetabasePath = (LPWSTR)LocalAlloc( LMEM_FIXED, (( cL + 1 )*sizeof(WCHAR) ) )))
|
|
{
|
|
memcpy( m_pszMetabasePath, pszMetabasePath, cL * sizeof(WCHAR) );
|
|
m_pszMetabasePath[ cL ] = L'\0';
|
|
}
|
|
else if ( !m_fIsIIS6 && ( m_pszMetabasePath = (LPWSTR)LocalAlloc( LMEM_FIXED, ( cL*sizeof(WCHAR) + sizeof(L"<nsepm>") )) ) )
|
|
{
|
|
memcpy( m_pszMetabasePath, pszMetabasePath, cL * sizeof(WCHAR) );
|
|
memcpy( m_pszMetabasePath + cL, L"<nsepm>", sizeof(L"<nsepm>") );
|
|
}
|
|
else
|
|
{
|
|
BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
|
|
}
|
|
|
|
error:
|
|
if (m_pcAdmCom)
|
|
{
|
|
CloseAdminBaseKey(m_pcAdmCom, MDataHandle);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
SetVariantAsByteArray(
|
|
VARIANT* pvarReturn,
|
|
DWORD cbLen,
|
|
LPBYTE pbIn
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create variant as byte array
|
|
|
|
Arguments:
|
|
|
|
pVarReturn - ptr to created variant
|
|
cbLen - byte count
|
|
pbIn - byte array
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
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
|
|
SetVariantAsBSTR(
|
|
VARIANT* pvarReturn,
|
|
DWORD cbLen,
|
|
LPBYTE pbIn
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create variant BSTR
|
|
|
|
Arguments:
|
|
|
|
pVarReturn - ptr to created variant
|
|
cbLen - byte count
|
|
pbIn - byte array
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
|
|
V_VT(pvarReturn) = VT_BSTR;
|
|
return SetBSTR( &V_BSTR(pvarReturn), cbLen, pbIn );
|
|
}
|
|
|
|
HRESULT
|
|
SetVariantAsBSTRFromStringW(
|
|
VARIANT* pvarReturn,
|
|
DWORD cbLen,
|
|
LPBYTE pbIn
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create variant BSTR
|
|
|
|
Arguments:
|
|
|
|
pVarReturn - ptr to created variant
|
|
cbLen - byte count
|
|
pbIn - byte array
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
|
|
V_VT(pvarReturn) = VT_BSTR;
|
|
return SetBSTRFromStringW( &V_BSTR(pvarReturn), cbLen, pbIn );
|
|
}
|
|
|
|
HRESULT
|
|
SetVariantAsLong(
|
|
VARIANT* pvarReturn,
|
|
DWORD dwV
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create variant as long
|
|
|
|
Arguments:
|
|
|
|
pVarReturn - ptr to created variant
|
|
dwV - value
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
|
|
V_VT(pvarReturn) = VT_I4;
|
|
V_I4(pvarReturn) = dwV;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
VariantResolveDispatch(
|
|
VARIANT * pVarOut,
|
|
VARIANT * pVarIn
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Extract value from IDispatch default property
|
|
|
|
Arguments:
|
|
|
|
pVarOut - ptr to created variant
|
|
pVarIn - ptr to IDispatch variant to resolve
|
|
|
|
Returns:
|
|
|
|
COM status
|
|
|
|
--*/
|
|
{
|
|
VARIANT varResolved; // value of IDispatch::Invoke
|
|
DISPPARAMS dispParamsNoArgs = {NULL, NULL, 0, 0};
|
|
EXCEPINFO ExcepInfo;
|
|
HRESULT hrCopy;
|
|
|
|
|
|
VariantInit(pVarOut);
|
|
|
|
hrCopy = VariantCopy(pVarOut, pVarIn);
|
|
|
|
if (FAILED(hrCopy))
|
|
{
|
|
return hrCopy;
|
|
}
|
|
|
|
// follow the IDispatch chain.
|
|
//
|
|
while (V_VT(pVarOut) == VT_DISPATCH)
|
|
{
|
|
HRESULT hrInvoke = S_OK;
|
|
|
|
// If the variant is equal to Nothing, then it can be argued
|
|
// with certainty that it does not have a default property!
|
|
// hence we return DISP_E_MEMBERNOTFOUND for this case.
|
|
//
|
|
if (V_DISPATCH(pVarOut) == NULL)
|
|
{
|
|
hrInvoke = DISP_E_MEMBERNOTFOUND;
|
|
}
|
|
else
|
|
{
|
|
VariantInit(&varResolved);
|
|
hrInvoke = V_DISPATCH(pVarOut)->Invoke(
|
|
DISPID_VALUE,
|
|
IID_NULL,
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
DISPATCH_PROPERTYGET | DISPATCH_METHOD,
|
|
&dispParamsNoArgs,
|
|
&varResolved,
|
|
&ExcepInfo,
|
|
NULL);
|
|
}
|
|
|
|
if (FAILED(hrInvoke))
|
|
{
|
|
if (hrInvoke == DISP_E_EXCEPTION)
|
|
{
|
|
//
|
|
// forward the ExcepInfo from Invoke to caller's ExcepInfo
|
|
//
|
|
SysFreeString(ExcepInfo.bstrHelpFile);
|
|
}
|
|
|
|
VariantClear(pVarOut);
|
|
return hrInvoke;
|
|
}
|
|
|
|
// The correct code to restart the loop is:
|
|
//
|
|
// VariantClear(pVar)
|
|
// VariantCopy(pVar, &varResolved);
|
|
// VariantClear(&varResolved);
|
|
//
|
|
// however, the same affect can be achieved by:
|
|
//
|
|
// VariantClear(pVar)
|
|
// *pVar = varResolved;
|
|
// VariantInit(&varResolved)
|
|
//
|
|
// this avoids a copy. The equivalence rests in the fact that
|
|
// *pVar will contain the pointers of varResolved, after we
|
|
// trash varResolved (WITHOUT releasing strings or dispatch
|
|
// pointers), so the net ref count is unchanged. For strings,
|
|
// there is still only one pointer to the string.
|
|
//
|
|
// NOTE: the next interation of the loop will do the VariantInit.
|
|
//
|
|
VariantClear(pVarOut);
|
|
*pVarOut = varResolved;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CIISDsCrMap::NonDelegatingQueryInterface(
|
|
REFIID iid,
|
|
LPVOID FAR* ppv
|
|
)
|
|
{
|
|
ASSERT(ppv);
|
|
|
|
if (IsEqualIID(iid, IID_IISDsCrMap)) {
|
|
|
|
*ppv = (IADsUser FAR *) this;
|
|
|
|
} else if (IsEqualIID(iid, IID_IADsExtension)) {
|
|
|
|
*ppv = (IADsExtension FAR *) this;
|
|
|
|
} else if (IsEqualIID(iid, IID_IUnknown)) {
|
|
|
|
//
|
|
// probably not needed since our 3rd party extension does not stand
|
|
// alone and provider does not ask for this, but to be safe
|
|
//
|
|
*ppv = (INonDelegatingUnknown FAR *) this;
|
|
|
|
} else {
|
|
|
|
*ppv = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
//
|
|
// Delegating AddRef to aggregator for IADsExtesnion and IISDsCrMap.
|
|
// AddRef on itself for IPrivateUnknown. (both tested.)
|
|
//
|
|
|
|
((IUnknown *) (*ppv)) -> AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// IADsExtension::Operate()
|
|
//
|
|
|
|
STDMETHODIMP
|
|
CIISDsCrMap::Operate(
|
|
THIS_ DWORD dwCode,
|
|
VARIANT varUserName,
|
|
VARIANT varPassword,
|
|
VARIANT varFlags
|
|
)
|
|
{
|
|
RRETURN(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CIISDsCrMap::ADSIInitializeDispatchManager(
|
|
long dwExtensionId
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (_fDispInitialized) {
|
|
|
|
RRETURN(E_FAIL);
|
|
}
|
|
|
|
hr = _pDispMgr->InitializeDispMgr(dwExtensionId);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
_fDispInitialized = TRUE;
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CIISDsCrMap::ADSIInitializeObject(
|
|
THIS_ BSTR lpszUserName,
|
|
BSTR lpszPassword,
|
|
long lnReserved
|
|
)
|
|
{
|
|
CCredentials NewCredentials(lpszUserName, lpszPassword, lnReserved);
|
|
|
|
m_Credentials = NewCredentials;
|
|
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CIISDsCrMap::ADSIReleaseObject()
|
|
{
|
|
delete this;
|
|
RRETURN(S_OK);
|
|
}
|
|
|