/*++ Copyright (C) 1999-2001 Microsoft Corporation Module Name: RESYNC2.CPP Abstract: History: ivanbrug 01-Oct-2000 changed for svchost migration --*/ #include "precomp.h" #include #include #include #include #include "WinMgmt.h" #include #include #include #include #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;iInstanceCount;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 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;im_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); };