Source code of Windows XP (NT5)
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.

1949 lines
46 KiB

  1. #include "precomp.h"
  2. #include <winsvc.h>
  3. #include <tchar.h>
  4. #include <persistcfg.h>
  5. #include <winntsec.h>
  6. #include "cntserv.h"
  7. #include "winmgmt.h"
  8. #include "sched.h"
  9. #include "resync2.h"
  10. #include <malloc.h>
  11. //***********************************************************************
  12. //
  13. // Defines
  14. //
  15. //***********************************************************************
  16. #define CORE_PROVIDER_UNLOAD_TIMEOUT ( 30 * 1000 )
  17. //***********************************************************************
  18. //
  19. // Globals
  20. //
  21. //***********************************************************************
  22. HINSTANCE g_hInstance;
  23. //***********************************************************************
  24. //
  25. // Dll Entry points and export points
  26. //
  27. //***********************************************************************
  28. BOOL APIENTRY DllMain( HINSTANCE hModule,
  29. DWORD ul_reason_for_call,
  30. LPVOID lpReserved
  31. )
  32. {
  33. switch(ul_reason_for_call){
  34. case DLL_PROCESS_ATTACH:
  35. g_hInstance = hModule;
  36. DisableThreadLibraryCalls(hModule);
  37. break;
  38. case DLL_PROCESS_DETACH:
  39. break;
  40. }
  41. return TRUE;
  42. };
  43. //
  44. //
  45. // InitialBreak
  46. //
  47. ///////////////////////////////////////////////////////////
  48. BOOL
  49. InitialBreak()
  50. {
  51. HKEY hKey;
  52. LONG lRet;
  53. BOOL bRet = FALSE;
  54. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  55. HOME_REG_PATH,
  56. 0,
  57. KEY_READ,
  58. &hKey);
  59. if (ERROR_SUCCESS == lRet)
  60. {
  61. DWORD dwType;
  62. DWORD dwVal;
  63. DWORD dwSize = sizeof(DWORD);
  64. lRet = RegQueryValueEx(hKey,
  65. INITIAL_BREAK,
  66. NULL,
  67. &dwType,
  68. (BYTE *)&dwVal,
  69. &dwSize);
  70. if (ERROR_SUCCESS == lRet &&
  71. dwType == REG_DWORD &&
  72. dwVal)
  73. {
  74. bRet = TRUE;
  75. }
  76. RegCloseKey(hKey);
  77. }
  78. return bRet;
  79. }
  80. //
  81. // the global structure
  82. //
  83. struct _PROG_RESOURCES g_ProgRes;
  84. void
  85. _PROG_RESOURCES::Init()
  86. {
  87. m_hExclusive = NULL;
  88. m_hTerminateEvent = NULL;
  89. m_bOleInitialized = NULL;
  90. m_pLoginFactory = NULL;
  91. m_pBackupFactory = NULL;
  92. m_dwLoginClsFacReg = 0;
  93. m_dwBackupClsFacReg = 0;
  94. g_fSetup = FALSE;
  95. g_fDoResync = TRUE;
  96. hMainMutex = NULL;
  97. bShuttingDownWinMgmt = FALSE;
  98. gbCoreLoaded = FALSE;
  99. ServiceStatus = SERVICE_STOPPED;
  100. ghCoreCanUnload = NULL;
  101. ghProviderCanUnload = NULL;
  102. ghCoreUnloaded = NULL;
  103. ghCoreLoaded = NULL;
  104. ghNeedRegistration = NULL;
  105. ghRegistrationDone = NULL;
  106. ghMofDirChange = NULL;
  107. ghLoadCtrEvent = NULL;
  108. ghUnloadCtrEvent = NULL;
  109. ghHoldOffNewClients = NULL;
  110. szHotMofDirectory = NULL;
  111. pWbemVssWriter = NULL;
  112. bWbemVssWriterSubscribed = false;
  113. };
  114. BOOL
  115. _PROG_RESOURCES::Phase1Build()
  116. {
  117. hMainMutex = CreateMutex(NULL, FALSE, NULL);
  118. g_fSetup = CheckSetupSwitch();
  119. if ( g_fSetup )
  120. {
  121. SetNoShellADAPSwitch();
  122. }
  123. // Look in the registry to decide if we will launch a resync perf or not
  124. g_fDoResync = CheckNoResyncSwitch();
  125. //
  126. // set this to have the Console Control Handler notification
  127. //
  128. SetProcessShutdownParameters(0x400,0);
  129. //
  130. // set to some defined value parames that might be outstanding if someone killed us
  131. //
  132. RegSetDWORD(HKEY_LOCAL_MACHINE,HOME_REG_PATH,DO_THROTTLE,1);
  133. return hMainMutex?TRUE:FALSE;
  134. };
  135. BOOL
  136. _PROG_RESOURCES::Phase2Build(HANDLE hTerminateEvt)
  137. {
  138. ghCoreCanUnload = CreateEvent(NULL,FALSE,FALSE,
  139. TEXT("WINMGMT_COREDLL_CANSHUTDOWN"));
  140. ghProviderCanUnload = CreateEvent(NULL,FALSE,FALSE,
  141. TEXT("WINMGMT_PROVIDER_CANSHUTDOWN"));
  142. SetEventDacl(ghProviderCanUnload,EVENT_ALL_ACCESS);
  143. ghCoreUnloaded = CreateEvent(NULL,FALSE,FALSE,
  144. TEXT("WINMGMT_COREDLL_UNLOADED"));
  145. ghCoreLoaded = CreateEvent(NULL,FALSE,FALSE,
  146. TEXT("WINMGMT_COREDLL_LOADED"));
  147. m_hTerminateEvent = CreateEvent(NULL,TRUE,FALSE,
  148. TEXT("WINMGMT_MARSHALLING_SERVER_TERMINATE"));
  149. if(m_hTerminateEvent == NULL)
  150. {
  151. TRACE((LOG_WINMGMT,"\nWINMGMT terminating because CreateEvent, last error = 0x%x\n",
  152. GetLastError()));
  153. return FALSE;
  154. }
  155. DWORD dwRet;
  156. m_hExclusive = CreateMutex( NULL, FALSE, TEXT("WINMGMT_MARSHALLING_SERVER"));
  157. if(m_hExclusive)
  158. dwRet = WaitForSingleObject(m_hExclusive, 0);
  159. if(m_hExclusive == NULL || dwRet != WAIT_OBJECT_0)
  160. {
  161. if(m_hExclusive)
  162. CloseHandle(m_hExclusive);
  163. m_hExclusive = NULL;
  164. TRACE((LOG_WINMGMT,"\nWINMGMT terminating an existing copy was detected"));
  165. return FALSE;
  166. }
  167. ghNeedRegistration = CreateEvent(NULL,TRUE,FALSE, __TEXT("WINMGMT_NEED_REGISTRATION"));
  168. SetObjectAccess2(ghNeedRegistration);
  169. ghRegistrationDone = CreateEvent(NULL,TRUE,FALSE, __TEXT("WINMGMT_REGISTRATION_DONE"));
  170. SetObjectAccess2(ghRegistrationDone);
  171. ghHoldOffNewClients = CreateMutex(NULL, FALSE, __TEXT("WINMGMT_KEEP_NEW_CLIENTS_AT_BAY"));
  172. if(ghHoldOffNewClients == NULL)
  173. ghHoldOffNewClients = OpenMutex(SYNCHRONIZE, FALSE, __TEXT("WINMGMT_KEEP_NEW_CLIENTS_AT_BAY"));
  174. if(ghNeedRegistration == NULL || ghRegistrationDone == NULL ||
  175. ghHoldOffNewClients == NULL)
  176. {
  177. TRACE((LOG_WINMGMT,"\nWINMGMT couldnt create the sync objects"));
  178. return FALSE;
  179. }
  180. if (!m_Monitor.Init())
  181. {
  182. return FALSE;
  183. }
  184. // don't create a writer if during setup
  185. if (!g_fSetup)
  186. {
  187. pWbemVssWriter = new CWbemVssWriter;
  188. if (!pWbemVssWriter)
  189. {
  190. TRACE((LOG_WINMGMT,"\nWINMGMT could not create the VssWriter"));
  191. return FALSE;
  192. }
  193. }
  194. return TRUE;
  195. }
  196. BOOL
  197. _PROG_RESOURCES::RegisterLogin()
  198. {
  199. HRESULT sc;
  200. DWORD dwFlags = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER;
  201. g_ProgRes.m_pLoginFactory = new CForwardFactory(CLSID_InProcWbemLevel1Login);
  202. g_ProgRes.m_pLoginFactory->AddRef();
  203. sc = CoRegisterClassObject(CLSID_WbemLevel1Login,
  204. g_ProgRes.m_pLoginFactory,
  205. dwFlags,
  206. REGCLS_MULTIPLEUSE,
  207. &g_ProgRes.m_dwLoginClsFacReg);
  208. if(sc != S_OK)
  209. {
  210. TRACE((LOG_WINMGMT,"\nFailed to register the "
  211. "CLSID_WbemLevel1Login class factory, "
  212. "sc = 0x%x", sc));
  213. return FALSE;
  214. }
  215. else
  216. {
  217. DEBUGTRACE((LOG_WINMGMT, "\nRegistered class factory with flags: 0x%X\n",
  218. dwFlags));
  219. return TRUE;
  220. }
  221. }
  222. BOOL
  223. _PROG_RESOURCES::RevokeLogin()
  224. {
  225. if(m_pLoginFactory) {
  226. CoRevokeClassObject(m_dwLoginClsFacReg);
  227. m_dwLoginClsFacReg = 0;
  228. m_pLoginFactory->Release();
  229. m_pLoginFactory = NULL;
  230. }
  231. return TRUE;
  232. }
  233. BOOL
  234. _PROG_RESOURCES::RegisterBackup()
  235. {
  236. HRESULT sc;
  237. DWORD dwFlags = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER;
  238. g_ProgRes.m_pBackupFactory = new CForwardFactory(CLSID_WbemBackupRestore);
  239. g_ProgRes.m_pBackupFactory->AddRef();
  240. sc = CoRegisterClassObject(CLSID_WbemBackupRestore,
  241. g_ProgRes.m_pBackupFactory,
  242. dwFlags,
  243. REGCLS_MULTIPLEUSE,
  244. &g_ProgRes.m_dwBackupClsFacReg);
  245. if(sc != S_OK)
  246. {
  247. TRACE((LOG_WINMGMT,"\nFailed to register the "
  248. "Backup/recovery class factory, "
  249. "sc = 0x%x", sc));
  250. return FALSE;
  251. }
  252. else
  253. {
  254. return TRUE;
  255. }
  256. }
  257. BOOL
  258. _PROG_RESOURCES::RevokeBackup()
  259. {
  260. if(m_pBackupFactory) {
  261. CoRevokeClassObject(m_dwBackupClsFacReg);
  262. m_dwBackupClsFacReg = 0;
  263. m_pBackupFactory->Release();
  264. m_pBackupFactory = NULL;
  265. }
  266. return TRUE;
  267. }
  268. _PROG_RESOURCES::Phase1Delete(BOOL bIsSystemShutdown)
  269. {
  270. if (!bIsSystemShutdown)
  271. {
  272. if(ghCoreCanUnload)
  273. {
  274. CloseHandle(ghCoreCanUnload);
  275. ghCoreCanUnload = NULL;
  276. };
  277. if(ghProviderCanUnload)
  278. {
  279. CloseHandle(ghProviderCanUnload);
  280. ghProviderCanUnload = NULL;
  281. }
  282. if(ghCoreUnloaded)
  283. {
  284. CloseHandle(ghCoreUnloaded);
  285. ghCoreUnloaded = NULL;
  286. }
  287. if(ghCoreLoaded)
  288. {
  289. CloseHandle(ghCoreLoaded);
  290. ghCoreLoaded = NULL;
  291. }
  292. if(ghNeedRegistration)
  293. {
  294. CloseHandle(ghNeedRegistration);
  295. ghNeedRegistration = NULL;
  296. }
  297. if(ghRegistrationDone)
  298. {
  299. CloseHandle(ghRegistrationDone);
  300. ghRegistrationDone = NULL;
  301. }
  302. if(ghMofDirChange)
  303. {
  304. CloseHandle(ghMofDirChange);
  305. ghMofDirChange = NULL;
  306. }
  307. }
  308. if (m_Monitor.IsRegistred())
  309. {
  310. m_Monitor.Unregister(bIsSystemShutdown);
  311. }
  312. if (!bIsSystemShutdown)
  313. {
  314. m_Monitor.Uninit();
  315. if(ghHoldOffNewClients)
  316. {
  317. CloseHandle(ghHoldOffNewClients);
  318. ghHoldOffNewClients = NULL;
  319. }
  320. if(m_hTerminateEvent)
  321. {
  322. CloseHandle(m_hTerminateEvent);
  323. m_hTerminateEvent = NULL;
  324. }
  325. if(m_hExclusive)
  326. {
  327. ReleaseMutex(m_hExclusive);
  328. CloseHandle(m_hExclusive);
  329. m_hExclusive = NULL;
  330. }
  331. if(szHotMofDirectory)
  332. {
  333. delete [] szHotMofDirectory;
  334. szHotMofDirectory = NULL;
  335. }
  336. }
  337. // shut down and delete our writer for volume snapshot backup
  338. if (pWbemVssWriter && !bIsSystemShutdown)
  339. {
  340. if (bWbemVssWriterSubscribed)
  341. {
  342. HRESULT hRes = pWbemVssWriter->Unsubscribe();
  343. if (SUCCEEDED(hRes))
  344. {
  345. bWbemVssWriterSubscribed = false;
  346. }
  347. else
  348. {
  349. TRACE((LOG_WINMGMT,"\nWINMGMT Could not unsubscribe the VssWriter"));
  350. }
  351. }
  352. delete pWbemVssWriter;
  353. pWbemVssWriter = NULL;
  354. }
  355. return TRUE;
  356. }
  357. _PROG_RESOURCES::Phase2Delete(BOOL bIsSystemShutdown)
  358. {
  359. if (!bIsSystemShutdown)
  360. {
  361. if(m_pLoginFactory) {
  362. CoRevokeClassObject(m_dwLoginClsFacReg);
  363. m_pLoginFactory->Release();
  364. m_pLoginFactory = NULL;
  365. m_dwLoginClsFacReg = 0;
  366. }
  367. if(m_pBackupFactory) {
  368. CoRevokeClassObject(m_dwBackupClsFacReg);
  369. m_pBackupFactory->Release();
  370. m_pBackupFactory = NULL;
  371. m_dwBackupClsFacReg = 0;
  372. }
  373. if(m_bOleInitialized)
  374. {
  375. CoUninitialize();
  376. m_bOleInitialized = FALSE;
  377. }
  378. }
  379. return TRUE;
  380. }
  381. BOOL
  382. _PROG_RESOURCES::Phase3Delete()
  383. {
  384. if (hMainMutex)
  385. {
  386. CloseHandle(hMainMutex);
  387. hMainMutex = NULL;
  388. }
  389. return TRUE;
  390. }
  391. //
  392. //
  393. // ShutDownCore
  394. //
  395. //
  396. /////////////////////////////////////////////////////////////////
  397. bool ShutDownCore(BOOL bProcessShutdown,BOOL bIsSystemShutDown)
  398. {
  399. SCODE sc = WBEM_E_FAILED;
  400. HMODULE hCoreModule = LoadLibrary(__TEXT("wbemcore.dll"));
  401. if(hCoreModule)
  402. {
  403. pfnShutDown pfn = (pfnShutDown)GetProcAddress(hCoreModule, "Shutdown");
  404. if(pfn)
  405. {
  406. sc = (pfn)(bProcessShutdown,bIsSystemShutDown);
  407. DEBUGTRACE((LOG_WINMGMT, "core is being shut down by WinMgmt.exe, it returned 0x%x",sc));
  408. }
  409. FreeLibrary(hCoreModule);
  410. }
  411. return sc == S_OK;
  412. }
  413. //
  414. //
  415. // void Cleanup
  416. //
  417. //
  418. // Release any currently loaded transports and close Ole etc.
  419. //
  420. //
  421. ///////////////////////////////////////////////////////////////////
  422. void Cleanup(BOOL bIsSystemShutDown)
  423. {
  424. //DBG_PRINTFA((pBuff,"Cleanup called\n"));
  425. if (!bIsSystemShutDown)
  426. {
  427. DEBUGTRACE((LOG_WINMGMT,"\nStarting cleanup, ID = %x", GetCurrentProcessId()));
  428. CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
  429. CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
  430. }
  431. g_ProgRes.Phase1Delete(bIsSystemShutDown);
  432. // If the core is still loaded, call its shutdown function
  433. ShutDownCore(TRUE,bIsSystemShutDown);
  434. g_ProgRes.Phase2Delete(bIsSystemShutDown);
  435. if (!bIsSystemShutDown)
  436. {
  437. DEBUGTRACE((LOG_WINMGMT,"\nEnding cleanup"));
  438. }
  439. return;
  440. }
  441. //
  442. //
  443. // BOOL Initialize
  444. //
  445. //
  446. ///////////////////////////////////////////////////////////////
  447. BOOL Initialize(HANDLE hTerminateEvt)
  448. {
  449. // Set the error mode. This is used to provent the system from putting up dialog boxs to
  450. // open files
  451. UINT errormode = SetErrorMode(0);
  452. errormode |= SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS;
  453. SetErrorMode(errormode);
  454. int iCnt;
  455. TCHAR tcName[MAX_PATH+1];
  456. DEBUGTRACE((LOG_WINMGMT,"\nStarting Initialize, ID = %x", GetCurrentProcessId()));
  457. if(!InitHotMofStuff(&g_ProgRes))
  458. return FALSE;
  459. if (!g_ProgRes.Phase2Build(hTerminateEvt))
  460. return FALSE;
  461. // Initialize Ole
  462. SCODE sc;
  463. sc = CoInitializeEx(NULL,COINIT_MULTITHREADED);
  464. if(FAILED(sc))
  465. {
  466. TRACE((LOG_WINMGMT,"\nWINMGMT Could not initialize Ole\n"));
  467. return FALSE;
  468. }
  469. else
  470. {
  471. g_ProgRes.m_bOleInitialized = TRUE;
  472. }
  473. //
  474. // Call the initialize function in core
  475. //
  476. HMODULE hCoreModule = GetModuleHandle(_T("wbemcore.dll"));
  477. if(hCoreModule)
  478. {
  479. HRESULT (STDAPICALLTYPE *pfn)(DWORD);
  480. pfn = (long (__stdcall *)(DWORD))GetProcAddress(hCoreModule, "Reinitialize");
  481. if(pfn)
  482. {
  483. sc = (*pfn)(0);
  484. DEBUGTRACE((LOG_WINMGMT, "core is being resumed: it returned 0x%x",sc));
  485. }
  486. else
  487. {
  488. DEBUGTRACE((LOG_WINMGMT, "failed to re-initialize core"));
  489. return FALSE;
  490. }
  491. }
  492. g_ProgRes.RegisterLogin();
  493. g_ProgRes.RegisterBackup();
  494. g_ProgRes.ServiceStatus = SERVICE_RUNNING;
  495. // Get the registry key which is the root for all the transports.
  496. // ==============================================================
  497. HKEY hKey;
  498. long lRet = RegOpenKey(HKEY_LOCAL_MACHINE,
  499. TEXT("Software\\Microsoft\\WBEM\\CIMOM\\TRANSPORTS"),
  500. &hKey);
  501. if(lRet != ERROR_SUCCESS)
  502. {
  503. DEBUGTRACE((LOG_WINMGMT,"\nRegOpenKey returned 0x%x while trying to open the transports node. Using default transports!",lRet));
  504. }
  505. else
  506. {
  507. /*
  508. // Loop through each transport subkey.
  509. // ===================================
  510. for(iCnt = 0;ERROR_SUCCESS == RegEnumKey(hKey,iCnt,tcName,MAX_PATH+1);
  511. iCnt++)
  512. {
  513. HKEY hSubKey;
  514. lRet = RegOpenKey(hKey,tcName,&hSubKey);
  515. if(lRet != ERROR_SUCCESS)
  516. continue;
  517. DWORD bytecount = sizeof(DWORD);
  518. DWORD dwType;
  519. // If the Enabled value isnt 1, then the transport is disabled
  520. // and is ignored.
  521. // ===========================================================
  522. char cTemp[20];
  523. bytecount=20;
  524. lRet = RegQueryValueEx(hSubKey, TEXT("Enabled"), NULL, &dwType,
  525. (LPBYTE) cTemp, &bytecount);
  526. if(lRet != ERROR_SUCCESS || dwType != REG_SZ || cTemp[0] != '1')
  527. {
  528. RegCloseKey(hSubKey);
  529. continue;
  530. }
  531. // Read the CLSID string and convert it into an CLSID structure.
  532. // =============================================================
  533. TCHAR szCLSID[50];
  534. bytecount = sizeof(szCLSID);
  535. lRet = RegQueryValueEx(hSubKey, TEXT("CLSID"), NULL, &dwType,
  536. (LPBYTE) &szCLSID, &bytecount);
  537. RegCloseKey(hSubKey);
  538. if(lRet != ERROR_SUCCESS)
  539. {
  540. continue;
  541. }
  542. CLSID clsid;
  543. sc = CLSIDFromString( szCLSID, &clsid);
  544. if(sc != S_OK)
  545. {
  546. continue;
  547. }
  548. // Load up the transport object and then initialize it.
  549. // ====================================================
  550. IWbemTransport * pTransport = NULL;
  551. sc = CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER,
  552. IID_IWbemTransport, (LPVOID *) &pTransport);
  553. if(sc != S_OK || pTransport == NULL)
  554. {
  555. continue;
  556. }
  557. sc = pTransport->Initialize();
  558. if(sc != S_OK)
  559. pTransport->Release();
  560. else
  561. g_ProgRes.m_TransportArray.Add(pTransport); // add it to the list
  562. }
  563. */
  564. RegCloseKey(hKey);
  565. };
  566. // initialize our writer for volume snapshot backup
  567. // this must be after CoInitializeEx and after wbem is initialized
  568. // (this pointer will be NULL during setup)
  569. if (g_ProgRes.pWbemVssWriter)
  570. {
  571. HRESULT hRes = g_ProgRes.pWbemVssWriter->Initialize();
  572. if (SUCCEEDED(hRes))
  573. {
  574. hRes = g_ProgRes.pWbemVssWriter->Subscribe();
  575. if (SUCCEEDED(hRes))
  576. {
  577. g_ProgRes.bWbemVssWriterSubscribed = true;
  578. }
  579. else
  580. {
  581. TRACE((LOG_WINMGMT,"\nWINMGMT Could not subscribe the VssWriter"));
  582. }
  583. }
  584. else
  585. {
  586. TRACE((LOG_WINMGMT,"\nWINMGMT Could not initialize the VssWriter"));
  587. }
  588. }
  589. DEBUGTRACE((LOG_WINMGMT,"\nInitialize complete"));
  590. // TO BE REPLACED WITH PROPER CODING --- FORCE CORE
  591. // ================================================
  592. return TRUE;
  593. }
  594. //
  595. //
  596. // WaitingFunction
  597. //
  598. // DESCRIPTION:
  599. //
  600. // Here is where we wait for messages and events during WinMgmt execution.
  601. // We return from here when the program/service is being stopped.
  602. //
  603. //////////////////////////////////////////////////////////////////
  604. void WaitingFunction(HANDLE hTerminate)
  605. {
  606. CSched sched;
  607. DEBUGTRACE((LOG_WINMGMT,"\nInside the waiting function"));
  608. HANDLE hEvents[] = {hTerminate,
  609. g_ProgRes.ghCoreCanUnload,
  610. g_ProgRes.ghCoreUnloaded,
  611. g_ProgRes.ghCoreLoaded,
  612. g_ProgRes.ghNeedRegistration,
  613. g_ProgRes.ghProviderCanUnload,
  614. g_ProgRes.ghMofDirChange // important, must be last entry!!!!
  615. };
  616. int iNumEvents = sizeof(hEvents) / sizeof(HANDLE);
  617. DWORD dwFlags;
  618. SCODE sc;
  619. CPersistentConfig per;
  620. per.TidyUp();
  621. sched.SetWorkItem(PossibleStartCore, 60000);
  622. //Load any MOFs in the MOF directory if needed...
  623. LoadMofsInDirectory(g_ProgRes.szHotMofDirectory);
  624. // resync the perf counters if
  625. // we haven't turned this off for debugging AND
  626. // we are not running during setup
  627. if(GLOB_IsResyncAllowed())
  628. {
  629. ResyncPerf(RESYNC_TYPE_INITIAL);
  630. GLOB_GetMonitor()->Register();
  631. }
  632. while(TRUE)
  633. {
  634. DWORD dwDelay = sched.GetWaitPeriod();
  635. DWORD dwObj = WaitForMultipleObjects(iNumEvents, hEvents, FALSE, dwDelay);
  636. switch (dwObj)
  637. {
  638. case 0: // bail out for terminate event
  639. {
  640. if (SERVICE_SHUTDOWN != g_ProgRes.ServiceStatus)
  641. {
  642. DEBUGTRACE((LOG_WINMGMT,"\nGot a termination event"));
  643. }
  644. {
  645. CInMutex im(g_ProgRes.hMainMutex);
  646. g_ProgRes.bShuttingDownWinMgmt = TRUE;
  647. }
  648. // call cleanup outside of a Mutex
  649. Cleanup((g_ProgRes.ServiceStatus == SERVICE_SHUTDOWN)?TRUE:FALSE);
  650. }
  651. return;
  652. case 1: // core can unload
  653. DEBUGTRACE((LOG_WINMGMT,"\nGot a core can unload event"));
  654. sched.SetWorkItem(FirstCoreShutdown, 30000); // 30 seconds until next unloac;
  655. break;
  656. case 2: // core went away
  657. DEBUGTRACE((LOG_WINMGMT,"\nGot a core unloaded event"));
  658. g_ProgRes.gbCoreLoaded = FALSE;
  659. break;
  660. case 3: // core loaded
  661. DEBUGTRACE((LOG_WINMGMT,"\nGot a core loaded event"));
  662. g_ProgRes.gbCoreLoaded = TRUE;
  663. break;
  664. case 4: // Need Registration
  665. DEBUGTRACE((LOG_WINMGMT,"\nGot a NeedRegistration event"));
  666. if (g_ProgRes.ServiceStatus == SERVICE_RUNNING)
  667. {
  668. g_ProgRes.RevokeLogin();
  669. g_ProgRes.RegisterLogin();
  670. }
  671. SetEvent(g_ProgRes.ghRegistrationDone);
  672. ResetEvent(g_ProgRes.ghNeedRegistration);
  673. break;
  674. case 5: // provider can unload
  675. {
  676. DEBUGTRACE((LOG_WINMGMT,"\nGot a provider can unload event"));
  677. CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
  678. //
  679. // HACKHACK: Call it again to make sure that components that
  680. // were released by unloading the first one can be unloaded
  681. //
  682. CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
  683. sched.SetWorkItem(FinalCoreShutdown, CORE_PROVIDER_UNLOAD_TIMEOUT); // 11 minutes until next unloac;
  684. }
  685. break;
  686. case 6: // change in the hot mof directory
  687. {
  688. DEBUGTRACE((LOG_WINMGMT,"\nGot change in the hot mof directory"));
  689. LoadMofsInDirectory(g_ProgRes.szHotMofDirectory);
  690. //Continue to monitor changes
  691. if (!FindNextChangeNotification(g_ProgRes.ghMofDirChange))
  692. {
  693. iNumEvents--;
  694. }
  695. }
  696. break;
  697. case WAIT_TIMEOUT:
  698. DEBUGTRACE((LOG_WINMGMT,"\nGot a TIMEOUT work item"));
  699. if(sched.IsWorkItemDue(FirstCoreShutdown))
  700. {
  701. // All the clients have left the core and a decent time interval has passed. Set the
  702. // WINMGMT_CORE_CAN_BACKUP event. When the core is done, it will set the WINMGMT_CORE_BACKUP_DONE
  703. // event which will start the final unloading.
  704. DEBUGTRACE((LOG_WINMGMT,"\nGot a FirstCoreShutdown work item"));
  705. sched.ClearWorkItem(FirstCoreShutdown);
  706. CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
  707. CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
  708. }
  709. if(sched.IsWorkItemDue(FinalCoreShutdown))
  710. {
  711. CInMutex im(g_ProgRes.hMainMutex);
  712. DEBUGTRACE((LOG_WINMGMT,"\nGot a FinalCoreShutdown work item"));
  713. CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
  714. //
  715. // HACKHACK: Call it again to make sure that components that
  716. // were released by unloading the first one can be unloaded
  717. CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
  718. sched.ClearWorkItem(FinalCoreShutdown);
  719. }
  720. if(sched.IsWorkItemDue(PossibleStartCore))
  721. {
  722. sched.StartCoreIfEssNeeded();
  723. sched.ClearWorkItem(PossibleStartCore);
  724. }
  725. break;
  726. }
  727. }
  728. }
  729. //***************************************************************************
  730. //
  731. // MyService::MyService
  732. //
  733. // DESCRIPTION:
  734. //
  735. // Constructor.
  736. //
  737. //***************************************************************************
  738. MyService::MyService(DWORD CtrlAccepted):CNtService(CtrlAccepted)
  739. {
  740. m_hStopEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  741. if(m_hStopEvent == NULL)
  742. {
  743. DEBUGTRACE((LOG_WINMGMT,"\nMyService could not initialize"));
  744. }
  745. }
  746. //***************************************************************************
  747. //
  748. // MyService::~MyService
  749. //
  750. // DESCRIPTION:
  751. //
  752. // Destructor.
  753. //
  754. //***************************************************************************
  755. MyService::~MyService()
  756. {
  757. if(m_hStopEvent)
  758. CloseHandle(m_hStopEvent);
  759. }
  760. //***************************************************************************
  761. //
  762. // DWORD MyService::WorkerThread
  763. //
  764. // DESCRIPTION:
  765. //
  766. // Where the service runs. In this case, the service just waits for
  767. // the terminate event to be set.
  768. //
  769. // RETURN VALUE:
  770. //
  771. // 0
  772. //***************************************************************************
  773. DWORD MyService::WorkerThread()
  774. {
  775. DEBUGTRACE((LOG_WINMGMT,"\nStarting service worker thread"));
  776. if(!::Initialize(m_hStopEvent))
  777. return 0;
  778. WaitingFunction(m_hStopEvent);
  779. if (SERVICE_SHUTDOWN != g_ProgRes.ServiceStatus )
  780. {
  781. DEBUGTRACE((LOG_WINMGMT,"\nStopping service worker thread"));
  782. }
  783. return 0;
  784. }
  785. //
  786. //
  787. // VOID MyService::Log
  788. //
  789. ///////////////////////////////////////////////////////////////////
  790. VOID MyService::Log(
  791. IN LPCSTR lpszMsg)
  792. {
  793. TRACE((LOG_WINMGMT,lpszMsg));
  794. }
  795. //
  796. //
  797. // the stop function
  798. //
  799. //////////////////////////////////////////////////////////////////
  800. VOID MyService::Stop(BOOL bSystemShutDownCalled)
  801. {
  802. g_ProgRes.ServiceStatus = (bSystemShutDownCalled)?SERVICE_SHUTDOWN:SERVICE_STOPPED;
  803. SetEvent(m_hStopEvent);
  804. };
  805. //
  806. // MyService::Pause
  807. //
  808. ////////////////////////////////////////////////////////////////////
  809. HRESULT WbemPauseService()
  810. {
  811. HRESULT hr = WBEM_S_NO_ERROR;
  812. g_ProgRes.ServiceStatus = SERVICE_PAUSED;
  813. g_ProgRes.RevokeLogin();
  814. GLOB_GetMonitor()->Unregister(FALSE);
  815. SCODE sc = WBEM_E_FAILED;
  816. HMODULE hCoreModule = LoadLibraryEx(__TEXT("wbemcore.dll"),NULL,0);
  817. if(hCoreModule)
  818. {
  819. pfnShutDown pfn = (pfnShutDown)GetProcAddress(hCoreModule, "Shutdown");
  820. if(pfn)
  821. {
  822. sc = pfn(FALSE,FALSE);
  823. DEBUGTRACE((LOG_WINMGMT, "core is being shut down by WinMgmt.exe, it returned 0x%x",sc));
  824. }
  825. else
  826. hr = WBEM_E_CRITICAL_ERROR;
  827. FreeLibrary(hCoreModule);
  828. }
  829. else
  830. hr = WBEM_E_CRITICAL_ERROR;
  831. return hr;
  832. }
  833. VOID MyService::Pause()
  834. {
  835. WbemPauseService();
  836. }
  837. //
  838. // MyService::Continue
  839. //
  840. ////////////////////////////////////////////////////////////////////
  841. HRESULT WbemContinueService()
  842. {
  843. HRESULT hr = WBEM_S_NO_ERROR;
  844. // HRESULT APIENTRY Reinitialize(DWORD dwReserved);
  845. SCODE sc = WBEM_E_FAILED;
  846. HMODULE hCoreModule = LoadLibraryEx(__TEXT("wbemcore.dll"),NULL,0);
  847. if(hCoreModule)
  848. {
  849. HRESULT (STDAPICALLTYPE *pfn)(DWORD);
  850. pfn = (long (__stdcall *)(DWORD))GetProcAddress(hCoreModule, "Reinitialize");
  851. if(pfn)
  852. {
  853. sc = (*pfn)(0);
  854. DEBUGTRACE((LOG_WINMGMT, "core is being resumed: it returned 0x%x",sc));
  855. }
  856. else
  857. hr = WBEM_E_CRITICAL_ERROR;
  858. FreeLibrary(hCoreModule);
  859. }
  860. else
  861. hr = WBEM_E_CRITICAL_ERROR;
  862. g_ProgRes.RegisterLogin();
  863. GLOB_GetMonitor()->Register();
  864. g_ProgRes.ServiceStatus = SERVICE_RUNNING;
  865. return hr;
  866. }
  867. VOID MyService::Continue()
  868. {
  869. WbemContinueService();
  870. }
  871. //
  872. //
  873. // this function will be executed before
  874. // the final SetServiceStatus(SERVICE_STOPPED)
  875. //
  876. //////////////////////////////////////////////////////////
  877. VOID MyService::FinalCleanup()
  878. {
  879. g_ProgRes.Phase3Delete();
  880. RegSetDWORD(HKEY_LOCAL_MACHINE,
  881. HOME_REG_PATH,
  882. _T("ProcessID"),
  883. 0);
  884. }
  885. //
  886. // TO be removed before RTM
  887. // publish process ID in the registry
  888. //
  889. ////////////////////////////////////////////////////
  890. DWORD
  891. RegSetDWORD(HKEY hKey,
  892. TCHAR * pName,
  893. TCHAR * pValue,
  894. DWORD dwValue)
  895. {
  896. HKEY hKey2;
  897. LONG lRet;
  898. lRet = RegOpenKeyEx(hKey,
  899. pName,
  900. 0,
  901. KEY_WRITE,
  902. &hKey2);
  903. if (ERROR_SUCCESS == lRet)
  904. {
  905. DWORD dwType = REG_DWORD;
  906. DWORD dwSize = sizeof(DWORD);
  907. lRet = RegSetValueEx(hKey2,
  908. pValue,
  909. NULL,
  910. dwType,
  911. (BYTE *)&dwValue,
  912. dwSize);
  913. RegCloseKey(hKey2);
  914. }
  915. return lRet;
  916. }
  917. DWORD
  918. RegGetDWORD(HKEY hKey,
  919. TCHAR * pName,
  920. TCHAR * pValue,
  921. DWORD * pdwValue)
  922. {
  923. HKEY hKey2;
  924. LONG lRet;
  925. if (0 == pdwValue)
  926. return ERROR_INVALID_PARAMETER;
  927. lRet = RegOpenKeyEx(hKey,
  928. pName,
  929. 0,
  930. KEY_READ,
  931. &hKey2);
  932. if (ERROR_SUCCESS == lRet)
  933. {
  934. DWORD dwSize = sizeof(DWORD);
  935. DWORD dwType =0;
  936. lRet = RegQueryValueEx(hKey2,
  937. pValue,
  938. NULL,
  939. &dwType,
  940. (BYTE *)pdwValue,
  941. &dwSize);
  942. RegCloseKey(hKey2);
  943. }
  944. return lRet;
  945. }
  946. //
  947. //
  948. // Interceptor
  949. //
  950. //
  951. ///////////////////////////////////////////////////////////
  952. #ifdef INSTRUMENTED_BUILD
  953. #ifdef _X86_
  954. #include <malloc.h>
  955. struct HEAP_ENTRY {
  956. WORD Size;
  957. WORD PrevSize;
  958. BYTE SegmentIndex;
  959. BYTE Flags;
  960. BYTE UnusedBytes;
  961. BYTE SmallTagIndex;
  962. };
  963. #define HEAP_SLOW_FLAGS 0x7d030f60
  964. // only the "header"
  965. typedef struct _HEAP {
  966. HEAP_ENTRY Entry;
  967. ULONG Signature;
  968. ULONG Flags;
  969. ULONG ForceFlags;
  970. } HEAP;
  971. BOOL g_FaultHeapEnabled = FALSE;
  972. BOOL g_FaultFileEnabled = FALSE;
  973. ULONG g_Seed;
  974. ULONG g_Factor = 100000;
  975. ULONG g_Percent = 0x20;
  976. //ULONG g_RowOfFailures = 10;
  977. //LONG g_NumFailInARow = 0;
  978. //LONG g_NumFailedAllocation = 0;
  979. BOOL g_bDisableBreak = FALSE;
  980. LONG g_nSuccConn = 0;
  981. #define SIZE_JUMP_ADR 5
  982. #define SIZE_SAVED_INSTR 12
  983. void
  984. _declspec(naked) Prolog__ReadFile(){
  985. _asm {
  986. // this is the space for the "saved istructions"
  987. nop ;
  988. nop ;
  989. nop ;
  990. nop ;
  991. nop ;
  992. nop ;
  993. nop ;
  994. nop ;
  995. nop ;
  996. nop ;
  997. nop ;
  998. nop ;
  999. // this is the place for the JMP
  1000. nop ;
  1001. nop ;
  1002. nop ;
  1003. nop ;
  1004. nop ;
  1005. nop ; // dist
  1006. nop ; // dist
  1007. nop ; // dist
  1008. nop ; // dist
  1009. }
  1010. }
  1011. BOOL _I_ReadFile(
  1012. HANDLE hFile, // handle to file
  1013. LPVOID lpBuffer, // data buffer
  1014. DWORD nNumberOfBytesToRead, // number of bytes to read
  1015. LPDWORD lpNumberOfBytesRead, // number of bytes read
  1016. LPOVERLAPPED lpOverlapped // offset
  1017. ){
  1018. DWORD * pDw = (DWORD *)_alloca(sizeof(DWORD));
  1019. BOOL bRet;
  1020. LONG Ret = RtlRandomEx(&g_Seed);
  1021. if (g_FaultFileEnabled && (Ret%g_Factor < g_Percent))
  1022. {
  1023. if (lpNumberOfBytesRead)
  1024. *lpNumberOfBytesRead = 0;
  1025. return FALSE;
  1026. }
  1027. _asm{
  1028. push lpOverlapped;
  1029. push lpNumberOfBytesRead;
  1030. push nNumberOfBytesToRead;
  1031. push lpBuffer;
  1032. push hFile;
  1033. call Prolog__ReadFile;
  1034. mov bRet,eax
  1035. }
  1036. return bRet;
  1037. }
  1038. void
  1039. _declspec(naked) Prolog__WriteFile(){
  1040. _asm {
  1041. // this is the space for the "saved istructions"
  1042. nop ;
  1043. nop ;
  1044. nop ;
  1045. nop ;
  1046. nop ;
  1047. nop ;
  1048. nop ;
  1049. nop ;
  1050. nop ;
  1051. nop ;
  1052. nop ;
  1053. nop ;
  1054. // this is the place for the JMP
  1055. nop ;
  1056. nop ;
  1057. nop ;
  1058. nop ;
  1059. nop ;
  1060. nop ; // dist
  1061. nop ; // dist
  1062. nop ; // dist
  1063. }
  1064. }
  1065. BOOL _I_WriteFile(
  1066. HANDLE hFile, // handle to file
  1067. LPCVOID lpBuffer, // data buffer
  1068. DWORD nNumberOfBytesToWrite, // number of bytes to write
  1069. LPDWORD lpNumberOfBytesWritten, // number of bytes written
  1070. LPOVERLAPPED lpOverlapped // overlapped buffer
  1071. ){
  1072. DWORD * pDw = (DWORD *)_alloca(sizeof(DWORD));
  1073. BOOL bRet;
  1074. LONG Ret = RtlRandomEx(&g_Seed);
  1075. if (g_FaultFileEnabled && (Ret%g_Factor < g_Percent))
  1076. {
  1077. if (lpNumberOfBytesWritten)
  1078. *lpNumberOfBytesWritten = 0;
  1079. return FALSE;
  1080. }
  1081. _asm{
  1082. push lpOverlapped;
  1083. push lpNumberOfBytesWritten;
  1084. push nNumberOfBytesToWrite;
  1085. push lpBuffer;
  1086. push hFile;
  1087. call Prolog__WriteFile;
  1088. mov bRet,eax
  1089. }
  1090. return bRet;
  1091. }
  1092. void
  1093. _declspec(naked) Prolog__CreateEvent(){
  1094. _asm {
  1095. // this is the space for the "saved istructions"
  1096. nop ;
  1097. nop ;
  1098. nop ;
  1099. nop ;
  1100. nop ;
  1101. nop ;
  1102. nop ;
  1103. nop ;
  1104. nop ;
  1105. nop ;
  1106. nop ;
  1107. nop ;
  1108. // this is the place for the JMP
  1109. nop ;
  1110. nop ;
  1111. nop ;
  1112. nop ;
  1113. nop ;
  1114. nop ; // dist
  1115. nop ; // dist
  1116. }
  1117. }
  1118. HANDLE _I_CreateEvent(
  1119. LPSECURITY_ATTRIBUTES lpEventAttributes, // SD
  1120. BOOL bManualReset, // reset type
  1121. BOOL bInitialState, // initial state
  1122. LPCWSTR lpName // object name
  1123. )
  1124. {
  1125. DWORD * pDw = (DWORD *)_alloca(sizeof(DWORD));
  1126. HANDLE hHandle;
  1127. LONG Ret = RtlRandomEx(&g_Seed);
  1128. if (g_FaultFileEnabled && (Ret%g_Factor < g_Percent))
  1129. {
  1130. return NULL;
  1131. }
  1132. _asm{
  1133. push lpName;
  1134. push bInitialState;
  1135. push bManualReset;
  1136. push lpEventAttributes
  1137. call Prolog__CreateEvent;
  1138. mov hHandle,eax
  1139. }
  1140. return hHandle;
  1141. }
  1142. void
  1143. _declspec(naked) Prolog__RtlFreeHeap(){
  1144. _asm {
  1145. // this is the space for the "saved istructions"
  1146. nop ;
  1147. nop ;
  1148. nop ;
  1149. nop ;
  1150. nop ;
  1151. nop ;
  1152. nop ;
  1153. nop ;
  1154. nop ;
  1155. nop ;
  1156. nop ;
  1157. nop ;
  1158. // this is the place for the JMP
  1159. nop ;
  1160. nop ;
  1161. nop ;
  1162. nop ;
  1163. nop ;
  1164. }
  1165. }
  1166. #define SPACE_STACK_ALLOC (4*sizeof(ULONG_PTR))
  1167. DWORD _I_RtlFreeHeap(VOID * pHeap,DWORD Flags,VOID * pBlock)
  1168. {
  1169. ULONG * pLong = (ULONG *)_alloca(sizeof(DWORD));
  1170. Flags |= (((HEAP *)pHeap)->Flags) | (((HEAP *)pHeap)->ForceFlags);
  1171. DWORD dwRet;
  1172. if (pBlock && !(HEAP_SLOW_FLAGS & Flags))
  1173. {
  1174. HEAP_ENTRY * pEntry = (HEAP_ENTRY *)pBlock-1;
  1175. DWORD RealSize = pEntry->Size * sizeof(HEAP_ENTRY);
  1176. DWORD Size = RealSize - pEntry->UnusedBytes;
  1177. ULONG_PTR * pL = (ULONG_PTR *)pBlock;
  1178. if (0 == (pEntry->Flags & 0x01) ||0xf0f0f0f0 == pL[1] )
  1179. {
  1180. if (!g_bDisableBreak)
  1181. DebugBreak();
  1182. }
  1183. DWORD CanMemset = RealSize-sizeof(HEAP_ENTRY);
  1184. memset(pBlock,0xF0,(CanMemset > SPACE_STACK_ALLOC)?CanMemset-SPACE_STACK_ALLOC:CanMemset);
  1185. if (pEntry->Size >=4)
  1186. {
  1187. RtlCaptureStackBackTrace (1,
  1188. (4 == pEntry->Size)?4:6,
  1189. (PVOID *)(pEntry+2),
  1190. pLong);
  1191. }
  1192. }
  1193. _asm {
  1194. push pBlock ;
  1195. push Flags ;
  1196. push pHeap ;
  1197. call Prolog__RtlFreeHeap ;
  1198. mov dwRet,eax ;
  1199. }
  1200. return dwRet;
  1201. }
  1202. void
  1203. _declspec(naked) Prolog__RtlAllocateHeap(){
  1204. _asm {
  1205. // this is the space for the "saved istructions"
  1206. nop ;
  1207. nop ;
  1208. nop ;
  1209. nop ;
  1210. nop ;
  1211. nop ;
  1212. nop ;
  1213. nop ;
  1214. nop ;
  1215. nop ;
  1216. nop ;
  1217. nop ;
  1218. // this is the place for the JMP
  1219. nop ;
  1220. nop ;
  1221. nop ;
  1222. nop ;
  1223. nop ;
  1224. nop ; // to make this distinct
  1225. }
  1226. }
  1227. VOID * _I_RtlAllocateHeap(VOID * pHeap,DWORD Flags,DWORD Size)
  1228. {
  1229. ULONG * pLong = (ULONG *)_alloca(sizeof(DWORD));
  1230. Flags |= (((HEAP *)pHeap)->Flags) | (((HEAP *)pHeap)->ForceFlags);
  1231. VOID * pRet;
  1232. DWORD NewSize = (Size < (3*sizeof(HEAP_ENTRY)))?(3*sizeof(HEAP_ENTRY)+SPACE_STACK_ALLOC):(Size+SPACE_STACK_ALLOC);
  1233. /*
  1234. if (g_FaultHeapEnabled && g_NumFailInARow)
  1235. {
  1236. InterlockedDecrement(&g_NumFailInARow);
  1237. goto here;
  1238. }
  1239. */
  1240. LONG Ret = RtlRandomEx(&g_Seed);
  1241. if (g_FaultHeapEnabled && (Ret%g_Factor < g_Percent))
  1242. {
  1243. // g_NumFailInARow = g_RowOfFailures;
  1244. //here:
  1245. // InterlockedIncrement(&g_NumFailedAllocation);
  1246. return NULL;
  1247. }
  1248. _asm {
  1249. push NewSize ;
  1250. push Flags ;
  1251. push pHeap ;
  1252. call Prolog__RtlAllocateHeap ;
  1253. mov pRet,eax ;
  1254. }
  1255. if (pRet && !(HEAP_SLOW_FLAGS & Flags) )
  1256. {
  1257. if (NewSize <= 0xffff)
  1258. NewSize = sizeof(HEAP_ENTRY)*((HEAP_ENTRY *)pRet-1)->Size;
  1259. if (!(HEAP_ZERO_MEMORY & Flags))
  1260. {
  1261. memset(pRet,0xc0,NewSize-sizeof(HEAP_ENTRY));
  1262. }
  1263. RtlCaptureStackBackTrace(1,
  1264. 4,
  1265. (PVOID *)((BYTE *)pRet+(NewSize-SPACE_STACK_ALLOC-sizeof(HEAP_ENTRY))),
  1266. pLong);
  1267. }
  1268. return pRet;
  1269. }
  1270. void
  1271. _declspec(naked) Prolog__RtlReAllocateHeap(){
  1272. _asm {
  1273. // this is the space for the "saved istructions"
  1274. nop ;
  1275. nop ;
  1276. nop ;
  1277. nop ;
  1278. nop ;
  1279. nop ;
  1280. nop ;
  1281. nop ;
  1282. nop ;
  1283. nop ;
  1284. nop ;
  1285. nop ;
  1286. // this is the place for the JMP
  1287. nop ;
  1288. nop ;
  1289. nop ;
  1290. nop ;
  1291. nop ;
  1292. nop ; // dist
  1293. nop ; // dist
  1294. nop ; // dist
  1295. nop ; // dist
  1296. nop ; // dist
  1297. }
  1298. }
  1299. VOID *
  1300. _I_RtlReAllocateHeap(
  1301. HANDLE pHeap, // handle to heap block
  1302. DWORD Flags, // heap reallocation options
  1303. LPVOID lpMem, // pointer to memory to reallocate
  1304. SIZE_T Size // number of bytes to reallocate
  1305. ){
  1306. ULONG * pLong = (ULONG *)_alloca(sizeof(DWORD));
  1307. Flags |= (((HEAP *)pHeap)->Flags) | (((HEAP *)pHeap)->ForceFlags);
  1308. VOID * pRet;
  1309. DWORD NewSize = (Size < (3*sizeof(HEAP_ENTRY)))?(3*sizeof(HEAP_ENTRY)+SPACE_STACK_ALLOC):(Size+SPACE_STACK_ALLOC);
  1310. _asm {
  1311. push NewSize ;
  1312. push lpMem ;
  1313. push Flags ;
  1314. push pHeap ;
  1315. call Prolog__RtlReAllocateHeap ;
  1316. mov pRet,eax ;
  1317. }
  1318. if (pRet && !(HEAP_SLOW_FLAGS & Flags) )
  1319. {
  1320. if (NewSize <= 0xffff)
  1321. NewSize = sizeof(HEAP_ENTRY)*((HEAP_ENTRY *)pRet-1)->Size;
  1322. RtlCaptureStackBackTrace(1,
  1323. 4,
  1324. (PVOID *)((BYTE *)pRet+(NewSize-SPACE_STACK_ALLOC-sizeof(HEAP_ENTRY))),
  1325. pLong);
  1326. }
  1327. return pRet;
  1328. }
  1329. void
  1330. _declspec(naked) Prolog__RtlValidateHeap(){
  1331. _asm {
  1332. // this is the space for the "saved istructions"
  1333. nop ;
  1334. nop ;
  1335. nop ;
  1336. nop ;
  1337. nop ;
  1338. nop ;
  1339. nop ;
  1340. nop ;
  1341. nop ;
  1342. nop ;
  1343. nop ;
  1344. nop ;
  1345. // this is the place for the JMP
  1346. nop ;
  1347. nop ;
  1348. nop ;
  1349. nop ;
  1350. nop ;
  1351. nop ; // dist
  1352. nop ; // dist
  1353. nop ; // dist
  1354. nop ; // dist
  1355. nop ; // dist
  1356. nop ; // dist
  1357. }
  1358. }
  1359. BOOL
  1360. _I_RtlValidateHeap(
  1361. HANDLE pHeap, // handle to heap block
  1362. DWORD dwFlags, // heap reallocation options
  1363. LPVOID lpMem // pointer to memory to validate
  1364. ){
  1365. ULONG * pLong = (ULONG *)_alloca(sizeof(DWORD));
  1366. BOOL bRet;
  1367. g_bDisableBreak = TRUE;
  1368. _asm {
  1369. push lpMem ;
  1370. push dwFlags ;
  1371. push pHeap ;
  1372. call Prolog__RtlValidateHeap ;
  1373. mov bRet,eax ;
  1374. }
  1375. g_bDisableBreak = FALSE;
  1376. return bRet;
  1377. }
  1378. #if 0
  1379. #define MAX_REMEMBER (1024)
  1380. struct CSCCTrace
  1381. {
  1382. VOID * p1;
  1383. VOID * p2;
  1384. DWORD Tid;
  1385. ULONG_PTR Trace[5];
  1386. } g_CSCCTrace[MAX_REMEMBER];
  1387. LONG g_CSCCIndex = -1;
  1388. void
  1389. _declspec(naked) Prolog__CoSwitchCallContext(){
  1390. _asm {
  1391. // this is the space for the "saved istructions"
  1392. nop ;
  1393. nop ;
  1394. nop ;
  1395. nop ;
  1396. nop ;
  1397. nop ;
  1398. nop ;
  1399. nop ;
  1400. nop ;
  1401. nop ;
  1402. nop ;
  1403. nop ;
  1404. // this is the place for the JMP
  1405. nop ;
  1406. nop ;
  1407. nop ;
  1408. nop ;
  1409. nop ;
  1410. nop ; // dist
  1411. nop ; // dist
  1412. nop ; // dist
  1413. nop ; // dist
  1414. nop ; // dist
  1415. nop ; // dist
  1416. nop ; // dist
  1417. }
  1418. }
  1419. HRESULT WINAPI
  1420. _I_CoSwitchCallContext(IUnknown * pNew,
  1421. IUnknown ** ppOld)
  1422. {
  1423. ULONG * pLong = (ULONG * )_alloca(sizeof(ULONG ));
  1424. long nIndex = InterlockedIncrement(&g_CSCCIndex);
  1425. nIndex %= MAX_REMEMBER;
  1426. CSCCTrace * pTrace = &g_CSCCTrace[nIndex];
  1427. pTrace->p1 = pNew;
  1428. if (ppOld)
  1429. pTrace->p2 = *ppOld;
  1430. else
  1431. pTrace->p2 = 0;
  1432. pTrace->Tid =GetCurrentThreadId();
  1433. RtlCaptureStackBackTrace (1,5,(PVOID *)pTrace->Trace,pLong);
  1434. HRESULT hRes;
  1435. _asm {
  1436. push ppOld;
  1437. push pNew;
  1438. call Prolog__CoSwitchCallContext;
  1439. mov hRes,eax;
  1440. };
  1441. return hRes;
  1442. }
  1443. #endif
  1444. void intercept2(WCHAR * Module,
  1445. LPSTR Function,
  1446. VOID * NewRoutine,
  1447. VOID * pPrologStorage,
  1448. DWORD Size)
  1449. {
  1450. FARPROC OldRoutine = GetProcAddress(GetModuleHandleW(Module),Function);
  1451. if (OldRoutine)
  1452. {
  1453. MEMORY_BASIC_INFORMATION MemBI;
  1454. DWORD dwOldProtect;
  1455. BOOL bRet, bRet2;
  1456. DWORD dwRet;
  1457. dwRet = VirtualQuery(OldRoutine,&MemBI,sizeof(MemBI));
  1458. bRet = VirtualProtect(MemBI.BaseAddress,
  1459. MemBI.RegionSize,
  1460. PAGE_EXECUTE_WRITECOPY,
  1461. &dwOldProtect);
  1462. dwRet = VirtualQuery(pPrologStorage,&MemBI,sizeof(MemBI));
  1463. bRet2 = VirtualProtect(MemBI.BaseAddress,
  1464. MemBI.RegionSize,
  1465. PAGE_EXECUTE_WRITECOPY,
  1466. &dwOldProtect);
  1467. if (bRet && bRet2)
  1468. {
  1469. VOID * pToJump = (VOID *)NewRoutine;
  1470. BYTE Arr[SIZE_JUMP_ADR] = { 0xe9 };
  1471. LONG * pOffset = (LONG *)&Arr[1];
  1472. * pOffset = (LONG)NewRoutine - (LONG)OldRoutine - SIZE_JUMP_ADR ;
  1473. // save the old code
  1474. memcpy(pPrologStorage,OldRoutine,Size);
  1475. // put the new code
  1476. memset(OldRoutine,0x90,Size);
  1477. memcpy(OldRoutine,Arr,SIZE_JUMP_ADR);
  1478. // adjust the prolog to continue
  1479. * pOffset = (LONG)OldRoutine + Size - (LONG)pPrologStorage - SIZE_SAVED_INSTR - SIZE_JUMP_ADR; // magic for nops
  1480. memcpy((BYTE *)pPrologStorage+SIZE_SAVED_INSTR,Arr,SIZE_JUMP_ADR);
  1481. }
  1482. }
  1483. else
  1484. {
  1485. OutputDebugStringA("GetProcAddress FAIL\n");
  1486. }
  1487. }
  1488. void unintercept(WCHAR * Module,
  1489. LPSTR Function,
  1490. VOID * pPrologStorage,
  1491. DWORD Size)
  1492. {
  1493. FARPROC OldRoutine = GetProcAddress(GetModuleHandleW(Module),Function);
  1494. if (OldRoutine)
  1495. {
  1496. memcpy((void *)OldRoutine,pPrologStorage,Size);
  1497. }
  1498. }
  1499. #endif /*_X86_*/
  1500. #ifndef STATUS_POSSIBLE_DEADLOCK
  1501. #define STATUS_POSSIBLE_DEADLOCK (0xC0000194L)
  1502. #endif
  1503. class CSetVectoredHandler
  1504. {
  1505. private:
  1506. // static ULONG_PTR Base;
  1507. // static ULONG_PTR Limit;
  1508. PVOID pVectorHandler;
  1509. enum ExceptionTypes
  1510. {
  1511. StatusAccessViolation,
  1512. CXXException,
  1513. StatusNoMemory,
  1514. OtherExceptions,
  1515. LastException
  1516. };
  1517. static LONG ExceptionCounters[LastException];
  1518. /*
  1519. BOOL GetDllLimits(WCHAR * pDllName)
  1520. {
  1521. UNICODE_STRING DllName;
  1522. RtlInitUnicodeString(&DllName,pDllName);
  1523. PEB_LDR_DATA * pLdr = NtCurrentPeb()->Ldr;
  1524. LIST_ENTRY * pHeadEntry = &pLdr->InLoadOrderModuleList;
  1525. LIST_ENTRY * pEntry = pLdr->InLoadOrderModuleList.Flink;
  1526. BOOL bFound = FALSE;
  1527. while (pHeadEntry != pEntry)
  1528. {
  1529. LDR_DATA_TABLE_ENTRY * pData = CONTAINING_RECORD(pEntry,
  1530. LDR_DATA_TABLE_ENTRY,
  1531. InLoadOrderLinks);
  1532. if (0 == _wcsicmp(DllName.Buffer,pData->BaseDllName.Buffer))
  1533. {
  1534. //OutputDebugStringA("found\n");
  1535. Base = (ULONG_PTR)pData->DllBase;
  1536. Limit = Base + (ULONG_PTR)pData->SizeOfImage;
  1537. bFound = TRUE;
  1538. break;
  1539. }
  1540. pEntry = pEntry->Flink;
  1541. }
  1542. return bFound;
  1543. }
  1544. */
  1545. public:
  1546. CSetVectoredHandler()
  1547. {
  1548. pVectorHandler = NULL;
  1549. //if (GetDllLimits(L"fastprox.dll"))
  1550. //{
  1551. pVectorHandler = AddVectoredExceptionHandler(TRUE,CSetVectoredHandler::VectoredHandler);
  1552. //}
  1553. };
  1554. ~CSetVectoredHandler()
  1555. {
  1556. if (pVectorHandler)
  1557. RemoveVectoredExceptionHandler(pVectorHandler);
  1558. };
  1559. static LONG WINAPI VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo)
  1560. {
  1561. PEXCEPTION_RECORD pExr = ExceptionInfo->ExceptionRecord;
  1562. PCONTEXT pCxr = ExceptionInfo->ContextRecord;
  1563. switch (pExr->ExceptionCode)
  1564. {
  1565. case STATUS_PRIVILEGED_INSTRUCTION:
  1566. case STATUS_INVALID_HANDLE:
  1567. case STATUS_STACK_OVERFLOW:
  1568. case STATUS_POSSIBLE_DEADLOCK:
  1569. case STATUS_ACCESS_VIOLATION:
  1570. InterlockedIncrement(&ExceptionCounters[(LONG)StatusAccessViolation]);
  1571. DebugBreak();
  1572. break;
  1573. case 0xe06d7363:
  1574. InterlockedIncrement(&ExceptionCounters[(LONG)CXXException]);
  1575. break;
  1576. case STATUS_NO_MEMORY:
  1577. InterlockedIncrement(&ExceptionCounters[(LONG)StatusNoMemory]);
  1578. break;
  1579. default:
  1580. InterlockedIncrement(&ExceptionCounters[(LONG)OtherExceptions]);
  1581. break;
  1582. }
  1583. return EXCEPTION_CONTINUE_SEARCH;
  1584. }
  1585. } g_C;
  1586. LONG CSetVectoredHandler::ExceptionCounters[CSetVectoredHandler::LastException];
  1587. #endif
  1588. //
  1589. //
  1590. // ServiceMain
  1591. //
  1592. ///////////////////////////////////////////////////////////
  1593. VOID WINAPI
  1594. ServiceMain(DWORD dwNumServicesArgs,
  1595. LPWSTR *lpServiceArgVectors)
  1596. {
  1597. #ifdef INSTRUMENTED_BUILD
  1598. #ifdef _X86_
  1599. intercept2(L"ntdll.dll","RtlFreeHeap",_I_RtlFreeHeap,Prolog__RtlFreeHeap,5);
  1600. intercept2(L"ntdll.dll","RtlAllocateHeap",_I_RtlAllocateHeap,Prolog__RtlAllocateHeap,5);
  1601. intercept2(L"ntdll.dll","RtlReAllocateHeap",_I_RtlReAllocateHeap,Prolog__RtlReAllocateHeap,5);
  1602. intercept2(L"ntdll.dll","RtlValidateHeap",_I_RtlValidateHeap,Prolog__RtlValidateHeap,7);
  1603. intercept2(L"kernel32.dll","CreateEventW",_I_CreateEvent,Prolog__CreateEvent,6);
  1604. intercept2(L"kernel32.dll","WriteFile",_I_WriteFile,Prolog__WriteFile,7);
  1605. intercept2(L"kernel32.dll","ReadFile",_I_ReadFile,Prolog__ReadFile,7);
  1606. g_nSuccConn = 0;
  1607. #endif /*_X86_*/
  1608. #endif
  1609. RegSetDWORD(HKEY_LOCAL_MACHINE,
  1610. HOME_REG_PATH,
  1611. _T("ProcessID"),
  1612. GetCurrentProcessId());
  1613. if (InitialBreak())
  1614. {
  1615. DebugBreak();
  1616. }
  1617. g_ProgRes.Init();
  1618. g_ProgRes.Phase1Build();
  1619. MyService ThisService(SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_PAUSE_CONTINUE);
  1620. ThisService.Run(SERVICE_NAME,
  1621. dwNumServicesArgs,
  1622. lpServiceArgVectors,
  1623. (void *)&ThisService);
  1624. #ifdef INSTRUMENTED_BUILD
  1625. #ifdef _X86_
  1626. unintercept(L"ntdll.dll","RtlFreeHeap",Prolog__RtlFreeHeap,5);
  1627. unintercept(L"ntdll.dll","RtlAllocateHeap",Prolog__RtlAllocateHeap,5);
  1628. unintercept(L"ntdll.dll","RtlReAllocateHeap",Prolog__RtlReAllocateHeap,5);
  1629. unintercept(L"ntdll.dll","RtlValidateHeap",Prolog__RtlValidateHeap,7);
  1630. unintercept(L"kernel32.dll","CreateEventW",Prolog__CreateEvent,6);
  1631. unintercept(L"kernel32.dll","WriteFile",Prolog__WriteFile,7);
  1632. unintercept(L"kernel32.dll","ReadFile",Prolog__ReadFile,7);
  1633. #endif /*_X86_*/
  1634. #endif
  1635. }