Leaked source code of windows server 2003
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.

1584 lines
46 KiB

  1. /*++
  2. Copyright (C) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. RESYNC2.CPP
  5. Abstract:
  6. implements the listener for WDM events and events for sync-up with IdleTask
  7. History:
  8. ivanbrug 01-Oct-2000 changed for svchost migration
  9. --*/
  10. #include "precomp.h"
  11. #include <winntsec.h>
  12. #include <malloc.h>
  13. #include <initguid.h>
  14. #include "WinMgmt.h"
  15. #include <Wmistr.h>
  16. #include <wmium.h>
  17. #include <wmicom.h>
  18. #include <wmimof.h>
  19. #include "resync2.h"
  20. #include "wbemdelta.h" // for DeltaDredge
  21. #include "arrtempl.h"
  22. //
  23. //
  24. // this is because WDMLib is __BADLY__ DESIGNED
  25. //
  26. /////////////////////////////////////////////////////////////
  27. void WINAPI EventCallbackRoutine(PWNODE_HEADER WnodeHeader, ULONG_PTR Context)
  28. {
  29. return;
  30. }
  31. //
  32. //
  33. // This class listens on WDM events
  34. //
  35. /////////////////////////////////////////////////////////////
  36. CWDMListener::CWDMListener():
  37. m_dwSignature(SIG_WDMEVENTS_FREE),
  38. m_hEventAdd(NULL),
  39. m_hEventRem(NULL),
  40. m_hWaitAdd(NULL),
  41. m_hWaitRem(NULL),
  42. m_UnInited(TRUE),
  43. m_GuidAdd(GUID_MOF_RESOURCE_ADDED_NOTIFICATION),
  44. m_GuidRem(GUID_MOF_RESOURCE_REMOVED_NOTIFICATION)
  45. {
  46. }
  47. DWORD
  48. CWDMListener::OpenAdd()
  49. {
  50. DWORD dwErr;
  51. dwErr = WmiOpenBlock(&m_GuidAdd,
  52. WMIGUID_NOTIFICATION | SYNCHRONIZE,
  53. &m_hEventAdd);
  54. if (ERROR_SUCCESS == dwErr)
  55. {
  56. if (RegisterWaitForSingleObject(&m_hWaitAdd,
  57. m_hEventAdd,
  58. CWDMListener::EvtCallBackAdd,
  59. this,
  60. INFINITE,
  61. WT_EXECUTEONLYONCE))
  62. {
  63. return ERROR_SUCCESS;
  64. }
  65. else
  66. {
  67. dwErr = GetLastError();
  68. }
  69. }
  70. else
  71. {
  72. dwErr = GetLastError();
  73. }
  74. // if here, some errors
  75. CloseAdd();
  76. return dwErr;
  77. }
  78. DWORD
  79. CWDMListener::OpenRemove()
  80. {
  81. DWORD dwRet;
  82. dwRet = WmiOpenBlock(&m_GuidRem,
  83. WMIGUID_NOTIFICATION | SYNCHRONIZE,
  84. &m_hEventRem);
  85. if (ERROR_SUCCESS == dwRet)
  86. {
  87. if (RegisterWaitForSingleObject(&m_hWaitRem,
  88. m_hEventRem,
  89. CWDMListener::EvtCallBackRem,
  90. this,
  91. INFINITE,
  92. WT_EXECUTEONLYONCE))
  93. {
  94. return ERROR_SUCCESS;
  95. }
  96. else
  97. {
  98. dwRet = GetLastError();
  99. }
  100. }
  101. else
  102. {
  103. dwRet = GetLastError();
  104. }
  105. CloseRemove();
  106. return dwRet;
  107. }
  108. DWORD
  109. CWDMListener::CloseAdd()
  110. {
  111. if (m_hWaitAdd)
  112. {
  113. UnregisterWaitEx(m_hWaitAdd,NULL);
  114. m_hWaitAdd = NULL;
  115. }
  116. if (m_hEventAdd)
  117. {
  118. WmiCloseBlock(m_hEventAdd);
  119. m_hEventAdd = NULL;
  120. }
  121. return 0;
  122. }
  123. DWORD
  124. CWDMListener::CloseRemove()
  125. {
  126. if (m_hWaitRem)
  127. {
  128. UnregisterWaitEx(m_hWaitRem,NULL);
  129. m_hWaitRem = NULL;
  130. }
  131. if (m_hEventRem)
  132. {
  133. WmiCloseBlock(m_hEventRem);
  134. m_hEventRem = NULL;
  135. }
  136. return 0;
  137. }
  138. VOID
  139. CWDMListener::Unregister()
  140. {
  141. CInCritSec ics(&m_cs);
  142. if (m_UnInited) return;
  143. CloseAdd();
  144. CloseRemove();
  145. m_dwSignature = SIG_WDMEVENTS_FREE;
  146. m_UnInited = TRUE;
  147. }
  148. CWDMListener::~CWDMListener()
  149. {
  150. Unregister();
  151. }
  152. DWORD
  153. CWDMListener::Register()
  154. {
  155. CInCritSec ics(&m_cs);
  156. if (!m_UnInited) // prevent multiple calls
  157. return 0;
  158. if (ERROR_SUCCESS == OpenAdd() && ERROR_SUCCESS == OpenRemove())
  159. {
  160. m_dwSignature = SIG_WDMEVENTS_BUSY;
  161. m_UnInited = FALSE;
  162. }
  163. return GetLastError();
  164. }
  165. VOID NTAPI
  166. CWDMListener::EvtCallBackAdd(VOID * pContext,BOOLEAN bTimerFired)
  167. {
  168. if (!GLOB_Monitor_IsRegistred()) return;
  169. CWDMListener * pThis = (CWDMListener *)pContext;
  170. if (NULL == pThis) return;
  171. if (SIG_WDMEVENTS_BUSY != pThis->m_dwSignature) return;
  172. pThis->EvtCallThis(bTimerFired,Type_Added);
  173. //
  174. // we have process the WDM event
  175. // since we are in the RtlpWorkerThread and
  176. // we are registred with WT_EXECUTEONLYONCE
  177. // REDO FROM START
  178. //
  179. {
  180. CInCritSec ics(&pThis->m_cs);
  181. if (ERROR_SUCCESS == pThis->CloseAdd())
  182. {
  183. pThis->OpenAdd();
  184. }
  185. }
  186. }
  187. VOID NTAPI
  188. CWDMListener::EvtCallBackRem(VOID * pContext,BOOLEAN bTimerFired)
  189. {
  190. if (!GLOB_Monitor_IsRegistred()) return;
  191. CWDMListener * pThis = (CWDMListener *)pContext;
  192. if (NULL == pThis) return;
  193. if (SIG_WDMEVENTS_BUSY != pThis->m_dwSignature) return;
  194. pThis->EvtCallThis(bTimerFired,Type_Removed);
  195. //
  196. // we have process the WDM event
  197. // since we are in the RtlpWorkerThread and
  198. // we are registred with WT_EXECUTEONLYONCE
  199. // REDO FROM START
  200. //
  201. {
  202. CInCritSec ics(&pThis->m_cs);
  203. if (ERROR_SUCCESS == pThis->CloseRemove())
  204. {
  205. pThis->OpenRemove();
  206. }
  207. }
  208. }
  209. VOID
  210. CWDMListener::EvtCallThis(BOOLEAN bTimerFired, int Type)
  211. {
  212. if (bTimerFired)
  213. {
  214. _DBG_ASSERT(FALSE);
  215. }
  216. else
  217. {
  218. if (m_UnInited)
  219. return;
  220. DWORD dwRet;
  221. if (Type_Added == Type)
  222. {
  223. dwRet = WmiReceiveNotifications(1,&m_hEventAdd,CWDMListener::WmiCallBack,(ULONG_PTR)this);
  224. }
  225. else if (Type_Removed == Type)
  226. {
  227. dwRet = WmiReceiveNotifications(1,&m_hEventRem,CWDMListener::WmiCallBack,(ULONG_PTR)this);
  228. }
  229. }
  230. }
  231. VOID WINAPI
  232. CWDMListener::WmiCallBack(PWNODE_HEADER Wnode,
  233. UINT_PTR NotificationContext)
  234. {
  235. // pThis is checked in the EventCallBack
  236. CWDMListener * pThis = (CWDMListener *)NotificationContext;
  237. #ifdef DEBUG_ADAP
  238. WCHAR pszClsID[40];
  239. StringFromGUID2(Wnode->Guid,pszClsID,40);
  240. DBG_PRINTFA((pBuff,"Flag %08x ProvId %08x %p GUID %S\n",
  241. Wnode->Flags,Wnode->ProviderId,(ULONG_PTR)Wnode->ClientContext,pszClsID));
  242. if (WNODE_FLAG_ALL_DATA & Wnode->Flags)
  243. {
  244. WNODE_ALL_DATA * pAllData = (WNODE_ALL_DATA *)Wnode;
  245. DWORD i;
  246. for (i=0;i<pAllData->InstanceCount;i++)
  247. {
  248. WCHAR pTmpBuff[MAX_PATH+1];
  249. pTmpBuff[MAX_PATH] = 0;
  250. DWORD dwSize = (pAllData->OffsetInstanceDataAndLength[i].LengthInstanceData>MAX_PATH)?MAX_PATH:pAllData->OffsetInstanceDataAndLength[i].LengthInstanceData;
  251. memcpy(pTmpBuff,(BYTE*)pAllData+pAllData->OffsetInstanceDataAndLength[i].OffsetInstanceData,dwSize);
  252. DBG_PRINTFA((pBuff,"%d - %S\n",i,pTmpBuff));
  253. }
  254. };
  255. #endif
  256. #ifdef DBG
  257. if (!HeapValidate(GetProcessHeap(),0,NULL))
  258. {
  259. DebugBreak();
  260. }
  261. if (!HeapValidate(CWin32DefaultArena::GetArenaHeap(),0,NULL))
  262. {
  263. DebugBreak();
  264. }
  265. #endif
  266. CWMIBinMof WMIBinMof;
  267. //=============================================================================
  268. // Note: this combo will always succeed, as all the initialize is doing is
  269. // setting a flag to FALSE and returning S_OK
  270. //=============================================================================
  271. if( SUCCEEDED( WMIBinMof.Initialize(NULL,FALSE)) )
  272. {
  273. if (WMIBinMof.BinaryMofEventChanged(Wnode))
  274. {
  275. #ifdef DEBUG_ADAP
  276. DBG_PRINTFA((pBuff,"---- WMIBinMof.BinaryMofEventChanged == CHANGED ----\n"));
  277. #endif
  278. DEBUGTRACE((LOG_WINMGMT,"WDM event && WMIBinMof.BinaryMofEventChanged == TRUE\n"));
  279. ResyncPerf(RESYNC_TYPE_WDMEVENT);
  280. #ifdef DBG
  281. if (!HeapValidate(GetProcessHeap(),0,NULL))
  282. {
  283. DebugBreak();
  284. }
  285. if (!HeapValidate(CWin32DefaultArena::GetArenaHeap(),0,NULL))
  286. {
  287. DebugBreak();
  288. }
  289. #endif
  290. }
  291. else
  292. {
  293. #ifdef DEBUG_ADAP
  294. DBG_PRINTFA((pBuff,"---- WMIBinMof.BinaryMofEventChanged == NOT CHANGED ----\n"));
  295. #endif
  296. }
  297. }
  298. return;
  299. }
  300. CCounterEvts::CCounterEvts():
  301. m_dwSignature(SIG_COUNTEEVENTS_BUSY),
  302. m_LoadCtrEvent(NULL),
  303. m_UnloadCtrEvent(NULL),
  304. m_Uninited(TRUE),
  305. m_WaitLoadCtr(NULL),
  306. m_WaitUnloadCtr(NULL),
  307. m_hWmiReverseAdapSetLodCtr(NULL),
  308. m_hWmiReverseAdapLodCtrDone(NULL),
  309. m_hPendingTasksStart(NULL),
  310. m_hPendingTasksComplete(NULL)
  311. {
  312. }
  313. //
  314. // allows localsystem to use the event
  315. //
  316. //
  317. // SDDL: L"O:SYG:SYD:(A;;0x1f0003;;;SY)"
  318. //
  319. DWORD g_LocalSystemSD[] = {
  320. 0x80040001, 0x00000014, 0x00000020, 0x00000000,
  321. 0x0000002c, 0x00000101, 0x05000000, 0x00000012,
  322. 0x00000101, 0x05000000, 0x00000012, 0x00300002,
  323. 0x00000001, 0x00140000, 0x001f0003, 0x00000101,
  324. 0x05000000, 0x00000012, 0x00000000, 0x00000000
  325. };
  326. //
  327. // allow administrators and localsystem to use the event
  328. //
  329. //
  330. // SDDL: L"O:SYG:SYD:(A;;0x1f0003;;;SY)(A;;0x1f0003;;;BA)"
  331. //
  332. DWORD g_LocalSystemAdminsSD[] = {
  333. 0x80040001, 0x00000014, 0x00000020, 0x00000000,
  334. 0x0000002c, 0x00000101, 0x05000000, 0x00000012,
  335. 0x00000101, 0x05000000, 0x00000012, 0x00340002,
  336. 0x00000002, 0x00140000, 0x001f0003, 0x00000101,
  337. 0x05000000, 0x00000012, 0x00180000, 0x001f0003,
  338. 0x00000201, 0x05000000, 0x00000020, 0x00000220
  339. };
  340. DWORD
  341. CCounterEvts::Init()
  342. {
  343. if (!m_Uninited)
  344. return 0;
  345. SECURITY_ATTRIBUTES sa;
  346. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  347. sa.lpSecurityDescriptor = (LPVOID)g_LocalSystemAdminsSD;
  348. sa.bInheritHandle = FALSE;
  349. m_LoadCtrEvent = CreateEvent(&sa, FALSE, FALSE,LOAD_CTR_EVENT_NAME);
  350. if (NULL == m_LoadCtrEvent)
  351. goto end_fail;
  352. m_UnloadCtrEvent = CreateEvent(&sa, FALSE, FALSE, UNLOAD_CTR_EVENT_NAME);
  353. if (NULL == m_UnloadCtrEvent)
  354. goto end_fail;
  355. m_hWmiReverseAdapSetLodCtr = CreateEvent(&sa,FALSE,FALSE,REVERSE_DREDGE_EVENT_NAME_SET);
  356. if (NULL == m_hWmiReverseAdapSetLodCtr)
  357. goto end_fail;
  358. m_hWmiReverseAdapLodCtrDone = CreateEvent(&sa,FALSE,FALSE,REVERSE_DREDGE_EVENT_NAME_ACK);
  359. if (NULL == m_hWmiReverseAdapLodCtrDone)
  360. goto end_fail;
  361. sa.lpSecurityDescriptor = (LPVOID)g_LocalSystemSD;
  362. m_hPendingTasksStart = CreateEvent(&sa,FALSE,FALSE,PENDING_TASK_START);
  363. if (!m_hPendingTasksStart)
  364. goto end_fail;
  365. m_hPendingTasksComplete = CreateEvent(&sa,TRUE,TRUE,PENDING_TASK_COMPLETE);
  366. if (!m_hPendingTasksComplete)
  367. goto end_fail;
  368. m_Uninited = FALSE;
  369. return NO_ERROR;
  370. end_fail:
  371. return GetLastError();
  372. }
  373. VOID NTAPI
  374. CCounterEvts::EvtCallBackLoad(VOID * pContext,BOOLEAN bTimerFired)
  375. {
  376. if (!GLOB_Monitor_IsRegistred()) return;
  377. CCounterEvts * pCounter = (CCounterEvts *)pContext;
  378. if (NULL == pCounter) return;
  379. if (SIG_COUNTEEVENTS_BUSY != pCounter->m_dwSignature) return;
  380. pCounter->CallBack(bTimerFired,Type_Load);
  381. }
  382. VOID NTAPI
  383. CCounterEvts::EvtCallBackUnload(VOID * pContext,BOOLEAN bTimerFired)
  384. {
  385. if (!GLOB_Monitor_IsRegistred()) return;
  386. CCounterEvts * pCounter = (CCounterEvts *)pContext;
  387. if (NULL == pCounter) return;
  388. if (SIG_COUNTEEVENTS_BUSY != pCounter->m_dwSignature) return;
  389. pCounter->CallBack(bTimerFired,Type_Unload);
  390. }
  391. VOID NTAPI
  392. CCounterEvts::EvtCallBackPendingTask(VOID * pContext,BOOLEAN bTimerFired)
  393. {
  394. if (!GLOB_Monitor_IsRegistred()) return;
  395. CCounterEvts * pCounter = (CCounterEvts *)pContext;
  396. if (NULL == pCounter) return;
  397. if (SIG_COUNTEEVENTS_BUSY != pCounter->m_dwSignature) return;
  398. pCounter->CallBackPending(bTimerFired);
  399. }
  400. VOID
  401. CCounterEvts::CallBack(BOOLEAN bTimerFired,int Type)
  402. {
  403. #ifdef DEBUG_ADAP
  404. DBG_PRINTFA((pBuff,"CallBack with type %d called\n",Type));
  405. #endif
  406. if (GLOB_IsResyncAllowed())
  407. {
  408. DWORD dwRet = WaitForSingleObject(m_hWmiReverseAdapSetLodCtr,0);
  409. if (WAIT_OBJECT_0 == dwRet)
  410. {
  411. // this is the hack not to spawn a Delta Dredge when there is before a Reverese Dredge
  412. #ifdef DEBUG_ADAP
  413. DBG_PRINTFA((pBuff," - SetEvent(m_hWmiReverseAdapLodCtrDone);\n"));
  414. #endif
  415. SetEvent(m_hWmiReverseAdapLodCtrDone);
  416. }
  417. else
  418. {
  419. #ifdef DEBUG_ADAP
  420. DBG_PRINTFA((pBuff," - ResyncPerf(RESYNC_TYPE_LODCTR);\n"));
  421. #endif
  422. ResyncPerf(RESYNC_TYPE_LODCTR);
  423. }
  424. }
  425. }
  426. VOID
  427. CCounterEvts::CallBackPending(BOOLEAN bTimerFired)
  428. {
  429. if (GLOB_IsResyncAllowed())
  430. {
  431. #ifdef DEBUG_ADAP
  432. DBG_PRINTFA((pBuff," - PendingTask Start set\n"));
  433. #endif
  434. ResyncPerf(RESYNC_TYPE_PENDING_TASKS);
  435. }
  436. }
  437. VOID RevertRegister_(HANDLE & hWaitHandle)
  438. {
  439. UnregisterWaitEx(hWaitHandle,NULL);
  440. hWaitHandle = NULL;
  441. }
  442. DWORD
  443. CCounterEvts::Register()
  444. {
  445. // automatic reset
  446. if (!RegisterWaitForSingleObject(&m_WaitLoadCtr,
  447. m_LoadCtrEvent,
  448. CCounterEvts::EvtCallBackLoad,
  449. this,
  450. INFINITE,
  451. WT_EXECUTEDEFAULT)) return GetLastError();
  452. OnDeleteIf<HANDLE &,VOID(*)(HANDLE &),RevertRegister_> UnReg1(m_WaitLoadCtr);
  453. // automatic reset
  454. if(!RegisterWaitForSingleObject(&m_WaitUnloadCtr,
  455. m_UnloadCtrEvent,
  456. CCounterEvts::EvtCallBackUnload,
  457. this,
  458. INFINITE,
  459. WT_EXECUTEDEFAULT)) return GetLastError();
  460. OnDeleteIf<HANDLE &,VOID(*)(HANDLE &),RevertRegister_> UnReg2(m_WaitUnloadCtr);
  461. if (!RegisterWaitForSingleObject(&m_hWaitPendingTasksStart,
  462. m_hPendingTasksStart,
  463. CCounterEvts::EvtCallBackPendingTask,
  464. this,
  465. INFINITE,
  466. WT_EXECUTEDEFAULT)) return GetLastError();
  467. OnDeleteIf<HANDLE &,VOID(*)(HANDLE &),RevertRegister_> UnReg3(m_hWaitPendingTasksStart);
  468. // here everything is OK
  469. UnReg1.dismiss();
  470. UnReg2.dismiss();
  471. UnReg3.dismiss();
  472. m_dwSignature = SIG_COUNTEEVENTS_BUSY;
  473. return ERROR_SUCCESS;
  474. }
  475. DWORD
  476. CCounterEvts::Unregister()
  477. {
  478. if (m_WaitLoadCtr)
  479. {
  480. UnregisterWaitEx(m_WaitLoadCtr,NULL);
  481. m_WaitLoadCtr = NULL;
  482. }
  483. if (m_WaitUnloadCtr)
  484. {
  485. UnregisterWaitEx(m_WaitUnloadCtr,NULL);
  486. m_WaitUnloadCtr = NULL;
  487. }
  488. if (m_hWaitPendingTasksStart)
  489. {
  490. UnregisterWaitEx(m_hWaitPendingTasksStart,NULL);
  491. m_hWaitPendingTasksStart = NULL;
  492. }
  493. m_dwSignature = SIG_COUNTEEVENTS_FREE;
  494. return 0;
  495. }
  496. VOID
  497. CCounterEvts::UnInit()
  498. {
  499. if (!m_Uninited)
  500. return;
  501. if(m_LoadCtrEvent) {
  502. CloseHandle(m_LoadCtrEvent);
  503. m_LoadCtrEvent = NULL;
  504. }
  505. if(m_UnloadCtrEvent)
  506. {
  507. CloseHandle(m_UnloadCtrEvent);
  508. m_UnloadCtrEvent = NULL;
  509. }
  510. if (m_hWmiReverseAdapSetLodCtr)
  511. {
  512. CloseHandle(m_hWmiReverseAdapSetLodCtr);
  513. m_hWmiReverseAdapSetLodCtr = NULL;
  514. }
  515. if (m_hWmiReverseAdapLodCtrDone)
  516. {
  517. CloseHandle(m_hWmiReverseAdapLodCtrDone);
  518. m_hWmiReverseAdapLodCtrDone = NULL;
  519. }
  520. if (m_hPendingTasksStart)
  521. {
  522. CloseHandle(m_hPendingTasksStart);
  523. m_hPendingTasksStart = NULL;
  524. }
  525. if (m_hPendingTasksComplete)
  526. {
  527. CloseHandle(m_hPendingTasksComplete);
  528. m_hPendingTasksComplete = NULL;
  529. }
  530. m_Uninited = TRUE;
  531. }
  532. CCounterEvts::~CCounterEvts()
  533. {
  534. if (!m_Uninited)
  535. UnInit();
  536. m_dwSignature = SIG_COUNTEEVENTS_FREE;
  537. }
  538. //
  539. // this is the main abstraction
  540. // the child classes will call the ResyncPerf function,
  541. // as long as the CWbemServices write hook.
  542. // The ResyncPerf function will grab the global monitor
  543. // and register a Timer Callback
  544. // the gate will be implemented in the GetAvailable function
  545. //
  546. //
  547. /////////////////////////////////////////////////////////////////////
  548. CMonitorEvents::CMonitorEvents():
  549. m_bInit(FALSE),
  550. m_bRegistred(FALSE)
  551. {
  552. };
  553. CMonitorEvents::~CMonitorEvents()
  554. {
  555. }
  556. //
  557. // We install a console control handler because we want to unregister
  558. // the WDM event monitor before the GIUD_REMOVE events gets in
  559. // the console applications get notified of shutdown before services and drivers
  560. //
  561. ////////////////////////////////////////////////////////
  562. BOOL WINAPI
  563. CMonitorEvents::MonitorCtrlHandler( DWORD dwCtrlType )
  564. {
  565. BOOL bRet = FALSE;
  566. switch(dwCtrlType)
  567. {
  568. case CTRL_SHUTDOWN_EVENT:
  569. GLOB_GetMonitor()->m_WDMListener.Unregister();
  570. #ifdef DEBUG_ADAP
  571. DBG_PRINTFA((pBuff,"WDM Handles closed\n"));
  572. #endif
  573. bRet = TRUE;
  574. break;
  575. default:
  576. bRet = FALSE;
  577. };
  578. return bRet;
  579. };
  580. BOOL
  581. CMonitorEvents::Init()
  582. {
  583. if (m_bInit) return TRUE;
  584. CInCritSec ics(&m_cs);
  585. if (m_bInit) return TRUE;
  586. m_dwSig = 'VEOM';
  587. m_CntsEvts.Init();
  588. m_dwADAPDelaySec = WMIADAP_DEFAULT_DELAY;
  589. m_dwLodCtrDelaySec = WMIADAP_DEFAULT_DELAY_LODCTR;
  590. m_dwTimeToFull = WMIADAP_DEFAULT_TIMETOFULL;
  591. m_dwTimeToKillAdap = MAX_PROCESS_WAIT;
  592. memset(&m_FileTime,0,sizeof(m_FileTime));
  593. RegRead();
  594. for (DWORD i=0;i<RESYNC_TYPE_MAX;i++)
  595. {
  596. m_ResyncTasks[i].dwSig = SIG_RESYNC_PERF;
  597. m_ResyncTasks[i].bFree = TRUE;
  598. m_ResyncTasks[i].pMonitor = this;
  599. m_ResyncTasks[i].hTimer = NULL;
  600. m_ResyncTasks[i].hWaitHandle = NULL;
  601. m_ResyncTasks[i].hProcess = NULL;
  602. m_ResyncTasks[i].Enabled = TRUE;
  603. }
  604. //m_ResyncTasks[RESYNC_TYPE_LODCTR].CmdType // to be decided by DeltaDredge
  605. m_ResyncTasks[RESYNC_TYPE_INITIAL].dwTimeDue = (m_dwADAPDelaySec)*1000;
  606. m_ResyncTasks[RESYNC_TYPE_LODCTR].CmdType = RESYNC_DELTA_THROTTLE;
  607. m_ResyncTasks[RESYNC_TYPE_LODCTR].dwTimeDue = (m_dwLodCtrDelaySec)*1000;
  608. // //RESYNC_TYPE_CLASSCREATION is the same
  609. m_ResyncTasks[RESYNC_TYPE_WDMEVENT].CmdType = RESYNC_RADAPD_THROTTLE;
  610. m_ResyncTasks[RESYNC_TYPE_WDMEVENT].dwTimeDue = (m_dwLodCtrDelaySec)*1000;
  611. m_ResyncTasks[RESYNC_TYPE_PENDING_TASKS].CmdType = RESYNC_FULL_RADAPD_NOTHROTTLE;
  612. m_ResyncTasks[RESYNC_TYPE_PENDING_TASKS].dwTimeDue = 500; // hard coded
  613. //
  614. // set up the console handler
  615. //
  616. SetConsoleCtrlHandler( MonitorCtrlHandler, TRUE );
  617. //
  618. // let's asses some initial state for the IdleTask business
  619. //
  620. m_OutStandingProcesses = 0;
  621. m_bFullReverseNeeded = FALSE;
  622. m_bInit = TRUE;
  623. return TRUE;
  624. };
  625. BOOL
  626. CMonitorEvents::Uninit()
  627. {
  628. if (!m_bInit) return TRUE;
  629. CInCritSec ics(&m_cs);
  630. if (!m_bInit) return TRUE;
  631. for (DWORD i=0;i<RESYNC_TYPE_MAX;i++)
  632. {
  633. if (m_ResyncTasks[i].hTimer)
  634. {
  635. DeleteTimerQueueTimer(NULL,m_ResyncTasks[i].hTimer,NULL);
  636. m_ResyncTasks[i].hTimer = NULL;
  637. }
  638. if (m_ResyncTasks[i].hWaitHandle)
  639. {
  640. UnregisterWaitEx(m_ResyncTasks[i].hWaitHandle,NULL);
  641. m_ResyncTasks[i].hWaitHandle = NULL;
  642. }
  643. if (m_ResyncTasks[i].hProcess)
  644. {
  645. CloseHandle(m_ResyncTasks[i].hProcess);
  646. m_ResyncTasks[i].hProcess = NULL;
  647. }
  648. m_ResyncTasks[i].dwSig = (DWORD)'eerf';
  649. }
  650. m_CntsEvts.UnInit();
  651. //
  652. // tear-down the console handler
  653. //
  654. SetConsoleCtrlHandler( MonitorCtrlHandler, FALSE );
  655. m_bInit = FALSE;
  656. m_dwSig = 'veom';
  657. return TRUE;
  658. };
  659. //
  660. //
  661. // called in the running/continue
  662. //
  663. /////////////
  664. DWORD
  665. CMonitorEvents::Register()
  666. {
  667. m_CntsEvts.Register();
  668. m_WDMListener.Register();
  669. m_bRegistred = TRUE;
  670. return 0;
  671. };
  672. //
  673. //
  674. // called in the pause/stop
  675. //
  676. //////////////////////////////////////////////////////////
  677. DWORD
  678. CMonitorEvents::Unregister(BOOL bIsSystemShutDown)
  679. {
  680. m_bRegistred = FALSE;
  681. if (!bIsSystemShutDown)
  682. {
  683. m_CntsEvts.Unregister();
  684. m_WDMListener.Unregister();
  685. }
  686. return 0;
  687. };
  688. //
  689. //
  690. //
  691. /////////////////////////////////////////////////////////
  692. VOID
  693. CMonitorEvents::RegRead()
  694. {
  695. // Read the initialization information
  696. LONG lRet;
  697. HKEY hKey;
  698. DWORD dwTemp;
  699. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  700. TEXT("Software\\Microsoft\\WBEM\\CIMOM"),
  701. NULL,
  702. KEY_READ|KEY_WRITE,
  703. &hKey);
  704. if (ERROR_SUCCESS == lRet)
  705. {
  706. OnDelete<HKEY,LONG(*)(HKEY),RegCloseKey> cm(hKey);
  707. DWORD dwType;
  708. DWORD dwSize = sizeof(DWORD);
  709. lRet = RegQueryValueEx(hKey,
  710. TEXT("ADAPDelay"),
  711. NULL,
  712. &dwType,
  713. (BYTE *)&m_dwADAPDelaySec,
  714. &dwSize);
  715. if (ERROR_SUCCESS == lRet && REG_DWORD == dwType)
  716. {
  717. //This is what we want
  718. }
  719. else if ( ERROR_FILE_NOT_FOUND == lRet )
  720. {
  721. dwTemp = WMIADAP_DEFAULT_DELAY;
  722. RegSetValueEx(hKey,
  723. TEXT("ADAPDelay"),
  724. NULL,
  725. REG_DWORD,
  726. (BYTE *)&dwTemp,
  727. sizeof(DWORD));
  728. }
  729. else
  730. {
  731. // Error
  732. ERRORTRACE( ( LOG_WINMGMT, "ResyncPerf experienced an error while attempting to read the WMIADAPDelay value in the CIMOM subkey. Continuing using a default value.\n" ) );
  733. }
  734. dwSize = sizeof(DWORD);
  735. lRet = RegQueryValueEx(hKey,
  736. TEXT("LodCtrDelay"),
  737. NULL,
  738. &dwType,
  739. (BYTE *)&m_dwLodCtrDelaySec,
  740. &dwSize);
  741. if (ERROR_SUCCESS == lRet && REG_DWORD == dwType)
  742. {
  743. //This is what we want
  744. }
  745. else if ( ERROR_FILE_NOT_FOUND == lRet )
  746. {
  747. dwTemp = WMIADAP_DEFAULT_DELAY_LODCTR;
  748. RegSetValueEx(hKey,
  749. TEXT("LodCtrDelay"),
  750. NULL,
  751. REG_DWORD,
  752. (BYTE *)&dwTemp,
  753. sizeof(DWORD));
  754. }
  755. else
  756. {
  757. // Error
  758. ERRORTRACE( ( LOG_WINMGMT, "ResyncPerf experienced an error while attempting to read the WMIADAPDelay value in the CIMOM subkey. Continuing using a default value.\n" ) );
  759. }
  760. dwSize = sizeof(DWORD);
  761. lRet = RegQueryValueEx(hKey,
  762. ADAP_TIME_TO_FULL,
  763. NULL,
  764. &dwType,
  765. (BYTE *)&m_dwTimeToFull,
  766. &dwSize);
  767. if (ERROR_SUCCESS == lRet && REG_DWORD == dwType)
  768. {
  769. //This is what we want
  770. }
  771. else if ( ERROR_FILE_NOT_FOUND == lRet )
  772. {
  773. dwTemp = WMIADAP_DEFAULT_TIMETOFULL;
  774. RegSetValueEx(hKey,
  775. ADAP_TIME_TO_FULL,
  776. NULL,
  777. REG_DWORD,
  778. (BYTE *)&dwTemp,
  779. sizeof(DWORD));
  780. }
  781. else
  782. {
  783. // Error
  784. ERRORTRACE( ( LOG_WINMGMT, "ResyncPerf experienced an error while attempting to read the WMIADAPDelay value in the CIMOM subkey. Continuing using a default value.\n" ) );
  785. }
  786. dwSize = sizeof(DWORD);
  787. lRet = RegQueryValueEx(hKey,
  788. ADAP_TIME_TO_KILL_ADAP,
  789. NULL,
  790. &dwType,
  791. (BYTE *)&m_dwTimeToKillAdap,
  792. &dwSize);
  793. if (ERROR_SUCCESS == lRet && REG_DWORD == dwType)
  794. {
  795. //This is what we want
  796. }
  797. else if ( ERROR_FILE_NOT_FOUND == lRet )
  798. {
  799. dwTemp = MAX_PROCESS_WAIT;
  800. RegSetValueEx(hKey,
  801. ADAP_TIME_TO_KILL_ADAP,
  802. NULL,
  803. REG_DWORD,
  804. (BYTE *)&dwTemp,
  805. sizeof(DWORD));
  806. }
  807. else
  808. {
  809. // Error
  810. 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));
  811. }
  812. //ADAP_TIMESTAMP_FULL
  813. dwSize = sizeof(FILETIME);
  814. lRet = RegQueryValueEx(hKey,
  815. ADAP_TIMESTAMP_FULL,
  816. NULL,
  817. &dwType,
  818. (BYTE *)&m_FileTime,
  819. &dwSize);
  820. }
  821. else
  822. {
  823. // Error
  824. ERRORTRACE( ( LOG_WINMGMT, "ResyncPerf could not open the CIMOM subkey to read initialization data. Continuing using a default value.\n" ) );
  825. }
  826. }
  827. //
  828. //
  829. //
  830. ////////////////////////////////////////////////////////
  831. ResyncPerfTask *
  832. CMonitorEvents::GetAvailable(DWORD dwReason)
  833. {
  834. ResyncPerfTask * pPerf = NULL;
  835. CInCritSec ics(&m_cs);
  836. if (m_ResyncTasks[dwReason].bFree)
  837. {
  838. m_ResyncTasks[dwReason].bFree = FALSE;
  839. m_ResyncTasks[dwReason].Type = dwReason;
  840. pPerf = &m_ResyncTasks[dwReason];
  841. }
  842. return pPerf;
  843. }
  844. TCHAR * g_Strings[] = {
  845. TEXT("/F /T"), // FULL Throttle
  846. TEXT("/D /T"), // DELTA Throttle
  847. TEXT("/R /T"), // REVERSE_ADAPTER Throttle
  848. TEXT("/F /R /T"), // FULL REVERSE_ADAPTER Throttle
  849. TEXT("/D /R /T"), // DELTA REVERSE_ADAPTER Throttle
  850. TEXT("/F /R") // FULL REVERSE no Throttle
  851. };
  852. void inline DoUnThrottleDredges()
  853. {
  854. #ifdef DEBUG_ADAP
  855. DBG_PRINTFA((pBuff,"DoUnThrottleDredges\n"));
  856. #endif
  857. RegSetDWORD(HKEY_LOCAL_MACHINE,HOME_REG_PATH,DO_THROTTLE,0);
  858. return;
  859. }
  860. void inline DoThrottleDredges()
  861. {
  862. #ifdef DEBUG_ADAP
  863. DBG_PRINTFA((pBuff,"DoThrottleDredges\n"));
  864. #endif
  865. RegSetDWORD(HKEY_LOCAL_MACHINE,HOME_REG_PATH,DO_THROTTLE,1);
  866. return;
  867. }
  868. BOOL
  869. CMonitorEvents::CreateProcess_(TCHAR * pCmdLine,
  870. CMonitorEvents * pMonitor,
  871. ResyncPerfTask * pPerf)
  872. {
  873. BOOL bRes = FALSE;
  874. STARTUPINFO si;
  875. PROCESS_INFORMATION ProcInfo;
  876. memset(&si,0,sizeof(STARTUPINFO));
  877. si.cb = sizeof(STARTUPINFO);
  878. si.dwFlags = STARTF_FORCEOFFFEEDBACK;
  879. // Get the appropriate cmdline and attach the proper command line switches
  880. LPTSTR pWriteableBuff = GetWMIADAPCmdLine( 64 );
  881. CVectorDeleteMe<TCHAR> vdm( pWriteableBuff );
  882. if ( NULL == pWriteableBuff )
  883. {
  884. ERRORTRACE((LOG_WINMGMT,"Memory Allocation error spawning dredger!\n"));
  885. pMonitor->Lock();
  886. pPerf->bFree = TRUE;
  887. pMonitor->Unlock();
  888. return bRes;
  889. }
  890. #ifdef DEBUG_ADAP
  891. DBG_PRINTFA((pBuff,"Creating process: %S\n",pCmdLine));
  892. #endif
  893. DEBUGTRACE((LOG_WINMGMT,"Creating process: %S\n",pCmdLine));
  894. bRes = CreateProcess(pWriteableBuff,
  895. pCmdLine,
  896. NULL,
  897. NULL,
  898. FALSE,
  899. CREATE_NO_WINDOW,
  900. NULL,
  901. NULL,
  902. &si,
  903. &ProcInfo);
  904. if (bRes)
  905. {
  906. CloseHandle(ProcInfo.hThread);
  907. pPerf->hProcess = ProcInfo.hProcess;
  908. if (RegisterWaitForSingleObject(&pPerf->hWaitHandle,
  909. pPerf->hProcess,
  910. CMonitorEvents::EventCallBack,
  911. pPerf,
  912. pMonitor->m_dwTimeToKillAdap,
  913. WT_EXECUTEONLYONCE|WT_EXECUTEINWAITTHREAD))
  914. {
  915. //
  916. // we don't need to free the slot,
  917. // because the event callback will do that
  918. //
  919. }
  920. else
  921. {
  922. DEBUGTRACE((LOG_WINMGMT,"Unable to schedule WmiADAP process termination handler: err %d\n",GetLastError()));
  923. CloseHandle(pPerf->hProcess);
  924. pPerf->hProcess = NULL;
  925. pMonitor->Lock();
  926. pPerf->bFree = TRUE;
  927. pMonitor->Unlock();
  928. }
  929. }
  930. else
  931. {
  932. ERRORTRACE((LOG_WINMGMT,"CreatProcess %S err: %d\n",pWriteableBuff,GetLastError()));
  933. pMonitor->Lock();
  934. pPerf->bFree = TRUE;
  935. pMonitor->Unlock();
  936. }
  937. return bRes;
  938. }
  939. VOID NTAPI
  940. CMonitorEvents::EventCallBack(VOID * pContext,BOOLEAN bTimerFired)
  941. {
  942. if (!GLOB_Monitor_IsRegistred()) return;
  943. ResyncPerfTask * pPerf = (ResyncPerfTask *)pContext;
  944. if (!pPerf || (SIG_RESYNC_PERF != pPerf->dwSig)) return;
  945. CMonitorEvents * pMonitor = pPerf->pMonitor;
  946. HANDLE hProcess = pPerf->hProcess;
  947. if(bTimerFired)
  948. {
  949. //
  950. // The LONG time-out for our process has expired
  951. // Kill The Process
  952. //
  953. TerminateProcess(pPerf->hProcess,0);
  954. #ifdef DEBUG_ADAP
  955. DBG_PRINTFA((pBuff,"WmiADAP did not finish within %d msec\n",pMonitor->m_dwTimeToKillAdap));
  956. #endif
  957. ERRORTRACE((LOG_WINMGMT,"the ResyncTask of type %d timed-out and has been killed\n",pPerf->Type));
  958. }
  959. else
  960. {
  961. //
  962. // the handle has been signaled, meaning that
  963. // the process exited normally
  964. //
  965. #ifdef DEBUG_ADAP
  966. DBG_PRINTFA((pBuff,"ResyncPerf for task %d completed\n",pPerf->Type));
  967. #endif
  968. }
  969. CloseHandle(pPerf->hProcess);
  970. //
  971. // if there was a call to ProcessIdleTasks
  972. // if we were forced to unthrottle the running tasks
  973. // revert back
  974. //
  975. if (RESYNC_TYPE_PENDING_TASKS == pPerf->Type)
  976. {
  977. pMonitor->m_bFullReverseNeeded = FALSE;
  978. DoThrottleDredges();
  979. #ifdef DEBUG_ADAP
  980. DBG_PRINTFA((pBuff,"Setting the WMI_ProcessIdleTasksComplete\n"));
  981. #endif
  982. if (GLOB_GetMonitor()->IsRegistred())
  983. SetEvent(GLOB_GetMonitor()->GetTaskCompleteEvent());
  984. }
  985. else // a process has exited or it has been terminated
  986. {
  987. LONG nProc = InterlockedDecrement(&pMonitor->m_OutStandingProcesses);
  988. #ifdef DEBUG_ADAP
  989. DBG_PRINTFA((pBuff,"(-) Outstanding Tasks %d\n",pMonitor->m_OutStandingProcesses));
  990. #endif
  991. if (0 == nProc &&
  992. pMonitor->m_bFullReverseNeeded)
  993. {
  994. // Create Here the process
  995. CMonitorEvents * pMonitor = GLOB_GetMonitor();
  996. ResyncPerfTask * pPerfTask = pMonitor->GetAvailable(RESYNC_TYPE_PENDING_TASKS);
  997. if (pPerfTask)
  998. {
  999. TCHAR pCmdLine[64];
  1000. StringCchCopy(pCmdLine,64,TEXT("wmiadap.exe "));
  1001. StringCchCat(pCmdLine,64,g_Strings[pPerfTask->CmdType]);
  1002. CMonitorEvents::CreateProcess_(pCmdLine,pMonitor,pPerfTask);
  1003. }
  1004. else
  1005. {
  1006. #ifdef DEBUG_ADAP
  1007. DBG_PRINTFA((pBuff,"GetAvailable(RESYNC_TYPE_PENDING_TASKS) returned NULL\n"));
  1008. #endif
  1009. }
  1010. }
  1011. }
  1012. pPerf->hProcess = NULL;
  1013. pMonitor->Lock();
  1014. pPerf->bFree = TRUE;
  1015. pMonitor->Unlock();
  1016. UnregisterWaitEx(pPerf->hWaitHandle,NULL);
  1017. pPerf->hWaitHandle = NULL;
  1018. }
  1019. //
  1020. // This is the main function executed when
  1021. // -1- the LoadCtr/UnlaodCtr events are set
  1022. // -2- the Unthrottle events is set by Schedule via the API exposed in Advapi32
  1023. // -3- it runs the 4-minutes-after-boot dredge
  1024. // This function also take care of Reverse-Adapter dredges, if needed
  1025. //
  1026. ////////////////////////////////////////////////////////////////
  1027. VOID NTAPI
  1028. CMonitorEvents::TimerCallBack(VOID * pContext,BOOLEAN bTimerFired)
  1029. {
  1030. if (!GLOB_Monitor_IsRegistred())
  1031. {
  1032. return;
  1033. }
  1034. if(bTimerFired)
  1035. {
  1036. ResyncPerfTask * pPerf = (ResyncPerfTask *)pContext;
  1037. CMonitorEvents * pMonitor = pPerf->pMonitor;
  1038. BOOL bFreeSlot = FALSE;
  1039. #ifdef DEBUG_ADAP
  1040. DBG_PRINTFA((pBuff,"TIMER: Command Type %x\n",pPerf->Type));
  1041. #endif
  1042. // check if the Delta Task was disabled on the Fly
  1043. if (!pPerf->Enabled)
  1044. {
  1045. #ifdef DEBUG_ADAP
  1046. DBG_PRINTFA((pBuff,"Task %d was disabled on the fly\n",pPerf->Type));
  1047. #endif
  1048. bFreeSlot = TRUE;
  1049. goto unregister_timer;
  1050. }
  1051. BOOL bDoSomething = TRUE;
  1052. BOOL RunDeltaLogic = TRUE;
  1053. BOOL AddReverseAdapter = FALSE;
  1054. BOOL WDMTriggeredReverseAdapter = FALSE;
  1055. BOOL bDoFullSystemReverseHere = FALSE;
  1056. if (RESYNC_TYPE_PENDING_TASKS == pPerf->Type)
  1057. {
  1058. pMonitor->Lock();
  1059. // here disable tasks that are on the wait list
  1060. for (DWORD i=0;i<RESYNC_TYPE_MAX;i++)
  1061. {
  1062. if (RESYNC_TYPE_PENDING_TASKS != i)
  1063. {
  1064. if (pMonitor->m_ResyncTasks[i].hTimer)
  1065. {
  1066. #ifdef DEBUG_ADAP
  1067. DBG_PRINTFA((pBuff,"Disabling the pending task %d\n",i));
  1068. #endif
  1069. pMonitor->m_ResyncTasks[i].Enabled = FALSE;
  1070. }
  1071. }
  1072. }
  1073. pMonitor->Unlock();
  1074. // now check if the are processes running
  1075. DoUnThrottleDredges();
  1076. if (pMonitor->m_OutStandingProcesses)
  1077. {
  1078. pMonitor->m_bFullReverseNeeded = TRUE;
  1079. // no need to CreateProcess, the last outstanding process will do that
  1080. #ifdef DEBUG_ADAP
  1081. DBG_PRINTFA((pBuff,"OutStandingProcess, no CreateProcessHere\n"));
  1082. #endif
  1083. bFreeSlot = TRUE;
  1084. goto unregister_timer;
  1085. }
  1086. else // no processes outstanding, create the process now
  1087. {
  1088. bDoFullSystemReverseHere = TRUE;
  1089. #ifdef DEBUG_ADAP
  1090. DBG_PRINTFA((pBuff,"GOTO CreateProcess\n"));
  1091. #endif
  1092. goto createprocess_label;
  1093. }
  1094. }
  1095. if (RESYNC_TYPE_INITIAL == pPerf->Type )
  1096. {
  1097. // check if the Reverse Adapters need a Delta
  1098. LONG lRet;
  1099. HKEY hKey;
  1100. DWORD dwTemp;
  1101. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1102. WBEM_REG_REVERSE_KEY,
  1103. NULL,
  1104. KEY_READ,
  1105. &hKey);
  1106. if (ERROR_SUCCESS == lRet)
  1107. {
  1108. DWORD dwType;
  1109. DWORD dwSize = sizeof(DWORD);
  1110. DWORD dwVal;
  1111. lRet = RegQueryValueEx(hKey,
  1112. WBEM_REG_REVERSE_VALUE,
  1113. NULL,
  1114. &dwType,
  1115. (BYTE *)&dwVal,
  1116. &dwSize);
  1117. // if the key is there, is NULL and it is of the right type
  1118. // OR if the key is not there
  1119. if( ERROR_SUCCESS == lRet &&
  1120. REG_DWORD == dwType &&
  1121. dwVal )
  1122. {
  1123. AddReverseAdapter = TRUE;
  1124. #ifdef DEBUG_ADAP
  1125. DBG_PRINTFA((pBuff,"\"Performance Refresh\" key set to %d\n",dwVal));
  1126. #endif
  1127. DEBUGTRACE((LOG_WINMGMT,"\"Performance Refresh\" key set to %d\n",dwVal));
  1128. }
  1129. RegCloseKey(hKey);
  1130. }
  1131. // check the WDM stuff
  1132. if (!AddReverseAdapter)
  1133. {
  1134. #ifdef DBG
  1135. if (!HeapValidate(GetProcessHeap(),0,NULL))
  1136. {
  1137. DebugBreak();
  1138. }
  1139. if (!HeapValidate(CWin32DefaultArena::GetArenaHeap(),0,NULL))
  1140. {
  1141. DebugBreak();
  1142. }
  1143. #endif
  1144. CWMIBinMof BinMof;
  1145. //=============================================================================
  1146. // Note: this combo will always succeed, as all the initialize is doing is
  1147. // setting a flag to FALSE and returning S_OK
  1148. //=============================================================================
  1149. if( SUCCEEDED( BinMof.Initialize(NULL,FALSE) ) )
  1150. {
  1151. WDMTriggeredReverseAdapter = BinMof.BinaryMofsHaveChanged();
  1152. if (WDMTriggeredReverseAdapter)
  1153. {
  1154. // override the previous decition
  1155. AddReverseAdapter = TRUE;
  1156. #ifdef DEBUG_ADAP
  1157. DBG_PRINTFA((pBuff,"BinaryMofs DO HAVE changed\n"));
  1158. #endif
  1159. DEBUGTRACE((LOG_WINMGMT,"CWMIBinMof.BinaryMofsHaveChanged == TRUE\n"));
  1160. }
  1161. #ifdef DBG
  1162. if (!HeapValidate(GetProcessHeap(),0,NULL))
  1163. {
  1164. DebugBreak();
  1165. }
  1166. if (!HeapValidate(CWin32DefaultArena::GetArenaHeap(),0,NULL))
  1167. {
  1168. DebugBreak();
  1169. }
  1170. #endif
  1171. }
  1172. }
  1173. // overrides delta with full, if the case
  1174. if (WMIADAP_DEFAULT_TIMETOFULL == pMonitor->GetFullTime())
  1175. {
  1176. // no override
  1177. }
  1178. else // read timestamp and decide
  1179. {
  1180. ULARGE_INTEGER li;
  1181. li.LowPart = pMonitor->GetTimeStamp().dwLowDateTime;
  1182. li.HighPart = pMonitor->GetTimeStamp().dwHighDateTime;
  1183. __int64 Seconds = pMonitor->GetFullTime();
  1184. Seconds *= 10000000; // number of 100ns units in 1 second
  1185. ULARGE_INTEGER liNow;
  1186. GetSystemTimeAsFileTime((FILETIME *)&liNow);
  1187. if ((li.QuadPart + Seconds) < liNow.QuadPart)
  1188. {
  1189. pPerf->CmdType = RESYNC_FULL_THROTTLE;
  1190. RunDeltaLogic = FALSE;
  1191. }
  1192. }
  1193. } // end if command type initial
  1194. if ((RESYNC_TYPE_INITIAL == pPerf->Type) && RunDeltaLogic)
  1195. {
  1196. DWORD ret = DeltaDredge2(0,NULL);
  1197. #ifdef DEBUG_ADAP
  1198. DBG_PRINTFA((pBuff,"DeltaDredge2 ret %d\n",ret));
  1199. #endif
  1200. switch(ret)
  1201. {
  1202. case FULL_DREDGE:
  1203. pPerf->CmdType = RESYNC_FULL_THROTTLE;
  1204. break;
  1205. case PARTIAL_DREDGE:
  1206. pPerf->CmdType = RESYNC_DELTA_THROTTLE;
  1207. break;
  1208. case NO_DREDGE:
  1209. //
  1210. // this is the case where we do nothing
  1211. DEBUGTRACE((LOG_WINMGMT,"No Dredge to run\n"));
  1212. //
  1213. bDoSomething = FALSE;
  1214. break;
  1215. default:
  1216. //
  1217. // never here
  1218. //
  1219. break;
  1220. }
  1221. #ifdef DEBUG_ADAP
  1222. DBG_PRINTFA((pBuff,"DeltaDredge2() ret = %d, bDoSomething = %d \n",ret,bDoSomething));
  1223. #endif
  1224. DEBUGTRACE((LOG_WINMGMT,"DeltaDredge2() ret = %d, bDoSomething = %d \n",ret,bDoSomething));
  1225. }
  1226. if (bDoSomething || AddReverseAdapter)
  1227. {
  1228. createprocess_label:
  1229. TCHAR pCmdLine[64];
  1230. StringCchCopy(pCmdLine,64,TEXT("wmiadap.exe "));
  1231. if (bDoFullSystemReverseHere)
  1232. {
  1233. StringCchCat(pCmdLine,64,g_Strings[pPerf->CmdType]);
  1234. }
  1235. else
  1236. {
  1237. if (bDoSomething && AddReverseAdapter)
  1238. {
  1239. StringCchCat(pCmdLine,64,g_Strings[pPerf->CmdType]);
  1240. StringCchCat(pCmdLine,64,TEXT(" /R"));
  1241. }
  1242. if (bDoSomething && !AddReverseAdapter)
  1243. {
  1244. StringCchCat(pCmdLine,64,g_Strings[pPerf->CmdType]);
  1245. }
  1246. if (!bDoSomething && AddReverseAdapter)
  1247. {
  1248. StringCchCat(pCmdLine,64,g_Strings[RESYNC_RADAPD_THROTTLE]);
  1249. }
  1250. }
  1251. CMonitorEvents::CreateProcess_(pCmdLine,pMonitor,pPerf);
  1252. if (GLOB_GetMonitor()->IsRegistred())
  1253. {
  1254. if (!bDoFullSystemReverseHere)
  1255. {
  1256. InterlockedIncrement(&(GLOB_GetMonitor()->m_OutStandingProcesses));
  1257. #ifdef DEBUG_ADAP
  1258. DBG_PRINTFA((pBuff,"(+) Outstanding Tasks %d\n",GLOB_GetMonitor()->m_OutStandingProcesses));
  1259. #endif
  1260. }
  1261. }
  1262. }
  1263. else
  1264. {
  1265. pMonitor->Lock();
  1266. pPerf->bFree = TRUE;
  1267. pMonitor->Unlock();
  1268. }
  1269. unregister_timer:
  1270. if (bFreeSlot)
  1271. {
  1272. pMonitor->Lock();
  1273. pPerf->bFree = TRUE;
  1274. pMonitor->Unlock();
  1275. }
  1276. DeleteTimerQueueTimer(NULL,pPerf->hTimer,NULL);
  1277. pPerf->hTimer = NULL;
  1278. pPerf->Enabled = TRUE;
  1279. }
  1280. else
  1281. {
  1282. // never here
  1283. _DBG_ASSERT(FALSE);
  1284. }
  1285. }
  1286. //
  1287. //
  1288. //
  1289. ///////////////////////////////////////////////
  1290. DWORD ResyncPerf(DWORD dwReason)
  1291. {
  1292. if(!GLOB_IsResyncAllowed())
  1293. {
  1294. ERRORTRACE((LOG_WINMGMT,"ResyncPerf disable g_fSetup or g_fDoResync\n"));
  1295. return 0;
  1296. }
  1297. ResyncPerfTask * pPerfTask = GLOB_GetMonitor()->GetAvailable(dwReason);
  1298. if (pPerfTask)
  1299. {
  1300. // here you have the slot for execution
  1301. // tell Reverse_Adapter that it's scheduled
  1302. if (RESYNC_TYPE_WDMEVENT == dwReason ||
  1303. RESYNC_TYPE_CLASSCREATION == dwReason)
  1304. {
  1305. LONG lRet;
  1306. HKEY hKey;
  1307. DWORD dwTemp;
  1308. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1309. WBEM_REG_REVERSE_KEY,
  1310. NULL,
  1311. KEY_READ|KEY_WRITE,
  1312. &hKey);
  1313. if (ERROR_SUCCESS == lRet)
  1314. {
  1315. DWORD dwType;
  1316. DWORD dwSize = sizeof(DWORD);
  1317. DWORD dwVal;
  1318. lRet = RegQueryValueEx(hKey,
  1319. WBEM_REG_REVERSE_VALUE,
  1320. NULL,
  1321. &dwType,
  1322. (BYTE *)&dwVal,
  1323. &dwSize);
  1324. // if the key is there, is NULL and it is of the right type
  1325. // OR if the key is not there
  1326. if((ERROR_SUCCESS == lRet &&
  1327. REG_DWORD == dwType &&
  1328. 0 == dwVal) ||
  1329. (ERROR_FILE_NOT_FOUND == lRet))
  1330. {
  1331. dwVal = 1;
  1332. RegSetValueEx(hKey,
  1333. WBEM_REG_REVERSE_VALUE,
  1334. 0,
  1335. REG_DWORD,
  1336. (BYTE *)&dwVal,
  1337. sizeof(DWORD));
  1338. }
  1339. RegCloseKey(hKey);
  1340. }
  1341. };
  1342. if (CreateTimerQueueTimer(&pPerfTask->hTimer,
  1343. NULL,
  1344. CMonitorEvents::TimerCallBack,
  1345. pPerfTask,
  1346. pPerfTask->dwTimeDue,
  1347. 0,
  1348. WT_EXECUTEONLYONCE|WT_EXECUTELONGFUNCTION))
  1349. {
  1350. return 0;
  1351. }
  1352. else
  1353. {
  1354. // ERRORTRACE
  1355. return GetLastError();
  1356. }
  1357. }
  1358. else
  1359. {
  1360. // no slot availables
  1361. return ERROR_BUSY;
  1362. }
  1363. }
  1364. //
  1365. //
  1366. // This function is called by the Hook installed in wbemcore
  1367. // that monitors class creation
  1368. //
  1369. ///////////////////////////////////////////
  1370. DWORD __stdcall
  1371. DredgeRA(VOID * pReserved)
  1372. {
  1373. //DBG_PRINTFA((pBuff,"Classes\n"));
  1374. return ResyncPerf(RESYNC_TYPE_CLASSCREATION);
  1375. };