1. Fix memory leaks, no longer allocate PropertyValue.
2. Added SettingsService that allows host to push setting data to agent.
3. Improved handling of exceptions especially those like hardcoded
breakpoint in system libraries (e.g. ntdll.dll).
4. Make sure debug monitor thread is terminated when monitored process
dies.
5. Fix memory leak by making sure all context object (process, thread,
registers, etc) are deleted when a process dies.
diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/WindowsDebugAgent.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/WindowsDebugAgent.cpp
index 1a70828..229802c 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/WindowsDebugAgent.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/WindowsDebugAgent.cpp
@@ -1,171 +1,180 @@
-/*******************************************************************************
- * 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 <stdio.h>
-#include <stdlib.h>
-
-#include "ProcessService.h"
-#include "WindowsOSDataService.h"
-#include "RunControlService.h"
-#include "SimpleRegistersService.h"
-#include "RegistersService.h"
-#include "MemoryService.h"
-#include "LoggingService.h"
-#include "BreakpointsService.h"
-
-#include "EventClientNotifier.h"
-#include "Logger.h"
-
-#include "TCFHeaders.h"
-
-static Protocol * proto;
-static ChannelServer * serv;
-static TCFBroadcastGroup * bcg;
-
-static long channelCount = 0;
-
-static void channel_server_connecting(Channel * c) {
-	trace(LOG_PROTOCOL, "channel server connecting");
-
-	send_hello_message(c);
-}
-
-static void channel_server_connected(Channel * c) {
-	channelCount++;
-	int i;
-
-	trace(LOG_PROTOCOL, "channel server connected, peer services:");
-	for (i = 0; i < c->peer_service_cnt; i++) {
-		trace(LOG_PROTOCOL, "  %s", c->peer_service_list[i]);
-	}
-}
-
-static void channel_server_receive(Channel * c) {
-	handle_protocol_message(c);
-}
-
-static void channel_server_disconnected(Channel * c) {
-	trace(LOG_PROTOCOL, "channel server disconnected");
-    protocol_release(c->protocol);
-	channelCount--;
-}
-
-static void channel_new_connection(ChannelServer * serv, Channel * c) {
-	protocol_reference(proto);
-    c->protocol = proto;
-	c->connecting = channel_server_connecting;
-	c->connected = channel_server_connected;
-	c->receive = channel_server_receive;
-	c->disconnected = channel_server_disconnected;
-	channel_set_broadcast_group(c, bcg);
-	channel_start(c);
-}
-
-static void check_for_shutdown(void *x) {
-
-	if (channelCount <= 0) {
-		trace(LOG_PROTOCOL, "check_for_shutdown");
-		cancel_event_loop();
-	}
-
-	post_event_with_delay(check_for_shutdown, NULL, 120 * 1000000);
-}
-
-// override this so we can actually break on it
-_CRTIMP void __cdecl __MINGW_NOTHROW _assert (const char* error, const char* file, int line)
-{
-	char message[256];
-	snprintf(message, sizeof(message),
-			"Fatal error: assertion failed at file=%s, line=%d: %s\n",
-			file ,line, error);
-	fputs(message, stderr);
-	trace(LOG_ALWAYS, message);
-	exit(3);
-}
-
-int main(int argc, char* argv[]) {
-#ifdef _DEBUG
-	static const char* log_name = "C:\\WindowsDebugAgentLog.txt";
-    log_mode = LOG_EVENTS | LOG_CHILD | LOG_WAITPID | LOG_CONTEXT | LOG_PROTOCOL | LOG_ASYNCREQ;
-    open_log_file(log_name);
-#endif
-
-	try {
-	// For interim test purpose only:
-	// Use this unpublished option to turn off BreakpointsService,
-	// namely use EDC generic breakpoints mechanism.
-	//
-	bool installBpService = true;
-	if (argc > 1 && strcmp(argv[1], "-nobpservice") == 0)
-		installBpService = false;
-
-	static const char * url = "TCP:";
-	PeerServer * ps = NULL;
-	ini_mdep();
-	ini_trace();
-	ini_asyncreq();
-
-	ini_events_queue();
-
-	bcg = broadcast_group_alloc();
-	proto = protocol_alloc();
-
-	LogTrace("Starting up");
-	EventClientNotifier::broadcastGroup = bcg;
-	
-	new ProcessService(proto);
-	new RunControlService(proto);
-	new WindowsOSDataService(proto);
-	new RegistersService(proto);
-	new MemoryService(proto);
-	new LoggingService(proto);
-	if (installBpService)
-		new BreakpointsService(proto);
-	
-	ps = channel_peer_from_url(url);
-
-	peer_server_addprop(ps, loc_strdup("Name"), loc_strdup("Win32 Debug Agent"));
-	peer_server_addprop(ps, loc_strdup("DebugSupport"), loc_strdup(
-			"Win32 Debug API"));
-
-	LPTSTR lpNameBuffer = NULL;
-	DWORD lpnSize = 0;
-	GetComputerName(lpNameBuffer, &lpnSize);
-	if (lpnSize == 0) // On Win XP this may return zero even if there is a valid name
-		lpnSize = 1024;
-	lpNameBuffer = new char[++lpnSize];
-	GetComputerName(lpNameBuffer, &lpnSize);
-	peer_server_addprop(ps, loc_strdup("Description"), loc_strdup(lpNameBuffer));
-	delete [] lpNameBuffer;
-
-	if (ps == NULL) {
-			LogTrace("invalid server URL");
-		exit(1);
-	}
-	serv = channel_server(ps);
-	if (serv == NULL) {
-			LogTrace("cannot create TCF server\n");
-		exit(1);
-	}
-	serv->new_conn = channel_new_connection;
-
-	discovery_start();
-
-#ifdef _DEBUG
-#else
-	post_event_with_delay(check_for_shutdown, NULL, 30 * 1000000);
-#endif
-
-	run_event_loop();
-	} catch (...) {
-		LogTrace("Exception thrown, caught at main");
-	}
-	return 0;
-}
+/*******************************************************************************

+ * 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 <stdio.h>

+#include <stdlib.h>

+

+#include "ProcessService.h"

+#include "WindowsOSDataService.h"

+#include "RunControlService.h"

+#include "SimpleRegistersService.h"

+#include "RegistersService.h"

+#include "MemoryService.h"

+#include "LoggingService.h"

+#include "SettingsService.h"

+#include "BreakpointsService.h"

+

+#include "EventClientNotifier.h"

+#include "Logger.h"

+

+#include "TCFHeaders.h"

+

+static Protocol * proto;

+static ChannelServer * serv;

+static TCFBroadcastGroup * bcg;

+

+static long channelCount = 0;

+

+static void channel_server_connecting(Channel * c) {

+	trace(LOG_PROTOCOL, "channel server connecting");

+

+	send_hello_message(c);

+}

+

+static void channel_server_connected(Channel * c) {

+	channelCount++;

+	int i;

+

+	trace(LOG_PROTOCOL, "channel server connected, peer services:");

+	for (i = 0; i < c->peer_service_cnt; i++) {

+		trace(LOG_PROTOCOL, "  %s", c->peer_service_list[i]);

+	}

+}

+

+static void channel_server_receive(Channel * c) {

+	handle_protocol_message(c);

+}

+

+static void channel_server_disconnected(Channel * c) {

+	trace(LOG_PROTOCOL, "channel server disconnected");

+    protocol_release(c->protocol);

+	channelCount--;

+}

+

+static void channel_new_connection(ChannelServer * serv, Channel * c) {

+	protocol_reference(proto);

+    c->protocol = proto;

+	c->connecting = channel_server_connecting;

+	c->connected = channel_server_connected;

+	c->receive = channel_server_receive;

+	c->disconnected = channel_server_disconnected;

+	channel_set_broadcast_group(c, bcg);

+	channel_start(c);

+}

+

+static void check_for_shutdown(void *x) {

+

+	if (channelCount <= 0) {

+		trace(LOG_PROTOCOL, "check_for_shutdown");

+		cancel_event_loop();

+	}

+

+	post_event_with_delay(check_for_shutdown, NULL, 120 * 1000000);

+}

+

+/*

+ * Central point for cleanup after debug session ends.
+ */

+void debug_session_ends() {

+	SettingsService::debugSessionEnds();

+}

+

+// override this so we can actually break on it

+_CRTIMP void __cdecl __MINGW_NOTHROW _assert (const char* error, const char* file, int line)

+{

+	char message[256];

+	snprintf(message, sizeof(message),

+			"Fatal error: assertion failed at file=%s, line=%d: %s\n",

+			file ,line, error);

+	fputs(message, stderr);

+	trace(LOG_ALWAYS, message);

+	exit(3);

+}

+

+int main(int argc, char* argv[]) {

+#ifdef _DEBUG

+	static const char* log_name = "C:\\WindowsDebugAgentLog.txt";

+    log_mode = LOG_EVENTS | LOG_CHILD | LOG_WAITPID | LOG_CONTEXT | LOG_PROTOCOL | LOG_ASYNCREQ;

+    open_log_file(log_name);

+#endif

+

+	try {

+	// For interim test purpose only:

+	// Use this unpublished option to turn off BreakpointsService,

+	// namely use EDC generic breakpoints mechanism.

+	//

+	bool installBpService = true;

+	if (argc > 1 && strcmp(argv[1], "-nobpservice") == 0)

+		installBpService = false;

+

+	static const char * url = "TCP:";

+	PeerServer * ps = NULL;

+	ini_mdep();

+	ini_trace();

+	ini_asyncreq();

+

+	ini_events_queue();

+

+	bcg = broadcast_group_alloc();

+	proto = protocol_alloc();

+

+	LogTrace("Starting up");

+	EventClientNotifier::broadcastGroup = bcg;

+	

+	new ProcessService(proto);

+	new RunControlService(proto);

+	new WindowsOSDataService(proto);

+	new RegistersService(proto);

+	new MemoryService(proto);

+	new LoggingService(proto);

+	new SettingsService(proto);

+	if (installBpService)

+		new BreakpointsService(proto);

+	

+	ps = channel_peer_from_url(url);

+

+	peer_server_addprop(ps, loc_strdup("Name"), loc_strdup("Win32 Debug Agent"));

+	peer_server_addprop(ps, loc_strdup("DebugSupport"), loc_strdup(

+			"Win32 Debug API"));

+

+	LPTSTR lpNameBuffer = NULL;

+	DWORD lpnSize = 0;

+	GetComputerName(lpNameBuffer, &lpnSize);

+	if (lpnSize == 0) // On Win XP this may return zero even if there is a valid name

+		lpnSize = 1024;

+	lpNameBuffer = new char[++lpnSize];

+	GetComputerName(lpNameBuffer, &lpnSize);

+	peer_server_addprop(ps, loc_strdup("Description"), loc_strdup(lpNameBuffer));

+	delete [] lpNameBuffer;

+

+	if (ps == NULL) {

+			LogTrace("invalid server URL");

+		exit(1);

+	}

+	serv = channel_server(ps);

+	if (serv == NULL) {

+			LogTrace("cannot create TCF server\n");

+		exit(1);

+	}

+	serv->new_conn = channel_new_connection;

+

+	discovery_start();

+

+#ifdef _DEBUG

+#else

+	post_event_with_delay(check_for_shutdown, NULL, 30 * 1000000);

+#endif

+

+	run_event_loop();

+	} catch (...) {

+		LogTrace("Exception thrown, caught at main");

+	}

+	return 0;

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/EventClientNotifier.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/EventClientNotifier.cpp
index 2244aac..9aa44a7 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/EventClientNotifier.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/EventClientNotifier.cpp
@@ -1,242 +1,254 @@
-/*******************************************************************************
- * Copyright (c) 2010 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 "EventClientNotifier.h"
-#include "TCFHeaders.h"
-#include "Logger.h"
-#include "AgentUtils.h"
-#include "TCFOutputStream.h"
-#include "ProtocolConstants.h"
-#include "ThreadContext.h"
-
-TCFBroadcastGroup * EventClientNotifier::broadcastGroup = NULL;
-
-static const char RUN_CONTROL[] = "RunControl";
-
-SendRemovedEventParams::SendRemovedEventParams(Context* context_, bool delete_) {
-	context = context_;
-	deleteContext = delete_;
-}
-
-SendExeEventParams::SendExeEventParams(Context* context_, unsigned long pcAddress_, const Properties& properties_) {
-	context = context_;
-	properties = properties_;
-	pcAddress = pcAddress_;
-}
-
-SendExceptionEventParams::SendExceptionEventParams(Context* context_,
-		const std::string& description_) {
-	context = context_;
-	description = description_;
-}
-
-SendSuspendEventParams::SendSuspendEventParams(Context* context_, unsigned long pcAddress_,
-		const char* reason_, const std::string& message_) {
-	context = context_;
-	pcAddress = pcAddress_;
-	reason = reason_;
-	message = message_;
-}
-
-void EventClientNotifier::SendContextAdded(Context* context) {
-	post_event(EventClientNotifier::SendContextAddedCallback, context);
-}
-
-void EventClientNotifier::SendContextAddedCallback(void* context) {
-	TCFOutputStream out(&broadcastGroup->out);
-
-	out.writeStringZ("E");
-	out.writeStringZ(RUN_CONTROL);
-	out.writeStringZ("contextAdded");
-
-	// <array of context data>
-	out.writeCharacter('[');
-	WriteContext(*(Context*) context, out);
-	out.writeCharacter(']');
-	out.writeZero();
-
-	out.writeComplete();
-
-	std::string contextID = ((Context*) context)->GetID();
-
-	LogTrace("EventClientNotifier::SendContextAdded ", "context id: %s",
-			contextID.c_str());
-
-}
-
-void EventClientNotifier::SendContextRemoved(Context* context, bool deleteContext) {
-	SendRemovedEventParams* params = new SendRemovedEventParams(context, deleteContext);
-	post_event(EventClientNotifier::SendContextRemovedCallback, params);
-}
-
-void EventClientNotifier::SendContextRemovedCallback(void* context) {
-	SendRemovedEventParams* params = (SendRemovedEventParams*) context;
-	TCFOutputStream out(&broadcastGroup->out);
-
-	out.writeStringZ("E");
-	out.writeStringZ(RUN_CONTROL);
-	out.writeStringZ("contextRemoved");
-
-	/* <array of context data> */
-	out.writeCharacter('[');
-	out.writeString(params->context->GetID().c_str());
-	out.writeCharacter(']');
-	out.writeZero();
-
-	out.writeComplete();
-
-	LogTrace("EventClientNotifier::SendContextRemoved ", "context id: %d",
-			params->context->GetID().c_str());
-
-	if (params->deleteContext)
-		delete params->context;
-
-	delete params;
-
-}
-
-void EventClientNotifier::SendExecutableEvent(Context* context, unsigned long pcAddress, const Properties& properties) { 
-	post_event(EventClientNotifier::SendExecutableEventCallback,
-			new SendExeEventParams(context, pcAddress, properties));
-}
-
-void EventClientNotifier::SendExecutableEventCallback(void* params) {
-	SendExeEventParams* eventParams = (SendExeEventParams*) params;
-
-	TCFOutputStream out(&broadcastGroup->out);
-
-	out.writeStringZ("E");
-	out.writeStringZ(RUN_CONTROL);
-	out.writeStringZ("contextSuspended");
-
-	out.writeString(eventParams->context->GetID());
-	out.writeZero();
-
-	out.writeLong(eventParams->pcAddress);
-	out.writeZero();
-
-	out.writeString(REASON_SHAREDLIB);
-	out.writeZero();
-
-	WriteProperties(eventParams->properties, out);
-
-	out.writeZero();
-
-	out.writeComplete();
-
-#if ENABLE_Trace
-	PropertyValue* exe = 0;
-	Properties::const_iterator iter = eventParams->properties.find(PROP_NAME);
-	if (iter != eventParams->properties.end())
-		exe = iter->second;
-	LogTrace("EventClientNotifier::SendExecutableEvent",
-			"context id: %s executable: %s address: %X",
-			eventParams->context->GetID().c_str(),
-			exe ? exe->getStringValue().c_str() : "<none>", 
-			eventParams->pcAddress);
-#endif
-	
-	delete eventParams;
-}
-
-void EventClientNotifier::SendContextSuspended(Context* context,
-		unsigned long pcAddress, const char* reason, const std::string& message) {
-	post_event(EventClientNotifier::SendContextSuspendedCallback,
-			new SendSuspendEventParams(context, pcAddress, reason, message));
-}
-
-void EventClientNotifier::SendContextSuspendedCallback(void* params_) {
-	SendSuspendEventParams* params = (SendSuspendEventParams*) params_;
-	TCFOutputStream out(&broadcastGroup->out);
-
-	out.writeStringZ("E");
-	out.writeStringZ(RUN_CONTROL);
-	out.writeStringZ("contextSuspended");
-
-	out.writeString(params->context->GetID().c_str());
-	out.writeZero();
-
-	out.writeLong(params->pcAddress);
-	out.writeZero();
-
-	out.writeString(params->reason);
-	out.writeZero();
-
-	out.writeCharacter('{');
-	if (params->message.length() > 0) {
-		out.writeString("message");
-		out.writeCharacter(':');
-		out.writeString(params->message.c_str());
-	}
-	out.writeCharacter('}');
-	out.writeZero();
-
-	out.writeComplete();
-
-	LogTrace("EventClientNotifier::SendContextSuspended ",
-			"context id: %s address: %X", params->context->GetID().c_str(),
-			params->pcAddress);
-
-	delete params;
-}
-
-
-
-void EventClientNotifier::SendContextException(Context* context,
-		const std::string& description) {
-	post_event(EventClientNotifier::SendContextExceptionCallback,
-			new SendExceptionEventParams(context, description));
-}
-
-void EventClientNotifier::SendContextExceptionCallback(void* params) {
-	SendExceptionEventParams* eventParams = (SendExceptionEventParams*) params;
-
-	TCFOutputStream out(&broadcastGroup->out);
-
-	out.writeStringZ("E");
-	out.writeStringZ(RUN_CONTROL);
-	out.writeStringZ("contextException");
-
-	out.writeString(eventParams->context->GetID());
-	out.writeZero();
-
-	out.writeCharacter('"');
-	out.writeString(eventParams->description.c_str());
-	out.writeCharacter('"');
-	out.writeZero();
-
-	out.writeComplete();
-
-	LogTrace("EventClientNotifier::SendContextException ", "context id: %s",
-			eventParams->context->GetID().c_str());
-
-	delete eventParams;
-}
-
-void EventClientNotifier::WriteContext(Context& context, TCFOutputStream& out) {
-	WriteProperties(context.GetProperties(), out);
-}
-
-void EventClientNotifier::WriteProperties(const Properties& properties, TCFOutputStream& out) {
-	out.writeCharacter('{');
-
-	for (Properties::const_iterator iter = properties.begin();
-			iter != properties.end(); iter++)
-	{
-		if (iter != properties.begin())
-			out.writeCharacter(',');
-
-		out.writeString(iter->first);
-		out.writeCharacter(':');
-		iter->second->writeToTCFChannel(out);
-	}
-
-	out.writeCharacter('}');
-}
+/*******************************************************************************

+ * Copyright (c) 2010 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 "EventClientNotifier.h"

+#include "TCFHeaders.h"

+#include "Logger.h"

+#include "AgentUtils.h"

+#include "TCFOutputStream.h"

+#include "ProtocolConstants.h"

+#include "ThreadContext.h"

+#include "ContextManager.h"

+

+extern void debug_session_ends();

+

+TCFBroadcastGroup * EventClientNotifier::broadcastGroup = NULL;

+

+static const char RUN_CONTROL[] = "RunControl";

+

+SendRemovedEventParams::SendRemovedEventParams(Context* context_, bool delete_) {

+	context = context_;

+	deleteContext = delete_;

+}

+

+SendExeEventParams::SendExeEventParams(Context* context_, unsigned long pcAddress_, const Properties& properties_) {

+	context = context_;

+	properties = properties_;

+	pcAddress = pcAddress_;

+}

+

+SendExceptionEventParams::SendExceptionEventParams(Context* context_,

+		const std::string& description_) {

+	context = context_;

+	description = description_;

+}

+

+SendSuspendEventParams::SendSuspendEventParams(Context* context_, unsigned long pcAddress_,

+		const char* reason_, const std::string& message_) {

+	context = context_;

+	pcAddress = pcAddress_;

+	reason = reason_;

+	message = message_;

+}

+

+void EventClientNotifier::SendContextAdded(Context* context) {

+	post_event(EventClientNotifier::SendContextAddedCallback, context);

+}

+

+void EventClientNotifier::SendContextAddedCallback(void* context) {

+	TCFOutputStream out(&broadcastGroup->out);

+

+	out.writeStringZ("E");

+	out.writeStringZ(RUN_CONTROL);

+	out.writeStringZ("contextAdded");

+

+	// <array of context data>

+	out.writeCharacter('[');

+	WriteContext(*(Context*) context, out);

+	out.writeCharacter(']');

+	out.writeZero();

+

+	out.writeComplete();

+

+	std::string contextID = ((Context*) context)->GetID();

+

+	LogTrace("EventClientNotifier::SendContextAdded ", "context id: %s",

+			contextID.c_str());

+

+}

+

+void EventClientNotifier::SendContextRemoved(Context* context, bool deleteContext) {

+	SendRemovedEventParams* params = new SendRemovedEventParams(context, deleteContext);

+	post_event(EventClientNotifier::SendContextRemovedCallback, params);

+}

+

+void EventClientNotifier::SendContextRemovedCallback(void* context) {

+	SendRemovedEventParams* params = (SendRemovedEventParams*) context;

+	TCFOutputStream out(&broadcastGroup->out);

+

+	out.writeStringZ("E");

+	out.writeStringZ(RUN_CONTROL);

+	out.writeStringZ("contextRemoved");

+

+	/* <array of context data> */

+	out.writeCharacter('[');

+	out.writeString(params->context->GetID().c_str());

+	out.writeCharacter(']');

+	out.writeZero();

+

+	out.writeComplete();

+

+	LogTrace("EventClientNotifier::SendContextRemoved ", "context id: %d",

+			params->context->GetID().c_str());

+

+	if (params->deleteContext) {

+		ContextID id = params->context->GetID();

+		delete params->context; // this will delete the context and all its children

+

+		int remained = ContextManager::getContexts().size();

+		trace(LOG_CONTEXT, "Context %s has died. \n\t\tNumber of contexts remained: %d\n", id.c_str(), remained);

+

+		if (remained == 0) {

+			debug_session_ends();

+		}

+	}

+

+	delete params;

+

+}

+

+void EventClientNotifier::SendExecutableEvent(Context* context, unsigned long pcAddress, const Properties& properties) { 

+	post_event(EventClientNotifier::SendExecutableEventCallback,

+			new SendExeEventParams(context, pcAddress, properties));

+}

+

+void EventClientNotifier::SendExecutableEventCallback(void* params) {

+	SendExeEventParams* eventParams = (SendExeEventParams*) params;

+

+	TCFOutputStream out(&broadcastGroup->out);

+

+	out.writeStringZ("E");

+	out.writeStringZ(RUN_CONTROL);

+	out.writeStringZ("contextSuspended");

+

+	out.writeString(eventParams->context->GetID());

+	out.writeZero();

+

+	out.writeLong(eventParams->pcAddress);

+	out.writeZero();

+

+	out.writeString(REASON_SHAREDLIB);

+	out.writeZero();

+

+	WriteProperties(eventParams->properties, out);

+

+	out.writeZero();

+

+	out.writeComplete();

+

+#if ENABLE_Trace

+	PropertyValue exe;

+	Properties::const_iterator iter = eventParams->properties.find(PROP_NAME);

+	if (iter != eventParams->properties.end())

+		exe = iter->second;

+	LogTrace("EventClientNotifier::SendExecutableEvent",

+			"context id: %s executable: %s address: %X",

+			eventParams->context->GetID().c_str(),

+			exe.getType() == PVT_UNKNOWN ? exe.getStringValue().c_str() : "<none>",

+			eventParams->pcAddress);

+#endif

+	

+	delete eventParams;

+}

+

+void EventClientNotifier::SendContextSuspended(Context* context,

+		unsigned long pcAddress, const char* reason, const std::string& message) {

+	post_event(EventClientNotifier::SendContextSuspendedCallback,

+			new SendSuspendEventParams(context, pcAddress, reason, message));

+}

+

+void EventClientNotifier::SendContextSuspendedCallback(void* params_) {

+	SendSuspendEventParams* params = (SendSuspendEventParams*) params_;

+	TCFOutputStream out(&broadcastGroup->out);

+

+	out.writeStringZ("E");

+	out.writeStringZ(RUN_CONTROL);

+	out.writeStringZ("contextSuspended");

+

+	out.writeString(params->context->GetID().c_str());

+	out.writeZero();

+

+	out.writeLong(params->pcAddress);

+	out.writeZero();

+

+	out.writeString(params->reason);

+	out.writeZero();

+

+	out.writeCharacter('{');

+	if (params->message.length() > 0) {

+		out.writeString("message");

+		out.writeCharacter(':');

+		out.writeString(params->message.c_str());

+	}

+	out.writeCharacter('}');

+	out.writeZero();

+

+	out.writeComplete();

+

+	LogTrace("EventClientNotifier::SendContextSuspended ",

+			"context id: %s address: %X", params->context->GetID().c_str(),

+			params->pcAddress);

+

+	delete params;

+}

+

+

+

+void EventClientNotifier::SendContextException(Context* context,

+		const std::string& description) {

+	post_event(EventClientNotifier::SendContextExceptionCallback,

+			new SendExceptionEventParams(context, description));

+}

+

+void EventClientNotifier::SendContextExceptionCallback(void* params) {

+	SendExceptionEventParams* eventParams = (SendExceptionEventParams*) params;

+

+	TCFOutputStream out(&broadcastGroup->out);

+

+	out.writeStringZ("E");

+	out.writeStringZ(RUN_CONTROL);

+	out.writeStringZ("contextException");

+

+	out.writeString(eventParams->context->GetID());

+	out.writeZero();

+

+	out.writeCharacter('"');

+	out.writeString(eventParams->description.c_str());

+	out.writeCharacter('"');

+	out.writeZero();

+

+	out.writeComplete();

+

+	LogTrace("EventClientNotifier::SendContextException ", "context id: %s",

+			eventParams->context->GetID().c_str());

+

+	delete eventParams;

+}

