Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1612 lines
52 KiB

// DBGLauncher.cpp : Implementation of WinMain
// Note: Proxy/Stub Information
// To build a separate proxy/stub DLL,
// run nmake -f DBGLauncherps.mk in the project directory.
#include "stdafx.h"
#include "resource.h"
#include "Messages.h"
#include <time.h>
#include <sys/timeb.h>
#include <strsafe.h>
#include "DBGLauncher_i.c"
#include "ocamon.h"
#define MAX_QUEUE_OPEN_RETRY 5
static WCHAR strGuidMQTestType[] =
L"{c30e0960-a2c0-11cf-9785-00608cb3e80c}";
// Some useful macros
#define RELEASE(punk) if (punk) { (punk)->Release(); (punk) = NULL; }
#define ADDREF(punk) ((punk) ? (punk)->AddRef() : 0)
CServiceModule _Module;
HANDLE g_hStopEvent = NULL;
BOOL g_ReadQueueFlag = TRUE;
BEGIN_OBJECT_MAP(ObjectMap)
END_OBJECT_MAP()
LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
{
while (p1 != NULL && *p1 != NULL)
{
LPCTSTR p = p2;
while (p != NULL && *p != NULL)
{
if (*p1 == *p)
return CharNext(p1);
p = CharNext(p);
}
p1 = CharNext(p1);
}
return NULL;
}
// Although some of these functions are big they are declared inline since they are only used once
inline HRESULT CServiceModule::RegisterServer(BOOL bRegTypeLib, BOOL bService)
{
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
return hr;
// Remove any previous service since it may point to
// the incorrect file
Uninstall();
SetupEventLog(FALSE);
// Add service entries
UpdateRegistryFromResource(IDR_DBGLauncher, TRUE);
// Adjust the AppID for Local Server or Service
CRegKey keyAppID;
LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE);
if (lRes != ERROR_SUCCESS)
return lRes;
CRegKey key;
lRes = key.Open(keyAppID, _T("{5D3C7CA6-DF04-4864-897D-83BF996692B3}"), KEY_WRITE);
if (lRes != ERROR_SUCCESS)
return lRes;
key.DeleteValue(_T("LocalService"));
if (bService)
{
key.SetValue(_T("DBGLauncher"), _T("LocalService") );
key.SetValue(_T("-Service"), _T("ServiceParameters"));
// Create service
Install();
}
// Add object entries
hr = CComModule::RegisterServer(bRegTypeLib);
CoUninitialize();
return hr;
}
inline HRESULT CServiceModule::UnregisterServer()
{
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
return hr;
// Remove service entries
UpdateRegistryFromResource(IDR_DBGLauncher, FALSE);
// Remove service
Uninstall();
// Remove object entries
CComModule::UnregisterServer(TRUE);
CoUninitialize();
return S_OK;
}
inline void CServiceModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, UINT nServiceNameID, const GUID* plibid)
{
CComModule::Init(p, h, plibid);
m_bService = TRUE;
LoadString(h, nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR));
// set up the initial service status
m_hServiceStatus = NULL;
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
m_status.dwCurrentState = SERVICE_STOPPED;
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
m_status.dwWin32ExitCode = 0;
m_status.dwServiceSpecificExitCode = 0;
m_status.dwCheckPoint = 0;
m_status.dwWaitHint = 0;
//
// Create Named Events
//
g_hStopEvent = CreateEvent(
NULL,
FALSE,
FALSE,
s_cszStopEvent
);
if(NULL == g_hStopEvent)
{
LogEvent( _T("Failed to create stop event: %s; hr=%ld"),
s_cszStopEvent,
GetLastError());
}
m_hMonNotifyPipe = NULL;
}
LONG CServiceModule::Unlock()
{
LONG l = CComModule::Unlock();
if (l == 0 && !m_bService)
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
return l;
}
BOOL CServiceModule::IsInstalled()
{
BOOL bResult = FALSE;
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM != NULL)
{
SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG);
if (hService != NULL)
{
bResult = TRUE;
::CloseServiceHandle(hService);
}
::CloseServiceHandle(hSCM);
}
return bResult;
}
inline BOOL CServiceModule::Install()
{
if (IsInstalled())
return TRUE;
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL)
{
MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
return FALSE;
}
SetupEventLog(TRUE);
// Get the executable file path
TCHAR szFilePath[_MAX_PATH];
::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
SC_HANDLE hService = ::CreateService(
hSCM, m_szServiceName, m_szServiceName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);
if (hService == NULL)
{
::CloseServiceHandle(hSCM);
MessageBox(NULL, _T("Couldn't create service"), m_szServiceName, MB_OK);
return FALSE;
}
SERVICE_FAILURE_ACTIONS Failure;
SC_ACTION Actions[3];
Failure.cActions = 3;
Failure.dwResetPeriod = 1200;
Failure.lpCommand = _T("");
Failure.lpRebootMsg = _T("");
Failure.lpsaActions = Actions;
Actions[0].Delay = 2000;
Actions[0].Type = SC_ACTION_RESTART;
Actions[1].Delay = 2000;
Actions[1].Type = SC_ACTION_RESTART;
Actions[2].Delay = 2000;
Actions[2].Type = SC_ACTION_RESTART;
::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);
return TRUE;
}
inline BOOL CServiceModule::Uninstall()
{
if (!IsInstalled())
return TRUE;
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL)
{
MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
return FALSE;
}
SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_STOP | DELETE);
if (hService == NULL)
{
::CloseServiceHandle(hSCM);
MessageBox(NULL, _T("Couldn't open service"), m_szServiceName, MB_OK);
return FALSE;
}
SERVICE_STATUS status;
::ControlService(hService, SERVICE_CONTROL_STOP, &status);
BOOL bDelete = ::DeleteService(hService);
::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);
if (bDelete)
return TRUE;
MessageBox(NULL, _T("Service could not be deleted"), m_szServiceName, MB_OK);
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////////////
// Logging functions
void CServiceModule::LogEvent(LPCTSTR pFormat, ...)
{
TCHAR chMsg[256];
HANDLE hEventSource;
LPTSTR lpszStrings[1];
va_list pArg;
va_start(pArg, pFormat);
// _vstprintf(chMsg, pFormat, pArg);
if (StringCbVPrintf(chMsg,sizeof chMsg, pFormat, pArg) != S_OK)
{
return;
}
va_end(pArg);
lpszStrings[0] = chMsg;
if (m_bService)
{
/* Get a handle to use with ReportEvent(). */
hEventSource = RegisterEventSource(NULL, m_szServiceName);
if (hEventSource != NULL)
{
/* Write to event log. */
ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, EVENT_MESSAGE, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
DeregisterEventSource(hEventSource);
}
}
else
{
// As we are not running as a service, just write the error to the console.
_putts(chMsg);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Service startup and registration
inline void CServiceModule::Start()
{
SERVICE_TABLE_ENTRY st[] =
{
{ m_szServiceName, _ServiceMain },
{ NULL, NULL }
};
if (m_bService && !::StartServiceCtrlDispatcher(st))
{
m_bService = FALSE;
}
if (m_bService == FALSE)
Run();
}
inline void CServiceModule::ServiceMain(DWORD /* dwArgc */, LPTSTR* /* lpszArgv */)
{
// Register the control request handler
m_status.dwCurrentState = SERVICE_START_PENDING;
m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
if (m_hServiceStatus == NULL)
{
LogEvent(_T("Handler not installed"));
return;
}
SetServiceStatus(SERVICE_START_PENDING);
m_status.dwWin32ExitCode = S_OK;
m_status.dwCheckPoint = 0;
m_status.dwWaitHint = 0;
// When the Run function returns, the service has stopped.
Run();
SetupEventLog(TRUE);
SetServiceStatus(SERVICE_STOPPED);
LogEvent(_T("Service stopped"));
}
inline void CServiceModule::Handler(DWORD dwOpcode)
{
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
SetServiceStatus(SERVICE_STOP_PENDING);
// SetServiceStatus(SERVICE_STOP_PENDING);
if(NULL != g_hStopEvent)
{
if(FALSE == SetEvent( g_hStopEvent ))
{
LogFatalEvent( _T("Unable to signal Stop Event; Error: %ld"), GetLastError());
}
CloseHandle( g_hStopEvent );
}
/// PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
// break;
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
break;
case SERVICE_CONTROL_PAUSE:
break;
case SERVICE_CONTROL_CONTINUE:
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
break;
default:
LogEvent(_T("Bad service request"));
}
}
void WINAPI CServiceModule::_ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
_Module.ServiceMain(dwArgc, lpszArgv);
}
void WINAPI CServiceModule::_Handler(DWORD dwOpcode)
{
_Module.Handler(dwOpcode);
}
void CServiceModule::SetServiceStatus(DWORD dwState)
{
m_status.dwCurrentState = dwState;
::SetServiceStatus(m_hServiceStatus, &m_status);
}
void CServiceModule::Run()
{
BYTE *byteVersionBuff = NULL;
VS_FIXEDFILEINFO *pVersionInfo = NULL;
UINT uLength = 0;
_Module.dwThreadID = GetCurrentThreadId();
TCHAR szFilePath[_MAX_PATH];
DWORD dwPlaceHolder = 0;
// HRESULT hr = CoInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call
// instead to make the EXE free threaded.
// This means that calls come in on a random RPC thread
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
_ASSERTE(SUCCEEDED(hr));
// This provides a NULL DACL which will allow access to everyone.
CSecurityDescriptor sd;
sd.InitializeFromThreadToken();
hr = CoInitializeSecurity(sd, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
_ASSERTE(SUCCEEDED(hr));
hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
_ASSERTE(SUCCEEDED(hr));
ZeroMemory(szFilePath, sizeof szFilePath);
::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
if (szFilePath[0] != _T('\0'))
{
DWORD dwBufferSize = GetFileVersionInfoSize(szFilePath,&dwPlaceHolder);
if (dwBufferSize > 0)
byteVersionBuff = (BYTE*) malloc (dwBufferSize);
if (byteVersionBuff)
{
GetFileVersionInfo(szFilePath,NULL,dwBufferSize,byteVersionBuff);
VerQueryValue(byteVersionBuff,_T("\\"),(VOID **) &pVersionInfo, &uLength);
LogEvent(_T("DbgLauncher service version: %d.%d.%d.%d Started."), HIWORD (pVersionInfo->dwFileVersionMS),LOWORD(pVersionInfo->dwFileVersionMS)
,HIWORD(pVersionInfo->dwFileVersionLS),LOWORD(pVersionInfo->dwFileVersionLS)) ;
}
}
// DWORD NameLength = sizeof(TCHAR) * (MAX_COMPUTERNAME_LENGTH + 1);
if (m_bService)
SetServiceStatus(SERVICE_RUNNING);
//
// Execute Archive Service
//
try
{
PrepareForDebuggerLaunch();
}
catch(...)
{
LogEvent( _T("dbgLauncher Service CRASHED !!! "));
}
if (m_hMonNotifyPipe != NULL &&
m_hMonNotifyPipe != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hMonNotifyPipe);
m_hMonNotifyPipe = NULL;
}
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
_Module.RevokeClassObjects();
CoUninitialize();
}
/////////////////////////////////////////////////////////////////////////////
//
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
{
lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
_Module.Init(ObjectMap, hInstance, IDS_SERVICENAME, &LIBID_DBGLAUNCHERLib);
_Module.m_bService = TRUE;
TCHAR szTokens[] = _T("-/");
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
while (lpszToken != NULL)
{
if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
NORM_IGNORECASE,
lpszToken,
-1,
_T("UnregServer"),
-1 ) == CSTR_EQUAL)
// if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
return _Module.UnregisterServer();
// Register as Local Server
if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
NORM_IGNORECASE,
lpszToken,
-1,
_T("RegServer"),
-1 ) == CSTR_EQUAL)
//if (lstrcmpi(lpszToken, _T("RegServer"))==0)
return _Module.RegisterServer(TRUE, FALSE);
// Register as Service
if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
NORM_IGNORECASE,
lpszToken,
-1,
_T("Service"),
-1 ) == CSTR_EQUAL)
// if (lstrcmpi(lpszToken, _T("Service"))==0)
return _Module.RegisterServer(TRUE, TRUE);
lpszToken = FindOneOf(lpszToken, szTokens);
}
// Are we Service or Local Server
CRegKey keyAppID;
LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ);
if (lRes != ERROR_SUCCESS)
return lRes;
CRegKey key;
lRes = key.Open(keyAppID, _T("{5D3C7CA6-DF04-4864-897D-83BF996692B3}"), KEY_READ);
if (lRes != ERROR_SUCCESS)
return lRes;
TCHAR szValue[_MAX_PATH];
DWORD dwLen = _MAX_PATH;
lRes = key.QueryValue(szValue,_T("LocalService"), &dwLen);
_Module.m_bService = FALSE;
if (lRes == ERROR_SUCCESS)
_Module.m_bService = TRUE;
_Module.Start();
// When we get here, the service has been stopped
return _Module.m_status.dwWin32ExitCode;
}
BOOL
CServiceModule::GetServiceParams(SVCPARAMS *ServiceParams)
{
HKEY hHKLM;
HKEY hDbgLauncherKey;
BYTE Buffer[MAX_PATH + 1];
DWORD Type;
DWORD BufferSize = MAX_PATH +1; // Set for largest value
BOOL Status = TRUE;
if(!RegConnectRegistry(NULL, HKEY_LOCAL_MACHINE, &hHKLM))
{
if(!RegOpenKeyEx(hHKLM,_T("Software\\Microsoft\\DbgLauncherSvc"), 0, KEY_ALL_ACCESS, &hDbgLauncherKey))
{
// Get the input queue directory path
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
if (RegQueryValueEx(hDbgLauncherKey,_T("DebuggerName"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
LogEvent(_T("Failed to get InputQueue value from registry."));
Status = FALSE;
}
else
{
if (StringCbCopy (ServiceParams->DebuggerName, sizeof ServiceParams->DebuggerName,(TCHAR *) Buffer)!= S_OK)
{
LogEvent (_T("Failed to copy debuggername reg value to ServiceParams->DebuggerName"));
Status = FALSE;
}
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// Now get the Primary Queue connection string
if (RegQueryValueEx(hDbgLauncherKey,_T("PrimaryQueue"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
LogEvent(_T("Failed to get PrimaryQueue value from registry."));
Status = FALSE;
}
else
{
if (StringCbCopy(ServiceParams->PrimaryQueue,sizeof ServiceParams->PrimaryQueue, (TCHAR *) Buffer)!= S_OK)
{
LogEvent (_T("Failed to copy PrimaryQueue reg value to ServiceParams->PrimaryQueue"));
Status = FALSE;
}
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// Now get the Primary Queue connection string
if (RegQueryValueEx(hDbgLauncherKey,_T("SecondaryQueue"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
LogEvent(_T("Failed to get SecondaryQueue value from registry."));
Status = FALSE;
}
else
{
if (StringCbCopy(ServiceParams->SecondaryQueue,sizeof ServiceParams->SecondaryQueue, (TCHAR *) Buffer)!= S_OK)
{
LogEvent (_T("Failed to copy SecondaryQueue reg value to ServiceParams->SecondaryQueue"));
Status = FALSE;
}
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// now get the primary response queue
if (RegQueryValueEx(hDbgLauncherKey,_T("PrimaryResponseQueue"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
LogEvent(_T("Failed to get Primary ResponseQueue value from registry."));
Status = FALSE;
}
else
{
if (StringCbCopy(ServiceParams->PrimaryResponseQueue,sizeof ServiceParams->PrimaryResponseQueue, (TCHAR *) Buffer) != S_OK)
{
LogEvent (_T("Failed to copy PrimaryResponseQueue reg value to ServiceParams->PrimaryResponseQueue"));
Status = FALSE;
}
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// now get the secondary response queue
if (RegQueryValueEx(hDbgLauncherKey,_T("SecondaryResponseQueue"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
LogEvent(_T("Failed to get Secondary ResponseQueue value from registry."));
Status = FALSE;
}
else
{
if (StringCbCopy(ServiceParams->SecondaryResponseQueue,sizeof ServiceParams->SecondaryResponseQueue, (TCHAR *) Buffer)!= S_OK)
{
LogEvent (_T("Failed to copy SecondaryResponseQueue reg value to ServiceParams->SecondaryResponseQueue"));
Status = FALSE;
}
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// Now get the ini release point
if (RegQueryValueEx(hDbgLauncherKey,_T("IniInstallLocation"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
LogEvent(_T("Failed to get IniInstallLocation Queue value from registry."));
Status = FALSE;
}
else
{
if (StringCbCopy(ServiceParams->IniInstallLocation,sizeof ServiceParams->IniInstallLocation, (TCHAR *) Buffer)!= S_OK)
{
LogEvent (_T("Failed to copy IniInstallLocation reg value to ServiceParams->IniInstallLocation"));
Status = FALSE;
}
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// Now get the Symbols server connection string
if (RegQueryValueEx(hDbgLauncherKey,_T("SymSrv"), 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
LogFatalEvent(_T("Failed to get the symbol server value from the registry."));
Status = FALSE;
}
else
{
if (StringCbCopy(ServiceParams->Symsrv,sizeof ServiceParams->Symsrv, (TCHAR *) Buffer) != S_OK)
{
LogEvent (_T("Failed to copy Symsrv reg value to ServiceParams->Symsrv"));
Status = FALSE;
}
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// Now get the Delay -- Min time between kd launches
if (RegQueryValueEx(hDbgLauncherKey,_T("Delay"), 0, &Type, Buffer, &BufferSize))
{
LogEvent(_T("Failed to get the min delay between dbg launches."));
}
else
{
ServiceParams->dwDelay = *((DWORD*)Buffer);
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// Now get the Primary Queue delay
if (RegQueryValueEx(hDbgLauncherKey,_T("PrimaryInterval"), 0, &Type, Buffer, &BufferSize))
{
LogFatalEvent(_T("Failed to get the Primary queue wait interval."));
Status = FALSE;
}
else
{
ServiceParams->dwPrimaryWait = *((DWORD*)Buffer);
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// Now get the Primary Queue delay
if (RegQueryValueEx(hDbgLauncherKey,_T("IniWaitTime"), 0, &Type, Buffer, &BufferSize))
{
LogFatalEvent(_T("Failed to get the triage.Ini wait interval."));
Status = FALSE;
}
else
{
ServiceParams->IniCheckWaitTime = *((DWORD*)Buffer);
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// Now get the Memory usage threshold
if (RegQueryValueEx(hDbgLauncherKey,_T("MaxKdProcesses"), 0, &Type, Buffer, &BufferSize))
{
LogFatalEvent(_T("Failed to get the Max Kd Processes setting."));
Status = FALSE;
}
else
{
ServiceParams->dwMaxKdProcesses = *((DWORD*)Buffer);
}
BufferSize = MAX_PATH +1;
ZeroMemory(Buffer, BufferSize);
// Now get the Memory usage threshold
if (RegQueryValueEx(hDbgLauncherKey,_T("MaxDumpSize"), 0, &Type, Buffer, &BufferSize))
{
LogEvent(_T("Failed to get the Max Dump Size setting."));
ServiceParams->dwMaxDumpSize = -1;
}
else
{
ServiceParams->dwMaxDumpSize = *((DWORD*)Buffer);
}
RegCloseKey(hHKLM);
RegCloseKey(hDbgLauncherKey);
return TRUE;
}
else
{
RegCloseKey(hHKLM);
return FALSE;
}
}
else
return FALSE;
}
DWORD
CServiceModule::CheckForIni (SVCPARAMS *ServiceParams)
{
FILETIME CreationTimeCurrent;
FILETIME CreationTimeNew;
TCHAR IniFileName[MAX_PATH];
TCHAR DebuggerPath[MAX_PATH];
TCHAR *Temp = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hFile2 = INVALID_HANDLE_VALUE;
ZeroMemory (&CreationTimeCurrent, sizeof FILETIME);
ZeroMemory (&CreationTimeNew, sizeof FILETIME);
if (_tcslen(ServiceParams->DebuggerName) + _tcslen(_T("\\winxp\\triage.ini")) < MAX_PATH)
{
if (StringCbCopy(DebuggerPath, sizeof DebuggerPath, ServiceParams->DebuggerName)!= S_OK)
{
LogEvent(_T("CheckForIni: Failed to build Debugger Path"));
}
Temp = DebuggerPath;
Temp += _tcslen(DebuggerPath);
if (Temp != DebuggerPath)
{
while(*Temp != _T('\\'))
{
-- Temp;
}
*(Temp+1) = _T('\0');
}
// Get the file path of the debugger remove the ocakd.exe string then add triage\\triage.ini
if (StringCbCat (DebuggerPath,sizeof DebuggerPath, _T("winxp\\triage.ini")) != S_OK)
{
LogEvent(_T("CheckForIni: Failed to build debugger path"));
}
// Check to see if we need a new triage.ini file.
// open a shared read handle to the existing ini file.
hFile = CreateFile(DebuggerPath,
GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
// Get the time date stamp of the existing triage ini file.
if ( GetFileTime(hFile,NULL,NULL,&CreationTimeCurrent) )
{
// Now get the filetime for the triage.ini replacement.
hFile2 = CreateFile(ServiceParams->IniInstallLocation,
GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile2 != INVALID_HANDLE_VALUE)
{
if (GetFileTime(hFile2, NULL,NULL,&CreationTimeNew))
{
// LogEvent (_T("Comparing the creation times"));
if ( CompareFileTime( &CreationTimeNew , &CreationTimeCurrent) == 1)
{
// copy the new file here.
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle (hFile);
if (hFile2 != INVALID_HANDLE_VALUE)
CloseHandle (hFile2);
if (CopyFile(ServiceParams->IniInstallLocation, DebuggerPath,FALSE) )
{
// LogEvent(_T("Successfully copied triage.ini from: %s to %s"),
// ServiceParams->IniInstallLocation, DebuggerPath);
;
}
else
{
// LogEvent(_T("Copy of file:%s to %s failed\n error code: %d"),ServiceParams->IniInstallLocation, DebuggerPath, GetLastError());
;
}
}
}
if (hFile2 != INVALID_HANDLE_VALUE)
CloseHandle (hFile2);
}
}
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle (hFile);
}
}
return 0;
}
HRESULT CServiceModule::ConnectToMSMQ(QUEUEHANDLE *hQueue, wchar_t *QueueConnectStr)
/*++
Routine Description:
This function is called when the WWW service is shutdown.
Arguments:
dwFlags - HSE_TERM_ADVISORY_UNLOAD or HSE_TERM_MUST_UNLOAD
Return Value:
TRUE when extension is ready to be unloaded,
--*/
{
HRESULT Hr = S_OK;
DWORD i;
i = 0;
Hr = MQOpenQueue(QueueConnectStr,
MQ_RECEIVE_ACCESS,
MQ_DENY_NONE,
hQueue);
return Hr;
}
BOOL CServiceModule::Initialize(PSVCPARAMS pParams)
{
HRESULT hr;
if (!GetServiceParams(pParams) )
{
LogFatalEvent(_T("Failed to read initialization data from the registry."));
return FALSE;
}
//ConnectToMSMQ
hr = ConnectToMSMQ(&(pParams->hPrimaryQueue),pParams->PrimaryQueue);
if (SUCCEEDED(hr))
{
LogEvent(_T("Connected to primary Queue"));
//pParams->PrimaryConnected = TRUE;
}
else
{
//pParams->PrimaryConnected = FALSE;
LogEvent(_T("Cannot connected to primary Queue %s, error %lx"), pParams->PrimaryQueue, hr);
}
hr = ConnectToMSMQ(&(pParams->hSecondaryQueue),pParams->SecondaryQueue);
if (SUCCEEDED(hr))
{
//pParams->PrimaryConnected = TRUE;
LogEvent(_T("Connected to secondary Queue"));
}
else
{
//pParams->PrimaryConnected = FALSE;
LogEvent(_T("Cannot connected to secondary Queue %s, error %lx"), pParams->SecondaryQueue, hr);
}
return TRUE;
}
BOOL CServiceModule::ReceiveQueueMessage(PSVCPARAMS pParams,
wchar_t *RecMessageBody,
wchar_t *szMessageGuid,
BOOL *bUsePrimary,
int *Type,
wchar_t *szSR)
{
MSGPROPID PropIds[5];
MQPROPVARIANT PropVariants[5];
HRESULT hrProps[5];
MQMSGPROPS MessageProps;
DWORD i = 0;
wchar_t RecLabel[100];
wchar_t LocalRecBody[MAX_PATH];
DWORD RecMessageBodySize = sizeof LocalRecBody;
DWORD RecLabelLength = sizeof RecLabel;
HRESULT hResult = 0;
BOOL Status = FALSE;
TCHAR *Temp = NULL;
ZeroMemory(LocalRecBody,sizeof LocalRecBody);
ZeroMemory(RecLabel,sizeof RecLabel);
i = 0;
PropIds[i] = PROPID_M_LABEL_LEN;
PropVariants[i].vt = VT_UI4;
PropVariants[i].ulVal = RecLabelLength;
i++;
PropIds[i] = PROPID_M_LABEL;
PropVariants[i].vt = VT_LPWSTR;
PropVariants[i].pwszVal = RecLabel;
i++;
MessageProps.aPropID = PropIds;
MessageProps.aPropVar = PropVariants;
MessageProps.aStatus = hrProps;
MessageProps.cProp = i;
// retrieve the current message
i = 0;
PropIds[i] = PROPID_M_LABEL_LEN;
PropVariants[i].vt = VT_UI4;
PropVariants[i].ulVal = RecLabelLength;
i++;
PropIds[i] = PROPID_M_LABEL;
PropVariants[i].vt = VT_LPWSTR;
PropVariants[i].pwszVal = RecLabel;
i++;
PropIds[i] = PROPID_M_BODY_SIZE;
PropVariants[i].vt = VT_UI4;
i++;
PropIds[i] = PROPID_M_BODY_TYPE;
PropVariants[i].vt = VT_UI4;
i++;
PropIds[i] = PROPID_M_BODY;
PropVariants[i].vt = VT_VECTOR|VT_UI1;
PropVariants[i].caub.pElems = (LPBYTE) LocalRecBody;
PropVariants[i].caub.cElems = RecMessageBodySize;
i++;
MessageProps.aPropID = PropIds;
MessageProps.aPropVar = PropVariants;
MessageProps.aStatus = hrProps;
MessageProps.cProp = i;
hResult = MQReceiveMessage( pParams->hPrimaryQueue,
0,
MQ_ACTION_RECEIVE,
&MessageProps,
NULL,
NULL,
NULL,
MQ_NO_TRANSACTION);
if (FAILED (hResult) )
{
if (hResult != (HRESULT) MQ_ERROR_IO_TIMEOUT)
{
if (hResult == (HRESULT) MQ_ERROR_QUEUE_NOT_AVAILABLE)
{
// Non Fatal Event
LogFatalEvent(_T("The %s MSMQ is unavailable."), pParams->PrimaryQueue );
}
else
{
if (hResult == (HRESULT) MQ_ERROR_INVALID_HANDLE)
{
// Close the current handle and attempt to reconnect to the MSMQ
MQCloseQueue( pParams->hPrimaryQueue );
ConnectToMSMQ(&(pParams->hPrimaryQueue), pParams->PrimaryQueue );
}
}
}
//g_ReadQueueFlag = !g_ReadQueueFlag;
hResult = MQReceiveMessage( pParams->hSecondaryQueue,
0,
MQ_ACTION_RECEIVE,
&MessageProps,
NULL,
NULL,
NULL,
MQ_NO_TRANSACTION);
if (FAILED(hResult) )
{
Status = FALSE;
if (hResult != (HRESULT)MQ_ERROR_IO_TIMEOUT)
{
if (hResult == (HRESULT)MQ_ERROR_QUEUE_NOT_AVAILABLE)
{
// Non Fatal Event
LogFatalEvent(_T("The %s MSMQ is unavailable."), pParams->SecondaryQueue);
}
else
{
if (hResult == (HRESULT)MQ_ERROR_INVALID_HANDLE)
{
// Close the current handle and attempt to reconnect to the MSMQ
MQCloseQueue(pParams->hSecondaryQueue);
ConnectToMSMQ(&(pParams->hSecondaryQueue), pParams->SecondaryQueue);
}
}
}
return Status;
}
//
// We have valid message from SecondaryQueue
//
}
else
{
//
// We have valid message from Primary Queue
//
}
//
// Copy the messge parameters
//
if (StringCbCopy(RecMessageBody,RecMessageBodySize, LocalRecBody) != S_OK)
{
LogEvent(_T("Failed to copy the recieved message body to RecMessageBody"));
}
if (StringCbCopy(szMessageGuid,RecLabelLength, RecLabel) != S_OK)
{
LogEvent(_T("Failed to copy the RecLabel into szMessageGuid."));
}
Status = TRUE;
*bUsePrimary = TRUE;
Temp = RecMessageBody;
while ( (*Temp != _T(';')) && (*Temp != _T('\0')))
{
++Temp;
}
if (*Temp != _T('\0'))
{
*Type = _wtoi (Temp+1);
// terminate the string here.
*Temp = _T('\0');
}
else
{
*Type = 1;
}
Temp = _tcsstr(LocalRecBody, _T(";SR="));
if (Temp != NULL)
{
// we got a SR number in message
Temp += 4;
StringCbCopy(szSR, 50, Temp);
} else
{
*szSR = _T('\0');
}
// Flip the read from queue flag for the next call
//g_ReadQueueFlag = !g_ReadQueueFlag;
return Status;
}
ULONG64
CServiceModule::GetFileSize(
LPWSTR wszFile
)
{
HANDLE hFile;
DWORD dwFileSize, dwFileSizeHi;
hFile = CreateFileW(wszFile, GENERIC_READ,
FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
{
dwFileSizeHi = 0;
dwFileSize=::GetFileSize(hFile,&dwFileSizeHi);
return (ULONG64) dwFileSize + ((ULONG64)dwFileSizeHi << 32);
}
return -1;
}
VOID
CServiceModule::NotifyDebuggerLaunch(
PDBADDCRASH_PARAMS pDbParams
)
{
HANDLE hPipe;
DWORD dwMode, cbWritten;
OCAKD_MONITOR_MESSAGE Msg;
OVERLAPPED WriteOverlapped;
Msg.MessageId = OKD_MESSAGE_DBGLAUNCH_NOTIFY;
Msg.u.DbglNotice.SizeOfStruct = sizeof(Msg.u.DbglNotice);
Msg.u.DbglNotice.Source = pDbParams->Source;
Msg.u.DbglNotice.nKdsRunning = m_DebuggerCount;
if (StringCbPrintfA(Msg.u.DbglNotice.CrashGuid, sizeof(Msg.u.DbglNotice.CrashGuid),
"%ws", pDbParams->Guid) != S_OK ||
StringCbPrintfA(Msg.u.DbglNotice.OriginalPath,sizeof(Msg.u.DbglNotice.OriginalPath),
"%ws", pDbParams->DumpPath) != S_OK)
{
return;
}
for (hPipe = m_hMonNotifyPipe;m_hMonNotifyPipe == NULL;)
{
hPipe = CreateFile(c_tszCollectPipeName, FILE_WRITE_DATA,
0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
m_hMonNotifyPipe = hPipe;
break;
}
if (GetLastError() != ERROR_PIPE_BUSY)
{
return;
}
// Do not wait long, this might block other processes
if (!WaitNamedPipe(c_tszCollectPipeName, 5*1000))
{
return;
}
}
// We are now connected to pipe
WriteOverlapped.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (WriteOverlapped.hEvent != NULL)
{
// Send crash information to monitor pipe
if (!WriteFile(hPipe, (LPVOID) &Msg, sizeof(Msg),
&cbWritten, &WriteOverlapped))
{
if (GetLastError() == ERROR_NO_DATA ||
GetLastError() == ERROR_BAD_PIPE)
{
// Open a different pipe next time
CloseHandle(hPipe);
m_hMonNotifyPipe = NULL;
} else if (GetLastError() == ERROR_IO_PENDING ||
!GetOverlappedResult(hPipe, &WriteOverlapped, &cbWritten,
TRUE))
{
// failed to write, exit silently
// Its up to monitor if it is keeping track of kds launched
} else
{
// Open a different pipe next time
CloseHandle(hPipe);
m_hMonNotifyPipe = NULL;
}
}
CloseHandle(WriteOverlapped.hEvent);
}
FlushFileBuffers(hPipe);
return;
}
BOOL CServiceModule::LaunchDebugger(
PDBADDCRASH_PARAMS pDbParams,
PPROCESS_INFORMATION pDbgProcess
)
{
STARTUPINFO StartupInfo;
wchar_t CommandLine [1024];
wchar_t SrParam[100];
HRESULT hr;
ZeroMemory(&StartupInfo,sizeof(STARTUPINFO));
StartupInfo.cb = sizeof(STARTUPINFO);
if ((pDbParams->dwMaxDumpSize != 0) && (pDbParams->dwMaxDumpSize != -1) &&
(GetFileSize(pDbParams->DumpPath) > pDbParams->dwMaxDumpSize))
{
LogEvent(_T("Dump %s is too large, deleting file\n"), pDbParams->DumpPath);
DeleteFileW(pDbParams->DumpPath);
return FALSE;
}
if (pDbParams->SrNumber[0])
{
hr = StringCbPrintf(SrParam, sizeof(SrParam), _T(" -sr %s"), pDbParams->SrNumber);
if (hr != S_OK)
{
LogEvent(_T("Bad SR %s: %lx"), pDbParams->SrNumber, hr);
return FALSE;
}
} else
{
SrParam[0] = _T('\0');
}
if ((hr = StringCbPrintf(CommandLine,sizeof CommandLine,
_T("%s -i %s -y %s -z \"%s\" -c \"!dbaddcrash -source %d -g %s -s %s -p %s%s;q\""),
pDbParams->Debugger,
pDbParams->SymPath,
pDbParams->SymPath,
pDbParams->DumpPath,
pDbParams->Source,
pDbParams->Guid,
pDbParams->ResponseMQ,
pDbParams->DumpPath,
SrParam)) != S_OK)
{
LogEvent(_T("Failed to build command line: %lx"), hr);
}
//LogEvent(_T("CommandLine Guid=%s queue=%d"),szMessageLabel,bUsePrimary);
//LogEvent(_T("CommandLine Path=%s"),szFilePath);
//LogEvent(_T("CommandLine: %s"),CommandLine);
if (!CreateProcess(NULL,
CommandLine,
NULL,
NULL,
FALSE,
//CREATE_NEW_CONSOLE,
CREATE_NO_WINDOW,
NULL,
NULL,
&StartupInfo,
pDbgProcess))
{
hr = GetLastError();
LogEvent(_T("Failed to launch debugger. Commandline %s, error %lx\n"), CommandLine, hr);
return FALSE;
}
//
// Notify Site monitor of debugger launch
//
NotifyDebuggerLaunch(pDbParams);
return TRUE;
}
BOOL CServiceModule::PrepareForDebuggerLaunch()
{
HANDLE ProcessHandles[50];
PROCESS_INFORMATION ProcessInfo;
wchar_t szFilePath[MAX_PATH];
wchar_t szSR[100];
HRESULT hr = 0;
HANDLE hStopEvent = INVALID_HANDLE_VALUE;
SVCPARAMS ServiceParams;
DWORD dwIndex = 0;
DWORD FreeIndex = 0;
DWORD dwWaitResult = 0;
BOOL Done = FALSE;
__time64_t CurrentTime = 0;
__time64_t NextCheckTime = 0;
wchar_t szMessageLabel[255];
BOOL bUsePrimary = FALSE;
int Type = 1;
DBADDCRASH_PARAMS DbParams;
ZeroMemory (ProcessHandles,sizeof ProcessHandles);
ZeroMemory(&ServiceParams,sizeof SVCPARAMS);
ZeroMemory (szMessageLabel, sizeof szMessageLabel);
ZeroMemory (szFilePath, sizeof szFilePath);
ZeroMemory(&DbParams, sizeof(DbParams));
m_DebuggerCount = 0;
hStopEvent = OpenEvent(
EVENT_ALL_ACCESS,
FALSE,
s_cszStopEvent
);
if (hStopEvent == NULL)
{
LogFatalEvent(_T("Failed to open stop event. Terminating"));
goto Done;
}
// get reg data
// Insert the stop event into the ocakd queue
++ m_DebuggerCount;
ProcessHandles[m_DebuggerCount -1] = hStopEvent;
if (!Initialize(&ServiceParams))
{
goto Done;
}
// fill the ocakd queue
Done = FALSE;
while ( (m_DebuggerCount <= ServiceParams.dwMaxKdProcesses+1 ) && (!Done))
{
if (!ReceiveQueueMessage(&ServiceParams, szFilePath, szMessageLabel, &bUsePrimary, &Type, szSR))
{
Done = TRUE;
}
else
{
DbParams.Debugger = ServiceParams.DebuggerName;
DbParams.DumpPath = szFilePath;
DbParams.Guid = szMessageLabel;
DbParams.SrNumber = szSR;
DbParams.ResponseMQ = (bUsePrimary) ?
ServiceParams.PrimaryResponseQueue : ServiceParams.SecondaryResponseQueue;
DbParams.SymPath = ServiceParams.Symsrv;
DbParams.Source = Type;
DbParams.dwMaxDumpSize = ServiceParams.dwMaxDumpSize;
if (LaunchDebugger(&DbParams, &ProcessInfo))
{
// LogEvent(_T("Launched: %s for file: %s with guid:%s and source: %d with return queue =%s"),
// ServiceParams.DebuggerName,szFilePath, szMessageLabel, Type, (bUsePrimary) ? ServiceParams.PrimaryResponseQueue : ServiceParams.SecondaryResponseQueue);
++ m_DebuggerCount;
ProcessHandles[m_DebuggerCount -1] = ProcessInfo.hProcess;
CloseHandle( ProcessInfo.hThread );
} // end else
}// end else
} // end while
if (m_DebuggerCount > ServiceParams.dwMaxKdProcesses+1)
m_DebuggerCount = ServiceParams.dwMaxKdProcesses+1;
while (1)
{
_time64(&CurrentTime);
if (CurrentTime > NextCheckTime)
{
// LogEvent (_T("Checking for new ini file"));
CheckForIni (&ServiceParams);
NextCheckTime= CurrentTime + (ServiceParams.IniCheckWaitTime * 60);
// LogEvent (_T("Back from ini file check"));
}
// now wait for one of the processes to complete or hStopEvent to be signaled.
dwWaitResult = WaitForMultipleObjects(m_DebuggerCount, (HANDLE *)ProcessHandles, FALSE, ServiceParams.dwDelay);
if (dwWaitResult == WAIT_FAILED)
{
LogFatalEvent(_T("Failed while waiting for prcesses to complete error code: %d"), GetLastError());
goto Cleanup;
}
else
{
if (dwWaitResult-WAIT_OBJECT_0 == 0)
{
LogEvent(_T("Stop request received terminating"));
goto Cleanup;
}
else // we have an event we can take action on.
{
if ( dwWaitResult == WAIT_TIMEOUT)
{
// no process completed so let's fill any empty slots in the
// Process array.
if (m_DebuggerCount <= ServiceParams.dwMaxKdProcesses)
{
// fill the queue until m_DebuggerCount == ServiceParams.dwMaxKdProcesses
Done = FALSE;
dwIndex = 1;
while ( (!Done) && (m_DebuggerCount <= ServiceParams.dwMaxKdProcesses) )
{
if (ProcessHandles[dwIndex] == NULL)
{
if (ReceiveQueueMessage(&ServiceParams, szFilePath, szMessageLabel,&bUsePrimary,&Type,szSR))
{
DbParams.Debugger = ServiceParams.DebuggerName;
DbParams.DumpPath = szFilePath;
DbParams.Guid = szMessageLabel;
DbParams.SrNumber = szSR;
DbParams.ResponseMQ = (bUsePrimary) ?
ServiceParams.PrimaryResponseQueue : ServiceParams.SecondaryResponseQueue;
DbParams.SymPath = ServiceParams.Symsrv;
DbParams.Source = Type;
DbParams.dwMaxDumpSize = ServiceParams.dwMaxDumpSize;
if (LaunchDebugger(&DbParams, &ProcessInfo))
{
ProcessHandles[dwIndex] = ProcessInfo.hProcess;
CloseHandle( ProcessInfo.hThread );
++m_DebuggerCount;
} // end else
}
else
{
Done = TRUE;
}
} // end if
++dwIndex;
} // end while
}
} // end if
else // A kd process completed now lets clean it up and launch a new one.
{
FreeIndex = (dwWaitResult - WAIT_OBJECT_0);
// check to make sure we are within our array range.
if ( (FreeIndex > ServiceParams.dwMaxKdProcesses))
{
LogFatalEvent( _T("Invalid array index returned by WaitForMultipleObjects. \n Index = %d, Count = %d"), FreeIndex,m_DebuggerCount);
}
else
{
CloseHandle(ProcessHandles[FreeIndex]);
ProcessHandles[FreeIndex] = NULL;
// if the queue is not now empty take the last Process handle and replace the current one.
if (m_DebuggerCount > 2)
{
// We have to do this because NULLs are not allowed in the HANDLE Array.
ProcessHandles[FreeIndex] = ProcessHandles[m_DebuggerCount-1];
ProcessHandles[m_DebuggerCount-1] = NULL;
-- m_DebuggerCount;
}
else
{
--m_DebuggerCount;
}
if (ReceiveQueueMessage(&ServiceParams, szFilePath, szMessageLabel,&bUsePrimary, &Type, szSR))
{
DbParams.Debugger = ServiceParams.DebuggerName;
DbParams.DumpPath = szFilePath;
DbParams.Guid = szMessageLabel;
DbParams.SrNumber = szSR;
DbParams.ResponseMQ = (bUsePrimary) ?
ServiceParams.PrimaryResponseQueue : ServiceParams.SecondaryResponseQueue;
DbParams.SymPath = ServiceParams.Symsrv;
DbParams.Source = Type;
DbParams.dwMaxDumpSize = ServiceParams.dwMaxDumpSize;
if (LaunchDebugger(&DbParams, &ProcessInfo))
{
++m_DebuggerCount;
ProcessHandles[m_DebuggerCount-1] = ProcessInfo.hProcess;
CloseHandle( ProcessInfo.hThread );
} // end else
} // end if
} // end else
} // end else
} // end else
} // end else
}// end while(1)
Cleanup:
//
// Cleanup - Close handle to the queue
//
Done:
// set the service status to stopped and return.
if (hStopEvent != INVALID_HANDLE_VALUE)
CloseHandle(hStopEvent);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////
// Routine to Log Fatal Errors to NT Event Log
void CServiceModule::LogFatalEvent(LPCTSTR pFormat, ...)
{
TCHAR chMsg[256];
HANDLE hEventSource;
LPTSTR lpszStrings[1];
va_list pArg;
va_start(pArg, pFormat);
// _vstprintf(chMsg, pFormat, pArg);
if (StringCbVPrintf(chMsg,sizeof chMsg, pFormat, pArg)!= S_OK)
{
return;
}
va_end(pArg);
lpszStrings[0] = chMsg;
/* Get a handle to use with ReportEvent(). */
hEventSource = RegisterEventSource(NULL, _T("DBGLauncher"));
if (hEventSource != NULL)
{
/* Write to event log. */
ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, EVENT_ERROR, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
DeregisterEventSource(hEventSource);
}
}
///////////////////////////////////////////////////////////////////////////////////////
// Routine to setup NT Event logging
HRESULT CServiceModule::SetupEventLog ( BOOL fSetup )
{
CRegKey key;
TCHAR szEventKey[MAX_PATH];
LONG lRes = 0;
if (StringCbCopy(szEventKey, sizeof szEventKey,s_cszEventLogKey)!= S_OK)
{
return E_FAIL;
}
if (StringCbCat(szEventKey,sizeof szEventKey, _T("\\")) != S_OK)
return E_FAIL;
if (StringCbCat(szEventKey, sizeof szEventKey,(LPTSTR)m_szServiceName) != S_OK)
return E_FAIL;
lRes = key.Create(HKEY_LOCAL_MACHINE, szEventKey);
if (lRes != ERROR_SUCCESS)
{
goto done;
}
if( TRUE == fSetup )
{
TCHAR szMyName[MAX_PATH];
GetModuleFileName(NULL, szMyName, (sizeof szMyName)/(sizeof szMyName[0]) );
key.SetValue(szMyName, _T("EventMessageFile"));
key.SetValue(EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE,
_T("TypesSupported"));
}
else
{
RegDeleteKey(HKEY_LOCAL_MACHINE, szEventKey);
}
done:
key.Close();
return HRESULT_FROM_WIN32(GetLastError());
}