1721 lines
43 KiB
C++
1721 lines
43 KiB
C++
#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;
|
|
}
|