+

+void EventClientNotifier::WriteContext(Context& context, TCFOutputStream& out) {

+	WriteProperties(context.GetProperties(), out);

+}

+

+void EventClientNotifier::WriteProperties(const Properties& properties, TCFOutputStream& out) {

+	out.writeCharacter('{');

+

+	for (Properties::const_iterator iter = properties.begin();

+			iter != properties.end(); iter++)

+	{

+		if (iter != properties.begin())

+			out.writeCharacter(',');

+

+		out.writeString(iter->first);

+		out.writeCharacter(':');

+		iter->second.writeToTCFChannel(out);

+	}

+

+	out.writeCharacter('}');

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/LoggingService.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/LoggingService.cpp
index 2863a51..9bc2f0c 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/LoggingService.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/LoggingService.cpp
@@ -1,198 +1,199 @@
-/*******************************************************************************
- * 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 <string>
-#include <vector>
-
-#include "LoggingService.h"
-#include "DebugMonitor.h"
-#include "ContextManager.h"
-#include "TCFChannel.h"
-
-static const char * sServiceName = "Logging";
-
-// ID of the console to write debug process output to
-static const char * sWindowsConsoleID = "ProgramOutputConsoleLogger";
-// Number of listeners to the service utilizing 'sWindowsConsoleID'.
-int LoggingService::numConsoleListeners = 0;
-
-/**
-* LoggingService: Communicates with logging hosts and allows the agent to send back messages
-* to be printed to a console or otherwise redirected.
-*/
-LoggingService::LoggingService(Protocol * proto) :
-	TCFService(proto) {
-	AddCommand("addListener", command_addListener);
-	AddCommand("removeListener", command_removeListener);
-}
-
-LoggingService::~LoggingService(void) {
-}
-
-const char* LoggingService::GetName() {
-	return sServiceName;
-}
-
-const char * LoggingService::GetWindowsConsoleID() {
-	return sWindowsConsoleID;
-}
-
-void LoggingService::command_addListener(const char * token, Channel * c) {
-
-	TCFChannel tcf(c);
-	std::string id = tcf.readString();
-	tcf.readZero();
-	tcf.readComplete();
-	
-	if ( id.compare(sWindowsConsoleID) == 0 )
-		numConsoleListeners++;
-	
-	sendOK(token, c);
-}
-
-
-void LoggingService::command_removeListener(const char * token, Channel * c) {
-	TCFChannel tcf(c);
-	std::string id = tcf.readString();
-	tcf.readZero();
-
-	if ( id.compare(sWindowsConsoleID) == 0 )
-		numConsoleListeners--;
-
-	sendOK(token, c);
-}
-
-void LoggingService::sendOK(const char * token, Channel * c)
-{
-	// Send OK message
-	TCFChannel tcf(c);
-	tcf.writeCompleteReply(token, 0);
-}
-
-
-struct LoggingMessage {
-	Channel* channel;
-	std::string str;
-	const char* consoleID;
-	
-	LoggingMessage(Channel* channel_, const std::string& str_, const char* consoleID_) 
-		: channel(channel_), str(str_), consoleID(consoleID_) 
-	{ }
-};
-
-struct DialogMessage {
-	Channel* channel;
-	IStatus::Severity severity;
-	std::string summary;
-	std::string details;
-
-	DialogMessage(Channel* channel_, const IStatus::Severity severity,
-					const std::string& summary_, const std::string& details_)
-	  : channel(channel_), severity(severity), summary(summary_), details(details_)
-	{ }
-};
-
-static void emit_logging_message(void *data) {
-	LoggingMessage* m = (LoggingMessage*) data;
-	
-	TCFChannel tcf(m->channel);
-
-	// write to the console
-	tcf.writeStringZ("E");
-	tcf.writeStringZ(sServiceName);
-	tcf.writeStringZ("write");
-
-	/* <array of context data> */
-	tcf.writeString(m->consoleID);
-	tcf.writeZero();
-	tcf.writeString(m->str);
-	tcf.writeZero();
-	tcf.writeComplete();
-	
-	delete m;
-}
-
-
-static void emit_logging_message_with_newline(void *data) {
-	LoggingMessage* m = (LoggingMessage*) data;
-
-	TCFChannel tcf(m->channel);
-
-	// write to the console
-	tcf.writeStringZ("E");
-	tcf.writeStringZ(sServiceName);
-	tcf.writeStringZ("writeln");
-
-	/* <array of context data> */
-	tcf.writeString(m->consoleID);
-	tcf.writeZero();
-	tcf.writeString(m->str);
-	tcf.writeZero();
-	tcf.writeComplete();
-
-	delete m;
-}
-
-
-static void emit_dialog_message(void *data) {
-	DialogMessage* m = (DialogMessage*) data;
-
-	TCFChannel tcf(m->channel);
-
-	// write to the console
-	tcf.writeStringZ("E");
-	tcf.writeStringZ(sServiceName);
-	tcf.writeStringZ("dialog");
-
-	/* <array of context data> */
-	tcf.writeString(LoggingService::GetWindowsConsoleID());
-	tcf.writeZero();
-	tcf.writeLong((long)m->severity);
-	tcf.writeZero();
-	tcf.writeString(m->summary);
-	tcf.writeZero();
-	tcf.writeString(m->details);
-	tcf.writeZero();
-	tcf.writeComplete();
-
-	delete m;
-}
-
-
-void LoggingService::WriteLoggingMessage(Channel *channel, const std::string& str, const char *consoleID)
-{
-	const char *windowsConsoleID = GetWindowsConsoleID();
-	// only send messages to the proper console service and when there are more than one listener
-	if ( numConsoleListeners > 0 && strcmp(windowsConsoleID, consoleID) == 0 )
-	{
-		LoggingMessage* message = new LoggingMessage(channel, str, consoleID);
-		post_event(emit_logging_message, message);
-	}
-}
-
-/** since 2.0 */
-void LoggingService::WriteLnLoggingMessage(Channel *channel, const std::string& str, const char *consoleID)
-{
-	const char *windowsConsoleID = GetWindowsConsoleID();
-	// only send messages to the proper console service and when there are more than one listener
-	if ( numConsoleListeners > 0 && strcmp(windowsConsoleID, consoleID) == 0 )
-	{
-		LoggingMessage* message = new LoggingMessage(channel, str, consoleID);
-		post_event(emit_logging_message_with_newline, message);
-	}
-}
-
-/** since 2.0 */
-void LoggingService::Dialog(Channel *channel, IStatus::Severity severity, const std::string& summary, const std::string& details)
-{
-	DialogMessage* message = new DialogMessage(channel, severity, summary, details);
-	post_event(emit_dialog_message, message);
-}
+/*******************************************************************************

+ * 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 <string>

+#include <vector>

+

+#include "LoggingService.h"

+#include "DebugMonitor.h"

+#include "ContextManager.h"

+#include "TCFChannel.h"

+

+static const char * sServiceName = "Logging";

+

+// ID of the console to write debug process output to

+static const char * sWindowsConsoleID = "ProgramOutputConsoleLogger";

+// Number of listeners to the service utilizing 'sWindowsConsoleID'.

+int LoggingService::numConsoleListeners = 0;

+

+/**

+* LoggingService: Communicates with logging hosts and allows the agent to send back messages

+* to be printed to a console or otherwise redirected.

+*/

+LoggingService::LoggingService(Protocol * proto) :

+	TCFService(proto) {

+	AddCommand("addListener", command_addListener);

+	AddCommand("removeListener", command_removeListener);

+}

+

+LoggingService::~LoggingService(void) {

+}

+

+const char* LoggingService::GetName() {

+	return sServiceName;

+}

+

+const char * LoggingService::GetWindowsConsoleID() {

+	return sWindowsConsoleID;

+}

+

+void LoggingService::command_addListener(const char * token, Channel * c) {

+

+	TCFChannel tcf(c);

+	std::string id = tcf.readString();

+	tcf.readZero();

+	tcf.readComplete();

+	

+	if ( id.compare(sWindowsConsoleID) == 0 )

+		numConsoleListeners++;

+	

+	sendOK(token, c);

+}

+

+

+void LoggingService::command_removeListener(const char * token, Channel * c) {

+	TCFChannel tcf(c);

+	std::string id = tcf.readString();

+	tcf.readZero();

+	tcf.readComplete();

+

+	if ( id.compare(sWindowsConsoleID) == 0 )

+		numConsoleListeners--;

+

+	sendOK(token, c);

+}

+

+void LoggingService::sendOK(const char * token, Channel * c)

+{

+	// Send OK message

+	TCFChannel tcf(c);

+	tcf.writeCompleteReply(token, 0);

+}

+

+

+struct LoggingMessage {

+	Channel* channel;

+	std::string str;

+	const char* consoleID;

+	

+	LoggingMessage(Channel* channel_, const std::string& str_, const char* consoleID_) 

+		: channel(channel_), str(str_), consoleID(consoleID_) 

+	{ }

+};

+

+struct DialogMessage {

+	Channel* channel;

+	IStatus::Severity severity;

+	std::string summary;

+	std::string details;

+

+	DialogMessage(Channel* channel_, const IStatus::Severity severity,

+					const std::string& summary_, const std::string& details_)

+	  : channel(channel_), severity(severity), summary(summary_), details(details_)

+	{ }

+};

+

+static void emit_logging_message(void *data) {

+	LoggingMessage* m = (LoggingMessage*) data;

+	

+	TCFChannel tcf(m->channel);

+

+	// write to the console

+	tcf.writeStringZ("E");

+	tcf.writeStringZ(sServiceName);

+	tcf.writeStringZ("write");

+

+	/* <array of context data> */

+	tcf.writeString(m->consoleID);

+	tcf.writeZero();

+	tcf.writeString(m->str);

+	tcf.writeZero();

+	tcf.writeComplete();

+	

+	delete m;

+}

+

+

+static void emit_logging_message_with_newline(void *data) {

+	LoggingMessage* m = (LoggingMessage*) data;

+

+	TCFChannel tcf(m->channel);

+

+	// write to the console

+	tcf.writeStringZ("E");

+	tcf.writeStringZ(sServiceName);

+	tcf.writeStringZ("writeln");

+

+	/* <array of context data> */

+	tcf.writeString(m->consoleID);

+	tcf.writeZero();

+	tcf.writeString(m->str);

+	tcf.writeZero();

+	tcf.writeComplete();

+

+	delete m;

+}

+

+

+static void emit_dialog_message(void *data) {

+	DialogMessage* m = (DialogMessage*) data;

+

+	TCFChannel tcf(m->channel);

+

+	// write to the console

+	tcf.writeStringZ("E");

+	tcf.writeStringZ(sServiceName);

+	tcf.writeStringZ("dialog");

+

+	/* <array of context data> */

+	tcf.writeString(LoggingService::GetWindowsConsoleID());

+	tcf.writeZero();

+	tcf.writeLong((long)m->severity);

+	tcf.writeZero();

+	tcf.writeString(m->summary);

+	tcf.writeZero();

+	tcf.writeString(m->details);

+	tcf.writeZero();

+	tcf.writeComplete();

+

+	delete m;

+}

+

+

+void LoggingService::WriteLoggingMessage(Channel *channel, const std::string& str, const char *consoleID)

+{

+	const char *windowsConsoleID = GetWindowsConsoleID();

+	// only send messages to the proper console service and when there are more than one listener

+	if ( numConsoleListeners > 0 && strcmp(windowsConsoleID, consoleID) == 0 )

+	{

+		LoggingMessage* message = new LoggingMessage(channel, str, consoleID);

+		post_event(emit_logging_message, message);

+	}

+}

+

+/** since 2.0 */

+void LoggingService::WriteLnLoggingMessage(Channel *channel, const std::string& str, const char *consoleID)

+{

+	const char *windowsConsoleID = GetWindowsConsoleID();

+	// only send messages to the proper console service and when there are more than one listener

+	if ( numConsoleListeners > 0 && strcmp(windowsConsoleID, consoleID) == 0 )

+	{

+		LoggingMessage* message = new LoggingMessage(channel, str, consoleID);

+		post_event(emit_logging_message_with_newline, message);

+	}

+}

+

+/** since 2.0 */

+void LoggingService::Dialog(Channel *channel, IStatus::Severity severity, const std::string& summary, const std::string& details)

+{

+	DialogMessage* message = new DialogMessage(channel, severity, summary, details);

+	post_event(emit_dialog_message, message);

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/PropertyValue.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/PropertyValue.cpp
index 753e9e2..cb06754 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/PropertyValue.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/PropertyValue.cpp
@@ -1,91 +1,118 @@
-/*******************************************************************************
- * Copyright (c) 2010 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. Feb 26, 2010
- *******************************************************************************/
-
-#include <assert.h>
-#include "PropertyValue.h"
-
-PropertyValue::PropertyValue() {}
-
-PropertyValue::PropertyValue(PropertyValue &src) {
-	type = src.type;
-	if (type == PVT_INT)
-		v.v_int = src.v.v_int;
-	else if (type == PVT_ULONG_INT)
-		v.v_int = src.v.v_ulong_int;
-	else if (type == PVT_BOOL)
-		v.v_bool = src.v.v_bool;
-	else if (type == PVT_STRING)
-		v_string = src.v_string;	// copy !
-}
-
-PropertyValue::PropertyValue(int x) {
-	type = PVT_INT;
-	v.v_int = x;
-}
-PropertyValue::PropertyValue(unsigned long int x) {
-	type = PVT_ULONG_INT;
-	v.v_ulong_int = x;
-}
-
-PropertyValue::PropertyValue(bool x) {
-	type = PVT_BOOL;
-	v.v_bool = x;
-}
-
-PropertyValue::PropertyValue(const char *x) {
-	type = PVT_STRING;
-	v_string = x;
-}
-
-PropertyValue::PropertyValue(const std::string& x) {
-	type = PVT_STRING;
-	v_string = x;
-}
-
-PropertyValue::~PropertyValue() {
-}
-
-
-PropertyType PropertyValue::getType() {
-	return type;
-}
-
-int PropertyValue::getIntValue() {
-	return v.v_int;
-}
-
-unsigned long int PropertyValue::getUnsignedLongIntValue() {
-	return v.v_ulong_int;
-}
-
-bool PropertyValue::getBoolValue() {
-	return v.v_bool;
-}
-
-const std::string& PropertyValue::getStringValue() {
-	return v_string;
-}
-
-void PropertyValue::writeToTCFChannel(TCFOutputStream& tcf_stream) {
-	switch (type) {
-	case PVT_INT:
-		tcf_stream.writeLong(v.v_int); break;
-	case PVT_ULONG_INT:
-		tcf_stream.writeULong(v.v_ulong_int); break;
-	case PVT_BOOL:
-		tcf_stream.writeBoolean(v.v_bool); break;
-	case PVT_STRING:
-		tcf_stream.writeString(v_string); break;
-	default:
-		assert(false);
-		break;
-	}
-}
+/*******************************************************************************

+ * Copyright (c) 2010 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. Feb 26, 2010

+ *******************************************************************************/

+

+#include <assert.h>

+#include "PropertyValue.h"

+#include "Logger.h"

+

+PropertyValue::PropertyValue() {

+	type = PVT_UNKNOWN;

+}

+

+PropertyValue::PropertyValue(const PropertyValue &src) {

+	type = src.type;

+	if (type == PVT_INT)

+		v.v_int = src.v.v_int;

+	else if (type == PVT_ULONG_INT)

+		v.v_int = src.v.v_ulong_int;

+	else if (type == PVT_BOOL)

+		v.v_bool = src.v.v_bool;

+	else if (type == PVT_STRING)

+		v_string = src.v_string;	// copy !

+}

+

+PropertyValue::PropertyValue(int x) {

+	type = PVT_INT;

+	v.v_int = x;

+}

+PropertyValue::PropertyValue(unsigned long int x) {

+	type = PVT_ULONG_INT;

+	v.v_ulong_int = x;

+}

+

+PropertyValue::PropertyValue(bool x) {

+	type = PVT_BOOL;

+	v.v_bool = x;

+}

+

+PropertyValue::PropertyValue(const char *x) {

+	type = PVT_STRING;

+	v_string = x;

+}

+

+PropertyValue::PropertyValue(const std::string& x) {

+	type = PVT_STRING;

+	v_string = x;

+}

+

+PropertyType PropertyValue::getType() {

+	return type;

+}

+

+int PropertyValue::getIntValue() {

+	return v.v_int;

+}

+

+unsigned long int PropertyValue::getUnsignedLongIntValue() {

+	return v.v_ulong_int;

+}

+

+bool PropertyValue::getBoolValue() {

+	return v.v_bool;

+}

+

+const std::string& PropertyValue::getStringValue() {

+	return v_string;

+}

+

+void PropertyValue::log() const  {

+	Logger::getLogger().Log(Logger::LOG_NORMAL, "PropertyValue::log type: %d", type);

+	switch (type) {

+	case PVT_INT:

+		Logger::getLogger().Log(Logger::LOG_NORMAL, "PropertyValue::log value: %d", v.v_int); break;

+	case PVT_ULONG_INT:

+		Logger::getLogger().Log(Logger::LOG_NORMAL, "PropertyValue::log value: %X", v.v_ulong_int); break;

+	case PVT_BOOL:

+		Logger::getLogger().Log(Logger::LOG_NORMAL, "PropertyValue::log value: %d", v.v_bool); break;

+	case PVT_STRING:

+		Logger::getLogger().Log(Logger::LOG_NORMAL, "PropertyValue::log value: %s", v_string.c_str()); break;

+	default:

+		assert(false);

+		break;

+	}

+}

+

+void PropertyValue::writeToTCFChannel(TCFOutputStream& tcf_stream) const {

+	switch (type) {

+	case PVT_INT:

+		tcf_stream.writeLong(v.v_int); break;

+	case PVT_ULONG_INT:

+		tcf_stream.writeULong(v.v_ulong_int); break;

+	case PVT_BOOL:

+		tcf_stream.writeBoolean(v.v_bool); break;

+	case PVT_STRING:

+		tcf_stream.writeString(v_string); break;

+	default:

+		assert(false);

+		break;

+	}

+}

+

+void logProperties(Properties& properties)

+{

+	Logger::getLogger().Log(Logger::LOG_NORMAL, "logProperties");

+	for (Properties::const_iterator iter = properties.begin();

+			iter != properties.end(); iter++)

+	{

+		Logger::getLogger().Log(Logger::LOG_NORMAL, "prop id: %s", iter->first.c_str());

+		iter->second.log();

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/PropertyValue.h b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/PropertyValue.h
index a41302b..abe050b 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/PropertyValue.h
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/PropertyValue.h
@@ -1,74 +1,76 @@
-/*******************************************************************************
- * Copyright (c) 2010 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. Feb 26, 2010
- *******************************************************************************/
-
-
-#ifndef PROPERTYVALUE_H_
-#define PROPERTYVALUE_H_
-
-#include <map>
-#include <string>
-#include "TCFOutputStream.h"
-
-enum PropertyType {
-	PVT_UNKNOWN,
-	PVT_INT,
-	PVT_ULONG_INT,
-	PVT_BOOL,
-	PVT_STRING
-};
-
-class PropertyValue {
-public:
-	PropertyValue();
-
-	PropertyValue(PropertyValue &src);
-
-	PropertyValue(int x);
-	
-	PropertyValue(unsigned long int x);
-
-	PropertyValue(bool x);
-
-	PropertyValue(const char *x);
-
-	PropertyValue(const std::string& x);
-
-	~PropertyValue();
-
-	PropertyType getType();
-
-	int getIntValue();
-	unsigned long int getUnsignedLongIntValue();
-
-	bool getBoolValue();
-
-	const std::string& getStringValue();
-
-
-	void writeToTCFChannel(TCFOutputStream& tcf_stream);
-
-private:
-	PropertyType type;
-
-	union {
-		int v_int;		
-		unsigned long int v_ulong_int;
-		bool v_bool;
-	} v;
-
-	// "std::string" is not allowed to be in a union.
-	// But I still prefer std::string to char* for easier memory management.
-	std::string v_string;
-};
-
-typedef std::map<std::string, PropertyValue*>	Properties;
-
-#endif /* PROPERTYVALUE_H_ */
+/*******************************************************************************

+ * Copyright (c) 2010 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. Feb 26, 2010

+ *******************************************************************************/

+

+

+#ifndef PROPERTYVALUE_H_

+#define PROPERTYVALUE_H_

+

+#include <map>

+#include <string>

+#include "TCFOutputStream.h"

+

+enum PropertyType {

+	PVT_UNKNOWN,

+	PVT_INT,

+	PVT_ULONG_INT,

+	PVT_BOOL,

+	PVT_STRING

+};

+

+class PropertyValue {

+public:

+	PropertyValue();

+

+	PropertyValue(const PropertyValue &src);

+

+	PropertyValue(int x);

+	

+	PropertyValue(unsigned long int x);

+

+	PropertyValue(bool x);

+

+	PropertyValue(const char *x);

+

+	PropertyValue(const std::string& x);

+

+	PropertyType getType();

+

+	int getIntValue();

+	unsigned long int getUnsignedLongIntValue();

+

+	bool getBoolValue();

+

+	const std::string& getStringValue();

+

+

+	void writeToTCFChannel(TCFOutputStream& tcf_stream) const;

+

+	void log() const;

+

+private:

+	PropertyType type;

+

+	union {

+		int v_int;		

+		unsigned long int v_ulong_int;

+		bool v_bool;

+	} v;

+

+	// "std::string" is not allowed to be in a union.

+	// But I still prefer std::string to char* for easier memory management.

+	std::string v_string;

+};

+

+typedef std::map<std::string, PropertyValue>	Properties;

+

+void logProperties(Properties& properties);

+

+#endif /* PROPERTYVALUE_H_ */

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RegisterGroupInAgent.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RegisterGroupInAgent.cpp
index 1b480ea..f104196 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RegisterGroupInAgent.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RegisterGroupInAgent.cpp
@@ -1,51 +1,51 @@
-/*******************************************************************************
- * 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  Feb, 2010
- *******************************************************************************/
-
-#include "RegisterGroupInAgent.h"
-#include "ContextManager.h"
-#include "assert.h"
-
-/**
- * Construct a register group context. The internal ID of the context will be
- * auto-generated. <br>
- * The constructed context will be added in debugged context cache. And it
- * will be added as child of the parent context.
- *
- * @param name
- *            name of the register group.
- * @param parentID
- *            internal ID of the parent (usually a register group).
- * @param props
- *            initial properties, cannot be null but can be empty. An
- *            internal copy of it will be made in this object.
- */
-RegisterGroupInAgent::RegisterGroupInAgent(const std::string& name, const ContextID& parentID, Properties& props):
-	Context(parentID, createInternalID(name, parentID), props)
-{
-	SetProperty(PROP_NAME, new PropertyValue(name));
-
-	// We only need to add register as debugged context.
-	ContextManager::addContext(this);
-	Context* parent = ContextManager::findContext(parentID);
-
-	if (parent != NULL)
-		parent->AddChild(this);
-	else
-		// parent is not cached, should not happen.
-		assert (false);
-}
-
-std::string& RegisterGroupInAgent::createInternalID(const std::string& name, const std::string& parentID) {
-	std::string* ret = new std::string(parentID);
-	ret->append(".rg");
-	ret->append(name);
-	return *ret;
-}
+/*******************************************************************************

+ * 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  Feb, 2010

+ *******************************************************************************/

+

+#include "RegisterGroupInAgent.h"

+#include "ContextManager.h"

+#include "assert.h"

+

+/**

+ * Construct a register group context. The internal ID of the context will be

+ * auto-generated. <br>

+ * The constructed context will be added in debugged context cache. And it

+ * will be added as child of the parent context.

+ *

+ * @param name

+ *            name of the register group.

+ * @param parentID

+ *            internal ID of the parent (usually a register group).

+ * @param props

+ *            initial properties, cannot be null but can be empty. An

+ *            internal copy of it will be made in this object.

+ */

+RegisterGroupInAgent::RegisterGroupInAgent(const std::string& name, const ContextID& parentID, Properties& props):

+	Context(parentID, createInternalID(name, parentID), props)

+{

+	SetProperty(PROP_NAME, PropertyValue(name));

+

+	// We only need to add register as debugged context.

+	ContextManager::addContext(this);

+	Context* parent = ContextManager::findContext(parentID);

+

+	if (parent != NULL)

+		parent->AddChild(this);

+	else

+		// parent is not cached, should not happen.

+		assert (false);

+}

+

+std::string& RegisterGroupInAgent::createInternalID(const std::string& name, const std::string& parentID) {

+	std::string* ret = new std::string(parentID);

+	ret->append(".rg");

+	ret->append(name);

+	return *ret;

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RegisterInAgent.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RegisterInAgent.cpp
index 06b054f..6c78943 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RegisterInAgent.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RegisterInAgent.cpp
@@ -1,51 +1,51 @@
-/*******************************************************************************
- * 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  Feb, 2010
- *******************************************************************************/
-
-#include "RegisterInAgent.h"
-#include "ContextManager.h"
-#include "assert.h"
-
-/**
- * Construct a register context. The internal ID of the context will be
- * auto-generated. <br>
- * The constructed context will be added in debugged context cache. And it
- * will be added as child of the parent context.
- *
- * @param name
- *            name of the register group.
- * @param parentID
- *            internal ID of the parent (usually a register group).
- * @param props
- *            initial properties, cannot be null but can be empty. An
- *            internal copy of it will be made in this object.
- */
-RegisterInAgent::RegisterInAgent(const std::string& name, const ContextID& parentID, Properties& props):
-	Context(parentID, createInternalID(name, parentID), props)
-{
-	SetProperty(PROP_NAME, new PropertyValue(name));
-
-	// We only need to add register as debugged context.
-	ContextManager::addContext(this);
-	Context* parent = ContextManager::findContext(parentID);
-
-	if (parent != NULL)
-		parent->AddChild(this);
-	else
-		// parent is not cached, should not happen.
-		assert (false);
-}
-
-std::string& RegisterInAgent::createInternalID(const std::string& name, const std::string& parentID) {
-	std::string* ret = new std::string(parentID);
-	ret->append(".r");
-	ret->append(name);
-	return *ret;
-}
+/*******************************************************************************

+ * 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  Feb, 2010

+ *******************************************************************************/

+

+#include "RegisterInAgent.h"

+#include "ContextManager.h"

+#include "assert.h"

+

+/**

+ * Construct a register context. The internal ID of the context will be

+ * auto-generated. <br>

+ * The constructed context will be added in debugged context cache. And it

+ * will be added as child of the parent context.

+ *

+ * @param name

+ *            name of the register group.

+ * @param parentID

+ *            internal ID of the parent (usually a register group).

+ * @param props

+ *            initial properties, cannot be null but can be empty. An

+ *            internal copy of it will be made in this object.

+ */

+RegisterInAgent::RegisterInAgent(const std::string& name, const ContextID& parentID, Properties& props):

+	Context(parentID, createInternalID(name, parentID), props)

+{

+	SetProperty(PROP_NAME, PropertyValue(name));

+

+	// We only need to add register as debugged context.

+	ContextManager::addContext(this);

+	Context* parent = ContextManager::findContext(parentID);

+

+	if (parent != NULL)

+		parent->AddChild(this);

+	else

+		// parent is not cached, should not happen.

+		assert (false);

+}

+

+std::string& RegisterInAgent::createInternalID(const std::string& name, const std::string& parentID) {

+	std::string* ret = new std::string(parentID);

+	ret->append(".r");

+	ret->append(name);

+	return *ret;

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RunControlContext.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RunControlContext.cpp
index 7350c3a..a64a4a5 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RunControlContext.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/RunControlContext.cpp
@@ -1,38 +1,38 @@
-/*******************************************************************************
- * Copyright (c) 2010 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 "RunControlContext.h"
-#include "AgentUtils.h"
-#include "ProtocolConstants.h"
-
-/*
- * Create a new context. Note the "internalID" should remain the same for the same context
- * (e.g. a process) in OS even when we create "context" object at different times.
- */
-RunControlContext::RunControlContext(ContextOSID osid, const ContextID& parentID, const ContextID& internalID) :
-	Context(parentID, internalID),
-	isDebugging(false)
-{
-	osID = osid;
-
-	initialize();
-}
-
-
-void RunControlContext::initialize()
-{
-	SetProperty(PROP_OS_ID, new PropertyValue(GetOSID()));
-}
-
-ContextOSID RunControlContext::GetOSID() {
-	return osID;
-}
-
-
+/*******************************************************************************

+ * Copyright (c) 2010 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 "RunControlContext.h"

+#include "AgentUtils.h"

+#include "ProtocolConstants.h"

+

+/*

+ * Create a new context. Note the "internalID" should remain the same for the same context

+ * (e.g. a process) in OS even when we create "context" object at different times.

+ */

+RunControlContext::RunControlContext(ContextOSID osid, const ContextID& parentID, const ContextID& internalID) :

+	Context(parentID, internalID),

+	isDebugging(false)

+{

+	osID = osid;

+

+	initialize();

+}

+

+

+void RunControlContext::initialize()

+{

+	SetProperty(PROP_OS_ID, PropertyValue(GetOSID()));

+}

+

+ContextOSID RunControlContext::GetOSID() {

+	return osID;

+}

+

+

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/TCFContext.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/TCFContext.cpp
index 112f029..0450b84 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/TCFContext.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/TCFContext.cpp
@@ -1,88 +1,92 @@
-/*******************************************************************************
- * Copyright (c) 2010 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 "TCFContext.h"
-#include "ContextManager.h"
-#include "AgentUtils.h"
-
-#undef remove
-
-/*
- * Create a new context.
- */
-Context::Context(const ContextID& parentID, const ContextID& internalID) {
-	this->internalID = internalID;
-	this->parentID = parentID;
-
-	initialize();
-
-	// Don't add the context to any context cache here as there are different
-	// caches for different purposes.
-	// See ContextManager for more.
-}
-
-Context::Context(const ContextID& parentID, const ContextID& internalID, Properties& props) {
-	this->internalID = internalID;
-	this->parentID = parentID;
-
-	// Copy the "props" to internal member. We need deep copy.
-	//	properties.insert(props.begin(), props.end());
-	for (Properties::iterator it = props.begin(); it != props.end(); it++) {
-		properties[it->first] = new PropertyValue(*(it->second));
-	}
-
-	initialize();
-}
-
-Context::~Context() {
-	// clear properties, which is a hint to clients who may still
-	// incorrectly hold on to a deallocated context.
-	for (Properties::iterator iter = properties.begin(); iter != properties.end(); iter++)
-		delete iter->second;
-	properties.clear();
-}
-
-void Context::initialize()
-{
-	SetProperty(PROP_ID, new PropertyValue(internalID));
-	SetProperty(PROP_PARENT_ID, new PropertyValue(parentID));
-}
-
-ContextID Context::GetID() {
-	return internalID;
-}
-
-ContextID Context::GetParentID() {
-	return parentID;
-}
-
-Properties& Context::GetProperties() {
-	return properties;
-}
-
-void Context::AddChild(Context* child) {
-	children_.push_back(child);
-}
-
-void Context::RemoveChild(Context* child) {
-	children_.remove(child);
-}
-
-std::list<Context*>& Context::GetChildren() {
-	return children_;
-}
-
-PropertyValue* Context::GetProperty(const std::string& key) {
-	return properties[key];
-}
-
-void Context::SetProperty(const std::string& key, PropertyValue* value) {
-	properties[key] = value;
-}
+/*******************************************************************************

+ * Copyright (c) 2010 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 "TCFContext.h"

+#include "ContextManager.h"

+#include "AgentUtils.h"

+

+#undef remove

+

+/*

+ * Create a new context.

+ */

+Context::Context(const ContextID& parentID, const ContextID& internalID) {

+	this->internalID = internalID;

+	this->parentID = parentID;

+

+	initialize();

+

+	// Don't add the context to any context cache here as there are different

+	// caches for different purposes.

+	// See ContextManager for more.

+}

+

+Context::Context(const ContextID& parentID, const ContextID& internalID, Properties& props) {

+	this->internalID = internalID;

+	this->parentID = parentID;

+	this->properties = props;

+	initialize();

+}

+

+Context::~Context() {

+	properties.clear();

+

+	// delete remaining children.

+	//

+	// This makes a copy.

+	std::list<Context *> remainingKids = GetChildren();

+

+	for (std::list<Context *>::iterator iter = remainingKids.begin();

+		iter != remainingKids.end(); iter++) {

+		Context* kid = *iter;

+		delete ContextManager::findContext(kid->GetID());

+	}

+

+	// Remove this context from global cache.

+	ContextManager::removeContext(GetID());

+}

+

+void Context::initialize()

+{

+	SetProperty(PROP_ID, PropertyValue(internalID));

+	SetProperty(PROP_PARENT_ID, PropertyValue(parentID));

+}

+

+ContextID Context::GetID() {

+	return internalID;

+}

+

+ContextID Context::GetParentID() {

+	return parentID;

+}

+

+Properties& Context::GetProperties() {

+	return properties;

+}

+

+void Context::AddChild(Context* child) {

+	children_.push_back(child);

+}

+

+void Context::RemoveChild(Context* child) {

+	children_.remove(child);

+}

+

+std::list<Context*>& Context::GetChildren() {

+	return children_;

+}

+

+PropertyValue& Context::GetProperty(const std::string& key) {

+	return properties[key];

+}

+

+void Context::SetProperty(const std::string& key, const PropertyValue& value) {

+	properties[key] = value;

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/TCFContext.h b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/TCFContext.h
index 4d3f69e..795e29e 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/TCFContext.h
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/TCFContext.h
@@ -1,94 +1,94 @@
-/*******************************************************************************
- * Copyright (c) 2010 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
- *******************************************************************************/
-#ifndef TCFCONTEXT_H_
-#define TCFCONTEXT_H_
-
-#include <map>
-#include <vector>
-#include <list>
-#include <string>
-
-#include "AgentException.h"
-#include "PropertyValue.h"
-
-#define ROOT_CONTEXT_ID	"root"
-
-/*
- * Properties of context.
- */
-/* From: TCF IRunControl.java.
- */
-#define PROP_ID 			"ID"
-#define PROP_PARENT_ID		"ParentID"
-#define PROP_PROCESS_ID		"ProcessID"
-#define PROP_IS_CONTAINER	"IsContainer"
-#define PROP_HAS_STATE		"HasState"
-#define PROP_CAN_RESUME		"CanResume"	// value: int/long
-#define PROP_CAN_COUNT		"CanCount"
-#define PROP_CAN_SUSPEND	"CanSuspend"
-#define PROP_CAN_TERMINATE	"CanTerminate"
-
-/* From: TCF IProcesses.java
- */
-/** Is the context attached */
-#define PROP_ATTACHED		"Attached"
-/** Process name. Client UI can show this name to a user */
-#define PROP_NAME 			"Name"
-
-
-typedef unsigned long ContextOSID; // ID in the OS
-typedef std::string ContextID; // ID in debugger
-typedef unsigned long ContextAddress; /* Type to represent byted address inside context memory */
-
-/*
- * Context in TCF agent.
- * The context can be a process, thread, register group, register, etc.
- */
-class Context {
-public:
-	Context(const ContextID& parentID, const ContextID& internalID);
-
-	Context(const ContextID& parentID, const ContextID& internalID, Properties& props);
-
-	virtual ~Context();
-
-	/*
-	 * Get unique ID for the instance. This is internal ID, not process ID
-	 * or thread ID in the OS.
-	 */
-	ContextID GetID();
-
-	/* Get internal ID of the process if the context is a thread.
-	 * Return invalid id if the context is a process.
-	 */
-	ContextID GetParentID();
-
-	virtual std::list<Context*>& GetChildren();
-	void AddChild(Context *);
-	void RemoveChild(Context *);
-
-	Properties& GetProperties();
-	PropertyValue* GetProperty(const std::string& key);
-	void SetProperty(const std::string& key, PropertyValue* value);
-
-private:
-	void initialize();
-
-	ContextID internalID;
-	ContextID parentID;
-
-	std::list<Context *> children_;
-	Properties properties;
-};
-
-typedef void ContextAttachCallBack(int, Context *, void *);
-
-#endif /* CONTEXT_H_ */
+/*******************************************************************************

+ * Copyright (c) 2010 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

+ *******************************************************************************/

+#ifndef TCFCONTEXT_H_

+#define TCFCONTEXT_H_

+

+#include <map>

+#include <vector>

+#include <list>

+#include <string>

+

+#include "AgentException.h"

+#include "PropertyValue.h"

+

+#define ROOT_CONTEXT_ID	"root"

+

+/*

+ * Properties of context.

+ */

+/* From: TCF IRunControl.java.

+ */

+#define PROP_ID 			"ID"

+#define PROP_PARENT_ID		"ParentID"

+#define PROP_PROCESS_ID		"ProcessID"

+#define PROP_IS_CONTAINER	"IsContainer"

+#define PROP_HAS_STATE		"HasState"

+#define PROP_CAN_RESUME		"CanResume"	// value: int/long

+#define PROP_CAN_COUNT		"CanCount"

+#define PROP_CAN_SUSPEND	"CanSuspend"

+#define PROP_CAN_TERMINATE	"CanTerminate"

+

+/* From: TCF IProcesses.java

+ */

+/** Is the context attached */

+#define PROP_ATTACHED		"Attached"

+/** Process name. Client UI can show this name to a user */

+#define PROP_NAME 			"Name"

+

+

+typedef unsigned long ContextOSID; // ID in the OS

+typedef std::string ContextID; // ID in debugger

+typedef unsigned long ContextAddress; /* Type to represent byted address inside context memory */

+

+/*

+ * Context in TCF agent.

+ * The context can be a process, thread, register group, register, etc.

+ */

+class Context {

+public:

+	Context(const ContextID& parentID, const ContextID& internalID);

+

+	Context(const ContextID& parentID, const ContextID& internalID, Properties& props);

+

+	virtual ~Context();

+

+	/*

+	 * Get unique ID for the instance. This is internal ID, not process ID

+	 * or thread ID in the OS.

+	 */

+	ContextID GetID();

+

+	/* Get internal ID of the process if the context is a thread.

+	 * Return invalid id if the context is a process.

+	 */

+	ContextID GetParentID();

+

+	virtual std::list<Context*>& GetChildren();

+	void AddChild(Context *);

+	void RemoveChild(Context *);

+

+	Properties& GetProperties();

+	PropertyValue& GetProperty(const std::string& key);

+	void SetProperty(const std::string& key, const PropertyValue& value);

+

+private:

+	void initialize();

+

+	ContextID internalID;

+	ContextID parentID;

+

+	std::list<Context *> children_;

+	Properties properties;

+};

+

+typedef void ContextAttachCallBack(int, Context *, void *);

+

+#endif /* CONTEXT_H_ */

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/RegisterInfoX86.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/RegisterInfoX86.cpp
index 0dc6eb2..8e052b0 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/RegisterInfoX86.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/RegisterInfoX86.cpp
@@ -1,84 +1,84 @@
-/*******************************************************************************
- * Copyright (c) 2010 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. March, 2010
- *******************************************************************************/
-
-#include "RegisterInfoX86.h"
-
-std::list<RegisterGroupInfo*> RegisterInfoX86::sRegisterGroupInfos;
-
-std::list<RegisterGroupInfo*>& RegisterInfoX86::getRegisterGroupInfo() {
-	if (sRegisterGroupInfos.size() == 0)
-		setupRegisterGroupInfo();
-	
-	return sRegisterGroupInfos;
-}
-	
-RegisterInfo* RegisterInfoX86::setupRegister(Properties& commProps, const char* name, const char* role) {
-	Properties props;
-	props[PROP_NAME] = new PropertyValue(name);
-	if (role != NULL)
-		props[PROP_ROLE] = new PropertyValue(role);
-	
-	return new RegisterInfo(commProps, props);
-}
-
-/*
- * Set up static info for x86 basic program execution registers
- * which includes GPR, Segment Registers and EFLAGS & EIP.
- * See "Intel® 64 and IA-32 Architectures Software DeveloperÂ’s Manual" Vol 1.
- */
-RegisterGroupInfo* RegisterInfoX86::setupRegGroup_Basic() {
-	// Properties common to all registers in the group
-	//
-	Properties commonProps;
-
-	commonProps[PROP_SIZE] = new PropertyValue(4);
-	commonProps[PROP_READABLE] = new PropertyValue(true);
-	commonProps[PROP_WRITEABLE] = new PropertyValue(true);
-	// pass value in big-endian string.
-	// Currently EDC host side does not honor this yet, instead
-	// it always assume big-endian....02/28/10
-	commonProps[PROP_BIG_ENDIAN] = new PropertyValue(true);
-	// See TCF RegistersProxy.Context for default values of other properties.
-
-	std::list<RegisterInfo*> regs;
-
-	regs.push_back(setupRegister(commonProps, "EAX", NULL));
-	regs.push_back(setupRegister(commonProps, "ECX", NULL));
-	regs.push_back(setupRegister(commonProps, "EDX", NULL));
-	regs.push_back(setupRegister(commonProps, "EBX", NULL));
-	regs.push_back(setupRegister(commonProps, "ESP", ROLE_SP));
-	regs.push_back(setupRegister(commonProps, "EBP", ROLE_FP));
-	regs.push_back(setupRegister(commonProps, "ESI", NULL));
-	regs.push_back(setupRegister(commonProps, "EDI", NULL));
-	regs.push_back(setupRegister(commonProps, "GS", NULL));
-	regs.push_back(setupRegister(commonProps, "FS", NULL));
-	regs.push_back(setupRegister(commonProps, "ES", NULL));
-	regs.push_back(setupRegister(commonProps, "DS", NULL));
-	regs.push_back(setupRegister(commonProps, "EIP", ROLE_PC));
-	regs.push_back(setupRegister(commonProps, "CS", NULL));
-	regs.push_back(setupRegister(commonProps, "EFL", NULL));
-	regs.push_back(setupRegister(commonProps, "SS", NULL));
-
-	Properties groupProps;
-	groupProps[PROP_NAME] =	new PropertyValue("Basic");
-	groupProps[PROP_DESCRIPTION] = new PropertyValue("Basic Program Execution Registers of x86");
-	groupProps[PROP_ROLE] =	new PropertyValue(ROLE_CORE);
-
-	return new RegisterGroupInfo(groupProps, regs);
-}
-
-/*
- * Set up static info about all registers and register groups supported.
- * Note this should be called only once.
- */
-void RegisterInfoX86::setupRegisterGroupInfo() {
-	sRegisterGroupInfos.push_back(setupRegGroup_Basic());
-}
+/*******************************************************************************

+ * Copyright (c) 2010 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. March, 2010

+ *******************************************************************************/

+

+#include "RegisterInfoX86.h"

+

+std::list<RegisterGroupInfo*> RegisterInfoX86::sRegisterGroupInfos;

+

+std::list<RegisterGroupInfo*>& RegisterInfoX86::getRegisterGroupInfo() {

+	if (sRegisterGroupInfos.size() == 0)

+		setupRegisterGroupInfo();

+	

+	return sRegisterGroupInfos;

+}

+	

+RegisterInfo* RegisterInfoX86::setupRegister(Properties& commProps, const char* name, const char* role) {

+	Properties props;

+	props[PROP_NAME] = PropertyValue(name);

+	if (role != NULL)

+		props[PROP_ROLE] = PropertyValue(role);

+	

+	return new RegisterInfo(commProps, props);

+}

+

+/*

+ * Set up static info for x86 basic program execution registers

+ * which includes GPR, Segment Registers and EFLAGS & EIP.

+ * See "Intel® 64 and IA-32 Architectures Software DeveloperÂ’s Manual" Vol 1.

+ */

+RegisterGroupInfo* RegisterInfoX86::setupRegGroup_Basic() {

+	// Properties common to all registers in the group

+	//

+	Properties commonProps;

+

+	commonProps[PROP_SIZE] = PropertyValue(4);

+	commonProps[PROP_READABLE] = PropertyValue(true);

+	commonProps[PROP_WRITEABLE] = PropertyValue(true);

+	// pass value in big-endian string.

+	// Currently EDC host side does not honor this yet, instead

+	// it always assume big-endian....02/28/10

+	commonProps[PROP_BIG_ENDIAN] = PropertyValue(true);

+	// See TCF RegistersProxy.Context for default values of other properties.

+

+	std::list<RegisterInfo*> regs;

+

+	regs.push_back(setupRegister(commonProps, "EAX", NULL));

+	regs.push_back(setupRegister(commonProps, "ECX", NULL));

+	regs.push_back(setupRegister(commonProps, "EDX", NULL));

+	regs.push_back(setupRegister(commonProps, "EBX", NULL));

+	regs.push_back(setupRegister(commonProps, "ESP", ROLE_SP));

+	regs.push_back(setupRegister(commonProps, "EBP", ROLE_FP));

+	regs.push_back(setupRegister(commonProps, "ESI", NULL));

+	regs.push_back(setupRegister(commonProps, "EDI", NULL));

+	regs.push_back(setupRegister(commonProps, "GS", NULL));

+	regs.push_back(setupRegister(commonProps, "FS", NULL));

+	regs.push_back(setupRegister(commonProps, "ES", NULL));

+	regs.push_back(setupRegister(commonProps, "DS", NULL));

+	regs.push_back(setupRegister(commonProps, "EIP", ROLE_PC));

+	regs.push_back(setupRegister(commonProps, "CS", NULL));

+	regs.push_back(setupRegister(commonProps, "EFL", NULL));

+	regs.push_back(setupRegister(commonProps, "SS", NULL));

+

+	Properties groupProps;

+	groupProps[PROP_NAME] =	PropertyValue("Basic");

+	groupProps[PROP_DESCRIPTION] = PropertyValue("Basic Program Execution Registers of x86");

+	groupProps[PROP_ROLE] =	PropertyValue(ROLE_CORE);

+

+	return new RegisterGroupInfo(groupProps, regs);

+}

+

+/*

+ * Set up static info about all registers and register groups supported.

+ * Note this should be called only once.

+ */

+void RegisterInfoX86::setupRegisterGroupInfo() {

+	sRegisterGroupInfos.push_back(setupRegGroup_Basic());

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/RegistersService.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/RegistersService.cpp
index 84d07ca..bc91758 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/RegistersService.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/RegistersService.cpp
@@ -1,263 +1,263 @@
-/*******************************************************************************
- * Copyright (c) 2010 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 "RegistersService.h"
-
-#include "DebugMonitor.h"
-#include "ContextManager.h"
-#include "EventClientNotifier.h"
-#include "Logger.h"
-#include "TCFChannel.h"
-#include "WinThread.h"
-#include "RegisterInfoX86.h"
-#include "RegisterGroupInAgent.h"
-#include "RegisterInAgent.h"
-#include "AgentUtils.h"
-
-static const char* sServiceName = "Registers";
-
-/**
- * Add register group & register contexts for the give thread context.
- *
- * @param threadContextID
- * @return list of register group contexts.
- */
-static void addRegisterContextsForThread(std::string threadContextID) {
-
-	// Get static register info first.
-	std::list<RegisterGroupInfo *>& rgInfoList = RegisterInfoX86::getRegisterGroupInfo();
-
-	// Now add thread-specific register contexts.
-	//
-	std::list<RegisterGroupInfo *>::iterator it;
-	for (it = rgInfoList.begin(); it != rgInfoList.end(); it++) {
-		Properties& props = (*it)->getProperties();
-
-		// This will be added as child context of the thread.
-		RegisterGroupInAgent* rgContext = new RegisterGroupInAgent(
-			props[PROP_NAME]->getStringValue(), threadContextID, props);
-
-		ContextID rgContextID = rgContext->GetID();
-
-		// Now add register contexts under the register group context
-		//
-		std::list<RegisterInfo*>& regs = (*it)->getRegisters();
-		for (std::list<RegisterInfo*>::iterator it2 = regs.begin(); it2 != regs.end(); it2++) {
-			Properties& regProps = (*it2)->getProperties();
-			new RegisterInAgent(regProps[PROP_NAME]->getStringValue(), rgContextID, regProps);
-		}
-	}
-}
-
-RegistersService::RegistersService(Protocol * proto) :
-	TCFService(proto)
-{
-	AddCommand("getContext", command_get_context);
-	AddCommand("getChildren", command_get_children);
-	AddCommand("get", command_get);
-	AddCommand("set", command_set);
-}
-
-RegistersService::~RegistersService() {
-	// TODO Auto-generated destructor stub
-}
-
-const char* RegistersService::GetName() {
-	return sServiceName;
-}
-
-void RegistersService::command_get_context(const char * token, Channel * c) {
-	LogTrace("RegistersService::command_get_context", "token: %s", token);
-	TCFChannel channel(c);
-	std::string id = channel.readString();
-	channel.readZero();
-	channel.readComplete();
-
-	Context* context = ContextManager::findContext(id);
-
-	if (context == NULL) {
-		// Return an invalid context ID error.
-		channel.writeCompleteReply(token, ERR_INV_CONTEXT, 1);
-		return;
-	}
-	
-	channel.writeReplyHeader(token);
-	channel.writeError(0);
-	EventClientNotifier::WriteContext(*context, channel);
-	channel.writeZero(); // end of context
-	channel.writeComplete();
-
-}
-
-void RegistersService::command_get_children(const char * token, Channel * c) {
-	LogTrace("RunControl::command_get_children", "token: %s", token);
-	TCFChannel channel(c);
-
-	std::string id = channel.readString();
-	channel.readZero();
-	channel.readComplete();
-
-	std::string parentID = id;
-	if (parentID.length() == 0)
-		parentID = "root";
-
-
-	Context* parent = ContextManager::findContext(parentID);
-
-	if (parent == NULL) {
-		// Return an invalid context ID error.
-		channel.writeCompleteReply(token, ERR_INV_CONTEXT, 1);
-		return;
-	}
-	
-	channel.writeReplyHeader(token);
-	
-	channel.writeError(0);
-
-	channel.writeCharacter('[');
-
-	std::list<Context*>& children = parent->GetChildren();
-
-	if (NULL != dynamic_cast<WinThread*>(parent)) {
-		// Currently it's assumed thread only has register group
-		// contexts as children.
-		// And we hook up the register children to a thread only
-		// when requested. This way we don't bother adding registers
-		// for a thread that user does not care about.
-		//  ..................02/11/10
-		if (children.size() == 0) {
-			// Add register contexts for the thread when accessed.
-			addRegisterContextsForThread(parentID);
-			children = parent->GetChildren();
-		}
-
-	}
-	std::list<Context*>::iterator itr;
-	for (itr = children.begin(); itr != children.end(); itr++) {
-		if (itr != children.begin())
-			channel.writeCharacter(',');
-		std::string contextID = ((Context*) *itr)->GetID();
-		channel.writeString(contextID);
-	}
-
-	channel.writeCharacter(']');
-	channel.writeZero(); // end of context
-
-	channel.writeComplete();
-}
-
-/**
- * Find the owner thread context for a register or register group context.
- * Return NULL if not found.
- * @param regCxt register or register group context.
- */
-WinThread* getThreadForRegisterContext(Context* regCxt) {
-	RegisterGroupInAgent* regGroup;
-
-	if (NULL != dynamic_cast<RegisterInAgent *>(regCxt))
-		regGroup = dynamic_cast<RegisterGroupInAgent*>(ContextManager::findContext(regCxt->GetParentID()));
-	else 
-		regGroup = dynamic_cast<RegisterGroupInAgent *>(regCxt);
-
-	if (regGroup == NULL)	 // invalid context
-		return NULL;
-	
-	std::string threadID = regGroup->GetParentID();
-	WinThread* thread = dynamic_cast<WinThread *>(ContextManager::findContext(threadID));
-
-	return thread;
-}
-
-/*
- * register values are passed as hex-string in big-endian
- */
-void RegistersService::command_get(const char * token, Channel * c) {
-	TCFChannel channel(c);
-	std::string regCxtID = channel.readString();
-	channel.readZero();
-	channel.readComplete();
-
-	RegisterInAgent* regCxt = dynamic_cast<RegisterInAgent *>(ContextManager::findContext(regCxtID));
-	WinThread* thread = getThreadForRegisterContext(regCxt);
-
-	if (regCxt == NULL || thread == NULL || !thread->IsDebugging()) {
-		// Return invalid-context-ID error.
-		channel.writeCompleteReply(token, ERR_INV_CONTEXT, 1);
-		return;
-	}
-
-	int regSize = regCxt->GetProperties()[PROP_SIZE]->getIntValue();
-
-	char *valueBuff = thread->GetRegisterValue(
-			regCxt->GetProperties()[PROP_NAME]->getStringValue(),
-			regSize);
-
-	if (valueBuff == NULL) {
-		// no values got. Assuming target is running.
-		channel.writeCompleteReply(token, ERR_IS_RUNNING, 1);
-		return;
-	}
-	
-	// Currently EDC host expects big-endian.
-	AgentUtils::SwapBytes(valueBuff, regSize);
-
-	channel.writeReplyHeader(token);
-	channel.writeError(0);
-
-	channel.writeBinaryData(valueBuff, regSize);
-	delete[] valueBuff;
-
-	channel.writeComplete();
-}
-
-/*
- */
-void RegistersService::command_set(const char * token, Channel * c) {
-	TCFChannel channel(c);
-
-	std::string regCxtID = channel.readString();
-	channel.readZero();
-
-	RegisterInAgent* regCxt = dynamic_cast<RegisterInAgent *>(ContextManager::findContext(regCxtID));
-
-	int regSize = 4;
-	if (regCxt != NULL) {
-		regSize = regCxt->GetProperties()[PROP_SIZE]->getIntValue();
-	}
-	char* val = channel.readBinaryData(regSize);
-	channel.readZero();
-	channel.readComplete();
-
-	WinThread* thread = getThreadForRegisterContext(regCxt);
-
-	if (regCxt == NULL || thread == NULL || !thread->IsDebugging()) {
-		// Return invalid-context-ID error.
-		channel.writeCompleteReply(token, ERR_INV_CONTEXT);
-		return;
-	}
-
-	// Currently EDC host sends big-endian data.
-	AgentUtils::SwapBytes(val, regSize);
-
-	bool ok = thread->SetRegisterValue(
-			regCxt->GetProperties()[PROP_NAME]->getStringValue(),
-			regSize, val);
-
-	delete[] val;
-
-	if (!ok) {
-		// Assuming target is running.
-		channel.writeCompleteReply(token, ERR_IS_RUNNING);
-	}
-	else {
-		channel.writeCompleteReply(token, 0);
-	}
-}
+/*******************************************************************************

+ * Copyright (c) 2010 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 "RegistersService.h"

+

+#include "DebugMonitor.h"

+#include "ContextManager.h"

+#include "EventClientNotifier.h"

+#include "Logger.h"

+#include "TCFChannel.h"

+#include "WinThread.h"

+#include "RegisterInfoX86.h"

+#include "RegisterGroupInAgent.h"

+#include "RegisterInAgent.h"

+#include "AgentUtils.h"

+

+static const char* sServiceName = "Registers";

+

+/**

+ * Add register group & register contexts for the give thread context.

+ *

+ * @param threadContextID

+ * @return list of register group contexts.

+ */

+static void addRegisterContextsForThread(std::string threadContextID) {

+

+	// Get static register info first.

+	std::list<RegisterGroupInfo *>& rgInfoList = RegisterInfoX86::getRegisterGroupInfo();

+

+	// Now add thread-specific register contexts.

+	//

+	std::list<RegisterGroupInfo *>::iterator it;

+	for (it = rgInfoList.begin(); it != rgInfoList.end(); it++) {

+		Properties& props = (*it)->getProperties();

+

+		// This will be added as child context of the thread.

+		RegisterGroupInAgent* rgContext = new RegisterGroupInAgent(

+			props[PROP_NAME].getStringValue(), threadContextID, props);

+

+		ContextID rgContextID = rgContext->GetID();

+

+		// Now add register contexts under the register group context

+		//

+		std::list<RegisterInfo*>& regs = (*it)->getRegisters();

+		for (std::list<RegisterInfo*>::iterator it2 = regs.begin(); it2 != regs.end(); it2++) {

+			Properties& regProps = (*it2)->getProperties();

+			new RegisterInAgent(regProps[PROP_NAME].getStringValue(), rgContextID, regProps);

+		}

+	}

+}

+

+RegistersService::RegistersService(Protocol * proto) :

+	TCFService(proto)

+{

+	AddCommand("getContext", command_get_context);

+	AddCommand("getChildren", command_get_children);

+	AddCommand("get", command_get);

+	AddCommand("set", command_set);

+}

+

+RegistersService::~RegistersService() {

+	// TODO Auto-generated destructor stub

+}

+

+const char* RegistersService::GetName() {

+	return sServiceName;

+}

+

+void RegistersService::command_get_context(const char * token, Channel * c) {

+	LogTrace("RegistersService::command_get_context", "token: %s", token);

+	TCFChannel channel(c);

+	std::string id = channel.readString();

+	channel.readZero();

+	channel.readComplete();

+

+	Context* context = ContextManager::findContext(id);

+

+	if (context == NULL) {

+		// Return an invalid context ID error.

+		channel.writeCompleteReply(token, ERR_INV_CONTEXT, 1);

+		return;

+	}

+	

+	channel.writeReplyHeader(token);

+	channel.writeError(0);

+	EventClientNotifier::WriteContext(*context, channel);

+	channel.writeZero(); // end of context

+	channel.writeComplete();

+

+}

+

+void RegistersService::command_get_children(const char * token, Channel * c) {

+	LogTrace("RunControl::command_get_children", "token: %s", token);

+	TCFChannel channel(c);

+

+	std::string id = channel.readString();

+	channel.readZero();

+	channel.readComplete();

+

+	std::string parentID = id;

+	if (parentID.length() == 0)

+		parentID = "root";

+

+

+	Context* parent = ContextManager::findContext(parentID);

+

+	if (parent == NULL) {

+		// Return an invalid context ID error.

+		channel.writeCompleteReply(token, ERR_INV_CONTEXT, 1);

+		return;

+	}

+	

+	channel.writeReplyHeader(token);

+	

+	channel.writeError(0);

+

+	channel.writeCharacter('[');

+

+	std::list<Context*>& children = parent->GetChildren();

+

+	if (NULL != dynamic_cast<WinThread*>(parent)) {

+		// Currently it's assumed thread only has register group

+		// contexts as children.

+		// And we hook up the register children to a thread only

+		// when requested. This way we don't bother adding registers

+		// for a thread that user does not care about.

+		//  ..................02/11/10

+		if (children.size() == 0) {

+			// Add register contexts for the thread when accessed.

+			addRegisterContextsForThread(parentID);

+			children = parent->GetChildren();

+		}

+

+	}

+	std::list<Context*>::iterator itr;

+	for (itr = children.begin(); itr != children.end(); itr++) {

+		if (itr != children.begin())

+			channel.writeCharacter(',');

+		std::string contextID = ((Context*) *itr)->GetID();

+		channel.writeString(contextID);

+	}

+

+	channel.writeCharacter(']');

+	channel.writeZero(); // end of context

+

+	channel.writeComplete();

+}

+

+/**

+ * Find the owner thread context for a register or register group context.

+ * Return NULL if not found.

+ * @param regCxt register or register group context.

+ */

+WinThread* getThreadForRegisterContext(Context* regCxt) {

+	RegisterGroupInAgent* regGroup;

+

+	if (NULL != dynamic_cast<RegisterInAgent *>(regCxt))

+		regGroup = dynamic_cast<RegisterGroupInAgent*>(ContextManager::findContext(regCxt->GetParentID()));

+	else 

+		regGroup = dynamic_cast<RegisterGroupInAgent *>(regCxt);

+

+	if (regGroup == NULL)	 // invalid context

+		return NULL;

+	

+	std::string threadID = regGroup->GetParentID();

+	WinThread* thread = dynamic_cast<WinThread *>(ContextManager::findContext(threadID));

+

+	return thread;

+}

+

+/*

+ * register values are passed as hex-string in big-endian

+ */

+void RegistersService::command_get(const char * token, Channel * c) {

+	TCFChannel channel(c);

+	std::string regCxtID = channel.readString();

+	channel.readZero();

+	channel.readComplete();

+

+	RegisterInAgent* regCxt = dynamic_cast<RegisterInAgent *>(ContextManager::findContext(regCxtID));

+	WinThread* thread = getThreadForRegisterContext(regCxt);

+

+	if (regCxt == NULL || thread == NULL || !thread->IsDebugging()) {

+		// Return invalid-context-ID error.

+		channel.writeCompleteReply(token, ERR_INV_CONTEXT, 1);

+		return;

+	}

+

+	int regSize = regCxt->GetProperties()[PROP_SIZE].getIntValue();

+

+	char *valueBuff = thread->GetRegisterValue(

+			regCxt->GetProperties()[PROP_NAME].getStringValue(),

+			regSize);

+

+	if (valueBuff == NULL) {

+		// no values got. Assuming target is running.

+		channel.writeCompleteReply(token, ERR_IS_RUNNING, 1);

+		return;

+	}

+	

+	// Currently EDC host expects big-endian.

+	AgentUtils::SwapBytes(valueBuff, regSize);

+

+	channel.writeReplyHeader(token);

+	channel.writeError(0);

+

+	channel.writeBinaryData(valueBuff, regSize);

+	delete[] valueBuff;

+

+	channel.writeComplete();

+}

+

+/*

+ */

+void RegistersService::command_set(const char * token, Channel * c) {

+	TCFChannel channel(c);

+

+	std::string regCxtID = channel.readString();

+	channel.readZero();

+

+	RegisterInAgent* regCxt = dynamic_cast<RegisterInAgent *>(ContextManager::findContext(regCxtID));

+

+	int regSize = 4;

+	if (regCxt != NULL) {

+		regSize = regCxt->GetProperties()[PROP_SIZE].getIntValue();

+	}

+	char* val = channel.readBinaryData(regSize);

+	channel.readZero();

+	channel.readComplete();

+

+	WinThread* thread = getThreadForRegisterContext(regCxt);

+

+	if (regCxt == NULL || thread == NULL || !thread->IsDebugging()) {

+		// Return invalid-context-ID error.

+		channel.writeCompleteReply(token, ERR_INV_CONTEXT);

+		return;

+	}

+

+	// Currently EDC host sends big-endian data.

+	AgentUtils::SwapBytes(val, regSize);

+

+	bool ok = thread->SetRegisterValue(

+			regCxt->GetProperties()[PROP_NAME].getStringValue(),

+			regSize, val);

+

+	delete[] val;

+

+	if (!ok) {

+		// Assuming target is running.

+		channel.writeCompleteReply(token, ERR_IS_RUNNING);

+	}

+	else {

+		channel.writeCompleteReply(token, 0);

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/ResumeContextAction.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/ResumeContextAction.cpp
index 3ee5f1e..421f090 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/ResumeContextAction.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/ResumeContextAction.cpp
@@ -1,79 +1,79 @@
-/*******************************************************************************
- * 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 "ResumeContextAction.h"
-#include "TCFContext.h"
-#include "WinProcess.h"
-#include "WinThread.h"
-#include "WinDebugMonitor.h"
-#include "RunControlService.h"
-#include "BreakpointsService.h"
-
-ResumeContextAction::ResumeContextAction(const AgentActionParams& params,
-		WinProcess& process,
-		WinThread& thread,
-		long resumeMode) : AgentAction(params), process_(process), thread_(thread) {
-	resumeMode_ = resumeMode;
-}
-
-ResumeContextAction::~ResumeContextAction(void) {
-}
-
-/*
- * This will & must be run in debugger monitor thread.
- */
-void ResumeContextAction::Run() {
-	// Single step over a breakpoint (if any) at current PC.
-	//
-	TBreakpoint* bpAtStartAddress = BreakpointsService::FindBreakpointByAddress(process_.GetProcessHandle(), thread_.GetPCAddress());
-	if (bpAtStartAddress) {
-		BreakpointsService::ClearBreak(bpAtStartAddress);
-		thread_.EnableSingleStep();
-	}
-	else if (resumeMode_ == RM_STEP_INTO)
-		thread_.EnableSingleStep();
-
-	ContinueDebugEvent(process_.GetOSID(), thread_.GetOSID(), DBG_CONTINUE);
-
-	// notify host the Resume action is done before
-	// any suspend event is reported.
-	params.reportSuccessForAction();
-
-	if (bpAtStartAddress) {
-		DEBUG_EVENT debugEvent;
-
-		if (WaitForDebugEvent(&debugEvent, 200 /* ms */)) {
-			// Done executing single instruction.
-			BreakpointsService::InsertBreak(bpAtStartAddress);	// restore the bp
-
-			if (debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) {
-				if (resumeMode_ == RM_STEP_INTO)
-					// single-step done, report suspend event to host.
-					process_.GetMonitor()->HandleDebugEvent(debugEvent);
-				else {
-					// other resume modes
-					// Ignore the SINGLE_STEP event, go on to Resume again
-					ContinueDebugEvent(process_.GetOSID(), thread_.GetOSID(), DBG_CONTINUE);
-				}
-			}
-			else {
-				// Other exceptions
-				// Handle the event, say, report to host.
-				process_.GetMonitor()->HandleDebugEvent(debugEvent);
-			}
-		}
-		else {
-			trace(LOG_ALWAYS, "Failed to execute one instruction. Error: %d", GetLastError());
-		}
-	}
-	else {
-		// the event loop of monitor thread would catch and report event.
-	}
-}
+/*******************************************************************************

+ * 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 "ResumeContextAction.h"

+#include "TCFContext.h"

+#include "WinProcess.h"

+#include "WinThread.h"

+#include "WinDebugMonitor.h"

+#include "RunControlService.h"

+#include "BreakpointsService.h"

+

+ResumeContextAction::ResumeContextAction(const AgentActionParams& params,

+		WinProcess& process,

+		WinThread& thread,

+		long resumeMode) : AgentAction(params), process_(process), thread_(thread) {

+	resumeMode_ = resumeMode;

+}

+

+ResumeContextAction::~ResumeContextAction(void) {

+}

+

+/*

+ * This will & must be run in debugger monitor thread.

+ */

+void ResumeContextAction::Run() {

+	// Single step over a breakpoint (if any) at current PC.

+	//

+	TBreakpoint* bpAtStartAddress = BreakpointsService::FindBreakpointByAddress(process_.GetProcessHandle(), thread_.GetPCAddress());

+	if (bpAtStartAddress) {

+		BreakpointsService::ClearBreak(bpAtStartAddress);

+		thread_.EnableSingleStep();

+	}

+	else if (resumeMode_ == RM_STEP_INTO)

+		thread_.EnableSingleStep();

+

+	ContinueDebugEvent(process_.GetOSID(), thread_.GetOSID(), thread_.GetContinueStatus());

+

+	// notify host the Resume action is done before

+	// any suspend event is reported.

+	params.reportSuccessForAction();

+

+	if (bpAtStartAddress) {

+		DEBUG_EVENT debugEvent;

+

+		if (WaitForDebugEvent(&debugEvent, 200 /* ms */)) {

+			// Done executing single instruction.

+			BreakpointsService::InsertBreak(bpAtStartAddress);	// restore the bp

+

+			if (debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) {

+				if (resumeMode_ == RM_STEP_INTO)

+					// single-step done, report suspend event to host.

+					process_.GetMonitor()->HandleDebugEvent(debugEvent);

+				else {

+					// other resume modes

+					// Ignore the SINGLE_STEP event, go on to Resume again

+					ContinueDebugEvent(process_.GetOSID(), thread_.GetOSID(), DBG_CONTINUE);

+				}

+			}

+			else {

+				// Other exceptions

+				// Handle the event, say, report to host.

+				process_.GetMonitor()->HandleDebugEvent(debugEvent);

+			}

+		}

+		else {

+			trace(LOG_ALWAYS, "Failed to execute one instruction. Error: %d", GetLastError());

+		}

+	}

+	else {

+		// the event loop of monitor thread would catch and report event.

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.cpp
new file mode 100644
index 0000000..3606e2c
--- /dev/null
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.cpp
@@ -0,0 +1,283 @@
+/*******************************************************************************

+ * 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 <string>

+#include <vector>

+

+#include "SettingsService.h"

+#include "TCFChannel.h"

+#include "WinDebugMonitor.h"

+

+#define _EXCEPTION_ACCESS_VIOLATION				1 << 0;

+#define _EXCEPTION_ARRAY_BOUNDS_EXCEEDED		1 << 1;

+#define _EXCEPTION_DATATYPE_MISALIGNMENT		1 << 2;

+#define _EXCEPTION_FLT_DENORMAL_OPERAND			1 << 3;

+#define _EXCEPTION_FLT_DIVIDE_BY_ZERO			1 << 4;

+#define _EXCEPTION_FLT_INEXACT_RESULT			1 << 5;

+#define _EXCEPTION_FLT_INVALID_OPERATION		1 << 6;

+#define _EXCEPTION_FLT_OVERFLOW					1 << 7;

+#define _EXCEPTION_FLT_STACK_CHECK				1 << 8;

+#define _EXCEPTION_FLT_UNDERFLOW				1 << 9;

+#define _EXCEPTION_ILLEGAL_INSTRUCTION			1 << 10;

+#define _EXCEPTION_IN_PAGE_ERROR				1 << 11;

+#define _EXCEPTION_INT_DIVIDE_BY_ZERO			1 << 12;

+#define _EXCEPTION_INT_OVERFLOW					1 << 13;

+#define _EXCEPTION_INVALID_DISPOSITION			1 << 14;

+#define _EXCEPTION_NONCONTINUABLE_EXCEPTION		1 << 15;

+#define _EXCEPTION_PRIV_INSTRUCTION				1 << 16;

+#define _EXCEPTION_STACK_OVERFLOW				1 << 17;

+#define _EXCEPTION_GUARD_PAGE					1 << 18;

+#define _EXCEPTION_INVALID_HANDLE				1 << 19;

+#define _DBG_CONTROL_C							1 << 20;

+#define _DBG_CONTROL_BREAK						1 << 21;

+#define _STATUS_NO_MEMORY						1 << 22;

+#define _STATUS_DLL_INIT_FAILED					1 << 23;

+#define _STATUS_DLL_NOT_FOUND					1 << 24;

+#define _STATUS_ENTRYPOINT_NOT_FOUND			1 << 25;

+#define _MS_CPLUS_EXCEPTION						1 << 26;

+

+

+static const char * sServiceName = "Settings";

+

+static std::set<std::string> modulesToDebug;

+static bool allowFilenameMatch;

+static bool enableDebugStringLogging;

+static unsigned long exceptionsBitmask;

+static std::vector<std::string> settingIdArray;

+static std::vector<std::string> executables;

+

+SettingsService::SettingsService(Protocol * proto) :

+	TCFService(proto) {

+	allowFilenameMatch = false;

+	enableDebugStringLogging = true;

+	exceptionsBitmask = 0x00000000L; // no exceptions reported by default

+

+    AddCommand("get", command_get_settings);		// compatibility -- not used

+    AddCommand("getIds", command_get_settings);

+    AddCommand("set", command_set_settings);

+}

+

+SettingsService::~SettingsService(void) {

+}

+

+const char* SettingsService::GetName() {

+	return sServiceName;

+}

+

+void SettingsService::command_get_settings(const char * token, Channel * c) {

+    TCFChannel channel(c);

+

+    channel.readComplete();

+

+    channel.writeReplyHeader(token);

+    channel.writeError(0);

+    write_stream(&c->out,'[');

+    write_stream(&c->out,']');

+

+    channel.writeZero();

+    channel.writeComplete();

+}

+

+static void read_setting_id(InputStream * inp, void * arg)

+{

+    Channel* c = static_cast<Channel*>(arg);

+

+    TCFChannel channel(c);

+    std::string id = channel.readString();

+    settingIdArray.push_back(id);

+}

+

+static void read_executable(InputStream * inp, void * arg)

+{

+    Channel* c = static_cast<Channel*>(arg);

+    TCFChannel channel(c);

+    std::string executable = channel.readString();

+	modulesToDebug.insert(executable);

+}

+

+static void read_setting_value(InputStream * inp, void * arg)

+{

+    Channel* c = static_cast<Channel*>(arg);

+    TCFChannel channel(c);

+

+    // the setting ids are stored in settingIdArray in the same

+    // order as this function gets called with the values.  so just

+    // pop the first one off each time to get the setting id for this value.

+    std::string id = settingIdArray.front();

+    settingIdArray.erase(settingIdArray.begin());

+

+    if (id.compare("addModules") == 0)

+    	json_read_array(inp, read_executable, c);

+    else if (id.compare("allowFilenameMatch") == 0)

+    	allowFilenameMatch = json_read_boolean(inp);

+    else if (id.compare("enableDebugStringLogging") == 0)

+    	enableDebugStringLogging = json_read_boolean(inp);

+    else if (id.compare("exceptionsBitmask") == 0)

+    	exceptionsBitmask = json_read_ulong(inp);

+    else {

+    	// skip unknown setting

+    	json_skip_object(&c->inp);

+    }

+}

+

+void SettingsService::command_set_settings(const char * token, Channel * c) {

+    TCFChannel channel(c);

+    std::string str = channel.readString(); // ignored

+    channel.readZero();

+

+    settingIdArray.clear();

+

+    // read the array of setting ids

+    json_read_array(&c->inp, read_setting_id, c);

+    channel.readZero();

+

+    // now read the array of setting values

+    json_read_array(&c->inp, read_setting_value, c);

+    channel.readZero();

+

+    channel.readComplete();

+

+    channel.writeReplyHeader(token);

+    channel.writeError(0);

+    channel.writeComplete();

+}

+

+std::string getFilenameFromPath(std::string path)

+{

+	std::string::size_type pos = path.find_last_of('\\');

+	if (pos == std::string::npos)

+		return NULL;

+

+	return path.substr(pos + 1, path.size() - pos - 1);

+}

+

+/*

+ * Called when debug session ends. Do any cleanup needed.

+ */

+void SettingsService::debugSessionEnds()

+{

+	modulesToDebug.clear();

+}

+

+bool SettingsService::reportDebugEventForModule(std::string module)

+{

+	// if modulesToDebug is empty then no filter has been set - report all events

+	if (modulesToDebug.empty())

+		return true;

+

+	// first look for an exact, full path match

+	if (modulesToDebug.count(module) > 0)

+		return true;

+

+	if (allowFilenameMatch)

+	{

+		// now just see if the filenames of any of the modules in the filter match the given module

+		std::set<std::string>::iterator itModules;

+		for (itModules = modulesToDebug.begin(); itModules

+				!= modulesToDebug.end(); itModules++)

+		{

+			std::string path = *itModules;

+

+			// get the filename

+			std::string filename = getFilenameFromPath(path);

+

+			// search the module string

+			if (std::string::npos != module.rfind(filename)) {

+				return true;

+			}

+		}

+	}

+

+	// filter is set but the given module is not in the list - don't report

+	return false;

+}

+

+bool SettingsService::reportDebugStringEvents()

+{

+	return enableDebugStringLogging;

+}

+

+bool SettingsService::reportExceptionEvent(const DEBUG_EVENT& debugEvent)

+{

+	switch (debugEvent.u.Exception.ExceptionRecord.ExceptionCode) {

+

+	// as a debugger we always report these

+	case EXCEPTION_SINGLE_STEP:

+	case EXCEPTION_BREAKPOINT:

+		return true;

+

+	// honor the exception settings

+	case EXCEPTION_ACCESS_VIOLATION:

+		return exceptionsBitmask & _EXCEPTION_ACCESS_VIOLATION;

+	case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:

+		return exceptionsBitmask & _EXCEPTION_ARRAY_BOUNDS_EXCEEDED;

+	case EXCEPTION_DATATYPE_MISALIGNMENT:

+		return exceptionsBitmask & _EXCEPTION_DATATYPE_MISALIGNMENT;

+	case EXCEPTION_FLT_DENORMAL_OPERAND:

+		return exceptionsBitmask & _EXCEPTION_FLT_DENORMAL_OPERAND;

+	case EXCEPTION_FLT_DIVIDE_BY_ZERO:

+		return exceptionsBitmask & _EXCEPTION_FLT_DIVIDE_BY_ZERO;

+	case EXCEPTION_FLT_INEXACT_RESULT:

+		return exceptionsBitmask & _EXCEPTION_FLT_INEXACT_RESULT;

+	case EXCEPTION_FLT_INVALID_OPERATION:

+		return exceptionsBitmask & _EXCEPTION_FLT_INVALID_OPERATION;

+	case EXCEPTION_FLT_OVERFLOW:

+		return exceptionsBitmask & _EXCEPTION_FLT_OVERFLOW;

+	case EXCEPTION_FLT_STACK_CHECK:

+		return exceptionsBitmask & _EXCEPTION_FLT_STACK_CHECK;

+	case EXCEPTION_FLT_UNDERFLOW:

+		return exceptionsBitmask & _EXCEPTION_FLT_UNDERFLOW;

+	case EXCEPTION_ILLEGAL_INSTRUCTION:

+		return exceptionsBitmask & _EXCEPTION_ILLEGAL_INSTRUCTION;

+	case EXCEPTION_IN_PAGE_ERROR:

+		return exceptionsBitmask & _EXCEPTION_IN_PAGE_ERROR;

+	case EXCEPTION_INT_DIVIDE_BY_ZERO:

+		return exceptionsBitmask & _EXCEPTION_INT_DIVIDE_BY_ZERO;

+	case EXCEPTION_INT_OVERFLOW:

+		return exceptionsBitmask & _EXCEPTION_INT_OVERFLOW;

+	case EXCEPTION_INVALID_DISPOSITION:

+		return exceptionsBitmask & _EXCEPTION_INVALID_DISPOSITION;

+	case EXCEPTION_NONCONTINUABLE_EXCEPTION:

+		return exceptionsBitmask & _EXCEPTION_NONCONTINUABLE_EXCEPTION;

+	case EXCEPTION_PRIV_INSTRUCTION:

+		return exceptionsBitmask & _EXCEPTION_PRIV_INSTRUCTION;

+	case EXCEPTION_STACK_OVERFLOW:

+		return exceptionsBitmask & _EXCEPTION_STACK_OVERFLOW;

+	case EXCEPTION_GUARD_PAGE:

+		return exceptionsBitmask & _EXCEPTION_GUARD_PAGE;

+	case EXCEPTION_INVALID_HANDLE:

+		return exceptionsBitmask & _EXCEPTION_INVALID_HANDLE;

+	case DBG_CONTROL_C:

+		return exceptionsBitmask & _DBG_CONTROL_C;

+	case DBG_CONTROL_BREAK:

+		return exceptionsBitmask & _DBG_CONTROL_BREAK;

+	case STATUS_NO_MEMORY:

+		return exceptionsBitmask & _STATUS_NO_MEMORY;

+	case STATUS_DLL_INIT_FAILED:

+		return exceptionsBitmask & _STATUS_DLL_INIT_FAILED;

+	case STATUS_DLL_NOT_FOUND:

+		return exceptionsBitmask & _STATUS_DLL_NOT_FOUND;

+	case STATUS_ENTRYPOINT_NOT_FOUND:

+		return exceptionsBitmask & _STATUS_ENTRYPOINT_NOT_FOUND;

+	case MS_CPLUS_EXCEPTION:

+		return exceptionsBitmask & _MS_CPLUS_EXCEPTION;

+

+	default:

+		// it's not one of the typical exceptions and we have no setting for it.

+		// if it's first chance, don't report it.  give it back for the process/os

+		// to handle.  otherwise we'll report it to the debugger.

+	    trace(LOG_ALWAYS, "\t -- first chance:%d, flags:%d", debugEvent.u.Exception.dwFirstChance, debugEvent.u.Exception.ExceptionRecord.ExceptionFlags);

+		if (debugEvent.u.Exception.dwFirstChance)

+			return false;

+	}

+

+	return true;

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.h b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.h
new file mode 100644
index 0000000..151dccb
--- /dev/null
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.h
@@ -0,0 +1,41 @@
+/*******************************************************************************

+ * 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

+ *******************************************************************************/

+#pragma once

+

+#include <set>

+

+#include "TCFService.h"

+

+// These aren't defined in any Windows system headers but can be found here:

+// http://msdn.microsoft.com/en-us/library/cc704588%28v=prot.10%29.aspx

+#define	STATUS_DLL_NOT_FOUND				((unsigned long) 0xC0000135L)

+#define	STATUS_ENTRYPOINT_NOT_FOUND			((unsigned long) 0xC0000139L)

+#define	MS_CPLUS_EXCEPTION					((unsigned long) 0xE06D7363L)

+

+

+struct Protocol;

+struct Channel;

+

+class SettingsService: public TCFService {

+public:

+	SettingsService(Protocol * proto);

+	~SettingsService(void);

+

+	const char* GetName();

+

+	static void command_get_settings(const char *, Channel *);

+	static void command_set_settings(const char *, Channel *);

+

+	static bool reportDebugEventForModule(std::string module);

+	static bool reportDebugStringEvents();

+	static bool reportExceptionEvent(const DEBUG_EVENT& debugEvent);

+	static void debugSessionEnds();

+};

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.cpp
index edec764..1379b35 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.cpp
@@ -1,716 +1,745 @@
-/*******************************************************************************
- * 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 <iostream>
-#include "TCFHeaders.h"
-#include "WinDebugMonitor.h"
-#include "Logger.h"
-#include "WinProcess.h"
-#include "WinThread.h"
-#include "EventClientNotifier.h"
-#include "AgentUtils.h"
-#include "psapi.h"
-#include "AgentAction.h"
-#include "ContextManager.h"
-#include "LoggingService.h"
-
-// These aren't defined in any Windows system headers
-#define	EXCEPTION_DLL_NOT_FOUND				((unsigned long) 0xC0000135L)
-#define	EXCEPTION_ENTRY_NOT_FOUND			((unsigned long) 0xC0000139L)
-#define	EXCEPTION_DLL_INIT_FAIL				((unsigned long) 0xC0000142L)
-#define	EXCEPTION_MS_CPLUS					((unsigned long) 0xE06D7363L)
-#define	EXCEPTION_VDM_EVENT					((unsigned long) 0x40000005L)
-
-#define BUFSIZE 512
-
-
-std::string GetExecutableInfo(HANDLE hFile, unsigned long& baseOfCode, unsigned long& codeSize)
-{
-	codeSize = 0;
-	BOOL bSuccess = FALSE;
-	TCHAR pszFilename[MAX_PATH+1];
-	HANDLE hFileMap;
-	std::wstring path;
-
-	// Get the file size.
-	DWORD dwFileSizeHi = 0;
-	DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);
-
-	if( dwFileSizeLo == 0 && dwFileSizeHi == 0 )
-	{
-		printf("Cannot map a file with a length of zero.\n");
-		return FALSE;
-	}
-
-	// Create a file mapping object.
-	hFileMap = CreateFileMapping(hFile,
-		NULL,
-		PAGE_READONLY,
-		0,
-		1,
-		NULL);
-
-	if (hFileMap)
-	{
-		// Create a file mapping to get the file name.
-		void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
-
-		if (pMem)
-		{
-
-			PIMAGE_DOS_HEADER dosHeader=(PIMAGE_DOS_HEADER )pMem;
-			PIMAGE_NT_HEADERS pNTHeader;
-
-			pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)dosHeader + dosHeader->e_lfanew);
-
-			if ( pNTHeader->Signature == IMAGE_NT_SIGNATURE )
-			{
-
-				PIMAGE_OPTIONAL_HEADER OptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNTHeader->OptionalHeader;
-				codeSize = OptionalHeader->SizeOfCode;
-				baseOfCode = OptionalHeader->BaseOfCode;
-			}
-
-
-			if (GetMappedFileName (GetCurrentProcess(),
-				pMem,
-				pszFilename,
-				MAX_PATH))
-			{
-
-				// Translate path with device name to drive letters.
-				TCHAR szTemp[BUFSIZE];
-				szTemp[0] = '\0';
-
-				if (GetLogicalDriveStrings(BUFSIZE-1, szTemp))
-				{
-					TCHAR szName[MAX_PATH];
-					TCHAR szDrive[3] = TEXT(" :");
-					BOOL bFound = FALSE;
-					TCHAR* p = szTemp;
-
-					do
-					{
-						// Copy the drive letter to the template string
-						*szDrive = *p;
-
-						// Look up each device name
-						if (QueryDosDevice(szDrive, szName, MAX_PATH))
-						{
-							UINT uNameLen = _tcslen(szName);
-
-							if (uNameLen < MAX_PATH)
-							{
-								bFound = _tcsnicmp(pszFilename, szName,
-									uNameLen) == 0;
-
-								if (bFound)
-								{
-									// Reconstruct pszFilename using szTempFile
-									// Replace device path with DOS path
-									TCHAR szTempFile[MAX_PATH];
-
-									snprintf(szTempFile, sizeof(szTempFile),
-										TEXT("%s%s"),
-										szDrive,
-										pszFilename+uNameLen);
-									strncpy(pszFilename, szTempFile, _tcslen(szTempFile));
-									pszFilename[_tcslen(szTempFile)] = 0;
-
-								}
-							}
-						}
-
-						// Go to the next NULL character.
-						while (*p++);
-					} while (!bFound && *p); // end of string
-				}
-			}
-			bSuccess = TRUE;
-			UnmapViewOfFile(pMem);
-		}
-
-		CloseHandle(hFileMap);
-	}
-	return AgentUtils::makeString(pszFilename);
-}
-
-WinDebugMonitor::WinDebugMonitor(const LaunchProcessParams& params) :
-		DebugMonitor(params)
-{
-	memset(&processInfo, 0, sizeof(processInfo));
-
-	handledFirstException_ = false;
-	waitForDebugEvents = true;
-	wfdeWait = 50;
-	monitorThread_ = NULL;
-	isAttach = false;
-}
-
-WinDebugMonitor::WinDebugMonitor(const AttachToProcessParams& params) :
-	DebugMonitor(params)
-{
-	memset(&processInfo, 0, sizeof(processInfo));
-
-	handledFirstException_ = false;
-	waitForDebugEvents = true;
-	wfdeWait = 50;
-	monitorThread_ = NULL;
-	this->processID = (DWORD) params.processID;
-	isAttach = true;
-}
-
-WinDebugMonitor::~WinDebugMonitor(void)
-{
-}
-
-void WinDebugMonitor::LaunchProcess(const LaunchProcessParams& params) throw (AgentException)
-{
-	(new WinDebugMonitor(params))->StartMonitor();
-}
-
-/*
- * Static method. Entry for attaching.
- */
-void WinDebugMonitor::AttachToProcess(const AttachToProcessParams& params) throw (AgentException)
-{
-	(new WinDebugMonitor(params))->StartMonitor();
-}
-
-void WinDebugMonitor::StartDebug() {
-	if (! isAttach)
-		StartProcessForDebug();
-	else
-		AttachToProcessForDebug();
-}
-
-
-void WinDebugMonitor::AttachToProcessForDebug()
-{
-	// Note this is supposed to reply to TCF request ProcessService::Command_Attach().
-
-	if (!DebugActiveProcess(processID))
-	{
-		DWORD err = GetLastError();
-
-		AgentActionReply::postReply(channel, token, set_win32_errno(err));
-	} else {
-		// Allow detach without kill.
-		DebugSetProcessKillOnExit(false);
-
-		// OK
-		AgentActionReply::postReply(channel, token, 0);
-	}
-}
-
-void WinDebugMonitor::StartProcessForDebug()
-{
-	STARTUPINFO			si;
-	memset(&si, 0, sizeof(si));
-    si.cb	       		= sizeof (si);
-	si.dwFlags	       	= STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW;
-	si.wShowWindow     	= SW_SHOWNORMAL;
-
-	TCHAR* argsBuffer = new TCHAR[args.size() + sizeof(TCHAR)];
-
-	strcpy(argsBuffer, args.c_str());
-	std::string exeName = executable;
-
-	LPTSTR workingDirectory = NULL;
-	if (directory.length() > 0)
-	{
-		workingDirectory = (LPTSTR)directory.c_str();
-	}
-
-	char* envBuffer = NULL;
-	std::string envString;
-	if (environment.size() > 0)
-	{
-		std::vector<std::string>::iterator itEnvData;
-		for (itEnvData = environment.begin(); itEnvData
-				!= environment.end(); itEnvData++)
-		{
-			std::string value = *itEnvData;
-			envString += value;
-			envString += char(0);
-		}
-		envString += char(0);
-		envBuffer = new char[envString.length()];
-		memcpy(envBuffer, envString.c_str(), envString.length());
-	}
-
-	if (!CreateProcess(exeName.c_str(), argsBuffer,
-		(LPSECURITY_ATTRIBUTES)NULL,
-		(LPSECURITY_ATTRIBUTES)NULL,
-		FALSE,
-		(GetDebugChildren() ? DEBUG_PROCESS : DEBUG_ONLY_THIS_PROCESS)  | CREATE_NEW_CONSOLE,
-		envBuffer,
-		workingDirectory,				//NULL,
-		(LPSTARTUPINFO)&si,
-		(LPPROCESS_INFORMATION)&processInfo))
-	{
-		DWORD err = GetLastError();
-		std::string msg = "Failed to start process ";
-		msg += '\"';
-		msg += AgentUtils::makeUTF8String(exeName);
-		msg += "\"";
-		err = set_win32_errno(err);
-
-		AgentActionReply::postReply(channel, token, err, 1, new std::string(msg));
-	} else {
-		// AOK	
-		AgentActionReply::postReply(channel, token, 0, 1);
-	}
-
-	delete[] envBuffer;
-	delete[] argsBuffer;
-}
-
-void WinDebugMonitor::CaptureMonitorThread()
-{
-	DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),
-		GetCurrentProcess(),&monitorThread_,
-		0,FALSE,DUPLICATE_SAME_ACCESS);
-}
-
-DWORD WINAPI debuggerMonitorThread(LPVOID param)
-{
-	WinDebugMonitor * dpm = (WinDebugMonitor*)param;
-	
-	try 
-	{
-		dpm->CaptureMonitorThread();
-		dpm->StartDebug();
-		dpm->EventLoop();
-	}
-	catch (const AgentException& e) 
-	{
-		DWORD error = GetLastError();
-		trace(LOG_ALWAYS, "Agent Exception: code=%x: %s", error, e.what());
-	}
-	
-	return 0;
-}
-
-void WinDebugMonitor::Suspend()
-{
-	SuspendThread(monitorThread_);
-}
-
-void WinDebugMonitor::Resume()
-{
-	ResumeThread(monitorThread_);
-}
-
-void WinDebugMonitor::StartMonitor()
-{
-	DWORD threadID = 0;
-	HANDLE startThread = CreateThread(
-		NULL,                   // default security attributes
-		0,                      // use default stack size
-		debuggerMonitorThread,  // thread function name
-		this,   				// argument to thread function
-		0,                      // use default creation flags
-		&threadID);   // returns the thread identifier
-
-	CloseHandle(startThread);
-}
-
-void WinDebugMonitor::EventLoop()
-{
-	DEBUG_EVENT debugEvent;
-
-	while (waitForDebugEvents)
-	{
-		if (WaitForDebugEvent(&debugEvent, wfdeWait))
-			HandleDebugEvent(debugEvent);
-		else {
-			DWORD err = GetLastError();
-			if (err == ERROR_SEM_TIMEOUT || err == 0)
-				HandleNoDebugEvent();
-			else {
-				trace(LOG_ALWAYS, "WinDebugMonitor::EventLoop: error %d", err);
-				waitForDebugEvents = false;
-			}
-		}
-	}
-}
-
-void WinDebugMonitor::Attach(unsigned long pid, ContextAttachCallBack * done, void * data, int selfattach) {
-	// TODO: implement
-}
-
-static const char * win32_debug_event_name(int event) {
-	switch (event) {
-	case CREATE_PROCESS_DEBUG_EVENT:
-		return "CREATE_PROCESS_DEBUG_EVENT";
-	case CREATE_THREAD_DEBUG_EVENT:
-		return "CREATE_THREAD_DEBUG_EVENT";
-	case EXCEPTION_DEBUG_EVENT:
-		return "EXCEPTION_DEBUG_EVENT";
-	case EXIT_PROCESS_DEBUG_EVENT:
-		return "EXIT_PROCESS_DEBUG_EVENT";
-	case EXIT_THREAD_DEBUG_EVENT:
-		return "EXIT_THREAD_DEBUG_EVENT";
-	case LOAD_DLL_DEBUG_EVENT:
-		return "LOAD_DLL_DEBUG_EVENT";
-	case OUTPUT_DEBUG_STRING_EVENT:
-		return "OUTPUT_DEBUG_STRING_EVENT";
-	case UNLOAD_DLL_DEBUG_EVENT:
-		return "UNLOAD_DLL_DEBUG_EVENT";
-	}
-	return "Unknown";
-}
-
-void WinDebugMonitor::HandleDebugEvent(DEBUG_EVENT& debugEvent)
-{
-	LogTrace("DebugProcessMonitor::HandleDebugEvent", "event code: %s", win32_debug_event_name(debugEvent.dwDebugEventCode));
-	switch (debugEvent.dwDebugEventCode)
-	{
-	case EXCEPTION_DEBUG_EVENT:
-		HandleExceptionEvent(debugEvent);
-		break;
-
-	case CREATE_PROCESS_DEBUG_EVENT:
-		HandleProcessCreatedEvent(debugEvent);
-		break;
-
-	case CREATE_THREAD_DEBUG_EVENT:
-		HandleThreadCreatedEvent(debugEvent);
-		break;
-
-	case EXIT_PROCESS_DEBUG_EVENT:
-		HandleProcessExitedEvent(debugEvent);
-		return;
-
-	case EXIT_THREAD_DEBUG_EVENT:
-		HandleThreadExitedEvent(debugEvent);
-		break;
-
-	case LOAD_DLL_DEBUG_EVENT:
-		HandleDLLLoadedEvent(debugEvent);
-		break;
-
-	case UNLOAD_DLL_DEBUG_EVENT:
-		HandleDLLUnloadedEvent(debugEvent);
-		break;
-
-	case OUTPUT_DEBUG_STRING_EVENT:
-		HandleDebugStringEvent(debugEvent);
-		break;
-
-	case RIP_EVENT:
-		HandleSystemDebugErrorEvent(debugEvent);
-		break;
-
-	default:
-		HandleUnknwonDebugEvent(debugEvent);
-		break;
-	}
-}
-
-void WinDebugMonitor::HandleNoDebugEvent()
-{
-	while (!actions_.empty())
-	{
-		AgentAction* action = actions_.front();
-		actions_.pop();
-		action->Run();
-		delete action;
-	}
-}
-
-std::string WinDebugMonitor::GetDebugExceptionDescription(const EXCEPTION_DEBUG_INFO& exceptionInfo) {
-	DWORD code = exceptionInfo.ExceptionRecord.ExceptionCode;
-
-	const char* base = "Exception";
-	std::string detail;
-
-	switch (code) {
-	case EXCEPTION_SINGLE_STEP:
-		base = "Step";
-		break;
-	case EXCEPTION_BREAKPOINT:
-		base = "Breakpoint";
-		break;
-
-	case EXCEPTION_ACCESS_VIOLATION:
-		base = "Access violation";
-		detail = " at 0x" + AgentUtils::IntToHexString(exceptionInfo.ExceptionRecord.ExceptionInformation[1]);
-		break;
-	case DBG_CONTROL_C:
-		base = "Control-C";
-		break;
-	case DBG_CONTROL_BREAK:
-		base = "Control-Break";
-		break;
-	case STATUS_DATATYPE_MISALIGNMENT:
-		base = "Datatype misalignment";
-		break;
-	case STATUS_IN_PAGE_ERROR:
-		base = "Virtual memory paging error";
-		break;
-	case STATUS_NO_MEMORY:
-		base = "Out of memory";
-		break;
-	case STATUS_ILLEGAL_INSTRUCTION:
-		base = "Illegal instruction";
-		break;
-	case STATUS_NONCONTINUABLE_EXCEPTION:
-		base =  "Noncontinuable exception";
-		break;
-	case STATUS_INVALID_DISPOSITION:
-		base =  "Invalid disposition";
-		break;
-	case STATUS_ARRAY_BOUNDS_EXCEEDED:
-		base = "Array bounds exceeded";
-		break;
-	case STATUS_FLOAT_DENORMAL_OPERAND:
-		base = "Floating point denormal operand";
-		break;
-	case STATUS_FLOAT_DIVIDE_BY_ZERO:
-		base =  "Floating point divide by zero";
-		break;
-	case STATUS_FLOAT_INEXACT_RESULT:
-		base =  "Floating point inexact result";
-		break;
-	case STATUS_FLOAT_INVALID_OPERATION:
-		base =  "Floating point invalid operation";
-		break;
-	case STATUS_FLOAT_STACK_CHECK:
-		base = "Floating point stack check";
-		break;
-	case STATUS_FLOAT_OVERFLOW:
-		base = "Floating point overflow";
-		break;
-	case STATUS_FLOAT_UNDERFLOW:
-		base = "Floating point underflow";
-		break;
-	case STATUS_INTEGER_DIVIDE_BY_ZERO:
-		base = "Integer divide by zero";
-		break;
-	case STATUS_INTEGER_OVERFLOW:
-		base = "Integer overflow";
-		break;
-	case STATUS_PRIVILEGED_INSTRUCTION:
-		base = "Privileged instruction";
-		break;
-	case STATUS_STACK_OVERFLOW:
-		base = "Stack overflow";
-		break;
-	case EXCEPTION_DLL_NOT_FOUND:
-		base = "DLL not found";
-		// TODO: find out how to determine which DLL it was...
-		break;
-	case EXCEPTION_DLL_INIT_FAIL:
-		base = "DLL initialization failed";
-		break;
-	case EXCEPTION_ENTRY_NOT_FOUND:
-		base = "Entry point not found";
-		break;
-	case EXCEPTION_MS_CPLUS:
-		base = "C++ exception";
-		break;
-
-	case RPC_S_UNKNOWN_IF:
-		base = "RPC unknown interface";
-		break;
-	case RPC_S_SERVER_UNAVAILABLE:
-		base = "RPC server unavailable";
-		break;
-	case EXCEPTION_VDM_EVENT:
-		base = "VDM event";
-		break;
-	}
-
-	if (detail.size() > 0) {
-		return std::string(base) + detail;
-	}
-	return base;
-}
-
-void WinDebugMonitor::HandleExceptionEvent(DEBUG_EVENT& debugEvent)
-{
-	LogTrace("DebugProcessMonitor::HandleExceptionEvent", "event code: %s",
-			GetDebugExceptionDescription(debugEvent.u.Exception).c_str());
-
-	HandleException(debugEvent);
-
-}
-
-void WinDebugMonitor::HandleProcessCreatedEvent(DEBUG_EVENT& debugEvent)
-{
-	WinProcess* process = new WinProcess(this, debugEvent);
-	WinThread* thread = new WinThread(*process, debugEvent);
-
-	process->SetDebugging(true);
-	thread->SetDebugging(true);
-
-	// record in our cache
-	ContextManager::addContext(process);
-	ContextManager::addContext(thread);
-
-	// Notify host
-	EventClientNotifier::SendContextAdded(process);
-	EventClientNotifier::SendContextAdded(thread);
-
-	unsigned long codeSize = 0;
-	unsigned long baseOfCode = 0;
-	std::string imageName = GetExecutableInfo(debugEvent.u.CreateProcessInfo.hFile, baseOfCode, codeSize);
-	thread->HandleExecutableEvent(true, imageName, (unsigned long)debugEvent.u.CreateProcessInfo.lpBaseOfImage, codeSize + baseOfCode);
-	CloseHandle(debugEvent.u.CreateProcessInfo.hFile);
-}
-
-void WinDebugMonitor::HandleThreadCreatedEvent(DEBUG_EVENT& debugEvent)
-{
-	WinProcess* process = WinProcess::GetProcessByID(debugEvent.dwProcessId);
-	if (process) {
-		WinThread* thread = new WinThread(*process, debugEvent);
-		thread->SetDebugging(true);
-		ContextManager::addContext(thread);
-		EventClientNotifier::SendContextAdded(thread);
-	} else {
-		assert(false);
-	}
-
-	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
-}
-
-void WinDebugMonitor::HandleProcessExitedEvent(DEBUG_EVENT& debugEvent)
-{
-	WinProcess* process = WinProcess::GetProcessByID(debugEvent.dwProcessId);
-	if (process) {
-		ContextManager::removeContext(process->GetID());
-		EventClientNotifier::SendContextRemoved(process, true);
-	} else {
-		assert(false);
-	}
-	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
-}
-
-void WinDebugMonitor::HandleThreadExitedEvent(DEBUG_EVENT& debugEvent)
-{
-	WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);
-	if (thread) {
-		ContextManager::removeContext(thread->GetID());
-		EventClientNotifier::SendContextRemoved(thread, true);
-	} else {
-		assert(false);
-	}
-	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
-}
-
-bool WinDebugMonitor::ShouldDebugFirstChance(const DEBUG_EVENT& debugEvent) {
-	if (debugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) {
-		const EXCEPTION_DEBUG_INFO& info = debugEvent.u.Exception;
-		if (!info.dwFirstChance)
-			return false;
-		return info.ExceptionRecord.ExceptionCode == EXCEPTION_DLL_NOT_FOUND;
-	}
-	return false;
-}
-
-bool WinDebugMonitor::ShouldReportException(const DEBUG_EVENT& debugEvent)
-{
-	if (debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_MS_CPLUS)
-		return false;
-	return true;
-}
-
-void WinDebugMonitor::HandleException(DEBUG_EVENT& debugEvent)
-{
-	WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);
-	if (!thread)
-		assert(false);
-	if (thread && (handledFirstException_ || isAttach || ShouldDebugFirstChance(debugEvent)) &&
-			ShouldReportException(debugEvent))
-		thread->HandleException(debugEvent);
-	else
-		ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
-	handledFirstException_ = true;
-}
-
-void WinDebugMonitor::HandleDLLLoadedEvent(DEBUG_EVENT& debugEvent)
-{
-	unsigned long codeSize = 0;
-	unsigned long baseOfCode = 0;
-	std::string moduleName = GetExecutableInfo(debugEvent.u.LoadDll.hFile, baseOfCode, codeSize);
-
-	LogTrace("DebugProcessMonitor::HandleDLLLoadedEvent", "Base address: %8.8x %s", debugEvent.u.LoadDll.lpBaseOfDll, moduleName.c_str());
-	WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);
-	if (thread) {
-		thread->HandleExecutableEvent(true, moduleName, (unsigned long)debugEvent.u.LoadDll.lpBaseOfDll, codeSize);
-	}
-}
-
-void WinDebugMonitor::HandleDLLUnloadedEvent(DEBUG_EVENT& debugEvent)
-{
-	WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);
-	if (thread) {
-		thread->HandleExecutableEvent(false, "", (unsigned long)debugEvent.u.CreateProcessInfo.lpBaseOfImage, 0);
-	}
-	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
-}
-
-void WinDebugMonitor::HandleDebugStringEvent(DEBUG_EVENT& debugEvent)
-{
-	WinProcess* process = WinProcess::GetProcessByID(debugEvent.dwProcessId);
-
-	if (debugEvent.u.DebugString.fUnicode == 0)
-	{
-		int debugStringLength = debugEvent.u.DebugString.nDebugStringLength;
-		char* debugStringBuffer = new char[debugStringLength + 1];
-		ReadProcessMemory(process->GetProcessHandle(), debugEvent.u.DebugString.lpDebugStringData, debugStringBuffer,
-				debugStringLength,NULL);
-		debugStringBuffer[debugStringLength] = 0;
-
-		// convert from ansi to utf-8
-		wchar_t* wideChars = new wchar_t[debugStringLength];
-
-		// Covert to Unicode.
-		if (MultiByteToWideChar(CP_ACP, 0, debugStringBuffer, debugStringLength,
-				wideChars, debugStringLength) != 0)
-		{
-		    int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideChars, debugStringLength, NULL, 0, NULL, NULL);
-		    std::string strTo( size_needed, 0 );
-		    WideCharToMultiByte(CP_UTF8, 0, wideChars, debugStringLength, &strTo[0], size_needed, NULL, NULL);
-			// write console data, if console
-			LoggingService::WriteLoggingMessage(channel, strTo, LoggingService::GetWindowsConsoleID());
-			LogTrace("DebugProcessMonitor::HandleDebugStringEvent", "%s", strTo.c_str());
-		}
-
-		delete[] wideChars;
-		delete[] debugStringBuffer;
-	}
-
-	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
-}
-
-void WinDebugMonitor::HandleSystemDebugErrorEvent(DEBUG_EVENT& debugEvent)
-{
-	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
-}
-
-void WinDebugMonitor::HandleUnknwonDebugEvent(DEBUG_EVENT& debugEvent)
-{
-	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
-}
-
-void WinDebugMonitor::SetProcess(WinProcess* process)
-{
-	process_ = process;
-}
-
-void WinDebugMonitor::PostAction(AgentAction* action)
-{
-	actions_.push(action);
-}
-
+/*******************************************************************************

+ * 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 <iostream>

+#include "TCFHeaders.h"

+#include "WinDebugMonitor.h"

+#include "Logger.h"

+#include "WinProcess.h"

+#include "WinThread.h"

+#include "EventClientNotifier.h"

+#include "AgentUtils.h"

+#include "psapi.h"

+#include "AgentAction.h"

+#include "ContextManager.h"

+#include "LoggingService.h"

+#include "SettingsService.h"

+

+

+#define BUFSIZE 512

+

+

+std::string GetExecutableInfo(HANDLE hFile, unsigned long& baseOfCode, unsigned long& codeSize)

+{

+	codeSize = 0;

+	BOOL bSuccess = FALSE;

+	TCHAR pszFilename[MAX_PATH+1];

+	HANDLE hFileMap;

+	std::wstring path;

+

+	// Get the file size.

+	DWORD dwFileSizeHi = 0;

+	DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);

+

+	if( dwFileSizeLo == 0 && dwFileSizeHi == 0 )

+	{

+		printf("Cannot map a file with a length of zero.\n");

+		return FALSE;

+	}

+

+	// Create a file mapping object.

+	hFileMap = CreateFileMapping(hFile,

+		NULL,

+		PAGE_READONLY,

+		0,

+		1,

+		NULL);

+

+	if (hFileMap)

+	{

+		// Create a file mapping to get the file name.

+		void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);

+

+		if (pMem)

+		{

+

+			PIMAGE_DOS_HEADER dosHeader=(PIMAGE_DOS_HEADER )pMem;

+			PIMAGE_NT_HEADERS pNTHeader;

+

+			pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)dosHeader + dosHeader->e_lfanew);

+

+			if ( pNTHeader->Signature == IMAGE_NT_SIGNATURE )

+			{

+

+				PIMAGE_OPTIONAL_HEADER OptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNTHeader->OptionalHeader;

+				codeSize = OptionalHeader->SizeOfCode;

+				baseOfCode = OptionalHeader->BaseOfCode;

+			}

+

+

+			if (GetMappedFileName (GetCurrentProcess(),

+				pMem,

+				pszFilename,

+				MAX_PATH))

+			{

+

+				// Translate path with device name to drive letters.

+				TCHAR szTemp[BUFSIZE];

+				szTemp[0] = '\0';

+

+				if (GetLogicalDriveStrings(BUFSIZE-1, szTemp))

+				{

+					TCHAR szName[MAX_PATH];

+					TCHAR szDrive[3] = TEXT(" :");

+					BOOL bFound = FALSE;

+					TCHAR* p = szTemp;

+

+					do

+					{

+						// Copy the drive letter to the template string

+						*szDrive = *p;

+

+						// Look up each device name

+						if (QueryDosDevice(szDrive, szName, MAX_PATH))

+						{

+							UINT uNameLen = _tcslen(szName);

+

+							if (uNameLen < MAX_PATH)

+							{

+								bFound = _tcsnicmp(pszFilename, szName,

+									uNameLen) == 0;

+

+								if (bFound)

+								{

+									// Reconstruct pszFilename using szTempFile

+									// Replace device path with DOS path

+									TCHAR szTempFile[MAX_PATH];

+

+									snprintf(szTempFile, sizeof(szTempFile),

+										TEXT("%s%s"),

+										szDrive,

+										pszFilename+uNameLen);

+									strncpy(pszFilename, szTempFile, _tcslen(szTempFile));

+									pszFilename[_tcslen(szTempFile)] = 0;

+

+								}

+							}

+						}

+

+						// Go to the next NULL character.

+						while (*p++);

+					} while (!bFound && *p); // end of string

+				}

+			}

+			bSuccess = TRUE;

+			UnmapViewOfFile(pMem);

+		}

+

+		CloseHandle(hFileMap);

+	}

+	return AgentUtils::makeString(pszFilename);

+}

+

+WinDebugMonitor::WinDebugMonitor(const LaunchProcessParams& params) :

+		DebugMonitor(params)

+{

+	memset(&processInfo, 0, sizeof(processInfo));

+

+	handledInitialDebugBreakpoint = false;

+	waitForDebugEvents = true;

+	wfdeWait = 50;

+	monitorThread_ = NULL;

+	isAttach = false;

+}

+

+WinDebugMonitor::WinDebugMonitor(const AttachToProcessParams& params) :

+	DebugMonitor(params)

+{

+	memset(&processInfo, 0, sizeof(processInfo));

+

+	// TODO don't think the NTDLL!DbgBreakPoint applies when attaching but need to test.  if you hit that breakpoint

+	// right after attaching then this needs to be change to false

+	handledInitialDebugBreakpoint = true;

+	waitForDebugEvents = true;

+	wfdeWait = 50;

+	monitorThread_ = NULL;

+	this->processID = (DWORD) params.processID;

+	isAttach = true;

+}

+

+WinDebugMonitor::~WinDebugMonitor(void)

+{

+}

+

+void WinDebugMonitor::LaunchProcess(const LaunchProcessParams& params) throw (AgentException)

+{

+	(new WinDebugMonitor(params))->StartMonitor();

+}

+

+/*

+ * Static method. Entry for attaching.

+ */

+void WinDebugMonitor::AttachToProcess(const AttachToProcessParams& params) throw (AgentException)

+{

+	(new WinDebugMonitor(params))->StartMonitor();

+}

+

+void WinDebugMonitor::StartDebug() {

+	if (! isAttach)

+		StartProcessForDebug();

+	else

+		AttachToProcessForDebug();

+}

+

+

+void WinDebugMonitor::AttachToProcessForDebug()

+{

+	// Note this is supposed to reply to TCF request ProcessService::Command_Attach().

+

+	if (!DebugActiveProcess(processID))

+	{

+		DWORD err = GetLastError();

+

+		AgentActionReply::postReply(channel, token, set_win32_errno(err));

+	} else {

+		// Allow detach without kill.

+		DebugSetProcessKillOnExit(false);

+

+		// OK

+		AgentActionReply::postReply(channel, token, 0);

+	}

+}

+

+void WinDebugMonitor::StartProcessForDebug()

+{

+	STARTUPINFO			si;

+	memset(&si, 0, sizeof(si));

+    si.cb	       		= sizeof (si);

+	si.dwFlags	       	= STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW;

+	si.wShowWindow     	= SW_SHOWNORMAL;

+

+	TCHAR* argsBuffer = new TCHAR[args.size() + sizeof(TCHAR)];

+

+	strcpy(argsBuffer, args.c_str());

+	std::string exeName = executable;

+

+	LPTSTR workingDirectory = NULL;

+	if (directory.length() > 0)

+	{

+		workingDirectory = (LPTSTR)directory.c_str();

+	}

+

+	char* envBuffer = NULL;

+	std::string envString;

+	if (environment.size() > 0)

+	{

+		std::vector<std::string>::iterator itEnvData;

+		for (itEnvData = environment.begin(); itEnvData

+				!= environment.end(); itEnvData++)

+		{

+			std::string value = *itEnvData;

+			envString += value;

+			envString += char(0);

+		}

+		envString += char(0);

+		envBuffer = new char[envString.length()];

+		memcpy(envBuffer, envString.c_str(), envString.length());

+	}

+

+	if (!CreateProcess(exeName.c_str(), argsBuffer,

+		(LPSECURITY_ATTRIBUTES)NULL,

+		(LPSECURITY_ATTRIBUTES)NULL,

+		FALSE,

+		(GetDebugChildren() ? DEBUG_PROCESS : DEBUG_ONLY_THIS_PROCESS)  | CREATE_NEW_CONSOLE,

+		envBuffer,

+		workingDirectory,				//NULL,

+		(LPSTARTUPINFO)&si,

+		(LPPROCESS_INFORMATION)&processInfo))

+	{

+		DWORD err = GetLastError();

+		std::string msg = "Failed to start process ";

+		msg += '\"';

+		msg += AgentUtils::makeUTF8String(exeName);

+		msg += "\"";

+		err = set_win32_errno(err);

+

+		AgentActionReply::postReply(channel, token, err, 1, new std::string(msg));

+	} else {

+		// AOK	

+		AgentActionReply::postReply(channel, token, 0, 1);

+

+		processID = processInfo.dwProcessId;

+	}

+

+	delete[] envBuffer;

+	delete[] argsBuffer;

+}

+

+void WinDebugMonitor::CaptureMonitorThread()

+{

+	DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),

+		GetCurrentProcess(),&monitorThread_,

+		0,FALSE,DUPLICATE_SAME_ACCESS);

+}

+

+DWORD WINAPI debuggerMonitorThread(LPVOID param)

+{

+	WinDebugMonitor * dpm = (WinDebugMonitor*)param;

+	

+	try 

+	{

+		dpm->CaptureMonitorThread();

+		dpm->StartDebug();

+		dpm->EventLoop();

+	}

+	catch (const AgentException& e) 

+	{

+		DWORD error = GetLastError();

+		trace(LOG_ALWAYS, "Agent Exception: code=%x: %s", error, e.what());

+	}

+	

+	return 0;

+}

+

+void WinDebugMonitor::Suspend()

+{

+	SuspendThread(monitorThread_);

+}

+

+void WinDebugMonitor::Resume()

+{

+	ResumeThread(monitorThread_);

+}

+

+void WinDebugMonitor::StartMonitor()

+{

+	DWORD threadID = 0;

+	HANDLE startThread = CreateThread(

+		NULL,                   // default security attributes

+		0,                      // use default stack size

+		debuggerMonitorThread,  // thread function name

+		this,   				// argument to thread function

+		0,                      // use default creation flags

+		&threadID);   // returns the thread identifier

+

+	CloseHandle(startThread);

+}

+

+void WinDebugMonitor::EventLoop()

+{

+	DEBUG_EVENT debugEvent;

+

+	while (waitForDebugEvents)

+	{

+		if (WaitForDebugEvent(&debugEvent, wfdeWait))

+			HandleDebugEvent(debugEvent);

+		else {

+			DWORD err = GetLastError();

+			if (err == ERROR_SEM_TIMEOUT || err == 0)

+				HandleNoDebugEvent();

+			else {

+				trace(LOG_ALWAYS, "WinDebugMonitor::EventLoop: error %d", err);

+				waitForDebugEvents = false;

+			}

+		}

+	}

+

+	trace(LOG_CONTEXT, "Monitor thread for process %d has exited. \n", processID);

+}

+

+void WinDebugMonitor::Attach(unsigned long pid, ContextAttachCallBack * done, void * data, int selfattach) {

+	// TODO: implement

+}

+

+static const char * win32_debug_event_name(int event) {

+	switch (event) {

+	case CREATE_PROCESS_DEBUG_EVENT:

+		return "CREATE_PROCESS_DEBUG_EVENT";

+	case CREATE_THREAD_DEBUG_EVENT:

+		return "CREATE_THREAD_DEBUG_EVENT";

+	case EXCEPTION_DEBUG_EVENT:

+		return "EXCEPTION_DEBUG_EVENT";

+	case EXIT_PROCESS_DEBUG_EVENT:

+		return "EXIT_PROCESS_DEBUG_EVENT";

+	case EXIT_THREAD_DEBUG_EVENT:

+		return "EXIT_THREAD_DEBUG_EVENT";

+	case LOAD_DLL_DEBUG_EVENT:

+		return "LOAD_DLL_DEBUG_EVENT";

+	case OUTPUT_DEBUG_STRING_EVENT:

+		return "OUTPUT_DEBUG_STRING_EVENT";

+	case UNLOAD_DLL_DEBUG_EVENT:

+		return "UNLOAD_DLL_DEBUG_EVENT";

+	}

+	return "Unknown";

+}

+

+void WinDebugMonitor::HandleDebugEvent(DEBUG_EVENT& debugEvent)

+{

+	LogTrace("DebugProcessMonitor::HandleDebugEvent", "event code: %s", win32_debug_event_name(debugEvent.dwDebugEventCode));

+	switch (debugEvent.dwDebugEventCode)

+	{

+	case EXCEPTION_DEBUG_EVENT:

+		HandleExceptionEvent(debugEvent);

+		break;

+

+	case CREATE_PROCESS_DEBUG_EVENT:

+		HandleProcessCreatedEvent(debugEvent);

+		break;

+

+	case CREATE_THREAD_DEBUG_EVENT:

+		HandleThreadCreatedEvent(debugEvent);

+		break;

+

+	case EXIT_PROCESS_DEBUG_EVENT:

+		HandleProcessExitedEvent(debugEvent);

+		return;

+

+	case EXIT_THREAD_DEBUG_EVENT:

+		HandleThreadExitedEvent(debugEvent);

+		break;

+

+	case LOAD_DLL_DEBUG_EVENT:

+		HandleDLLLoadedEvent(debugEvent);

+		break;

+

+	case UNLOAD_DLL_DEBUG_EVENT:

+		HandleDLLUnloadedEvent(debugEvent);

+		break;

+

+	case OUTPUT_DEBUG_STRING_EVENT:

+		HandleDebugStringEvent(debugEvent);

+		break;

+

+	case RIP_EVENT:

+		HandleSystemDebugErrorEvent(debugEvent);

+		break;

+

+	default:

+		HandleUnknwonDebugEvent(debugEvent);

+		break;

+	}

+}

+

+void WinDebugMonitor::HandleNoDebugEvent()

+{

+	while (!actions_.empty())

+	{

+		AgentAction* action = actions_.front();

+		actions_.pop();

+		action->Run();

+		delete action;

+	}

+}

+

+std::string WinDebugMonitor::GetDebugExceptionDescription(const EXCEPTION_DEBUG_INFO& exceptionInfo) {

+	DWORD code = exceptionInfo.ExceptionRecord.ExceptionCode;

+

+	const char* base = "Unknown Exception";

+	std::string detail;

+

+	switch (code) {

+	case EXCEPTION_SINGLE_STEP:

+		base = "Step";

+		break;

+	case EXCEPTION_BREAKPOINT:

+		base = "Breakpoint";

+		break;

+

+	case EXCEPTION_ACCESS_VIOLATION:

+		base = "Access violation";

+		detail = " at 0x" + AgentUtils::IntToHexString(exceptionInfo.ExceptionRecord.ExceptionInformation[1]);

+		break;

+	case DBG_CONTROL_C:

+		base = "Control-C";

+		break;

+	case DBG_CONTROL_BREAK:

+		base = "Control-Break";

+		break;

+	case STATUS_DATATYPE_MISALIGNMENT:

+		base = "Datatype misalignment";

+		break;

+	case STATUS_IN_PAGE_ERROR:

+		base = "Virtual memory paging error";

+		break;

+	case STATUS_NO_MEMORY:

+		base = "Out of memory";

+		break;

+	case STATUS_ILLEGAL_INSTRUCTION:

+		base = "Illegal instruction";

+		break;

+	case STATUS_NONCONTINUABLE_EXCEPTION:

+		base =  "Noncontinuable exception";

+		break;

+	case STATUS_INVALID_DISPOSITION:

+		base =  "Invalid disposition";

+		break;

+	case STATUS_ARRAY_BOUNDS_EXCEEDED:

+		base = "Array bounds exceeded";

+		break;

+	case STATUS_FLOAT_DENORMAL_OPERAND:

+		base = "Floating point denormal operand";

+		break;

+	case STATUS_FLOAT_DIVIDE_BY_ZERO:

+		base =  "Floating point divide by zero";

+		break;

+	case STATUS_FLOAT_INEXACT_RESULT:

+		base =  "Floating point inexact result";

+		break;

+	case STATUS_FLOAT_INVALID_OPERATION:

+		base =  "Floating point invalid operation";

+		break;

+	case STATUS_FLOAT_STACK_CHECK:

+		base = "Floating point stack check";

+		break;

+	case STATUS_FLOAT_OVERFLOW:

+		base = "Floating point overflow";

+		break;

+	case STATUS_FLOAT_UNDERFLOW:

+		base = "Floating point underflow";

+		break;

+	case STATUS_INTEGER_DIVIDE_BY_ZERO:

+		base = "Integer divide by zero";

+		break;

+	case STATUS_INTEGER_OVERFLOW:

+		base = "Integer overflow";

+		break;

+	case STATUS_PRIVILEGED_INSTRUCTION:

+		base = "Privileged instruction";

+		break;

+	case STATUS_STACK_OVERFLOW:

+		base = "Stack overflow";

+		break;

+	case STATUS_DLL_NOT_FOUND:

+		base = "DLL not found";

+		// TODO: find out how to determine which DLL it was...

+		break;

+	case STATUS_DLL_INIT_FAILED:

+		base = "DLL initialization failed";

+		break;

+	case STATUS_ENTRYPOINT_NOT_FOUND:

+		base = "Entry point not found";

+		break;

+	case MS_CPLUS_EXCEPTION:

+		base = "C++ exception";

+		break;

+

+	case RPC_S_UNKNOWN_IF:

+		base = "RPC unknown interface";

+		break;

+	case RPC_S_SERVER_UNAVAILABLE:

+		base = "RPC server unavailable";

+		break;

+	}

+

+	if (detail.size() > 0) {

+		return std::string(base) + detail;

+	}

+	return base;

+}

+

+void WinDebugMonitor::HandleExceptionEvent(DEBUG_EVENT& debugEvent)

+{

+	EXCEPTION_RECORD &e = debugEvent.u.Exception.ExceptionRecord;

+	LogTrace("DebugProcessMonitor::HandleExceptionEvent", "Exception in thread %d at 0x%x: code 0x%x (%s)",

+			debugEvent.dwThreadId, e.ExceptionAddress, e.ExceptionCode,

+			GetDebugExceptionDescription(debugEvent.u.Exception).c_str());

+

+    WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);

+	if (!thread)

+		assert(false);

+

+	// ignore initial breakpoint in NTDLL!DbgBreakPoint for newly launched process if necessary

+	if (!handledInitialDebugBreakpoint && e.ExceptionCode == EXCEPTION_BREAKPOINT)

+	{

+	    trace(LOG_ALWAYS, "\t -- ignored: initial ntdll DbgBreakPoint breakpoint");

+		handledInitialDebugBreakpoint = true;

+		// The "DBG_EXCEPTION_NOT_HANDLED" flag will make some other unknown breakpoint(s) in system dlls

+		// show up on some machines. But "DBG_CONTINUE" won't.

+		ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+		return;

+	}

+

+	if (thread && SettingsService::reportExceptionEvent(debugEvent))

+	{

+	    trace(LOG_ALWAYS, "\t -- reported to host debugger.");

+		thread->HandleException(debugEvent);

+	}

+	else

+	{

+		trace(LOG_ALWAYS, "\t -- ignored.");

+		// Note DBG_EXCEPTION_NOT_HANDLED is used here.

+		ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);

+	}

+}

+

+void WinDebugMonitor::HandleProcessCreatedEvent(DEBUG_EVENT& debugEvent)

+{

+	WinProcess* process = new WinProcess(this, debugEvent);

+	WinThread* thread = new WinThread(*process, debugEvent);

+

+	process->SetDebugging(true);

+	thread->SetDebugging(true);

+

+	// record in our cache

+	ContextManager::addContext(process);

+	ContextManager::addContext(thread);

+

+	// Notify host

+	EventClientNotifier::SendContextAdded(process);

+	EventClientNotifier::SendContextAdded(thread);

+

+	unsigned long codeSize = 0;

+	unsigned long baseOfCode = 0;

+	std::string imageName = GetExecutableInfo(debugEvent.u.CreateProcessInfo.hFile, baseOfCode, codeSize);

+

+	if (SettingsService::reportDebugEventForModule(imageName))

+		thread->HandleExecutableEvent(true, imageName, (unsigned long)debugEvent.u.CreateProcessInfo.lpBaseOfImage, codeSize + baseOfCode);

+	else

+		ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+

+	CloseHandle(debugEvent.u.CreateProcessInfo.hFile);

+}

+

+void WinDebugMonitor::HandleThreadCreatedEvent(DEBUG_EVENT& debugEvent)

+{

+	WinProcess* process = WinProcess::GetProcessByID(debugEvent.dwProcessId);

+	if (process) {

+		WinThread* thread = new WinThread(*process, debugEvent);

+		thread->SetDebugging(true);

+		ContextManager::addContext(thread);

+		EventClientNotifier::SendContextAdded(thread);

+	} else {

+		assert(false);

+	}

+

+	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+}

+

+void WinDebugMonitor::HandleProcessExitedEvent(DEBUG_EVENT& debugEvent)

+{

+	WinProcess* process = WinProcess::GetProcessByID(debugEvent.dwProcessId);

+	if (process) {

+		EventClientNotifier::SendContextRemoved(process, true);

+	} else {

+		assert(false);

+	}

+	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+}

+

+/**

+ * Make sure monitor thread is killed after the process being debugged died or

+ * is terminated.

+ * Note there is one monitor thread for each debugged process. The "process_id"

+ * passed in should be the process being monitored.

+ */

+void WinDebugMonitor::ProcessDied(DWORD process_id)

+{

+	// Terminate monitor thread if the process being monitored has died.

+	if (processID == process_id)

+		waitForDebugEvents = false;

+	else

+		assert(false);

+}

+

+void WinDebugMonitor::HandleThreadExitedEvent(DEBUG_EVENT& debugEvent)

+{

+	WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);

+	if (thread) {

+		EventClientNotifier::SendContextRemoved(thread, true);

+	} else {

+		assert(false);

+	}

+	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+}

+

+void WinDebugMonitor::HandleDLLLoadedEvent(DEBUG_EVENT& debugEvent)

+{

+	unsigned long codeSize = 0;

+	unsigned long baseOfCode = 0;

+	std::string moduleName = GetExecutableInfo(debugEvent.u.LoadDll.hFile, baseOfCode, codeSize);

+

+	if (SettingsService::reportDebugEventForModule(moduleName))

+	{

+		LogTrace("DebugProcessMonitor::HandleDLLLoadedEvent", "Base address: %8.8x %s", debugEvent.u.LoadDll.lpBaseOfDll, moduleName.c_str());

+		WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);

+		if (thread) {

+			thread->HandleExecutableEvent(true, moduleName, (unsigned long)debugEvent.u.LoadDll.lpBaseOfDll, codeSize);

+		}

+	}

+	else

+	{

+		ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+	}

+

+	CloseHandle(debugEvent.u.LoadDll.hFile);

+}

