Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

550 lines
15 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
bitssrvcfgimp.h
Abstract:
Implementation header to define server configuration information.
--*/
HRESULT PropertyIDManager::LoadPropertyInfo( const WCHAR * MachineName )
{
bool ComLoaded;
HRESULT Hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
if ( RPC_E_CHANGED_MODE == Hr )
ComLoaded = false;
else if ( FAILED(Hr) )
return Hr;
else
ComLoaded = true;
BSTR MetaIDBSTR = NULL;
BSTR UserTypeBSTR = NULL;
WCHAR *PathBuffer = NULL;
SIZE_T PathBufferSize = 0;
MetaIDBSTR = SysAllocString( L"MetaId" );
UserTypeBSTR = SysAllocString( L"UserType" );
if ( !MetaIDBSTR || !UserTypeBSTR)
{
Hr = E_OUTOFMEMORY;
goto exit;
}
PathBuffer = (WCHAR*)HeapAlloc( GetProcessHeap(), 0, 1024 );
if ( !PathBuffer )
{
Hr = E_OUTOFMEMORY;
goto exit;
}
PathBufferSize = 1024;
for ( SIZE_T i = 0; i < g_NumberOfProperties; i++ )
{
WCHAR SchemaPrefix[] = L"IIS://";
WCHAR SchemaPath[] = L"/Schema/";
SIZE_T SchemaPrefixSize = ( sizeof( SchemaPrefix ) / sizeof( WCHAR ) ) - 1;
SIZE_T SchemaPathSize = ( sizeof( SchemaPath ) / sizeof( WCHAR ) ) - 1;
SIZE_T MachineNameSize = wcslen( MachineName );
SIZE_T PropertyNameSize = wcslen( g_Properties[i].PropertyName );
SIZE_T PathSize = SchemaPrefixSize + SchemaPathSize +
MachineNameSize + PropertyNameSize + 1;
if ( PathBufferSize < ( PathSize * sizeof( WCHAR ) ) )
{
WCHAR *NewBuffer =
(WCHAR*)HeapReAlloc(
GetProcessHeap(),
0,
PathBuffer,
PathSize * sizeof( WCHAR ) );
if ( !NewBuffer )
{
Hr = E_OUTOFMEMORY;
goto exit;
}
PathBuffer = NewBuffer;
PathBufferSize = PathSize * sizeof( WCHAR );
}
// build schema path
WCHAR *ObjectPath = PathBuffer;
{
WCHAR *TempPointer = ObjectPath;
memcpy( TempPointer, SchemaPrefix, SchemaPrefixSize * sizeof( WCHAR ) );
TempPointer += SchemaPrefixSize;
memcpy( TempPointer, MachineName, MachineNameSize * sizeof( WCHAR ) );
TempPointer += MachineNameSize;
memcpy( TempPointer, SchemaPath, SchemaPathSize * sizeof( WCHAR ) );
TempPointer += SchemaPathSize;
memcpy( TempPointer, g_Properties[i].PropertyName, ( PropertyNameSize + 1 ) * sizeof( WCHAR ) );
}
// Open the object
IADs *MbObject = NULL;
Hr = ADsGetObject(
ObjectPath,
__uuidof( *MbObject ),
reinterpret_cast<void**>( &MbObject ) );
if ( FAILED( Hr ) )
{
#if defined( ALLOW_OVERWRITES )
// workaround for IIS issue. IIS isn't handling schema extension property. Dream up a ID.
if ( E_ADS_UNKNOWN_OBJECT == Hr &&
MD_BITS_ALLOW_OVERWRITES == i )
{
m_PropertyIDs[i] = m_PropertyIDs[ i - 1] + 1;
m_PropertyUserTypes[i] = m_PropertyUserTypes[ i - 1 ];
continue;
}
else
#endif
goto exit;
}
VARIANT var;
VariantInit( &var );
Hr = MbObject->Get( MetaIDBSTR, &var );
if ( FAILED(Hr ) )
{
MbObject->Release();
goto exit;
}
Hr = VariantChangeType( &var, &var, 0, VT_UI4 );
if ( FAILED(Hr ) )
{
MbObject->Release();
VariantClear( &var );
goto exit;
}
m_PropertyIDs[i] = var.ulVal;
VariantClear( &var );
Hr = MbObject->Get( UserTypeBSTR, &var );
if ( FAILED( Hr ) )
{
MbObject->Release();
goto exit;
}
Hr = VariantChangeType( &var, &var, 0, VT_UI4 );
if ( FAILED( Hr ) )
{
MbObject->Release();
VariantClear( &var );
goto exit;
}
m_PropertyUserTypes[i] = var.ulVal;
VariantClear( &var );
MbObject->Release();
}
Hr = S_OK;
exit:
SysFreeString( MetaIDBSTR );
SysFreeString( UserTypeBSTR );
if ( ComLoaded )
CoUninitialize();
if ( PathBuffer )
{
HeapFree( GetProcessHeap(), 0, PathBuffer );
PathBuffer = 0;
PathBufferSize = 0;
}
return Hr;
}
// ================================================================================================
// Auxiliary functions that access the IIS Metabase
// ================================================================================================
LPWSTR
CSimplePropertyReader::ConvertObjectPathToADSI(
LPCWSTR szObjectPath )
{
WCHAR *szReturnPath = NULL;
SIZE_T ReturnPathSize = 0;
if ( _wcsnicmp( L"IIS://", szObjectPath, wcslen( L"IIS://") ) == 0 )
{
// already have an adsi path
ReturnPathSize = wcslen( szObjectPath ) + 1;
szReturnPath = new WCHAR[ ReturnPathSize ];
THROW_OUTOFMEMORY_IFNULL( szReturnPath );
memcpy( szReturnPath, szObjectPath, ReturnPathSize * sizeof( WCHAR ) );
}
else if ( _wcsnicmp( L"/LM/", szObjectPath, wcslen( L"/LM/" ) ) == 0 )
{
//metabase path to local machine
ReturnPathSize = wcslen( szObjectPath ) + wcslen( L"IIS://LocalHost/" ) + 1;
szReturnPath = new WCHAR[ ReturnPathSize ];
THROW_OUTOFMEMORY_IFNULL( szReturnPath );
StringCchCopyW( szReturnPath, ReturnPathSize, L"IIS://LocalHost/" );
StringCchCatW( szReturnPath, ReturnPathSize, szObjectPath + wcslen( L"/LM/" ) );
}
else if ( _wcsnicmp( L"LM/", szObjectPath, wcslen( L"LM/" ) ) == 0 )
{
//metabase path to local machine
ReturnPathSize = wcslen( szObjectPath ) + wcslen( L"IIS://LocalHost/" ) + 1;
szReturnPath = new WCHAR[ ReturnPathSize ];
THROW_OUTOFMEMORY_IFNULL( szReturnPath );
StringCchCopyW( szReturnPath, ReturnPathSize, L"IIS://LocalHost/" );
StringCchCatW( szReturnPath, ReturnPathSize, szObjectPath + wcslen( L"LM/" ) );
}
else
{
//metabase path to another server
ReturnPathSize = wcslen( szObjectPath ) + wcslen( L"IIS://" ) + 1;
szReturnPath = new WCHAR[ ReturnPathSize ];
THROW_OUTOFMEMORY_IFNULL( szReturnPath );
if ( '/' == szObjectPath[0] )
StringCchCopyW( szReturnPath, ReturnPathSize, L"IIS:/" );
else
StringCchCopyW( szReturnPath, ReturnPathSize, L"IIS://" );
StringCchCatW( szReturnPath, ReturnPathSize, (WCHAR*)szObjectPath );
}
// check for a trailing \ character
SIZE_T StringLength = wcslen( szReturnPath );
if ( StringLength >= 1 )
{
if ( L'\\' == szReturnPath[ StringLength - 1 ] ||
L'/' == szReturnPath[ StringLength - 1 ] )
{
szReturnPath[ StringLength - 1 ] = L'\0';
}
}
return szReturnPath;
}
BSTR CSimplePropertyReader::GetADsStringProperty( IADs *MetaObj, BSTR bstrPropName)
{
BSTR bstrRetval;
VARIANT vt;
THROW_COMERROR( MetaObj->Get( bstrPropName, &vt ) );
THROW_COMERROR( VariantChangeType( &vt, &vt, 0, VT_BSTR ) );
bstrRetval = vt.bstrVal;
vt.bstrVal = NULL;
VariantClear( &vt );
return bstrRetval;
}
LPWSTR CSimplePropertyReader::GetAdmObjStringProperty(
SmartIMSAdminBasePointer IISAdminBase,
METADATA_HANDLE MdVDirKey,
DWORD dwMDIdentifier )
{
METADATA_RECORD MdRecord;
DWORD dwBytesRequired = 0;
WCHAR *szBuffer = NULL;
try
{
memset( &MdRecord, 0, sizeof( MdRecord ) );
MdRecord.dwMDIdentifier = dwMDIdentifier;
MdRecord.dwMDAttributes = METADATA_INHERIT;
MdRecord.dwMDUserType = IIS_MD_UT_FILE;
MdRecord.dwMDDataType = STRING_METADATA;
MdRecord.dwMDDataLen = 0;
MdRecord.pbMDData = NULL;
HRESULT hr =
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&dwBytesRequired );
if (hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ))
throw ComError( hr );
szBuffer = reinterpret_cast<WCHAR *>(new BYTE[ dwBytesRequired ]);
THROW_OUTOFMEMORY_IFNULL(szBuffer);
memset( szBuffer, 0, dwBytesRequired );
MdRecord.dwMDDataLen = dwBytesRequired;
MdRecord.pbMDData = (PBYTE)szBuffer;
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&dwBytesRequired ) );
}
catch( ComError Error )
{
// just forward the error
throw;
}
return szBuffer;
}
CAccessRemoteVDir::CAccessRemoteVDir() :
m_MetaObj(NULL),
m_fIsImpersonated(FALSE),
m_hUserToken(INVALID_HANDLE_VALUE),
m_szUNCPath(NULL),
m_szUNCUsername(NULL),
m_szUNCPassword(NULL)
{
}
CAccessRemoteVDir::~CAccessRemoteVDir()
{
//
// Free the user token obtained when/if LogonUser() was called
//
if (m_hUserToken != INVALID_HANDLE_VALUE)
{
CloseHandle( m_hUserToken );
m_hUserToken = INVALID_HANDLE_VALUE;
}
//
// If CAccessRemoteVDir::RevertFromUNCAccount() wasn't called before
// the destructor was called, then make sure we revert the impersonation.
// Is advised the the code that is using this class explicity call
// RevertFromUNCAccount(), however. This test is a safe guard in case
// the call is not made.
//
if (m_fIsImpersonated)
{
RevertToSelf();
}
//
// Free variables used when using the IIS AdmObj to access the meta store.
// All the m_szUNC* variables assume memory was allocated by calling
// CSimplePropertyReader::GetAdmObjStringProperty(), which allocated a buffer
// by calling "new BYTE[ ...]"
//
if (m_szUNCPath)
{
delete [] reinterpret_cast<BYTE*>(m_szUNCPath);
m_szUNCPath = NULL;
}
if (m_szUNCUsername)
{
delete [] reinterpret_cast<BYTE*>(m_szUNCUsername);
m_szUNCUsername = NULL;
}
if (m_szUNCPassword)
{
delete [] reinterpret_cast<BYTE*>(m_szUNCPassword);
m_szUNCPassword = NULL;
}
}
void
CAccessRemoteVDir::RevertFromUNCAccount()
{
// revert to previous security setting
if (m_fIsImpersonated)
{
if (!RevertToSelf())
{
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
m_fIsImpersonated = FALSE;
}
if (m_hUserToken != INVALID_HANDLE_VALUE)
{
// revert to previous security setting
CloseHandle( m_hUserToken );
m_hUserToken = INVALID_HANDLE_VALUE;
}
}
inline BOOL
CAccessRemoteVDir::IsUNCPath(LPCWSTR szPath)
{
if ( szPath && szPath[0] == L'\\' && szPath[1] == L'\\' )
{
return TRUE;
}
return FALSE;
}
void
CAccessRemoteVDir::LoginToUNC(
SmartIMSAdminBasePointer IISAdminBase,
METADATA_HANDLE MdVDirKey )
{
try
{
m_szUNCPath = CSimplePropertyReader::GetAdmObjStringProperty(IISAdminBase, MdVDirKey, MD_VR_PATH);
//
// Don't logon if the path isn't a UNC path
//
if (!IsUNCPath(m_szUNCPath))
{
// this class destructor will free m_szUNCPath;
return;
}
m_szUNCUsername = CSimplePropertyReader::GetAdmObjStringProperty(IISAdminBase, MdVDirKey, MD_VR_USERNAME);
m_szUNCPassword = CSimplePropertyReader::GetAdmObjStringProperty(IISAdminBase, MdVDirKey, MD_VR_PASSWORD);
ImpersonateUNCUser(m_szUNCPath, m_szUNCUsername, m_szUNCPassword, &m_hUserToken);
m_fIsImpersonated = TRUE;
}
catch( ComError Error )
{
// just forward the error
throw;
}
}
void
CAccessRemoteVDir::ImpersonateUNCUser(IN LPCWSTR szUNCPath, IN LPCWSTR szUNCUsername, IN LPCWSTR szUNCPassword, OUT HANDLE *hUserToken)
{
*hUserToken = INVALID_HANDLE_VALUE;
// make sure we are not getting unexpected data
if (!szUNCUsername || !szUNCPassword || szUNCUsername[0] == L'\0')
{
throw ComError( HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) );
}
// crack the user name into a user and domain
WCHAR *szUserName = (WCHAR*)szUNCUsername;
WCHAR *szDomainName = NULL;
WCHAR *p = szUserName;
while(*p != L'\0')
{
if(*p == L'\\')
{
*p = L'\0';
p++;
//
// first part is domain
// second is user.
//
szDomainName = szUserName;
szUserName = p;
break;
}
p++;
}
if ( !LogonUserW(
szUserName,
szDomainName,
(WCHAR*)szUNCPassword,
LOGON32_LOGON_BATCH,
LOGON32_PROVIDER_DEFAULT,
hUserToken ) )
{
if ( GetLastError() == ERROR_LOGON_TYPE_NOT_GRANTED )
{
if ( !LogonUserW(
szUserName,
szDomainName,
(WCHAR*)szUNCPassword,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
hUserToken ) )
{
// LogonUser() may touch the handle
// make sure we don't think we have a valid handle
*hUserToken = INVALID_HANDLE_VALUE;
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
}
else
{
*hUserToken = INVALID_HANDLE_VALUE;
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
}
if ( !ImpersonateLoggedOnUser( *hUserToken ) )
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}