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.
 
 
 
 
 
 

2827 lines
77 KiB

/************************************************************************
Copyright (c) 2002 Microsoft Corporation
Module Name :
config.cpp
Abstract :
Configuration APIs
Author :
Revision History :
***********************************************************************/
#include "precomp.h"
#include <sddl.h>
#pragma warning( disable : 4355 )
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;
}
}
void
FindWorkItemForVDIR(
SmartITaskSchedulerPointer TaskScheduler,
LPCWSTR Key,
SmartITaskPointer* ReturnedTask,
LPWSTR* ReturnedTaskName )
{
HRESULT Hr;
SIZE_T KeyLength = sizeof(WCHAR) * ( wcslen( Key ) + 1 );
WORD DataLength;
if ( ReturnedTask )
(*ReturnedTask).Clear();
if ( ReturnedTaskName )
*ReturnedTaskName = NULL;
SmartITaskPointer Task;
SmartIEnumWorkItemsPointer EnumWorkItems;
LPWSTR *ItemNames = NULL;
BYTE *ItemData = NULL;
ULONG NamesReturned = 0;
try
{
THROW_COMERROR( TaskScheduler->Enum( EnumWorkItems.GetRecvPointer() ) );
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], Task.GetUUID(),
(IUnknown**)Task.GetRecvPointer() ) );
THROW_COMERROR( Task->GetWorkItemData( &DataLength, &ItemData ) );
if ( KeyLength == DataLength &&
( wcscmp( Key, (WCHAR*)ItemData ) == 0 ) )
{
// Found the item, cleanup and return
if ( ReturnedTask )
*ReturnedTask = Task;
if ( ReturnedTaskName )
{
*ReturnedTaskName = ItemNames[i];
ItemNames[i] = NULL;
}
FreeReturnedWorkItems(
NamesReturned,
&ItemNames );
CoTaskMemFree( ItemData );
return;
}
CoTaskMemFree( ItemData );
ItemData = NULL;
}
FreeReturnedWorkItems(
NamesReturned,
&ItemNames );
NamesReturned = 0;
}
}
catch( ComError Error )
{
FreeReturnedWorkItems(
NamesReturned,
&ItemNames );
CoTaskMemFree( ItemData );
throw;
}
}
WCHAR *BasePathOf( IN WCHAR *pPath )
{
WCHAR *pBasePath;
if (!pPath)
{
return NULL;
}
if ( (pBasePath=wcsrchr(pPath,L'/'))
|| (pBasePath=wcsrchr(pPath,L'\\')) )
{
pBasePath++;
}
else
{
pBasePath = pPath;
}
return pBasePath;
}
void CreateWorkItemForVDIR(
IN SmartITaskSchedulerPointer TaskScheduler,
IN LPWSTR Path,
IN LPWSTR Key )
{
WORD KeySize = sizeof(WCHAR) * ( wcslen( Key ) + 1 );
WCHAR ItemName[MAX_PATH];
WCHAR ItemCommentFormat[MAX_PATH];
WCHAR ItemComment[2*MAX_PATH];
WCHAR Parameters[4*MAX_PATH];
//
// Use the last part of the path for the item name and description comment.
//
const WCHAR *pBasePath = BasePathOf(Path);
if (!pBasePath || 0==wcslen(pBasePath))
{
throw ComError( HRESULT_FROM_WIN32(ERROR_INVALID_NAME) );
}
//
// Construct the description/comment string.
//
DWORD Result;
void* InsertArray[2] = { (void*)pBasePath, (void*)Key };
if ( !LoadString(g_hinst, IDS_WORK_ITEM_COMMENT, ItemCommentFormat, MAX_PATH) )
{
throw ComError( HRESULT_FROM_WIN32(GetLastError()) );
}
Result = FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPCVOID)ItemCommentFormat,
0,
0,
ItemComment,
ARRAY_ELEMENTS(ItemComment),
(va_list*)InsertArray );
ItemComment[ ARRAY_ELEMENTS(ItemComment) - 1 ] = L'\0';
if ( !Result )
{
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
//
// Construct the task scheduler item name. Since StringCchPrintfW() is always
// defined to return a (possibly trunctated) buffer, we can ignore the error
// return in this case.
//
StringCchPrintfW(
ItemName,
ARRAY_ELEMENTS(ItemName),
L"BITS_%s_%s", pBasePath, Key );
//
// Construct the runstring for the task.
//
StringCchPrintfW(
Parameters,
ARRAY_ELEMENTS(Parameters),
L"bitsmgr.dll,Cleanup_RunDLL %s \"%s\" %s", Path, ItemName, Key );
WORD TriggerNumber;
SmartITaskPointer Task;
SmartITaskTriggerPointer TaskTrigger;
SmartIPersistFilePointer PersistFile;
try
{
try
{
FindWorkItemForVDIR( TaskScheduler, Key, &Task, NULL );
return; // work item already found
}
catch( ComError Error )
{
if ( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) != Error.m_Hr )
throw;
}
// error not found
THROW_COMERROR( TaskScheduler->NewWorkItem( ItemName, CLSID_CTask,
Task.GetUUID(), (IUnknown**)Task.GetRecvPointer() ) );
// 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 ) );
Task->SetComment( ItemComment ); // Don't fail if this one fails...
// Set the trigger information. Set start time to now, with a default
// interval of once a day.
THROW_COMERROR( Task->CreateTrigger( &TriggerNumber, TaskTrigger.GetRecvPointer() ) );
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( PersistFile.GetUUID(),
(void**)PersistFile.GetRecvPointer() ) );
THROW_COMERROR( PersistFile->Save( NULL, TRUE ) );
}
catch( ComError Error )
{
TaskScheduler->Delete( ItemName );
throw;
}
}
void
DeleteWorkItemForVDIR(
SmartITaskSchedulerPointer TaskScheduler,
LPWSTR Key )
{
LPWSTR TaskName = NULL;
try
{
FindWorkItemForVDIR( TaskScheduler, Key, NULL, &TaskName );
THROW_COMERROR( TaskScheduler->Delete( TaskName ) );
}
catch( ComError Error )
{
CoTaskMemFree( TaskName );
if ( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) == Error.m_Hr )
return;
throw;
}
}
void
ConnectToTaskScheduler(
LPWSTR ComputerName,
SmartITaskSchedulerPointer * TaskScheduler )
{
THROW_COMERROR(
CoCreateInstance(
CLSID_CTaskScheduler,
NULL,
CLSCTX_INPROC_SERVER,
(*TaskScheduler).GetUUID(),
(void**)(*TaskScheduler).GetRecvPointer() ) );
THROW_COMERROR( (*TaskScheduler)->SetTargetComputer( ComputerName ) );
}
void
IsBITSEnabledOnVDir(
PropertyIDManager *PropertyManager,
IMSAdminBase *IISAdminBase,
LPWSTR VirtualDirectory,
BOOL *IsEnabled )
{
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;
try
{
THROW_COMERROR(
IISAdminBase->GetData(
METADATA_MASTER_ROOT_HANDLE,
VirtualDirectory,
&MdRecord,
&BufferRequired ) );
}
catch( ComError Error )
{
if ( MD_ERROR_DATA_NOT_FOUND == Error.m_Hr ||
HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Error.m_Hr )
return;
throw;
}
*IsEnabled = IsEnabledVal ? true : false;
}
LPWSTR
BITSGetFileOwnerSidString(LPCWSTR szFile)
{
DWORD cbSizeNeeded = 0;
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
PSID pOwnerSid = NULL;
BOOL fOwnerDefaulted = FALSE;
LPWSTR pszSidString = NULL;
try
{
//
// Retrieve the file owner. Call GetFileSecurity twice - first to get
// the buffer size, then the actual information retrieval.
//
if (!GetFileSecurity(szFile, OWNER_SECURITY_INFORMATION, NULL, 0, &cbSizeNeeded))
{
DWORD dwError = GetLastError();
if (dwError != ERROR_INSUFFICIENT_BUFFER)
{
throw ComError( HRESULT_FROM_WIN32( dwError ) );
}
}
else
{
// we don't expect this to ever succeed
throw ComError( E_UNEXPECTED );
}
//
// Allocate the buffer space necessary and retrieve the info.
//
pSecurityDescriptor = reinterpret_cast<SECURITY_DESCRIPTOR *>(new BYTE[cbSizeNeeded]);
THROW_OUTOFMEMORY_IFNULL(pSecurityDescriptor);
if (!GetFileSecurity(szFile, OWNER_SECURITY_INFORMATION, pSecurityDescriptor, cbSizeNeeded, &cbSizeNeeded))
{
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
//
// Retrieve & validate the owner sid.
//
if (!GetSecurityDescriptorOwner(pSecurityDescriptor, &pOwnerSid, &fOwnerDefaulted))
{
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
if (!IsValidSid(pOwnerSid))
{
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
if(!ConvertSidToStringSidW(pOwnerSid, &pszSidString))
{
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
}
catch ( ComError Error )
{
if (pSecurityDescriptor)
{
delete [] reinterpret_cast<BYTE *>(pSecurityDescriptor);
pSecurityDescriptor = NULL;
}
throw;
}
//
// Everthing went fine
//
if (pSecurityDescriptor)
{
delete [] reinterpret_cast<BYTE *>(pSecurityDescriptor);
pSecurityDescriptor = NULL;
}
// caller should free this memory
return pszSidString;
}
LPWSTR
BITSAddAclForDirectoryOwner(LPCWSTR szBaseAcl, LPCWSTR szUserPartialAclPrefix, LPCWSTR szDirectory)
{
LPCWSTR szUserPartialAclSuffix = L")";
LPWSTR szFullAcl = NULL;
DWORD cchFullAcl = 0;
LPWSTR pszUserSID = NULL;
try
{
pszUserSID = BITSGetFileOwnerSidString(szDirectory);
cchFullAcl = wcslen(szBaseAcl) + wcslen(szUserPartialAclPrefix) + wcslen(pszUserSID) + wcslen(szUserPartialAclSuffix) + 1;
// ATT: this buffer is being allocated and it should be freed by the caller
szFullAcl = new WCHAR[ cchFullAcl ];
THROW_OUTOFMEMORY_IFNULL(szFullAcl);
StringCchPrintfW(szFullAcl, cchFullAcl, L"%ws%ws%ws%ws", szBaseAcl, szUserPartialAclPrefix, pszUserSID, szUserPartialAclSuffix);
}
catch( ComError Error )
{
//
// Free the String SID obtained by calling ConvertSidToStringSid()
//
if (pszUserSID)
{
LocalFree(reinterpret_cast<HLOCAL>(pszUserSID));
pszUserSID = NULL;
}
}
//
// Free the String SID obtained by calling ConvertSidToStringSid()
//
if (pszUserSID)
{
LocalFree(reinterpret_cast<HLOCAL>(pszUserSID));
pszUserSID = NULL;
}
// this string should be freed by the caller
return szFullAcl;
}
void
BITSCreateDirectory(
const WCHAR *Path,
const WCHAR *SDString,
BOOL fAllowInheritanceFromParent,
BOOL fAddOwnerExplicitly )
{
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
PACL pDacl = NULL;
BOOL fDaclPresent = TRUE;
BOOL fDaclDefaulted = TRUE;
DWORD dwProtectedFlag = 0;
DWORD dwError = ERROR_SUCCESS;
LPWSTR szExpandedAcl = NULL;
try
{
//
// Note that we are setting the SecurityDescriptor as NULL initially.
// We will set the security separately via SetNamedSecurityInfo(), otherwise
// the inherited ACLs will not be computed.
//
if (!CreateDirectory(Path, NULL))
{
dwError = GetLastError();
// ignore error if directory already exists
if ( ERROR_ALREADY_EXISTS != dwError )
{
throw ComError( HRESULT_FROM_WIN32( dwError ) );
}
}
//
// If we were given a security descriptor string, use it to set the security permissions
//
if ( SDString )
{
if (fAddOwnerExplicitly)
{
//
// Grab the SID for the Owner of the directory we just created, transform it to string
// format and add it to the SDDL string that we were given.
// We do this in order to guarantee to the owner of the directory the right to
// create subdirectories and files. CO permissions will only last during creation time,
// so it doesn't help in our scenario. This behavior was confirmed by the Security team.
//
szExpandedAcl = BITSAddAclForDirectoryOwner(SDString, BITS_EXPLICITOWNER_PARTIAL_ACL, Path);
}
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
(szExpandedAcl? szExpandedAcl : SDString), // security descriptor string
SDDL_REVISION_1, // revision level
&pSecurityDescriptor, // SD
NULL ) ) // SD size
{
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
SECURITY_ATTRIBUTES SecurityAttributes =
{
sizeof( SECURITY_ATTRIBUTES ),
pSecurityDescriptor,
FALSE
};
if (!GetSecurityDescriptorDacl(pSecurityDescriptor, &fDaclPresent, &pDacl, &fDaclDefaulted))
{
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
}
if (!fDaclPresent || !pDacl)
{
throw ComError( HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) );
}
//
// Decide if we are going to interrupt the inheritance from the parent or not.
//
dwProtectedFlag = (fAllowInheritanceFromParent? UNPROTECTED_DACL_SECURITY_INFORMATION : PROTECTED_DACL_SECURITY_INFORMATION);
//
// Set the permissions in the directory
//
dwError = SetNamedSecurityInfoW(
(WCHAR *)Path, // object name
SE_FILE_OBJECT, // object type
DACL_SECURITY_INFORMATION | dwProtectedFlag, // Security info flags
NULL, // psidOwner
NULL, // psidGroup
pDacl, // pDacl
NULL); // pSacl
if (dwError != ERROR_SUCCESS)
{
throw ComError( HRESULT_FROM_WIN32( dwError ) );
}
}
}
catch ( ComError Error )
{
if ( szExpandedAcl)
{
delete [] szExpandedAcl;
szExpandedAcl = NULL;
}
if ( pSecurityDescriptor )
{
LocalFree( pSecurityDescriptor );
}
throw;
}
//
// Success! Cleanup...
//
if ( szExpandedAcl)
{
delete [] szExpandedAcl;
szExpandedAcl = NULL;
}
if ( pSecurityDescriptor )
{
LocalFree( pSecurityDescriptor );
}
}
void
LogDeleteError(
DWORD Message,
StringHandle Name,
HRESULT Hr )
{
HANDLE EventHandle =
RegisterEventSource(
NULL, // server name
EVENT_LOG_SOURCE_NAME // source name
);
if ( EventHandle )
{
const WCHAR *Strings[] = { (const WCHAR*)Name };
ReportEvent(
EventHandle, // handle to event log
EVENTLOG_ERROR_TYPE, // event type
BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
Message, // event identifier
NULL, // user security identifier
1, // number of strings to merge
sizeof( Hr ), // size of binary data
Strings, // array of strings to merge
&Hr // binary data buffer
);
DeregisterEventSource( EventHandle );
}
}
//---------------------------------------------------------------------------
// DeleteDirectoryTree()
//
// Recursive delete of a directory tree.
//
// Note: Do not follow or delete reparse points.
//---------------------------------------------------------------------------
void
DeleteDirectoryTree( IN StringHandle Directory )
{
StringHandle SearchString = Directory + StringHandle(L"\\*");
HANDLE FindHandle = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA FindData;
WIN32_FILE_ATTRIBUTE_DATA FileAttributes;
try
{
if (!GetFileAttributesEx(Directory,
GetFileExInfoStandard,
&FileAttributes))
{
throw ComError(HRESULT_FROM_WIN32(GetLastError()));
}
// If the specified directory is a reparse point then ignore it.
if (FileAttributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
{
return;
}
FindHandle = FindFirstFile( SearchString, &FindData );
if ( INVALID_HANDLE_VALUE == FindHandle )
{
throw ComError(HRESULT_FROM_WIN32(GetLastError()));
}
do
{
// Ignore reparse points.
if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
{
continue;
}
// Ignore this and parent directory references.
if ( ( _wcsicmp( L".", FindData.cFileName ) == 0 )
|| ( _wcsicmp( L"..", FindData.cFileName ) == 0 ) )
{
continue;
}
StringHandle NewItem = Directory
+ StringHandle(L"\\")
+ StringHandle( FindData.cFileName );
if ( FILE_ATTRIBUTE_DIRECTORY & FindData.dwFileAttributes )
{
DeleteDirectoryTree( NewItem );
}
else
{
if ( !DeleteFile( NewItem ) )
{
HRESULT DeleteHr = HRESULT_FROM_WIN32( GetLastError() );
LogDeleteError(
BITSSRV_EVENTLOG_DELETEFILE_ERROR,
NewItem,
DeleteHr );
}
}
} while( FindNextFile( FindHandle, &FindData ) );
FindClose( FindHandle );
FindHandle = INVALID_HANDLE_VALUE;
if ( !RemoveDirectory( Directory ) )
{
HRESULT DeleteHr = HRESULT_FROM_WIN32( GetLastError() );
LogDeleteError(
BITSSRV_EVENTLOG_REMOVEDIRECTORY_ERROR,
Directory,
DeleteHr );
}
}
catch( const ComError & )
{
if ( INVALID_HANDLE_VALUE != FindHandle)
{
FindClose( FindHandle );
}
throw;
}
}
void
CreateBITSCacheDirectory(
PropertyIDManager *PropertyManager,
SmartIMSAdminBasePointer IISAdminBase,
METADATA_HANDLE MdVDirKey,
StringHandle GuidString )
{
DWORD BufferRequired;
WCHAR VDirPath[ MAX_PATH ];
WCHAR VDirSessionDir[ MAX_PATH ];
METADATA_RECORD MdRecord;
MdRecord.dwMDIdentifier = MD_VR_PATH;
MdRecord.dwMDAttributes = METADATA_INHERIT;
MdRecord.dwMDUserType = IIS_MD_UT_FILE;
MdRecord.dwMDDataType = STRING_METADATA;
MdRecord.dwMDDataLen = sizeof( VDirPath );
MdRecord.pbMDData = (unsigned char*)VDirPath;
MdRecord.dwMDDataTag = 0;
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CONNECTION_DIR );
MdRecord.dwMDDataLen = sizeof( VDirSessionDir );
MdRecord.pbMDData = (unsigned char*)VDirSessionDir;
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
StringHandle VDirSessionDirPath = StringHandle( VDirPath ) + StringHandle( L"\\" ) +
StringHandle( VDirSessionDir );
StringHandle CleanupGuids = VDirSessionDirPath + StringHandle( L"\\" ) +
StringHandle( CLEANUP_GUIDS_NAME );
StringHandle CleanupGuidFile = CleanupGuids + StringHandle( L"\\" ) +
GuidString;
StringHandle VDirRequestsPath = VDirSessionDirPath + StringHandle( L"\\" ) +
StringHandle( REQUESTS_DIR_NAMEW );
StringHandle VDirRepliesPath = VDirSessionDirPath + StringHandle( L"\\" ) +
StringHandle( REPLIES_DIR_NAMEW );
//
// Start some filesystem work
//
// *If* our VDir is located in a remote share, use the IIS
// connection account info to connect to the share
//
CAccessRemoteVDir oVDir;
oVDir.LoginToUNC( IISAdminBase, MdVDirKey );
try
{
BITSCreateDirectory(
VDirSessionDirPath,
BITS_SESSIONS_DIR_ACL,
FALSE, // turn on the PROTECTED flag on the ACL, such that inheritance is interupted from the parent
TRUE ); // explicitly add the SID of the creator owner to the ACL. Note that inheritance will be computed
BITSCreateDirectory(
CleanupGuids,
BITS_CLEANUPGUIDS_DIR_ACL,
TRUE, // Let the ACL for this directory inherit from the parent
FALSE );// don't add the SID for the owner. It will be inherited
{
HANDLE GuidFile =
CreateFile(
CleanupGuidFile,
GENERIC_ALL,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL );
if ( INVALID_HANDLE_VALUE == GuidFile )
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
CloseHandle( GuidFile );
}
BITSCreateDirectory(
VDirRequestsPath,
BITS_REQUESTS_DIR_ACL,
TRUE, // Let the ACL for this directory inherit from the parent
FALSE );// don't add the SID for the owner. It will be inherited
BITSCreateDirectory(
VDirRepliesPath,
BITS_REPLIES_DIR_ACL,
TRUE, // Let the ACL for this directory inherit from the parent
FALSE );// don't add the SID for the owner. It will be inherited
}
catch( ComError Error )
{
// don't let this error propagate with the wrong user
oVDir.RevertFromUNCAccount();
throw;
}
//
// Done with the filesystem access
//
oVDir.RevertFromUNCAccount();
StringHandle SessionDirKeyPath = StringHandle( VDirSessionDir );
StringHandle RequestsDirKeyPath = SessionDirKeyPath + StringHandle( L"\\" ) +
StringHandle( REQUESTS_DIR_NAMEW );
StringHandle RepliesDirKeyPath = SessionDirKeyPath + StringHandle( L"\\" ) +
StringHandle( REPLIES_DIR_NAMEW );
{
HRESULT Hr = IISAdminBase->AddKey(
MdVDirKey,
SessionDirKeyPath );
if ( FAILED( Hr ) && ( HRESULT_FROM_WIN32( ERROR_DUP_NAME ) != Hr ) )
throw ComError( Hr );
}
{
HRESULT Hr = IISAdminBase->AddKey(
MdVDirKey,
RepliesDirKeyPath );
if ( FAILED( Hr ) && ( HRESULT_FROM_WIN32( ERROR_DUP_NAME ) != Hr ) )
throw ComError( Hr );
}
DWORD AccessPermission = 0;
MdRecord.dwMDIdentifier = MD_ACCESS_PERM;
MdRecord.dwMDAttributes = METADATA_INHERIT;
MdRecord.dwMDUserType = IIS_MD_UT_FILE;
MdRecord.dwMDDataType = DWORD_METADATA;
MdRecord.dwMDDataLen = sizeof( AccessPermission );
MdRecord.pbMDData = (unsigned char*)&AccessPermission;
MdRecord.dwMDDataTag = 0;
THROW_COMERROR(
IISAdminBase->SetData(
MdVDirKey, //metadata handle..
SessionDirKeyPath, //path of the key relative to hMDHandle.
&MdRecord ) );
AccessPermission = 1; // read only permissions
THROW_COMERROR(
IISAdminBase->SetData(
MdVDirKey, //metadata handle..
RepliesDirKeyPath, //path of the key relative to hMDHandle.
&MdRecord ) );
//
// Set BITS-Sessions to disable browse.
//
DWORD BrowsePermission = 0;
MdRecord.dwMDIdentifier = MD_DIRECTORY_BROWSING;
MdRecord.dwMDAttributes = METADATA_INHERIT;
MdRecord.dwMDUserType = IIS_MD_UT_FILE;
MdRecord.dwMDDataType = DWORD_METADATA;
MdRecord.dwMDDataLen = sizeof( BrowsePermission );
MdRecord.pbMDData = (unsigned char*)&BrowsePermission;
MdRecord.dwMDDataTag = 0;
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
BrowsePermission &= ~MD_DIRBROW_ENABLED;
MdRecord.dwMDAttributes &= ~METADATA_ISINHERITED;
THROW_COMERROR(
IISAdminBase->SetData(
MdVDirKey,
SessionDirKeyPath,
&MdRecord ) );
}
void
DeleteBITSCacheDirectory(
PropertyIDManager *PropertyManager,
SmartIMSAdminBasePointer IISAdminBase,
METADATA_HANDLE MdVDirKey,
const WCHAR *szObjectPath )
{
DWORD BufferRequired;
WCHAR VDirPath[ MAX_PATH ];
WCHAR VDirSessionDir[ MAX_PATH ];
METADATA_RECORD MdRecord;
MdRecord.dwMDIdentifier = MD_VR_PATH;
MdRecord.dwMDAttributes = METADATA_INHERIT;
MdRecord.dwMDUserType = IIS_MD_UT_FILE;
MdRecord.dwMDDataType = STRING_METADATA;
MdRecord.dwMDDataLen = sizeof( VDirPath );
MdRecord.pbMDData = (unsigned char*)VDirPath;
MdRecord.dwMDDataTag = 0;
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CONNECTION_DIR );
MdRecord.dwMDDataLen = sizeof( VDirSessionDir );
MdRecord.pbMDData = (unsigned char*)VDirSessionDir;
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
WCHAR GuidString[ 255 ];
{
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;
HRESULT Hr =
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired );
if ( MD_ERROR_DATA_NOT_FOUND == Hr )
return; // The cache directory was never created.
THROW_COMERROR( Hr );
}
StringHandle VDirSessionDirPath = StringHandle( VDirPath ) + StringHandle( L"\\" ) +
StringHandle( VDirSessionDir );
StringHandle CleanupGuids = VDirSessionDirPath + StringHandle( L"\\" ) +
StringHandle( CLEANUP_GUIDS_NAME );
StringHandle CleanupGuidFile = CleanupGuids + StringHandle( L"\\" ) +
GuidString;
//
// Prepare to do some filesystem work
//
// *If* our VDir is located in a remote share, use the IIS
// connection account info to impersonate that user
CAccessRemoteVDir oVDir;
oVDir.LoginToUNC( IISAdminBase, MdVDirKey );
try
{
DeleteFile( CleanupGuidFile );
BOOL RemovedCleanupDirs = RemoveDirectory( CleanupGuids );
if ( RemovedCleanupDirs ||
ERROR_PATH_NOT_FOUND == GetLastError() ||
ERROR_FILE_NOT_FOUND == GetLastError() )
{
// This is the last "enlistment"
DeleteDirectoryTree( VDirSessionDirPath );
}
}
catch( ComError Error )
{
// don't let this error propagate with the wrong user
oVDir.RevertFromUNCAccount();
throw;
}
//
// Done with the filesystem access
//
oVDir.RevertFromUNCAccount();
IISAdminBase->DeleteKey( MdVDirKey, VDirSessionDir );
}
void
DeleteOldBITSCacheDirectory(
PropertyIDManager *PropertyManager,
SmartIMSAdminBasePointer IISAdminBase,
METADATA_HANDLE MdVDirKey,
const WCHAR *szObjectPath )
{
DWORD BufferRequired;
WCHAR VDirPath[ MAX_PATH ];
WCHAR VDirSessionDir[ MAX_PATH ];
METADATA_RECORD MdRecord;
MdRecord.dwMDIdentifier = MD_VR_PATH;
MdRecord.dwMDAttributes = METADATA_INHERIT;
MdRecord.dwMDUserType = IIS_MD_UT_FILE;
MdRecord.dwMDDataType = STRING_METADATA;
MdRecord.dwMDDataLen = sizeof( VDirPath );
MdRecord.pbMDData = (unsigned char*)VDirPath;
MdRecord.dwMDDataTag = 0;
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CONNECTION_DIR );
MdRecord.dwMDDataLen = sizeof( VDirSessionDir );
MdRecord.pbMDData = (unsigned char*)VDirSessionDir;
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
StringHandle VDirSessionDirPath = StringHandle( VDirPath ) + StringHandle( L"\\" ) +
StringHandle( VDirSessionDir );
StringHandle VDirSessionDirPath2 = StringHandle( VDirPath ) + StringHandle( L"\\" ) +
StringHandle( VDirSessionDir ) + StringHandle(L".bak");
StringHandle DirectoryToDelete;
//
// Prepare to do some filesystem work
//
// *If* our VDir is located in a remote share, use the IIS
// connection account info to impersonate that user
CAccessRemoteVDir oVDir;
oVDir.LoginToUNC( IISAdminBase, MdVDirKey );
try
{
if ( !MoveFileEx(
VDirSessionDirPath,
VDirSessionDirPath2,
0 ) )
{
DWORD dwError = GetLastError();
if ( ERROR_PATH_NOT_FOUND == dwError ||
ERROR_FILE_NOT_FOUND == dwError )
{
oVDir.RevertFromUNCAccount();
return;
}
DirectoryToDelete = VDirSessionDirPath;
}
else
{
DirectoryToDelete = VDirSessionDirPath2;
}
DeleteDirectoryTree( DirectoryToDelete );
}
catch( ComError Error )
{
// don't let this error propagate with the wrong user
oVDir.RevertFromUNCAccount();
throw;
}
//
// Done with the filesystem access
//
oVDir.RevertFromUNCAccount();
}
void
GetVDirPropertyVersion(
PropertyIDManager *PropertyManager,
SmartIMSAdminBasePointer IISAdminBase,
METADATA_HANDLE MdVDirKey,
bool * pIsEnabled,
DWORD * pdwVersion )
{
*pIsEnabled = false;
*pdwVersion = 0;
HRESULT Hr;
DWORD IsEnabled = 0;
METADATA_RECORD MdRecord;
DWORD BufferRequired;
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 ) )
throw ComError( Hr );
}
*pIsEnabled = !!IsEnabled;
MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_METADATA_VERSION );
MdRecord.dwMDDataLen = sizeof(*pdwVersion);
MdRecord.pbMDData = (PBYTE)pdwVersion;
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 ) )
throw ComError( Hr );
}
}
void
SetVDirEnabled(
PropertyIDManager *PropertyManager,
SmartIMSAdminBasePointer IISAdminBase,
METADATA_HANDLE MdVDirKey )
{
METADATA_RECORD MdRecord;
DWORD EnableData = 1;
DWORD MetadataVersion = CURRENT_UPLOAD_METADATA_VERSION;
MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_METADATA_VERSION );
MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_UPLOAD_METADATA_VERSION );
MdRecord.dwMDDataType = DWORD_METADATA;
MdRecord.dwMDDataLen = sizeof(MetadataVersion);
MdRecord.pbMDData = (PBYTE)&MetadataVersion;
MdRecord.dwMDDataTag = 0;
THROW_COMERROR(
IISAdminBase->SetData(
MdVDirKey,
NULL,
&MdRecord ) );
MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_UPLOAD_ENABLED );
MdRecord.dwMDDataLen = sizeof(EnableData);
MdRecord.pbMDData = (PBYTE)&EnableData;
THROW_COMERROR(
IISAdminBase->SetData(
MdVDirKey,
NULL,
&MdRecord ) );
}
void
EnableBITSForVDIR(
PropertyIDManager *PropertyManager,
SmartIMSAdminBasePointer IISAdminBase,
LPWSTR Path )
{
HRESULT Hr;
METADATA_RECORD MdRecord;
METADATA_HANDLE MdVDirKey = NULL;
LPWSTR NewScriptMapBuffer = NULL;
SmartITaskSchedulerPointer TaskScheduler;
DWORD BufferRequired;
bool IsEnabled = 0;
DWORD MetadataVersion = 0;
try
{
THROW_COMERROR(
IISAdminBase->OpenKey(
METADATA_MASTER_ROOT_HANDLE,
Path,
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
METABASE_OPEN_KEY_TIMEOUT,
&MdVDirKey ) );
GetVDirPropertyVersion(
PropertyManager,
IISAdminBase,
MdVDirKey,
&IsEnabled,
&MetadataVersion );
if ( IsEnabled )
{
if ( MetadataVersion >= CURRENT_UPLOAD_METADATA_VERSION )
{
// Nothing to do, just leave.
IISAdminBase->CloseKey( MdVDirKey );
return;
}
IISAdminBase->CloseKey( MdVDirKey );
MdVDirKey = NULL;
DisableBITSForVDIR(
PropertyManager,
IISAdminBase,
Path,
false,
true );
EnableBITSForVDIR(
PropertyManager,
IISAdminBase,
Path );
return;
}
// Generate the new GUID string
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 );
// build the string to add to the scriptmap
WCHAR SystemDir[ MAX_PATH + 1 ];
if (!GetSystemDirectoryW( SystemDir, MAX_PATH ) )
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
SystemDir[ MAX_PATH ] = L'\0';
WCHAR ScriptMapString[ MAX_PATH * 2 + 1 ];
StringCchPrintfW(
ScriptMapString,
ARRAY_ELEMENTS( 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
CreateBITSCacheDirectory(
PropertyManager,
IISAdminBase,
MdVDirKey,
StringHandle( GuidString ) );
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;
try
{
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
}
catch( ComError Error )
{
if ( MD_ERROR_DATA_NOT_FOUND == Error.m_Hr ||
HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Error.m_Hr )
{
AccessFlags = 0;
}
else
throw;
}
if ( AccessFlags & ( MD_ACCESS_SCRIPT | MD_ACCESS_EXECUTE ) )
{
AccessFlags &= ~( MD_ACCESS_SCRIPT | MD_ACCESS_EXECUTE );
MdRecord.dwMDAttributes &= ~METADATA_ISINHERITED;
THROW_COMERROR(
IISAdminBase->SetData(
MdVDirKey,
NULL,
&MdRecord ) );
}
//
// 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;
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 )
{
// 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) );
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
// 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 );
THROW_COMERROR(
IISAdminBase->SetData(
MdVDirKey,
NULL,
&MdRecord ) );
// Create the task scheduler cleanup work item
ConnectToTaskScheduler( NULL, &TaskScheduler );
CreateWorkItemForVDIR( TaskScheduler, Path, GuidString );
delete[] NewScriptMapBuffer;
NewScriptMapBuffer = NULL;
SetVDirEnabled(
PropertyManager,
IISAdminBase,
MdVDirKey );
IISAdminBase->CloseKey( MdVDirKey );
}
catch( ComError Exception )
{
if ( MdVDirKey )
{
delete[] NewScriptMapBuffer;
IISAdminBase->CloseKey( MdVDirKey );
try
{
DisableBITSForVDIR(
PropertyManager,
IISAdminBase,
Path,
true,
false );
}
catch( const ComError & )
{
}
}
throw;
}
}
void
DisableBITSForVDIR(
PropertyIDManager *PropertyManager,
SmartIMSAdminBasePointer IISAdminBase,
LPCWSTR Path,
bool RollbackCleanup,
bool DisableForUpgrade )
{
METADATA_HANDLE MdVDirKey = NULL;
LPWSTR OriginalScriptMap = NULL;
LPWSTR NewScriptMap = NULL;
SmartITaskSchedulerPointer TaskScheduler;
try
{
#if 0
if ( !RollbackCleanup && !DisableForUpgrade )
CleanupForRemoval( Path );
#endif
// 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];
StringCchPrintfW(
ScriptMapString2,
ARRAY_ELEMENTS( 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 ];
StringCchPrintfW(
ScriptMapString3,
ARRAY_ELEMENTS( 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,
METABASE_OPEN_KEY_TIMEOUT,
&MdVDirKey ) );
if ( DisableForUpgrade )
{
DeleteOldBITSCacheDirectory(
PropertyManager,
IISAdminBase,
MdVDirKey,
Path );
}
else
{
DeleteBITSCacheDirectory(
PropertyManager,
IISAdminBase,
MdVDirKey,
Path );
}
//
// 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;
HRESULT 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;
THROW_COMERROR(
IISAdminBase->GetData(
MdVDirKey,
NULL,
&MdRecord,
&BufferRequired ) );
// 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 new scriptmap
THROW_COMERROR(
IISAdminBase->SetData(
MdVDirKey,
NULL,
&MdRecord ) );
// Set the enabled property first
DWORD EnableData = 0;
METADATA_RECORD 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;
MdEnabledRecord.dwMDDataTag = 0;
THROW_COMERROR(
IISAdminBase->SetData(
MdVDirKey,
NULL,
&MdEnabledRecord ) );
if ( !DisableForUpgrade )
{
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 ) )
{
try
{
ConnectToTaskScheduler( NULL, &TaskScheduler );
DeleteWorkItemForVDIR( TaskScheduler, GuidString );
THROW_COMERROR(
IISAdminBase->DeleteData(
MdVDirKey,
NULL,
PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY ),
ALL_METADATA ) );
}
catch( const ComError & )
{
if ( !RollbackCleanup )
throw;
}
}
}
delete[] OriginalScriptMap;
delete[] NewScriptMap;
IISAdminBase->CloseKey( MdVDirKey );
MdVDirKey = NULL;
}
catch( ComError Exception )
{
delete[] OriginalScriptMap;
delete[] NewScriptMap;
if ( MdVDirKey )
IISAdminBase->CloseKey( MdVDirKey );
throw;
}
}
void
FindWorkItemForVDIR(
PropertyIDManager *PropertyManager,
SmartIMSAdminBasePointer AdminBase,
LPCWSTR Path,
LPWSTR *ReturnedTaskName )
{
if ( ReturnedTaskName )
*ReturnedTaskName = NULL;
try
{
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;
THROW_COMERROR(
AdminBase->GetData(
METADATA_MASTER_ROOT_HANDLE,
Path,
&MdRecord,
&BufferRequired ) );
SmartITaskSchedulerPointer TaskScheduler;
ConnectToTaskScheduler( NULL, &TaskScheduler );
FindWorkItemForVDIR( TaskScheduler, GuidString, NULL, ReturnedTaskName );
}
catch( ComError Error )
{
// simply return NULL if the task item isn't found.
if ( MD_ERROR_DATA_NOT_FOUND == Error.m_Hr ||
HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) == Error.m_Hr )
throw ComError( S_FALSE );
}
}
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 = CSimplePropertyReader::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) ];
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 ];
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()
{
if ( m_InitComplete )
return S_OK;
// Lock object
while( InterlockedExchange( &m_Lock, 1 ) )
Sleep( 0 );
try
{
if ( !m_PropertyMan )
{
m_PropertyMan = new PropertyIDManager();
HRESULT Hr = m_PropertyMan->LoadPropertyInfo();
if ( FAILED(Hr) )
{
delete m_PropertyMan;
m_PropertyMan = NULL;
throw ComError( Hr );
}
}
if ( !m_ADSIPath )
{
SmartIADsPointer ObjectADS;
if ( m_pObject )
THROW_COMERROR(
m_pObject->QueryInterface( __uuidof(*ObjectADS),
(void**) ObjectADS.GetRecvPointer() ) );
else
THROW_COMERROR(
m_pOuter->QueryInterface( __uuidof(*ObjectADS),
(void**) ObjectADS.GetRecvPointer() ) );
THROW_COMERROR( ObjectADS->get_ADsPath( &m_ADSIPath ) );
}
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 ];
StringCchCopyW( m_Path, PathSize, L"/LM/" );
StringCchCatW( m_Path, PathSize, reinterpret_cast<WCHAR*>( m_ADSIPath ) + wcslen( L"IIS://LocalHost/" ) );
}
else
{
THROW_COMERROR( ConnectToRemoteExtension( ) );
}
}
m_InitComplete = true;
// unlock
InterlockedExchange( &m_Lock, 0 );
return S_OK;
}
catch( ComError Error )
{
InterlockedExchange( &m_Lock, 0 );
return Error.m_Hr;
}
}
STDMETHODIMP CBITSExtensionSetup::EnableBITSUploads()
{
try
{
THROW_COMERROR( LoadPath() );
if ( m_RemoteInterface )
return m_RemoteInterface->EnableBITSUploads();
SmartIMSAdminBasePointer AdminBase;
THROW_COMERROR(
CoCreateInstance(
GETAdminBaseCLSID(TRUE),
NULL,
CLSCTX_SERVER,
AdminBase.GetUUID(),
(LPVOID*)AdminBase.GetRecvPointer() ) );
EnableBITSForVDIR( m_PropertyMan, AdminBase, m_Path );
return S_OK;
}
catch( ComError Error )
{
return Error.m_Hr;
}
}
STDMETHODIMP CBITSExtensionSetup::DisableBITSUploads()
{
try
{
THROW_COMERROR( LoadPath() );
if ( m_RemoteInterface )
return m_RemoteInterface->DisableBITSUploads();
SmartIMSAdminBasePointer AdminBase;
THROW_COMERROR(
CoCreateInstance(
GETAdminBaseCLSID(TRUE),
NULL,
CLSCTX_SERVER,
AdminBase.GetUUID(),
(LPVOID*)AdminBase.GetRecvPointer() ) );
DisableBITSForVDIR( m_PropertyMan, AdminBase, m_Path, false, false );
return S_OK;
}
catch( ComError Error )
{
return Error.m_Hr;
}
}
STDMETHODIMP
CBITSExtensionSetup::GetCleanupTaskName( BSTR *pTaskName )
{
LPWSTR TaskName = NULL;
try
{
*pTaskName = NULL;
THROW_COMERROR( LoadPath() );
if ( m_RemoteInterface )
return m_RemoteInterface->GetCleanupTaskName( pTaskName );
SmartIMSAdminBasePointer AdminBase;
THROW_COMERROR(
CoCreateInstance(
GETAdminBaseCLSID(TRUE),
NULL,
CLSCTX_SERVER,
AdminBase.GetUUID(),
(LPVOID*)AdminBase.GetRecvPointer() ) );
FindWorkItemForVDIR( m_PropertyMan, AdminBase, m_Path, &TaskName );
if ( TaskName )
{
*pTaskName = SysAllocString( TaskName );
if ( !*pTaskName )
throw ComError( E_OUTOFMEMORY );
CoTaskMemFree( TaskName );
TaskName = NULL;
}
return S_OK;
}
catch( ComError Error )
{
CoTaskMemFree( TaskName );
return Error.m_Hr;
}
}
STDMETHODIMP
CBITSExtensionSetup::GetCleanupTask(
[in] REFIID riid,
[out,retval] IUnknown **ppUnk )
{
HRESULT Hr = S_OK;
SmartITaskSchedulerPointer TaskScheduler;
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 ];
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;
}
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;
}
SysFreeString( ItemName );
delete[] HostName;
return Hr;
}
#include "bitssrvcfgimp.h"