+

+void WinDebugMonitor::HandleDLLUnloadedEvent(DEBUG_EVENT& debugEvent)

+{

+	// if our process knows about this dll then it must be in the list of modules to debug

+	WinProcess* process = WinProcess::GetProcessByID(debugEvent.dwProcessId);

+	if (process)

+	{

+		Properties props = process->GetExecutablesByAddress()[(unsigned long)debugEvent.u.UnloadDll.lpBaseOfDll];

+		if (!props.empty())

+		{

+			WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);

+			if (thread) {

+				thread->HandleExecutableEvent(false, "", (unsigned long)debugEvent.u.UnloadDll.lpBaseOfDll, 0);

+			}

+		}

+	}

+

+	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+}

+

+void WinDebugMonitor::HandleDebugStringEvent(DEBUG_EVENT& debugEvent)

+{

+	if (SettingsService::reportDebugStringEvents())

+	{

+		WinProcess* process = WinProcess::GetProcessByID(debugEvent.dwProcessId);

+

+		if (debugEvent.u.DebugString.fUnicode == 0)

+		{

+			int debugStringLength = debugEvent.u.DebugString.nDebugStringLength;

+			char* debugStringBuffer = new char[debugStringLength + 1];

+			ReadProcessMemory(process->GetProcessHandle(), debugEvent.u.DebugString.lpDebugStringData, debugStringBuffer,

+					debugStringLength,NULL);

+			debugStringBuffer[debugStringLength] = 0;

+

+			// convert from ansi to utf-8

+			wchar_t* wideChars = new wchar_t[debugStringLength];

+

+			// Covert to Unicode.

+			if (MultiByteToWideChar(CP_ACP, 0, debugStringBuffer, debugStringLength,

+					wideChars, debugStringLength) != 0)

+			{

+			    int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideChars, debugStringLength, NULL, 0, NULL, NULL);

+			    std::string strTo( size_needed, 0 );

+			    WideCharToMultiByte(CP_UTF8, 0, wideChars, debugStringLength, &strTo[0], size_needed, NULL, NULL);

+				// write console data, if console

+				LoggingService::WriteLoggingMessage(channel, strTo, LoggingService::GetWindowsConsoleID());

+				LogTrace("DebugProcessMonitor::HandleDebugStringEvent", "%s", strTo.c_str());

+			}

+

+			delete[] wideChars;

+			delete[] debugStringBuffer;

+		}

+	}

