|
|
#include "stdafx.h"
#include "svcobjdef.h"
#include "dbghelp.h"
#include "Processes.h"
#include "Notify.h"
#include "resource.h"
CEMSessionThread::CEMSessionThread ( IN PEmObject pEmObj ) {
ATLTRACE(_T("CEMSessionThread::CEMSessionThread\n"));
m_pEmSessObj = pEmObj; eDBGSessType = SessType_Automatic;
m_pDBGClient = NULL; m_pDBGControl = NULL; m_pDBGSymbols = NULL;
m_pASTManager = &(_Module.m_SessionManager);
m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
m_hCDBStarted = CreateEvent ( NULL, FALSE, FALSE, NULL );
//// - InitAutomaticSession..
m_bRecursive = FALSE; m_bstrEcxFilePath = NULL; m_bstrNotificationString = NULL; m_bstrAltSymPath = NULL; m_bGenerateMiniDump = FALSE; m_bGenerateUserDump = FALSE;
//// - InitManualSession..
m_bstrUserName = NULL; m_bstrPassword = NULL; m_nPort = 0; m_bBlockIncomingIPConnections = FALSE;
m_bContinueSession = TRUE; m_pEcxFile = NULL;
ZeroMemory(&m_sp, sizeof(m_sp)); ZeroMemory(&m_pi, sizeof(m_pi)); };
CEMSessionThread::~CEMSessionThread(){
ATLTRACE(_T("CEMSessionThread::~CEMSessionThread\n"));
if(m_bstrUserName) SysFreeString(m_bstrUserName); if(m_bstrPassword) SysFreeString(m_bstrPassword);
if(m_pDBGClient) m_pDBGClient->Release(); if(m_pDBGControl) m_pDBGControl->Release(); if(m_pDBGSymbols) m_pDBGSymbols->Release();
if(m_bstrEcxFilePath) ::SysFreeString(m_bstrEcxFilePath); if(m_bstrNotificationString) ::SysFreeString(m_bstrNotificationString ); if(m_bstrAltSymPath) ::SysFreeString(m_bstrAltSymPath);
CloseHandle( m_hEvent ); CloseHandle( m_hCDBStarted ); };
DWORD CEMSessionThread::Run ( void ) { ATLTRACE(_T("CEMSessionThread::Run\n"));
TCHAR szConnectString[_MAX_PATH] = _T(""); char *szClientConnectString = NULL; DWORD dwLastRet = -1L; HRESULT hr = E_FAIL, hrActual = E_FAIL; EmSessionStatus nStatus = STAT_SESS_NONE_STAT_NONE; UINT nPid = 0; EmObject EmObj; PEMSession pEmSess = NULL;
do { do {
if( m_pEmSessObj->type == EMOBJ_SERVICE ) {
if( (m_pEmSessObj->nStatus == STAT_SESS_NOT_STARTED_NOTRUNNING) || (m_pEmSessObj->nStatus & STAT_SESS_STOPPED) ) {
hr = S_OK;
do {
dwLastRet = StartServiceAndGetPid( m_pEmSessObj->szSecName, &nPid );
if( dwLastRet != ERROR_SERVICE_ALREADY_RUNNING ) {
hr = HRESULT_FROM_WIN32(dwLastRet); break; }
} while ( false );
FAILEDHR_BREAK(hr);
hr = m_pASTManager->GetSession( m_pEmSessObj->guidstream, &pEmSess ); FAILEDHR_BREAK(hr);
memcpy((void *)&EmObj, (void *) pEmSess->pEmObj, sizeof EmObject); EmObj.nStatus = STAT_SESS_NOT_STARTED_RUNNING; EmObj.nId = nPid; EmObj.hr = S_OK;
hr = m_pASTManager->UpdateSessObject( EmObj.guidstream, &EmObj ); FAILEDHR_BREAK(hr); } }
//
// Get server connection string and start CDB server
// Ex: -server tcp:port=XXX -p YYY
// -server npipe:pipe=EM_YYY -p YYY
//
hr = GetServerConnectString( szConnectString, _MAX_PATH ); if( FAILED(hr) ) {
hrActual = hr; nStatus = STAT_SESS_STOPPED_FAILED; break; }
hr = StartCDBServer( szConnectString );
// Indicates that the CDB server got started or failed..
SetEvent(m_hCDBStarted);
if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_CDBSERVERSTARTFAILED; nStatus = STAT_SESS_STOPPED_FAILED; break; }
#ifdef _DEBUG
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_DEBUG_IN_PROGRESS_NONE, S_OK, L"StartCDBServer Successful" ); #else
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_DEBUG_IN_PROGRESS_NONE, S_OK, NULL ); #endif
//
// Get client connection string and start monitoring
// Ex: -remote tcp:server=ABCD,port=XXX
// -remote npipe:server=ABCD,pipe=EM_YYY
//
hr = GetClientConnectString( szConnectString, _MAX_PATH ); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_CDBSERVERSTARTFAILED; nStatus = STAT_SESS_STOPPED_FAILED; break; }
size_t Len = wcstombs( NULL, szConnectString, 0 ); szClientConnectString = (char *)calloc(Len+1, sizeof(char)); _ASSERTE( szClientConnectString != NULL );
if( szClientConnectString == NULL ) { hr = HRESULT_FROM_WIN32( GetLastError() );
hrActual = hr; hr = EMERROR_CDBSERVERSTARTFAILED; nStatus = STAT_SESS_STOPPED_FAILED; break; }
wcstombs( szClientConnectString, szConnectString, Len );
if( eDBGSessType == SessType_Automatic ){
StartAutomaticExcepMonitoring( szClientConnectString ); } else{
//
// Need info..
//
StartAutomaticExcepMonitoring( szClientConnectString ); // StartManualExcepMonitoring( szClientConnectString );
}
hr = S_OK; } while ( m_bRecursive && m_bContinueSession ); // Need to put in a way of stopping the session.
} while( false );
if(FAILED(hr)) {
#ifdef _DEBUG
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_FAILED, hrActual, L"CEMSessionThread::Run - Failed", true, true ); #else
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_FAILED, hrActual, NULL, true, true ); #endif
StopServer(); }
if( szClientConnectString != NULL ){ free(szClientConnectString); }
return hr; }
HRESULT CEMSessionThread::StartAutomaticExcepMonitoring( char *pszConnectString ) { ATLTRACE(_T("CEMSessionThread::StartAutomaticExcepMonitoring\n"));
HRESULT hr = E_FAIL, hrActual = E_FAIL;
TCHAR szUniqueFileName[_MAX_PATH+1] = _T(""); char szLogFile[_MAX_PATH+1] = ""; TCHAR szLogDir[_MAX_PATH+1] = _T("");
char szEcxFile[_MAX_PATH+1] = ""; TCHAR szEcxDir[_MAX_PATH+1] = _T("");
bool bStop = FALSE; char szCmd[_MAX_PATH+1] = ""; TCHAR szFileExt[_MAX_EXT+1] = _T(""); DWORD dwBufSize = _MAX_PATH; char szAltSymPath[_MAX_PATH+1] = ""; EmSessionStatus nStatus = STAT_SESS_NONE_STAT_NONE; bstr_t bstrStatus;
do { _ASSERTE(m_bstrEcxFilePath != NULL); _Module.GetEmDirectory( EMOBJ_CMDSET, szEcxDir, dwBufSize, NULL, NULL ); _stprintf(szEcxDir, _T("%s\\%s"), szEcxDir, m_bstrEcxFilePath); wcstombs( szEcxFile, szEcxDir, dwBufSize );
dwBufSize = _MAX_PATH; _Module.GetEmDirectory( EMOBJ_LOGFILE, szLogDir, dwBufSize, szFileExt, _MAX_EXT ); CreateDirectory( szLogDir, NULL );
GetUniqueFileName( m_pEmSessObj, szUniqueFileName, _T(""), szFileExt, false );
_stprintf(szLogDir, _T("%s\\%s"), szLogDir, szUniqueFileName); wcstombs( szLogFile, szLogDir, dwBufSize );
hr = DebugConnect( pszConnectString, IID_IDebugClient, (void **)&m_pDBGClient ); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_CONNECTIONTOSERVERFAILED; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"DebugConnect failed"; break; }
#ifdef _DEBUG
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_DEBUG_IN_PROGRESS_NONE, hr, L"DebugConnect Succeeded.." ); #else
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_DEBUG_IN_PROGRESS_NONE, hr, NULL ); #endif
hr = m_pDBGClient->QueryInterface( IID_IDebugControl, (void **)&m_pDBGControl ); if( FAILED(hr) ) {
nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"IDbgClient::QIFace ( IDbgControl ) failed"; break; }
hr = m_pDBGClient->QueryInterface( IID_IDebugSymbols, (void **)&m_pDBGSymbols ); if( FAILED(hr) ) {
nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"IDbgClient::QIFace ( IDebugSymbols ) failed"; break; }
wcstombs( szAltSymPath, m_bstrAltSymPath, dwBufSize ); if( strcmp( szAltSymPath, "" ) != 0 ) {
hr = m_pDBGSymbols->SetSymbolPath(szAltSymPath); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_ALTSYMPATHFAILED; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"Alternate symbol path could not be set"; break; } }
if( eDBGSessType == SessType_Automatic ) {
hr = m_pDBGControl->OpenLogFile(szLogFile, FALSE); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_UNABLETOCREATELOGFILE; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"Open log file failed"; break; } }
/*
hr = m_pDBGControl->ExecuteCommandFile( DEBUG_OUTCTL_LOG_ONLY, szEcxFile, DEBUG_EXECUTE_DEFAULT ); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_ECXFILEEXECUTIONFAILED; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"ExecCommandFile failed"; break; } */ m_EventCallbacks.m_pEMThread = this; hr = m_pDBGClient->SetEventCallbacks(&m_EventCallbacks); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_CALLBACKSCANNOTBEREGISTERED; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"SetEventCallback failed"; break; }
ULONG ExecStatus = DEBUG_STATUS_BREAK;
if( _tcscmp( m_bstrEcxFilePath, _T("") ) != 0 ) {
m_pEcxFile = fopen(szEcxFile, "r"); if( m_pEcxFile == NULL ) {
hr = HRESULT_FROM_WIN32(GetLastError()); hrActual = hr; hr = EMERROR_ECXFILEOPENFAILED; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"fopen failed"; break; }
hr = ExecuteCommandsTillGo(NULL); }
do {
hr = KeepDebuggeeRunning(); if( FAILED(hr) ) {
nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"KeepDebugeeRunning failed"; break; }
hr = CanContinue(); if( FAILED(hr) ) {
nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"Can Continue() failed"; break; }
hr = m_pDBGClient->DispatchCallbacks(INFINITE); // Milli Secs..
if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_DISPATCHCALLBACKFAILED; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"DispatchCallbacks failed"; break; }
//
// Is this call required???
//
hr = CanContinue(); if( hr != S_OK ) { bstrStatus = L"CanContinue hr != S_OK"; break; }
hr = BreakIn(); if( FAILED(hr) ) { bstrStatus = L"BreakIn";
nStatus = STAT_SESS_STOPPED_FAILED; break; }
if( strcmp( szEcxFile, "" ) != 0 ) { ExecuteCommandsTillGo(NULL); }
if( eDBGServie == DBGService_HandleException ) { break; }
dwBufSize = _MAX_PATH; hr = GetCmd( eDBGServie, szCmd, dwBufSize ); if( FAILED(hr) ) {
nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"GetCmd failed"; break; } /*
hr = BreakIn(); if( FAILED(hr) ) { bstrStatus = L"BreakIn";
nStatus = STAT_SESS_STOPPED_FAILED; break; }
*/ if( strcmp( szCmd, "q" ) == 0 ){
if( eDBGSessType == SessType_Automatic ) {
hr = m_pDBGControl->CloseLogFile();
if( FAILED(hr) ) { bstrStatus = L"CloseLogFile"; nStatus = STAT_SESS_STOPPED_FAILED; break; } }
hr = m_pDBGControl->Execute( DEBUG_OUTCTL_ALL_CLIENTS, szCmd, DEBUG_EXECUTE_DEFAULT );
// hr = m_pDBGControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
// hr = m_pDBGClient->EndSession(DEBUG_END_ACTIVE_TERMINATE);
SetEvent( m_hEvent );
break; }
if( strcmp( szCmd, "qd" ) == 0 ) {
if( eDBGSessType == SessType_Automatic ) {
hr = m_pDBGControl->CloseLogFile();
if( FAILED(hr) ) {
bstrStatus = L"CloseLogFile"; nStatus = STAT_SESS_STOPPED_FAILED; break; } }
hr = m_pDBGControl->Execute( DEBUG_OUTCTL_ALL_CLIENTS, szCmd, DEBUG_EXECUTE_DEFAULT ); /*
hr = m_pDBGClient->DetachProcesses(); */
SetEvent( m_hEvent );
break; }
hr = m_pDBGControl->Execute( DEBUG_OUTCTL_ALL_CLIENTS, szCmd, DEBUG_EXECUTE_DEFAULT ); if( FAILED(hr) ) {
bstrStatus = L"DbgControl::Execute failed"; nStatus = STAT_SESS_STOPPED_FAILED; break; }
Sleep(2000);
hr = m_pDBGControl->GetExecutionStatus(&ExecStatus); if( FAILED(hr) ) {
bstrStatus = L"GetExecutionStatus"; nStatus = STAT_SESS_STOPPED_FAILED; break; } } // Will have to terminate if either no deubuggee or
// stop is requested..
while( CanContinue() == S_OK );
hr = m_pDBGControl->GetExecutionStatus(&ExecStatus); if( FAILED(hr) ) { bstrStatus = L"DbgControl::GetExecutionStatus failed"; nStatus = STAT_SESS_STOPPED_FAILED; break; }
if(ExecStatus != DEBUG_STATUS_NO_DEBUGGEE) { if( eDBGSessType == SessType_Automatic ) {
m_pDBGControl->CloseLogFile(); }
m_pDBGClient->EndSession(DEBUG_END_PASSIVE); } } while(FALSE);
if(FAILED(hr)) {
#ifdef _DEBUG
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_FAILED, hr, bstrStatus, true, true ); #else
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_FAILED, hr, NULL, true, true ); #endif
}
//
// When we are here, the debug session is guarenteed to be stopped.
//
{ EmObject EmObj; EmObj.dateEnd = CServiceModule::GetCurrentTime(); m_pASTManager->UpdateSessObject( m_pEmSessObj->guidstream, EMOBJ_FLD_DATEEND, &EmObj ); }
if( m_pEcxFile ) { fclose( m_pEcxFile ); m_pEcxFile = NULL; }
StopServer();
return hr; }
HRESULT CEMSessionThread::StartManualExcepMonitoring( char *pszConnectString ) { ATLTRACE(_T("CEMSessionThread::StartManualExcepMonitoring\n"));
HRESULT hr = E_FAIL, hrActual = E_FAIL; char szLogFile[_MAX_PATH+1] = ""; TCHAR szLogDir[_MAX_PATH+1] = _T("");
char szEcxFile[_MAX_PATH+1] = ""; TCHAR szEcxDir[_MAX_PATH+1] = _T("");
bool bStop = FALSE; char szCmd[_MAX_PATH+1] = ""; DWORD dwBufSize = _MAX_PATH; EmSessionStatus nStatus = STAT_SESS_NONE_STAT_NONE; bstr_t bstrStatus;
do { _ASSERTE(m_bstrEcxFilePath != NULL); _Module.GetEmDirectory( EMOBJ_CMDSET, szEcxDir, dwBufSize, NULL, NULL ); _stprintf(szEcxDir, _T("%s\\%s"), szEcxDir, m_bstrEcxFilePath); wcstombs( szEcxFile, szEcxDir, dwBufSize );
dwBufSize = _MAX_PATH; _Module.GetEmDirectory( EMOBJ_LOGFILE, szLogDir, dwBufSize, NULL, NULL ); _stprintf(szLogDir, _T("%s\\%s"), szLogDir, _T("EmLog.Dbl")); wcstombs( szLogFile, szLogDir, dwBufSize );
hr = DebugConnect( pszConnectString, IID_IDebugClient, (void **)&m_pDBGClient ); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_CONNECTIONTOSERVERFAILED; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"DebugConnect failed"; break; }
#ifdef _DEBUG
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_DEBUG_IN_PROGRESS_NONE, hr, L"DebugConnect Succeeded.." ); #else
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_DEBUG_IN_PROGRESS_NONE, hr, NULL ); #endif
hr = m_pDBGClient->QueryInterface( IID_IDebugControl, (void **)&m_pDBGControl ); if( FAILED(hr) ) {
nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"IDbgClient::QIFace ( IDbgControl ) failed"; break; }
hr = m_pDBGControl->OpenLogFile(szLogFile, FALSE); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_UNABLETOCREATELOGFILE; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"Open log file failed"; break; }
hr = m_pDBGControl->ExecuteCommandFile( DEBUG_OUTCTL_LOG_ONLY, szEcxFile, DEBUG_EXECUTE_DEFAULT ); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_ECXFILEEXECUTIONFAILED; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"ExecCommandFile failed"; break; }
m_EventCallbacks.m_pEMThread = this; hr = m_pDBGClient->SetEventCallbacks(&m_EventCallbacks); if( FAILED(hr) ) {
hrActual = hr; hr = EMERROR_CALLBACKSCANNOTBEREGISTERED; nStatus = STAT_SESS_STOPPED_FAILED; bstrStatus = L"SetEventCallback failed"; break; }
ULONG ExecStatus = DEBUG_STATUS_BREAK;
// m_pDBGClient->ConnectSession(DEBUG_CONNECT_SESSION_DEFAULT);
while( true ) {
hr = m_pDBGClient->DispatchCallbacks(INFINITE); // Milli Secs..
FAILEDHR_BREAK(hr); //DispatchCallbacks return S_FALSE if timeout expires
}
hr = S_OK;
} while(FALSE);
#ifdef _DEBUG
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_SUCCESS, hr, bstrStatus ); #else
m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_SUCCESS, hr, NULL ); #endif
return hr; }
HRESULT CEMSessionThread::StartCDBServer ( IN LPTSTR lpszConnectString ) {
ATLTRACE(_T("CEMSessionThread::StartCDBServer\n"));
TCHAR szCdbDir[_MAX_PATH+1] = _T(""); ULONG ccCdbDir = _MAX_PATH; HRESULT hr = E_FAIL;
ccCdbDir = _MAX_DIR; hr = _Module.GetCDBInstallDir( szCdbDir, &ccCdbDir ); if( FAILED(hr) ) return hr;
_tcsncat( szCdbDir, _T("\\cdb.exe"), _MAX_DIR );
BOOL bCdbCreated = CreateProcess(// This has to be obtained from the registry...
szCdbDir, lpszConnectString, NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, NULL, NULL, &m_sp, &m_pi );
if(bCdbCreated == FALSE){ return HRESULT_FROM_WIN32(GetLastError()); }
//
// Wait till CDB does some initializations..
// Don't know how long to wait.. have to figure out a way..
//
Sleep(2000);
return S_OK; }
HRESULT CEMSessionThread::GetClientConnectString ( IN OUT LPTSTR pszConnectString, IN DWORD dwBuffSize ) { ATLTRACE(_T("CEMSessionThread::GetClientConnectString\n"));
_ASSERTE(pszConnectString != NULL); _ASSERTE(dwBuffSize > 0L);
HRESULT hr = E_FAIL; DWORD dwBuff = MAX_COMPUTERNAME_LENGTH;
TCHAR szCompName[MAX_COMPUTERNAME_LENGTH + 1];
do { if( pszConnectString == NULL || dwBuffSize <= 0L ) break;
if(GetComputerName(szCompName, &dwBuff) == FALSE){ HRESULT_FROM_WIN32(GetLastError()); break; }
if( m_nPort != 0 ){ _stprintf(pszConnectString, _T("tcp:server=%s,port=%d"), szCompName, m_nPort); } else { _stprintf(pszConnectString, _T("npipe:server=%s,pipe=EM_%d"), szCompName, m_pEmSessObj->nId); }
hr = S_OK; } while( false );
return hr; }
HRESULT CEMSessionThread::GetServerConnectString ( IN OUT LPTSTR lpszConnectString, IN DWORD dwBuffSize ) { ATLTRACE(_T("CEMSessionThread::GetServerConnectString\n"));
_ASSERTE(lpszConnectString != NULL); _ASSERTE(dwBuffSize > 0L);
HRESULT hr = E_FAIL;
do { if( lpszConnectString == NULL || dwBuffSize <= 0L ) break;
if( m_nPort != 0 ){ _stprintf(lpszConnectString, _T(" -server tcp:port=%d -p %d"), m_nPort, m_pEmSessObj->nId); } else { _stprintf(lpszConnectString, _T(" -server npipe:pipe=EM_%d -p %d"), m_pEmSessObj->nId, m_pEmSessObj->nId); }
hr = S_OK; } while( false );
return hr; }
typedef BOOL (WINAPI*PFNWR)( IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile, IN MINIDUMP_TYPE DumpType, IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL );
HRESULT CEMSessionThread::CreateDumpFile( BOOL bMiniDump ) { ATLTRACE(_T("CEMSessionThread::CreateDumpFile\n"));
HRESULT hr = E_FAIL; HANDLE hDumpFile = INVALID_HANDLE_VALUE, hProcess = NULL; HMODULE hDbgHelp = NULL; LONG lStatus = 0L;
TCHAR szDumpFile[_MAX_PATH + 1] = _T(""); // a-kjaw, bug ID: 296024/25
DWORD dwBufSize = _MAX_PATH; TCHAR szCmd[_MAX_PATH + 1] = _T(""); // a-kjaw, bug ID: 296026
DWORD dwLastErr = 0L; TCHAR szFileExt[_MAX_EXT + 1] = _T(""); LPCTSTR lpszDbgHelpDll = _T("\\dbghelp.dll"), lpszUserDumpExe = _T("\\userdump.exe");
do {
hr = m_pASTManager->GetSessionStatus( m_pEmSessObj->guidstream, &lStatus ); FAILEDHR_BREAK(hr);
//
// We cannot generate dump files if the debuggee has stopped..
//
if( lStatus & STAT_SESS_STOPPED ) {
hr = EMERROR_INVALIDPROCESS; break; }
if( bMiniDump ){
_Module.GetEmDirectory( EMOBJ_MINIDUMP, szCmd, dwBufSize, szFileExt, _MAX_EXT ); CreateDirectory( szCmd, NULL );
GetUniqueFileName ( m_pEmSessObj, szDumpFile, _T("mini"), szFileExt, false );
_tcscat( szCmd, _T("\\")); _tcscat( szCmd, szDumpFile);
hDumpFile = CreateFile( szCmd, GENERIC_ALL, 0, NULL, // sa
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hDumpFile == INVALID_HANDLE_VALUE ) {
dwLastErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwLastErr); break; }
dwBufSize = _MAX_DIR; hr = _Module.GetEmInstallDir( szCmd, &dwBufSize ); if( FAILED(hr) ) break;
_tcsncat( szCmd, lpszDbgHelpDll, _MAX_PATH ); hDbgHelp = LoadLibrary(szCmd); if( hDbgHelp == NULL ) {
hr = HRESULT_FROM_WIN32(GetLastError()); break; }
PFNWR pFunc = (PFNWR) GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if(!pFunc) {
hr = E_FAIL; break; }
hr = HRESULT_FROM_WIN32(GetProcessHandle(m_pEmSessObj->nId, &hProcess)); FAILEDHR_BREAK(hr);
hr = S_FALSE;
if( pFunc(hProcess, m_pEmSessObj->nId, (HANDLE)hDumpFile, MiniDumpNormal, NULL, NULL, NULL) ) {
hr = S_OK; }
} else{
dwBufSize = _MAX_PATH; _Module.GetEmDirectory( EMOBJ_USERDUMP, szDumpFile, dwBufSize, szFileExt, _MAX_EXT ); CreateDirectory( szDumpFile, NULL );
_stprintf( szCmd, _T(" %d \"%s\""), m_pEmSessObj->nId, szDumpFile );
GetUniqueFileName ( m_pEmSessObj, szDumpFile, _T("user"), szFileExt, false ); _tcscat(szCmd, _T("\\")); _tcscat(szCmd, szDumpFile);
STARTUPINFO sp; PROCESS_INFORMATION pi;
ZeroMemory(&sp, sizeof(sp)); ZeroMemory(&pi, sizeof(pi));
dwBufSize = _MAX_DIR; hr = _Module.GetEmInstallDir( szDumpFile, &dwBufSize ); if( FAILED(hr) ) break;
_tcsncat( szDumpFile, lpszUserDumpExe, _MAX_PATH );
BOOL bRet = CreateProcess(// This has to be obtained from the registry...
szDumpFile, szCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &sp, &pi );
WaitForSingleObject( pi.hProcess, INFINITE ); CloseHandle(pi.hProcess);
hr = S_OK; } } while(FALSE);
if(hDumpFile != INVALID_HANDLE_VALUE) { CloseHandle(hDumpFile); }
if(hDbgHelp) { FreeLibrary( hDbgHelp ); } if(hProcess) { CloseHandle( hProcess ); }
if(hr == S_OK){
lStatus |= STAT_FILECREATED_SUCCESSFULLY; } else {
lStatus |= STAT_FILECREATION_FAILED; }
hr = m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, lStatus, hr, NULL );
return hr; }
HRESULT CEMSessionThread::StopDebugging( ) { ATLTRACE(_T("CEMSessionThread::StopDebugging\n"));
HRESULT hr = S_OK; IDebugClient *pDBGClntLocal = NULL; IDebugControl *pDBGCtrlLocal = NULL;
do { /*
// We seem to allow manual sessions to be stopped too..
if( eDBGSessType == SessType_Manual ) {
hr = S_OK; break; } */ m_bContinueSession = FALSE;
eDBGServie = DBGService_Stop;
hr = m_pDBGClient->CreateClient(&pDBGClntLocal); FAILEDHR_BREAK(hr);
hr = pDBGClntLocal->ExitDispatch(m_pDBGClient); FAILEDHR_BREAK(hr);
WaitForSingleObject( m_hEvent, INFINITE );
#ifdef _DEBUG
hr = m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_SUCCESS, S_OK, L"CEMSessionThread::StopDebugging - called" ); #else
hr = m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_SUCCESS, S_OK, NULL ); #endif
FAILEDHR_BREAK(hr);
} while(FALSE);
return hr; }
HRESULT CEMSessionThread::GetCmd ( IN eDBGServiceRequested eDBGSvc, IN OUT char * pszCmdBuff, IN OUT DWORD &dwBufLen ) { ATLTRACE(_T("CEMSessionThread::GetCmd\n"));
HRESULT hr = S_OK; char szPostDebug[_MAX_PATH] = "C:\\Program Files\\Debuggers\\bin\\em\\config\\PostDebug.ecx";
_ASSERTE( pszCmdBuff != NULL ); _ASSERTE( dwBufLen > 0 );
do { if( pszCmdBuff == NULL || dwBufLen < 1L ){ hr = E_INVALIDARG; break; }
strcpy( pszCmdBuff, "" );
switch( eDBGSvc ) { case DBGService_Stop: case DBGService_HandleException: strncpy( pszCmdBuff, "q", dwBufLen ); break; case DBGService_Cancel: strncpy( pszCmdBuff, "qd", dwBufLen ); // QD (Quit and Detach);
break; case DBGService_CreateMiniDump: sprintf( pszCmdBuff, ".dump /m d:\\EMMiniDump%d.dmp", m_pEmSessObj->nId ); break; case DBGService_CreateUserDump: sprintf( pszCmdBuff, ".dump d:\\EMUserDump%d.dmp", m_pEmSessObj->nId ); break; case DBGService_Go: strncpy( pszCmdBuff, "g", dwBufLen ); break; default: hr = E_INVALIDARG; } } while( false );
dwBufLen = strlen( pszCmdBuff );
return hr; }
HRESULT CEMSessionThread::OnException ( IN PEXCEPTION_RECORD64 pException ) {
ATLTRACE(_T("CEMSessionThread::OnException\n"));
HRESULT hr = S_OK; IDebugClient *pDBGClntLocal = NULL;
DWORD excpcd = pException->ExceptionCode; TCHAR szTemp[_MAX_PATH+1] = _T(""); TCHAR szDesc[sizeof EmObject+1] = _T("");
do { if(excpcd == EXCEPTION_BREAKPOINT){
break; }
if(m_bGenerateMiniDump) {
hr = CreateDumpFile( TRUE ); FAILEDHR_BREAK(hr); }
if(m_bGenerateUserDump) {
hr = CreateDumpFile( FALSE ); FAILEDHR_BREAK(hr); }
if(excpcd == EXCEPTION_ACCESS_VIOLATION){
#ifdef _DEBUG
m_pASTManager->SetSessionStatus(m_pEmSessObj->guidstream, STAT_SESS_STOPPED_ACCESSVIOLATION_OCCURED, S_OK, L"OnException - AV"); #else
m_pASTManager->SetSessionStatus(m_pEmSessObj->guidstream, STAT_SESS_STOPPED_ACCESSVIOLATION_OCCURED, S_OK, NULL); #endif
::LoadString(_Module.GetResourceInstance(), IDS_DEBUGGEE_ACCESSVIOLATION, szTemp, _MAX_PATH); GetDescriptionFromEmObj(m_pEmSessObj, szDesc, sizeof EmObject, szTemp); NotifyAdmin(szDesc); } else{ // Exception..
#ifdef _DEBUG
m_pASTManager->SetSessionStatus(m_pEmSessObj->guidstream, STAT_SESS_STOPPED_EXCEPTION_OCCURED, S_OK, L"OnException - Exception"); #else
m_pASTManager->SetSessionStatus(m_pEmSessObj->guidstream, STAT_SESS_STOPPED_EXCEPTION_OCCURED, S_OK, NULL); #endif
::LoadString(_Module.GetResourceInstance(), IDS_DEBUGGEE_EXCEPTION, szTemp, _MAX_PATH); GetDescriptionFromEmObj(m_pEmSessObj, szDesc, sizeof EmObject, szTemp); NotifyAdmin(szDesc); }
hr = m_pDBGClient->CreateClient(&pDBGClntLocal); FAILEDHR_BREAK(hr);
hr = pDBGClntLocal->ExitDispatch(m_pDBGClient); FAILEDHR_BREAK(hr); } while(FALSE);
return hr; }
HRESULT CEMSessionThread::CanContinue() { ATLTRACE(_T("CEMSessionThread::CanContinue\n"));
ULONG ExecStatus = DEBUG_STATUS_BREAK; HRESULT hr = S_OK;
do { hr = m_pDBGControl->GetExecutionStatus(&ExecStatus); FAILEDHR_BREAK(hr);
//
// We don't have anything to do if the debuggee
// has exited.
//
if( ExecStatus == DEBUG_STATUS_NO_DEBUGGEE ){ hr = S_FALSE; break; }
if( IsStopRequested() == TRUE ){ hr = S_FALSE; break; } } while( false );
return hr; }
HRESULT CEMSessionThread::KeepDebuggeeRunning() { ATLTRACE(_T("CEMSessionThread::KeepDebuggeeRunning\n"));
HRESULT hr = E_FAIL; ULONG ExecStatus = DEBUG_STATUS_BREAK;
do { hr = m_pDBGControl->GetExecutionStatus(&ExecStatus); FAILEDHR_BREAK(hr);
if( ExecStatus != DEBUG_STATUS_BREAK ){ break; }
hr = BreakIn(); FAILEDHR_BREAK(hr);
hr = m_pDBGControl->Execute( DEBUG_OUTCTL_ALL_CLIENTS, "g", DEBUG_EXECUTE_DEFAULT ); FAILEDHR_BREAK(hr);
} while( false );
return hr; }
HRESULT CEMSessionThread::BreakIn() { ATLTRACE(_T("CEMSessionThread::BreakIn\n"));
HRESULT hr = E_FAIL; ULONG ExecStatus = DEBUG_STATUS_BREAK;
do { hr = m_pDBGControl->GetExecutionStatus(&ExecStatus); FAILEDHR_BREAK(hr);
if( ExecStatus == DEBUG_STATUS_GO || ExecStatus == DEBUG_STATUS_GO_HANDLED || ExecStatus == DEBUG_STATUS_GO_NOT_HANDLED ){
hr = m_pDBGControl->SetInterrupt(DEBUG_INTERRUPT_ACTIVE); FAILEDHR_BREAK(hr);
//
// Though SetInterrupt returns immediately, it takes some time
// for the interrrupt to occur..
//
Sleep(2000); } } while( false );
return hr; }
HRESULT CEMSessionThread::OnProcessExit ( IN ULONG nExitCode ) { ATLTRACE(_T("CEMSessionThread::OnProcessExit\n"));
HRESULT hr = S_OK; IDebugClient *pDBGClntLocal = NULL; IDebugControl *pDBGCtrlLocal = NULL;
do { #ifdef _DEBUG
hr = m_pASTManager->SetSessionStatus(m_pEmSessObj->guidstream, STAT_SESS_STOPPED_DEBUGGEE_EXITED, S_OK, L"OnProcessExit"); #else
hr = m_pASTManager->SetSessionStatus(m_pEmSessObj->guidstream, STAT_SESS_STOPPED_DEBUGGEE_EXITED, S_OK, NULL); #endif
FAILEDHR_BREAK(hr);
hr = m_pDBGClient->CreateClient(&pDBGClntLocal); FAILEDHR_BREAK(hr);
hr = pDBGClntLocal->ExitDispatch(m_pDBGClient); FAILEDHR_BREAK(hr);
} while ( false );
return hr; }
HRESULT CEMSessionThread::Execute() { ATLTRACE(_T("CEMSessionThread::Execute\n"));
HRESULT hr = E_FAIL;
do { hr = m_pDBGControl->Execute( DEBUG_OUTCTL_ALL_CLIENTS, "? a;g", DEBUG_EXECUTE_DEFAULT ); FAILEDHR_BREAK(hr);
} while ( false );
return hr; }
HRESULT CEMSessionThread::InitAutomaticSession ( IN BOOL bRecursive, IN BSTR bstrEcxFilePath, IN BSTR bstrNotificationString, IN BSTR bstrAltSymPath, IN BOOL bGenerateMiniDump, IN BOOL bGenerateUserDump ) { ATLTRACE(_T("CEMSessionThread::InitAutomaticSession\n"));
_ASSERTE(bstrEcxFilePath != NULL);
if(bstrEcxFilePath == NULL) { return E_INVALIDARG; }
eDBGSessType = SessType_Automatic; m_bRecursive = bRecursive; m_bstrEcxFilePath = ::SysAllocString(bstrEcxFilePath); m_bstrNotificationString = ::SysAllocString(bstrNotificationString); m_bstrAltSymPath = ::SysAllocString(bstrAltSymPath); m_bGenerateMiniDump = bGenerateMiniDump; m_bGenerateUserDump = bGenerateUserDump;
return S_OK; }
HRESULT CEMSessionThread::InitManualSession ( IN BSTR bstrEcxFilePath, IN UINT nPortNumber, IN BSTR bstrUserName, IN BSTR bstrPassword, IN BOOL bBlockIncomingIPConnections, IN BSTR bstrAltSymPath ) { ATLTRACE(_T("CEMSessionThread::InitManualSession\n"));
_ASSERTE( nPortNumber != 0 ); _ASSERTE( bstrUserName != NULL ); _ASSERTE( bstrPassword != NULL );
HRESULT hr = E_FAIL;
do {
if( ( nPortNumber == 0 ) || ( bstrUserName == NULL )|| ( bstrPassword == NULL ) ) {
hr = E_INVALIDARG; break; }
eDBGSessType = SessType_Manual;
if(bstrEcxFilePath) m_bstrEcxFilePath = ::SysAllocString(bstrEcxFilePath);
m_nPort = nPortNumber; m_bBlockIncomingIPConnections = bBlockIncomingIPConnections; if(bstrUserName) m_bstrUserName = ::SysAllocString(bstrUserName); if(bstrPassword) m_bstrPassword = ::SysAllocString(bstrPassword); if(bstrAltSymPath) m_bstrAltSymPath = ::SysAllocString(bstrAltSymPath);
hr = S_OK;
} while ( false );
return hr; }
HRESULT CEMSessionThread::StopServer() { ATLTRACE(_T("CEMSessionThread::StopServer\n"));
HRESULT hr = E_FAIL;
do {
if(m_pi.hProcess){
TerminateProcess(m_pi.hProcess, 0); ZeroMemory((void *)&m_pi, sizeof PROCESS_INFORMATION); } } while( false );
return hr; }
HRESULT CEMSessionThread::NotifyAdmin(LPCTSTR lpszData) { ATLTRACE(_T("CEMSessionThread::NotifyAdmin\n"));
DWORD dwLastRet = 0L;
CNotify AdminNotify(m_bstrNotificationString, lpszData);
dwLastRet = AdminNotify.Notify();
return HRESULT_FROM_WIN32(dwLastRet); }
HRESULT CEMSessionThread::GetDescriptionFromEmObj ( const PEmObject pEmObj, LPTSTR lpszDesc, ULONG cchDesc, LPCTSTR lpszHeader /* = NULL */ ) const { _ASSERTE( pEmObj != NULL ); _ASSERTE( lpszDesc != NULL ); _ASSERTE( cchDesc > 0 );
HRESULT hr = E_FAIL; TCHAR szTemp[_MAX_PATH+1] = _T(""); int j = 0;
do { if( pEmObj == NULL || lpszDesc == NULL || cchDesc <= 0 ) { return E_INVALIDARG; } /*
short type; unsigned char guidstream[ 16 ]; LONG nId; TCHAR szName[ 256 ]; TCHAR szSecName[ 256 ]; LONG nStatus; DATE dateStart; DATE dateEnd; TCHAR szBucket1[ 64 ]; DWORD dwBucket1; HRESULT hr; */ j = _sntprintf(lpszDesc, cchDesc, _T("%s"), _T(""));
if( lpszHeader ) {
j += _sntprintf(lpszDesc+j, cchDesc, _T("%s -- "), lpszHeader); }
if( pEmObj->type == EMOBJ_PROCESS ) {
::LoadString(_Module.GetResourceInstance(), IDS_PROCESS, szTemp, _MAX_PATH); } else if( pEmObj->type == EMOBJ_SERVICE ) {
::LoadString(_Module.GetResourceInstance(), IDS_SERVICE, szTemp, _MAX_PATH); }
if(_tcscmp(szTemp, _T("")) != 0) {
j += _sntprintf(lpszDesc+j, cchDesc, _T("%s : %d - "), szTemp, pEmObj->nId); }
if(_tcscmp(pEmObj->szName, _T("")) != 0) { ::LoadString(_Module.GetResourceInstance(), IDS_IMAGENAME, szTemp, _MAX_PATH); j += _sntprintf(lpszDesc+j, cchDesc, _T("%s : %s - "), szTemp, pEmObj->szName); }
if(_tcscmp(pEmObj->szSecName, _T("")) != 0) { ::LoadString(_Module.GetResourceInstance(), IDS_SHORTNAME, szTemp, _MAX_PATH); j += _sntprintf(lpszDesc+j, cchDesc, _T("%s : %s - "), szTemp, pEmObj->szSecName); }
#ifdef _DEBUG
StringFromGUID2(*(GUID*)pEmObj->guidstream, szTemp, _MAX_PATH); if( pEmObj->guidstream && strcmp((const char*)pEmObj->guidstream, "") != 0 ) { j += _sntprintf(lpszDesc+j, cchDesc, _T("%s"), szTemp); } #endif // _DEBUG
} while ( false );
return hr; }
HRESULT CEMSessionThread::CancelDebugging() { ATLTRACE(_T("CEMSessionThread::CancelDebugging\n"));
HRESULT hr = S_OK; IDebugClient *pDBGClntLocal = NULL; IDebugControl *pDBGCtrlLocal = NULL;
do { if( eDBGSessType == SessType_Manual ) {
hr = S_OK; break; }
m_bContinueSession = FALSE;
eDBGServie = DBGService_Cancel;
hr = m_pDBGClient->CreateClient(&pDBGClntLocal); FAILEDHR_BREAK(hr);
hr = pDBGClntLocal->ExitDispatch(m_pDBGClient); FAILEDHR_BREAK(hr);
WaitForSingleObject( m_hEvent, INFINITE );
#ifdef _DEBUG
hr = m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_SUCCESS, S_OK, L"CEMSessionThread::CancelDebugging - called" ); #else
hr = m_pASTManager->SetSessionStatus( m_pEmSessObj->guidstream, STAT_SESS_STOPPED_SUCCESS, S_OK, NULL ); #endif
FAILEDHR_BREAK(hr);
} while(FALSE);
return hr; }
HRESULT CEMSessionThread::ExecuteCommandsTillGo ( OUT DWORD *pdwRes ) { _ASSERTE( m_pEcxFile != NULL ); _ASSERTE( m_pDBGControl != NULL );
HRESULT hr = E_FAIL; char cmd[MAX_COMMAND] = ""; ULONG ExecStatus = DEBUG_STATUS_BREAK;
__try {
if( m_pEcxFile == NULL || m_pDBGControl == NULL ) {
hr = E_INVALIDARG; goto qExecuteCommandsTillGo; }
if( pdwRes ) *pdwRes = 0L; // success
Sleep(2000); //
do { hr = m_pDBGControl->GetExecutionStatus(&ExecStatus); if( FAILED(hr) ) { goto qExecuteCommandsTillGo; }
//
// we can execute commands only when the debuggee is in
// this state..
//
if( ExecStatus != DEBUG_STATUS_BREAK ) { hr = E_FAIL; goto qExecuteCommandsTillGo; }
if (fgets(cmd, MAX_COMMAND-1, m_pEcxFile)) { cmd[strlen(cmd) - 1] = 0; if( strcmp( cmd, "g" ) == 0 || strcmp( cmd, "G" ) == 0 ) { hr = S_OK; goto qExecuteCommandsTillGo; }
hr = m_pDBGControl->OutputPrompt(DEBUG_OUTPUT_PROMPT, "> "); if( FAILED(hr) ) { goto qExecuteCommandsTillGo; }
hr = m_pDBGControl->Execute( DEBUG_OUTCTL_ALL_CLIENTS, cmd, DEBUG_EXECUTE_ECHO );
if( FAILED(hr) ) { goto qExecuteCommandsTillGo; }
} else // eof reached..??
{ if( pdwRes ) { *pdwRes = GetLastError(); } GetLastError(); hr = S_FALSE; goto qExecuteCommandsTillGo; } } while ( true );
qExecuteCommandsTillGo: if( FAILED(hr) ) {}
} __except ( EXCEPTION_EXECUTE_HANDLER, 1 ) {
hr = E_UNEXPECTED; _ASSERTE( false ); }
return hr; }
|