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.
424 lines
11 KiB
424 lines
11 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
helpsvc.cpp
|
|
|
|
Abstract:
|
|
Housekeeping for the HelpSvc service.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 04/15/2001
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <idletask.h>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const WCHAR s_szRoot [] = HC_REGISTRY_PCHSVC;
|
|
static const WCHAR s_szStartItSrv [] = L"StartItSrv";
|
|
static const WCHAR s_szDataCollection[] = L"DataCollection";
|
|
|
|
typedef MPC::SmartLockGeneric<MPC::CComSafeAutoCriticalSection> LocalSmartLock;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef DEBUG
|
|
static void StartIdleTaskServer()
|
|
{
|
|
MPC::wstring strValue;
|
|
bool fFound;
|
|
|
|
if(SUCCEEDED(MPC::RegKey_Value_Read( strValue, fFound, s_szRoot, s_szStartItSrv )) && fFound)
|
|
{
|
|
PROCESS_INFORMATION piProcessInformation;
|
|
STARTUPINFOW siStartupInfo;
|
|
BOOL fStarted;
|
|
|
|
MPC::SubstituteEnvVariables( strValue );
|
|
|
|
::ZeroMemory( (PVOID)&piProcessInformation, sizeof( piProcessInformation ) );
|
|
::ZeroMemory( (PVOID)&siStartupInfo , sizeof( siStartupInfo ) ); siStartupInfo.cb = sizeof( siStartupInfo );
|
|
|
|
fStarted = ::CreateProcessW( NULL ,
|
|
(LPWSTR)strValue.c_str(),
|
|
NULL ,
|
|
NULL ,
|
|
FALSE ,
|
|
NORMAL_PRIORITY_CLASS ,
|
|
NULL ,
|
|
NULL ,
|
|
&siStartupInfo ,
|
|
&piProcessInformation );
|
|
|
|
|
|
if(piProcessInformation.hProcess) ::CloseHandle( piProcessInformation.hProcess );
|
|
if(piProcessInformation.hThread ) ::CloseHandle( piProcessInformation.hThread );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ServiceHandler_HelpSvc::ServiceHandler_HelpSvc( /*[in]*/ LPCWSTR szServiceName, /*[in]*/ CComRedirectorFactory* rgClasses ) :
|
|
ServiceHandler ( szServiceName, rgClasses ),
|
|
m_svc_Timer ( this, ServiceShutdownCallback ),
|
|
m_batch_Event ( this, BatchCallback ),
|
|
m_batch_Timer ( this, BatchCallback2 ),
|
|
m_dc_Timer ( this, DataCollectionCallback ),
|
|
m_dc_TimerRestart( this, DataCollectionRestartCallback ),
|
|
m_dc_EventStart ( this, IdleStartCallback , WT_EXECUTEONLYONCE ),
|
|
m_dc_EventStop ( this, IdleStopCallback , WT_EXECUTEONLYONCE )
|
|
{
|
|
// MPC::CComSafeAutoCriticalSection m_cs;
|
|
// CComPtr<IPCHService> m_svc;
|
|
// LocalTimer m_svc_Timer;
|
|
//
|
|
m_batch_Notification = INVALID_HANDLE_VALUE; // HANDLE m_batch_Notification;
|
|
// LocalEvent m_batch_Event;
|
|
// LocalTimer m_batch_Timer;
|
|
//
|
|
// LocalTimer m_dc_Timer;
|
|
// LocalTimer m_dc_TimerRestart;
|
|
//
|
|
m_dc_IdleHandle = NULL; // HANDLE m_dc_IdleHandle;
|
|
m_dc_IdleStart = NULL; // HANDLE m_dc_IdleStart;
|
|
m_dc_IdleStop = NULL; // HANDLE m_dc_IdleStop;
|
|
// LocalEvent m_dc_EventStart;
|
|
// LocalEvent m_dc_EventStop;
|
|
}
|
|
|
|
HRESULT ServiceHandler_HelpSvc::Initialize()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "ServiceHandler_HelpSvc::Initialize" );
|
|
|
|
const DWORD s_dwNotify = FILE_NOTIFY_CHANGE_FILE_NAME |
|
|
FILE_NOTIFY_CHANGE_DIR_NAME |
|
|
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
|
FILE_NOTIFY_CHANGE_SIZE |
|
|
FILE_NOTIFY_CHANGE_CREATION;
|
|
|
|
|
|
HRESULT hr;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ServiceHandler::Initialize());
|
|
|
|
try
|
|
{
|
|
{
|
|
MPC::wstring strBatch( HC_ROOT_HELPSVC_BATCH ); MPC::SubstituteEnvVariables( strBatch );
|
|
|
|
m_batch_Notification = ::FindFirstChangeNotificationW( strBatch.c_str(), TRUE, s_dwNotify );
|
|
if(m_batch_Notification != INVALID_HANDLE_VALUE)
|
|
{
|
|
m_batch_Event.Attach( m_batch_Notification );
|
|
m_batch_Event.Set ( INFINITE );
|
|
}
|
|
}
|
|
|
|
DataCollection_Queue();
|
|
}
|
|
catch(...)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
void ServiceHandler_HelpSvc::Cleanup()
|
|
{
|
|
try
|
|
{
|
|
m_svc_Timer .Reset();
|
|
|
|
m_dc_Timer .Reset();
|
|
m_dc_TimerRestart.Reset();
|
|
|
|
IdleTask_Cleanup();
|
|
|
|
////////////////////
|
|
|
|
if(m_batch_Notification != INVALID_HANDLE_VALUE)
|
|
{
|
|
m_batch_Event.Attach( NULL );
|
|
|
|
::FindCloseChangeNotification( m_batch_Notification );
|
|
|
|
m_batch_Notification = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
////////////////////
|
|
|
|
//
|
|
// Find the HelpSvc class factory and force a shutdown.
|
|
//
|
|
{
|
|
CComRedirectorFactory* classes;
|
|
|
|
for(classes=m_rgClasses; classes->m_pclsid; classes++)
|
|
{
|
|
IPCHService* svc;
|
|
|
|
if(SUCCEEDED(classes->GetServer( NULL, __uuidof( IPCHService ), (void**)&svc )))
|
|
{
|
|
(void)svc->PrepareForShutdown();
|
|
|
|
svc->Release();
|
|
|
|
::Sleep( 3000 ); // Give some time to shutdown code.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
|
|
ServiceHandler::Cleanup();
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT ServiceHandler_HelpSvc::IdleTask_Initialize()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "ServiceHandler_HelpSvc::IdleTask_Initialize" );
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
{
|
|
LocalSmartLock lock( &m_cs );
|
|
|
|
if(!m_dc_IdleHandle)
|
|
{
|
|
try
|
|
{
|
|
DWORD dwErr = ::RegisterIdleTask( ItHelpSvcDataCollectionTaskId, &m_dc_IdleHandle, &m_dc_IdleStart, &m_dc_IdleStop );
|
|
|
|
#ifdef DEBUG
|
|
if(dwErr != ERROR_SUCCESS)
|
|
{
|
|
StartIdleTaskServer();
|
|
|
|
dwErr = ::RegisterIdleTask( ItHelpSvcDataCollectionTaskId, &m_dc_IdleHandle, &m_dc_IdleStart, &m_dc_IdleStop );
|
|
}
|
|
#endif
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, HRESULT_FROM_WIN32(dwErr));
|
|
|
|
lock = NULL; // Release lock before going into the Event code!!!
|
|
|
|
m_dc_EventStart.Attach( m_dc_IdleStart );
|
|
m_dc_EventStop .Attach( m_dc_IdleStop );
|
|
|
|
m_dc_EventStart.Set( INFINITE );
|
|
}
|
|
catch(...)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
void ServiceHandler_HelpSvc::IdleTask_Cleanup()
|
|
{
|
|
try
|
|
{
|
|
m_dc_EventStart.Attach( NULL );
|
|
m_dc_EventStop .Attach( NULL );
|
|
|
|
{
|
|
LocalSmartLock lock( &m_cs );
|
|
|
|
if(m_dc_IdleHandle)
|
|
{
|
|
::UnregisterIdleTask( m_dc_IdleHandle, m_dc_IdleStart, m_dc_IdleStop );
|
|
|
|
m_dc_IdleHandle = NULL;
|
|
m_dc_IdleStart = NULL;
|
|
m_dc_IdleStop = NULL;
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT ServiceHandler_HelpSvc::DataCollection_Queue()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "ServiceHandler_HelpSvc::DataCollection_Queue" );
|
|
|
|
MPC::wstring strValue;
|
|
bool fFound;
|
|
DWORD dwDelay = 10 * 1000;
|
|
|
|
if(SUCCEEDED(MPC::RegKey_Value_Read( strValue, fFound, s_szRoot, s_szDataCollection )) && fFound)
|
|
{
|
|
DATE dDate;
|
|
|
|
if(SUCCEEDED(MPC::ConvertStringToDate( strValue, dDate, /*fGMT*/false, /*fCIM*/true, 0 )))
|
|
{
|
|
const DATE c_OneDay = 1.0;
|
|
const DATE c_MillisecInOneDay = 24.0 * 60.0 * 60.0 * 1000.0;
|
|
|
|
DATE dDiff = c_OneDay - (MPC::GetLocalTime() - dDate);
|
|
|
|
//
|
|
// Wait at least six hours between DC.
|
|
//
|
|
if(dDiff > 0) dwDelay = dDiff * c_MillisecInOneDay;
|
|
}
|
|
}
|
|
|
|
m_dc_Timer.Set( dwDelay, 0 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT ServiceHandler_HelpSvc::DataCollection_Execute( /*[in]*/ bool fCancel )
|
|
{
|
|
if(!fCancel) ConnectToServer();
|
|
|
|
{
|
|
LocalSmartLock lock( &m_cs );
|
|
|
|
if(m_svc)
|
|
{
|
|
m_svc->TriggerScheduledDataCollection( fCancel ? VARIANT_FALSE : VARIANT_TRUE );
|
|
|
|
lock = NULL; // Release lock before going into the Timer code!!!
|
|
|
|
m_svc_Timer.Set( 60 * 1000, 0 );
|
|
}
|
|
}
|
|
|
|
m_dc_TimerRestart.Set( 1 * 1000, 0 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////
|
|
|
|
void ServiceHandler_HelpSvc::ConnectToServer()
|
|
{
|
|
{
|
|
LocalSmartLock lock( &m_cs );
|
|
|
|
if(!m_svc)
|
|
{
|
|
m_svc.CoCreateInstance( CLSID_PCHService );
|
|
}
|
|
}
|
|
|
|
m_svc_Timer.Set( 60 * 1000, 0 );
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT ServiceHandler_HelpSvc::ServiceShutdownCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
|
|
{
|
|
{
|
|
LocalSmartLock lock( &m_cs );
|
|
|
|
m_svc.Release();
|
|
}
|
|
|
|
DataCollection_Queue();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT ServiceHandler_HelpSvc::BatchCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
|
|
{
|
|
m_batch_Timer.Set( 5000, 0 );
|
|
|
|
{
|
|
LocalSmartLock lock( &m_cs );
|
|
|
|
::FindNextChangeNotification( m_batch_Notification );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT ServiceHandler_HelpSvc::BatchCallback2( /*[in]*/ BOOLEAN TimerOrWaitFired )
|
|
{
|
|
//
|
|
// If not already running, start it.
|
|
//
|
|
ConnectToServer();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
HRESULT ServiceHandler_HelpSvc::DataCollectionCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
|
|
{
|
|
MPC::wstring strDate;
|
|
|
|
if(FAILED(IdleTask_Initialize()))
|
|
{
|
|
DataCollection_Execute( /*fCancel*/false );
|
|
}
|
|
|
|
if(SUCCEEDED(MPC::ConvertDateToString( MPC::GetLocalTime(), strDate, /*fGMT*/false, /*fCIM*/true, 0 )))
|
|
{
|
|
(void)MPC::RegKey_Value_Write( strDate, s_szRoot, s_szDataCollection );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT ServiceHandler_HelpSvc::DataCollectionRestartCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
|
|
{
|
|
DataCollection_Queue();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT ServiceHandler_HelpSvc::IdleStartCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
|
|
{
|
|
m_dc_EventStart.Reset( );
|
|
m_dc_EventStop .Set ( INFINITE );
|
|
|
|
DataCollection_Execute( /*fCancel*/false );
|
|
|
|
|
|
IdleTask_Cleanup();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT ServiceHandler_HelpSvc::IdleStopCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
|
|
{
|
|
m_dc_EventStop .Reset( );
|
|
m_dc_EventStart.Set ( INFINITE );
|
|
|
|
DataCollection_Execute( /*fCancel*/true );
|
|
|
|
return S_OK;
|
|
}
|