+

+	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+}

+

+void WinDebugMonitor::HandleSystemDebugErrorEvent(DEBUG_EVENT& debugEvent)

+{

+	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+}

+

+void WinDebugMonitor::HandleUnknwonDebugEvent(DEBUG_EVENT& debugEvent)

+{

+	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+}

+

+void WinDebugMonitor::PostAction(AgentAction* action)

+{

+	actions_.push(action);

+}

+

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.h b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.h
index aed6d0a..81346bc 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.h
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.h
@@ -1,114 +1,101 @@
-/*******************************************************************************
- * 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
- *******************************************************************************/
-
-#pragma once
-
-#include <string>
-#include <vector>
-#include "stdafx.h"
-#include "DebugMonitor.h"
-#include "TCFChannel.h" 
-#include <queue>
-
-extern "C" {
-#include "channel.h"
-#include "events.h"
-}
-
-class AgentAction;
-class AgentActionParams;
-class WinProcess;
-
-/*
- * Windows implementation of DebugMonitor.
- */
-class WinDebugMonitor: public DebugMonitor {
-public:
-	WinDebugMonitor(const LaunchProcessParams& params);
-
-	WinDebugMonitor(const AttachToProcessParams& params);
-
-	virtual ~WinDebugMonitor(void);
-
-	void StartProcessForDebug();
-	void EventLoop();
-	void StartMonitor();
-
-	void CaptureMonitorThread();
-	void SetProcess(WinProcess* process);
-	void Suspend();
-	void Resume();
-
-	void PostAction(AgentAction* action);
-
-	virtual void Attach(unsigned long pid, ContextAttachCallBack * done,
-			void * data, int selfattach);
-
-	void StartDebug();
-
-	/*
-	 * Launch a process and monitor it.
-	 */
-	static void LaunchProcess(const LaunchProcessParams& params) throw (AgentException);
-
-	/*
-	 * Attach to a process and monitor it.
-	 * processID: the Windows process ID.
-	 */
-	static void AttachToProcess(const AttachToProcessParams& params) throw (AgentException);
-
-	/**
-	 * Tell whether the exception is a first-chance exception where we want
-	 * to immediately suspend and debug.  Usually, we allow a user-written
-	 * __try/__except handler take these, but in some cases (e.g. DLL laod failure)
-	 * the process will just crash.
-	 */
-	bool ShouldDebugFirstChance(const DEBUG_EVENT& debugEvent);
-
-	bool ShouldReportException(const DEBUG_EVENT& debugEvent);
-
-	static std::string GetDebugExceptionDescription(const EXCEPTION_DEBUG_INFO& exceptionInfo);
-
-	void HandleDebugEvent(DEBUG_EVENT& debugEvent);
-
-private:
-	void AttachToProcessForDebug();
-
-	void HandleNoDebugEvent();
-
-	void HandleExceptionEvent(DEBUG_EVENT& debugEvent);
-	void HandleProcessCreatedEvent(DEBUG_EVENT& debugEvent);
-	void HandleThreadCreatedEvent(DEBUG_EVENT& debugEvent);
-	void HandleProcessExitedEvent(DEBUG_EVENT& debugEvent);
-	void HandleThreadExitedEvent(DEBUG_EVENT& debugEvent);
-	void HandleDLLLoadedEvent(DEBUG_EVENT& debugEvent);
-	void HandleDLLUnloadedEvent(DEBUG_EVENT& debugEvent);
-	void HandleDebugStringEvent(DEBUG_EVENT& debugEvent);
-	void HandleSystemDebugErrorEvent(DEBUG_EVENT& debugEvent);
-	void HandleUnknwonDebugEvent(DEBUG_EVENT& debugEvent);
-
-	void HandleException(DEBUG_EVENT& debugEvent);
-
-private:
-
-	DWORD wfdeWait;
-	bool waitForDebugEvents;
-	bool handledFirstException_;
-	DWORD processID;
-	bool isAttach;
-
-	PROCESS_INFORMATION processInfo;
-	HANDLE monitorThread_;
-	WinProcess* process_;
-	std::queue<AgentAction*> actions_;
-
-};
-
+/*******************************************************************************

+ * 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

+ *******************************************************************************/

