mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1949 lines
46 KiB
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
|
|
|
|
}
|