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.
907 lines
26 KiB
907 lines
26 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cleanup.cpp
|
|
|
|
Abstract:
|
|
|
|
This file implements the BITS server extensions cleanup worker
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
const UINT64 NanoSec100PerSec = 10000000; //no of 100 nanosecs per second
|
|
|
|
inline UINT64 FILETIMEToUINT64( const FILETIME & FileTime )
|
|
{
|
|
ULARGE_INTEGER LargeInteger;
|
|
LargeInteger.HighPart = FileTime.dwHighDateTime;
|
|
LargeInteger.LowPart = FileTime.dwLowDateTime;
|
|
return LargeInteger.QuadPart;
|
|
};
|
|
|
|
class PollKillError
|
|
{
|
|
public:
|
|
HRESULT m_Hr;
|
|
PollKillError( HRESULT Hr ) :
|
|
m_Hr( Hr )
|
|
{
|
|
}
|
|
};
|
|
|
|
class CleanupWorker
|
|
{
|
|
|
|
public:
|
|
CleanupWorker( BOOL DeleteAll, HWND hwnd, const WCHAR* Path,
|
|
const WCHAR *WorkItemName, const WCHAR *GuidString );
|
|
~CleanupWorker();
|
|
void DoIt();
|
|
|
|
private:
|
|
|
|
BOOL m_DeleteAll;
|
|
HWND m_hwnd;
|
|
const WCHAR * m_Path;
|
|
const WCHAR * m_WorkItemName;
|
|
const WCHAR * m_GuidString;
|
|
const WCHAR * m_ADSIPath;
|
|
IADs * m_VDir;
|
|
BSTR m_VDirPath;
|
|
BSTR m_SessionDirectory;
|
|
BSTR m_UNCUsername;
|
|
BSTR m_UNCPassword;
|
|
UINT64 m_CleanupThreshold;
|
|
|
|
StringHandle m_SessionDirPath;
|
|
StringHandle m_RequestsDirPath;
|
|
StringHandle m_RepliesDirPath;
|
|
|
|
VARIANT m_vt;
|
|
|
|
HANDLE m_UserToken;
|
|
HANDLE m_EventLog;
|
|
|
|
BSTR m_BITSCleanupWorkItemKeyBSTR;
|
|
BSTR m_BITSUploadEnabledBSTR;
|
|
BSTR m_BITSSessionTimeoutBSTR;
|
|
BSTR m_PathBSTR;
|
|
BSTR m_BITSSessionDirectoryBSTR;
|
|
BSTR m_UNCUserNameBSTR;
|
|
BSTR m_UNCPasswordBSTR;
|
|
|
|
void PollKill();
|
|
|
|
void DeleteDirectoryAndFiles( StringHandle Directory );
|
|
bool DirectoryExists( StringHandle Directory );
|
|
UINT64 LastDirectoryTime( StringHandle Directory );
|
|
void RemoveSession( StringHandle SessionGuid );
|
|
void RemoveSessions( bool SecondPass );
|
|
|
|
void RemoveConnectionsFromTree(
|
|
const WCHAR * DirectoryPath,
|
|
bool IsConnectionDirectory,
|
|
const WCHAR * FileSystemPath = NULL );
|
|
|
|
void RemoveConnection( const WCHAR * ConnectionDirectory, const WCHAR *FilesystemPath,
|
|
const WCHAR * SessionGuid );
|
|
|
|
void LogDeletedJob( const WCHAR *SessionGuid );
|
|
void LogUnableToRemoveSession( const WCHAR *SessionGuid, HRESULT Hr );
|
|
void LogUnexpectedError( HRESULT Hr );
|
|
void LogUnableToScanDirectory( const WCHAR *Path, HRESULT Hr );
|
|
|
|
};
|
|
|
|
void
|
|
BITSSetCurrentThreadToken(
|
|
HANDLE hToken )
|
|
{
|
|
|
|
if ( !SetThreadToken( NULL, hToken ) )
|
|
{
|
|
|
|
for( unsigned int i = 0; i < 100; i ++ )
|
|
{
|
|
|
|
Sleep( 10 );
|
|
|
|
if ( SetThreadToken( NULL, hToken ) )
|
|
return;
|
|
|
|
}
|
|
|
|
TerminateProcess( NULL, GetLastError() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CleanupWorker::CleanupWorker(
|
|
BOOL DeleteAll,
|
|
HWND hwnd,
|
|
const WCHAR* Path,
|
|
const WCHAR* WorkItemName,
|
|
const WCHAR* GuidString ) :
|
|
m_DeleteAll( DeleteAll ),
|
|
m_hwnd( hwnd ),
|
|
m_Path( Path ),
|
|
m_WorkItemName( WorkItemName ),
|
|
m_GuidString( GuidString ),
|
|
m_ADSIPath( NULL ),
|
|
m_VDir( NULL ),
|
|
m_VDirPath( NULL ),
|
|
m_SessionDirectory( NULL ),
|
|
m_CleanupThreshold( 0 ),
|
|
m_UNCUsername( NULL ),
|
|
m_UNCPassword( NULL ),
|
|
m_UserToken( NULL ),
|
|
m_EventLog( NULL ),
|
|
m_BITSCleanupWorkItemKeyBSTR( NULL ),
|
|
m_BITSUploadEnabledBSTR( NULL ),
|
|
m_BITSSessionTimeoutBSTR( NULL ),
|
|
m_PathBSTR( NULL ),
|
|
m_BITSSessionDirectoryBSTR( NULL ),
|
|
m_UNCUserNameBSTR( NULL ),
|
|
m_UNCPasswordBSTR( NULL )
|
|
{
|
|
VariantInit( &m_vt );
|
|
|
|
m_BITSCleanupWorkItemKeyBSTR = SysAllocString( L"BITSCleanupWorkItemKey" );
|
|
m_BITSUploadEnabledBSTR = SysAllocString( L"BITSUploadEnabled" );
|
|
m_BITSSessionTimeoutBSTR = SysAllocString( L"BITSSessionTimeout" );
|
|
m_PathBSTR = SysAllocString( L"Path" );
|
|
m_BITSSessionDirectoryBSTR = SysAllocString( L"BITSSessionDirectory" );
|
|
m_UNCUserNameBSTR = SysAllocString( L"UNCUserName" );
|
|
m_UNCPasswordBSTR = SysAllocString( L"UNCPassword" );
|
|
|
|
if ( !m_BITSCleanupWorkItemKeyBSTR || !m_BITSUploadEnabledBSTR || !m_BITSSessionTimeoutBSTR ||
|
|
!m_PathBSTR || !m_BITSSessionDirectoryBSTR || !m_UNCUserNameBSTR || !m_UNCPasswordBSTR )
|
|
{
|
|
|
|
SysFreeString( m_BITSCleanupWorkItemKeyBSTR );
|
|
SysFreeString( m_BITSUploadEnabledBSTR );
|
|
SysFreeString( m_BITSSessionTimeoutBSTR );
|
|
SysFreeString( m_PathBSTR );
|
|
SysFreeString( m_BITSSessionDirectoryBSTR );
|
|
SysFreeString( m_UNCUserNameBSTR );
|
|
SysFreeString( m_UNCPasswordBSTR );
|
|
|
|
throw ComError( E_OUTOFMEMORY );
|
|
}
|
|
|
|
|
|
m_EventLog =
|
|
RegisterEventSource(
|
|
NULL, // server name
|
|
EVENT_LOG_SOURCE_NAME // source name
|
|
);
|
|
|
|
if ( !m_EventLog )
|
|
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
|
|
|
|
}
|
|
|
|
CleanupWorker::~CleanupWorker()
|
|
{
|
|
|
|
if ( m_EventLog )
|
|
DeregisterEventSource( m_EventLog );
|
|
|
|
if ( m_UserToken )
|
|
{
|
|
BITSSetCurrentThreadToken( NULL );
|
|
CloseHandle( m_UserToken );
|
|
}
|
|
|
|
delete m_ADSIPath;
|
|
SysFreeString( m_VDirPath );
|
|
SysFreeString( m_SessionDirectory );
|
|
SysFreeString( m_UNCUsername );
|
|
SysFreeString( m_UNCPassword );
|
|
|
|
// Free hardcoded strings
|
|
SysFreeString( m_BITSCleanupWorkItemKeyBSTR );
|
|
SysFreeString( m_BITSUploadEnabledBSTR );
|
|
SysFreeString( m_BITSSessionTimeoutBSTR );
|
|
SysFreeString( m_PathBSTR );
|
|
SysFreeString( m_BITSSessionDirectoryBSTR );
|
|
SysFreeString( m_UNCUserNameBSTR );
|
|
SysFreeString( m_UNCPasswordBSTR );
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CleanupWorker::DeleteDirectoryAndFiles()
|
|
//
|
|
// This method deletes the specified directory and the files it contains. If
|
|
// the specified directory contains subdirectories, then they will not be
|
|
// deleted (and the delete of the main directory will fail).
|
|
//
|
|
// If the directory is a reparse point, then it will do nothing. If the
|
|
// specified directory contains reparse points then they will be ignored as
|
|
// well.
|
|
//---------------------------------------------------------------------------
|
|
void
|
|
CleanupWorker::DeleteDirectoryAndFiles( StringHandle Directory )
|
|
{
|
|
|
|
HANDLE FindHandle = INVALID_HANDLE_VALUE;
|
|
WIN32_FILE_ATTRIBUTE_DATA FileAttributes;
|
|
|
|
try
|
|
{
|
|
// Check the specified directory. If its not actually a directory, or
|
|
// it's a reparse point then don't process it.
|
|
if (!GetFileAttributesEx( Directory,
|
|
GetFileExInfoStandard,
|
|
&FileAttributes))
|
|
{
|
|
throw ComError(HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
if ( (FileAttributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
|
|
|| !(FileAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
StringHandle SearchPath = Directory + StringHandle(L"\\*");
|
|
|
|
WIN32_FIND_DATA FindData;
|
|
|
|
FindHandle = FindFirstFile( SearchPath,
|
|
&FindData );
|
|
|
|
if ( INVALID_HANDLE_VALUE == FindHandle )
|
|
{
|
|
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
|
|
}
|
|
|
|
do
|
|
{
|
|
|
|
if ( (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
|| (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
StringHandle FileName = StringHandle( Directory ) + StringHandle( L"\\" ) +
|
|
StringHandle( FindData.cFileName );
|
|
DeleteFile( FileName );
|
|
|
|
}
|
|
while ( FindNextFile( FindHandle, &FindData ) );
|
|
|
|
FindClose( FindHandle );
|
|
FindHandle = INVALID_HANDLE_VALUE;
|
|
|
|
if ( !RemoveDirectory( Directory ) )
|
|
{
|
|
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
|
|
}
|
|
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
if ( INVALID_HANDLE_VALUE != FindHandle )
|
|
{
|
|
FindClose( FindHandle );
|
|
}
|
|
throw;
|
|
}
|
|
|
|
if ( INVALID_HANDLE_VALUE != FindHandle )
|
|
{
|
|
FindClose( FindHandle );
|
|
}
|
|
}
|
|
|
|
bool
|
|
CleanupWorker::DirectoryExists(
|
|
StringHandle Directory )
|
|
{
|
|
|
|
DWORD dwAttributes =
|
|
GetFileAttributes( Directory );
|
|
|
|
if ( INVALID_FILE_ATTRIBUTES == dwAttributes )
|
|
{
|
|
|
|
if ( GetLastError() == ERROR_PATH_NOT_FOUND ||
|
|
GetLastError() == ERROR_FILE_NOT_FOUND )
|
|
return false;
|
|
|
|
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CleanupWorker::LastDirectoryTime()
|
|
//
|
|
// Walk a directory and find the most recent "Last Write Time" for it or
|
|
// and of its contents.
|
|
//
|
|
// Note: Ignore reparse points.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
UINT64
|
|
CleanupWorker::LastDirectoryTime(
|
|
StringHandle Directory )
|
|
{
|
|
UINT64 LatestTime = 0;
|
|
HANDLE FindHandle = INVALID_HANDLE_VALUE;
|
|
WIN32_FILE_ATTRIBUTE_DATA FileAttributesData;
|
|
|
|
if (!GetFileAttributesEx( Directory,
|
|
GetFileExInfoStandard,
|
|
&FileAttributesData ) )
|
|
{
|
|
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
|
|
}
|
|
|
|
LatestTime = FILETIMEToUINT64( FileAttributesData.ftCreationTime );
|
|
|
|
StringHandle SearchPath = Directory + StringHandle(L"\\*");
|
|
|
|
WIN32_FIND_DATA FindData;
|
|
|
|
FindHandle =
|
|
FindFirstFile(
|
|
SearchPath,
|
|
&FindData
|
|
);
|
|
|
|
if ( INVALID_HANDLE_VALUE == FindHandle )
|
|
throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
|
|
|
|
try
|
|
{
|
|
|
|
do
|
|
{
|
|
|
|
if ( (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
|| (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
UINT64 CreationTime = FILETIMEToUINT64( FindData.ftCreationTime );
|
|
UINT64 LastWriteTime = FILETIMEToUINT64( FindData.ftLastWriteTime );
|
|
LatestTime = max( LatestTime, max( CreationTime, LastWriteTime ) );
|
|
}
|
|
while ( FindNextFile( FindHandle, &FindData ) );
|
|
|
|
FindClose( FindHandle );
|
|
FindHandle = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
if ( INVALID_HANDLE_VALUE == FindHandle )
|
|
FindClose( FindHandle );
|
|
|
|
throw;
|
|
}
|
|
|
|
return LatestTime;
|
|
|
|
}
|
|
|
|
void
|
|
CleanupWorker::RemoveSession(
|
|
StringHandle SessionGuid )
|
|
{
|
|
|
|
StringHandle RequestDir = m_RequestsDirPath + StringHandle("\\") + SessionGuid;
|
|
StringHandle ReplyDir = m_RepliesDirPath + StringHandle("\\") + SessionGuid;
|
|
|
|
bool RequestExists = DirectoryExists( RequestDir );
|
|
bool ReplyExists = DirectoryExists( ReplyDir );
|
|
|
|
|
|
UINT64 LastTime = 0;
|
|
|
|
if ( RequestExists )
|
|
{
|
|
try
|
|
{
|
|
LastTime = LastDirectoryTime( RequestDir );
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
LogUnableToScanDirectory( RequestDir, Error.m_Hr );
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( ReplyExists )
|
|
{
|
|
|
|
try
|
|
{
|
|
LastTime = max( LastTime, LastDirectoryTime( ReplyDir ) );
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
LogUnableToScanDirectory( ReplyDir, Error.m_Hr );
|
|
return;
|
|
}
|
|
}
|
|
|
|
FILETIME ftCurrentTime;
|
|
GetSystemTimeAsFileTime( &ftCurrentTime );
|
|
UINT64 CurrentTime = FILETIMEToUINT64( ftCurrentTime );
|
|
|
|
if ( ( 0xFFFFFFFF - LastTime > m_CleanupThreshold ) &&
|
|
( LastTime + m_CleanupThreshold < CurrentTime ) )
|
|
|
|
{
|
|
|
|
try
|
|
{
|
|
if ( RequestExists )
|
|
{
|
|
DeleteDirectoryAndFiles( RequestDir );
|
|
}
|
|
|
|
if ( ReplyExists )
|
|
{
|
|
DeleteDirectoryAndFiles( ReplyDir );
|
|
}
|
|
|
|
LogDeletedJob( SessionGuid );
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
LogUnableToRemoveSession( SessionGuid, Error.m_Hr );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CleanupWorker::RemoveSessions()
|
|
//
|
|
// Inspect the current "Replies directory" and "Requests directory" and
|
|
// remove any BITS session directories that are older than the current
|
|
// cleanup threshold.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// SecondPass TRUE: Inspect the Replies Directory Path.
|
|
// FALSE: Inspect the Requests Directory Path.
|
|
//--------------------------------------------------------------------------
|
|
void
|
|
CleanupWorker::RemoveSessions( IN bool SecondPass )
|
|
{
|
|
|
|
StringHandle SearchDirectory = (SecondPass)? m_RepliesDirPath : m_RequestsDirPath;
|
|
StringHandle SearchString = SearchDirectory + StringHandle( L"\\*" );
|
|
HANDLE FindHandle = INVALID_HANDLE_VALUE;
|
|
WIN32_FIND_DATA FindData;
|
|
WIN32_FILE_ATTRIBUTE_DATA FileAttributes;
|
|
|
|
try
|
|
{
|
|
if (!GetFileAttributesEx(SearchDirectory,
|
|
GetFileExInfoStandard,
|
|
&FileAttributes))
|
|
{
|
|
throw ComError(HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
if ( (FileAttributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
|
|
|| !(FileAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
FindHandle = FindFirstFile( SearchString, &FindData );
|
|
|
|
if ( INVALID_HANDLE_VALUE == FindHandle )
|
|
{
|
|
throw ComError(HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
do
|
|
{
|
|
|
|
PollKill();
|
|
|
|
// If its not a directory then ignore it...
|
|
if ( !(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If its a reparse point then ignore it.
|
|
if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If its this directory or the parent directory reference then
|
|
// ignore it.
|
|
if ( ( _wcsicmp( L".", FindData.cFileName ) == 0 )
|
|
|| ( _wcsicmp( L"..", FindData.cFileName ) == 0 ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// If the name isn't a GUID then ignore it.
|
|
GUID Guid;
|
|
if ( FAILED( IIDFromString( FindData.cFileName, &Guid ) ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
try
|
|
{
|
|
RemoveSession( StringHandle( FindData.cFileName ) );
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
LogUnexpectedError( Error.m_Hr );
|
|
}
|
|
|
|
} while( FindNextFile( FindHandle, &FindData ) );
|
|
|
|
FindClose( FindHandle );
|
|
FindHandle = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
catch( const ComError & )
|
|
{
|
|
if ( INVALID_HANDLE_VALUE != FindHandle )
|
|
{
|
|
FindClose( FindHandle );
|
|
}
|
|
throw;
|
|
}
|
|
catch( const PollKillError & )
|
|
{
|
|
if ( INVALID_HANDLE_VALUE != FindHandle )
|
|
{
|
|
FindClose( FindHandle );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
CleanupWorker::PollKill()
|
|
{
|
|
|
|
if ( m_hwnd )
|
|
{
|
|
|
|
MSG msg;
|
|
|
|
while( PeekMessage(
|
|
&msg,
|
|
m_hwnd,
|
|
0,
|
|
0,
|
|
PM_REMOVE ) )
|
|
{
|
|
|
|
if ( WM_QUIT == msg.message )
|
|
throw PollKillError( (HRESULT)msg.wParam );
|
|
|
|
TranslateMessage( &msg );
|
|
DispatchMessage( &msg );
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
CleanupWorker::DoIt()
|
|
{
|
|
|
|
try
|
|
{
|
|
|
|
m_ADSIPath = CSimplePropertyReader::ConvertObjectPathToADSI( m_Path );
|
|
|
|
try
|
|
{
|
|
THROW_COMERROR( ADsGetObject( m_ADSIPath, __uuidof(*m_VDir), (void**)&m_VDir ) );
|
|
|
|
if ( m_GuidString )
|
|
{
|
|
|
|
BSTR BSTRGuid = CSimplePropertyReader::GetADsStringProperty( m_VDir, m_BITSCleanupWorkItemKeyBSTR );
|
|
int Result = wcscmp( (LPWSTR)BSTRGuid, m_GuidString );
|
|
|
|
SysFreeString( BSTRGuid );
|
|
|
|
if ( Result != 0 )
|
|
throw ComError( E_ADS_UNKNOWN_OBJECT );
|
|
|
|
}
|
|
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
|
|
if ( ( Error.m_Hr == E_ADS_UNKNOWN_OBJECT ) ||
|
|
( Error.m_Hr == HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) ) ||
|
|
( Error.m_Hr == E_ADS_PROPERTY_NOT_FOUND ) )
|
|
{
|
|
// Somehow the virtual directory was deleted, but the
|
|
// task scheduler work item wasn't. Try to delete it now.
|
|
|
|
if ( m_WorkItemName )
|
|
{
|
|
|
|
SmartITaskSchedulerPointer TaskScheduler;
|
|
|
|
try
|
|
{
|
|
ConnectToTaskScheduler( NULL, &TaskScheduler );
|
|
TaskScheduler->Delete( m_WorkItemName );
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// Nothing more to do after deleting the task.
|
|
return;
|
|
}
|
|
|
|
THROW_COMERROR( m_VDir->Get( m_BITSUploadEnabledBSTR, &m_vt ) );
|
|
THROW_COMERROR( VariantChangeType( &m_vt, &m_vt, 0, VT_BOOL ) );
|
|
|
|
if ( !m_vt.boolVal ) // Uploads arn't enabled on this directory
|
|
return;
|
|
|
|
if ( !m_DeleteAll )
|
|
{
|
|
|
|
THROW_COMERROR( m_VDir->Get( m_BITSSessionTimeoutBSTR, &m_vt ) );
|
|
THROW_COMERROR( VariantChangeType( &m_vt, &m_vt, 0, VT_BSTR ) );
|
|
|
|
if ( L'-' == *m_vt.bstrVal )
|
|
return; // do not run cleanup in this directory since cleanup has been disabled
|
|
|
|
UINT64 CleanupSeconds;
|
|
if ( 1 != swscanf( (WCHAR*)m_vt.bstrVal, L"%I64u", &CleanupSeconds ) )
|
|
return;
|
|
|
|
if ( CleanupSeconds > ( 0xFFFFFFFFFFFFFFFF / NanoSec100PerSec ) )
|
|
m_CleanupThreshold = 0xFFFFFFFFFFFFFFFF; // overflow case
|
|
else
|
|
m_CleanupThreshold = CleanupSeconds * NanoSec100PerSec;
|
|
|
|
}
|
|
else
|
|
m_CleanupThreshold = 0;
|
|
|
|
|
|
m_VDirPath = CSimplePropertyReader::GetADsStringProperty( m_VDir, m_PathBSTR );
|
|
m_SessionDirectory = CSimplePropertyReader::GetADsStringProperty( m_VDir, m_BITSSessionDirectoryBSTR );
|
|
m_UNCUsername = CSimplePropertyReader::GetADsStringProperty( m_VDir, m_UNCUserNameBSTR );
|
|
m_UNCPassword = CSimplePropertyReader::GetADsStringProperty( m_VDir, m_UNCPasswordBSTR );
|
|
|
|
m_SessionDirPath = StringHandle( (WCHAR*)m_VDirPath) + StringHandle(L"\\") +
|
|
StringHandle( (WCHAR*)m_SessionDirectory );
|
|
m_RequestsDirPath = m_SessionDirPath + StringHandle(L"\\") + StringHandle( REQUESTS_DIR_NAMEW );
|
|
m_RepliesDirPath = m_SessionDirPath + StringHandle(L"\\") + StringHandle( REPLIES_DIR_NAMEW );
|
|
|
|
if (CAccessRemoteVDir::IsUNCPath(m_VDirPath))
|
|
{
|
|
CAccessRemoteVDir::ImpersonateUNCUser(m_VDirPath, m_UNCUsername, m_UNCPassword, &m_UserToken);
|
|
}
|
|
|
|
RemoveSessions( false );
|
|
RemoveSessions( true );
|
|
|
|
}
|
|
catch( PollKillError Error )
|
|
{
|
|
throw;
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
LogUnexpectedError( Error.m_Hr );
|
|
throw;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void
|
|
CleanupWorker::LogDeletedJob(
|
|
const WCHAR *SessionGuid )
|
|
{
|
|
|
|
if ( m_EventLog )
|
|
{
|
|
|
|
const WCHAR *Strings[] = { (const WCHAR*)m_SessionDirPath, SessionGuid };
|
|
|
|
ReportEvent(
|
|
m_EventLog, // handle to event log
|
|
EVENTLOG_INFORMATION_TYPE, // event type
|
|
BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
|
|
BITSSRV_EVENTLOG_DELETED_SESSION, // event identifier
|
|
NULL, // user security identifier
|
|
2, // number of strings to merge
|
|
0, // size of binary data
|
|
Strings, // array of strings to merge
|
|
NULL // binary data buffer
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
CleanupWorker::LogUnableToRemoveSession(
|
|
const WCHAR *SessionGuid,
|
|
HRESULT Hr )
|
|
{
|
|
|
|
if ( m_EventLog )
|
|
{
|
|
|
|
const WCHAR *Strings[] = { (const WCHAR*)m_SessionDirPath, SessionGuid };
|
|
|
|
ReportEvent(
|
|
m_EventLog, // handle to event log
|
|
EVENTLOG_ERROR_TYPE, // event type
|
|
BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
|
|
BITSSRV_EVENTLOG_CANT_REMOVE_SESSION, // event identifier
|
|
NULL, // user security identifier
|
|
2, // number of strings to merge
|
|
sizeof(Hr), // size of binary data
|
|
Strings, // array of strings to merge
|
|
&Hr // binary data buffer
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
CleanupWorker::
|
|
LogUnableToScanDirectory(
|
|
const WCHAR *Path,
|
|
HRESULT Hr )
|
|
{
|
|
|
|
if ( m_EventLog )
|
|
{
|
|
|
|
const WCHAR *Strings[] = { Path };
|
|
|
|
ReportEvent(
|
|
m_EventLog, // handle to event log
|
|
EVENTLOG_ERROR_TYPE, // event type
|
|
BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
|
|
BITSSRV_EVENTLOG_CANT_SCAN_DIRECTORY, // 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
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
CleanupWorker::LogUnexpectedError(
|
|
HRESULT Hr )
|
|
{
|
|
|
|
if ( m_EventLog )
|
|
{
|
|
|
|
const WCHAR *Strings[] = { m_Path };
|
|
|
|
ReportEvent(
|
|
m_EventLog, // handle to event log
|
|
EVENTLOG_ERROR_TYPE, // event type
|
|
BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
|
|
BITSSRV_EVENTLOG_UNEXPECTED_ERROR, // 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
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void Cleanup_RunDLLW(HWND hwndStub, HINSTANCE hAppInstance, LPWSTR lpszCmdLine, int nCmdShow )
|
|
{
|
|
int NumArgs;
|
|
|
|
LPWSTR * CommandArgs =
|
|
CommandLineToArgvW(
|
|
lpszCmdLine,
|
|
&NumArgs );
|
|
|
|
if ( !CommandArgs )
|
|
return;
|
|
|
|
|
|
if ( FAILED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) )
|
|
return;
|
|
|
|
if ( NumArgs != 2 && NumArgs != 3 )
|
|
return;
|
|
|
|
LPWSTR Path = CommandArgs[0];
|
|
LPWSTR WorkItemName = CommandArgs[1];
|
|
LPWSTR GuidString = NumArgs == 3 ? CommandArgs[2] : NULL;
|
|
|
|
try
|
|
{
|
|
CleanupWorker Worker( FALSE, hwndStub, Path, WorkItemName, GuidString );
|
|
Worker.DoIt();
|
|
}
|
|
catch( PollKillError PollAbort )
|
|
{
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
}
|
|
|
|
CoUninitialize( );
|
|
GlobalFree( CommandArgs );
|
|
|
|
}
|
|
|
|
void CleanupForRemoval( LPCWSTR Path )
|
|
{
|
|
|
|
HANDLE hToken = NULL;
|
|
|
|
try
|
|
{
|
|
if (!OpenThreadToken( GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken ) )
|
|
{
|
|
if ( GetLastError() != ERROR_NO_TOKEN )
|
|
return;
|
|
}
|
|
|
|
CleanupWorker Worker( TRUE, NULL, Path, NULL, NULL );
|
|
Worker.DoIt();
|
|
}
|
|
catch( ComError Error )
|
|
{
|
|
}
|
|
catch( PollKillError PollAbort )
|
|
{
|
|
}
|
|
|
|
if ( hToken )
|
|
BITSSetCurrentThreadToken( hToken );
|
|
|
|
}
|