+

+#pragma once

+

+#include <string>

+#include "stdafx.h"

+#include "DebugMonitor.h"

+#include "TCFChannel.h" 

+#include <queue>

+

+extern "C" {

+#include "channel.h"

+#include "events.h"

+}

+

+class AgentAction;

+class AgentActionParams;

+class WinProcess;

+

+/*

+ * Windows implementation of DebugMonitor.

+ */

+class WinDebugMonitor: public DebugMonitor {

+public:

+	WinDebugMonitor(const LaunchProcessParams& params);

+

+	WinDebugMonitor(const AttachToProcessParams& params);

+

+	virtual ~WinDebugMonitor(void);

+

+	void StartProcessForDebug();

+	void EventLoop();

+	void StartMonitor();

+

+	void CaptureMonitorThread();

+	void Suspend();

+	void Resume();

+

+	void PostAction(AgentAction* action);

+

+	virtual void Attach(unsigned long pid, ContextAttachCallBack * done,

+			void * data, int selfattach);

+

+	void StartDebug();

+

+	/*

+	 * Launch a process and monitor it.

+	 */

+	static void LaunchProcess(const LaunchProcessParams& params) throw (AgentException);

+

+	/*

+	 * Attach to a process and monitor it.

+	 * processID: the Windows process ID.

+	 */

+	static void AttachToProcess(const AttachToProcessParams& params) throw (AgentException);

+

+	static std::string GetDebugExceptionDescription(const EXCEPTION_DEBUG_INFO& exceptionInfo);

+

+	void HandleDebugEvent(DEBUG_EVENT& debugEvent);

+

+	void ProcessDied(DWORD process_id);

+

+private:

+	void AttachToProcessForDebug();

+

+	void HandleNoDebugEvent();

+

+	void HandleExceptionEvent(DEBUG_EVENT& debugEvent);

+	void HandleProcessCreatedEvent(DEBUG_EVENT& debugEvent);

+	void HandleThreadCreatedEvent(DEBUG_EVENT& debugEvent);

+	void HandleProcessExitedEvent(DEBUG_EVENT& debugEvent);

+	void HandleThreadExitedEvent(DEBUG_EVENT& debugEvent);

+	void HandleDLLLoadedEvent(DEBUG_EVENT& debugEvent);

+	void HandleDLLUnloadedEvent(DEBUG_EVENT& debugEvent);

+	void HandleDebugStringEvent(DEBUG_EVENT& debugEvent);

+	void HandleSystemDebugErrorEvent(DEBUG_EVENT& debugEvent);

+	void HandleUnknwonDebugEvent(DEBUG_EVENT& debugEvent);

+

+private:

+

+	DWORD wfdeWait;

+	bool waitForDebugEvents;

+	bool handledInitialDebugBreakpoint;

+	DWORD processID;

+	bool isAttach;

+

+	PROCESS_INFORMATION processInfo;

+	HANDLE monitorThread_;

+	std::queue<AgentAction*> actions_;

+

+};

