|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
mdwriter.cxx
Abstract:
This file contains implementation for snapshot writer class
Author:
Ming Lu (MingLu) 30-Apr-2000
--*/
#include <dbgutil.h>
#include "mdwriter.hxx"
#define TIMEOUT_INTERVAL ( 2 * 60 )
#define DEFAULT_SAVE_TIMEOUT 30000
#define IISCOMPONENT L"IISMETABASE"
#define METABASEPATH L"%windir%\\system32\\inetsrv"
#define METABASENAME1 L"metabase.bin"
#define METABASENAME2 L"MetaBase.XML"
#define METABASENAME3 L"MBSchema.XML"
#define NT_SETUP_KEY "SYSTEM\\Setup"
static VSS_ID s_WRITERID = { 0x59b1f0cf, 0x90ef, 0x465f, 0x96, 0x09, 0x6c, 0xa8, 0xb2, 0x93, 0x83, 0x66 };
static LPCWSTR s_WRITERNAME = L"IIS Metabase Writer";
BOOL g_fWriterSubscribed = FALSE; CIISVssWriter * g_pIISVssWriter = NULL;
VOID CALLBACK UnlockMBProc( LPVOID pIISVssWriter, DWORD dwTimerLowValue, DWORD dwTimerHighValue );
BOOL CIISVssWriter::Initialize( VOID ) { HRESULT hr;
if ( !InitializeCriticalSectionAndSpinCount( &m_csMBLock, 0 ) ) { return FALSE; } m_fCSInited = TRUE;
hr = CVssWriter::Initialize( s_WRITERID, s_WRITERNAME, VSS_UT_SYSTEMSERVICE, VSS_ST_OTHER ); if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error in base object Initialize(). hr = %x\n", hr ));
return FALSE; }
m_hTimer = CreateWaitableTimer( NULL, FALSE, NULL ); if( !m_hTimer ) { DBGPRINTF(( DBG_CONTEXT, "Error creating timer object. hr = %x\n", HRESULT_FROM_WIN32( GetLastError() ) ));
return FALSE; }
hr = CoCreateInstance( CLSID_MDCOM, NULL, CLSCTX_INPROC_SERVER, IID_IMDCOM, (void**) &m_pMdObject); if( SUCCEEDED( hr ) ) { hr = m_pMdObject->ComMDInitialize(); if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error initialize MDCOM object. hr = %x\n", hr ));
m_pMdObject->Release(); m_pMdObject = NULL;
return FALSE; } } else { DBGPRINTF(( DBG_CONTEXT, "Error creating MDCOM object. hr = %x\n", hr ));
return FALSE; }
return TRUE; }
bool STDMETHODCALLTYPE CIISVssWriter::OnIdentify( IN IVssCreateWriterMetadata *pMetadata ) { HRESULT hr;
hr = pMetadata->AddComponent( VSS_CT_FILEGROUP, NULL, IISCOMPONENT, NULL, 0, 0, FALSE, FALSE, FALSE ); if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error AddComponent(). hr = %x\n", hr ));
return FALSE; }
if ( TsIsNtWksta() ) { hr = pMetadata->AddFilesToFileGroup( NULL, IISCOMPONENT, METABASEPATH, METABASENAME1, FALSE, NULL ); if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error AddFilesToFileGroup(). hr = %x\n", hr ));
return FALSE; } } else { hr = pMetadata->AddFilesToFileGroup( NULL, IISCOMPONENT, METABASEPATH, METABASENAME2, FALSE, NULL ); if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error AddFilesToFileGroup(). hr = %x\n", hr ));
return FALSE; }
hr = pMetadata->AddFilesToFileGroup( NULL, IISCOMPONENT, METABASEPATH, METABASENAME3, FALSE, NULL ); if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error AddFilesToFileGroup(). hr = %x\n", hr ));
return FALSE; } }
hr = pMetadata->SetRestoreMethod( VSS_RME_RESTORE_AT_REBOOT, // restore method
NULL, // service name
NULL, // user procedure
VSS_WRE_NEVER, // when to call writer restore method
TRUE // reboot is required
); if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error setting restore method. hr = %x\n", hr ));
return FALSE; }
return TRUE; }
bool STDMETHODCALLTYPE CIISVssWriter::OnPrepareBackup( IN IVssWriterComponents *) { return TRUE; }
bool STDMETHODCALLTYPE CIISVssWriter::OnPrepareSnapshot( VOID ) { HRESULT hr;
if( IsPathAffected( METABASEPATH ) ) { //
// First try to lock the tree
//
hr = m_pMdObject->ComMDOpenMetaObjectW( METADATA_MASTER_ROOT_HANDLE, NULL, METADATA_PERMISSION_READ, DEFAULT_SAVE_TIMEOUT, &m_mdhRoot);
if ( SUCCEEDED( hr ) ) { //
// call metadata com api
//
hr = m_pMdObject->ComMDSaveData( m_mdhRoot );
if( SUCCEEDED( hr ) ) { hr = m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
if( SUCCEEDED ( hr ) ) { return TRUE; }
DBGPRINTF(( DBG_CONTEXT, "Error on unlocking the metabase. hr = %x\n", hr ));
return FALSE; }
DBGPRINTF(( DBG_CONTEXT, "Error on saving the metabase. hr = %x\n", hr ));
m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
return FALSE; }
DBGPRINTF(( DBG_CONTEXT, "Error on locking down the metabase. hr = %x\n", hr ));
return FALSE; }
return TRUE; }
bool STDMETHODCALLTYPE CIISVssWriter::OnFreeze( VOID ) { HRESULT hr;
if( IsPathAffected( METABASEPATH ) ) { //
// Lock down the metabase
//
hr = m_pMdObject->ComMDOpenMetaObjectW(METADATA_MASTER_ROOT_HANDLE, NULL, METADATA_PERMISSION_READ, DEFAULT_SAVE_TIMEOUT, &m_mdhRoot);
if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error on locking down the metabase. hr = %x\n", hr ));
return FALSE; } else { if( !ResetTimer( m_hTimer, TIMEOUT_INTERVAL ) ) { DBGPRINTF(( DBG_CONTEXT, "Could not reset the internal timer. hr = %x\n", hr ));
return FALSE; }
EnterCriticalSection( &m_csMBLock );
m_fMBLocked = TRUE;
LeaveCriticalSection( &m_csMBLock );
} }
return TRUE; }
bool STDMETHODCALLTYPE CIISVssWriter::OnThaw( VOID ) { HRESULT hr;
if( IsPathAffected( METABASEPATH ) ) {
EnterCriticalSection( &m_csMBLock );
if( m_fMBLocked ) { hr = m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error on unlocking the metabase. hr = %x\n", hr ));
LeaveCriticalSection( &m_csMBLock );
return FALSE; }
m_fMBLocked = FALSE;
LeaveCriticalSection( &m_csMBLock );
CancelWaitableTimer( m_hTimer ); } else { LeaveCriticalSection( &m_csMBLock ); } }
return TRUE; }
bool STDMETHODCALLTYPE CIISVssWriter::OnBackupComplete( IN IVssWriterComponents *) { return TRUE; }
bool STDMETHODCALLTYPE CIISVssWriter::OnAbort( VOID ) { HRESULT hr;
if( IsPathAffected( METABASEPATH ) ) {
EnterCriticalSection( &m_csMBLock );
if( m_fMBLocked ) { hr = m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error on unlocking the metabase. hr = %x\n", hr ));
LeaveCriticalSection( &m_csMBLock );
return FALSE; }
m_fMBLocked = FALSE;
LeaveCriticalSection( &m_csMBLock );
CancelWaitableTimer( m_hTimer ); } else { LeaveCriticalSection( &m_csMBLock ); } }
return true; }
VOID CIISVssWriter::UnlockMetaBase( VOID ) { HRESULT hr;
EnterCriticalSection( &m_csMBLock );
if( m_fMBLocked ) { hr = m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
if( FAILED( hr ) ) { DBGPRINTF(( DBG_CONTEXT, "Error on unlocking the metabase. hr = %x\n", hr ));
LeaveCriticalSection( &m_csMBLock );
return; }
m_fMBLocked = FALSE; }
LeaveCriticalSection( &m_csMBLock ); }
BOOL CIISVssWriter::ResetTimer( HANDLE hTimer, DWORD dwDuration ) { LARGE_INTEGER li; const int nNanosecondsPersecond = 10000000; __int64 qwTimeFromNowInNanoseconds = (__int64)dwDuration * nNanosecondsPersecond;
qwTimeFromNowInNanoseconds = -qwTimeFromNowInNanoseconds;
li.LowPart = (DWORD) (qwTimeFromNowInNanoseconds & 0xFFFFFFFF); li.HighPart = (LONG) (qwTimeFromNowInNanoseconds >> 32);
if( !SetWaitableTimer( hTimer, &li, 0, UnlockMBProc, this, FALSE ) ) { return FALSE; }
return TRUE; }
VOID CALLBACK UnlockMBProc( LPVOID pIISVssWriter, DWORD , DWORD ) { ( ( CIISVssWriter * )pIISVssWriter )->UnlockMetaBase(); }
DWORD WINAPI InitMDWriterThread( LPVOID ) { HRESULT hr = S_OK; HKEY hKey; DWORD dwType; DWORD cbData; DWORD dwSetupInProgress = 0; DWORD dwUpgradeInProcess = 0;
hr = CoInitializeEx( NULL, COINIT_MULTITHREADED ); if( FAILED( hr ) ) { goto exit; }
//
// Read the setup registry key to see if we are in
// setup mode. If we are, don't init IIS writer.
//
if ( !RegOpenKeyEx( HKEY_LOCAL_MACHINE, NT_SETUP_KEY, 0, KEY_QUERY_VALUE, &hKey ) ) { cbData = sizeof( DWORD );
if( !RegQueryValueEx( hKey, "SystemSetupInProgress", NULL, &dwType, ( LPBYTE )&dwSetupInProgress, &cbData ) ) { if( dwType == REG_DWORD && dwSetupInProgress != 0 ) { //
// We are in setup mode
//
RegCloseKey( hKey ); goto exit; } }
if( !RegQueryValueEx( hKey, "UpgradeInProgress", NULL, &dwType, ( LPBYTE )&dwUpgradeInProcess, &cbData ) ) { if( dwType == REG_DWORD && dwUpgradeInProcess != 0 ) { //
// We are in upgrade mode
//
RegCloseKey( hKey ); goto exit; } }
RegCloseKey( hKey ); }
//
// OK, we are not in setup mode, initialize our IIS writer
//
g_pIISVssWriter = new CIISVssWriter; if ( g_pIISVssWriter == NULL ) { //
// oh well. guess we won�t support snapshots
//
DBGPRINTF(( DBG_CONTEXT, "Error on creating the writer object, out of memory\n" ));
goto exit; } else { //
// cool, we�ve got the object now.
//
if( !g_pIISVssWriter->Initialize() ) { DBGPRINTF(( DBG_CONTEXT, "Error on initializing the writer object\n" ));
delete g_pIISVssWriter; g_pIISVssWriter = NULL;
goto exit; }
if( SUCCEEDED( g_pIISVssWriter->Subscribe() ) ) { g_fWriterSubscribed = TRUE; } else { DBGPRINTF(( DBG_CONTEXT, "Error on subscribing the writer object\n" ));
delete g_pIISVssWriter; g_pIISVssWriter = NULL; } }
exit: //
// Let the TerminateMDWriter know we are ready to terminate during
// IISADMIN service shutdown
//
if( SUCCEEDED( hr ) ) { CoUninitialize(); }
return (DWORD)hr; }
HRESULT InitializeMDWriter( HANDLE *phMDWriterThread ) { HRESULT hr = S_OK; DWORD dwThreadID;
DBG_ASSERT( phMDWriterThread != NULL );
*phMDWriterThread = CreateThread( NULL, 0, InitMDWriterThread, NULL, 0, &dwThreadID); if( *phMDWriterThread == NULL ) { hr = HRESULT_FROM_WIN32( GetLastError() ); }
return hr; }
VOID TerminateMDWriter( HANDLE hMDWriterThread ) { DBG_ASSERT( hMDWriterThread != NULL );
//
// Only do cleanup if the hMDWriterThread is signaled
//
if( WAIT_OBJECT_0 == WaitForSingleObject( hMDWriterThread, INFINITE ) ) { if( g_pIISVssWriter ) { if( g_fWriterSubscribed ) { DBG_ASSERT( g_pIISVssWriter );
g_pIISVssWriter->Unsubscribe(); }
delete g_pIISVssWriter; g_pIISVssWriter = NULL; } } }
|