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

#include "precomp.h"
#include <winsvc.h>
#include <tchar.h>
#include <persistcfg.h>
#include <winntsec.h>
#include "cntserv.h"
#include "winmgmt.h"
#include "sched.h"
#include "resync2.h"
#include <malloc.h>
//***********************************************************************
//
// Defines
//
//***********************************************************************
#define CORE_PROVIDER_UNLOAD_TIMEOUT ( 30 * 1000 )
//***********************************************************************
//
// Globals
//
//***********************************************************************
HINSTANCE g_hInstance;
//***********************************************************************
//
// Dll Entry points and export points
//
//***********************************************************************
BOOL APIENTRY DllMain( HINSTANCE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch(ul_reason_for_call){
case DLL_PROCESS_ATTACH:
g_hInstance = hModule;
DisableThreadLibraryCalls(hModule);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
};
//
//
// InitialBreak
//
///////////////////////////////////////////////////////////
BOOL
InitialBreak()
{
HKEY hKey;
LONG lRet;
BOOL bRet = FALSE;
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
HOME_REG_PATH,
0,
KEY_READ,
&hKey);
if (ERROR_SUCCESS == lRet)
{
DWORD dwType;
DWORD dwVal;
DWORD dwSize = sizeof(DWORD);
lRet = RegQueryValueEx(hKey,
INITIAL_BREAK,
NULL,
&dwType,
(BYTE *)&dwVal,
&dwSize);
if (ERROR_SUCCESS == lRet &&
dwType == REG_DWORD &&
dwVal)
{
bRet = TRUE;
}
RegCloseKey(hKey);
}
return bRet;
}
//
// the global structure
//
struct _PROG_RESOURCES g_ProgRes;
void
_PROG_RESOURCES::Init()
{
m_hExclusive = NULL;
m_hTerminateEvent = NULL;
m_bOleInitialized = NULL;
m_pLoginFactory = NULL;
m_pBackupFactory = NULL;
m_dwLoginClsFacReg = 0;
m_dwBackupClsFacReg = 0;
g_fSetup = FALSE;
g_fDoResync = TRUE;
hMainMutex = NULL;
bShuttingDownWinMgmt = FALSE;
gbCoreLoaded = FALSE;
ServiceStatus = SERVICE_STOPPED;
ghCoreCanUnload = NULL;
ghProviderCanUnload = NULL;
ghCoreUnloaded = NULL;
ghCoreLoaded = NULL;
ghNeedRegistration = NULL;
ghRegistrationDone = NULL;
ghMofDirChange = NULL;
ghLoadCtrEvent = NULL;
ghUnloadCtrEvent = NULL;
ghHoldOffNewClients = NULL;
szHotMofDirectory = NULL;
pWbemVssWriter = NULL;
bWbemVssWriterSubscribed = false;
};
BOOL
_PROG_RESOURCES::Phase1Build()
{
hMainMutex = CreateMutex(NULL, FALSE, NULL);
g_fSetup = CheckSetupSwitch();
if ( g_fSetup )
{
SetNoShellADAPSwitch();
}
// Look in the registry to decide if we will launch a resync perf or not
g_fDoResync = CheckNoResyncSwitch();
//
// set this to have the Console Control Handler notification
//
SetProcessShutdownParameters(0x400,0);
//
// set to some defined value parames that might be outstanding if someone killed us
//
RegSetDWORD(HKEY_LOCAL_MACHINE,HOME_REG_PATH,DO_THROTTLE,1);
return hMainMutex?TRUE:FALSE;
};
BOOL
_PROG_RESOURCES::Phase2Build(HANDLE hTerminateEvt)
{
ghCoreCanUnload = CreateEvent(NULL,FALSE,FALSE,
TEXT("WINMGMT_COREDLL_CANSHUTDOWN"));
ghProviderCanUnload = CreateEvent(NULL,FALSE,FALSE,
TEXT("WINMGMT_PROVIDER_CANSHUTDOWN"));
SetEventDacl(ghProviderCanUnload,EVENT_ALL_ACCESS);
ghCoreUnloaded = CreateEvent(NULL,FALSE,FALSE,
TEXT("WINMGMT_COREDLL_UNLOADED"));
ghCoreLoaded = CreateEvent(NULL,FALSE,FALSE,
TEXT("WINMGMT_COREDLL_LOADED"));
m_hTerminateEvent = CreateEvent(NULL,TRUE,FALSE,
TEXT("WINMGMT_MARSHALLING_SERVER_TERMINATE"));
if(m_hTerminateEvent == NULL)
{
TRACE((LOG_WINMGMT,"\nWINMGMT terminating because CreateEvent, last error = 0x%x\n",
GetLastError()));
return FALSE;
}
DWORD dwRet;
m_hExclusive = CreateMutex( NULL, FALSE, TEXT("WINMGMT_MARSHALLING_SERVER"));
if(m_hExclusive)
dwRet = WaitForSingleObject(m_hExclusive, 0);
if(m_hExclusive == NULL || dwRet != WAIT_OBJECT_0)
{
if(m_hExclusive)
CloseHandle(m_hExclusive);
m_hExclusive = NULL;
TRACE((LOG_WINMGMT,"\nWINMGMT terminating an existing copy was detected"));
return FALSE;
}
ghNeedRegistration = CreateEvent(NULL,TRUE,FALSE, __TEXT("WINMGMT_NEED_REGISTRATION"));
SetObjectAccess2(ghNeedRegistration);
ghRegistrationDone = CreateEvent(NULL,TRUE,FALSE, __TEXT("WINMGMT_REGISTRATION_DONE"));
SetObjectAccess2(ghRegistrationDone);
ghHoldOffNewClients = CreateMutex(NULL, FALSE, __TEXT("WINMGMT_KEEP_NEW_CLIENTS_AT_BAY"));
if(ghHoldOffNewClients == NULL)
ghHoldOffNewClients = OpenMutex(SYNCHRONIZE, FALSE, __TEXT("WINMGMT_KEEP_NEW_CLIENTS_AT_BAY"));
if(ghNeedRegistration == NULL || ghRegistrationDone == NULL ||
ghHoldOffNewClients == NULL)
{
TRACE((LOG_WINMGMT,"\nWINMGMT couldnt create the sync objects"));
return FALSE;
}
if (!m_Monitor.Init())
{
return FALSE;
}
// don't create a writer if during setup
if (!g_fSetup)
{
pWbemVssWriter = new CWbemVssWriter;
if (!pWbemVssWriter)
{
TRACE((LOG_WINMGMT,"\nWINMGMT could not create the VssWriter"));
return FALSE;
}
}
return TRUE;
}
BOOL
_PROG_RESOURCES::RegisterLogin()
{
HRESULT sc;
DWORD dwFlags = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER;
g_ProgRes.m_pLoginFactory = new CForwardFactory(CLSID_InProcWbemLevel1Login);
g_ProgRes.m_pLoginFactory->AddRef();
sc = CoRegisterClassObject(CLSID_WbemLevel1Login,
g_ProgRes.m_pLoginFactory,
dwFlags,
REGCLS_MULTIPLEUSE,
&g_ProgRes.m_dwLoginClsFacReg);
if(sc != S_OK)
{
TRACE((LOG_WINMGMT,"\nFailed to register the "
"CLSID_WbemLevel1Login class factory, "
"sc = 0x%x", sc));
return FALSE;
}
else
{
DEBUGTRACE((LOG_WINMGMT, "\nRegistered class factory with flags: 0x%X\n",
dwFlags));
return TRUE;
}
}
BOOL
_PROG_RESOURCES::RevokeLogin()
{
if(m_pLoginFactory) {
CoRevokeClassObject(m_dwLoginClsFacReg);
m_dwLoginClsFacReg = 0;
m_pLoginFactory->Release();
m_pLoginFactory = NULL;
}
return TRUE;
}
BOOL
_PROG_RESOURCES::RegisterBackup()
{
HRESULT sc;
DWORD dwFlags = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER;
g_ProgRes.m_pBackupFactory = new CForwardFactory(CLSID_WbemBackupRestore);
g_ProgRes.m_pBackupFactory->AddRef();
sc = CoRegisterClassObject(CLSID_WbemBackupRestore,
g_ProgRes.m_pBackupFactory,
dwFlags,
REGCLS_MULTIPLEUSE,
&g_ProgRes.m_dwBackupClsFacReg);
if(sc != S_OK)
{
TRACE((LOG_WINMGMT,"\nFailed to register the "
"Backup/recovery class factory, "
"sc = 0x%x", sc));
return FALSE;
}
else
{
return TRUE;
}
}
BOOL
_PROG_RESOURCES::RevokeBackup()
{
if(m_pBackupFactory) {
CoRevokeClassObject(m_dwBackupClsFacReg);
m_dwBackupClsFacReg = 0;
m_pBackupFactory->Release();
m_pBackupFactory = NULL;
}
return TRUE;
}
_PROG_RESOURCES::Phase1Delete(BOOL bIsSystemShutdown)
{
if (!bIsSystemShutdown)
{
if(ghCoreCanUnload)
{
CloseHandle(ghCoreCanUnload);
ghCoreCanUnload = NULL;
};
if(ghProviderCanUnload)
{
CloseHandle(ghProviderCanUnload);
ghProviderCanUnload = NULL;
}
if(ghCoreUnloaded)
{
CloseHandle(ghCoreUnloaded);
ghCoreUnloaded = NULL;
}
if(ghCoreLoaded)
{
CloseHandle(ghCoreLoaded);
ghCoreLoaded = NULL;
}
if(ghNeedRegistration)
{
CloseHandle(ghNeedRegistration);
ghNeedRegistration = NULL;
}
if(ghRegistrationDone)
{
CloseHandle(ghRegistrationDone);
ghRegistrationDone = NULL;
}
if(ghMofDirChange)
{
CloseHandle(ghMofDirChange);
ghMofDirChange = NULL;
}
}
if (m_Monitor.IsRegistred())
{
m_Monitor.Unregister(bIsSystemShutdown);
}
if (!bIsSystemShutdown)
{
m_Monitor.Uninit();
if(ghHoldOffNewClients)
{
CloseHandle(ghHoldOffNewClients);
ghHoldOffNewClients = NULL;
}
if(m_hTerminateEvent)
{
CloseHandle(m_hTerminateEvent);
m_hTerminateEvent = NULL;
}
if(m_hExclusive)
{
ReleaseMutex(m_hExclusive);
CloseHandle(m_hExclusive);
m_hExclusive = NULL;
}
if(szHotMofDirectory)
{
delete [] szHotMofDirectory;
szHotMofDirectory = NULL;
}
}
// shut down and delete our writer for volume snapshot backup
if (pWbemVssWriter && !bIsSystemShutdown)
{
if (bWbemVssWriterSubscribed)
{
HRESULT hRes = pWbemVssWriter->Unsubscribe();
if (SUCCEEDED(hRes))
{
bWbemVssWriterSubscribed = false;
}
else
{
TRACE((LOG_WINMGMT,"\nWINMGMT Could not unsubscribe the VssWriter"));
}
}
delete pWbemVssWriter;
pWbemVssWriter = NULL;
}
return TRUE;
}
_PROG_RESOURCES::Phase2Delete(BOOL bIsSystemShutdown)
{
if (!bIsSystemShutdown)
{
if(m_pLoginFactory) {
CoRevokeClassObject(m_dwLoginClsFacReg);
m_pLoginFactory->Release();
m_pLoginFactory = NULL;
m_dwLoginClsFacReg = 0;
}
if(m_pBackupFactory) {
CoRevokeClassObject(m_dwBackupClsFacReg);
m_pBackupFactory->Release();
m_pBackupFactory = NULL;
m_dwBackupClsFacReg = 0;
}
if(m_bOleInitialized)
{
CoUninitialize();
m_bOleInitialized = FALSE;
}
}
return TRUE;
}
BOOL
_PROG_RESOURCES::Phase3Delete()
{
if (hMainMutex)
{
CloseHandle(hMainMutex);
hMainMutex = NULL;
}
return TRUE;
}
//
//
// ShutDownCore
//
//
/////////////////////////////////////////////////////////////////
bool ShutDownCore(BOOL bProcessShutdown,BOOL bIsSystemShutDown)
{
SCODE sc = WBEM_E_FAILED;
HMODULE hCoreModule = LoadLibrary(__TEXT("wbemcore.dll"));
if(hCoreModule)
{
pfnShutDown pfn = (pfnShutDown)GetProcAddress(hCoreModule, "Shutdown");
if(pfn)
{
sc = (pfn)(bProcessShutdown,bIsSystemShutDown);
DEBUGTRACE((LOG_WINMGMT, "core is being shut down by WinMgmt.exe, it returned 0x%x",sc));
}
FreeLibrary(hCoreModule);
}
return sc == S_OK;
}
//
//
// void Cleanup
//
//
// Release any currently loaded transports and close Ole etc.
//
//
///////////////////////////////////////////////////////////////////
void Cleanup(BOOL bIsSystemShutDown)
{
//DBG_PRINTFA((pBuff,"Cleanup called\n"));
if (!bIsSystemShutDown)
{
DEBUGTRACE((LOG_WINMGMT,"\nStarting cleanup, ID = %x", GetCurrentProcessId()));
CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
}
g_ProgRes.Phase1Delete(bIsSystemShutDown);
// If the core is still loaded, call its shutdown function
ShutDownCore(TRUE,bIsSystemShutDown);
g_ProgRes.Phase2Delete(bIsSystemShutDown);
if (!bIsSystemShutDown)
{
DEBUGTRACE((LOG_WINMGMT,"\nEnding cleanup"));
}
return;
}
//
//
// BOOL Initialize
//
//
///////////////////////////////////////////////////////////////
BOOL Initialize(HANDLE hTerminateEvt)
{
// Set the error mode. This is used to provent the system from putting up dialog boxs to
// open files
UINT errormode = SetErrorMode(0);
errormode |= SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS;
SetErrorMode(errormode);
int iCnt;
TCHAR tcName[MAX_PATH+1];
DEBUGTRACE((LOG_WINMGMT,"\nStarting Initialize, ID = %x", GetCurrentProcessId()));
if(!InitHotMofStuff(&g_ProgRes))
return FALSE;
if (!g_ProgRes.Phase2Build(hTerminateEvt))
return FALSE;
// Initialize Ole
SCODE sc;
sc = CoInitializeEx(NULL,COINIT_MULTITHREADED);
if(FAILED(sc))
{
TRACE((LOG_WINMGMT,"\nWINMGMT Could not initialize Ole\n"));
return FALSE;
}
else
{
g_ProgRes.m_bOleInitialized = TRUE;
}
//
// Call the initialize function in core
//
HMODULE hCoreModule = GetModuleHandle(_T("wbemcore.dll"));
if(hCoreModule)
{
HRESULT (STDAPICALLTYPE *pfn)(DWORD);
pfn = (long (__stdcall *)(DWORD))GetProcAddress(hCoreModule, "Reinitialize");
if(pfn)
{
sc = (*pfn)(0);
DEBUGTRACE((LOG_WINMGMT, "core is being resumed: it returned 0x%x",sc));
}
else
{
DEBUGTRACE((LOG_WINMGMT, "failed to re-initialize core"));
return FALSE;
}
}
g_ProgRes.RegisterLogin();
g_ProgRes.RegisterBackup();
g_ProgRes.ServiceStatus = SERVICE_RUNNING;
// Get the registry key which is the root for all the transports.
// ==============================================================
HKEY hKey;
long lRet = RegOpenKey(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\WBEM\\CIMOM\\TRANSPORTS"),
&hKey);
if(lRet != ERROR_SUCCESS)
{
DEBUGTRACE((LOG_WINMGMT,"\nRegOpenKey returned 0x%x while trying to open the transports node. Using default transports!",lRet));
}
else
{
/*
// Loop through each transport subkey.
// ===================================
for(iCnt = 0;ERROR_SUCCESS == RegEnumKey(hKey,iCnt,tcName,MAX_PATH+1);
iCnt++)
{
HKEY hSubKey;
lRet = RegOpenKey(hKey,tcName,&hSubKey);
if(lRet != ERROR_SUCCESS)
continue;
DWORD bytecount = sizeof(DWORD);
DWORD dwType;
// If the Enabled value isnt 1, then the transport is disabled
// and is ignored.
// ===========================================================
char cTemp[20];
bytecount=20;
lRet = RegQueryValueEx(hSubKey, TEXT("Enabled"), NULL, &dwType,
(LPBYTE) cTemp, &bytecount);
if(lRet != ERROR_SUCCESS || dwType != REG_SZ || cTemp[0] != '1')
{
RegCloseKey(hSubKey);
continue;
}
// Read the CLSID string and convert it into an CLSID structure.
// =============================================================
TCHAR szCLSID[50];
bytecount = sizeof(szCLSID);
lRet = RegQueryValueEx(hSubKey, TEXT("CLSID"), NULL, &dwType,
(LPBYTE) &szCLSID, &bytecount);
RegCloseKey(hSubKey);
if(lRet != ERROR_SUCCESS)
{
continue;
}
CLSID clsid;
sc = CLSIDFromString( szCLSID, &clsid);
if(sc != S_OK)
{
continue;
}
// Load up the transport object and then initialize it.
// ====================================================
IWbemTransport * pTransport = NULL;
sc = CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER,
IID_IWbemTransport, (LPVOID *) &pTransport);
if(sc != S_OK || pTransport == NULL)
{
continue;
}
sc = pTransport->Initialize();
if(sc != S_OK)
pTransport->Release();
else
g_ProgRes.m_TransportArray.Add(pTransport); // add it to the list
}
*/
RegCloseKey(hKey);
};
// initialize our writer for volume snapshot backup
// this must be after CoInitializeEx and after wbem is initialized
// (this pointer will be NULL during setup)
if (g_ProgRes.pWbemVssWriter)
{
HRESULT hRes = g_ProgRes.pWbemVssWriter->Initialize();
if (SUCCEEDED(hRes))
{
hRes = g_ProgRes.pWbemVssWriter->Subscribe();
if (SUCCEEDED(hRes))
{
g_ProgRes.bWbemVssWriterSubscribed = true;
}
else
{
TRACE((LOG_WINMGMT,"\nWINMGMT Could not subscribe the VssWriter"));
}
}
else
{
TRACE((LOG_WINMGMT,"\nWINMGMT Could not initialize the VssWriter"));
}
}
DEBUGTRACE((LOG_WINMGMT,"\nInitialize complete"));
// TO BE REPLACED WITH PROPER CODING --- FORCE CORE
// ================================================
return TRUE;
}
//
//
// WaitingFunction
//
// DESCRIPTION:
//
// Here is where we wait for messages and events during WinMgmt execution.
// We return from here when the program/service is being stopped.
//
//////////////////////////////////////////////////////////////////
void WaitingFunction(HANDLE hTerminate)
{
CSched sched;
DEBUGTRACE((LOG_WINMGMT,"\nInside the waiting function"));
HANDLE hEvents[] = {hTerminate,
g_ProgRes.ghCoreCanUnload,
g_ProgRes.ghCoreUnloaded,
g_ProgRes.ghCoreLoaded,
g_ProgRes.ghNeedRegistration,
g_ProgRes.ghProviderCanUnload,
g_ProgRes.ghMofDirChange // important, must be last entry!!!!
};
int iNumEvents = sizeof(hEvents) / sizeof(HANDLE);
DWORD dwFlags;
SCODE sc;
CPersistentConfig per;
per.TidyUp();
sched.SetWorkItem(PossibleStartCore, 60000);
//Load any MOFs in the MOF directory if needed...
LoadMofsInDirectory(g_ProgRes.szHotMofDirectory);
// resync the perf counters if
// we haven't turned this off for debugging AND
// we are not running during setup
if(GLOB_IsResyncAllowed())
{
ResyncPerf(RESYNC_TYPE_INITIAL);
GLOB_GetMonitor()->Register();
}
while(TRUE)
{
DWORD dwDelay = sched.GetWaitPeriod();
DWORD dwObj = WaitForMultipleObjects(iNumEvents, hEvents, FALSE, dwDelay);
switch (dwObj)
{
case 0: // bail out for terminate event
{
if (SERVICE_SHUTDOWN != g_ProgRes.ServiceStatus)
{
DEBUGTRACE((LOG_WINMGMT,"\nGot a termination event"));
}
{
CInMutex im(g_ProgRes.hMainMutex);
g_ProgRes.bShuttingDownWinMgmt = TRUE;
}
// call cleanup outside of a Mutex
Cleanup((g_ProgRes.ServiceStatus == SERVICE_SHUTDOWN)?TRUE:FALSE);
}
return;
case 1: // core can unload
DEBUGTRACE((LOG_WINMGMT,"\nGot a core can unload event"));
sched.SetWorkItem(FirstCoreShutdown, 30000); // 30 seconds until next unloac;
break;
case 2: // core went away
DEBUGTRACE((LOG_WINMGMT,"\nGot a core unloaded event"));
g_ProgRes.gbCoreLoaded = FALSE;
break;
case 3: // core loaded
DEBUGTRACE((LOG_WINMGMT,"\nGot a core loaded event"));
g_ProgRes.gbCoreLoaded = TRUE;
break;
case 4: // Need Registration
DEBUGTRACE((LOG_WINMGMT,"\nGot a NeedRegistration event"));
if (g_ProgRes.ServiceStatus == SERVICE_RUNNING)
{
g_ProgRes.RevokeLogin();
g_ProgRes.RegisterLogin();
}
SetEvent(g_ProgRes.ghRegistrationDone);
ResetEvent(g_ProgRes.ghNeedRegistration);
break;
case 5: // provider can unload
{
DEBUGTRACE((LOG_WINMGMT,"\nGot a provider can unload event"));
CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
//
// HACKHACK: Call it again to make sure that components that
// were released by unloading the first one can be unloaded
//
CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
sched.SetWorkItem(FinalCoreShutdown, CORE_PROVIDER_UNLOAD_TIMEOUT); // 11 minutes until next unloac;
}
break;
case 6: // change in the hot mof directory
{
DEBUGTRACE((LOG_WINMGMT,"\nGot change in the hot mof directory"));
LoadMofsInDirectory(g_ProgRes.szHotMofDirectory);
//Continue to monitor changes
if (!FindNextChangeNotification(g_ProgRes.ghMofDirChange))
{
iNumEvents--;
}
}
break;
case WAIT_TIMEOUT:
DEBUGTRACE((LOG_WINMGMT,"\nGot a TIMEOUT work item"));
if(sched.IsWorkItemDue(FirstCoreShutdown))
{
// All the clients have left the core and a decent time interval has passed. Set the
// WINMGMT_CORE_CAN_BACKUP event. When the core is done, it will set the WINMGMT_CORE_BACKUP_DONE
// event which will start the final unloading.
DEBUGTRACE((LOG_WINMGMT,"\nGot a FirstCoreShutdown work item"));
sched.ClearWorkItem(FirstCoreShutdown);
CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
}
if(sched.IsWorkItemDue(FinalCoreShutdown))
{
CInMutex im(g_ProgRes.hMainMutex);
DEBUGTRACE((LOG_WINMGMT,"\nGot a FinalCoreShutdown work item"));
CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
//
// HACKHACK: Call it again to make sure that components that
// were released by unloading the first one can be unloaded
CoFreeUnusedLibrariesEx ( CORE_PROVIDER_UNLOAD_TIMEOUT , 0 ) ;
sched.ClearWorkItem(FinalCoreShutdown);
}
if(sched.IsWorkItemDue(PossibleStartCore))
{
sched.StartCoreIfEssNeeded();
sched.ClearWorkItem(PossibleStartCore);
}
break;
}
}
}
//***************************************************************************
//
// MyService::MyService
//
// DESCRIPTION:
//
// Constructor.
//
//***************************************************************************
MyService::MyService(DWORD CtrlAccepted):CNtService(CtrlAccepted)
{
m_hStopEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if(m_hStopEvent == NULL)
{
DEBUGTRACE((LOG_WINMGMT,"\nMyService could not initialize"));
}
}
//***************************************************************************
//
// MyService::~MyService
//
// DESCRIPTION:
//
// Destructor.
//
//***************************************************************************
MyService::~MyService()
{
if(m_hStopEvent)
CloseHandle(m_hStopEvent);
}
//***************************************************************************
//
// DWORD MyService::WorkerThread
//
// DESCRIPTION:
//
// Where the service runs. In this case, the service just waits for
// the terminate event to be set.
//
// RETURN VALUE:
//
// 0
//***************************************************************************
DWORD MyService::WorkerThread()
{
DEBUGTRACE((LOG_WINMGMT,"\nStarting service worker thread"));
if(!::Initialize(m_hStopEvent))
return 0;
WaitingFunction(m_hStopEvent);
if (SERVICE_SHUTDOWN != g_ProgRes.ServiceStatus )
{
DEBUGTRACE((LOG_WINMGMT,"\nStopping service worker thread"));
}
return 0;
}
//
//
// VOID MyService::Log
//
///////////////////////////////////////////////////////////////////
VOID MyService::Log(
IN LPCSTR lpszMsg)
{
TRACE((LOG_WINMGMT,lpszMsg));
}
//
//
// the stop function
//
//////////////////////////////////////////////////////////////////
VOID MyService::Stop(BOOL bSystemShutDownCalled)
{
g_ProgRes.ServiceStatus = (bSystemShutDownCalled)?SERVICE_SHUTDOWN:SERVICE_STOPPED;
SetEvent(m_hStopEvent);
};
//
// MyService::Pause
//
////////////////////////////////////////////////////////////////////
HRESULT WbemPauseService()
{
HRESULT hr = WBEM_S_NO_ERROR;
g_ProgRes.ServiceStatus = SERVICE_PAUSED;
g_ProgRes.RevokeLogin();
GLOB_GetMonitor()->Unregister(FALSE);
SCODE sc = WBEM_E_FAILED;
HMODULE hCoreModule = LoadLibraryEx(__TEXT("wbemcore.dll"),NULL,0);
if(hCoreModule)
{
pfnShutDown pfn = (pfnShutDown)GetProcAddress(hCoreModule, "Shutdown");
if(pfn)
{
sc = pfn(FALSE,FALSE);
DEBUGTRACE((LOG_WINMGMT, "core is being shut down by WinMgmt.exe, it returned 0x%x",sc));
}
else
hr = WBEM_E_CRITICAL_ERROR;
FreeLibrary(hCoreModule);
}
else
hr = WBEM_E_CRITICAL_ERROR;
return hr;
}
VOID MyService::Pause()
{
WbemPauseService();
}
//
// MyService::Continue
//
////////////////////////////////////////////////////////////////////
HRESULT WbemContinueService()
{
HRESULT hr = WBEM_S_NO_ERROR;
// HRESULT APIENTRY Reinitialize(DWORD dwReserved);
SCODE sc = WBEM_E_FAILED;
HMODULE hCoreModule = LoadLibraryEx(__TEXT("wbemcore.dll"),NULL,0);
if(hCoreModule)
{
HRESULT (STDAPICALLTYPE *pfn)(DWORD);
pfn = (long (__stdcall *)(DWORD))GetProcAddress(hCoreModule, "Reinitialize");
if(pfn)
{
sc = (*pfn)(0);
DEBUGTRACE((LOG_WINMGMT, "core is being resumed: it returned 0x%x",sc));
}
else
hr = WBEM_E_CRITICAL_ERROR;
FreeLibrary(hCoreModule);
}
else
hr = WBEM_E_CRITICAL_ERROR;
g_ProgRes.RegisterLogin();
GLOB_GetMonitor()->Register();
g_ProgRes.ServiceStatus = SERVICE_RUNNING;
return hr;
}
VOID MyService::Continue()
{
WbemContinueService();
}
//
//
// this function will be executed before
// the final SetServiceStatus(SERVICE_STOPPED)
//
//////////////////////////////////////////////////////////
VOID MyService::FinalCleanup()
{
g_ProgRes.Phase3Delete();
RegSetDWORD(HKEY_LOCAL_MACHINE,
HOME_REG_PATH,
_T("ProcessID"),
0);
}
//
// TO be removed before RTM
// publish process ID in the registry
//
////////////////////////////////////////////////////
DWORD
RegSetDWORD(HKEY hKey,
TCHAR * pName,
TCHAR * pValue,
DWORD dwValue)
{
HKEY hKey2;
LONG lRet;
lRet = RegOpenKeyEx(hKey,
pName,
0,
KEY_WRITE,
&hKey2);
if (ERROR_SUCCESS == lRet)
{
DWORD dwType = REG_DWORD;
DWORD dwSize = sizeof(DWORD);
lRet = RegSetValueEx(hKey2,
pValue,
NULL,
dwType,
(BYTE *)&dwValue,
dwSize);
RegCloseKey(hKey2);
}
return lRet;
}
DWORD
RegGetDWORD(HKEY hKey,
TCHAR * pName,
TCHAR * pValue,
DWORD * pdwValue)
{
HKEY hKey2;
LONG lRet;
if (0 == pdwValue)
return ERROR_INVALID_PARAMETER;
lRet = RegOpenKeyEx(hKey,
pName,
0,
KEY_READ,
&hKey2);
if (ERROR_SUCCESS == lRet)
{
DWORD dwSize = sizeof(DWORD);
DWORD dwType =0;
lRet = RegQueryValueEx(hKey2,
pValue,
NULL,
&dwType,
(BYTE *)pdwValue,
&dwSize);
RegCloseKey(hKey2);
}
return lRet;
}
//
//
// Interceptor
//
//
///////////////////////////////////////////////////////////
#ifdef INSTRUMENTED_BUILD
#ifdef _X86_
#include <malloc.h>
struct HEAP_ENTRY {
WORD Size;
WORD PrevSize;
BYTE SegmentIndex;
BYTE Flags;
BYTE UnusedBytes;
BYTE SmallTagIndex;
};
#define HEAP_SLOW_FLAGS 0x7d030f60
// only the "header"
typedef struct _HEAP {
HEAP_ENTRY Entry;
ULONG Signature;
ULONG Flags;
ULONG ForceFlags;
} HEAP;
BOOL g_FaultHeapEnabled = FALSE;
BOOL g_FaultFileEnabled = FALSE;
ULONG g_Seed;
ULONG g_Factor = 100000;
ULONG g_Percent = 0x20;
//ULONG g_RowOfFailures = 10;
//LONG g_NumFailInARow = 0;
//LONG g_NumFailedAllocation = 0;
BOOL g_bDisableBreak = FALSE;
LONG g_nSuccConn = 0;
#define SIZE_JUMP_ADR 5
#define SIZE_SAVED_INSTR 12
void
_declspec(naked) Prolog__ReadFile(){
_asm {
// this is the space for the "saved istructions"
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
// this is the place for the JMP
nop ;
nop ;
nop ;
nop ;
nop ;
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
}
}
BOOL _I_ReadFile(
HANDLE hFile, // handle to file
LPVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToRead, // number of bytes to read
LPDWORD lpNumberOfBytesRead, // number of bytes read
LPOVERLAPPED lpOverlapped // offset
){
DWORD * pDw = (DWORD *)_alloca(sizeof(DWORD));
BOOL bRet;
LONG Ret = RtlRandomEx(&g_Seed);
if (g_FaultFileEnabled && (Ret%g_Factor < g_Percent))
{
if (lpNumberOfBytesRead)
*lpNumberOfBytesRead = 0;
return FALSE;
}
_asm{
push lpOverlapped;
push lpNumberOfBytesRead;
push nNumberOfBytesToRead;
push lpBuffer;
push hFile;
call Prolog__ReadFile;
mov bRet,eax
}
return bRet;
}
void
_declspec(naked) Prolog__WriteFile(){
_asm {
// this is the space for the "saved istructions"
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
// this is the place for the JMP
nop ;
nop ;
nop ;
nop ;
nop ;
nop ; // dist
nop ; // dist
nop ; // dist
}
}
BOOL _I_WriteFile(
HANDLE hFile, // handle to file
LPCVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten, // number of bytes written
LPOVERLAPPED lpOverlapped // overlapped buffer
){
DWORD * pDw = (DWORD *)_alloca(sizeof(DWORD));
BOOL bRet;
LONG Ret = RtlRandomEx(&g_Seed);
if (g_FaultFileEnabled && (Ret%g_Factor < g_Percent))
{
if (lpNumberOfBytesWritten)
*lpNumberOfBytesWritten = 0;
return FALSE;
}
_asm{
push lpOverlapped;
push lpNumberOfBytesWritten;
push nNumberOfBytesToWrite;
push lpBuffer;
push hFile;
call Prolog__WriteFile;
mov bRet,eax
}
return bRet;
}
void
_declspec(naked) Prolog__CreateEvent(){
_asm {
// this is the space for the "saved istructions"
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
// this is the place for the JMP
nop ;
nop ;
nop ;
nop ;
nop ;
nop ; // dist
nop ; // dist
}
}
HANDLE _I_CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // SD
BOOL bManualReset, // reset type
BOOL bInitialState, // initial state
LPCWSTR lpName // object name
)
{
DWORD * pDw = (DWORD *)_alloca(sizeof(DWORD));
HANDLE hHandle;
LONG Ret = RtlRandomEx(&g_Seed);
if (g_FaultFileEnabled && (Ret%g_Factor < g_Percent))
{
return NULL;
}
_asm{
push lpName;
push bInitialState;
push bManualReset;
push lpEventAttributes
call Prolog__CreateEvent;
mov hHandle,eax
}
return hHandle;
}
void
_declspec(naked) Prolog__RtlFreeHeap(){
_asm {
// this is the space for the "saved istructions"
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
// this is the place for the JMP
nop ;
nop ;
nop ;
nop ;
nop ;
}
}
#define SPACE_STACK_ALLOC (4*sizeof(ULONG_PTR))
DWORD _I_RtlFreeHeap(VOID * pHeap,DWORD Flags,VOID * pBlock)
{
ULONG * pLong = (ULONG *)_alloca(sizeof(DWORD));
Flags |= (((HEAP *)pHeap)->Flags) | (((HEAP *)pHeap)->ForceFlags);
DWORD dwRet;
if (pBlock && !(HEAP_SLOW_FLAGS & Flags))
{
HEAP_ENTRY * pEntry = (HEAP_ENTRY *)pBlock-1;
DWORD RealSize = pEntry->Size * sizeof(HEAP_ENTRY);
DWORD Size = RealSize - pEntry->UnusedBytes;
ULONG_PTR * pL = (ULONG_PTR *)pBlock;
if (0 == (pEntry->Flags & 0x01) ||0xf0f0f0f0 == pL[1] )
{
if (!g_bDisableBreak)
DebugBreak();
}
DWORD CanMemset = RealSize-sizeof(HEAP_ENTRY);
memset(pBlock,0xF0,(CanMemset > SPACE_STACK_ALLOC)?CanMemset-SPACE_STACK_ALLOC:CanMemset);
if (pEntry->Size >=4)
{
RtlCaptureStackBackTrace (1,
(4 == pEntry->Size)?4:6,
(PVOID *)(pEntry+2),
pLong);
}
}
_asm {
push pBlock ;
push Flags ;
push pHeap ;
call Prolog__RtlFreeHeap ;
mov dwRet,eax ;
}
return dwRet;
}
void
_declspec(naked) Prolog__RtlAllocateHeap(){
_asm {
// this is the space for the "saved istructions"
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
// this is the place for the JMP
nop ;
nop ;
nop ;
nop ;
nop ;
nop ; // to make this distinct
}
}
VOID * _I_RtlAllocateHeap(VOID * pHeap,DWORD Flags,DWORD Size)
{
ULONG * pLong = (ULONG *)_alloca(sizeof(DWORD));
Flags |= (((HEAP *)pHeap)->Flags) | (((HEAP *)pHeap)->ForceFlags);
VOID * pRet;
DWORD NewSize = (Size < (3*sizeof(HEAP_ENTRY)))?(3*sizeof(HEAP_ENTRY)+SPACE_STACK_ALLOC):(Size+SPACE_STACK_ALLOC);
/*
if (g_FaultHeapEnabled && g_NumFailInARow)
{
InterlockedDecrement(&g_NumFailInARow);
goto here;
}
*/
LONG Ret = RtlRandomEx(&g_Seed);
if (g_FaultHeapEnabled && (Ret%g_Factor < g_Percent))
{
// g_NumFailInARow = g_RowOfFailures;
//here:
// InterlockedIncrement(&g_NumFailedAllocation);
return NULL;
}
_asm {
push NewSize ;
push Flags ;
push pHeap ;
call Prolog__RtlAllocateHeap ;
mov pRet,eax ;
}
if (pRet && !(HEAP_SLOW_FLAGS & Flags) )
{
if (NewSize <= 0xffff)
NewSize = sizeof(HEAP_ENTRY)*((HEAP_ENTRY *)pRet-1)->Size;
if (!(HEAP_ZERO_MEMORY & Flags))
{
memset(pRet,0xc0,NewSize-sizeof(HEAP_ENTRY));
}
RtlCaptureStackBackTrace(1,
4,
(PVOID *)((BYTE *)pRet+(NewSize-SPACE_STACK_ALLOC-sizeof(HEAP_ENTRY))),
pLong);
}
return pRet;
}
void
_declspec(naked) Prolog__RtlReAllocateHeap(){
_asm {
// this is the space for the "saved istructions"
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
// this is the place for the JMP
nop ;
nop ;
nop ;
nop ;
nop ;
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
}
}
VOID *
_I_RtlReAllocateHeap(
HANDLE pHeap, // handle to heap block
DWORD Flags, // heap reallocation options
LPVOID lpMem, // pointer to memory to reallocate
SIZE_T Size // number of bytes to reallocate
){
ULONG * pLong = (ULONG *)_alloca(sizeof(DWORD));
Flags |= (((HEAP *)pHeap)->Flags) | (((HEAP *)pHeap)->ForceFlags);
VOID * pRet;
DWORD NewSize = (Size < (3*sizeof(HEAP_ENTRY)))?(3*sizeof(HEAP_ENTRY)+SPACE_STACK_ALLOC):(Size+SPACE_STACK_ALLOC);
_asm {
push NewSize ;
push lpMem ;
push Flags ;
push pHeap ;
call Prolog__RtlReAllocateHeap ;
mov pRet,eax ;
}
if (pRet && !(HEAP_SLOW_FLAGS & Flags) )
{
if (NewSize <= 0xffff)
NewSize = sizeof(HEAP_ENTRY)*((HEAP_ENTRY *)pRet-1)->Size;
RtlCaptureStackBackTrace(1,
4,
(PVOID *)((BYTE *)pRet+(NewSize-SPACE_STACK_ALLOC-sizeof(HEAP_ENTRY))),
pLong);
}
return pRet;
}
void
_declspec(naked) Prolog__RtlValidateHeap(){
_asm {
// this is the space for the "saved istructions"
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
// this is the place for the JMP
nop ;
nop ;
nop ;
nop ;
nop ;
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
}
}
BOOL
_I_RtlValidateHeap(
HANDLE pHeap, // handle to heap block
DWORD dwFlags, // heap reallocation options
LPVOID lpMem // pointer to memory to validate
){
ULONG * pLong = (ULONG *)_alloca(sizeof(DWORD));
BOOL bRet;
g_bDisableBreak = TRUE;
_asm {
push lpMem ;
push dwFlags ;
push pHeap ;
call Prolog__RtlValidateHeap ;
mov bRet,eax ;
}
g_bDisableBreak = FALSE;
return bRet;
}
#if 0
#define MAX_REMEMBER (1024)
struct CSCCTrace
{
VOID * p1;
VOID * p2;
DWORD Tid;
ULONG_PTR Trace[5];
} g_CSCCTrace[MAX_REMEMBER];
LONG g_CSCCIndex = -1;
void
_declspec(naked) Prolog__CoSwitchCallContext(){
_asm {
// this is the space for the "saved istructions"
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
nop ;
// this is the place for the JMP
nop ;
nop ;
nop ;
nop ;
nop ;
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
nop ; // dist
}
}
HRESULT WINAPI
_I_CoSwitchCallContext(IUnknown * pNew,
IUnknown ** ppOld)
{
ULONG * pLong = (ULONG * )_alloca(sizeof(ULONG ));
long nIndex = InterlockedIncrement(&g_CSCCIndex);
nIndex %= MAX_REMEMBER;
CSCCTrace * pTrace = &g_CSCCTrace[nIndex];
pTrace->p1 = pNew;
if (ppOld)
pTrace->p2 = *ppOld;
else
pTrace->p2 = 0;
pTrace->Tid =GetCurrentThreadId();
RtlCaptureStackBackTrace (1,5,(PVOID *)pTrace->Trace,pLong);
HRESULT hRes;
_asm {
push ppOld;
push pNew;
call Prolog__CoSwitchCallContext;
mov hRes,eax;
};
return hRes;
}
#endif
void intercept2(WCHAR * Module,
LPSTR Function,
VOID * NewRoutine,
VOID * pPrologStorage,
DWORD Size)
{
FARPROC OldRoutine = GetProcAddress(GetModuleHandleW(Module),Function);
if (OldRoutine)
{
MEMORY_BASIC_INFORMATION MemBI;
DWORD dwOldProtect;
BOOL bRet, bRet2;
DWORD dwRet;
dwRet = VirtualQuery(OldRoutine,&MemBI,sizeof(MemBI));
bRet = VirtualProtect(MemBI.BaseAddress,
MemBI.RegionSize,
PAGE_EXECUTE_WRITECOPY,
&dwOldProtect);
dwRet = VirtualQuery(pPrologStorage,&MemBI,sizeof(MemBI));
bRet2 = VirtualProtect(MemBI.BaseAddress,
MemBI.RegionSize,
PAGE_EXECUTE_WRITECOPY,
&dwOldProtect);
if (bRet && bRet2)
{
VOID * pToJump = (VOID *)NewRoutine;
BYTE Arr[SIZE_JUMP_ADR] = { 0xe9 };
LONG * pOffset = (LONG *)&Arr[1];
* pOffset = (LONG)NewRoutine - (LONG)OldRoutine - SIZE_JUMP_ADR ;
// save the old code
memcpy(pPrologStorage,OldRoutine,Size);
// put the new code
memset(OldRoutine,0x90,Size);
memcpy(OldRoutine,Arr,SIZE_JUMP_ADR);
// adjust the prolog to continue
* pOffset = (LONG)OldRoutine + Size - (LONG)pPrologStorage - SIZE_SAVED_INSTR - SIZE_JUMP_ADR; // magic for nops
memcpy((BYTE *)pPrologStorage+SIZE_SAVED_INSTR,Arr,SIZE_JUMP_ADR);
}
}
else
{
OutputDebugStringA("GetProcAddress FAIL\n");
}
}
void unintercept(WCHAR * Module,
LPSTR Function,
VOID * pPrologStorage,
DWORD Size)
{
FARPROC OldRoutine = GetProcAddress(GetModuleHandleW(Module),Function);
if (OldRoutine)
{
memcpy((void *)OldRoutine,pPrologStorage,Size);
}
}
#endif /*_X86_*/
#ifndef STATUS_POSSIBLE_DEADLOCK
#define STATUS_POSSIBLE_DEADLOCK (0xC0000194L)
#endif
class CSetVectoredHandler
{
private:
// static ULONG_PTR Base;
// static ULONG_PTR Limit;
PVOID pVectorHandler;
enum ExceptionTypes
{
StatusAccessViolation,
CXXException,
StatusNoMemory,
OtherExceptions,
LastException
};
static LONG ExceptionCounters[LastException];
/*
BOOL GetDllLimits(WCHAR * pDllName)
{
UNICODE_STRING DllName;
RtlInitUnicodeString(&DllName,pDllName);
PEB_LDR_DATA * pLdr = NtCurrentPeb()->Ldr;
LIST_ENTRY * pHeadEntry = &pLdr->InLoadOrderModuleList;
LIST_ENTRY * pEntry = pLdr->InLoadOrderModuleList.Flink;
BOOL bFound = FALSE;
while (pHeadEntry != pEntry)
{
LDR_DATA_TABLE_ENTRY * pData = CONTAINING_RECORD(pEntry,
LDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
if (0 == _wcsicmp(DllName.Buffer,pData->BaseDllName.Buffer))
{
//OutputDebugStringA("found\n");
Base = (ULONG_PTR)pData->DllBase;
Limit = Base + (ULONG_PTR)pData->SizeOfImage;
bFound = TRUE;
break;
}
pEntry = pEntry->Flink;
}
return bFound;
}
*/
public:
CSetVectoredHandler()
{
pVectorHandler = NULL;
//if (GetDllLimits(L"fastprox.dll"))
//{
pVectorHandler = AddVectoredExceptionHandler(TRUE,CSetVectoredHandler::VectoredHandler);
//}
};
~CSetVectoredHandler()
{
if (pVectorHandler)
RemoveVectoredExceptionHandler(pVectorHandler);
};
static LONG WINAPI VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
PEXCEPTION_RECORD pExr = ExceptionInfo->ExceptionRecord;
PCONTEXT pCxr = ExceptionInfo->ContextRecord;
switch (pExr->ExceptionCode)
{
case STATUS_PRIVILEGED_INSTRUCTION:
case STATUS_INVALID_HANDLE:
case STATUS_STACK_OVERFLOW:
case STATUS_POSSIBLE_DEADLOCK:
case STATUS_ACCESS_VIOLATION:
InterlockedIncrement(&ExceptionCounters[(LONG)StatusAccessViolation]);
DebugBreak();
break;
case 0xe06d7363:
InterlockedIncrement(&ExceptionCounters[(LONG)CXXException]);
break;
case STATUS_NO_MEMORY:
InterlockedIncrement(&ExceptionCounters[(LONG)StatusNoMemory]);
break;
default:
InterlockedIncrement(&ExceptionCounters[(LONG)OtherExceptions]);
break;
}
return EXCEPTION_CONTINUE_SEARCH;
}
} g_C;
LONG CSetVectoredHandler::ExceptionCounters[CSetVectoredHandler::LastException];
#endif
//
//
// ServiceMain
//
///////////////////////////////////////////////////////////
VOID WINAPI
ServiceMain(DWORD dwNumServicesArgs,
LPWSTR *lpServiceArgVectors)
{
#ifdef INSTRUMENTED_BUILD
#ifdef _X86_
intercept2(L"ntdll.dll","RtlFreeHeap",_I_RtlFreeHeap,Prolog__RtlFreeHeap,5);
intercept2(L"ntdll.dll","RtlAllocateHeap",_I_RtlAllocateHeap,Prolog__RtlAllocateHeap,5);
intercept2(L"ntdll.dll","RtlReAllocateHeap",_I_RtlReAllocateHeap,Prolog__RtlReAllocateHeap,5);
intercept2(L"ntdll.dll","RtlValidateHeap",_I_RtlValidateHeap,Prolog__RtlValidateHeap,7);
intercept2(L"kernel32.dll","CreateEventW",_I_CreateEvent,Prolog__CreateEvent,6);
intercept2(L"kernel32.dll","WriteFile",_I_WriteFile,Prolog__WriteFile,7);
intercept2(L"kernel32.dll","ReadFile",_I_ReadFile,Prolog__ReadFile,7);
g_nSuccConn = 0;
#endif /*_X86_*/
#endif
RegSetDWORD(HKEY_LOCAL_MACHINE,
HOME_REG_PATH,
_T("ProcessID"),
GetCurrentProcessId());
if (InitialBreak())
{
DebugBreak();
}
g_ProgRes.Init();
g_ProgRes.Phase1Build();
MyService ThisService(SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_PAUSE_CONTINUE);
ThisService.Run(SERVICE_NAME,
dwNumServicesArgs,
lpServiceArgVectors,
(void *)&ThisService);
#ifdef INSTRUMENTED_BUILD
#ifdef _X86_
unintercept(L"ntdll.dll","RtlFreeHeap",Prolog__RtlFreeHeap,5);
unintercept(L"ntdll.dll","RtlAllocateHeap",Prolog__RtlAllocateHeap,5);
unintercept(L"ntdll.dll","RtlReAllocateHeap",Prolog__RtlReAllocateHeap,5);
unintercept(L"ntdll.dll","RtlValidateHeap",Prolog__RtlValidateHeap,7);
unintercept(L"kernel32.dll","CreateEventW",Prolog__CreateEvent,6);
unintercept(L"kernel32.dll","WriteFile",Prolog__WriteFile,7);
unintercept(L"kernel32.dll","ReadFile",Prolog__ReadFile,7);
#endif /*_X86_*/
#endif
}