+

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.cpp
index 9ae67e9..27842ad 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.cpp
@@ -1,152 +1,148 @@
-/*******************************************************************************
- * 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_;
-}
-
+/*******************************************************************************

+ * 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_;

+}

+

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.h b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.h
index d79d49d..635976e 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.h
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.h
@@ -1,56 +1,57 @@
-/*******************************************************************************
- * 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
- *******************************************************************************/
-#pragma once
-
-#include <vector>
-#include "stdafx.h"
-#include "ProcessContext.h"
-#include "WinDebugMonitor.h"
-
-class WinThread;
-class WinDebugMonitor;
-
-class WinProcess : public ProcessContext {
-public:
-	WinProcess(WinDebugMonitor* monitor, DEBUG_EVENT& debugEvent);
-	WinProcess(DWORD procID, std::string procName);
-
-	virtual ~WinProcess(void);
-
-	//
-	// Overrides of RunControlContext
-	//
-	virtual int ReadMemory(const ReadWriteMemoryParams& params) throw (AgentException);
-	virtual int WriteMemory(const ReadWriteMemoryParams& params) throw (AgentException);
-	virtual void Terminate(const AgentActionParams& params) throw (AgentException);
-	virtual void SingleStep(const AgentActionParams& params) throw (AgentException);
-	//
-	//	end overrides
-
-	HANDLE GetProcessHandle();
-
-	WinDebugMonitor* GetMonitor();
-
-	static WinProcess* GetProcessByID(int processID);
-
-	std::map<std::string, Properties>& GetExecutables();
-
-private:
-	void initialize();
-
-	bool isRoot_;
-	HANDLE processHandle_;
-	std::string processName_;
-	WinDebugMonitor* monitor_;
-	std::map<std::string, Properties> executables_;
-
-	static std::map<int, WinProcess*> processIDMap;
-};
+/*******************************************************************************

+ * 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

+ *******************************************************************************/

