|
|
/************************************************************************
Copyright (c) 2002 Microsoft Corporation
Module Name :
config.cpp
Abstract :
Configuration APIs
Author :
Revision History :
***********************************************************************/
#include "precomp.h"
#pragma warning( disable : 4355 )
WCHAR * ConvertObjectPathToADSI( const WCHAR *ObjectPath ) {
WCHAR * ReturnPath = NULL; SIZE_T ReturnPathSize = 0;
if ( _wcsnicmp( L"IIS://", (WCHAR*)ObjectPath, wcslen( L"IIS://") ) == 0 ) { // already have an adsi path
ReturnPathSize = wcslen( ObjectPath ) + 1; ReturnPath = new WCHAR[ ReturnPathSize ];
if ( !ReturnPath ) throw ComError( E_OUTOFMEMORY );
memcpy( ReturnPath, ObjectPath, ReturnPathSize * sizeof( WCHAR ) ); } else if ( _wcsnicmp( L"/LM/", (WCHAR*)ObjectPath, wcslen( L"/LM/" ) ) == 0 ) { //metabase path to local machine
ReturnPathSize = wcslen( (WCHAR*)ObjectPath ) + wcslen( L"IIS://LocalHost/" ) + 1; ReturnPath = new WCHAR[ ReturnPathSize ]; if ( !ReturnPath ) throw ComError( E_OUTOFMEMORY );
StringCchCopyW( ReturnPath, ReturnPathSize, L"IIS://LocalHost/" ); StringCchCatW( ReturnPath, ReturnPathSize, ObjectPath + wcslen( L"/LM/" ) ); } else if ( _wcsnicmp( L"LM/", (WCHAR*)ObjectPath, wcslen( L"LM/" ) ) == 0 ) { //metabase path to local machine
ReturnPathSize = wcslen( (WCHAR*)ObjectPath ) + wcslen( L"IIS://LocalHost/" ) + 1; ReturnPath = new WCHAR[ ReturnPathSize ]; if ( !ReturnPath ) throw ComError( E_OUTOFMEMORY );
StringCchCopyW( ReturnPath, ReturnPathSize, L"IIS://LocalHost/" ); StringCchCatW( ReturnPath, ReturnPathSize, ObjectPath + wcslen( L"LM/" ) ); } else { //metabase path to another server
ReturnPathSize = wcslen( (WCHAR*)ObjectPath ) + wcslen( L"IIS://" ) + 1; ReturnPath = new WCHAR[ ReturnPathSize ];
if ( !ReturnPath ) throw ComError( E_OUTOFMEMORY );
if ( '/' == *(WCHAR*)ObjectPath ) StringCchCopyW( ReturnPath, ReturnPathSize, L"IIS:/" ); else StringCchCopyW( ReturnPath, ReturnPathSize, L"IIS://" );
StringCchCatW( ReturnPath, ReturnPathSize, (WCHAR*)ObjectPath );
}
return ReturnPath; }
HRESULT GetTypeInfo( const GUID & guid, ITypeInfo **TypeInfo ) {
DWORD Result; HRESULT hr; WCHAR DllName[ MAX_PATH ];
Result = GetModuleFileName( g_hinst, DllName, MAX_PATH - 1 );
if ( !Result ) return HRESULT_FROM_WIN32( GetLastError() );
ITypeLib *TypeLib;
hr = LoadTypeLibEx( DllName, REGKIND_NONE, &TypeLib );
if ( FAILED( hr ) ) return hr;
hr = TypeLib->GetTypeInfoOfGuid( guid, TypeInfo );
TypeLib->Release();
return hr; }
void FreeReturnedWorkItems( ULONG NamesReturned, LPWSTR **ItemNamesPtr ) {
LPWSTR *ItemNames = *ItemNamesPtr;
if ( ItemNames ) {
for( ULONG i = 0; i < NamesReturned; i++ ) { CoTaskMemFree( ItemNames[i] ); }
CoTaskMemFree( ItemNames );
*ItemNamesPtr = NULL;
}
}
HRESULT FindWorkItemForVDIR( ITaskScheduler *TaskScheduler, LPCWSTR Key, ITask **ReturnedTask, LPWSTR *ReturnedTaskName ) {
HRESULT Hr; SIZE_T KeyLength = sizeof(WCHAR) * ( wcslen( Key ) + 1 ); WORD DataLength; if ( ReturnedTask ) *ReturnedTask = NULL;
if ( ReturnedTaskName ) *ReturnedTaskName = NULL;
ITask *Task = NULL; IEnumWorkItems *EnumWorkItems = NULL; LPWSTR *ItemNames = NULL; BYTE *ItemData = NULL; ULONG NamesReturned = 0;
try { THROW_COMERROR( TaskScheduler->Enum( &EnumWorkItems ) ); while( 1 ) {
THROW_COMERROR( EnumWorkItems->Next( 255, &ItemNames, &NamesReturned ) );
if ( !NamesReturned ) throw ComError( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) );
for ( ULONG i = 0; i < NamesReturned; i++ ) {
THROW_COMERROR( TaskScheduler->Activate( ItemNames[i], __uuidof( *Task ), (IUnknown**)&Task ) ); THROW_COMERROR( Task->GetWorkItemData( &DataLength, &ItemData ) );
if ( KeyLength == DataLength && ( wcscmp( Key, (WCHAR*)ItemData ) == 0 ) ) {
// Found the item, cleanup and return
if ( ReturnedTask ) *ReturnedTask = Task; else Task->Release();
if ( ReturnedTaskName ) { *ReturnedTaskName = ItemNames[i]; ItemNames[i] = NULL; }
FreeReturnedWorkItems( NamesReturned, &ItemNames );
EnumWorkItems->Release(); CoTaskMemFree( ItemData ); return S_OK; }
Task->Release(); Task = NULL;
CoTaskMemFree( ItemData ); ItemData = NULL;
}
FreeReturnedWorkItems( NamesReturned, &ItemNames ); NamesReturned = 0;
}
} catch( ComError Error ) { if ( EnumWorkItems ) EnumWorkItems->Release();
if ( Task ) Task->Release();
FreeReturnedWorkItems( NamesReturned, &ItemNames ); CoTaskMemFree( ItemData );
return Error.m_Hr; }
}
HRESULT CreateWorkItemForVDIR( ITaskScheduler *TaskScheduler, LPCWSTR Path, LPCWSTR Key ) { WORD KeySize = sizeof(WCHAR) * ( wcslen( Key ) + 1 );
WCHAR ItemNameFormat[ MAX_PATH ]; WCHAR ItemName[ MAX_PATH * 4 ]; WCHAR Parameters[ MAX_PATH * 4];
LoadString( g_hinst, IDS_WORK_ITEM_NAME, ItemNameFormat, MAX_PATH - 1 );
// Use the last part of the path for the description
const WCHAR *ShortPath = Path + wcslen( Path );
while( *ShortPath != L'/' && *ShortPath != L'\\' && ShortPath != Path ) ShortPath--;
if ( *ShortPath == L'/' || *ShortPath == L'\\' ) ShortPath++;
DWORD Result; void* InsertArray[2] = { (void*)ShortPath, (void*)Key }; Result = FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, (LPCVOID)ItemNameFormat, 0, 0, ItemName, MAX_PATH * 4, (va_list*)InsertArray );
if ( !Result ) return HRESULT_FROM_WIN32( GetLastError() );
StringCbPrintfW( Parameters, sizeof( Parameters ), L"bitsmgr.dll,Cleanup_RunDLL %s \"%s\" %s", Path, ItemName, Key );
WORD TriggerNumber; ITask *Task = NULL; ITaskTrigger *TaskTrigger = NULL; IPersistFile *PersistFile = NULL;
try { HRESULT Hr;
Hr = FindWorkItemForVDIR( TaskScheduler, Key, &Task, NULL );
if ( SUCCEEDED( Hr ) ) { // The work item already exists
Task->Release(); return S_OK; }
if ( FAILED(Hr) && HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) != Hr ) THROW_COMERROR( Hr );
THROW_COMERROR( TaskScheduler->NewWorkItem( ItemName, CLSID_CTask, __uuidof( *Task ), (IUnknown**)&Task ) );
// Set basic task data
THROW_COMERROR( Task->SetApplicationName( L"%SystemRoot%\\system32\\rundll32.exe" ) ); THROW_COMERROR( Task->SetMaxRunTime( INFINITE ) ); THROW_COMERROR( Task->SetParameters( Parameters ) ); THROW_COMERROR( Task->SetPriority( IDLE_PRIORITY_CLASS ) ); THROW_COMERROR( Task->SetAccountInformation( L"", NULL ) ); //Run as localsystem
THROW_COMERROR( Task->SetFlags( TASK_FLAG_RUN_ONLY_IF_LOGGED_ON | TASK_FLAG_HIDDEN ) ); THROW_COMERROR( Task->SetWorkItemData( KeySize, (BYTE*)Key ) );
// set trigger information. Set start time to now, with a default
// interval of once a day.
THROW_COMERROR( Task->CreateTrigger( &TriggerNumber, &TaskTrigger ) );
SYSTEMTIME LocalTime; GetLocalTime( &LocalTime ); TASK_TRIGGER Trigger; memset( &Trigger, 0, sizeof( Trigger ) ); Trigger.cbTriggerSize = sizeof(Trigger); Trigger.wBeginYear = LocalTime.wYear; Trigger.wBeginMonth = LocalTime.wMonth; Trigger.wBeginDay = LocalTime.wDay; Trigger.wStartHour = LocalTime.wHour; Trigger.wStartMinute = LocalTime.wMinute; Trigger.TriggerType = TASK_TIME_TRIGGER_DAILY; Trigger.MinutesDuration = 24 * 60; // 24 hours per day
Trigger.MinutesInterval = 12 * 60; // twice per day
Trigger.Type.Daily.DaysInterval = 1; THROW_COMERROR( TaskTrigger->SetTrigger( &Trigger ) );
// Commit the changes to disk.
THROW_COMERROR( Task->QueryInterface( __uuidof( IPersistFile ), (void**)&PersistFile ) ); THROW_COMERROR( PersistFile->Save( NULL, TRUE ) );
PersistFile->Release(); TaskTrigger->Release(); Task->Release();
return S_OK; } catch( ComError Error ) { if ( TaskTrigger ) TaskTrigger->Release();
if ( Task ) Task->Release();
if ( PersistFile ) PersistFile->Release();
TaskScheduler->Delete( ItemName );
return Error.m_Hr; } }
HRESULT DeleteWorkItemForVDIR( ITaskScheduler *TaskScheduler, LPWSTR Key ) { HRESULT Hr; LPWSTR TaskName = NULL;
Hr = FindWorkItemForVDIR( TaskScheduler, Key, NULL, &TaskName );
if ( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) == Hr ) return S_OK;
if ( FAILED( Hr ) ) return Hr;
Hr = TaskScheduler->Delete( TaskName );
CoTaskMemFree( TaskName ); return Hr;
}
HRESULT ConnectToTaskScheduler( LPWSTR ComputerName, ITaskScheduler ** TaskScheduler ) {
HRESULT Hr;
Hr = CoCreateInstance( CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, __uuidof( **TaskScheduler ), (void **) TaskScheduler );
if ( FAILED( Hr ) ) return Hr;
Hr = (*TaskScheduler)->SetTargetComputer( ComputerName );
if ( FAILED( Hr ) ) { (*TaskScheduler)->Release(); (*TaskScheduler) = NULL; return Hr; }
return S_OK;
}
HRESULT IsBITSEnabledOnVDir( PropertyIDManager *PropertyManager, IMSAdminBase *IISAdminBase, LPWSTR VirtualDirectory, BOOL *IsEnabled ) {
HRESULT Hr; DWORD BufferRequired;
*IsEnabled = false;
DWORD IsEnabledVal; METADATA_RECORD MdRecord; memset( &MdRecord, 0, sizeof( MdRecord ) ); MdRecord.dwMDDataType = DWORD_METADATA; MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED ); MdRecord.dwMDDataLen = sizeof(IsEnabled); MdRecord.pbMDData = (PBYTE)&IsEnabledVal;
Hr = IISAdminBase->GetData( METADATA_MASTER_ROOT_HANDLE, VirtualDirectory, &MdRecord, &BufferRequired );
if ( MD_ERROR_DATA_NOT_FOUND == Hr || HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr ) return S_OK;
if ( FAILED( Hr ) ) return Hr; *IsEnabled = IsEnabledVal ? true : false; return S_OK; }
HRESULT EnableBITSForVDIR( PropertyIDManager *PropertyManager, IMSAdminBase *IISAdminBase, LPCWSTR Path ) {
HRESULT Hr; METADATA_HANDLE MdVDirKey = NULL; LPWSTR NewScriptMapBuffer = NULL; ITaskScheduler* TaskScheduler = NULL;
try {
Hr = DisableBITSForVDIR( PropertyManager, IISAdminBase, Path, true );
if ( FAILED( Hr ) ) throw ComError( Hr );
// build the string to add to the scriptmap
WCHAR SystemDir[ MAX_PATH + 1 ];
if (!GetSystemDirectoryW( SystemDir, MAX_PATH ) ) throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
WCHAR ScriptMapString[ MAX_PATH * 2 + 1 ];
StringCbPrintfW( ScriptMapString, sizeof( ScriptMapString ), L"*,%s\\bitssrv.dll,1," BITS_COMMAND_VERBW, SystemDir );
int RetChars = wcslen( ScriptMapString ); ScriptMapString[ RetChars ] = L'\0'; ScriptMapString[ RetChars + 1] = L'\0';
RetChars += 2; // ScriptMapScript is now double NULL terminated
Hr = IISAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE, Path, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 30000, &MdVDirKey );
if (FAILED(Hr)) throw ComError(Hr);
DWORD IsEnabled;
DWORD BufferRequired; METADATA_RECORD MdRecord;
DWORD AccessFlags; MdRecord.dwMDIdentifier = MD_ACCESS_PERM; MdRecord.dwMDAttributes = METADATA_INHERIT; MdRecord.dwMDUserType = IIS_MD_UT_FILE; MdRecord.dwMDDataType = DWORD_METADATA; MdRecord.dwMDDataLen = sizeof( AccessFlags ); MdRecord.pbMDData = (unsigned char*)&AccessFlags; MdRecord.dwMDDataTag = 0;
Hr = IISAdminBase->GetData( MdVDirKey, NULL, &MdRecord, &BufferRequired );
if ( MD_ERROR_DATA_NOT_FOUND == Hr || HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr ) { AccessFlags = 0; } else if ( FAILED( Hr ) ) { throw ComError( Hr ); }
if ( AccessFlags & ( MD_ACCESS_SCRIPT | MD_ACCESS_EXECUTE ) ) { AccessFlags &= ~( MD_ACCESS_SCRIPT | MD_ACCESS_EXECUTE ); MdRecord.dwMDAttributes &= ~METADATA_ISINHERITED;
Hr = IISAdminBase->SetData( MdVDirKey, NULL, &MdRecord );
if ( FAILED( Hr ) ) throw ComError( Hr );
}
MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED ); MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES; MdRecord.dwMDUserType = ALL_METADATA; MdRecord.dwMDDataType = DWORD_METADATA; MdRecord.dwMDDataLen = sizeof(IsEnabled); MdRecord.pbMDData = (PBYTE)&IsEnabled; MdRecord.dwMDDataTag = 0;
Hr = IISAdminBase->GetData( MdVDirKey, NULL, &MdRecord, &BufferRequired ); if ( FAILED( Hr ) ) { if ( !( MD_ERROR_DATA_NOT_FOUND == Hr || HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr ) ) { IISAdminBase->CloseKey( MdVDirKey ); return S_OK; } } else if ( IsEnabled ) { IISAdminBase->CloseKey( MdVDirKey ); return S_OK; }
//
// retrieve the current scriptmap adding room to the allocated memory
//
memset( &MdRecord, 0, sizeof( MdRecord ) );
MdRecord.dwMDDataType = MULTISZ_METADATA; MdRecord.dwMDAttributes = METADATA_INHERIT; MdRecord.dwMDUserType = IIS_MD_UT_FILE; MdRecord.dwMDIdentifier = MD_SCRIPT_MAPS; MdRecord.dwMDDataLen = 0; MdRecord.pbMDData = (PBYTE)NULL;
Hr = IISAdminBase->GetData( MdVDirKey, NULL, &MdRecord, &BufferRequired );
if ( MD_ERROR_DATA_NOT_FOUND == Hr || HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr ) { // The Current key doesn't exist.
MdRecord.pbMDData = (PBYTE)ScriptMapString; MdRecord.dwMDDataLen = RetChars * sizeof(WCHAR); } else if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) == Hr ) {
NewScriptMapBuffer = new WCHAR[ ( BufferRequired / sizeof(WCHAR) ) + RetChars ]; MdRecord.pbMDData = (PBYTE)NewScriptMapBuffer; MdRecord.dwMDDataLen = BufferRequired + ( RetChars * sizeof(WCHAR) );
Hr = IISAdminBase->GetData( MdVDirKey, NULL, &MdRecord, &BufferRequired );
if ( FAILED(Hr) ) throw ComError( Hr );
// append script entry at the end
for( WCHAR *p = NewScriptMapBuffer; *p != 0; p += ( wcslen( p ) + 1 ) ); memcpy( p, ScriptMapString, RetChars * sizeof(WCHAR) );
MdRecord.pbMDData = (PBYTE)NewScriptMapBuffer; MdRecord.dwMDDataLen = (DWORD)( ( (char*)p - (char*)NewScriptMapBuffer ) + ( RetChars * sizeof(WCHAR) ) ); } else throw ComError( Hr );
// Write out the new values starting with ScriptMap
Hr = IISAdminBase->SetData( MdVDirKey, NULL, &MdRecord );
if ( FAILED( Hr ) ) throw ComError( Hr ); // Set the enabled property
DWORD EnableData = 1; memset( &MdRecord, 0, sizeof( MdRecord ) ); MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES; MdRecord.dwMDDataType = DWORD_METADATA; MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_UPLOAD_ENABLED ); MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED ); MdRecord.dwMDDataLen = sizeof(EnableData); MdRecord.pbMDData = (PBYTE)&EnableData;
Hr = IISAdminBase->SetData( MdVDirKey, NULL, &MdRecord );
if ( FAILED( Hr ) ) throw ComError( Hr );
delete[] NewScriptMapBuffer;
// Create the task scheduler cleanup work item
WCHAR GuidString[ 255 ];
// first try looking up the guid
MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES; MdRecord.dwMDDataType = STRING_METADATA; MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY ); MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY ); MdRecord.dwMDDataLen = sizeof( GuidString ); MdRecord.pbMDData = (PBYTE)GuidString; MdRecord.dwMDDataTag = 0; Hr = IISAdminBase->GetData( MdVDirKey, NULL, &MdRecord, &BufferRequired );
if ( MD_ERROR_DATA_NOT_FOUND == Hr || HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr ) {
// create a new guid and save it away
GUID guid; THROW_COMERROR( CoCreateGuid( &guid ) ); StringFromGUID2( guid, GuidString, 254 ); MdRecord.dwMDDataLen = sizeof(WCHAR) * ( wcslen(GuidString) + 1 ); MdRecord.pbMDData = (PBYTE)GuidString;
THROW_COMERROR( IISAdminBase->SetData( MdVDirKey, NULL, &MdRecord ) );
}
else if ( FAILED( Hr ) ) throw ComError( Hr );
THROW_COMERROR( ConnectToTaskScheduler( NULL, &TaskScheduler ) ); THROW_COMERROR( CreateWorkItemForVDIR( TaskScheduler, Path, GuidString ) );
TaskScheduler->Release(); IISAdminBase->CloseKey( MdVDirKey ); return S_OK; } catch( ComError Exception ) { if ( TaskScheduler ) TaskScheduler->Release();
DisableBITSForVDIR( PropertyManager, IISAdminBase, Path, false );
delete[] NewScriptMapBuffer; if ( MdVDirKey ) IISAdminBase->CloseKey( MdVDirKey ); return Exception.m_Hr; }
}
HRESULT DisableBITSForVDIR( PropertyIDManager *PropertyManager, IMSAdminBase *IISAdminBase, LPCWSTR Path, bool DisableForEnable ) {
HRESULT Hr; METADATA_HANDLE MdVDirKey = NULL; LPWSTR OriginalScriptMap = NULL; LPWSTR NewScriptMap = NULL; ITaskScheduler* TaskScheduler = NULL;
try {
if ( !DisableForEnable ) CleanupForRemoval( Path );
// build the string to add to the scriptmap
WCHAR SystemDir[ MAX_PATH + 1 ];
if (!GetSystemDirectoryW( SystemDir, MAX_PATH ) ) throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
WCHAR ScriptMapString[ MAX_PATH * 2 + 1 ];
StringCchPrintfW( ScriptMapString, MAX_PATH * 2 + 1, L"*,%s\\bitssrv.dll,1,BITS_COMMAND", SystemDir );
int RetChars = wcslen( ScriptMapString ); ScriptMapString[ RetChars ] = L'\0'; ScriptMapString[ RetChars + 1] = L'\0';
// ScriptMapScript is now double NULL terminated
WCHAR ScriptMapString2[ MAX_PATH * 2 + 1];
StringCbPrintfW( ScriptMapString2, sizeof( ScriptMapString2 ), L"*,%\\bitsserver.dll,1,BITS_COMMAND", SystemDir );
RetChars = wcslen( ScriptMapString2 ); ScriptMapString2[ RetChars ] = L'\0'; ScriptMapString2[ RetChars + 1 ] = L'\0';
// ScriptMapScript2 is not double NULL terminated
WCHAR ScriptMapString3[ MAX_PATH * 2 + 1 ];
StringCbPrintfW( ScriptMapString3, sizeof( ScriptMapString3 ), L"*,%s\\bitssrv.dll,1," BITS_COMMAND_VERBW, SystemDir ); RetChars = wcslen( ScriptMapString3 ); ScriptMapString3[ RetChars ] = L'\0'; ScriptMapString3[ RetChars + 1] = L'\0';
// ScriptMapScript3 is now double NULL terminated
THROW_COMERROR( IISAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE, Path, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 30000, &MdVDirKey ) );
//
// retrieve the current scriptmap adding room to the allocated memory
//
DWORD BufferRequired;
METADATA_RECORD MdRecord; memset( &MdRecord, 0, sizeof( MdRecord ) );
MdRecord.dwMDDataType = MULTISZ_METADATA; MdRecord.dwMDAttributes = METADATA_INHERIT; MdRecord.dwMDUserType = IIS_MD_UT_FILE; MdRecord.dwMDIdentifier = MD_SCRIPT_MAPS; MdRecord.dwMDDataLen = 0; MdRecord.pbMDData = (PBYTE)NULL;
Hr = IISAdminBase->GetData( MdVDirKey, NULL, &MdRecord, &BufferRequired );
if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) != Hr ) throw ComError( Hr );
OriginalScriptMap = new WCHAR[ BufferRequired / 2 + 2 ]; NewScriptMap = new WCHAR[ BufferRequired / 2 + 2 ];
OriginalScriptMap[0] = OriginalScriptMap[1] = L'\0';
MdRecord.dwMDDataLen = BufferRequired; MdRecord.pbMDData = (PBYTE)OriginalScriptMap;
Hr = IISAdminBase->GetData( MdVDirKey, NULL, &MdRecord, &BufferRequired );
if ( FAILED(Hr) ) throw ComError( Hr );
// Copy the orignal Scriptmap to the new scriptmap
// removing bits goo in the process.
LPWSTR CurrentOriginalItem = OriginalScriptMap; LPWSTR CurrentNewItem = NewScriptMap;
for( ;L'\0' != *CurrentOriginalItem; CurrentOriginalItem += ( wcslen( CurrentOriginalItem ) + 1 ) ) {
if ( _wcsicmp( CurrentOriginalItem, ScriptMapString ) == 0 ) continue; //remove this item
if ( _wcsicmp( CurrentOriginalItem, ScriptMapString2 ) == 0 ) continue;
if ( _wcsicmp( CurrentOriginalItem, ScriptMapString3 ) == 0 ) continue;
SIZE_T CurrentOriginalItemSize = wcslen( CurrentOriginalItem ) + 1; memcpy( CurrentNewItem, CurrentOriginalItem, CurrentOriginalItemSize * sizeof( WCHAR ) ); CurrentNewItem += CurrentOriginalItemSize;
}
// Add the extra 0
*CurrentNewItem++ = L'\0';
MdRecord.dwMDDataLen = (DWORD)( (char*)CurrentNewItem - (char*)NewScriptMap ); MdRecord.pbMDData = (PBYTE)NewScriptMap;
// Set the is enabled property first
DWORD EnableData = 0; METADATA_RECORD MdEnabledRecord; memset( &MdEnabledRecord, 0, sizeof( MdEnabledRecord ) );
MdEnabledRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES; MdEnabledRecord.dwMDDataType = DWORD_METADATA; MdEnabledRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_UPLOAD_ENABLED ); MdEnabledRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED ); MdEnabledRecord.dwMDDataLen = sizeof(EnableData); MdEnabledRecord.pbMDData = (PBYTE)&EnableData;
Hr = IISAdminBase->SetData( MdVDirKey, NULL, &MdEnabledRecord );
if ( FAILED( Hr ) ) throw ComError( Hr );
// set the new scriptmap
Hr = IISAdminBase->SetData( MdVDirKey, NULL, &MdRecord );
if ( FAILED( Hr ) ) throw ComError( Hr );
WCHAR GuidString[ 255 ]; memset( &MdRecord, 0, sizeof( MdRecord ) );
MdRecord.dwMDDataType = STRING_METADATA; MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES; MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY ); MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY ); MdRecord.dwMDDataLen = sizeof( GuidString ); MdRecord.pbMDData = (PBYTE)GuidString;
Hr = IISAdminBase->GetData( MdVDirKey, NULL, &MdRecord, &BufferRequired );
if ( FAILED( Hr ) && Hr != MD_ERROR_DATA_NOT_FOUND ) throw ComError( Hr );
if ( SUCCEEDED( Hr ) && !DisableForEnable ) { THROW_COMERROR( ConnectToTaskScheduler( NULL, &TaskScheduler ) ); THROW_COMERROR( DeleteWorkItemForVDIR( TaskScheduler, GuidString ) ); TaskScheduler->Release();
THROW_COMERROR( IISAdminBase->DeleteData( MdVDirKey, NULL, PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY ), ALL_METADATA ) );
}
delete[] OriginalScriptMap; delete[] NewScriptMap;
IISAdminBase->CloseKey( MdVDirKey ); MdVDirKey = NULL; return S_OK;
} catch( ComError Exception ) { if ( TaskScheduler ) TaskScheduler->Release();
delete[] OriginalScriptMap; delete[] NewScriptMap; if ( MdVDirKey ) IISAdminBase->CloseKey( MdVDirKey ); return Exception.m_Hr; }
}
HRESULT FindWorkItemForVDIR( PropertyIDManager *PropertyManager, IMSAdminBase *AdminBase, LPCWSTR Path, LPWSTR *ReturnedTaskName ) {
if ( ReturnedTaskName ) *ReturnedTaskName = NULL;
WCHAR GuidString[ 255 ]; DWORD BufferRequired; METADATA_RECORD MdRecord; HRESULT Hr;
MdRecord.dwMDDataType = STRING_METADATA; MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES; MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY ); MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY ); MdRecord.dwMDDataLen = sizeof( GuidString ); MdRecord.pbMDData = (PBYTE)GuidString; MdRecord.dwMDDataTag = 0;
Hr = AdminBase->GetData( METADATA_MASTER_ROOT_HANDLE, Path, &MdRecord, &BufferRequired );
if ( MD_ERROR_DATA_NOT_FOUND == Hr ) return S_FALSE;
ITaskScheduler* TaskScheduler = NULL; Hr = ConnectToTaskScheduler( NULL, &TaskScheduler );
if ( FAILED( Hr ) ) return Hr;
Hr = FindWorkItemForVDIR( TaskScheduler, GuidString, NULL, ReturnedTaskName );
// simply return NULL if the task item isn't found.
if ( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) == Hr ) Hr = S_FALSE;
TaskScheduler->Release();
return Hr; }
CBITSExtensionSetupFactory::CBITSExtensionSetupFactory() : m_cref(1), m_TypeInfo(NULL) { OBJECT_CREATED } CBITSExtensionSetupFactory::~CBITSExtensionSetupFactory() { if ( m_TypeInfo ) m_TypeInfo->Release();
OBJECT_DESTROYED }
STDMETHODIMP CBITSExtensionSetupFactory::QueryInterface(REFIID riid, LPVOID *ppv) { if (!ppv) return E_FAIL; *ppv = NULL; if (IsEqualIID(riid, IID_IUnknown)) *ppv = static_cast<IUnknown *>(this); else if (IsEqualIID(riid, __uuidof(IBITSExtensionSetupFactory))) *ppv = static_cast<IBITSExtensionSetupFactory *>(this); if (*ppv) { reinterpret_cast<IUnknown *>(*ppv)->AddRef(); return S_OK; } return E_NOINTERFACE; }
STDMETHODIMP_(ULONG) CBITSExtensionSetupFactory::AddRef() { return InterlockedIncrement((LONG *)&m_cref); }
STDMETHODIMP_(ULONG) CBITSExtensionSetupFactory::Release() { if (InterlockedDecrement((LONG *)&m_cref) == 0) { // we need to decrement our object count in the DLL
delete this; return 0; } return m_cref; }
HRESULT CBITSExtensionSetupFactory::LoadTypeInfo() {
if ( m_TypeInfo ) return S_OK;
return ::GetTypeInfo( __uuidof( IBITSExtensionSetupFactory ), &m_TypeInfo );
}
STDMETHODIMP CBITSExtensionSetupFactory::GetIDsOfNames( REFIID, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID, DISPID FAR* rgDispId ) {
HRESULT Hr; Hr = LoadTypeInfo();
if ( FAILED( Hr ) ) return Hr;
return DispGetIDsOfNames( m_TypeInfo, rgszNames, cNames, rgDispId);
}
STDMETHODIMP CBITSExtensionSetupFactory::GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo ) {
*ppTInfo = NULL;
if(iTInfo != 0) return ResultFromScode(DISP_E_BADINDEX);
HRESULT Hr; Hr = LoadTypeInfo();
if ( FAILED( Hr ) ) return Hr;
m_TypeInfo->AddRef(); *ppTInfo = m_TypeInfo;
return NOERROR; }
STDMETHODIMP CBITSExtensionSetupFactory::GetTypeInfoCount( unsigned int FAR* pctinfo ) { *pctinfo = 1; return NOERROR; }
STDMETHODIMP CBITSExtensionSetupFactory::Invoke( DISPID dispIdMember, REFIID, LCID, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr ) {
HRESULT Hr; Hr = LoadTypeInfo();
if ( FAILED( Hr ) ) return Hr;
return DispInvoke( this, m_TypeInfo, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
}
STDMETHODIMP CBITSExtensionSetupFactory::GetObject( BSTR Path, IBITSExtensionSetup **ppExtensionSetup ) {
WCHAR *ObjectPath = NULL; IUnknown *Object = NULL;
try { if ( !Path || !ppExtensionSetup ) throw ComError( E_INVALIDARG );
*ppExtensionSetup = NULL; ObjectPath = ConvertObjectPathToADSI( (WCHAR*)Path );
THROW_COMERROR( ADsGetObject( BSTR( ObjectPath ), __uuidof( IUnknown ), (void**)&Object ) );
delete ObjectPath; ObjectPath = NULL;
CBITSExtensionSetup *SetupObj = new CBITSExtensionSetup( NULL, Object );
if ( !SetupObj ) throw ComError( E_OUTOFMEMORY );
Object = NULL; *ppExtensionSetup = static_cast<IBITSExtensionSetup*>( SetupObj ); return S_OK; } catch( ComError Error ) { delete ObjectPath; if ( Object ) Object->Release(); return Error.m_Hr; }
}
STDMETHODIMP CNonDelegatingIUnknown::QueryInterface(REFIID riid, LPVOID *ppv) { if (!ppv) return E_FAIL; *ppv = NULL;
if ( riid == __uuidof(IUnknown) ) *ppv = static_cast<IUnknown *>(this); else if ( riid == __uuidof(IDispatch) ) *ppv = static_cast<IDispatch*>(m_DelegatingIUnknown); else if ( riid == __uuidof(IBITSExtensionSetup) ) *ppv = static_cast<IBITSExtensionSetup *>(m_DelegatingIUnknown); else if ( riid == __uuidof(IADsExtension) ) *ppv = static_cast<IADsExtension *>(m_DelegatingIUnknown);
if (*ppv) { reinterpret_cast<IUnknown *>(*ppv)->AddRef(); return S_OK; } return E_NOINTERFACE; }
STDMETHODIMP_(ULONG) CNonDelegatingIUnknown::AddRef() { return InterlockedIncrement((LONG *)&m_cref); }
STDMETHODIMP_(ULONG) CNonDelegatingIUnknown::Release() { if (InterlockedDecrement((LONG *)&m_cref) == 0) { // we need to decrement our object count in the DLL
delete m_DelegatingIUnknown; return 0; } return m_cref; }
CNonDelegatingIUnknown::CNonDelegatingIUnknown( CBITSExtensionSetup * DelegatingIUnknown ) : m_DelegatingIUnknown( DelegatingIUnknown ), m_cref(1) { }
CBITSExtensionSetup::CBITSExtensionSetup( IUnknown *Outer, IUnknown *Object ) : m_pOuter( Outer ), m_pObject( Object ), m_OuterDispatch( NULL ), m_TypeInfo( NULL ), m_ADSIPath( NULL ), m_Path( NULL ), m_PropertyMan( NULL ), m_DelegationIUnknown( this ), m_RemoteInterface( NULL ), m_InitComplete( false ), m_Lock( 0 ) {
if ( m_pOuter ) {
HRESULT Hr = m_pOuter->QueryInterface( __uuidof( IDispatch ), (void**)&m_OuterDispatch );
if ( FAILED( Hr ) ) m_OuterDispatch = NULL;
}
OBJECT_CREATED }
CBITSExtensionSetup::~CBITSExtensionSetup() { if ( m_pObject ) { m_pObject->Release(); m_pObject = NULL; }
if ( m_OuterDispatch ) m_OuterDispatch->Release();
if ( m_TypeInfo ) m_TypeInfo->Release();
delete[] m_Path; // Noop on NULL
m_Path = NULL;
if ( m_RemoteInterface ) m_RemoteInterface->Release();
delete m_PropertyMan;
SysFreeString( m_ADSIPath );
OBJECT_DESTROYED }
STDMETHODIMP CBITSExtensionSetup::QueryInterface(REFIID riid, LPVOID *ppv) { if ( m_pOuter ) return m_pOuter->QueryInterface( riid, ppv ); else return m_DelegationIUnknown.QueryInterface( riid, ppv ); }
STDMETHODIMP_(ULONG) CBITSExtensionSetup::AddRef() { if ( m_pOuter ) return m_pOuter->AddRef(); else return m_DelegationIUnknown.AddRef(); }
STDMETHODIMP_(ULONG) CBITSExtensionSetup::Release() { if ( m_pOuter ) return m_pOuter->AddRef(); else return m_DelegationIUnknown.AddRef(); }
HRESULT CBITSExtensionSetup::LoadTypeInfo() {
if ( m_TypeInfo ) return S_OK;
// Lock object
while( InterlockedExchange( &m_Lock, 1 ) ) Sleep( 0 );
HRESULT Hr = ::GetTypeInfo( __uuidof( IBITSExtensionSetup ), &m_TypeInfo );
// Unlock the object
InterlockedExchange( &m_Lock, 0 ); return Hr;
}
STDMETHODIMP CBITSExtensionSetup::Operate( ULONG dwCode, VARIANT varData1, VARIANT varData2, VARIANT varData3) {
return E_NOTIMPL;
}
STDMETHODIMP CBITSExtensionSetup::PrivateGetIDsOfNames( REFIID, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID, DISPID FAR* rgDispId ) {
HRESULT Hr; Hr = LoadTypeInfo();
if ( FAILED( Hr ) ) return Hr;
return DispGetIDsOfNames( m_TypeInfo, rgszNames, cNames, rgDispId);
}
STDMETHODIMP CBITSExtensionSetup::PrivateGetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo ) {
*ppTInfo = NULL;
if(iTInfo != 0) return ResultFromScode(DISP_E_BADINDEX);
HRESULT Hr; Hr = LoadTypeInfo();
if ( FAILED( Hr ) ) return Hr;
m_TypeInfo->AddRef(); *ppTInfo = m_TypeInfo;
return NOERROR; }
STDMETHODIMP CBITSExtensionSetup::PrivateGetTypeInfoCount( unsigned int FAR* pctinfo ) { *pctinfo = 1; return NOERROR; }
STDMETHODIMP CBITSExtensionSetup::PrivateInvoke( DISPID dispIdMember, REFIID, LCID, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr ) {
HRESULT Hr; Hr = LoadTypeInfo();
if ( FAILED( Hr ) ) return Hr;
return DispInvoke( static_cast<IBITSExtensionSetup*>(this), m_TypeInfo, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
}
STDMETHODIMP CBITSExtensionSetup::GetIDsOfNames( REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId ) {
if ( m_OuterDispatch ) return m_OuterDispatch->GetIDsOfNames( riid, rgszNames, cNames, lcid, rgDispId ); return PrivateGetIDsOfNames( riid, rgszNames, cNames, lcid, rgDispId );
}
STDMETHODIMP CBITSExtensionSetup::GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo ) {
if ( m_OuterDispatch ) return m_OuterDispatch->GetTypeInfo( iTInfo, lcid, ppTInfo );
return PrivateGetTypeInfo( iTInfo, lcid, ppTInfo );
}
STDMETHODIMP CBITSExtensionSetup::GetTypeInfoCount( unsigned int FAR* pctinfo ) {
if ( m_OuterDispatch ) return m_OuterDispatch->GetTypeInfoCount( pctinfo );
return PrivateGetTypeInfoCount( pctinfo );
}
STDMETHODIMP CBITSExtensionSetup::Invoke( DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr ) {
if ( m_OuterDispatch ) return m_OuterDispatch->Invoke( dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
return PrivateInvoke( dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
}
HRESULT CBITSExtensionSetup::ConnectToRemoteExtension() { WCHAR *HostName = NULL; WCHAR *NewPath = NULL; BSTR NewPathBSTR = NULL; IBITSExtensionSetupFactory* Factory = NULL;
try {
// Extract out the host part of the path
const SIZE_T PrefixSize = sizeof(L"IIS://")/sizeof(WCHAR) - 1; if ( _wcsnicmp( (WCHAR*)m_ADSIPath, L"IIS://", PrefixSize ) != 0 ) throw ComError( E_INVALIDARG );
WCHAR *HostNameStart = ((WCHAR*)m_ADSIPath) + PrefixSize;
WCHAR *p = HostNameStart;
while( L'/' != *p ) { if ( L'\0' == *p ) throw ComError( E_INVALIDARG );
p++; }
SIZE_T HostNameSize = (char*)p - (char*)HostNameStart + sizeof(L'\0'); HostName = new WCHAR[ HostNameSize / sizeof(WCHAR) ]; if ( !HostName ) throw ComError( E_OUTOFMEMORY );
memcpy( HostName, HostNameStart, HostNameSize - sizeof(WCHAR) ); HostName[ ( HostNameSize - sizeof(WCHAR) ) / sizeof(WCHAR) ] = L'\0';
if ( L'\0' == *++p ) throw ComError( E_INVALIDARG );
SIZE_T NewPathSize = wcslen( L"IIS://LocalHost/" ) + wcslen( p ) + 1; NewPath = new WCHAR[ NewPathSize ];
if ( !NewPath ) throw ComError( E_OUTOFMEMORY );
StringCchCopyW( NewPath, NewPathSize, L"IIS://LocalHost/" ); StringCchCatW( NewPath, NewPathSize, p );
NewPathBSTR = SysAllocString( NewPath );
if ( !NewPathBSTR ) throw ComError( E_OUTOFMEMORY );
COSERVERINFO coinfo; coinfo.dwReserved1 = 0; coinfo.dwReserved2 = 0; coinfo.pAuthInfo = NULL; coinfo.pwszName = HostName;
GUID guid = __uuidof( IBITSExtensionSetupFactory ); MULTI_QI mqi; mqi.hr = S_OK; mqi.pIID = &guid; mqi.pItf = NULL;
THROW_COMERROR( CoCreateInstanceEx( __uuidof(BITSExtensionSetupFactory), NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, &coinfo, 1, &mqi ) ); THROW_COMERROR( mqi.hr );
Factory = (IBITSExtensionSetupFactory*)mqi.pItf; mqi.pItf = NULL;
THROW_COMERROR( Factory->GetObject( NewPathBSTR, &m_RemoteInterface ) );
Factory->Release();
SysFreeString( NewPathBSTR ); delete[] NewPath; delete[] HostName;
return S_OK; } catch( ComError Error ) { SysFreeString( NewPathBSTR ); delete[] HostName; delete[] NewPath;
if ( Factory ) Factory->Release();
return Error.m_Hr; }
}
HRESULT CBITSExtensionSetup::LoadPath() {
HRESULT Hr;
if ( m_InitComplete ) return S_OK;
// Lock object
while( InterlockedExchange( &m_Lock, 1 ) ) Sleep( 0 );
if ( !m_PropertyMan ) {
m_PropertyMan = new PropertyIDManager();
if ( !m_PropertyMan ) { Hr = E_OUTOFMEMORY; goto error; }
Hr = m_PropertyMan->LoadPropertyInfo();
if ( FAILED(Hr) ) { delete m_PropertyMan; m_PropertyMan = NULL; goto error; } }
if ( !m_ADSIPath ) { IADs *ObjectADS = NULL;
if ( m_pObject ) Hr = m_pObject->QueryInterface( __uuidof(*ObjectADS), (void**) &ObjectADS ); else Hr = m_pOuter->QueryInterface( __uuidof(*ObjectADS), (void**) &ObjectADS );
if ( FAILED( Hr ) ) goto error;
Hr = ObjectADS->get_ADsPath( &m_ADSIPath );
ObjectADS->Release(); ObjectADS = NULL;
if ( FAILED( Hr ) ) goto error;
}
if ( !m_Path && !m_RemoteInterface ) {
if ( _wcsnicmp( (WCHAR*)m_ADSIPath, L"IIS://LocalHost/", wcslen( L"IIS://LocalHost/" ) ) == 0 ) { SIZE_T PathSize = wcslen( (WCHAR*)m_ADSIPath ) + 1; m_Path = new WCHAR[ PathSize ]; if ( !m_Path ) { Hr = E_OUTOFMEMORY; goto error; }
StringCchCopyW( m_Path, PathSize, L"/LM/" ); StringCchCatW( m_Path, PathSize, reinterpret_cast<WCHAR*>( m_ADSIPath ) + wcslen( L"IIS://LocalHost/" ) ); } else { Hr = ConnectToRemoteExtension( );
if ( FAILED( Hr ) ) goto error;
}
}
m_InitComplete = true; // unlock
InterlockedExchange( &m_Lock, 0 ); return S_OK;
error: // unlock
InterlockedExchange( &m_Lock, 0 ); return Hr;
}
STDMETHODIMP CBITSExtensionSetup::EnableBITSUploads() {
HRESULT Hr = LoadPath();
if ( FAILED(Hr) ) return Hr;
if ( m_RemoteInterface ) return m_RemoteInterface->EnableBITSUploads();
IMSAdminBase *AdminBase = NULL;
Hr = CoCreateInstance( GETAdminBaseCLSID(TRUE), NULL, CLSCTX_SERVER, __uuidof( IMSAdminBase ), (LPVOID*)&AdminBase );
if ( FAILED( Hr ) ) return Hr;
Hr = EnableBITSForVDIR( m_PropertyMan, AdminBase, m_Path );
AdminBase->Release(); return Hr; }
STDMETHODIMP CBITSExtensionSetup::DisableBITSUploads() {
HRESULT Hr = LoadPath();
if ( FAILED(Hr) ) return Hr;
if ( m_RemoteInterface ) return m_RemoteInterface->DisableBITSUploads();
IMSAdminBase *AdminBase = NULL;
Hr = CoCreateInstance( GETAdminBaseCLSID(TRUE), NULL, CLSCTX_SERVER, __uuidof( IMSAdminBase ), (LPVOID*)&AdminBase );
if ( FAILED( Hr ) ) return Hr;
Hr = DisableBITSForVDIR( m_PropertyMan, AdminBase, m_Path, false );
AdminBase->Release(); return Hr;
}
STDMETHODIMP CBITSExtensionSetup::GetCleanupTaskName( BSTR *pTaskName ) {
*pTaskName = NULL;
HRESULT Hr = LoadPath();
if ( FAILED(Hr) ) return Hr;
if ( m_RemoteInterface ) return m_RemoteInterface->GetCleanupTaskName( pTaskName );
IMSAdminBase *AdminBase = NULL;
Hr = CoCreateInstance( GETAdminBaseCLSID(TRUE), NULL, CLSCTX_SERVER, __uuidof( IMSAdminBase ), (LPVOID*)&AdminBase );
if ( FAILED( Hr ) ) return Hr;
LPWSTR TaskName = NULL; Hr = FindWorkItemForVDIR( m_PropertyMan, AdminBase, m_Path, &TaskName );
if ( SUCCEEDED( Hr ) && TaskName ) {
*pTaskName = SysAllocString( TaskName ); if ( !*pTaskName ) Hr = E_OUTOFMEMORY;
CoTaskMemFree( TaskName ); TaskName = NULL;
}
AdminBase->Release(); return Hr;
}
STDMETHODIMP CBITSExtensionSetup::GetCleanupTask( [in] REFIID riid, [out,retval] IUnknown **ppUnk ) {
HRESULT Hr = S_OK; ITaskScheduler *TaskScheduler = NULL; BSTR ItemName = NULL; WCHAR *HostName = NULL; if ( ppUnk ) *ppUnk = NULL;
try {
THROW_COMERROR( LoadPath() );
//
// Build the taskscheduler form of the host name
//
const SIZE_T PrefixSize = sizeof(L"IIS://")/sizeof(WCHAR) - 1; if ( _wcsnicmp( (WCHAR*)m_ADSIPath, L"IIS://", PrefixSize ) != 0 ) throw ComError( E_INVALIDARG );
WCHAR *HostNameStart = ((WCHAR*)m_ADSIPath) + PrefixSize; WCHAR *p = HostNameStart;
while( L'/' != *p ) { if ( L'\0' == *p ) throw ComError( E_INVALIDARG );
p++; }
SIZE_T HostNameSize = (char*)p - (char*)HostNameStart + sizeof(L'\0'); HostName = new WCHAR[ ( HostNameSize / sizeof(WCHAR) ) + 2 ]; if ( !HostName ) throw ComError( E_OUTOFMEMORY );
HostName[0] = HostName[1] = L'\\'; memcpy( HostName + 2, HostNameStart, HostNameSize - sizeof(WCHAR) ); HostName[ ( ( HostNameSize - sizeof(WCHAR) ) / sizeof(WCHAR) ) + 2 ] = L'\0';
if ( _wcsicmp( HostName, L"\\\\LocalHost" ) == 0 ) { delete[] HostName; HostName = NULL; }
THROW_COMERROR( ConnectToTaskScheduler( HostName, &TaskScheduler ) ); THROW_COMERROR( GetCleanupTaskName( &ItemName ) );
if ( ItemName ) THROW_COMERROR( TaskScheduler->Activate( (LPCWSTR)ItemName, riid, ppUnk ) ); else Hr = S_FALSE;
} catch( ComError Error ) { Hr = Error.m_Hr; }
if ( TaskScheduler ) TaskScheduler->Release();
SysFreeString( ItemName ); delete[] HostName;
return Hr;
}
#include "bitssrvcfgimp.h"
|