mirror of https://github.com/tongzx/nt5src
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.
1646 lines
43 KiB
1646 lines
43 KiB
/*++
|
|
|
|
Copyright (C) 1999-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
RESYNC2.CPP
|
|
|
|
Abstract:
|
|
|
|
|
|
History:
|
|
|
|
ivanbrug 01-Oct-2000 changed for svchost migration
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <winntsec.h>
|
|
#include <malloc.h>
|
|
#include <tchar.h>
|
|
#include <initguid.h>
|
|
#include "WinMgmt.h"
|
|
#include <Wmistr.h>
|
|
#include <wmium.h>
|
|
#include <wmicom.h>
|
|
#include <wmimof.h>
|
|
#include "resync2.h"
|
|
#include "wbemdelta.h" // for DeltaDredge
|
|
#include "arrtempl.h"
|
|
|
|
//
|
|
//
|
|
// this is because WDMLib is __BADLY__ DESIGNED
|
|
//
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
void WINAPI EventCallbackRoutine(PWNODE_HEADER WnodeHeader, ULONG_PTR Context)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
//
|
|
// This class listens on WDM events
|
|
//
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
CWDMListener::CWDMListener():
|
|
m_dwSignature(SIG_WDMEVENTS_BUSY),
|
|
m_hEventAdd(NULL),
|
|
m_hEventRem(NULL),
|
|
m_hWaitAdd(NULL),
|
|
m_hWaitRem(NULL),
|
|
m_UnInited(TRUE),
|
|
m_GuidAdd(GUID_MOF_RESOURCE_ADDED_NOTIFICATION),
|
|
m_GuidRem(GUID_MOF_RESOURCE_REMOVED_NOTIFICATION)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
DWORD
|
|
CWDMListener::OpenAdd()
|
|
{
|
|
DWORD dwErr;
|
|
dwErr = WmiOpenBlock(&m_GuidAdd,
|
|
WMIGUID_NOTIFICATION | SYNCHRONIZE,
|
|
&m_hEventAdd);
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
|
|
if (RegisterWaitForSingleObject(&m_hWaitAdd,
|
|
m_hEventAdd,
|
|
CWDMListener::EvtCallBackAdd,
|
|
this,
|
|
INFINITE,
|
|
WT_EXECUTEONLYONCE))
|
|
{
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
|
|
// if here, some errors
|
|
CloseAdd();
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
CWDMListener::OpenRemove()
|
|
{
|
|
DWORD dwRet;
|
|
|
|
dwRet = WmiOpenBlock(&m_GuidRem,
|
|
WMIGUID_NOTIFICATION | SYNCHRONIZE,
|
|
&m_hEventRem);
|
|
if (ERROR_SUCCESS == dwRet)
|
|
{
|
|
if (RegisterWaitForSingleObject(&m_hWaitRem,
|
|
m_hEventRem,
|
|
CWDMListener::EvtCallBackRem,
|
|
this,
|
|
INFINITE,
|
|
WT_EXECUTEONLYONCE))
|
|
{
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
dwRet = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwRet = GetLastError();
|
|
}
|
|
|
|
CloseRemove();
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
DWORD
|
|
CWDMListener::CloseAdd()
|
|
{
|
|
if (m_hWaitAdd){
|
|
UnregisterWaitEx(m_hWaitAdd,NULL);
|
|
m_hWaitAdd = NULL;
|
|
}
|
|
if (m_hEventAdd){
|
|
WmiCloseBlock(m_hEventAdd);
|
|
m_hEventAdd = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
CWDMListener::CloseRemove()
|
|
{
|
|
if (m_hWaitRem){
|
|
UnregisterWaitEx(m_hWaitRem,NULL);
|
|
m_hWaitRem = NULL;
|
|
}
|
|
if (m_hEventRem){
|
|
WmiCloseBlock(m_hEventRem);
|
|
m_hEventRem = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
CWDMListener::Unregister()
|
|
{
|
|
CInCritSec ics(&m_cs);
|
|
|
|
if (m_UnInited)
|
|
return;
|
|
|
|
m_UnInited = TRUE;
|
|
m_dwSignature = SIG_WDMEVENTS_FREE;
|
|
|
|
CloseAdd();
|
|
CloseRemove();
|
|
}
|
|
|
|
CWDMListener::~CWDMListener()
|
|
{
|
|
Unregister();
|
|
}
|
|
|
|
DWORD
|
|
CWDMListener::Register()
|
|
{
|
|
CInCritSec ics(&m_cs);
|
|
|
|
if (!m_UnInited) // prevent multiple calls
|
|
return 0;
|
|
|
|
m_dwSignature = SIG_WDMEVENTS_BUSY;
|
|
|
|
if (ERROR_SUCCESS == OpenAdd() && ERROR_SUCCESS == OpenRemove())
|
|
{
|
|
// OK here
|
|
m_UnInited = FALSE;
|
|
}
|
|
else
|
|
{
|
|
m_dwSignature = SIG_WDMEVENTS_FREE;
|
|
m_UnInited = TRUE;
|
|
}
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
VOID NTAPI
|
|
CWDMListener::EvtCallBackAdd(VOID * pContext,BOOLEAN bTimerFired)
|
|
{
|
|
if (!GLOB_Monitor_IsRegistred())
|
|
{
|
|
return;
|
|
}
|
|
|
|
CWDMListener * pThis = (CWDMListener *)pContext;
|
|
|
|
if (SIG_WDMEVENTS_BUSY != pThis->m_dwSignature)
|
|
{
|
|
return;
|
|
};
|
|
|
|
if (pThis)
|
|
pThis->EvtCallThis(bTimerFired,Type_Added);
|
|
|
|
//
|
|
// we have process the WDM event
|
|
// since we are in the RtlpWorkerThread and
|
|
// we are registred with WT_EXECUTEONLYONCE
|
|
// REDO FROM START
|
|
//
|
|
{
|
|
CInCritSec ics(&pThis->m_cs);
|
|
if (ERROR_SUCCESS == pThis->CloseAdd())
|
|
{
|
|
pThis->OpenAdd();
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID NTAPI
|
|
CWDMListener::EvtCallBackRem(VOID * pContext,BOOLEAN bTimerFired)
|
|
{
|
|
if (!GLOB_Monitor_IsRegistred())
|
|
{
|
|
return;
|
|
}
|
|
|
|
CWDMListener * pThis = (CWDMListener *)pContext;
|
|
|
|
if (SIG_WDMEVENTS_BUSY != pThis->m_dwSignature)
|
|
{
|
|
return;
|
|
};
|
|
|
|
if (pThis)
|
|
pThis->EvtCallThis(bTimerFired,Type_Removed);
|
|
|
|
//
|
|
// we have process the WDM event
|
|
// since we are in the RtlpWorkerThread and
|
|
// we are registred with WT_EXECUTEONLYONCE
|
|
// REDO FROM START
|
|
//
|
|
{
|
|
CInCritSec ics(&pThis->m_cs);
|
|
if (ERROR_SUCCESS == pThis->CloseRemove())
|
|
{
|
|
pThis->OpenRemove();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
CWDMListener::EvtCallThis(BOOLEAN bTimerFired, int Type)
|
|
{
|
|
if (bTimerFired)
|
|
{
|
|
// never here
|
|
}
|
|
else
|
|
{
|
|
if (m_UnInited)
|
|
return;
|
|
|
|
DWORD dwRet;
|
|
if (Type_Added == Type)
|
|
{
|
|
dwRet = WmiReceiveNotifications(1,&m_hEventAdd,CWDMListener::WmiCallBack,(ULONG_PTR)this);
|
|
}
|
|
else if (Type_Removed == Type)
|
|
{
|
|
dwRet = WmiReceiveNotifications(1,&m_hEventRem,CWDMListener::WmiCallBack,(ULONG_PTR)this);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID WINAPI
|
|
CWDMListener::WmiCallBack(PWNODE_HEADER Wnode,
|
|
UINT_PTR NotificationContext)
|
|
{
|
|
|
|
CWDMListener * pThis = (CWDMListener *)NotificationContext;
|
|
|
|
#ifdef DEBUG_ADAP
|
|
|
|
WCHAR pszClsID[40];
|
|
StringFromGUID2(Wnode->Guid,pszClsID,40);
|
|
DBG_PRINTFA((pBuff,"Flag %08x ProvId %08x %p GUID %S\n",
|
|
Wnode->Flags,Wnode->ProviderId,(ULONG_PTR)Wnode->ClientContext,pszClsID));
|
|
if (WNODE_FLAG_ALL_DATA & Wnode->Flags)
|
|
{
|
|
WNODE_ALL_DATA * pAllData = (WNODE_ALL_DATA *)Wnode;
|
|
DWORD i;
|
|
for (i=0;i<pAllData->InstanceCount;i++)
|
|
{
|
|
WCHAR pTmpBuff[MAX_PATH+1];
|
|
pTmpBuff[MAX_PATH] = 0;
|
|
DWORD dwSize = (pAllData->OffsetInstanceDataAndLength[i].LengthInstanceData>MAX_PATH)?MAX_PATH:pAllData->OffsetInstanceDataAndLength[i].LengthInstanceData;
|
|
memcpy(pTmpBuff,(BYTE*)pAllData+pAllData->OffsetInstanceDataAndLength[i].OffsetInstanceData,dwSize);
|
|
DBG_PRINTFA((pBuff,"%d - %S\n",i,pTmpBuff));
|
|
//DEBUGTRACE((LOG_WMIADAP,"%d - %S\n",i,pTmpBuff));
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
#ifdef DBG
|
|
if (!HeapValidate(GetProcessHeap(),0,NULL))
|
|
{
|
|
DebugBreak();
|
|
}
|
|
if (!HeapValidate(CWin32DefaultArena::GetArenaHeap(),0,NULL))
|
|
{
|
|
DebugBreak();
|
|
}
|
|
#endif
|
|
|
|
CWMIBinMof WMIBinMof;
|
|
//=============================================================================
|
|
// Note: this combo will always succeed, as all the initialize is doing is
|
|
// setting a flag to FALSE and returning S_OK
|
|
//=============================================================================
|
|
if( SUCCEEDED( WMIBinMof.Initialize(NULL,FALSE)) )
|
|
{
|
|
if (WMIBinMof.BinaryMofEventChanged(Wnode))
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"---- WMIBinMof.BinaryMofEventChanged == CHANGED ----\n"));
|
|
#endif
|
|
ERRORTRACE((LOG_WMIADAP,"WDM event && WMIBinMof.BinaryMofEventChanged == TRUE\n"));
|
|
|
|
ResyncPerf(RESYNC_TYPE_WDMEVENT);
|
|
#ifdef DBG
|
|
if (!HeapValidate(GetProcessHeap(),0,NULL))
|
|
{
|
|
DebugBreak();
|
|
}
|
|
if (!HeapValidate(CWin32DefaultArena::GetArenaHeap(),0,NULL))
|
|
{
|
|
DebugBreak();
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"---- WMIBinMof.BinaryMofEventChanged == NOT CHANGED ----\n"));
|
|
#endif
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
CCounterEvts::CCounterEvts():
|
|
m_dwSignature(SIG_COUNTEEVENTS_BUSY),
|
|
m_LoadCtrEvent(NULL),
|
|
m_UnloadCtrEvent(NULL),
|
|
m_Uninited(TRUE),
|
|
m_WaitLoadCtr(NULL),
|
|
m_WaitUnloadCtr(NULL),
|
|
m_hWmiReverseAdapSetLodCtr(NULL),
|
|
m_hWmiReverseAdapLodCtrDone(NULL),
|
|
m_hPendingTasksStart(NULL),
|
|
m_hPendingTasksComplete(NULL)
|
|
{
|
|
}
|
|
|
|
DWORD g_LocalSystemSD[] = {
|
|
0x80040001, 0x00000014, 0x00000020, 0x00000000,
|
|
0x0000002c, 0x00000101, 0x05000000, 0x00000012,
|
|
0x00000101, 0x05000000, 0x00000012, 0x00300002,
|
|
0x00000001, 0x00140000, 0x001f0003, 0x00000101,
|
|
0x05000000, 0x00000012, 0x00000000, 0x00000000
|
|
};
|
|
|
|
//
|
|
// for testing purpose, allow administrators to use the event
|
|
//
|
|
DWORD g_LocalSystemAdminsSD[] = {
|
|
0x80040001, 0x00000014, 0x00000020, 0x00000000,
|
|
0x0000002c, 0x00000101, 0x05000000, 0x00000012,
|
|
0x00000101, 0x05000000, 0x00000012, 0x00340002,
|
|
0x00000002, 0x00140000, 0x001f0003, 0x00000101,
|
|
0x05000000, 0x00000012, 0x00180000, 0x001f0003,
|
|
0x00000201, 0x05000000, 0x00000020, 0x00000220
|
|
};
|
|
|
|
DWORD
|
|
CCounterEvts::Init()
|
|
{
|
|
if (!m_Uninited)
|
|
return 0;
|
|
|
|
m_LoadCtrEvent = CreateEvent(NULL, FALSE, FALSE,LOAD_CTR_EVENT_NAME);
|
|
if (m_LoadCtrEvent)
|
|
SetObjectAccess2(m_LoadCtrEvent);
|
|
else
|
|
goto end_fail;
|
|
|
|
m_UnloadCtrEvent = CreateEvent(NULL, FALSE, FALSE, UNLOAD_CTR_EVENT_NAME);
|
|
|
|
if (m_UnloadCtrEvent)
|
|
SetObjectAccess2(m_UnloadCtrEvent);
|
|
else
|
|
goto end_fail;
|
|
|
|
m_hWmiReverseAdapSetLodCtr = CreateEvent(NULL,FALSE,FALSE,REVERSE_DREDGE_EVENT_NAME_SET);
|
|
|
|
if (m_hWmiReverseAdapSetLodCtr)
|
|
SetObjectAccess2(m_hWmiReverseAdapSetLodCtr);
|
|
else
|
|
goto end_fail;
|
|
|
|
m_hWmiReverseAdapLodCtrDone = CreateEvent(NULL,FALSE,FALSE,REVERSE_DREDGE_EVENT_NAME_ACK);
|
|
if (m_hWmiReverseAdapLodCtrDone)
|
|
SetObjectAccess2(m_hWmiReverseAdapLodCtrDone);
|
|
else
|
|
goto end_fail;
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
//sa.lpSecurityDescriptor = (LPVOID)g_LocalSystemSD;
|
|
// test only
|
|
sa.lpSecurityDescriptor = (LPVOID)g_LocalSystemAdminsSD;
|
|
sa.bInheritHandle = FALSE;
|
|
|
|
m_hPendingTasksStart = CreateEvent(&sa,FALSE,FALSE,PENDING_TASK_START);
|
|
if (!m_hPendingTasksStart)
|
|
goto end_fail;
|
|
|
|
m_hPendingTasksComplete = CreateEvent(&sa,TRUE,TRUE,PENDING_TASK_COMPLETE);
|
|
if (!m_hPendingTasksComplete)
|
|
goto end_fail;
|
|
|
|
m_Uninited = FALSE;
|
|
return NO_ERROR;
|
|
|
|
end_fail:
|
|
return GetLastError();
|
|
}
|
|
|
|
VOID NTAPI
|
|
CCounterEvts::EvtCallBackLoad(VOID * pContext,BOOLEAN bTimerFired)
|
|
{
|
|
if (!GLOB_Monitor_IsRegistred())
|
|
{
|
|
return;
|
|
}
|
|
|
|
CCounterEvts * pCounter = (CCounterEvts *)pContext;
|
|
|
|
if (SIG_COUNTEEVENTS_BUSY != pCounter->m_dwSignature)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pCounter->CallBack(bTimerFired,Type_Load);
|
|
|
|
}
|
|
|
|
VOID NTAPI
|
|
CCounterEvts::EvtCallBackUnload(VOID * pContext,BOOLEAN bTimerFired)
|
|
{
|
|
if (!GLOB_Monitor_IsRegistred())
|
|
{
|
|
return;
|
|
}
|
|
|
|
CCounterEvts * pCounter = (CCounterEvts *)pContext;
|
|
|
|
if (SIG_COUNTEEVENTS_BUSY != pCounter->m_dwSignature)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pCounter->CallBack(bTimerFired,Type_Unload);
|
|
|
|
}
|
|
|
|
VOID NTAPI
|
|
CCounterEvts::EvtCallBackPendingTask(VOID * pContext,BOOLEAN bTimerFired)
|
|
{
|
|
if (!GLOB_Monitor_IsRegistred())
|
|
{
|
|
return;
|
|
}
|
|
|
|
CCounterEvts * pCounter = (CCounterEvts *)pContext;
|
|
|
|
if (SIG_COUNTEEVENTS_BUSY != pCounter->m_dwSignature)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pCounter->CallBackPending(bTimerFired);
|
|
|
|
}
|
|
|
|
VOID
|
|
CCounterEvts::CallBack(BOOLEAN bTimerFired,int Type)
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"CallBack with type %d called\n",Type));
|
|
#endif
|
|
|
|
if (GLOB_IsResyncAllowed())
|
|
{
|
|
DWORD dwRet = WaitForSingleObject(m_hWmiReverseAdapSetLodCtr,0);
|
|
if (WAIT_OBJECT_0 == dwRet)
|
|
{
|
|
// this is the hack not to spawn a Delta Dredge when there is before a Reverese Dredge
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff," - SetEvent(m_hWmiReverseAdapLodCtrDone);\n"));
|
|
#endif
|
|
SetEvent(m_hWmiReverseAdapLodCtrDone);
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff," - ResyncPerf(RESYNC_TYPE_LODCTR);\n"));
|
|
#endif
|
|
ResyncPerf(RESYNC_TYPE_LODCTR);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CCounterEvts::CallBackPending(BOOLEAN bTimerFired)
|
|
{
|
|
if (GLOB_IsResyncAllowed())
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff," - PendingTask Start set\n"));
|
|
#endif
|
|
ResyncPerf(RESYNC_TYPE_PENDING_TASKS);
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
CCounterEvts::Register()
|
|
{
|
|
m_dwSignature = SIG_COUNTEEVENTS_BUSY;
|
|
|
|
BOOL LoadUnloadOK = FALSE;
|
|
if (RegisterWaitForSingleObject(&m_WaitLoadCtr,
|
|
m_LoadCtrEvent,
|
|
CCounterEvts::EvtCallBackLoad,
|
|
this,
|
|
INFINITE,
|
|
WT_EXECUTEDEFAULT)) // automatic reset
|
|
{
|
|
if(RegisterWaitForSingleObject(&m_WaitUnloadCtr,
|
|
m_UnloadCtrEvent,
|
|
CCounterEvts::EvtCallBackUnload,
|
|
this,
|
|
INFINITE,
|
|
WT_EXECUTEDEFAULT)) // automatic reset
|
|
{
|
|
LoadUnloadOK = TRUE;
|
|
}
|
|
else
|
|
{
|
|
UnregisterWaitEx(m_WaitLoadCtr,NULL);
|
|
m_WaitLoadCtr = NULL;
|
|
}
|
|
}
|
|
|
|
if (LoadUnloadOK &&
|
|
RegisterWaitForSingleObject(&m_hWaitPendingTasksStart,
|
|
m_hPendingTasksStart,
|
|
CCounterEvts::EvtCallBackPendingTask,
|
|
this,
|
|
INFINITE,
|
|
WT_EXECUTEDEFAULT))
|
|
{
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
UnregisterWaitEx(m_WaitLoadCtr,NULL);
|
|
m_WaitLoadCtr = NULL;
|
|
UnregisterWaitEx(m_WaitUnloadCtr,NULL);
|
|
m_WaitUnloadCtr = NULL;
|
|
}
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
CCounterEvts::Unregister()
|
|
{
|
|
m_dwSignature = SIG_COUNTEEVENTS_FREE;
|
|
|
|
if (m_WaitLoadCtr)
|
|
{
|
|
UnregisterWaitEx(m_WaitLoadCtr,NULL);
|
|
m_WaitLoadCtr = NULL;
|
|
}
|
|
if (m_WaitUnloadCtr)
|
|
{
|
|
UnregisterWaitEx(m_WaitUnloadCtr,NULL);
|
|
m_WaitUnloadCtr = NULL;
|
|
}
|
|
if (m_hWaitPendingTasksStart)
|
|
{
|
|
UnregisterWaitEx(m_hWaitPendingTasksStart,NULL);
|
|
m_hWaitPendingTasksStart = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
VOID
|
|
CCounterEvts::UnInit()
|
|
{
|
|
if (!m_Uninited)
|
|
return;
|
|
|
|
if(m_LoadCtrEvent) {
|
|
CloseHandle(m_LoadCtrEvent);
|
|
m_LoadCtrEvent = NULL;
|
|
}
|
|
if(m_UnloadCtrEvent)
|
|
{
|
|
CloseHandle(m_UnloadCtrEvent);
|
|
m_UnloadCtrEvent = NULL;
|
|
}
|
|
if (m_hWmiReverseAdapSetLodCtr)
|
|
{
|
|
CloseHandle(m_hWmiReverseAdapSetLodCtr);
|
|
m_hWmiReverseAdapSetLodCtr = NULL;
|
|
}
|
|
if (m_hWmiReverseAdapLodCtrDone)
|
|
{
|
|
CloseHandle(m_hWmiReverseAdapLodCtrDone);
|
|
m_hWmiReverseAdapLodCtrDone = NULL;
|
|
}
|
|
if (m_hPendingTasksStart)
|
|
{
|
|
CloseHandle(m_hPendingTasksStart);
|
|
m_hPendingTasksStart = NULL;
|
|
}
|
|
if (m_hPendingTasksComplete)
|
|
{
|
|
CloseHandle(m_hPendingTasksComplete);
|
|
m_hPendingTasksComplete = NULL;
|
|
}
|
|
m_Uninited = TRUE;
|
|
}
|
|
|
|
CCounterEvts::~CCounterEvts()
|
|
{
|
|
if (!m_Uninited)
|
|
UnInit();
|
|
|
|
m_dwSignature = SIG_COUNTEEVENTS_FREE;
|
|
}
|
|
|
|
//
|
|
// this is the main abstraction
|
|
// the child classes will call the ResyncPerf function,
|
|
// as long as the CWbemServices write hook.
|
|
// The ResyncPerf function will grab the global monitor
|
|
// and register a Timer Callback
|
|
// the gate will be implemented in the GetAvailable function
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
CMonitorEvents::CMonitorEvents():
|
|
m_bInit(FALSE),
|
|
m_bRegistred(FALSE)
|
|
{
|
|
InitializeCriticalSection(&m_cs);
|
|
};
|
|
|
|
CMonitorEvents::~CMonitorEvents()
|
|
{
|
|
DeleteCriticalSection(&m_cs);
|
|
}
|
|
|
|
|
|
BOOL WINAPI
|
|
CMonitorEvents::MonitorCtrlHandler( DWORD dwCtrlType )
|
|
{
|
|
BOOL bRet = FALSE;
|
|
switch(dwCtrlType)
|
|
{
|
|
case CTRL_SHUTDOWN_EVENT:
|
|
|
|
GLOB_GetMonitor()->m_WDMListener.Unregister();
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"WDM Handles closed\n"));
|
|
#endif
|
|
bRet = TRUE;
|
|
break;
|
|
default:
|
|
bRet = FALSE;
|
|
};
|
|
return bRet;
|
|
};
|
|
|
|
|
|
BOOL
|
|
CMonitorEvents::Init()
|
|
{
|
|
|
|
if (m_bInit)
|
|
return TRUE;
|
|
|
|
Lock();
|
|
|
|
if (m_bInit)
|
|
{
|
|
Unlock();
|
|
return TRUE;
|
|
}
|
|
|
|
m_dwSig = 'VEOM';
|
|
m_CntsEvts.Init();
|
|
m_dwADAPDelaySec = WMIADAP_DEFAULT_DELAY;
|
|
m_dwLodCtrDelaySec = WMIADAP_DEFAULT_DELAY_LODCTR;
|
|
m_dwTimeToFull = WMIADAP_DEFAULT_TIMETOFULL;
|
|
m_dwTimeToKillAdap = MAX_PROCESS_WAIT;
|
|
|
|
memset(&m_FileTime,0,sizeof(m_FileTime));
|
|
|
|
RegRead();
|
|
|
|
for (DWORD i=0;i<RESYNC_TYPE_MAX;i++)
|
|
{
|
|
m_ResyncTasks[i].dwSig = SIG_RESYNC_PERF;
|
|
m_ResyncTasks[i].bFree = TRUE;
|
|
m_ResyncTasks[i].pMonitor = this;
|
|
m_ResyncTasks[i].hTimer = NULL;
|
|
m_ResyncTasks[i].hWaitHandle = NULL;
|
|
m_ResyncTasks[i].hProcess = NULL;
|
|
m_ResyncTasks[i].Enabled = TRUE;
|
|
}
|
|
|
|
//m_ResyncTasks[RESYNC_TYPE_LODCTR].CmdType // to be decided by DeltaDredge
|
|
m_ResyncTasks[RESYNC_TYPE_INITIAL].dwTimeDue = (m_dwADAPDelaySec)*1000;
|
|
|
|
m_ResyncTasks[RESYNC_TYPE_LODCTR].CmdType = RESYNC_DELTA_THROTTLE;
|
|
m_ResyncTasks[RESYNC_TYPE_LODCTR].dwTimeDue = (m_dwLodCtrDelaySec)*1000;
|
|
|
|
// //RESYNC_TYPE_CLASSCREATION is the same
|
|
m_ResyncTasks[RESYNC_TYPE_WDMEVENT].CmdType = RESYNC_RADAPD_THROTTLE;
|
|
m_ResyncTasks[RESYNC_TYPE_WDMEVENT].dwTimeDue = (m_dwLodCtrDelaySec)*1000;
|
|
|
|
m_ResyncTasks[RESYNC_TYPE_PENDING_TASKS].CmdType = RESYNC_FULL_RADAPD_NOTHROTTLE;
|
|
m_ResyncTasks[RESYNC_TYPE_PENDING_TASKS].dwTimeDue = 500; // hard coded
|
|
|
|
//
|
|
// set up the console handler
|
|
//
|
|
SetConsoleCtrlHandler( MonitorCtrlHandler, TRUE );
|
|
|
|
//
|
|
// let's asses some initial state for the IdleTask business
|
|
//
|
|
m_OutStandingProcesses = 0;
|
|
m_bFullReverseNeeded = FALSE;
|
|
|
|
m_bInit = TRUE;
|
|
|
|
Unlock();
|
|
|
|
return TRUE;
|
|
};
|
|
|
|
|
|
BOOL
|
|
CMonitorEvents::Uninit()
|
|
{
|
|
if (!m_bInit)
|
|
return TRUE;
|
|
|
|
Lock();
|
|
|
|
if (!m_bInit)
|
|
{
|
|
Unlock();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
for (DWORD i=0;i<RESYNC_TYPE_MAX;i++)
|
|
{
|
|
if (m_ResyncTasks[i].hTimer)
|
|
{
|
|
DeleteTimerQueueTimer(NULL,m_ResyncTasks[i].hTimer,NULL);
|
|
m_ResyncTasks[i].hTimer = NULL;
|
|
}
|
|
if (m_ResyncTasks[i].hWaitHandle)
|
|
{
|
|
UnregisterWaitEx(m_ResyncTasks[i].hWaitHandle,NULL);
|
|
m_ResyncTasks[i].hWaitHandle = NULL;
|
|
}
|
|
if (m_ResyncTasks[i].hProcess)
|
|
{
|
|
CloseHandle(m_ResyncTasks[i].hProcess);
|
|
m_ResyncTasks[i].hProcess = NULL;
|
|
}
|
|
m_ResyncTasks[i].dwSig = (DWORD)'eerf';
|
|
}
|
|
|
|
m_CntsEvts.UnInit();
|
|
|
|
//
|
|
// tear-down the console handler
|
|
//
|
|
SetConsoleCtrlHandler( MonitorCtrlHandler, FALSE );
|
|
|
|
m_bInit = FALSE;
|
|
m_dwSig = 'veom';
|
|
|
|
Unlock();
|
|
|
|
return TRUE;
|
|
};
|
|
|
|
|
|
//
|
|
//
|
|
// called in the running/continue
|
|
//
|
|
/////////////
|
|
|
|
DWORD
|
|
CMonitorEvents::Register()
|
|
{
|
|
m_CntsEvts.Register();
|
|
m_WDMListener.Register();
|
|
|
|
m_bRegistred = TRUE;
|
|
|
|
return 0;
|
|
};
|
|
|
|
//
|
|
//
|
|
// called in the pause/stop
|
|
//
|
|
//////////////////////////////////////////////////////////
|
|
|
|
DWORD
|
|
CMonitorEvents::Unregister(BOOL bIsSystemShutDown)
|
|
{
|
|
|
|
m_bRegistred = FALSE;
|
|
|
|
if (!bIsSystemShutDown)
|
|
{
|
|
m_CntsEvts.Unregister();
|
|
m_WDMListener.Unregister();
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
//
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
|
|
VOID
|
|
CMonitorEvents::RegRead()
|
|
{
|
|
// Read the initialization information
|
|
|
|
LONG lRet;
|
|
HKEY hKey;
|
|
DWORD dwTemp;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
_T("Software\\Microsoft\\WBEM\\CIMOM"),
|
|
NULL,
|
|
KEY_READ|KEY_WRITE,
|
|
&hKey);
|
|
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwSize = sizeof(DWORD);
|
|
lRet = RegQueryValueEx(hKey,
|
|
_T("ADAPDelay"),
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)&m_dwADAPDelaySec,
|
|
&dwSize);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
//This is what we want
|
|
}
|
|
else if ( ERROR_FILE_NOT_FOUND == lRet )
|
|
{
|
|
dwTemp = WMIADAP_DEFAULT_DELAY;
|
|
RegSetValueEx(hKey,
|
|
_T("ADAPDelay"),
|
|
NULL,
|
|
REG_DWORD,
|
|
(BYTE *)&dwTemp,
|
|
sizeof(DWORD));
|
|
}
|
|
else
|
|
{
|
|
// Error
|
|
ERRORTRACE( ( LOG_WINMGMT, "ResyncPerf experienced an error while attempting to read the WMIADAPDelay value in the CIMOM subkey. Continuing using a default value.\n" ) );
|
|
}
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
_T("LodCtrDelay"),
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)&m_dwLodCtrDelaySec,
|
|
&dwSize);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
//This is what we want
|
|
}
|
|
else if ( ERROR_FILE_NOT_FOUND == lRet )
|
|
{
|
|
dwTemp = WMIADAP_DEFAULT_DELAY_LODCTR;
|
|
RegSetValueEx(hKey,
|
|
_T("LodCtrDelay"),
|
|
NULL,
|
|
REG_DWORD,
|
|
(BYTE *)&dwTemp,
|
|
sizeof(DWORD));
|
|
}
|
|
else
|
|
{
|
|
// Error
|
|
ERRORTRACE( ( LOG_WINMGMT, "ResyncPerf experienced an error while attempting to read the WMIADAPDelay value in the CIMOM subkey. Continuing using a default value.\n" ) );
|
|
}
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
ADAP_TIME_TO_FULL,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)&m_dwTimeToFull,
|
|
&dwSize);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
//This is what we want
|
|
}
|
|
else if ( ERROR_FILE_NOT_FOUND == lRet )
|
|
{
|
|
dwTemp = WMIADAP_DEFAULT_TIMETOFULL;
|
|
RegSetValueEx(hKey,
|
|
ADAP_TIME_TO_FULL,
|
|
NULL,
|
|
REG_DWORD,
|
|
(BYTE *)&dwTemp,
|
|
sizeof(DWORD));
|
|
}
|
|
else
|
|
{
|
|
// Error
|
|
ERRORTRACE( ( LOG_WINMGMT, "ResyncPerf experienced an error while attempting to read the WMIADAPDelay value in the CIMOM subkey. Continuing using a default value.\n" ) );
|
|
}
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
ADAP_TIME_TO_KILL_ADAP,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)&m_dwTimeToKillAdap,
|
|
&dwSize);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
//This is what we want
|
|
}
|
|
else if ( ERROR_FILE_NOT_FOUND == lRet )
|
|
{
|
|
dwTemp = MAX_PROCESS_WAIT;
|
|
RegSetValueEx(hKey,
|
|
ADAP_TIME_TO_KILL_ADAP,
|
|
NULL,
|
|
REG_DWORD,
|
|
(BYTE *)&dwTemp,
|
|
sizeof(DWORD));
|
|
}
|
|
else
|
|
{
|
|
// Error
|
|
ERRORTRACE( ( LOG_WINMGMT, "ResyncPerf experienced an error while attempting to read the %S value in the CIMOM subkey. Continuing using a default value.\n",ADAP_TIME_TO_KILL_ADAP));
|
|
}
|
|
|
|
//ADAP_TIMESTAMP_FULL
|
|
dwSize = sizeof(FILETIME);
|
|
lRet = RegQueryValueEx(hKey,
|
|
ADAP_TIMESTAMP_FULL,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)&m_FileTime,
|
|
&dwSize);
|
|
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
{
|
|
// Error
|
|
ERRORTRACE( ( LOG_WINMGMT, "ResyncPerf could not open the CIMOM subkey to read initialization data. Continuing using a default value.\n" ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////
|
|
|
|
ResyncPerfTask *
|
|
CMonitorEvents::GetAvailable(DWORD dwReason)
|
|
{
|
|
ResyncPerfTask * pPerf = NULL;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
if (m_ResyncTasks[dwReason].bFree)
|
|
{
|
|
m_ResyncTasks[dwReason].bFree = FALSE;
|
|
m_ResyncTasks[dwReason].Type = dwReason;
|
|
pPerf = &m_ResyncTasks[dwReason];
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
return pPerf;
|
|
}
|
|
|
|
TCHAR * g_Strings[] = {
|
|
_T("/F /T"), // FULL Throttle
|
|
_T("/D /T"), // DELTA Throttle
|
|
_T("/R /T"), // REVERSE_ADAPTER Throttle
|
|
_T("/F /R /T"), // FULL REVERSE_ADAPTER Throttle
|
|
_T("/D /R /T"), // DELTA REVERSE_ADAPTER Throttle
|
|
_T("/F /R") // FULL REVERSE no Throttle
|
|
};
|
|
|
|
void inline DoUnThrottleDredges()
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"DoUnThrottleDredges\n"));
|
|
#endif
|
|
RegSetDWORD(HKEY_LOCAL_MACHINE,HOME_REG_PATH,DO_THROTTLE,0);
|
|
return;
|
|
}
|
|
|
|
void inline DoThrottleDredges()
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"DoThrottleDredges\n"));
|
|
#endif
|
|
RegSetDWORD(HKEY_LOCAL_MACHINE,HOME_REG_PATH,DO_THROTTLE,1);
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
CMonitorEvents::CreateProcess_(TCHAR * pCmdLine,
|
|
CMonitorEvents * pMonitor,
|
|
ResyncPerfTask * pPerf)
|
|
{
|
|
BOOL bRes = FALSE;
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION ProcInfo;
|
|
memset(&si,0,sizeof(STARTUPINFO));
|
|
si.cb = sizeof(STARTUPINFO);
|
|
si.dwFlags = STARTF_FORCEOFFFEEDBACK;
|
|
|
|
// Get the appropriate cmdline and attach the proper command line switches
|
|
LPTSTR pWriteableBuff = GetWMIADAPCmdLine( 64 );
|
|
CVectorDeleteMe<TCHAR> vdm( pWriteableBuff );
|
|
|
|
if ( NULL == pWriteableBuff )
|
|
{
|
|
ERRORTRACE((LOG_WINMGMT,"Memory Allocation error spawning dredger!\n"));
|
|
pMonitor->Lock();
|
|
pPerf->bFree = TRUE;
|
|
pMonitor->Unlock();
|
|
return bRes;
|
|
}
|
|
|
|
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"Creating process: %S\n",pCmdLine));
|
|
#endif
|
|
DEBUGTRACE((LOG_WMIADAP,"Creating process: %S\n",pCmdLine));
|
|
|
|
bRes = CreateProcess(pWriteableBuff,
|
|
pCmdLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
CREATE_NO_WINDOW,
|
|
NULL,
|
|
NULL,
|
|
&si,
|
|
&ProcInfo);
|
|
if (bRes)
|
|
{
|
|
CloseHandle(ProcInfo.hThread);
|
|
|
|
pPerf->hProcess = ProcInfo.hProcess;
|
|
|
|
if (RegisterWaitForSingleObject(&pPerf->hWaitHandle,
|
|
pPerf->hProcess,
|
|
CMonitorEvents::EventCallBack,
|
|
pPerf,
|
|
pMonitor->m_dwTimeToKillAdap,
|
|
WT_EXECUTEONLYONCE|WT_EXECUTEINWAITTHREAD))
|
|
{
|
|
//
|
|
// we don't need to free the slot,
|
|
// because the event callback will do that
|
|
//
|
|
}
|
|
else
|
|
{
|
|
DEBUGTRACE((LOG_WMIADAP,"Unable to schedule WmiADAP process termination handler: err %d\n",GetLastError()));
|
|
CloseHandle(pPerf->hProcess);
|
|
pPerf->hProcess = NULL;
|
|
pMonitor->Lock();
|
|
pPerf->bFree = TRUE;
|
|
pMonitor->Unlock();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WINMGMT,"CreatProcess %S err: %d\n",pWriteableBuff,GetLastError()));
|
|
pMonitor->Lock();
|
|
pPerf->bFree = TRUE;
|
|
pMonitor->Unlock();
|
|
}
|
|
return bRes;
|
|
}
|
|
|
|
VOID NTAPI
|
|
CMonitorEvents::EventCallBack(VOID * pContext,BOOLEAN bTimerFired)
|
|
{
|
|
if (!GLOB_Monitor_IsRegistred())
|
|
{
|
|
return;
|
|
}
|
|
|
|
ResyncPerfTask * pPerf = (ResyncPerfTask *)pContext;
|
|
|
|
if (!pPerf || (SIG_RESYNC_PERF != pPerf->dwSig))
|
|
{
|
|
return;
|
|
}
|
|
|
|
CMonitorEvents * pMonitor = pPerf->pMonitor;
|
|
HANDLE hProcess = pPerf->hProcess;
|
|
|
|
if(bTimerFired)
|
|
{
|
|
//
|
|
// The LONG time-out for our process has expired
|
|
// Kill The Process
|
|
//
|
|
TerminateProcess(pPerf->hProcess,0);
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"WmiADAP did not finish within %d msec\n",pMonitor->m_dwTimeToKillAdap));
|
|
#endif
|
|
ERRORTRACE((LOG_WMIADAP,"the ResyncTask of type %d timed-out and has been killed\n",pPerf->Type));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// the handle has been signaled, meaning that
|
|
// the process exited normally
|
|
//
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"ResyncPerf for task %d completed\n",pPerf->Type));
|
|
#endif
|
|
}
|
|
|
|
CloseHandle(pPerf->hProcess);
|
|
//
|
|
// if there was a call to ProcessIdleTasks
|
|
// if we were forced to unthrottle the running tasks
|
|
// revert back
|
|
//
|
|
if (RESYNC_TYPE_PENDING_TASKS == pPerf->Type)
|
|
{
|
|
pMonitor->m_bFullReverseNeeded = FALSE;
|
|
DoThrottleDredges();
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"Setting the WMI_ProcessIdleTasksComplete\n"));
|
|
#endif
|
|
if (GLOB_GetMonitor()->IsRegistred())
|
|
SetEvent(GLOB_GetMonitor()->GetTaskCompleteEvent());
|
|
}
|
|
else // a process has exited or it has been terminated
|
|
{
|
|
LONG nProc = InterlockedDecrement(&pMonitor->m_OutStandingProcesses);
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"(-) Outstanding Tasks %d\n",pMonitor->m_OutStandingProcesses));
|
|
#endif
|
|
if (0 == nProc &&
|
|
pMonitor->m_bFullReverseNeeded)
|
|
{
|
|
// Create Here the process
|
|
CMonitorEvents * pMonitor = GLOB_GetMonitor();
|
|
ResyncPerfTask * pPerfTask = pMonitor->GetAvailable(RESYNC_TYPE_PENDING_TASKS);
|
|
if (pPerfTask)
|
|
{
|
|
TCHAR pCmdLine[64];
|
|
_tcscpy(pCmdLine,_T("wmiadap.exe "));
|
|
_tcscat(pCmdLine,g_Strings[pPerfTask->CmdType]);
|
|
CMonitorEvents::CreateProcess_(pCmdLine,pMonitor,pPerfTask);
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"GetAvailable(RESYNC_TYPE_PENDING_TASKS) returned NULL\n"));
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
pPerf->hProcess = NULL;
|
|
pMonitor->Lock();
|
|
pPerf->bFree = TRUE;
|
|
pMonitor->Unlock();
|
|
|
|
UnregisterWaitEx(pPerf->hWaitHandle,NULL);
|
|
pPerf->hWaitHandle = NULL;
|
|
|
|
}
|
|
|
|
VOID NTAPI
|
|
CMonitorEvents::TimerCallBack(VOID * pContext,BOOLEAN bTimerFired)
|
|
{
|
|
if (!GLOB_Monitor_IsRegistred())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(bTimerFired)
|
|
{
|
|
ResyncPerfTask * pPerf = (ResyncPerfTask *)pContext;
|
|
CMonitorEvents * pMonitor = pPerf->pMonitor;
|
|
BOOL bFreeSlot = FALSE;
|
|
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"TIMER: Command Type %x\n",pPerf->Type));
|
|
#endif
|
|
|
|
if (!pPerf->Enabled)
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"Task %d was disabled on the fly\n",pPerf->Type));
|
|
#endif
|
|
bFreeSlot = TRUE;
|
|
goto unregister_timer;
|
|
}
|
|
|
|
BOOL bDoSomething = TRUE;
|
|
BOOL RunDeltaLogic = TRUE;
|
|
BOOL AddReverseAdapter = FALSE;
|
|
BOOL WDMTriggeredReverseAdapter = FALSE;
|
|
BOOL bDoFullSystemReverseHere = FALSE;
|
|
|
|
if (RESYNC_TYPE_PENDING_TASKS == pPerf->Type)
|
|
{
|
|
pMonitor->Lock();
|
|
// here disable tasks that are on the wait list
|
|
for (DWORD i=0;i<RESYNC_TYPE_MAX;i++)
|
|
{
|
|
if (RESYNC_TYPE_PENDING_TASKS != i)
|
|
{
|
|
if (pMonitor->m_ResyncTasks[i].hTimer)
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"Disabling the pending task %d\n",i));
|
|
#endif
|
|
pMonitor->m_ResyncTasks[i].Enabled = FALSE;
|
|
}
|
|
}
|
|
}
|
|
pMonitor->Unlock();
|
|
// now check if the are processes running
|
|
DoUnThrottleDredges();
|
|
if (pMonitor->m_OutStandingProcesses)
|
|
{
|
|
pMonitor->m_bFullReverseNeeded = TRUE;
|
|
// no need to CreateProcess, the last outstanding process will do that
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"OutStandingProcess, no CreateProcessHere\n"));
|
|
#endif
|
|
bFreeSlot = TRUE;
|
|
goto unregister_timer;
|
|
}
|
|
else // no processes outstanding, create the process now
|
|
{
|
|
bDoFullSystemReverseHere = TRUE;
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"GOTO CreateProcess\n"));
|
|
#endif
|
|
goto createprocess_label;
|
|
}
|
|
}
|
|
|
|
if (RESYNC_TYPE_INITIAL == pPerf->Type )
|
|
{
|
|
// check if the Reverse Adapters need a Delta
|
|
|
|
LONG lRet;
|
|
HKEY hKey;
|
|
DWORD dwTemp;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
WBEM_REG_REVERSE_KEY,
|
|
NULL,
|
|
KEY_READ|KEY_WRITE,
|
|
&hKey);
|
|
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwSize = sizeof(DWORD);
|
|
DWORD dwVal;
|
|
lRet = RegQueryValueEx(hKey,
|
|
WBEM_REG_REVERSE_VALUE,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)&dwVal,
|
|
&dwSize);
|
|
|
|
// if the key is there, is NULL and it is of the right type
|
|
// OR if the key is not there
|
|
if( ERROR_SUCCESS == lRet &&
|
|
REG_DWORD == dwType &&
|
|
dwVal )
|
|
{
|
|
AddReverseAdapter = TRUE;
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"\"Performance Refresh\" key set to %d\n",dwVal));
|
|
#endif
|
|
DEBUGTRACE((LOG_WMIADAP,"\"Performance Refresh\" key set to %d\n",dwVal));
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
// check the WDM stuff
|
|
if (!AddReverseAdapter)
|
|
{
|
|
#ifdef DBG
|
|
if (!HeapValidate(GetProcessHeap(),0,NULL))
|
|
{
|
|
DebugBreak();
|
|
}
|
|
if (!HeapValidate(CWin32DefaultArena::GetArenaHeap(),0,NULL))
|
|
{
|
|
DebugBreak();
|
|
}
|
|
#endif
|
|
|
|
CWMIBinMof BinMof;
|
|
//=============================================================================
|
|
// Note: this combo will always succeed, as all the initialize is doing is
|
|
// setting a flag to FALSE and returning S_OK
|
|
//=============================================================================
|
|
if( SUCCEEDED( BinMof.Initialize(NULL,FALSE) ) )
|
|
{
|
|
WDMTriggeredReverseAdapter = BinMof.BinaryMofsHaveChanged();
|
|
if (WDMTriggeredReverseAdapter)
|
|
{
|
|
// override the previous decition
|
|
AddReverseAdapter = TRUE;
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"BinaryMofs DO HAVE changed\n"));
|
|
#endif
|
|
DEBUGTRACE((LOG_WMIADAP,"CWMIBinMof.BinaryMofsHaveChanged == TRUE\n"));
|
|
}
|
|
|
|
#ifdef DBG
|
|
if (!HeapValidate(GetProcessHeap(),0,NULL))
|
|
{
|
|
DebugBreak();
|
|
}
|
|
if (!HeapValidate(CWin32DefaultArena::GetArenaHeap(),0,NULL))
|
|
{
|
|
DebugBreak();
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// overrides delta with full, if the case
|
|
if (WMIADAP_DEFAULT_TIMETOFULL == pMonitor->GetFullTime())
|
|
{
|
|
// no override
|
|
}
|
|
else // read timestamp and decide
|
|
{
|
|
ULARGE_INTEGER li;
|
|
li.LowPart = pMonitor->GetTimeStamp().dwLowDateTime;
|
|
li.HighPart = pMonitor->GetTimeStamp().dwHighDateTime;
|
|
__int64 Seconds = pMonitor->GetFullTime();
|
|
Seconds *= 10000000; // number of 100ns units in 1 second
|
|
|
|
ULARGE_INTEGER liNow;
|
|
GetSystemTimeAsFileTime((FILETIME *)&liNow);
|
|
|
|
if ((li.QuadPart + Seconds) < liNow.QuadPart)
|
|
{
|
|
pPerf->CmdType = RESYNC_FULL_THROTTLE;
|
|
RunDeltaLogic = FALSE;
|
|
}
|
|
}
|
|
} // end if command type initial
|
|
|
|
if ((RESYNC_TYPE_INITIAL == pPerf->Type) && RunDeltaLogic)
|
|
{
|
|
DWORD ret = DeltaDredge2(0,NULL);
|
|
// DBG_PRINTFA((pBuff,"DeltaDredge ret %d\n",ret));
|
|
switch(ret)
|
|
{
|
|
case FULL_DREDGE:
|
|
pPerf->CmdType = RESYNC_FULL_THROTTLE;
|
|
break;
|
|
case PARTIAL_DREDGE:
|
|
pPerf->CmdType = RESYNC_DELTA_THROTTLE;
|
|
break;
|
|
case NO_DREDGE:
|
|
//
|
|
// this is the case where we do nothing
|
|
ERRORTRACE((LOG_WINMGMT,"No Dredge to run\n"));
|
|
//
|
|
bDoSomething = FALSE;
|
|
break;
|
|
default:
|
|
//
|
|
// never here
|
|
//
|
|
break;
|
|
}
|
|
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"DeltaDredge() ret = %d, bDoSomething = %d \n",ret,bDoSomething));
|
|
#endif
|
|
DEBUGTRACE((LOG_WMIADAP,"DeltaDredge() ret = %d, bDoSomething = %d \n",ret,bDoSomething));
|
|
}
|
|
|
|
if (bDoSomething || AddReverseAdapter)
|
|
{
|
|
createprocess_label:
|
|
TCHAR pCmdLine[64];
|
|
_tcscpy(pCmdLine,_T("wmiadap.exe "));
|
|
|
|
if (bDoFullSystemReverseHere)
|
|
{
|
|
_tcscat(pCmdLine,g_Strings[pPerf->CmdType]);
|
|
}
|
|
else
|
|
{
|
|
if (bDoSomething && AddReverseAdapter)
|
|
{
|
|
_tcscat(pCmdLine,g_Strings[pPerf->CmdType]);
|
|
_tcscat(pCmdLine,_T(" /R"));
|
|
}
|
|
if (bDoSomething && !AddReverseAdapter)
|
|
{
|
|
_tcscat(pCmdLine,g_Strings[pPerf->CmdType]);
|
|
}
|
|
if (!bDoSomething && AddReverseAdapter)
|
|
{
|
|
_tcscat(pCmdLine,g_Strings[RESYNC_RADAPD_THROTTLE]);
|
|
}
|
|
}
|
|
CMonitorEvents::CreateProcess_(pCmdLine,pMonitor,pPerf);
|
|
|
|
if (GLOB_GetMonitor()->IsRegistred())
|
|
{
|
|
if (!bDoFullSystemReverseHere)
|
|
{
|
|
InterlockedIncrement(&(GLOB_GetMonitor()->m_OutStandingProcesses));
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"(+) Outstanding Tasks %d\n",GLOB_GetMonitor()->m_OutStandingProcesses));
|
|
#endif
|
|
}
|
|
//ResetEvent(GLOB_GetMonitor()->GetTaskCompleteEvent());
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
pMonitor->Lock();
|
|
pPerf->bFree = TRUE;
|
|
pMonitor->Unlock();
|
|
}
|
|
|
|
unregister_timer:
|
|
if (bFreeSlot)
|
|
{
|
|
pMonitor->Lock();
|
|
pPerf->bFree = TRUE;
|
|
pMonitor->Unlock();
|
|
}
|
|
DeleteTimerQueueTimer(NULL,pPerf->hTimer,NULL);
|
|
pPerf->hTimer = NULL;
|
|
pPerf->Enabled = TRUE;
|
|
|
|
}
|
|
else
|
|
{
|
|
// never here
|
|
DebugBreak();
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
///////////////////////////////////////////////
|
|
|
|
DWORD ResyncPerf(DWORD dwReason)
|
|
{
|
|
|
|
if(!GLOB_IsResyncAllowed())
|
|
{
|
|
ERRORTRACE((LOG_WINMGMT,"ResyncPerf disable g_fSetup or g_fDoResync\n"));
|
|
return 0;
|
|
}
|
|
|
|
ResyncPerfTask * pPerfTask = GLOB_GetMonitor()->GetAvailable(dwReason);
|
|
|
|
if (pPerfTask)
|
|
{
|
|
// here you have the slot for execution
|
|
// tell Reverse_Adapter that it's scheduled
|
|
if (RESYNC_TYPE_WDMEVENT == dwReason ||
|
|
RESYNC_TYPE_CLASSCREATION == dwReason)
|
|
{
|
|
|
|
LONG lRet;
|
|
HKEY hKey;
|
|
DWORD dwTemp;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
WBEM_REG_REVERSE_KEY,
|
|
NULL,
|
|
KEY_READ|KEY_WRITE,
|
|
&hKey);
|
|
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwSize = sizeof(DWORD);
|
|
DWORD dwVal;
|
|
lRet = RegQueryValueEx(hKey,
|
|
WBEM_REG_REVERSE_VALUE,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)&dwVal,
|
|
&dwSize);
|
|
|
|
// if the key is there, is NULL and it is of the right type
|
|
// OR if the key is not there
|
|
if((ERROR_SUCCESS == lRet &&
|
|
REG_DWORD == dwType &&
|
|
0 == dwVal) ||
|
|
(ERROR_FILE_NOT_FOUND == lRet))
|
|
{
|
|
dwVal = 1;
|
|
RegSetValueEx(hKey,
|
|
WBEM_REG_REVERSE_VALUE,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE *)&dwVal,
|
|
sizeof(DWORD));
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
};
|
|
|
|
if (CreateTimerQueueTimer(&pPerfTask->hTimer,
|
|
NULL,
|
|
CMonitorEvents::TimerCallBack,
|
|
pPerfTask,
|
|
pPerfTask->dwTimeDue,
|
|
0,
|
|
WT_EXECUTEONLYONCE|WT_EXECUTELONGFUNCTION))
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
// ERRORTRACE
|
|
return GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// no slot availables
|
|
return ERROR_BUSY;
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
// This function is called by the Hook installed in wbemcore
|
|
// that monitors class creation
|
|
//
|
|
///////////////////////////////////////////
|
|
|
|
DWORD __stdcall
|
|
DredgeRA(VOID * pReserved)
|
|
{
|
|
//DBG_PRINTFA((pBuff,"Classes\n"));
|
|
return ResyncPerf(RESYNC_TYPE_CLASSCREATION);
|
|
};
|