+#pragma once

+

+#include <vector>

+#include <set>

+#include "stdafx.h"

+#include "ProcessContext.h"

+#include "WinDebugMonitor.h"

+

+class WinThread;

+class WinDebugMonitor;

+

+class WinProcess : public ProcessContext {

+public:

+	WinProcess(WinDebugMonitor* monitor, DEBUG_EVENT& debugEvent);

+	WinProcess(DWORD procID, std::string procName);

+

+	virtual ~WinProcess(void);

+

+	//

+	// Overrides of RunControlContext

+	//

+	virtual int ReadMemory(const ReadWriteMemoryParams& params) throw (AgentException);

+	virtual int WriteMemory(const ReadWriteMemoryParams& params) throw (AgentException);

+	virtual void Terminate(const AgentActionParams& params) throw (AgentException);

+	virtual void SingleStep(const AgentActionParams& params) throw (AgentException);

+	//

+	//	end overrides

+

+	HANDLE GetProcessHandle();

+

+	WinDebugMonitor* GetMonitor();

+

+	static WinProcess* GetProcessByID(int processID);

+

+	std::map<int, Properties>& GetExecutablesByAddress();

+

+private:

+	void initialize();

+

+	bool isRoot_;

+	HANDLE processHandle_;

+	std::string processName_;

+	WinDebugMonitor* monitor_;

+	std::map<int, Properties> executablesByAddress_;

+

+	static std::map<int, WinProcess*> processIDMap;

+};

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.cpp
index 811b235..ecfc2c8 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.cpp
@@ -1,472 +1,493 @@
-/*******************************************************************************
- * 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 <stdio.h>
-#include <assert.h>
-
-#include "stdafx.h"
-#include "WinThread.h"
-#include "WinProcess.h"
-#include "AgentUtils.h"
-#include "EventClientNotifier.h"
-#include "Logger.h"
-#include "WinDebugMonitor.h"
-#include "ResumeContextAction.h"
-#include "ProtocolConstants.h"
-#include "RunControlService.h"
-#include "BreakpointsService.h"
-
-std::map<std::pair<int, int>, WinThread*> WinThread::threadIDMap_;
-
-WinThread::WinThread(WinProcess& process, DEBUG_EVENT& debugEvent) :
-	ThreadContext(debugEvent.dwThreadId, process.GetID(), CreateInternalID(debugEvent.dwThreadId, process.GetID())),
-	threadLookupPair_(debugEvent.dwProcessId, debugEvent.dwThreadId),
-	parentProcess_(process)
-{
-	process.AddChild(this);
-
-	threadIDMap_[threadLookupPair_] = this;
-
-	threadContextValid_ = false;
-	if (debugEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
-		handle_ = debugEvent.u.CreateProcessInfo.hThread;
-		startAddress_
-				= (unsigned long) debugEvent.u.CreateProcessInfo.lpStartAddress;
-		localBase_ = debugEvent.u.CreateProcessInfo.lpThreadLocalBase;
-	} else if (debugEvent.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT) {
-		handle_ = debugEvent.u.CreateThread.hThread;
-		startAddress_
-				= (unsigned long) debugEvent.u.CreateThread.lpStartAddress;
-		localBase_ = debugEvent.u.CreateThread.lpThreadLocalBase;
-	}
-	isSuspended_ = false;
-	isTerminating_ = false;
-	isUserSuspended_ = false;
-
-	initialize();
-}
-
-// Initialize thread specific properties.
-void WinThread::initialize()
-{
-	char buf[32];
-	_snprintf(buf, sizeof(buf), "0x%08x", startAddress_);
-	SetProperty(PROP_NAME, new PropertyValue(buf));
-
-	int supportedResumeModes = (1 << RM_RESUME) | (1 << RM_STEP_INTO);
-	SetProperty(PROP_CAN_RESUME, new PropertyValue(supportedResumeModes));
-
-	SetProperty(PROP_CAN_TERMINATE, new PropertyValue(true));
-	SetProperty(PROP_CAN_SUSPEND, new PropertyValue(true));
-}
-
-int WinThread::GetThreadID() {
-	return GetOSID();
-}
-
-WinThread::~WinThread(void) {
-	parentProcess_.RemoveChild(this);
-	threadIDMap_.erase(threadLookupPair_);
-}
-
-ContextAddress WinThread::GetPCAddress() {
-	// The following is actually the address of the instruction that causes
-	// the exception, not the actual PC register value which is usually 
-	// pointing to the byte after the exception instruction.
-	// But what we need here is PC value.
-	//
-	// exceptionInfo_.ExceptionRecord.ExceptionAddress;
-
-	assert(threadContextValid_);
-	return threadContextInfo_.Eip;
-}
-
-const char* WinThread::GetSuspendReason() {
-	const char* reason = REASON_EXCEPTION;
-
-	switch (exceptionInfo_.ExceptionRecord.ExceptionCode) {
-	case USER_SUSPEND_THREAD:
-		return REASON_USER_REQUEST;
-	case EXCEPTION_SINGLE_STEP:
-		return REASON_STEP;
-	case EXCEPTION_BREAKPOINT:
-		return REASON_BREAKPOINT;
-	}
-
-	return reason;
-}
-
-
-std::string WinThread::GetExceptionMessage() {
-	if (exceptionInfo_.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP
-			|| exceptionInfo_.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT
-			|| exceptionInfo_.ExceptionRecord.ExceptionCode == USER_SUSPEND_THREAD)
-		return "";
-
-	return WinDebugMonitor::GetDebugExceptionDescription(exceptionInfo_);
-}
-
-void WinThread::MarkSuspended() {
-	isSuspended_ = true;
-	threadContextValid_ = false;
-}
-
-void WinThread::HandleException(DEBUG_EVENT& debugEvent) {
-	MarkSuspended();
-	exceptionInfo_ = debugEvent.u.Exception;
-	EnsureValidContextInfo();
-	AdjustPC();
-	EventClientNotifier::SendContextSuspended(this,
-			GetPCAddress(), GetSuspendReason(), GetExceptionMessage());
-
-}
-
-/*
- * Check if the program is stopped due to a software breakpoint
- * installed by the agent, if yes, move PC back by one byte.
- */
-void WinThread::AdjustPC() {
-	// Bail out if the agent does not install & manage
-	// breakpoints (namely the EDC host uses generic
-	// software breakpoint mechanism).
-	if (! BreakpointsService::ServiceInstalled())
-		return;
-
-	/*
-	 * Check
-	 * 1. Did we stop due to a breakpoint exception ?
-	 *   -- This is to prevent adjusting PC for other exceptions such as
-	 *      divide-by-zero & invalid code.
-	 * 2. is there a software breakpoint at the byte right before the PC?
-	 *   -- this is to exclude the case of user-inserted "int 3" instruction.
-	 */
-	if (exceptionInfo_.ExceptionRecord.ExceptionCode != EXCEPTION_BREAKPOINT)
-		return;
-
-	ContextAddress pc = GetPCAddress();
-	pc--;
-	if (NULL != BreakpointsService::FindBreakpointByAddress(parentProcess_.GetProcessHandle(), pc)) {
-		SetRegisterValue("EIP", 4, (char*)&pc);
-	}
-}
-
-void WinThread::HandleExecutableEvent(bool isLoaded, const std::string& exePath,
-		unsigned long baseAddress, unsigned long codeSize) {
-	MarkSuspended();
-	EnsureValidContextInfo();
-
-	if(parentProcess_.GetExecutables().find(exePath) != parentProcess_.GetExecutables().end())
-	{
-		Properties existingProps = parentProcess_.GetExecutables()[exePath];
-		if (existingProps[PROP_MODULE_LOADED]->getBoolValue())
-		{
-			delete existingProps[PROP_MODULE_LOADED];
-			existingProps[PROP_MODULE_LOADED] = new PropertyValue(false);
-			EventClientNotifier::SendExecutableEvent(this,
-					threadContextInfo_.Eip, existingProps);
-		}
-	}
-
-	Properties props;
-	props[PROP_FILE] = new PropertyValue(exePath);
-	props[PROP_NAME] = new PropertyValue(AgentUtils::GetFileNameFromPath(exePath));
-	props[PROP_MODULE_LOADED] = new PropertyValue(isLoaded);
-	props[PROP_IMAGE_BASE_ADDRESS] = new PropertyValue((int) baseAddress);
-	props[PROP_CODE_SIZE] = new PropertyValue((int) codeSize);
-
-	parentProcess_.GetExecutables()[exePath] = props;
-	EventClientNotifier::SendExecutableEvent(this, 
-			threadContextInfo_.Eip, props);
-}
-
-bool WinThread::isSuspended() {
-	return isSuspended_;
-}
-
-#ifndef CONTEXT_ALL
-#define CONTEXT_ALL             (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \
-	CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | \
-	CONTEXT_EXTENDED_REGISTERS)
-#endif
-
-void WinThread::EnsureValidContextInfo() {
-	if (!threadContextValid_ && isSuspended()) {
-		threadContextInfo_.ContextFlags = CONTEXT_ALL;
-		if (GetThreadContext(handle_, &threadContextInfo_) != 0) {
-			registerValueCache_.clear();
-			// Cache general registers
-			registerValueCache_["EAX"] = AgentUtils::IntToHexString(
-					threadContextInfo_.Eax);
-			registerValueCache_["ECX"] = AgentUtils::IntToHexString(
-					threadContextInfo_.Ecx);
-			registerValueCache_["EDX"] = AgentUtils::IntToHexString(
-					threadContextInfo_.Edx);
-			registerValueCache_["EBX"] = AgentUtils::IntToHexString(
-					threadContextInfo_.Ebx);
-			registerValueCache_["ESP"] = AgentUtils::IntToHexString(
-					threadContextInfo_.Esp);
-			registerValueCache_["EBP"] = AgentUtils::IntToHexString(
-					threadContextInfo_.Ebp);
-			registerValueCache_["ESI"] = AgentUtils::IntToHexString(
-					threadContextInfo_.Esi);
-			registerValueCache_["EDI"] = AgentUtils::IntToHexString(
-					threadContextInfo_.Edi);
-			registerValueCache_["EIP"] = AgentUtils::IntToHexString(
-					threadContextInfo_.Eip);
-			registerValueCache_["GS"] = AgentUtils::IntToHexString(
-					threadContextInfo_.SegGs);
-			registerValueCache_["FS"] = AgentUtils::IntToHexString(
-					threadContextInfo_.SegFs);
-			registerValueCache_["ES"] = AgentUtils::IntToHexString(
-					threadContextInfo_.SegEs);
-			registerValueCache_["DS"] = AgentUtils::IntToHexString(
-					threadContextInfo_.SegDs);
-			registerValueCache_["CS"] = AgentUtils::IntToHexString(
-					threadContextInfo_.SegCs);
-			registerValueCache_["EFL"] = AgentUtils::IntToHexString(
-					threadContextInfo_.EFlags);
-			registerValueCache_["SS"] = AgentUtils::IntToHexString(
-					threadContextInfo_.SegSs);
-
-			threadContextValid_ = true;
-		}
-	}
-}
-
-void WinThread::SetContextInfo() {
-	if (isSuspended()) {
-		threadContextInfo_.ContextFlags = CONTEXT_ALL;
-		// Set general registers values
-		threadContextInfo_.Eax = AgentUtils::HexStringToInt(
-				registerValueCache_["EAX"]);
-		threadContextInfo_.Ecx = AgentUtils::HexStringToInt(
-				registerValueCache_["ECX"]);
-		threadContextInfo_.Edx = AgentUtils::HexStringToInt(
-				registerValueCache_["EDX"]);
-		threadContextInfo_.Ebx = AgentUtils::HexStringToInt(
-				registerValueCache_["EBX"]);
-		threadContextInfo_.Esp = AgentUtils::HexStringToInt(
-				registerValueCache_["ESP"]);
-		threadContextInfo_.Ebp = AgentUtils::HexStringToInt(
-				registerValueCache_["EBP"]);
-		threadContextInfo_.Esi = AgentUtils::HexStringToInt(
-				registerValueCache_["ESI"]);
-		threadContextInfo_.Edi = AgentUtils::HexStringToInt(
-				registerValueCache_["EDI"]);
-		threadContextInfo_.Eip = AgentUtils::HexStringToInt(
-				registerValueCache_["EIP"]);
-		threadContextInfo_.SegGs = AgentUtils::HexStringToInt(
-				registerValueCache_["GS"]);
-		threadContextInfo_.SegFs = AgentUtils::HexStringToInt(
-				registerValueCache_["FS"]);
-		threadContextInfo_.SegEs = AgentUtils::HexStringToInt(
-				registerValueCache_["ES"]);
-		threadContextInfo_.SegDs = AgentUtils::HexStringToInt(
-				registerValueCache_["DS"]);
-		threadContextInfo_.SegCs = AgentUtils::HexStringToInt(
-				registerValueCache_["CS"]);
-		threadContextInfo_.EFlags = AgentUtils::HexStringToInt(
-				registerValueCache_["EFL"]);
-		threadContextInfo_.SegSs = AgentUtils::HexStringToInt(
-				registerValueCache_["SS"]);
-		SetThreadContext(handle_, &threadContextInfo_);
-	}
-}
-
-WinThread* WinThread::GetThreadByID(int processID, int threadID) {
-	std::pair<int, int> ptPair(processID, threadID);
-	std::map<std::pair<int, int>, WinThread*>::iterator iter = threadIDMap_.find(ptPair);
-	if (iter == threadIDMap_.end())
-		return NULL;
-	else
-		return iter->second;
-}
-
-std::vector<std::string> WinThread::GetRegisterValues(
-		const std::vector<std::string>& registerIDs) {
-	std::vector<std::string> registerValues;
-
-	if (isSuspended()) {
-		EnsureValidContextInfo();
-
-		std::vector<std::string>::const_iterator itVectorData;
-		for (itVectorData = registerIDs.begin(); itVectorData
-				!= registerIDs.end(); itVectorData++) {
-			std::string registerID = *itVectorData;
-			std::string registerValue = registerValueCache_[registerID];
-			registerValues.push_back(registerValue);
-		}
-	}
-
-	return registerValues;
-}
-
-/*
- * Get pointer to register value cache for a given register.
- * Return NULL if the register is not found.
- */
-void* WinThread::getRegisterValueBuffer(const std::string& regName) {
-	void* v = NULL;
-
-	if (regName == "EAX")
-		v = (void*)&threadContextInfo_.Eax;
-	else if (regName == "EBX")
-		v = (void*)&threadContextInfo_.Ebx;
-	else if (regName == "ECX")
-		v = (void*)&threadContextInfo_.Ecx;
-	else if (regName == "EDX")
-		v = (void*)&threadContextInfo_.Edx;
-	else if (regName == "ESP")
-		v = (void*)&threadContextInfo_.Esp;
-	else if (regName == "EBP")
-		v = (void*)&threadContextInfo_.Ebp;
-	else if (regName == "ESI")
-		v = (void*)&threadContextInfo_.Esi;
-	else if (regName == "EDI")
-		v = (void*)&threadContextInfo_.Edi;
-	else if (regName == "EIP")
-		v = (void*)&threadContextInfo_.Eip;
-	else if (regName == "EFL")
-		v = (void*)&threadContextInfo_.EFlags;
-	else if (regName == "GS")
-		v = (void*)&threadContextInfo_.SegGs;
-	else if (regName == "FS")
-		v = (void*)&threadContextInfo_.SegFs;
-	else if (regName == "ES")
-		v = (void*)&threadContextInfo_.SegEs;
-	else if (regName == "DS")
-		v = (void*)&threadContextInfo_.SegDs;
-	else if (regName == "CS")
-		v = (void*)&threadContextInfo_.SegCs;
-	else if (regName == "SS")
-		v = (void*)&threadContextInfo_.SegSs;
-	else {
-		assert(false);
-	}
-
-	return v;
-}
-
-/*
- * Read one register.
- * Return binary data buffer, which caller should free by calling delete[].
- */
-char* WinThread::GetRegisterValue(const std::string& regName, int regSize) {
-
-	char* ret = NULL;
-
-	if (isSuspended()) {
-		EnsureValidContextInfo();
-
-		ret = new char[regSize];
-
-		void* v = getRegisterValueBuffer(regName);
-		assert(v != NULL);
-
-		memcpy((void*)ret, v, regSize);
-	}
-
-	return ret;
-}
-
-bool WinThread::SetRegisterValue(const std::string& regName, int regSize, char* val) {
-
-	if (! isSuspended())
-		return false;
-
-	void* v = getRegisterValueBuffer(regName);
-	assert(v != NULL);
-
-	memcpy(v, (void*)val, regSize);
-	return SetThreadContext(handle_, &threadContextInfo_);
-}
-
-void WinThread::SetRegisterValues(const std::vector<std::string>& registerIDs,
-		const std::vector<std::string>& registerValues) {
-	if (isSuspended()) {
-		std::vector<std::string>::const_reverse_iterator itVectorData;
-		int idx = registerValues.size();
-		for (itVectorData = registerIDs.rbegin(); itVectorData
-				!= registerIDs.rend(); itVectorData++) {
-			std::string registerID = *itVectorData;
-			registerValueCache_[registerID] = registerValues[--idx];
-		}
-
-		SetContextInfo();
-	}
-}
-
-int WinThread::ReadMemory(const ReadWriteMemoryParams& params) throw (AgentException) {
-	return parentProcess_.ReadMemory(params);
-}
-
-int WinThread::WriteMemory(const ReadWriteMemoryParams& params) throw (AgentException) {
-	return parentProcess_.WriteMemory(params);
-}
-
-void WinThread::Terminate(const AgentActionParams& params) throw (AgentException) {
-	parentProcess_.Terminate(params);
-}
-
-void WinThread::Suspend(const AgentActionParams& params) throw (AgentException) {
-	DWORD suspendCount = SuspendThread(handle_);
-	MarkSuspended();
-	EnsureValidContextInfo();
-	exceptionInfo_.ExceptionRecord.ExceptionCode = USER_SUSPEND_THREAD; // "Suspended"
-	isUserSuspended_ = true;
-	if (! isTerminating_)	// don't send Suspend event if we are terminating.
-		EventClientNotifier::SendContextSuspended(this,
-				GetPCAddress(), GetSuspendReason(), GetExceptionMessage());
-	Logger::getLogger().Log(Logger::LOG_NORMAL, "WinThread::Suspend",
-			"suspendCount: %d", suspendCount);
-
-	params.reportSuccessForAction();
-}
-
-void WinThread::Resume(const AgentActionParams& params) throw (AgentException) {
-	if (! isSuspended()) {
-		params.reportSuccessForAction();
-		return;
-	}
-
-	if (isUserSuspended_){
-		ResumeThread(handle_);
-		isUserSuspended_ = false;
-		params.reportSuccessForAction();
-	}
-	else {
-		parentProcess_.GetMonitor()->PostAction(new ResumeContextAction(
-			params, parentProcess_, *this, RM_RESUME));
-	}
-}
-
-/*
- * Enable single instruction step by setting Trap Flag (TF) bit.
- */
-void WinThread::EnableSingleStep() {
-#define FLAG_TRACE_BIT 0x100
-	// The bit will be auto-cleared after next resume.
-	threadContextInfo_.EFlags |= FLAG_TRACE_BIT;
-	SetThreadContext(handle_, &threadContextInfo_);
-}
-
-void WinThread::SingleStep(const AgentActionParams& params) throw (AgentException) {
-	parentProcess_.GetMonitor()->PostAction(new ResumeContextAction(
-			params, parentProcess_, *this, RM_STEP_INTO));
-}
-
-void WinThread::PrepareForTermination(const AgentActionParams& params) throw (AgentException) {
-	isTerminating_ = true;
-
-	if (isSuspended()) {
-		Suspend(params);
-		ContinueDebugEvent(parentProcess_.GetOSID(), GetOSID(), DBG_CONTINUE);
-	}
-}
+/*******************************************************************************

+ * 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 <stdio.h>

+#include <assert.h>

+

+#include "stdafx.h"

+#include "WinThread.h"

+#include "WinProcess.h"

+#include "AgentUtils.h"

+#include "EventClientNotifier.h"

+#include "Logger.h"

+#include "WinDebugMonitor.h"

+#include "ResumeContextAction.h"

+#include "ProtocolConstants.h"

+#include "RunControlService.h"

+#include "BreakpointsService.h"

+

+std::map<std::pair<int, int>, WinThread*> WinThread::threadIDMap_;

+

+WinThread::WinThread(WinProcess& process, DEBUG_EVENT& debugEvent) :

+	ThreadContext(debugEvent.dwThreadId, process.GetID(), CreateInternalID(debugEvent.dwThreadId, process.GetID())),

+	threadLookupPair_(debugEvent.dwProcessId, debugEvent.dwThreadId),

+	parentProcess_(process)

+{

+	process.AddChild(this);

+

+	threadIDMap_[threadLookupPair_] = this;

+

+	threadContextValid_ = false;

+	if (debugEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {

+		handle_ = debugEvent.u.CreateProcessInfo.hThread;

+		startAddress_

+				= (unsigned long) debugEvent.u.CreateProcessInfo.lpStartAddress;

+		localBase_ = debugEvent.u.CreateProcessInfo.lpThreadLocalBase;

+	} else if (debugEvent.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT) {

+		handle_ = debugEvent.u.CreateThread.hThread;

+		startAddress_

+				= (unsigned long) debugEvent.u.CreateThread.lpStartAddress;

+		localBase_ = debugEvent.u.CreateThread.lpThreadLocalBase;

+	}

+	isSuspended_ = false;

+	isTerminating_ = false;

+	isUserSuspended_ = false;

+

+	// just to ensure that new threads are resumed with DBG_CONTINUE.  this is normally set/changed

+	// in HandleException

+	exceptionInfo_.ExceptionRecord.ExceptionCode = USER_SUSPEND_THREAD;

+

+	initialize();

+}

+

+// Initialize thread specific properties.

+void WinThread::initialize()

+{

+	char buf[32];

+	_snprintf(buf, sizeof(buf), "0x%08x", startAddress_);

+	SetProperty(PROP_NAME, PropertyValue(buf));

+

+	int supportedResumeModes = (1 << RM_RESUME) | (1 << RM_STEP_INTO);

+	SetProperty(PROP_CAN_RESUME, PropertyValue(supportedResumeModes));

+

+	SetProperty(PROP_CAN_TERMINATE, PropertyValue(true));

+	SetProperty(PROP_CAN_SUSPEND, PropertyValue(true));

+}

+

+int WinThread::GetThreadID() {

+	return GetOSID();

+}

+

+WinThread::~WinThread(void) {

+	parentProcess_.RemoveChild(this);

+	threadIDMap_.erase(threadLookupPair_);

+

+	// Destructor of parent classes will be called which will

+	// delete all children contexts (registers, etc).

+}

+

+ContextAddress WinThread::GetPCAddress() {

+	// The following is actually the address of the instruction that causes

+	// the exception, not the actual PC register value which is usually 

+	// pointing to the byte after the exception instruction.

+	// But what we need here is PC value.

+	//

+	// exceptionInfo_.ExceptionRecord.ExceptionAddress;

+

+	assert(threadContextValid_);

+	return threadContextInfo_.Eip;

+}

+

+const char* WinThread::GetSuspendReason() {

+	const char* reason = REASON_EXCEPTION;

+

+	switch (exceptionInfo_.ExceptionRecord.ExceptionCode) {

+	case USER_SUSPEND_THREAD:

+		return REASON_USER_REQUEST;

+	case EXCEPTION_SINGLE_STEP:

+		return REASON_STEP;

+	case EXCEPTION_BREAKPOINT:

+		return REASON_BREAKPOINT;

+	}

+

+	return reason;

+}

+

+DWORD WinThread::GetContinueStatus() {

+	// for resuming from any exception other than breakpoint or step (which the debugger handles), we must pass

+	// DBG_EXCEPTION_NOT_HANDLED to allow the process under debug the chance to handle it

+	switch (exceptionInfo_.ExceptionRecord.ExceptionCode) {

+	case USER_SUSPEND_THREAD:

+	case EXCEPTION_SINGLE_STEP:

+	case EXCEPTION_BREAKPOINT:

+		return DBG_CONTINUE;

+	}

+

+	return DBG_EXCEPTION_NOT_HANDLED;

+}

+

+std::string WinThread::GetExceptionMessage() {

+	if (exceptionInfo_.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP

+			|| exceptionInfo_.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT

+			|| exceptionInfo_.ExceptionRecord.ExceptionCode == USER_SUSPEND_THREAD)

+		return "";

+

+	return WinDebugMonitor::GetDebugExceptionDescription(exceptionInfo_);

+}

+

+void WinThread::MarkSuspended() {

+	isSuspended_ = true;

+	threadContextValid_ = false;

+}

+

+void WinThread::HandleException(DEBUG_EVENT& debugEvent) {

+	exceptionInfo_ = debugEvent.u.Exception;

+	MarkSuspended();

+	EnsureValidContextInfo();

+	AdjustPC();

+	EventClientNotifier::SendContextSuspended(this,

+			GetPCAddress(), GetSuspendReason(), GetExceptionMessage());

+

+}

+

+/*

+ * Check if the program is stopped due to a software breakpoint

+ * installed by the agent, if yes, move PC back by one byte.

+ */

