| /******************************************************************************* |
| * 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, new PropertyValue(processName_)); |
| |
| // do not support process stepping yet |
| int supportedResumeModes = (1 << RM_RESUME); |
| SetProperty(PROP_CAN_RESUME, new PropertyValue(supportedResumeModes)); |
| |
| SetProperty(PROP_CAN_TERMINATE, new PropertyValue(true)); |
| SetProperty(PROP_CAN_SUSPEND, new PropertyValue(true)); |
| } |
| |
| WinProcess::~WinProcess(void) { |
| // This makes a copy. |
| std::list<Context *> remainingKids = GetChildren(); |
| |
| // delete children |
| for (std::list<Context *>::iterator iter = remainingKids.begin(); |
| iter != remainingKids.end(); iter++) { |
| Context* kid = *iter; |
| delete ContextManager::removeContext(kid->GetID()); |
| } |
| |
| processIDMap.erase(GetOSID()); |
| } |
| |
| 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<std::string, Properties>& WinProcess::GetExecutables() |
| { |
| return executables_; |
| } |
| |