| /******************************************************************************* | |
| * Copyright (c) 2009 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). | |
| } | |
| HANDLE WinProcess::GetProcessHandle() { | |
| return processHandle_; | |
| } | |
| WinProcess* WinProcess::GetProcessByID(int processID) { | |
| std::map<int, WinProcess*>::iterator iter = processIDMap.find(processID); | |
| if (iter == processIDMap.end()) | |
| return NULL; | |
| else | |
| return iter->second; | |
| } | |
| int WinProcess::ReadMemory(const ReadWriteMemoryParams& params) throw (AgentException) { | |
| int result = 0; | |
| boolean 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) { | |
| // to do: handle breakpoints and watchpoints | |
| int result = 0; | |
| boolean 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() { | |
| return monitor_; | |
| } | |
| std::map<int, Properties>& WinProcess::GetExecutablesByAddress() | |
| { | |
| return executablesByAddress_; | |
| } | |