+void WinThread::AdjustPC() {

+	// Bail out if the agent does not install & manage

+	// breakpoints (namely the EDC host uses generic

+	// software breakpoint mechanism).

+	if (! BreakpointsService::ServiceInstalled())

+		return;

+

+	/*

+	 * Check

+	 * 1. Did we stop due to a breakpoint exception ?

+	 *   -- This is to prevent adjusting PC for other exceptions such as

+	 *      divide-by-zero & invalid code.

+	 * 2. is there a software breakpoint at the byte right before the PC?

+	 *   -- this is to exclude the case of user-inserted "int 3" instruction.

+	 */

+	if (exceptionInfo_.ExceptionRecord.ExceptionCode != EXCEPTION_BREAKPOINT)

+		return;

+

+	ContextAddress pc = GetPCAddress();

+	pc--;

+	if (NULL != BreakpointsService::FindBreakpointByAddress(parentProcess_.GetProcessHandle(), pc)) {

+		SetRegisterValue("EIP", 4, (char*)&pc);

+	}

+}

+

+void WinThread::HandleExecutableEvent(bool isLoaded, const std::string& exePath,

+		unsigned long baseAddress, unsigned long codeSize) {

+	MarkSuspended();

+	EnsureValidContextInfo();

+

+	Properties props;

+	if (isLoaded)

+	{

+		props[PROP_ID] = PropertyValue((int) baseAddress);

+		props[PROP_FILE] = PropertyValue(exePath);

+		props[PROP_NAME] = PropertyValue(AgentUtils::GetFileNameFromPath(exePath));

+		props[PROP_MODULE_LOADED] = PropertyValue(isLoaded);

+		props[PROP_IMAGE_BASE_ADDRESS] = PropertyValue((int) baseAddress);

+		props[PROP_CODE_SIZE] = PropertyValue((int) codeSize);

+	}

+	else

+	{

+		props = parentProcess_.GetExecutablesByAddress()[baseAddress];

+		if (props.empty())

+		{ // We have an unloaded event for an executable we didn't know about.

+			props[PROP_ID] = PropertyValue((int) baseAddress);

+			props[PROP_IMAGE_BASE_ADDRESS] = PropertyValue((int) baseAddress);

+		}

+		props[PROP_MODULE_LOADED] = PropertyValue(false);

+	}

+

+	parentProcess_.GetExecutablesByAddress()[baseAddress] = props;

+	EventClientNotifier::SendExecutableEvent(this,

+			threadContextInfo_.Eip, props);

+}

+

+bool WinThread::isSuspended() {

+	return isSuspended_;

+}

+

+#ifndef CONTEXT_ALL

+#define CONTEXT_ALL             (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \

+	CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | \

+	CONTEXT_EXTENDED_REGISTERS)

+#endif

+

+void WinThread::EnsureValidContextInfo() {

+	if (!threadContextValid_ && isSuspended()) {

+		threadContextInfo_.ContextFlags = CONTEXT_ALL;

+		if (GetThreadContext(handle_, &threadContextInfo_) != 0) {

+			registerValueCache_.clear();

+			// Cache general registers

+			registerValueCache_["EAX"] = AgentUtils::IntToHexString(

+					threadContextInfo_.Eax);

+			registerValueCache_["ECX"] = AgentUtils::IntToHexString(

+					threadContextInfo_.Ecx);

+			registerValueCache_["EDX"] = AgentUtils::IntToHexString(

+					threadContextInfo_.Edx);

+			registerValueCache_["EBX"] = AgentUtils::IntToHexString(

+					threadContextInfo_.Ebx);

+			registerValueCache_["ESP"] = AgentUtils::IntToHexString(

+					threadContextInfo_.Esp);

+			registerValueCache_["EBP"] = AgentUtils::IntToHexString(

+					threadContextInfo_.Ebp);

+			registerValueCache_["ESI"] = AgentUtils::IntToHexString(

+					threadContextInfo_.Esi);

+			registerValueCache_["EDI"] = AgentUtils::IntToHexString(

+					threadContextInfo_.Edi);

+			registerValueCache_["EIP"] = AgentUtils::IntToHexString(

+					threadContextInfo_.Eip);

+			registerValueCache_["GS"] = AgentUtils::IntToHexString(

+					threadContextInfo_.SegGs);

+			registerValueCache_["FS"] = AgentUtils::IntToHexString(

+					threadContextInfo_.SegFs);

+			registerValueCache_["ES"] = AgentUtils::IntToHexString(

+					threadContextInfo_.SegEs);

+			registerValueCache_["DS"] = AgentUtils::IntToHexString(

+					threadContextInfo_.SegDs);

+			registerValueCache_["CS"] = AgentUtils::IntToHexString(

+					threadContextInfo_.SegCs);

+			registerValueCache_["EFL"] = AgentUtils::IntToHexString(

+					threadContextInfo_.EFlags);

+			registerValueCache_["SS"] = AgentUtils::IntToHexString(

+					threadContextInfo_.SegSs);

+

+			threadContextValid_ = true;

+		}

+	}

+}

+

+void WinThread::SetContextInfo() {

+	if (isSuspended()) {

+		threadContextInfo_.ContextFlags = CONTEXT_ALL;

+		// Set general registers values

+		threadContextInfo_.Eax = AgentUtils::HexStringToInt(

+				registerValueCache_["EAX"]);

+		threadContextInfo_.Ecx = AgentUtils::HexStringToInt(

+				registerValueCache_["ECX"]);

+		threadContextInfo_.Edx = AgentUtils::HexStringToInt(

+				registerValueCache_["EDX"]);

+		threadContextInfo_.Ebx = AgentUtils::HexStringToInt(

+				registerValueCache_["EBX"]);

+		threadContextInfo_.Esp = AgentUtils::HexStringToInt(

+				registerValueCache_["ESP"]);

+		threadContextInfo_.Ebp = AgentUtils::HexStringToInt(

+				registerValueCache_["EBP"]);

+		threadContextInfo_.Esi = AgentUtils::HexStringToInt(

+				registerValueCache_["ESI"]);

+		threadContextInfo_.Edi = AgentUtils::HexStringToInt(

+				registerValueCache_["EDI"]);

+		threadContextInfo_.Eip = AgentUtils::HexStringToInt(

+				registerValueCache_["EIP"]);

+		threadContextInfo_.SegGs = AgentUtils::HexStringToInt(

+				registerValueCache_["GS"]);

+		threadContextInfo_.SegFs = AgentUtils::HexStringToInt(

+				registerValueCache_["FS"]);

+		threadContextInfo_.SegEs = AgentUtils::HexStringToInt(

+				registerValueCache_["ES"]);

+		threadContextInfo_.SegDs = AgentUtils::HexStringToInt(

+				registerValueCache_["DS"]);

+		threadContextInfo_.SegCs = AgentUtils::HexStringToInt(

+				registerValueCache_["CS"]);

+		threadContextInfo_.EFlags = AgentUtils::HexStringToInt(

+				registerValueCache_["EFL"]);

+		threadContextInfo_.SegSs = AgentUtils::HexStringToInt(

+				registerValueCache_["SS"]);

+		SetThreadContext(handle_, &threadContextInfo_);

+	}

+}

+

+WinThread* WinThread::GetThreadByID(int processID, int threadID) {

+	std::pair<int, int> ptPair(processID, threadID);

+	std::map<std::pair<int, int>, WinThread*>::iterator iter = threadIDMap_.find(ptPair);

+	if (iter == threadIDMap_.end())

+		return NULL;

+	else

+		return iter->second;

+}

+

+std::vector<std::string> WinThread::GetRegisterValues(

+		const std::vector<std::string>& registerIDs) {

+	std::vector<std::string> registerValues;

+

+	if (isSuspended()) {

+		EnsureValidContextInfo();

+

+		std::vector<std::string>::const_iterator itVectorData;

+		for (itVectorData = registerIDs.begin(); itVectorData

+				!= registerIDs.end(); itVectorData++) {

+			std::string registerID = *itVectorData;

+			std::string registerValue = registerValueCache_[registerID];

+			registerValues.push_back(registerValue);

+		}

+	}

+

+	return registerValues;

+}

+

+/*

+ * Get pointer to register value cache for a given register.

+ * Return NULL if the register is not found.

+ */

+void* WinThread::getRegisterValueBuffer(const std::string& regName) {

+	void* v = NULL;

+

+	if (regName == "EAX")

+		v = (void*)&threadContextInfo_.Eax;

+	else if (regName == "EBX")

+		v = (void*)&threadContextInfo_.Ebx;

+	else if (regName == "ECX")

+		v = (void*)&threadContextInfo_.Ecx;

+	else if (regName == "EDX")

+		v = (void*)&threadContextInfo_.Edx;

+	else if (regName == "ESP")

+		v = (void*)&threadContextInfo_.Esp;

+	else if (regName == "EBP")

+		v = (void*)&threadContextInfo_.Ebp;

+	else if (regName == "ESI")

+		v = (void*)&threadContextInfo_.Esi;

+	else if (regName == "EDI")

+		v = (void*)&threadContextInfo_.Edi;

+	else if (regName == "EIP")

+		v = (void*)&threadContextInfo_.Eip;

+	else if (regName == "EFL")

+		v = (void*)&threadContextInfo_.EFlags;

+	else if (regName == "GS")

+		v = (void*)&threadContextInfo_.SegGs;

+	else if (regName == "FS")

+		v = (void*)&threadContextInfo_.SegFs;

+	else if (regName == "ES")

+		v = (void*)&threadContextInfo_.SegEs;

+	else if (regName == "DS")

+		v = (void*)&threadContextInfo_.SegDs;

+	else if (regName == "CS")

+		v = (void*)&threadContextInfo_.SegCs;

+	else if (regName == "SS")

+		v = (void*)&threadContextInfo_.SegSs;

+	else {

+		assert(false);

+	}

+

+	return v;

+}

+

+/*

+ * Read one register.

+ * Return binary data buffer, which caller should free by calling delete[].

+ */

+char* WinThread::GetRegisterValue(const std::string& regName, int regSize) {

+

+	char* ret = NULL;

+

+	if (isSuspended()) {

+		EnsureValidContextInfo();

+

+		ret = new char[regSize];

+

+		void* v = getRegisterValueBuffer(regName);

+		assert(v != NULL);

+

+		memcpy((void*)ret, v, regSize);

+	}

+

+	return ret;

+}

+

+bool WinThread::SetRegisterValue(const std::string& regName, int regSize, char* val) {

+

+	if (! isSuspended())

+		return false;

+

+	void* v = getRegisterValueBuffer(regName);

+	assert(v != NULL);

+

+	memcpy(v, (void*)val, regSize);

+	return SetThreadContext(handle_, &threadContextInfo_);

+}

+

+void WinThread::SetRegisterValues(const std::vector<std::string>& registerIDs,

+		const std::vector<std::string>& registerValues) {

+	if (isSuspended()) {

+		std::vector<std::string>::const_reverse_iterator itVectorData;

+		int idx = registerValues.size();

+		for (itVectorData = registerIDs.rbegin(); itVectorData

+				!= registerIDs.rend(); itVectorData++) {

+			std::string registerID = *itVectorData;

+			registerValueCache_[registerID] = registerValues[--idx];

+		}

+

+		SetContextInfo();

+	}

+}

+

+int WinThread::ReadMemory(const ReadWriteMemoryParams& params) throw (AgentException) {

+	return parentProcess_.ReadMemory(params);

+}

+

+int WinThread::WriteMemory(const ReadWriteMemoryParams& params) throw (AgentException) {

+	return parentProcess_.WriteMemory(params);

+}

+

+void WinThread::Terminate(const AgentActionParams& params) throw (AgentException) {

+	parentProcess_.Terminate(params);

+}

+

+void WinThread::Suspend(const AgentActionParams& params) throw (AgentException) {

+	DWORD suspendCount = SuspendThread(handle_);

+	MarkSuspended();

+	EnsureValidContextInfo();

+	exceptionInfo_.ExceptionRecord.ExceptionCode = USER_SUSPEND_THREAD; // "Suspended"

+	isUserSuspended_ = true;

+	if (! isTerminating_)	// don't send Suspend event if we are terminating.

+		EventClientNotifier::SendContextSuspended(this,

+				GetPCAddress(), GetSuspendReason(), GetExceptionMessage());

+	Logger::getLogger().Log(Logger::LOG_NORMAL, "WinThread::Suspend",

+			"suspendCount: %d", suspendCount);

+

+	params.reportSuccessForAction();

+}

+

+void WinThread::Resume(const AgentActionParams& params) throw (AgentException) {

+	if (! isSuspended()) {

+		params.reportSuccessForAction();

+		return;

+	}

+

+	if (isUserSuspended_){

+		ResumeThread(handle_);

+		isUserSuspended_ = false;

+		params.reportSuccessForAction();

+	}

+	else {

+		parentProcess_.GetMonitor()->PostAction(new ResumeContextAction(

+			params, parentProcess_, *this, RM_RESUME));

+	}

+}

+

+/*

+ * Enable single instruction step by setting Trap Flag (TF) bit.

+ */

+void WinThread::EnableSingleStep() {

+#define FLAG_TRACE_BIT 0x100

+	// The bit will be auto-cleared after next resume.

+	threadContextInfo_.EFlags |= FLAG_TRACE_BIT;

+	SetThreadContext(handle_, &threadContextInfo_);

+}

+

+void WinThread::SingleStep(const AgentActionParams& params) throw (AgentException) {

+	parentProcess_.GetMonitor()->PostAction(new ResumeContextAction(

+			params, parentProcess_, *this, RM_STEP_INTO));

+}

+

+void WinThread::PrepareForTermination(const AgentActionParams& params) throw (AgentException) {

+	isTerminating_ = true;

+

+	if (isSuspended()) {

+		Suspend(params);

+		ContinueDebugEvent(parentProcess_.GetOSID(), GetOSID(), DBG_CONTINUE);

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.h b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.h
index 57a0270..e4d99c0 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.h
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.h
@@ -1,101 +1,103 @@
-/*******************************************************************************
- * 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
- *******************************************************************************/
-#pragma once
-
-#include "stdafx.h"
-#include "ThreadContext.h"
-
-#define USER_SUSPEND_THREAD 0
-
-class WinProcess;
-
-class WinThread : public ThreadContext {
-public:
-	WinThread(WinProcess& process, DEBUG_EVENT& debugEvent);
-	virtual ~WinThread(void);
-
-	int GetThreadID();
-
-	static WinThread* GetThreadByID(int processID, int threadID);
-
-	virtual std::vector<std::string> GetRegisterValues(
-			const std::vector<std::string>& registerIDs);
-
-	virtual void SetRegisterValues(const std::vector<std::string>& registerIDs,
-			const std::vector<std::string>& registerValues);
-
-	char*	GetRegisterValue(const std::string& regName, int regSize);
-	bool 	SetRegisterValue(const std::string& regName, int regSize, char* val);
-
-	//
-	// overrides of RunControlContext
-	//
-	virtual int ReadMemory(const ReadWriteMemoryParams& params) throw (AgentException);
-	virtual int WriteMemory(const ReadWriteMemoryParams& params) throw (AgentException);
-
-	virtual void Resume(const AgentActionParams& params) throw (AgentException);
-
-	virtual void Suspend(const AgentActionParams& params) throw (AgentException);
-
-	virtual void Terminate(const AgentActionParams& params) throw (AgentException);
-
-	virtual void SingleStep(const AgentActionParams& params) throw (AgentException);
-	//
-	//	end overrides
-	
-	void PrepareForTermination(const AgentActionParams& params) throw (AgentException);
-
-	void HandleException(DEBUG_EVENT& debugEvent);
-	void HandleExecutableEvent(bool isLoaded, const std::string& exePath,
-			unsigned long baseAddress, unsigned long codeSize);
-
-	/** Address where suspend is reported */
-	ContextAddress GetPCAddress();
-
-	void EnableSingleStep();
-
-private:
-	void initialize();
-
-	void EnsureValidContextInfo();
-	void SetContextInfo();
-	bool isSuspended();
-	void MarkSuspended();
-
-	void AdjustPC();
-
-	/** REASON_xx code for suspend */
-	const char* GetSuspendReason();
-	/** Description for suspend */
-	std::string GetExceptionMessage();
-
-private:
-	void* getRegisterValueBuffer(const std::string& regName);
-
-	std::pair<int, int> threadLookupPair_;
-
-	bool threadContextValid_;
-	bool isSuspended_;
-	bool isTerminating_;
-	bool isUserSuspended_;
-	CONTEXT threadContextInfo_;
-	EXCEPTION_DEBUG_INFO exceptionInfo_;
-	std::map<std::string, std::string> registerValueCache_;
-
-	WinProcess& parentProcess_;
-
-	unsigned long startAddress_;
-	HANDLE handle_;
-	void* localBase_;
-
-	static std::map<std::pair<int, int>, WinThread*> threadIDMap_;
-
-};
+/*******************************************************************************

+ * 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

+ *******************************************************************************/

+#pragma once

+

+#include "stdafx.h"

+#include "ThreadContext.h"

+

+#define USER_SUSPEND_THREAD 0

+

+class WinProcess;

+

+class WinThread : public ThreadContext {

+public:

+	WinThread(WinProcess& process, DEBUG_EVENT& debugEvent);

+	virtual ~WinThread(void);

+

+	int GetThreadID();

+

+	static WinThread* GetThreadByID(int processID, int threadID);

+

+	virtual std::vector<std::string> GetRegisterValues(

+			const std::vector<std::string>& registerIDs);

+

+	virtual void SetRegisterValues(const std::vector<std::string>& registerIDs,

+			const std::vector<std::string>& registerValues);

+

+	char*	GetRegisterValue(const std::string& regName, int regSize);

+	bool 	SetRegisterValue(const std::string& regName, int regSize, char* val);

+

+	//

+	// overrides of RunControlContext

+	//

+	virtual int ReadMemory(const ReadWriteMemoryParams& params) throw (AgentException);

+	virtual int WriteMemory(const ReadWriteMemoryParams& params) throw (AgentException);

+

+	virtual void Resume(const AgentActionParams& params) throw (AgentException);

+

+	virtual void Suspend(const AgentActionParams& params) throw (AgentException);

+

+	virtual void Terminate(const AgentActionParams& params) throw (AgentException);

+

+	virtual void SingleStep(const AgentActionParams& params) throw (AgentException);

+	//

+	//	end overrides

+	

+	void PrepareForTermination(const AgentActionParams& params) throw (AgentException);

+

+	void HandleException(DEBUG_EVENT& debugEvent);

+	void HandleExecutableEvent(bool isLoaded, const std::string& exePath,

+			unsigned long baseAddress, unsigned long codeSize);

+

+	/* Address where suspend is reported */

+	ContextAddress GetPCAddress();

+

+	void EnableSingleStep();

+

+	DWORD GetContinueStatus();

+

+private:

+	void initialize();

+

+	void EnsureValidContextInfo();

+	void SetContextInfo();

+	bool isSuspended();

+	void MarkSuspended();

+

+	void AdjustPC();

+

+	/** REASON_xx code for suspend */

+	const char* GetSuspendReason();

+	/** Description for suspend */

+	std::string GetExceptionMessage();

+

+private:

+	void* getRegisterValueBuffer(const std::string& regName);

+

+	std::pair<int, int> threadLookupPair_;

+

+	bool threadContextValid_;

+	bool isSuspended_;

+	bool isTerminating_;

+	bool isUserSuspended_;

+	CONTEXT threadContextInfo_;

+	EXCEPTION_DEBUG_INFO exceptionInfo_;

+	std::map<std::string, std::string> registerValueCache_;

+

+	WinProcess& parentProcess_;

+

+	unsigned long startAddress_;

+	HANDLE handle_;

+	void* localBase_;

+

+	static std::map<std::pair<int, int>, WinThread*> threadIDMap_;

+

+};