/******************************************************************************* | |
* Copyright (c) 2009, 2011 Nokia and others. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* Nokia - Initial API and implementation | |
*******************************************************************************/ | |
#include "StdAfx.h" | |
#include "WinProcess.h" | |
#include "WinThread.h" | |
#include "EventClientNotifier.h" | |
#include "AgentUtils.h" | |
#include "Psapi.h" | |
#include "assert.h" | |
#include "WinDebugMonitor.h" | |
#include "TerminateProcessAction.h" | |
#include "ProtocolConstants.h" | |
#include "RunControlService.h" | |
#include "ContextManager.h" | |
#include "BreakpointsService.h" | |
std::map<int, WinProcess*> WinProcess::processIDMap; | |
WinProcess::WinProcess(WinDebugMonitor* monitor, DEBUG_EVENT& debugEvent) | |
: ProcessContext(debugEvent.dwProcessId, ROOT_CONTEXT_ID, CreateInternalID(debugEvent.dwProcessId)), | |
processHandle_(debugEvent.u.CreateProcessInfo.hProcess), | |
monitor_(monitor) | |
{ | |
isRoot_ = true; | |
processIDMap[debugEvent.dwProcessId] = this; | |
// Get the name for the new process | |
std::string moduleFileName = "unknown"; | |
int bufferSize = 32768; | |
{ | |
LPTSTR processNameBuffer = new TCHAR[bufferSize]; | |
int nameLength = GetProcessImageFileName((HMODULE) processHandle_, | |
processNameBuffer, bufferSize); | |
if (nameLength > 0) | |
moduleFileName = AgentUtils::makeString(processNameBuffer); | |
delete[] processNameBuffer; | |
} | |
int lastSlash = moduleFileName.find_last_of("\\"); | |
if (lastSlash > 0) | |
moduleFileName = moduleFileName.substr(lastSlash + 1); | |
processName_ = moduleFileName; | |
Initialize(); | |
} | |
WinProcess::WinProcess(DWORD procID, std::string procName) | |
: ProcessContext(procID, ROOT_CONTEXT_ID, CreateInternalID(procID)), | |
processHandle_(NULL), | |
monitor_(NULL) | |
{ | |
processName_ = procName; | |
Initialize(); | |
} | |
// Initialize process specific properties. | |
void WinProcess::Initialize() { | |
SetProperty(PROP_NAME, PropertyValue(processName_)); | |
// do not support process stepping yet | |
int supportedResumeModes = (1 << RM_RESUME); | |
SetProperty(PROP_CAN_RESUME, PropertyValue(supportedResumeModes)); | |
SetProperty(PROP_CAN_TERMINATE, PropertyValue(true)); | |
SetProperty(PROP_CAN_SUSPEND, PropertyValue(true)); | |
} | |
WinProcess::~WinProcess(void) { | |
processIDMap.erase(GetOSID()); | |
GetMonitor()->ProcessDied(GetOSID()); | |
// Destructor of parent classes will be called which will | |
// delete all children contexts (threads, registers, etc). | |
} | |
const HANDLE& WinProcess::GetProcessHandle() const { | |
return processHandle_; | |
} | |
WinProcess* WinProcess::GetProcessByID(int processID) { | |
std::map<int, WinProcess*>::iterator iter = processIDMap.find(processID); | |
if (iter == processIDMap.end()) | |
return NULL; | |
return iter->second; | |
} | |
int WinProcess::ReadMemory(const ReadWriteMemoryParams& params) throw (AgentException) { | |
int result = 0; | |
BOOL success | |
= ::ReadProcessMemory(processHandle_, (LPCVOID) params.address, | |
params.memBuffer, params.size, params.sizeTransferred); | |
if (!success) | |
result = ::GetLastError(); | |
else | |
BreakpointsService::RemoveBreakpointsFromMemoryRead(processHandle_, params.address, params.memBuffer, params.size); | |
return result; | |
} | |
int WinProcess::WriteMemory(const ReadWriteMemoryParams& params) throw (AgentException) { | |
int result = 0; | |
BOOL success | |
= ::WriteProcessMemory(processHandle_, (LPVOID) params.address, | |
params.memBuffer, params.size, params.sizeTransferred); | |
if (!success) | |
result = ::GetLastError(); | |
else { | |
BreakpointsService::ReInsertBreakpointsAfterMemoryWrite(processHandle_, params.address, params.memBuffer, params.size); | |
} | |
return result; | |
} | |
void WinProcess::Terminate(const AgentActionParams& params) throw (AgentException) { | |
if (monitor_) | |
monitor_->PostAction(new TerminateProcessAction(params, GetOSID())); | |
} | |
// TODO: if we report an error, DSF gets confused... | |
// just report success even though it's not implemented | |
void WinProcess::SingleStep(const AgentActionParams& params) throw (AgentException) { | |
AgentActionReply::postReply(params.channel, params.token, 0); | |
//AgentActionReply::postReply(params.channel, params.token, ERR_UNSUPPORTED); | |
}; | |
WinDebugMonitor* WinProcess::GetMonitor() const { | |
return monitor_; | |
} | |
std::map<int, Properties>& WinProcess::GetExecutablesByAddress() { | |
return executablesByAddress_; | |
} | |
void WinProcess::SetDebugRegister(WinHWBkptMgr::DRMask drMask, ContextAddress addr, WinHWBkptMgr::DRFlags flags) { | |
const std::list<Context*>& children = GetChildren(); | |
std::list<Context*>::const_iterator c; | |
for (c = children.begin(); c != children.end(); c++) { | |
WinThread* winThread = dynamic_cast<WinThread*>(*c); | |
if (winThread != NULL) | |
winThread->SetDebugRegister(drMask, addr, flags); | |
} | |
} | |
void WinProcess::ClearDebugRegister(WinHWBkptMgr::DRMask drMask) { | |
const std::list<Context*>& children = GetChildren(); | |
std::list<Context*>::const_iterator c; | |
for (c = children.begin(); c != children.end(); c++) { | |
WinThread* winThread = dynamic_cast<WinThread*>(*c); | |
if (winThread != NULL) | |
winThread->ClearDebugRegister(drMask); | |
} | |
} |