diff --git a/src/plugins/debugger/cdb/cdb.pri b/src/plugins/debugger/cdb/cdb.pri
index 6ac5997efa9c610c48920b59481b94bfe55bb5f6..050083339741180d4df7e8bf7167810346ab61a7 100644
--- a/src/plugins/debugger/cdb/cdb.pri
+++ b/src/plugins/debugger/cdb/cdb.pri
@@ -1,32 +1,8 @@
-# Detect presence of "Debugging Tools For Windows"
-# in case VS compilers are used.      
+include(cdbcore.pri)
 
-win32 {
-contains(QMAKE_CXX, cl) {
-
-CDB_PATH="$$(CDB_PATH)"
-isEmpty(CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows/sdk"
-
-!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows (x86)/sdk"
-!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows (x64)/sdk"
-!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows 64-bit/sdk"
-
-exists($$CDB_PATH) {
-
-message("Adding support for $$CDB_PATH")
-
-DEFINES+=CDB_ENABLED
-
-CDB_PLATFORM=i386
-
-INCLUDEPATH*=$$CDB_PATH
-INCLUDEPATH*=$$PWD
-DEPENDPATH*=$$PWD
-
-CDB_LIBPATH=$$CDB_PATH/lib/$$CDB_PLATFORM
+!isEmpty(CDB_PATH) {
 
 HEADERS += \
-    $$PWD/cdbcom.h \
     $$PWD/cdbdebugengine.h \
     $$PWD/cdbdebugengine_p.h \
     $$PWD/cdbdebugeventcallback.h \
@@ -63,8 +39,4 @@ SOURCES += \
 FORMS += $$PWD/cdboptionspagewidget.ui
 
 LIBS+=-lpsapi
-} else {
-   message("Debugging Tools for Windows could not be found in $$CDB_PATH")
-} # exists($$CDB_PATH)
-} # (QMAKE_CXX, cl)
-} # win32
+}
diff --git a/src/plugins/debugger/cdb/cdbassembler.cpp b/src/plugins/debugger/cdb/cdbassembler.cpp
index 268c664ddb0e20fe527f44ac6ff42f0a5c1f56b8..db21fbf1e76cc97db940c1022491c52a1b822edd 100644
--- a/src/plugins/debugger/cdb/cdbassembler.cpp
+++ b/src/plugins/debugger/cdb/cdbassembler.cpp
@@ -70,7 +70,7 @@ bool getRegisters(CIDebugControl *ctl,
     ULONG count;
     HRESULT hr = ireg->GetNumberRegisters(&count);
     if (FAILED(hr)) {
-        *errorMessage= msgComFailed("GetNumberRegisters", hr);
+        *errorMessage= CdbCore::msgComFailed("GetNumberRegisters", hr);
         return false;
     }
     if (!count)
@@ -80,7 +80,7 @@ bool getRegisters(CIDebugControl *ctl,
     for (ULONG r = 0; r < count; r++) {
         hr = ireg->GetDescriptionWide(r, wszBuf, MAX_PATH - 1, 0, 0);
         if (FAILED(hr)) {
-            *errorMessage= msgComFailed("GetDescriptionWide", hr);
+            *errorMessage= CdbCore::msgComFailed("GetDescriptionWide", hr);
             return false;
         }
         Register reg;
@@ -93,13 +93,13 @@ bool getRegisters(CIDebugControl *ctl,
     memset(valuesPtr, 0, count * sizeof(DEBUG_VALUE));
     hr = ireg->GetValues(count, 0, 0, valuesPtr);
     if (FAILED(hr)) {
-        *errorMessage= msgComFailed("GetValues", hr);
+        *errorMessage= CdbCore::msgComFailed("GetValues", hr);
         return false;
     }
     if (base < 2)
         base = 10;
     for (ULONG r = 0; r < count; r++)
-        (*registers)[r].value = CdbSymbolGroupContext::debugValueToString(values.at(r), ctl, 0, base);
+        (*registers)[r].value = CdbCore::debugValueToString(values.at(r), 0, base, ctl);
     return true;
 }
 
@@ -211,8 +211,7 @@ void DisassemblerOutputParser::parse(const QStringList &l)
     }
 }
 
-bool dissassemble(CIDebugClient *client,
-                  CIDebugControl *ctl,
+bool dissassemble(CdbCore::CoreEngine *engine,
                   ULONG64 offset,
                   unsigned long beforeLines,
                   unsigned long afterLines,
@@ -222,26 +221,11 @@ bool dissassemble(CIDebugClient *client,
 {
     if (debugCDB)
         qDebug() << Q_FUNC_INFO << offset;
-
-    const ULONG flags = DEBUG_DISASM_MATCHING_SYMBOLS|DEBUG_DISASM_SOURCE_LINE_NUMBER|DEBUG_DISASM_SOURCE_FILE_NAME;
-    // Catch the output by temporarily setting another handler.
-    // We use the method that outputs to the output handler as it
-    // conveniently provides the 'beforeLines' context (stepping back
-    // in assembler code). We build a complete string first as line breaks
-    // may occur in-between messages.
-    StringOutputHandler stringHandler;
-    OutputRedirector redir(client, &stringHandler);
-    // For some reason, we need to output to "all clients"
-    const HRESULT hr =  ctl->OutputDisassemblyLines(DEBUG_OUTCTL_ALL_CLIENTS,
-                                                    beforeLines, beforeLines + afterLines,
-                                                    offset, flags, 0, 0, 0, 0);
-    if (FAILED(hr)) {
-        *errorMessage= QString::fromLatin1("Unable to disassamble at 0x%1: %2").
-                       arg(offset, 0, 16).arg(msgComFailed("OutputDisassemblyLines", hr));
+    QString lines;
+    if (!engine->dissassemble(offset, beforeLines, afterLines, &lines, errorMessage))
         return false;
-    }
     DisassemblerOutputParser parser(str, addressFieldWidth);
-    parser.parse(stringHandler.result().split(QLatin1Char('\n')));
+    parser.parse(lines.split(QLatin1Char('\n')));
     return true;
 }
 
diff --git a/src/plugins/debugger/cdb/cdbassembler.h b/src/plugins/debugger/cdb/cdbassembler.h
index b029f67fd6d8d8304501a165d78ebe9e34ae77a4..a6ae15f098b4187d2be4647e87ce02dd4d62f560 100644
--- a/src/plugins/debugger/cdb/cdbassembler.h
+++ b/src/plugins/debugger/cdb/cdbassembler.h
@@ -39,6 +39,10 @@ QT_BEGIN_NAMESPACE
 class QTextStream;
 QT_END_NAMESPACE
 
+namespace CdbCore {
+    class CoreEngine;
+}
+
 namespace Debugger {
 namespace Internal {
 
@@ -51,8 +55,7 @@ bool getRegisters(CIDebugControl *ctl,
                   QString *errorMessage,
                   int base = 10 /* 16 for hex, etc */);
 
-bool dissassemble(CIDebugClient *client,
-                  CIDebugControl *ctl,
+bool dissassemble(CdbCore::CoreEngine *engine,
                   ULONG64 offset,
                   unsigned long beforeLines,
                   unsigned long afterLines,
diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp
index 9ec69d3be35faff45bf6f86e975af591967fe4eb..6b3fda2c72740e8bad8bda2840f3a370a213b6ce 100644
--- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp
+++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp
@@ -161,7 +161,7 @@ bool CDBBreakPoint::apply(CIDebugBreakpoint *ibp, QString *errorMessage) const
     const HRESULT hr = ibp->SetOffsetExpressionWide(reinterpret_cast<PCWSTR>(expr.utf16()));
     if (FAILED(hr)) {
         *errorMessage = QString::fromLatin1("Unable to set breakpoint '%1' : %2").
-                        arg(expr, msgComFailed("SetOffsetExpressionWide", hr));
+                        arg(expr, CdbCore::msgComFailed("SetOffsetExpressionWide", hr));
         return false;
     }
     // Pass Count is ignoreCount + 1
@@ -192,7 +192,7 @@ bool CDBBreakPoint::add(CIDebugControl* debugControl,
         *id = 0;
     HRESULT hr = debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &ibp);
     if (FAILED(hr)) {
-        *errorMessage = msgCannotAddBreakPoint(msgComFailed("AddBreakpoint2", hr));
+        *errorMessage = msgCannotAddBreakPoint(CdbCore::msgComFailed("AddBreakpoint2", hr));
         return false;
     }
     if (!ibp) {
@@ -210,7 +210,7 @@ bool CDBBreakPoint::add(CIDebugControl* debugControl,
     if (id) {
         hr = ibp->GetId(id);
         if (FAILED(hr)) {
-            *errorMessage = msgCannotAddBreakPoint(msgComFailed("GetId", hr));
+            *errorMessage = msgCannotAddBreakPoint(CdbCore::msgComFailed("GetId", hr));
             return false;
         }
     }
@@ -326,7 +326,7 @@ bool CDBBreakPoint::retrieve(CIDebugBreakpoint *ibp, QString *errorMessage)
     const HRESULT hr =ibp->GetOffsetExpressionWide(wszBuf, MAX_PATH, 0);
     if (FAILED(hr)) {
         *errorMessage = QString::fromLatin1("Cannot retrieve breakpoint: %1").
-                        arg(msgComFailed("GetOffsetExpressionWide", hr));
+                        arg(CdbCore::msgComFailed("GetOffsetExpressionWide", hr));
         return false;
     }
     // Pass Count is ignoreCount + 1
@@ -398,7 +398,7 @@ bool CDBBreakPoint::getBreakPointCount(CIDebugControl* debugControl, ULONG *coun
     if (FAILED(hr)) {
         if (errorMessage)
             *errorMessage = QString::fromLatin1("Cannot determine breakpoint count: %1").
-                            arg(msgComFailed("GetNumberBreakpoints", hr));
+                            arg(CdbCore::msgComFailed("GetNumberBreakpoints", hr));
         return false;
     }
     return true;
@@ -416,7 +416,7 @@ bool CDBBreakPoint::getBreakPoints(CIDebugControl* debugControl, QList<CDBBreakP
         const HRESULT hr = debugControl->GetBreakpointByIndex2(b, &ibp);
         if (FAILED(hr)) {
             *errorMessage = QString::fromLatin1("Cannot retrieve breakpoint %1: %2").
-                            arg(b).arg(msgComFailed("GetBreakpointByIndex2", hr));
+                            arg(b).arg(CdbCore::msgComFailed("GetBreakpointByIndex2", hr));
             return false;
         }
         CDBBreakPoint bp;
@@ -438,7 +438,7 @@ static IDebugBreakpoint2 *breakPointById(CIDebugControl *ctl, unsigned long id,
     CIDebugBreakpoint *ibp = 0;
     const HRESULT hr = ctl->GetBreakpointById2(id, &ibp);
     if (FAILED(hr)) {
-        *errorMessage = msgNoBreakPointWithId(id, msgComFailed("GetBreakpointById2", hr));
+        *errorMessage = msgNoBreakPointWithId(id, CdbCore::msgComFailed("GetBreakpointById2", hr));
         return 0;
     }
     if (!ibp) {
@@ -458,7 +458,7 @@ static bool removeBreakPointById(CIDebugControl *ctl, unsigned long id, QString
         return false;
     const HRESULT hr = ctl->RemoveBreakpoint2(ibp);
     if (FAILED(hr)) {
-        *errorMessage = QString::fromLatin1("Cannot remove breakpoint %1: %2").arg(id).arg(msgComFailed("RemoveBreakpointById2", hr));
+        *errorMessage = QString::fromLatin1("Cannot remove breakpoint %1: %2").arg(id).arg(CdbCore::msgComFailed("RemoveBreakpointById2", hr));
         return false;
     }
     return true;
@@ -486,7 +486,7 @@ static bool setBreakPointEnabledById(CIDebugControl *ctl, unsigned long id, bool
     ULONG flags;
     HRESULT hr = ibp->GetFlags(&flags);
     if (FAILED(hr)) {
-        *errorMessage = msgCannotSetBreakPointEnabled(id, enabled, msgComFailed("GetFlags", hr));
+        *errorMessage = msgCannotSetBreakPointEnabled(id, enabled, CdbCore::msgComFailed("GetFlags", hr));
         return false;
     }
     const bool wasEnabled = (flags & DEBUG_BREAKPOINT_ENABLED);
@@ -500,7 +500,7 @@ static bool setBreakPointEnabledById(CIDebugControl *ctl, unsigned long id, bool
     }
     hr = ibp->SetFlags(flags);
     if (FAILED(hr)) {
-        *errorMessage = msgCannotSetBreakPointEnabled(id, enabled, msgComFailed("SetFlags", hr));
+        *errorMessage = msgCannotSetBreakPointEnabled(id, enabled, CdbCore::msgComFailed("SetFlags", hr));
         return false;
     }
     return true;
diff --git a/src/plugins/debugger/cdb/cdbcore.pri b/src/plugins/debugger/cdb/cdbcore.pri
new file mode 100644
index 0000000000000000000000000000000000000000..1232f516b6e953a98215318ba123174bcc8c93e1
--- /dev/null
+++ b/src/plugins/debugger/cdb/cdbcore.pri
@@ -0,0 +1,43 @@
+# Detect presence of "Debugging Tools For Windows"
+# in case VS compilers are used.      
+
+win32 {
+contains(QMAKE_CXX, cl) {
+
+CDB_PATH="$$(CDB_PATH)"
+isEmpty(CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows/sdk"
+
+!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows (x86)/sdk"
+!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows (x64)/sdk"
+!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows 64-bit/sdk"
+
+exists($$CDB_PATH) {
+
+message("Adding support for $$CDB_PATH")
+
+DEFINES+=CDB_ENABLED
+
+CDB_PLATFORM=i386
+
+INCLUDEPATH*=$$CDB_PATH
+CDB_LIBPATH=$$CDB_PATH/lib/$$CDB_PLATFORM
+
+HEADERS += \
+    $$PWD/cdbcom.h \
+    $$PWD/coreengine.h \
+    $$PWD/debugoutputbase.h \
+    $$PWD/debugeventcallbackbase.h
+SOURCES += \    
+    $$PWD/coreengine.cpp \
+    $$PWD/debugoutputbase.cpp \
+    $$PWD/debugeventcallbackbase.cpp
+
+INCLUDEPATH*=$$PWD
+DEPENDPATH*=$$PWD
+
+} else {
+   message("Debugging Tools for Windows could not be found in $$CDB_PATH")
+   CDB_PATH=""
+} # exists($$CDB_PATH)
+} # (QMAKE_CXX, cl)
+} # win32
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp
index fc4d0136fb5588e09273c0259c0d082108421b0e..26f269581e1f76f3d264305fd440e03f1a8a31f0 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp
@@ -29,6 +29,8 @@
 
 #include "cdbdebugengine.h"
 #include "cdbdebugengine_p.h"
+#include "cdbdebugoutput.h"
+#include "cdbdebugeventcallback.h"
 #include "cdbstacktracecontext.h"
 #include "cdbstackframecontext.h"
 #include "cdbsymbolgroupcontext.h"
@@ -71,10 +73,6 @@
 #define DBGHELP_TRANSLATE_TCHAR
 #include <inc/Dbghelp.h>
 
-static const char *dbgHelpDllC = "dbghelp";
-static const char *dbgEngineDllC = "dbgeng";
-static const char *debugCreateFuncC = "DebugCreate";
-
 static const char *localSymbolRootC = "local";
 
 namespace Debugger {
@@ -84,56 +82,18 @@ typedef QList<WatchData> WatchList;
 
 // ----- Message helpers
 
-QString msgDebugEngineComResult(HRESULT hr)
-{
-    switch (hr) {
-        case S_OK:
-        return QLatin1String("S_OK");
-        case S_FALSE:
-        return QLatin1String("S_FALSE");
-        case E_FAIL:
-        break;
-        case E_INVALIDARG:
-        return QLatin1String("E_INVALIDARG");
-        case E_NOINTERFACE:
-        return QLatin1String("E_NOINTERFACE");
-        case E_OUTOFMEMORY:
-        return QLatin1String("E_OUTOFMEMORY");
-        case E_UNEXPECTED:
-        return QLatin1String("E_UNEXPECTED");
-        case E_NOTIMPL:
-        return QLatin1String("E_NOTIMPL");
-    }
-    if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
-        return QLatin1String("ERROR_ACCESS_DENIED");;
-    if (hr == HRESULT_FROM_NT(STATUS_CONTROL_C_EXIT))
-        return QLatin1String("STATUS_CONTROL_C_EXIT");
-    return QLatin1String("E_FAIL ") + Utils::winErrorMessage(HRESULT_CODE(hr));
-}
-
 static QString msgStackIndexOutOfRange(int idx, int size)
 {
     return QString::fromLatin1("Frame index %1 out of range (%2).").arg(idx).arg(size);
 }
 
-QString msgComFailed(const char *func, HRESULT hr)
-{
-    return QString::fromLatin1("%1 failed: %2").arg(QLatin1String(func), msgDebugEngineComResult(hr));
-}
-
 QString msgDebuggerCommandFailed(const QString &command, HRESULT hr)
 {
-    return QString::fromLatin1("Unable to execute '%1': %2").arg(command, msgDebugEngineComResult(hr));
+    return QString::fromLatin1("Unable to execute '%1': %2").arg(command, CdbCore::msgDebugEngineComResult(hr));
 }
 
 static const char *msgNoStackTraceC = "Internal error: no stack trace present.";
 
-static inline QString msgLibLoadFailed(const QString &lib, const QString &why)
-{
-    return CdbDebugEngine::tr("Unable to load the debugger engine library '%1': %2").
-            arg(lib, why);
-}
-
 // Format function failure message. Pass in Q_FUNC_INFO
 static QString msgFunctionFailed(const char *func, const QString &why)
 {
@@ -152,148 +112,6 @@ static QString msgFunctionFailed(const char *func, const QString &why)
 
 // ----- Engine helpers
 
-static inline ULONG getInterruptTimeOutSecs(CIDebugControl *ctl)
-{
-    ULONG rc = 0;
-    ctl->GetInterruptTimeout(&rc);
-    return rc;
-}
-
-bool getExecutionStatus(CIDebugControl *ctl,
-                        ULONG *executionStatus,
-                        QString *errorMessage /* = 0 */)
-{
-    const HRESULT hr = ctl->GetExecutionStatus(executionStatus);
-    if (FAILED(hr)) {
-        if (errorMessage)
-            *errorMessage = msgComFailed("GetExecutionStatus", hr);
-        return false;
-    }
-    return true;
-}
-
-const char *executionStatusString(ULONG executionStatus)
-{
-    switch (executionStatus) {
-    case DEBUG_STATUS_NO_CHANGE:
-        return "DEBUG_STATUS_NO_CHANGE";
-    case DEBUG_STATUS_GO:
-        return "DEBUG_STATUS_GO";
-    case DEBUG_STATUS_GO_HANDLED:
-        return "DEBUG_STATUS_GO_HANDLED";
-    case DEBUG_STATUS_GO_NOT_HANDLED:
-        return "DEBUG_STATUS_GO_NOT_HANDLED";
-    case DEBUG_STATUS_STEP_OVER:
-        return "DEBUG_STATUS_STEP_OVER";
-    case DEBUG_STATUS_STEP_INTO:
-        return "DEBUG_STATUS_STEP_INTO";
-    case DEBUG_STATUS_BREAK:
-        return "DEBUG_STATUS_BREAK";
-    case DEBUG_STATUS_NO_DEBUGGEE:
-        return "DEBUG_STATUS_NO_DEBUGGEE";
-    case DEBUG_STATUS_STEP_BRANCH:
-        return "DEBUG_STATUS_STEP_BRANCH";
-    case DEBUG_STATUS_IGNORE_EVENT:
-        return "DEBUG_STATUS_IGNORE_EVENT";
-    case DEBUG_STATUS_RESTART_REQUESTED:
-        return "DEBUG_STATUS_RESTART_REQUESTED";
-    case DEBUG_STATUS_REVERSE_GO:
-        return "DEBUG_STATUS_REVERSE_GO";
-          case DEBUG_STATUS_REVERSE_STEP_BRANCH:
-        return "DEBUG_STATUS_REVERSE_STEP_BRANCH";
-    case DEBUG_STATUS_REVERSE_STEP_OVER:
-        return "DEBUG_STATUS_REVERSE_STEP_OVER";
-    case DEBUG_STATUS_REVERSE_STEP_INTO:
-        return "DEBUG_STATUS_REVERSE_STEP_INTO";
-        default:
-        break;
-    }
-    return "<Unknown execution status>";
-}
-
-// Debug convenience
-const char *executionStatusString(CIDebugControl *ctl)
-{
-    ULONG executionStatus;
-    if (getExecutionStatus(ctl, &executionStatus))
-        return executionStatusString(executionStatus);
-    return "<failed>";
-}
-
-// --------- DebuggerEngineLibrary
-DebuggerEngineLibrary::DebuggerEngineLibrary() :
-    m_debugCreate(0)
-{
-}
-
-// Build a lib name as "Path\x.dll"
-static inline QString libPath(const QString &libName, const QString &path = QString())
-{
-    QString rc = path;
-    if (!rc.isEmpty())
-        rc += QDir::separator();
-    rc += libName;
-    rc += QLatin1String(".dll");
-    return rc;
-}
-
-bool DebuggerEngineLibrary::init(const QString &path,
-                                 QString *dbgEngDLL,
-                                 QString *errorMessage)
-{
-    // Load the dependent help lib first
-    const QString helpLibPath = libPath(QLatin1String(dbgHelpDllC), path);
-    QLibrary helpLib(helpLibPath, 0);
-    if (!helpLib.isLoaded() && !helpLib.load()) {
-        *errorMessage = msgLibLoadFailed(helpLibPath, helpLib.errorString());
-        return false;
-    }
-    // Load dbgeng lib
-    const QString engineLibPath = libPath(QLatin1String(dbgEngineDllC), path);
-    QLibrary lib(engineLibPath, 0);
-    if (!lib.isLoaded() && !lib.load()) {
-        *errorMessage = msgLibLoadFailed(engineLibPath, lib.errorString());
-        return false;
-    }
-    *dbgEngDLL = engineLibPath;
-    // Locate symbols
-    void *createFunc = lib.resolve(debugCreateFuncC);
-    if (!createFunc) {
-        *errorMessage = CdbDebugEngine::tr("Unable to resolve '%1' in the debugger engine library '%2'").
-                        arg(QLatin1String(debugCreateFuncC), QLatin1String(dbgEngineDllC));
-        return false;
-    }
-    m_debugCreate = static_cast<DebugCreateFunction>(createFunc);
-    return true;
-}
-
-// ----- SyntaxSetter
-SyntaxSetter::SyntaxSetter(CIDebugControl *ctl, ULONG desiredSyntax) :
-    m_desiredSyntax(desiredSyntax),
-    m_ctl(ctl)
-{
-    m_ctl->GetExpressionSyntax(&m_oldSyntax);
-    if (m_oldSyntax != m_desiredSyntax)
-        m_ctl->SetExpressionSyntax(m_desiredSyntax);
-}
-
-SyntaxSetter::~SyntaxSetter()
-{
-    if (m_oldSyntax != m_desiredSyntax)
-        m_ctl->SetExpressionSyntax(m_oldSyntax);
-}
-
-// CdbComInterfaces
-CdbComInterfaces::CdbComInterfaces() :
-    debugClient(0),
-    debugControl(0),
-    debugSystemObjects(0),
-    debugSymbols(0),
-    debugRegisters(0),
-    debugDataSpaces(0)
-{
-}
-
 // --- CdbDebugEnginePrivate
 
 CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *manager,
@@ -303,82 +121,41 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *manager,
     m_hDebuggeeProcess(0),
     m_hDebuggeeThread(0),
     m_breakEventMode(BreakEventHandle),
-    m_dumper(new CdbDumperHelper(manager, &m_cif)),
+    m_dumper(new CdbDumperHelper(manager, this)),
     m_currentThreadId(-1),
     m_eventThreadId(-1),
     m_interruptArticifialThreadId(-1),
     m_ignoreInitialBreakPoint(false),
     m_interrupted(false),    
-    m_watchTimer(-1),
-    m_debugEventCallBack(engine),
     m_engine(engine),
     m_currentStackTrace(0),
     m_firstActivatedFrame(true),
     m_inferiorStartupComplete(false),
     m_mode(AttachCore)
 {
+    connect(this, SIGNAL(watchTimerDebugEvent()), this, SLOT(handleDebugEvent()));
 }
 
 bool CdbDebugEnginePrivate::init(QString *errorMessage)
 {
     enum {  bufLen = 10240 };
-    // Load the DLL
-    DebuggerEngineLibrary lib;
-    if (!lib.init(m_options->path, &m_dbengDLL, errorMessage))
-        return false;
-    // Initialize the COM interfaces
-    HRESULT hr;
-    hr = lib.debugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_cif.debugClient));
-    if (FAILED(hr)) {
-        *errorMessage = QString::fromLatin1("Creation of IDebugClient5 failed: %1").arg(msgDebugEngineComResult(hr));
-        return false;
-    }
-
-    m_cif.debugClient->SetOutputCallbacksWide(&m_debugOutputCallBack);
-    m_cif.debugClient->SetEventCallbacksWide(&m_debugEventCallBack);
-
-    hr = lib.debugCreate( __uuidof(IDebugControl4), reinterpret_cast<void**>(&m_cif.debugControl));
-    if (FAILED(hr)) {
-        *errorMessage = QString::fromLatin1("Creation of IDebugControl4 failed: %1").arg(msgDebugEngineComResult(hr));
-        return false;
-    }
-
-    setCodeLevel();
-
-    hr = lib.debugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_cif.debugSystemObjects));
-    if (FAILED(hr)) {
-        *errorMessage = QString::fromLatin1("Creation of IDebugSystemObjects4 failed: %1").arg(msgDebugEngineComResult(hr));
-        return false;
-    }
-
-    hr = lib.debugCreate( __uuidof(IDebugSymbols3), reinterpret_cast<void**>(&m_cif.debugSymbols));
-    if (FAILED(hr)) {
-        *errorMessage = QString::fromLatin1("Creation of IDebugSymbols3 failed: %1").arg(msgDebugEngineComResult(hr));
-        return false;
-    }
-
-    WCHAR buf[bufLen];
-    hr = m_cif.debugSymbols->GetImagePathWide(buf, bufLen, 0);
-    if (FAILED(hr)) {
-        *errorMessage = msgComFailed("GetImagePathWide", hr);
-        return false;
-    }
-    m_baseImagePath = QString::fromUtf16(buf);
-
-    hr = lib.debugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_cif.debugRegisters));
-    if (FAILED(hr)) {
-        *errorMessage = QString::fromLatin1("Creation of IDebugRegisters2 failed: %1").arg(msgDebugEngineComResult(hr));
-        return false;
-    }
 
-    hr = lib.debugCreate( __uuidof(IDebugDataSpaces4), reinterpret_cast<void**>(&m_cif.debugDataSpaces));
-    if (FAILED(hr)) {
-        *errorMessage = QString::fromLatin1("Creation of IDebugDataSpaces4 failed: %1").arg(msgDebugEngineComResult(hr));
+    if (!CdbCore::CoreEngine::init(m_options->path, errorMessage))
         return false;
-    }
+    CdbDebugOutput *output = new CdbDebugOutput;
+    setDebugOutput(DebugOutputBasePtr(output));
+    connect(output, SIGNAL(debuggerOutput(int,QString)),
+            manager(), SLOT(showDebuggerOutput(int,QString)));
+    connect(output, SIGNAL(debuggerInputPrompt(int,QString)),
+            manager(), SLOT(showDebuggerInput(int,QString)));
+    connect(output, SIGNAL(debuggeeOutput(QString)),
+            manager(), SLOT(showApplicationOutput(QString)));
+    connect(output, SIGNAL(debuggeeInputPrompt(QString)),
+            manager(), SLOT(showApplicationOutput(QString)));
+
+    setDebugEventCallback(DebugEventCallbackBasePtr(new CdbDebugEventCallback(m_engine)));
+    updateCodeLevel();
 
-    if (debugCDB)
-        qDebug() << QString::fromLatin1("CDB Initialization succeeded, interrupt time out %1s.").arg(getInterruptTimeOutSecs(m_cif.debugControl));
     return true;
 }
 
@@ -395,49 +172,16 @@ IDebuggerEngine *CdbDebugEngine::create(Debugger::DebuggerManager *manager,
     return 0;
 }
 
-// Adapt code level setting to the setting of the action.
-static inline const char *codeLevelName(ULONG level)
+void  CdbDebugEnginePrivate::updateCodeLevel()
 {
-    return level == DEBUG_LEVEL_ASSEMBLY ? "assembly" : "source";
-}
-
-bool CdbDebugEnginePrivate::setCodeLevel()
-{
-    const ULONG codeLevel = theDebuggerBoolSetting(OperateByInstruction) ?
-                            DEBUG_LEVEL_ASSEMBLY : DEBUG_LEVEL_SOURCE;
-    ULONG currentCodeLevel = DEBUG_LEVEL_ASSEMBLY;
-    HRESULT hr = m_cif.debugControl->GetCodeLevel(&currentCodeLevel);
-    if (FAILED(hr)) {
-        m_engine->warning(QString::fromLatin1("Cannot determine code level: %1").arg(msgComFailed("GetCodeLevel", hr)));
-        return true;
-    }
-    if (debugCDB)
-        qDebug() << Q_FUNC_INFO << "\nSetting code level to " << codeLevelName(codeLevel) << " (was" << codeLevelName(currentCodeLevel) << ')';
-    if (currentCodeLevel == codeLevel)
-        return false;
-    hr = m_cif.debugControl->SetCodeLevel(codeLevel);
-    if (FAILED(hr)) {
-        m_engine->warning(QString::fromLatin1("Cannot set code level: %1").arg(msgComFailed("SetCodeLevel", hr)));
-        return false;
-    }
-    return true;
+    const CdbCore::CoreEngine::CodeLevel cl = theDebuggerBoolSetting(OperateByInstruction) ?
+                                              CdbCore::CoreEngine::CodeLevelAssembly : CdbCore::CoreEngine::CodeLevelSource;
+    setCodeLevel(cl);
 }
 
 CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
 {
     cleanStackTrace();
-    if (m_cif.debugClient)
-        m_cif.debugClient->Release();
-    if (m_cif.debugControl)
-        m_cif.debugControl->Release();
-    if (m_cif.debugSystemObjects)
-        m_cif.debugSystemObjects->Release();
-    if (m_cif.debugSymbols)
-        m_cif.debugSymbols->Release();
-    if (m_cif.debugRegisters)
-        m_cif.debugRegisters->Release();
-    if (m_cif.debugDataSpaces)
-        m_cif.debugDataSpaces->Release();
 }
 
 DebuggerManager *CdbDebugEnginePrivate::manager() const
@@ -477,14 +221,6 @@ CdbDebugEngine::CdbDebugEngine(DebuggerManager *manager, const QSharedPointer<Cd
             this, SLOT(slotConsoleStubStarted()));
     connect(&m_d->m_consoleStubProc, SIGNAL(wrapperStopped()),
             this, SLOT(slotConsoleStubTerminated()));
-    connect(&m_d->m_debugOutputCallBack, SIGNAL(debuggerOutput(int,QString)),
-            manager, SLOT(showDebuggerOutput(int,QString)));
-    connect(&m_d->m_debugOutputCallBack, SIGNAL(debuggerInputPrompt(int,QString)),
-            manager, SLOT(showDebuggerInput(int,QString)));
-    connect(&m_d->m_debugOutputCallBack, SIGNAL(debuggeeOutput(QString)),
-            manager, SLOT(showApplicationOutput(QString)));
-    connect(&m_d->m_debugOutputCallBack, SIGNAL(debuggeeInputPrompt(QString)),
-            manager, SLOT(showApplicationOutput(QString)));
 }
 
 CdbDebugEngine::~CdbDebugEngine()
@@ -499,26 +235,6 @@ void CdbDebugEngine::setState(DebuggerState state, const char *func, int line)
     IDebuggerEngine::setState(state);
 }
 
-void CdbDebugEngine::startWatchTimer()
-{
-    if (debugCDB)
-        qDebug() << Q_FUNC_INFO;
-
-    if (m_d->m_watchTimer == -1)
-        m_d->m_watchTimer = startTimer(0);
-}
-
-void CdbDebugEngine::killWatchTimer()
-{
-    if (debugCDB)
-        qDebug() << Q_FUNC_INFO;
-
-    if (m_d->m_watchTimer != -1) {
-        killTimer(m_d->m_watchTimer);
-        m_d->m_watchTimer = -1;
-    }
-}
-
 void CdbDebugEngine::shutdown()
 {
     exitDebugger();
@@ -543,7 +259,7 @@ QString CdbDebugEngine::editorToolTip(const QString &exp, const QString &functio
     // No function/symbol context found, try to evaluate in current context.
     // Do not append type as this will mostly be 'long long' for integers, etc.
     QString type;
-    if (!evaluateExpression(exp, &rc, &type, &errorMessage))
+    if (!m_d->evaluateExpression(exp, &rc, &type, &errorMessage))
         return QString();
     return rc;
 }
@@ -601,7 +317,7 @@ void CdbDebugEnginePrivate::checkVersion()
         versionNotChecked = false;
         // Get engine DLL version
         QString errorMessage;
-        const QString version = Utils::winGetDLLVersion(Utils::WinDLLProductVersion, m_dbengDLL, &errorMessage);
+        const QString version = Utils::winGetDLLVersion(Utils::WinDLLProductVersion, dbengDLL(), &errorMessage);
         if (version.isEmpty()) {
             qWarning("%s\n", qPrintable(errorMessage));
             return;
@@ -663,12 +379,12 @@ void CdbDebugEngine::startDebugger(const QSharedPointer<DebuggerStartParameters>
     bool rc = false;
     bool needWatchTimer = false;
     m_d->clearForRun();
-    m_d->setCodeLevel();
+    m_d->updateCodeLevel();
     m_d->m_ignoreInitialBreakPoint = false;
     switch (mode) {
     case AttachExternal:
     case AttachCrashedExternal:
-        rc = startAttachDebugger(sp->attachPID, mode, &errorMessage);
+        rc = m_d->startAttachDebugger(sp->attachPID, mode, &errorMessage);
         needWatchTimer = true; // Fetch away module load, etc. even if crashed
         break;
     case StartInternal:
@@ -695,7 +411,7 @@ void CdbDebugEngine::startDebugger(const QSharedPointer<DebuggerStartParameters>
     }
     if (rc) {
         if (needWatchTimer)
-            startWatchTimer();
+            m_d->startWatchTimer();
             emit startSuccessful();
     } else {
         warning(errorMessage);
@@ -706,7 +422,7 @@ void CdbDebugEngine::startDebugger(const QSharedPointer<DebuggerStartParameters>
 
 bool CdbDebugEngine::startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *errorMessage)
 {
-    // Need to attrach invasively, otherwise, no notification signals
+    // Need to attach invasively, otherwise, no notification signals
     // for for CreateProcess/ExitProcess occur.
     // Initial breakpoint occur:
     // 1) Desired: When attaching to a crashed process
@@ -716,75 +432,25 @@ bool CdbDebugEngine::startAttachDebugger(qint64 pid, DebuggerStartMode sm, QStri
     // by lookup at the state of the application (startup trap). However,
     // there is no startup trap when attaching to a process that has been
     // running for a while. (see notifyException).
-    ULONG flags = DEBUG_ATTACH_INVASIVE_RESUME_PROCESS;
-    if (manager()->startParameters()->startMode != AttachCrashedExternal)
-        flags |= DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK;
-    const HRESULT hr = m_d->m_cif.debugClient->AttachProcess(NULL, pid, flags);
-    if (debugCDB)
-        qDebug() << "Attaching to " << pid << " using flags" << flags << " returns " << hr << executionStatusString(m_d->m_cif.debugControl);
-    if (FAILED(hr)) {
-        *errorMessage = tr("Attaching to a process failed for process id %1: %2").arg(pid).arg(msgDebugEngineComResult(hr));
-        return false;
-    } else {
+    const bool suppressInitialBreakPoint = sm != AttachCrashedExternal;
+    const bool rc = m_d->startAttachDebugger(pid, suppressInitialBreakPoint, errorMessage);
+    if (rc)
         m_d->m_mode = sm;
-    }
-    return true;
+    return rc;
 }
 
 bool CdbDebugEngine::startDebuggerWithExecutable(DebuggerStartMode sm, QString *errorMessage)
 {
-    DEBUG_CREATE_PROCESS_OPTIONS dbgopts;
-    memset(&dbgopts, 0, sizeof(dbgopts));
-    dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
-
     const QSharedPointer<DebuggerStartParameters> sp = manager()->startParameters();
-    const QString filename(sp->executable);
-    // Set image path
-    const QFileInfo fi(filename);
-    QString imagePath = QDir::toNativeSeparators(fi.absolutePath());
-    if (!m_d->m_baseImagePath.isEmpty()) {
-        imagePath += QLatin1Char(';');
-        imagePath += m_d->m_baseImagePath;
-    }
-    HRESULT hr = m_d->m_cif.debugSymbols->SetImagePathWide(reinterpret_cast<PCWSTR>(imagePath.utf16()));
-    if (FAILED(hr)) {
-        *errorMessage = tr("Unable to set the image path to %1: %2").arg(imagePath, msgComFailed("SetImagePathWide", hr));
-        return false;
-    }
-
-    if (debugCDB)
-        qDebug() << Q_FUNC_INFO <<'\n' << filename << imagePath;
-
-    ULONG symbolOptions = SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS;
-    if (m_d->m_options->verboseSymbolLoading)
-        symbolOptions |= SYMOPT_DEBUG;
-    m_d->m_cif.debugSymbols->SetSymbolOptions(symbolOptions);
-
-    const QString cmd = Utils::AbstractProcess::createWinCommandline(filename, sp->processArgs);
-    if (debugCDB)
-        qDebug() << "Starting " << cmd;
-    PCWSTR env = 0;
-    QByteArray envData;
-    if (!sp->environment.empty()) {
-        envData = Utils::AbstractProcess::createWinEnvironment(Utils::AbstractProcess::fixWinEnvironment(sp->environment));
-        env = reinterpret_cast<PCWSTR>(envData.data());
-    }
-    // The working directory cannot be empty.
-    PCWSTR workingDirC = 0;
-    const QString workingDir = sp->workingDir.isEmpty() ? QString() : QDir::toNativeSeparators(sp->workingDir);
-    if (!workingDir.isEmpty())
-        workingDirC = workingDir.utf16();
-    hr = m_d->m_cif.debugClient->CreateProcess2Wide(NULL,
-                                                    reinterpret_cast<PWSTR>(const_cast<ushort *>(cmd.utf16())),
-                                                    &dbgopts, sizeof(dbgopts),
-                                                    workingDirC, env);
-    if (FAILED(hr)) {
-        *errorMessage = tr("Unable to create a process '%1': %2").arg(cmd, msgDebugEngineComResult(hr));
-        return false;
-    } else {
+    const bool rc = m_d->startDebuggerWithExecutable(sp->workingDir,
+                                                     sp->executable,
+                                                     sp->processArgs,
+                                                     sp->environment,
+                                                     m_d->m_options->verboseSymbolLoading,
+                                                     errorMessage);
+    if (rc)
         m_d->m_mode = sm;
-    }
-    return true;
+    return rc;
 }
 
 void CdbDebugEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 initialThreadHandle)
@@ -792,7 +458,7 @@ void CdbDebugEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG6
     m_engine->setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__);
     setDebuggeeHandles(reinterpret_cast<HANDLE>(processHandle), reinterpret_cast<HANDLE>(initialThreadHandle));
     ULONG currentThreadId;
-    if (SUCCEEDED(m_cif.debugSystemObjects->GetThreadIdByHandle(initialThreadHandle, &currentThreadId))) {
+    if (SUCCEEDED(interfaces().debugSystemObjects->GetThreadIdByHandle(initialThreadHandle, &currentThreadId))) {
         m_currentThreadId = currentThreadId;
     } else {
         m_currentThreadId = 0;
@@ -810,20 +476,20 @@ void CdbDebugEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG6
         const QString crashParameter = manager()->startParameters()->crashParameter;
         if (!crashParameter.isEmpty()) {
             ULONG64 evtNr = crashParameter.toULongLong();
-            const HRESULT hr = m_cif.debugControl->SetNotifyEventHandle(evtNr);
+            const HRESULT hr = interfaces().debugControl->SetNotifyEventHandle(evtNr);
             // Unless QtCreator is spawned by the debugger and inherits the handles,
             // the event handling does not work reliably
             // (that is, the crash event is not delivered).
             if (SUCCEEDED(hr)) {
                 QTimer::singleShot(0, m_engine, SLOT(slotBreakAttachToCrashed()));
             } else {
-                m_engine->warning(QString::fromLatin1("Handshake failed on event #%1: %2").arg(evtNr).arg(msgComFailed("SetNotifyEventHandle", hr)));
+                m_engine->warning(QString::fromLatin1("Handshake failed on event #%1: %2").arg(evtNr).arg(CdbCore::msgComFailed("SetNotifyEventHandle", hr)));
             }
         }
     }
     m_engine->setState(InferiorRunning, Q_FUNC_INFO, __LINE__);
     if (debugCDBExecution)
-        qDebug() << "<processCreatedAttached" << executionStatusString(m_cif.debugControl);
+        qDebug() << "<processCreatedAttached";
 }
 
 void CdbDebugEngine::processTerminated(unsigned long exitCode)
@@ -851,41 +517,27 @@ bool CdbDebugEnginePrivate::endInferior(EndInferiorAction action, QString *error
     }
     bool success = false;
     switch (action) {
-    case DetachInferior: {            
-            const HRESULT hr = m_cif.debugClient->DetachCurrentProcess();
-            if (SUCCEEDED(hr)) {
+    case DetachInferior:
+            if (detachCurrentProcess(errorMessage))
                 success = true;
-            } else {
-                *errorMessage += msgComFailed("DetachCurrentProcess", hr);
-            }
-        }
             break;
-    case TerminateInferior: {
+    case TerminateInferior:
             do {
                 // The exit process event handler will not be called.
-                HRESULT hr = m_cif.debugClient->TerminateCurrentProcess();
-                if (FAILED(hr)) {
-                    *errorMessage += msgComFailed("TerminateCurrentProcess", hr);
-                    break;
-                }
+                terminateCurrentProcess(errorMessage);
                 if (wasRunning) {
                     success = true;
                     break;
                 }
-                hr = m_cif.debugClient->TerminateProcesses();
-                if (SUCCEEDED(hr)) {
+                if (terminateProcesses(errorMessage))
                     success = true;
-                } else {
-                    *errorMessage += msgComFailed("TerminateProcesses", hr);
-                }
             } while (false);
             QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
             break;
-        }
     }
     // Perform cleanup even when failed..no point clinging to the process
     setDebuggeeHandles(0, 0);
-    m_engine->killWatchTimer();
+    killWatchTimer();
     m_engine->setState(success ? InferiorShutDown : InferiorShutdownFailed, Q_FUNC_INFO, __LINE__);
     return success;
 }
@@ -929,10 +581,10 @@ void CdbDebugEnginePrivate::endDebugging(EndDebuggingMode em)
     // Clean up resources (open files, etc.)
     m_engine->setState(EngineShuttingDown, Q_FUNC_INFO, __LINE__);
     clearForRun();
-    const HRESULT hr = m_cif.debugClient->EndSession(DEBUG_END_PASSIVE);
+    const bool endedCleanly = endSession(&errorMessage);
     m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
-    if (!SUCCEEDED(hr)) {
-        errorMessage = QString::fromLatin1("There were errors trying to end debugging: %1").arg(msgComFailed("EndSession", hr));
+    if (!endedCleanly) {
+        errorMessage = QString::fromLatin1("There were errors trying to end debugging:\n%1").arg(errorMessage);
         manager()->showDebuggerOutput(LogError, errorMessage);
     }
 }
@@ -965,7 +617,7 @@ void CdbDebugEngine::evaluateWatcher(WatchData *wd)
     QString errorMessage;
     QString value;
     QString type;
-    if (evaluateExpression(wd->exp, &value, &type, &errorMessage)) {
+    if (m_d->evaluateExpression(wd->exp, &value, &type, &errorMessage)) {
         wd->setValue(value);
         wd->setType(type);
     } else {
@@ -1017,14 +669,14 @@ bool CdbDebugEnginePrivate::executeContinueCommand(const QString &command)
     if (debugCDB)
         qDebug() << Q_FUNC_INFO << command;
     clearForRun();
-    setCodeLevel(); // Step by instruction
+    updateCodeLevel(); // Step by instruction
     m_engine->setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__);
     manager()->showDebuggerOutput(LogMisc, CdbDebugEngine::tr("Continuing with '%1'...").arg(command));
     QString errorMessage;
-    const bool success = CdbDebugEnginePrivate::executeDebuggerCommand(m_cif.debugControl, command, &errorMessage);
+    const bool success = executeDebuggerCommand(command, &errorMessage);
     if (success) {
         m_engine->setState(InferiorRunning, Q_FUNC_INFO, __LINE__);
-        m_engine->startWatchTimer();
+        startWatchTimer();
     } else {
         m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__);
         m_engine->warning(CdbDebugEngine::tr("Unable to continue: %1").arg(errorMessage));
@@ -1077,14 +729,14 @@ bool CdbDebugEngine::step(unsigned long executionStatus)
                             || m_d->m_currentThreadId == triggeringEventThread
                             || manager()->threadsHandler()->threads().size() == 1;
     m_d->clearForRun(); // clears thread ids
-    m_d->setCodeLevel(); // Step by instruction or source line
+    m_d->updateCodeLevel(); // Step by instruction or source line
     setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__);
     bool success = false;
     if (sameThread && executionStatus != CdbExtendedExecutionStatusStepOut) { // Step event-triggering thread, use fast API
-        const HRESULT hr = m_d->m_cif.debugControl->SetExecutionStatus(executionStatus);
+        const HRESULT hr = m_d->interfaces().debugControl->SetExecutionStatus(executionStatus);
         success = SUCCEEDED(hr);
         if (!success)
-            warning(msgStepFailed(executionStatus, m_d->m_currentThreadId, msgComFailed("SetExecutionStatus", hr)));
+            warning(msgStepFailed(executionStatus, m_d->m_currentThreadId, CdbCore::msgComFailed("SetExecutionStatus", hr)));
     } else {
         // Need to use a command to explicitly specify the current thread
         QString command;
@@ -1102,7 +754,7 @@ bool CdbDebugEngine::step(unsigned long executionStatus)
             break;
         }
         manager()->showDebuggerOutput(tr("Stepping %1").arg(command));
-        const HRESULT hr = m_d->m_cif.debugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, command.toLatin1().constData(), DEBUG_EXECUTE_ECHO);
+        const HRESULT hr = m_d->interfaces().debugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, command.toLatin1().constData(), DEBUG_EXECUTE_ECHO);
         success = SUCCEEDED(hr);
         if (!success)
             warning(msgStepFailed(executionStatus, m_d->m_currentThreadId, msgDebuggerCommandFailed(command, hr)));
@@ -1111,7 +763,7 @@ bool CdbDebugEngine::step(unsigned long executionStatus)
         // Oddity: Step into will first break at the calling function. Ignore
         if (executionStatus == DEBUG_STATUS_STEP_INTO || executionStatus == DEBUG_STATUS_REVERSE_STEP_INTO)
             m_d->m_breakEventMode = CdbDebugEnginePrivate::BreakEventIgnoreOnce;
-        startWatchTimer();
+        m_d->startWatchTimer();
         setState(InferiorRunning, Q_FUNC_INFO, __LINE__);
     } else {
         setState(InferiorStopped, Q_FUNC_INFO, __LINE__);
@@ -1159,9 +811,9 @@ bool CdbDebugEnginePrivate::continueInferiorProcess(QString *errorMessagePtr /*
 {
     if (debugCDBExecution)
         qDebug() << "continueInferiorProcess";
-    const HRESULT hr = m_cif.debugControl->SetExecutionStatus(DEBUG_STATUS_GO);
+    const HRESULT hr = interfaces().debugControl->SetExecutionStatus(DEBUG_STATUS_GO);
     if (FAILED(hr)) {
-        const QString errorMessage = msgComFailed("SetExecutionStatus", hr);
+        const QString errorMessage = CdbCore::msgComFailed("SetExecutionStatus", hr);
         if (errorMessagePtr) {
             *errorMessagePtr = errorMessage;
         } else {
@@ -1176,14 +828,11 @@ bool CdbDebugEnginePrivate::continueInferiorProcess(QString *errorMessagePtr /*
 bool CdbDebugEnginePrivate::continueInferior(QString *errorMessage)
 {
     // Check state: Are we running?
-    ULONG executionStatus;
-    if (!getExecutionStatus(m_cif.debugControl, &executionStatus, errorMessage))
-        return false;
-
+    const ULONG ex = executionStatus();
     if (debugCDB)
-        qDebug() << Q_FUNC_INFO << "\n    ex=" << executionStatus;
+        qDebug() << Q_FUNC_INFO << "\n    ex=" << ex;
 
-    if (executionStatus == DEBUG_STATUS_GO) {
+    if (ex == DEBUG_STATUS_GO) {
         m_engine->warning(QLatin1String("continueInferior() called while debuggee is running."));
         return true;
     }
@@ -1192,15 +841,15 @@ bool CdbDebugEnginePrivate::continueInferior(QString *errorMessage)
     bool success = false;
     do {
         clearForRun();
-        setCodeLevel();
-        m_engine->killWatchTimer();
+        updateCodeLevel();
+        killWatchTimer();
         manager()->resetLocation();
         manager()->showStatusMessage(CdbDebugEngine::tr("Running requested..."), messageTimeOut);
 
         if (!continueInferiorProcess(errorMessage))
             break;
 
-        m_engine->startWatchTimer();
+        startWatchTimer();
         success = true;
     } while (false);
     if (success) {
@@ -1215,28 +864,14 @@ bool CdbDebugEnginePrivate::interruptInterferiorProcess(QString *errorMessage)
 {
 
     // Interrupt the interferior process without notifications
+    // Could use setInterrupt, but that does not work.
     if (debugCDBExecution) {
-        ULONG executionStatus;
-        getExecutionStatus(m_cif.debugControl, &executionStatus, errorMessage);
-        qDebug() << "interruptInterferiorProcess  ex=" << executionStatus;
+        qDebug() << "interruptInterferiorProcess  ex=" << executionStatus();
     }
-
-    if (DebugBreakProcess(m_hDebuggeeProcess)) {
+    const bool rc = debugBreakProcess(m_hDebuggeeProcess, errorMessage);
+    if (rc)
         m_interrupted = true;
-    } else {
-        *errorMessage = QString::fromLatin1("DebugBreakProcess failed: %1").arg(Utils::winErrorMessage(GetLastError()));
-        return false;
-    }
-#if 0
-    const HRESULT hr = m_cif.debugControl->SetInterrupt(DEBUG_INTERRUPT_ACTIVE|DEBUG_INTERRUPT_EXIT);
-    if (FAILED(hr)) {
-        *errorMessage = QString::fromLatin1("Unable to interrupt debuggee after %1s: %2").
-                        arg(getInterruptTimeOutSecs(m_cif.debugControl)).arg(msgComFailed("SetInterrupt", hr));
-        return false;
-    }
-    m_interrupted = true;
-#endif
-    return true;
+    return rc;
 }
 
 void CdbDebugEngine::slotBreakAttachToCrashed()
@@ -1271,7 +906,7 @@ void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber)
     tempBreakPoint.fileName = fileName;
     tempBreakPoint.lineNumber = lineNumber;
     tempBreakPoint.oneShot = true;
-    const bool ok = tempBreakPoint.add(m_d->m_cif.debugControl, &errorMessage)
+    const bool ok = tempBreakPoint.add(m_d->interfaces().debugControl, &errorMessage)
                     && m_d->continueInferior(&errorMessage);
     if (!ok)
         warning(errorMessage);
@@ -1284,7 +919,7 @@ void CdbDebugEngine::runToFunctionExec(const QString &functionName)
     CDBBreakPoint tempBreakPoint;
     tempBreakPoint.funcName = functionName;
     tempBreakPoint.oneShot = true;
-    const bool ok = tempBreakPoint.add(m_d->m_cif.debugControl, &errorMessage)
+    const bool ok = tempBreakPoint.add(m_d->interfaces().debugControl, &errorMessage)
                     && m_d->continueInferior(&errorMessage);
     if (!ok)
         warning(errorMessage);
@@ -1327,64 +962,10 @@ void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &v
 void CdbDebugEngine::executeDebuggerCommand(const QString &command)
 {
     QString errorMessage;
-    if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_d->m_cif.debugControl, command, &errorMessage))
+    if (!m_d->executeDebuggerCommand(command, &errorMessage))
         warning(errorMessage);
 }
 
-bool CdbDebugEnginePrivate::executeDebuggerCommand(CIDebugControl *ctrl, const QString &command, QString *errorMessage)
-{
-    // output to all clients, else we do not see anything
-    const HRESULT hr = ctrl->ExecuteWide(DEBUG_OUTCTL_ALL_CLIENTS, reinterpret_cast<PCWSTR>(command.utf16()), 0);
-    if (debugCDB)
-        qDebug() << "executeDebuggerCommand" << command << SUCCEEDED(hr);
-    if (FAILED(hr)) {
-        *errorMessage = QString::fromLatin1("Unable to execute '%1': %2").
-                        arg(command, msgDebugEngineComResult(hr));
-        return false;
-    }
-    return true;
-}
-
-bool CdbDebugEngine::evaluateExpression(const QString &expression,
-                                        QString *value,
-                                        QString *type,
-                                        QString *errorMessage)
-{
-    DEBUG_VALUE debugValue;
-    if (!m_d->evaluateExpression(m_d->m_cif.debugControl, expression, &debugValue, errorMessage))
-        return false;
-    *value = CdbSymbolGroupContext::debugValueToString(debugValue, m_d->m_cif.debugControl, type);
-    return true;
-}
-
-bool CdbDebugEnginePrivate::evaluateExpression(CIDebugControl *ctrl,
-                                               const QString &expression,
-                                               DEBUG_VALUE *debugValue,
-                                               QString *errorMessage)
-{
-    if (debugCDB > 1)
-        qDebug() << Q_FUNC_INFO << expression;
-
-    memset(debugValue, 0, sizeof(DEBUG_VALUE));
-    // Original syntax must be restored, else setting breakpoints will fail.
-    SyntaxSetter syntaxSetter(ctrl, DEBUG_EXPR_CPLUSPLUS);
-    ULONG errorPosition = 0;
-    const HRESULT hr = ctrl->EvaluateWide(reinterpret_cast<PCWSTR>(expression.utf16()),
-                                          DEBUG_VALUE_INVALID, debugValue,
-                                          &errorPosition);
-    if (FAILED(hr)) {
-        if (HRESULT_CODE(hr) == 517) {
-            *errorMessage = QString::fromLatin1("Unable to evaluate '%1': Expression out of scope.").
-                            arg(expression);
-        } else {
-            *errorMessage = QString::fromLatin1("Unable to evaluate '%1': Error at %2: %3").
-                            arg(expression).arg(errorPosition).arg(msgDebugEngineComResult(hr));
-        }
-        return false;
-    }
-    return true;
-}
-
 void CdbDebugEngine::activateFrame(int frameIndex)
 {
     if (debugCDB)
@@ -1478,7 +1059,7 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
     // called again from the debug event handler.
 
     ULONG dummy;
-    const bool wasRunning = !CDBBreakPoint::getBreakPointCount(m_cif.debugControl, &dummy);
+    const bool wasRunning = !CDBBreakPoint::getBreakPointCount(interfaces().debugControl, &dummy);
     if (debugCDB)
         qDebug() << Q_FUNC_INFO << "\n  Running=" << wasRunning;
 
@@ -1493,8 +1074,8 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
     }
 
     QStringList warnings;
-    const bool ok = CDBBreakPoint::synchronizeBreakPoints(m_cif.debugControl,
-                                                 m_cif.debugSymbols,
+    const bool ok = CDBBreakPoint::synchronizeBreakPoints(interfaces().debugControl,
+                                                 interfaces().debugSymbols,
                                                  manager()->breakHandler(),
                                                  errorMessage, &warnings);
     if (const int warningsCount = warnings.size())
@@ -1535,8 +1116,7 @@ void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent,
         }
         QString disassembly;
         QApplication::setOverrideCursor(Qt::WaitCursor);
-        ok = dissassemble(m_d->m_cif.debugClient, m_d->m_cif.debugControl, offset,
-                          ContextLines, ContextLines, addressFieldWith, QTextStream(&disassembly), &errorMessage);
+        ok = dissassemble(m_d, offset, ContextLines, ContextLines, addressFieldWith, QTextStream(&disassembly), &errorMessage);
         QApplication::restoreOverrideCursor();
         if (!ok)
             break;
@@ -1556,10 +1136,10 @@ void CdbDebugEngine::fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 l
         return;
     ULONG received;
     QByteArray data(length, '\0');
-    const HRESULT hr = m_d->m_cif.debugDataSpaces->ReadVirtual(addr, data.data(), length, &received);
+    const HRESULT hr = m_d->interfaces().debugDataSpaces->ReadVirtual(addr, data.data(), length, &received);
     if (FAILED(hr)) {
         warning(tr("Unable to retrieve %1 bytes of memory at 0x%2: %3").
-                arg(length).arg(addr, 0, 16).arg(msgComFailed("ReadVirtual", hr)));
+                arg(length).arg(addr, 0, 16).arg(CdbCore::msgComFailed("ReadVirtual", hr)));
         return;
     }
     if (received < length)
@@ -1593,7 +1173,7 @@ QList<Symbol> CdbDebugEngine::moduleSymbols(const QString &moduleName)
             errorMessage = tr("Cannot retrieve symbols while the debuggee is running.");
             break;
         }
-        if (!getModuleSymbols(m_d->m_cif.debugSymbols, moduleName, &rc, &errorMessage))
+        if (!getModuleSymbols(m_d->interfaces().debugSymbols, moduleName, &rc, &errorMessage))
             break;
         success = true;
     } while (false);
@@ -1611,40 +1191,11 @@ void CdbDebugEngine::reloadRegisters()
         qDebug() << Q_FUNC_INFO << intBase;
     QList<Register> registers;
     QString errorMessage;
-    if (!getRegisters(m_d->m_cif.debugControl, m_d->m_cif.debugRegisters, &registers, &errorMessage, intBase))
+    if (!getRegisters(m_d->interfaces().debugControl, m_d->interfaces().debugRegisters, &registers, &errorMessage, intBase))
         warning(msgFunctionFailed("reloadRegisters" , errorMessage));
     manager()->registerHandler()->setRegisters(registers);
 }
 
-void CdbDebugEngine::timerEvent(QTimerEvent* te)
-{
-    // Fetch away the debug events and notify if debuggee
-    // stops. Note that IDebugEventCallback does not
-    // cover all cases of a debuggee stopping execution
-    // (such as step over,etc).
-    if (te->timerId() != m_d->m_watchTimer)
-        return;
-
-    const HRESULT hr = m_d->m_cif.debugControl->WaitForEvent(0, 1);
-    if (debugCDB)
-        if (debugCDB > 1 || hr != S_FALSE)
-            qDebug() << Q_FUNC_INFO << "WaitForEvent" << state() << msgDebugEngineComResult(hr);
-
-    switch (hr) {
-        case S_OK:
-            killWatchTimer();
-            m_d->handleDebugEvent();
-            break;
-        case S_FALSE:
-        case E_PENDING:
-        case E_FAIL:
-            break;
-        case E_UNEXPECTED: // Occurs on ExitProcess.
-            killWatchTimer();
-            break;
-    }
-}
-
 void CdbDebugEngine::slotConsoleStubStarted()
 {
     const qint64 appPid = m_d->m_consoleStubProc.applicationPID();
@@ -1653,7 +1204,7 @@ void CdbDebugEngine::slotConsoleStubStarted()
     // Attach to console process
     QString errorMessage;
     if (startAttachDebugger(appPid, AttachExternal, &errorMessage)) {
-        startWatchTimer();
+        m_d->startWatchTimer();
         manager()->notifyInferiorPidChanged(appPid);
     } else {
         QMessageBox::critical(manager()->mainWindow(), tr("Debugger Error"), errorMessage);
@@ -1713,7 +1264,7 @@ void CdbDebugEnginePrivate::handleDebugEvent()
 {
     if (debugCDBExecution)
         qDebug() << "handleDebugEvent mode " << m_breakEventMode
-                << executionStatusString(m_cif.debugControl) << " interrupt" << m_interrupted
+                << CdbCore::msgExecutionStatusString(executionStatus()) << " interrupt" << m_interrupted
                 << " startupcomplete" << m_inferiorStartupComplete;
     // restore mode and do special handling
     const HandleBreakEventMode mode = m_breakEventMode;
@@ -1754,7 +1305,7 @@ void CdbDebugEnginePrivate::handleDebugEvent()
     }
         break;
     case BreakEventIgnoreOnce:
-        m_engine->startWatchTimer();
+        startWatchTimer();
         m_interrupted = false;
         break;
     case BreakEventSyncBreakPoints: {
@@ -1762,7 +1313,7 @@ void CdbDebugEnginePrivate::handleDebugEvent()
             // Temp stop to sync breakpoints
             QString errorMessage;
             attemptBreakpointSynchronization(&errorMessage);
-            m_engine->startWatchTimer();
+            startWatchTimer();
             continueInferiorProcess(&errorMessage);
             if (!errorMessage.isEmpty())
                 m_engine->warning(QString::fromLatin1("In handleDebugEvent: %1").arg(errorMessage));
@@ -1783,17 +1334,17 @@ void CdbDebugEnginePrivate::setDebuggeeHandles(HANDLE hDebuggeeProcess,  HANDLE
 bool CdbDebugEnginePrivate::setCDBThreadId(unsigned long threadId, QString *errorMessage)
 {
     ULONG currentThreadId;
-    HRESULT hr = m_cif.debugSystemObjects->GetCurrentThreadId(&currentThreadId);
+    HRESULT hr = interfaces().debugSystemObjects->GetCurrentThreadId(&currentThreadId);
     if (FAILED(hr)) {
-        *errorMessage = msgComFailed("GetCurrentThreadId", hr);
+        *errorMessage = CdbCore::msgComFailed("GetCurrentThreadId", hr);
         return false;
     }
     if (currentThreadId == threadId)
         return true;
-    hr = m_cif.debugSystemObjects->SetCurrentThreadId(threadId);
+    hr = interfaces().debugSystemObjects->SetCurrentThreadId(threadId);
     if (FAILED(hr)) {
         *errorMessage = QString::fromLatin1("Failed to change to from thread %1 to %2: SetCurrentThreadId() failed: %3").
-                        arg(currentThreadId).arg(threadId).arg(msgDebugEngineComResult(hr));
+                        arg(currentThreadId).arg(threadId).arg(CdbCore::msgDebugEngineComResult(hr));
         return false;
     }
     const QString msg = CdbDebugEngine::tr("Changing threads: %1 -> %2").arg(currentThreadId).arg(threadId);
@@ -1810,7 +1361,7 @@ ULONG CdbDebugEnginePrivate::updateThreadList()
     ULONG currentThreadId;
     QString errorMessage;
     // When interrupting, an artifical thread with a breakpoint is created.
-    if (!CdbStackTraceContext::getThreads(m_cif, true, &threads, &currentThreadId, &errorMessage))
+    if (!CdbStackTraceContext::getThreads(interfaces(), true, &threads, &currentThreadId, &errorMessage))
         m_engine->warning(errorMessage);
     manager()->threadsHandler()->setThreads(threads);
     return currentThreadId;
@@ -1903,7 +1454,7 @@ void CdbDebugEnginePrivate::updateModules()
 {
     QList<Module> modules;
     QString errorMessage;
-    if (!getModuleList(m_cif.debugSymbols, &modules, &errorMessage))
+    if (!getModuleList(interfaces().debugSymbols, &modules, &errorMessage))
         m_engine->warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
     manager()->modulesHandler()->setModules(modules);
 }
@@ -1929,14 +1480,6 @@ void CdbDebugEngine::reloadSourceFiles()
 {
 }
 
-QStringList CdbDebugEnginePrivate::sourcePaths() const
-{
-    WCHAR wszBuf[MAX_PATH];
-    if (SUCCEEDED(m_cif.debugSymbols->GetSourcePathWide(wszBuf, MAX_PATH, 0)))
-        return QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)).split(QLatin1Char(';'));
-    return QStringList();
-}
-
 void CdbDebugEngine::syncDebuggerPaths()
 {
      if (debugCDB)
@@ -1949,39 +1492,6 @@ void CdbDebugEngine::syncDebuggerPaths()
     }
 }
 
-static inline QString pathString(const QStringList &s)
-{  return s.join(QString(QLatin1Char(';')));  }
-
-bool CdbDebugEnginePrivate::setSourcePaths(const QStringList &s, QString *errorMessage)
-{
-    const HRESULT hr = m_cif.debugSymbols->SetSourcePathWide(reinterpret_cast<PCWSTR>(pathString(s).utf16()));
-    if (FAILED(hr)) {
-        if (errorMessage)
-            *errorMessage = msgComFailed("SetSourcePathWide", hr);
-        return false;
-    }
-    return true;
-}
-
-QStringList CdbDebugEnginePrivate::symbolPaths() const
-{
-    WCHAR wszBuf[MAX_PATH];
-    if (SUCCEEDED(m_cif.debugSymbols->GetSymbolPathWide(wszBuf, MAX_PATH, 0)))
-        return QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)).split(QLatin1Char(';'));
-    return QStringList();
-}
-
-bool CdbDebugEnginePrivate::setSymbolPaths(const QStringList &s, QString *errorMessage)
-{
-    const HRESULT hr = m_cif.debugSymbols->SetSymbolPathWide(reinterpret_cast<PCWSTR>(pathString(s).utf16()));
-    if (FAILED(hr)) {
-        if (errorMessage)
-            *errorMessage = msgComFailed("SetSymbolPathWide", hr);
-        return false;
-    }
-    return true;
-}
-
 // Accessed by DebuggerManager
 IDebuggerEngine *createWinEngine(DebuggerManager *parent,
                                  bool cmdLineEnabled,
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.h b/src/plugins/debugger/cdb/cdbdebugengine.h
index 59d7658a925c5a3d3791ab961e18ba9cfefcd16c..52fb70119d6d8d53c24bc9800f1ba2bf01dd88c8 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.h
+++ b/src/plugins/debugger/cdb/cdbdebugengine.h
@@ -43,7 +43,7 @@ namespace Internal {
 class DisassemblerViewAgent;
 class CdbDebugEventCallback;
 class CdbDebugOutput;
-struct CdbDebugEnginePrivate;
+class CdbDebugEnginePrivate;
 struct CdbOptions;
 
 class CdbDebugEngine : public IDebuggerEngine
@@ -104,9 +104,6 @@ public:
 public slots:
     void syncDebuggerPaths();
 
-protected:
-    void timerEvent(QTimerEvent*);
-
 private slots:
     void slotConsoleStubStarted();
     void slotConsoleStubError(const QString &msg);
@@ -116,19 +113,16 @@ private slots:
 
 private:
     void setState(DebuggerState state, const char *func, int line);
-    bool startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *errorMessage);
-    bool startDebuggerWithExecutable(DebuggerStartMode sm, QString *errorMessage);
-    void startWatchTimer();
-    void killWatchTimer();
+    inline bool startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *errorMessage);
+    inline bool startDebuggerWithExecutable(DebuggerStartMode sm, QString *errorMessage);
     void processTerminated(unsigned long exitCode);
-    bool evaluateExpression(const QString &expression, QString *value, QString *type, QString *errorMessage);
     void evaluateWatcher(WatchData *wd);
     QString editorToolTip(const QString &exp, const QString &function);
     bool step(unsigned long executionStatus);
 
     CdbDebugEnginePrivate *m_d;
 
-    friend struct CdbDebugEnginePrivate;
+    friend class CdbDebugEnginePrivate;
     friend class CdbDebugEventCallback;
     friend class CdbDebugOutput;
 };
diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h
index 89a7fa15f74fbf3c64c60331da1baf54e7a19c8c..55e7287723074f7241b68567baada8101e94047b 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine_p.h
+++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h
@@ -30,8 +30,7 @@
 #ifndef DEBUGGER_CDBENGINEPRIVATE_H
 #define DEBUGGER_CDBENGINEPRIVATE_H
 
-#include "cdbdebugeventcallback.h"
-#include "cdbdebugoutput.h"
+#include "coreengine.h"
 #include "cdboptions.h"
 #include "cdbdumperhelper.h"
 #include "stackhandler.h"
@@ -50,52 +49,11 @@ class WatchHandler;
 class CdbStackFrameContext;
 class CdbStackTraceContext;
 
-// Thin wrapper around the 'DBEng' debugger engine shared library
-// which is loaded at runtime.
-
-class DebuggerEngineLibrary
+class CdbDebugEnginePrivate : public CdbCore::CoreEngine
 {
+    Q_OBJECT
 public:
-    DebuggerEngineLibrary();
-    bool init(const QString &path, QString *dbgEngDLL, QString *errorMessage);
-
-    inline HRESULT debugCreate(REFIID interfaceId, PVOID *interfaceHandle) const
-        { return m_debugCreate(interfaceId, interfaceHandle); }
-
-private:
-    // The exported functions of the library
-    typedef HRESULT (STDAPICALLTYPE *DebugCreateFunction)(REFIID, PVOID *);
-
-    DebugCreateFunction m_debugCreate;
-};
-
-// A class that sets an expression syntax on the debug control while in scope.
-// Can be nested as it checks for the old value.
-class SyntaxSetter {
-    Q_DISABLE_COPY(SyntaxSetter)
-public:
-    explicit inline SyntaxSetter(CIDebugControl *ctl, ULONG desiredSyntax);
-    inline  ~SyntaxSetter();
-private:
-    const ULONG m_desiredSyntax;
-    CIDebugControl *m_ctl;
-    ULONG m_oldSyntax;
-};
-
-// helper struct to pass interfaces around
-struct CdbComInterfaces
-{
-    CdbComInterfaces();
-    CIDebugClient*          debugClient;
-    CIDebugControl*         debugControl;
-    CIDebugSystemObjects*   debugSystemObjects;
-    CIDebugSymbols*         debugSymbols;
-    CIDebugRegisters*       debugRegisters;
-    CIDebugDataSpaces*      debugDataSpaces;
-};
 
-struct CdbDebugEnginePrivate
-{
     typedef QMap<QString, QString> EditorToolTipCache;
 
     enum HandleBreakEventMode { // Special modes for break event handler.
@@ -107,15 +65,14 @@ struct CdbDebugEnginePrivate
     explicit CdbDebugEnginePrivate(DebuggerManager *parent,
                                    const QSharedPointer<CdbOptions> &options,
                                    CdbDebugEngine* engine);
+    ~CdbDebugEnginePrivate();
     bool init(QString *errorMessage);
-        ~CdbDebugEnginePrivate();
 
     void checkVersion();
     void processCreatedAttached(ULONG64 processHandle, ULONG64 initialThreadHandle);
     void setDebuggeeHandles(HANDLE hDebuggeeProcess,  HANDLE hDebuggeeThread);
 
-    bool isDebuggeeRunning() const { return m_watchTimer != -1; }
-    void handleDebugEvent();
+    bool isDebuggeeRunning() const { return isWatchTimerRunning(); }
     ULONG updateThreadList();
     bool setCDBThreadId(unsigned long threadId, QString *errorMessage);
     void updateStackTrace();
@@ -143,17 +100,12 @@ struct CdbDebugEnginePrivate
     enum EndDebuggingMode { EndDebuggingDetach, EndDebuggingTerminate, EndDebuggingAuto };
     void endDebugging(EndDebuggingMode em = EndDebuggingAuto);
 
-    static bool executeDebuggerCommand(CIDebugControl *ctrl, const QString &command, QString *errorMessage);
-    static bool evaluateExpression(CIDebugControl *ctrl, const QString &expression, DEBUG_VALUE *v, QString *errorMessage);
-
-    QStringList sourcePaths() const;
-    bool setSourcePaths(const QStringList &s, QString *errorMessage);
-
-    QStringList symbolPaths() const;
-    bool setSymbolPaths(const QStringList &s, QString *errorMessage);
+    void updateCodeLevel();
 
-    bool setCodeLevel();
+public slots:
+    void handleDebugEvent();
 
+public:
     const QSharedPointer<CdbOptions>  m_options;
     HANDLE                  m_hDebuggeeProcess;
     HANDLE                  m_hDebuggeeThread;
@@ -164,12 +116,7 @@ struct CdbDebugEnginePrivate
     bool                    m_ignoreInitialBreakPoint;
     HandleBreakEventMode    m_breakEventMode;
 
-    int                     m_watchTimer;
-    CdbComInterfaces        m_cif;
-    CdbDebugEventCallback   m_debugEventCallBack;
-    CdbDebugOutput          m_debugOutputCallBack;    
     QSharedPointer<CdbDumperHelper> m_dumper;
-    QString                 m_baseImagePath;
 
     CdbDebugEngine *m_engine;
     inline DebuggerManager *manager() const;
@@ -181,19 +128,8 @@ struct CdbDebugEnginePrivate
 
     DebuggerStartMode m_mode;
     Utils::ConsoleProcess m_consoleStubProc;
-    QString m_dbengDLL;
 };
 
-// helper functions
-
-bool getExecutionStatus(CIDebugControl *ctl, ULONG *executionStatus, QString *errorMessage = 0);
-const char *executionStatusString(ULONG executionStatus);
-const char *executionStatusString(CIDebugControl *ctl);
-
-// Message
-QString msgDebugEngineComResult(HRESULT hr);
-QString msgComFailed(const char *func, HRESULT hr);
-
 enum { messageTimeOut = 5000 };
 
 enum { debugCDB = 0 };
diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
index 26c24b2058ba22fc3afd99809c46f5d35670d46a..0ffc51ff20eda399951dc68beec59dcc55e86d32 100644
--- a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp
@@ -40,174 +40,6 @@
 namespace Debugger {
 namespace Internal {
 
-//     CdbDebugEventCallbackBase
-CdbDebugEventCallbackBase::CdbDebugEventCallbackBase()
-{
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::QueryInterface(
-    THIS_
-    IN REFIID InterfaceId,
-    OUT PVOID* Interface)
-{
-    *Interface = NULL;
-
-    if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
-        IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))  {
-        *Interface = (IDebugOutputCallbacks *)this;
-        AddRef();
-        return S_OK;
-    } else {
-        return E_NOINTERFACE;
-    }
-}
-
-STDMETHODIMP_(ULONG) CdbDebugEventCallbackBase::AddRef(THIS)
-{
-    // This class is designed to be static so
-    // there's no true refcount.
-    return 1;
-}
-
-STDMETHODIMP_(ULONG) CdbDebugEventCallbackBase::Release(THIS)
-{
-    // This class is designed to be static so
-    // there's no true refcount.
-    return 0;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT2)
-{
-    return S_OK;
-}
-STDMETHODIMP CdbDebugEventCallbackBase::Exception(
-    THIS_
-    __in PEXCEPTION_RECORD64,
-    __in ULONG /* FirstChance */
-    )
-{
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::CreateThread(
-    THIS_
-    __in ULONG64 /* Handle */,
-    __in ULONG64 /* DataOffset */,
-    __in ULONG64 /* StartOffset */
-    )
-{
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::ExitThread(
-    THIS_
-    __in ULONG /* ExitCode */
-    )
-{
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::CreateProcess(
-    THIS_
-    __in ULONG64 /* ImageFileHandle */,
-    __in ULONG64 /* Handle */,
-    __in ULONG64 /* BaseOffset */,
-    __in ULONG /* ModuleSize */,
-    __in_opt PCWSTR /* ModuleName */,
-    __in_opt PCWSTR /* ImageName */,
-    __in ULONG /* CheckSum */,
-    __in ULONG /* TimeDateStamp */,
-    __in ULONG64 /* InitialThreadHandle */,
-    __in ULONG64 /* ThreadDataOffset */,
-    __in ULONG64 /* StartOffset */
-    )
-{    
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::ExitProcess(
-    THIS_
-    __in ULONG /* ExitCode */
-    )
-{
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::LoadModule(
-    THIS_
-    __in ULONG64 /* ImageFileHandle */,
-    __in ULONG64 /* BaseOffset */,
-    __in ULONG /* ModuleSize */,
-    __in_opt PCWSTR /* ModuleName */,
-    __in_opt PCWSTR /* ImageName */,
-    __in ULONG /* CheckSum */,
-    __in ULONG /* TimeDateStamp */
-    )
-{    
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::UnloadModule(
-    THIS_
-    __in_opt PCWSTR /* ImageBaseName */,
-    __in ULONG64 /* BaseOffset */
-    )
-{
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::SystemError(
-    THIS_
-    __in ULONG /* Error */,
-    __in ULONG /* Level */
-    )
-{
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::SessionStatus(
-    THIS_
-    __in ULONG /* Status */
-    )
-{
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::ChangeDebuggeeState(
-    THIS_
-    __in ULONG /* Flags */,
-    __in ULONG64 /* Argument */
-    )
-{
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::ChangeEngineState(
-    THIS_
-    __in ULONG /* Flags */,
-    __in ULONG64 /* Argument */
-    )
-{
-    return S_OK;
-}
-
-STDMETHODIMP CdbDebugEventCallbackBase::ChangeSymbolState(
-    THIS_
-    __in ULONG /* Flags */,
-    __in ULONG64 /* Argument */
-    )
-{    
-    return S_OK;
-}
-
-IDebugEventCallbacksWide *CdbDebugEventCallbackBase::getEventCallback(CIDebugClient *clnt)
-{
-    IDebugEventCallbacksWide *rc = 0;
-    if (SUCCEEDED(clnt->GetEventCallbacksWide(&rc)))
-        return rc;
-    return 0;
-}
-
 // ---------- CdbDebugEventCallback
 
 CdbDebugEventCallback::CdbDebugEventCallback(CdbDebugEngine* dbg) :
@@ -420,18 +252,5 @@ STDMETHODIMP IgnoreDebugEventCallback::GetInterestMask(THIS_ __out PULONG mask)
     return S_OK;
 }
 
-// --------- EventCallbackRedirector
-EventCallbackRedirector::EventCallbackRedirector(CIDebugClient *client,  IDebugEventCallbacksWide *cb) :
-        m_client(client),
-        m_oldCb(CdbDebugEventCallbackBase::getEventCallback(client))
-{
-    client->SetEventCallbacksWide(cb);
-}
-
-EventCallbackRedirector::~EventCallbackRedirector()
-{
-    m_client->SetEventCallbacksWide(m_oldCb);
-}
-
 } // namespace Internal
 } // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.h b/src/plugins/debugger/cdb/cdbdebugeventcallback.h
index 4250cd5b24c03d106c0284542552522fb9c0bb28..99c99a937a118625265ab9fe23b2168b6eb9b232 100644
--- a/src/plugins/debugger/cdb/cdbdebugeventcallback.h
+++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.h
@@ -30,7 +30,7 @@
 #ifndef DEBUGGER_CDBDEBUGEVENTCALLBACK_H
 #define DEBUGGER_CDBDEBUGEVENTCALLBACK_H
 
-#include "cdbcom.h"
+#include "debugeventcallbackbase.h"
 
 #include <QtCore/QStringList>
 
@@ -41,122 +41,7 @@ namespace Internal {
 
 class CdbDebugEngine;
 
-// Base class for event callbacks that takes care
-// Active X magic. Provides base implementations with
-// the exception of GetInterestMask
-class CdbDebugEventCallbackBase  : public IDebugEventCallbacksWide
-{
-protected:
-    CdbDebugEventCallbackBase();
-public:
-    // IUnknown.
-    STDMETHOD(QueryInterface)(
-        THIS_
-        IN REFIID InterfaceId,
-        OUT PVOID* Interface
-        );
-    STDMETHOD_(ULONG, AddRef)(
-        THIS
-        );
-    STDMETHOD_(ULONG, Release)(
-        THIS
-        );
-
-    // IDebugEventCallbacks.
-
-    STDMETHOD(Breakpoint)(
-        THIS_
-        __in PDEBUG_BREAKPOINT2 Bp
-        );
-
-    STDMETHOD(Exception)(
-        THIS_
-        __in PEXCEPTION_RECORD64 Exception,
-        __in ULONG FirstChance
-        );
-
-    STDMETHOD(CreateThread)(
-        THIS_
-        __in ULONG64 Handle,
-        __in ULONG64 DataOffset,
-        __in ULONG64 StartOffset
-        );
-    STDMETHOD(ExitThread)(
-        THIS_
-        __in ULONG ExitCode
-        );
-
-    STDMETHOD(CreateProcess)(
-        THIS_
-        __in ULONG64 ImageFileHandle,
-        __in ULONG64 Handle,
-        __in ULONG64 BaseOffset,
-        __in ULONG ModuleSize,
-        __in_opt PCWSTR ModuleName,
-        __in_opt PCWSTR ImageName,
-        __in ULONG CheckSum,
-        __in ULONG TimeDateStamp,
-        __in ULONG64 InitialThreadHandle,
-        __in ULONG64 ThreadDataOffset,
-        __in ULONG64 StartOffset
-        );
-
-    STDMETHOD(ExitProcess)(
-        THIS_
-        __in ULONG ExitCode
-        );
-
-    STDMETHOD(LoadModule)(
-        THIS_
-        __in ULONG64 ImageFileHandle,
-        __in ULONG64 BaseOffset,
-        __in ULONG ModuleSize,
-        __in_opt PCWSTR ModuleName,
-        __in_opt PCWSTR ImageName,
-        __in ULONG CheckSum,
-        __in ULONG TimeDateStamp
-        );
-
-    STDMETHOD(UnloadModule)(
-        THIS_
-        __in_opt PCWSTR ImageBaseName,
-        __in ULONG64 BaseOffset
-        );
-
-    STDMETHOD(SystemError)(
-        THIS_
-        __in ULONG Error,
-        __in ULONG Level
-        );
-
-    STDMETHOD(SessionStatus)(
-        THIS_
-        __in ULONG Status
-        );
-
-    STDMETHOD(ChangeDebuggeeState)(
-        THIS_
-        __in ULONG Flags,
-        __in ULONG64 Argument
-        );
-
-    STDMETHOD(ChangeEngineState)(
-        THIS_
-        __in ULONG Flags,
-        __in ULONG64 Argument
-        );
-
-    STDMETHOD(ChangeSymbolState)(
-        THIS_
-        __in ULONG Flags,
-        __in ULONG64 Argument
-        );
-
-
-    static IDebugEventCallbacksWide *getEventCallback(CIDebugClient *clnt);
-};
-
-class CdbDebugEventCallback : public CdbDebugEventCallbackBase
+class CdbDebugEventCallback : public CdbCore::DebugEventCallbackBase
 {
 public:
     explicit CdbDebugEventCallback(CdbDebugEngine* dbg);
@@ -239,7 +124,7 @@ private:
 
 // Event handler logs exceptions to the debugger window
 // and ignores the rest. To be used for running dumper calls.
-class CdbExceptionLoggerEventCallback : public CdbDebugEventCallbackBase
+class CdbExceptionLoggerEventCallback : public CdbCore::DebugEventCallbackBase
 {
 public:
     CdbExceptionLoggerEventCallback(int logChannel,
@@ -270,7 +155,7 @@ private:
 };
 
 // Event handler that ignores everything
-class IgnoreDebugEventCallback : public CdbDebugEventCallbackBase
+class IgnoreDebugEventCallback : public CdbCore::DebugEventCallbackBase
 {
 public:
     explicit IgnoreDebugEventCallback();
@@ -281,19 +166,6 @@ public:
         );
 };
 
-// Utility class to temporarily redirect events to another handler
-// as long as in scope
-class EventCallbackRedirector {
-    Q_DISABLE_COPY(EventCallbackRedirector)
-public:
-    explicit EventCallbackRedirector(CIDebugClient *client,  IDebugEventCallbacksWide *cb);
-    ~EventCallbackRedirector();
-private:
-    CIDebugClient *m_client;
-    IDebugEventCallbacksWide *m_oldCb;
-};
-
-
 } // namespace Internal
 } // namespace Debugger
 
diff --git a/src/plugins/debugger/cdb/cdbdebugoutput.cpp b/src/plugins/debugger/cdb/cdbdebugoutput.cpp
index b3c8a76575f5518e71c86c4aa116574bcb7e2d27..04a2729f0f6a79aab50691ab8d91dd58a99ebddc 100644
--- a/src/plugins/debugger/cdb/cdbdebugoutput.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugoutput.cpp
@@ -37,62 +37,6 @@
 namespace Debugger {
 namespace Internal {
 
-CdbDebugOutputBase::CdbDebugOutputBase()
-{
-}
-
-STDMETHODIMP CdbDebugOutputBase::QueryInterface(
-    THIS_
-    IN REFIID InterfaceId,
-    OUT PVOID* Interface
-    )
-{
-    *Interface = NULL;
-
-    if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
-        IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacksWide)))
-    {
-        *Interface = (IDebugOutputCallbacksWide*)this;
-        AddRef();
-        return S_OK;
-    } else {
-        return E_NOINTERFACE;
-    }
-}
-
-STDMETHODIMP_(ULONG) CdbDebugOutputBase::AddRef(THIS)
-{
-    // This class is designed to be static so
-    // there's no true refcount.
-    return 1;
-}
-
-STDMETHODIMP_(ULONG) CdbDebugOutputBase::Release(THIS)
-{
-    // This class is designed to be static so
-    // there's no true refcount.
-    return 0;
-}
-
-STDMETHODIMP CdbDebugOutputBase::Output(
-    THIS_
-    IN ULONG mask,
-    IN PCWSTR text
-    )
-{
-    const QString msg = QString::fromUtf16(reinterpret_cast<const ushort *>(text));
-    output(mask, msg);
-    return S_OK;
-}
-
-IDebugOutputCallbacksWide *CdbDebugOutputBase::getOutputCallback(CIDebugClient *client)
-{
-    IDebugOutputCallbacksWide *rc;
-     if (FAILED(client->GetOutputCallbacksWide(&rc)))
-         return 0;
-     return rc;
-}
-
 // ------------------------- CdbDebugOutput
 
 // Return a prefix for debugger messages
@@ -145,18 +89,5 @@ void CdbDebugOutput::output(ULONG mask, const QString &msg)
     }
 }
 
-// Utility class to temporarily redirect output to another handler
-// as long as in scope
-OutputRedirector::OutputRedirector(CIDebugClient *client, IDebugOutputCallbacksWide *newHandler) :
-        m_client(client),
-        m_oldHandler(CdbDebugOutputBase::getOutputCallback(client))
-{
-    m_client->SetOutputCallbacksWide(newHandler);
-}
-OutputRedirector::~OutputRedirector()
-{
-    m_client->SetOutputCallbacksWide(m_oldHandler);
-}
-
 } // namespace Internal
 } // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbdebugoutput.h b/src/plugins/debugger/cdb/cdbdebugoutput.h
index ad2473c787425bb245c2544da383ccac62eaebca..90ed71bfd5121540833349b61b00d51d11235431 100644
--- a/src/plugins/debugger/cdb/cdbdebugoutput.h
+++ b/src/plugins/debugger/cdb/cdbdebugoutput.h
@@ -30,49 +30,15 @@
 #ifndef DEBUGGER_CDBOUTPUT_H
 #define DEBUGGER_CDBOUTPUT_H
 
-#include "cdbcom.h"
+#include "debugoutputbase.h"
 
 #include <QtCore/QObject>
 
 namespace Debugger {
 namespace Internal {
 
-// CdbDebugOutputBase is a base class for output handlers
-// that takes care of the Active X magic and conversion to QString.
-
-class CdbDebugOutputBase : public IDebugOutputCallbacksWide
-{
-public:
-    // IUnknown.
-    STDMETHOD(QueryInterface)(
-        THIS_
-        IN REFIID InterfaceId,
-        OUT PVOID* Interface
-        );
-    STDMETHOD_(ULONG, AddRef)(
-        THIS
-        );
-    STDMETHOD_(ULONG, Release)(
-        THIS
-        );
-
-    // IDebugOutputCallbacks.
-    STDMETHOD(Output)(
-        THIS_
-        IN ULONG mask,
-        IN PCWSTR text
-        );
-
-    // Helpers to retrieve the output callbacks IF
-    static IDebugOutputCallbacksWide *getOutputCallback(CIDebugClient *client);
-
-protected:
-    CdbDebugOutputBase();
-    virtual void output(ULONG mask, const QString &message) = 0;
-};
-
 // Standard CDB output handler
-class CdbDebugOutput : public QObject, public CdbDebugOutputBase
+class CdbDebugOutput : public QObject, public CdbCore::DebugOutputBase
 {
     Q_OBJECT
 public:
@@ -88,34 +54,6 @@ signals:
     void debuggeeInputPrompt(const QString &message);
 };
 
-// An output handler that adds lines to a string (to be
-// used for cases in which linebreaks occur in-between calls
-// to output).
-class StringOutputHandler : public CdbDebugOutputBase
-{
-public:
-    StringOutputHandler() {}
-    QString result() const { return m_result; }
-
-protected:
-    virtual void output(ULONG, const QString &message) { m_result += message; }
-
-private:
-    QString m_result;
-};
-
-// Utility class to temporarily redirect output to another handler
-// as long as in scope
-class OutputRedirector {
-    Q_DISABLE_COPY(OutputRedirector)
-public:
-    explicit OutputRedirector(CIDebugClient *client, IDebugOutputCallbacksWide *newHandler);
-    ~OutputRedirector();
-private:
-    CIDebugClient *m_client;
-    IDebugOutputCallbacksWide *m_oldHandler;
-};
-
 } // namespace Internal
 } // namespace Debugger
 
diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
index 852f3f929b3db8a2b8547d21135a5b2384de8d14..10f9405e65871f9137a8a797a5c33edf5cc7b042 100644
--- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp
+++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
@@ -94,59 +94,13 @@ namespace Debugger {
 namespace Internal {
 
 // ------- Call load helpers
-// Alloc memory in debuggee using the ".dvalloc" command as
-// there seems to be no API for it.
-static bool allocDebuggeeMemory(CdbComInterfaces *cif,
-                                int size, ULONG64 *address, QString *errorMessage)
-{
-    *address = 0;
-    const QString allocCmd = QLatin1String(".dvalloc ") + QString::number(size);
-    StringOutputHandler stringHandler;
-    OutputRedirector redir(cif->debugClient, &stringHandler);
-    if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, allocCmd, errorMessage))
-        return false;
-   // "Allocated 1000 bytes starting at 003a0000" .. hopefully never localized
-    bool ok = false;
-    const QString output = stringHandler.result();
-    const int lastBlank = output.lastIndexOf(QLatin1Char(' '));
-    if (lastBlank != -1) {
-        const qint64 addri = output.mid(lastBlank + 1).toLongLong(&ok, 16);
-        if (ok)
-            *address = addri;
-    }
-     if (loadDebug > 1)
-        qDebug() << Q_FUNC_INFO << '\n' << output << *address << ok;
-    if (!ok) {
-        *errorMessage = QString::fromLatin1("Failed to parse output '%1'").arg(output);
-        return false;
-    }
-    return true;
-}
-
-// Alloc an AscII string in debuggee
-static bool createDebuggeeAscIIString(CdbComInterfaces *cif,
-                                      const QString &s,
-                                      ULONG64 *address,
-                                      QString *errorMessage)
-{
-    QByteArray sAsciiData = s.toLocal8Bit();
-    sAsciiData += '\0';
-    if (!allocDebuggeeMemory(cif, sAsciiData.size(), address, errorMessage))
-        return false;
-    const HRESULT hr = cif->debugDataSpaces->WriteVirtual(*address, sAsciiData.data(), sAsciiData.size(), 0);
-    if (FAILED(hr)) {
-        *errorMessage= msgComFailed("WriteVirtual", hr);
-        return false;
-    }
-    return true;
-}
 
-// Load a library into the debuggee. Currently requires
+    // Load a library into the debuggee. Currently requires
 // the QtCored4.pdb file to be present as we need "qstrdup"
 // as dummy symbol. This is ok ATM since dumpers only
 // make sense for Qt apps.
 static bool debuggeeLoadLibrary(DebuggerManager *manager,
-                                CdbComInterfaces *cif,
+                                CdbCore::CoreEngine *engine,
                                 unsigned long threadId,
                                 const QString &moduleName,
                                 QString *errorMessage)
@@ -154,12 +108,13 @@ static bool debuggeeLoadLibrary(DebuggerManager *manager,
     if (loadDebug > 1)
         qDebug() << Q_FUNC_INFO << moduleName;
     // Try to ignore the breakpoints, skip stray startup-complete trap exceptions
-    CdbExceptionLoggerEventCallback exLogger(LogWarning, true, manager);
-    EventCallbackRedirector eventRedir(cif->debugClient, &exLogger);
+    QSharedPointer<CdbExceptionLoggerEventCallback> exLogger(new CdbExceptionLoggerEventCallback(LogWarning, true, manager));
+    CdbCore::EventCallbackRedirector eventRedir(engine, exLogger);
+    Q_UNUSED(eventRedir)
     // Make a call to LoadLibraryA. First, reserve memory in debugger
     // and copy name over.
     ULONG64 nameAddress;
-    if (!createDebuggeeAscIIString(cif, moduleName, &nameAddress, errorMessage))
+    if (!engine->createDebuggeeAscIIString(moduleName, &nameAddress, errorMessage))
         return false;
     // We want to call "HMODULE LoadLibraryA(LPCTSTR lpFileName)"
     // (void* LoadLibraryA(char*)). However, despite providing a symbol
@@ -168,7 +123,7 @@ static bool debuggeeLoadLibrary(DebuggerManager *manager,
     // Prepare call: Locate 'qstrdup' in the (potentially namespaced) corelib. For some
     // reason, the symbol is present in QtGui as well without type information.
     QString dummyFunc = QLatin1String("*qstrdup");
-    if (resolveSymbol(cif->debugSymbols, QLatin1String("QtCore[d]*4!"), &dummyFunc, errorMessage) != ResolveSymbolOk)
+    if (resolveSymbol(engine->interfaces().debugSymbols, QLatin1String("QtCore[d]*4!"), &dummyFunc, errorMessage) != ResolveSymbolOk)
         return false;
 
     QString callCmd; {
@@ -179,16 +134,16 @@ static bool debuggeeLoadLibrary(DebuggerManager *manager,
     if (loadDebug)
         qDebug() << "Calling" << callCmd;
 
-    if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, callCmd, errorMessage))
+    if (!engine->executeDebuggerCommand(callCmd, errorMessage))
         return false;
     // Execute current thread. This will hit a breakpoint.
     QString goCmd;
     QTextStream(&goCmd) << '~' << threadId << " g";
-    if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, goCmd, errorMessage))
+    if (!engine->executeDebuggerCommand(goCmd, errorMessage))
         return false;
-    const HRESULT hr = cif->debugControl->WaitForEvent(0, waitTimeOutMS);
+    const HRESULT hr = engine->waitForEvent(waitTimeOutMS);
     if (FAILED(hr)) {
-        *errorMessage = msgComFailed("WaitForEvent", hr);
+        *errorMessage = CdbCore::msgComFailed("WaitForEvent", hr);
         return false;
     }
     return true;
@@ -339,13 +294,13 @@ void CdbDumperInitThread ::run()
 // ------------------- CdbDumperHelper
 
 CdbDumperHelper::CdbDumperHelper(DebuggerManager *manager,
-                                 CdbComInterfaces *cif) :
+                                 CdbCore::CoreEngine *coreEngine) :
     m_tryInjectLoad(true),
     m_msgDisabled(QLatin1String("Dumpers are disabled")),
     m_msgNotInScope(QLatin1String("Data not in scope")),
     m_state(NotLoaded),
     m_manager(manager),
-    m_cif(cif),
+    m_coreEngine(coreEngine),
     m_inBufferAddress(0),
     m_inBufferSize(0),
     m_outBufferAddress(0),
@@ -433,7 +388,7 @@ CdbDumperHelper::CallLoadResult CdbDumperHelper::initCallLoad(QString *errorMess
         qDebug() << Q_FUNC_INFO;
     // Do we have Qt and are we already loaded by accident?
     QStringList modules;
-    if (!getModuleNameList(m_cif->debugSymbols, &modules, errorMessage))
+    if (!getModuleNameList(m_coreEngine->interfaces().debugSymbols, &modules, errorMessage))
         return CallLoadError;
     // Are we already loaded by some accident?
     if (!modules.filter(QLatin1String(dumperModuleNameC), Qt::CaseInsensitive).isEmpty())
@@ -442,7 +397,7 @@ CdbDumperHelper::CallLoadResult CdbDumperHelper::initCallLoad(QString *errorMess
     if (modules.filter(QLatin1String(qtCoreModuleNameC), Qt::CaseInsensitive).isEmpty())
         return CallLoadNoQtApp;
     // Try to load
-    if (!debuggeeLoadLibrary(m_manager, m_cif, m_dumperCallThread, m_library, errorMessage))
+    if (!debuggeeLoadLibrary(m_manager, m_coreEngine, m_dumperCallThread, m_library, errorMessage))
         return CallLoadError;
     return CallLoadOk;
 }
@@ -457,7 +412,7 @@ static inline bool getSymbolAddress(CIDebugSymbols *sg,
     // Get address
     HRESULT hr = sg->GetOffsetByNameWide(reinterpret_cast<PCWSTR>(name.utf16()), address);
     if (FAILED(hr)) {
-        *errorMessage = msgComFailed("GetOffsetByNameWide", hr);
+        *errorMessage = CdbCore::msgComFailed("GetOffsetByNameWide", hr);
         return false;
     }
     // Get size. Even works for arrays
@@ -466,12 +421,12 @@ static inline bool getSymbolAddress(CIDebugSymbols *sg,
         ULONG type;
         hr = sg->GetOffsetTypeId(*address, &type, &moduleAddress);
         if (FAILED(hr)) {
-            *errorMessage = msgComFailed("GetOffsetTypeId", hr);
+            *errorMessage = CdbCore::msgComFailed("GetOffsetTypeId", hr);
             return false;
         }
         hr = sg->GetTypeSize(moduleAddress, type, size);
         if (FAILED(hr)) {
-            *errorMessage = msgComFailed("GetTypeSize", hr);
+            *errorMessage = CdbCore::msgComFailed("GetTypeSize", hr);
             return false;
         }
     } // size desired
@@ -488,14 +443,14 @@ bool CdbDumperHelper::initResolveSymbols(QString *errorMessage)
     QString inBufferSymbol = QLatin1String("*qDumpInBuffer");
     QString outBufferSymbol = QLatin1String("*qDumpOutBuffer");
     const QString dumperModuleName = QLatin1String(dumperModuleNameC);
-    bool rc = resolveSymbol(m_cif->debugSymbols, &m_dumpObjectSymbol, errorMessage) == ResolveSymbolOk
-                    && resolveSymbol(m_cif->debugSymbols, dumperModuleName, &inBufferSymbol, errorMessage) == ResolveSymbolOk
-                    && resolveSymbol(m_cif->debugSymbols, dumperModuleName, &outBufferSymbol, errorMessage) == ResolveSymbolOk;
+    bool rc = resolveSymbol(m_coreEngine->interfaces().debugSymbols, &m_dumpObjectSymbol, errorMessage) == ResolveSymbolOk
+                    && resolveSymbol(m_coreEngine->interfaces().debugSymbols, dumperModuleName, &inBufferSymbol, errorMessage) == ResolveSymbolOk
+                    && resolveSymbol(m_coreEngine->interfaces().debugSymbols, dumperModuleName, &outBufferSymbol, errorMessage) == ResolveSymbolOk;
     if (!rc)
         return false;
     //  Determine buffer addresses, sizes and alloc buffer
-    rc = getSymbolAddress(m_cif->debugSymbols, inBufferSymbol, &m_inBufferAddress, &m_inBufferSize, errorMessage)
-         && getSymbolAddress(m_cif->debugSymbols, outBufferSymbol, &m_outBufferAddress, &m_outBufferSize, errorMessage);
+    rc = getSymbolAddress(m_coreEngine->interfaces().debugSymbols, inBufferSymbol, &m_inBufferAddress, &m_inBufferSize, errorMessage)
+         && getSymbolAddress(m_coreEngine->interfaces().debugSymbols, outBufferSymbol, &m_outBufferAddress, &m_outBufferSize, errorMessage);
     if (!rc)
         return false;
     m_buffer = new char[qMax(m_inBufferSize, m_outBufferSize)];
@@ -532,41 +487,24 @@ bool CdbDumperHelper::initKnownTypes(QString *errorMessage)
     return true;
 }
 
-// Write to debuggee memory in chunks
-bool CdbDumperHelper::writeToDebuggee(CIDebugDataSpaces *ds, const QByteArray &buffer, quint64 address, QString *errorMessage)
-{
-    char *ptr = const_cast<char*>(buffer.data());
-    ULONG bytesToWrite = buffer.size();
-    while (bytesToWrite > 0) {
-        ULONG bytesWritten = 0;
-        const HRESULT hr = ds->WriteVirtual(address, ptr, bytesToWrite, &bytesWritten);
-        if (FAILED(hr)) {
-            *errorMessage = msgComFailed("WriteVirtual", hr);
-            return false;
-        }
-        bytesToWrite -= bytesWritten;
-        ptr += bytesWritten;
-    }
-    return true;
-}
-
 CdbDumperHelper::CallResult
     CdbDumperHelper::callDumper(const QString &callCmd, const QByteArray &inBuffer, const char **outDataPtr,
                                 bool ignoreAccessViolation, QString *errorMessage)
 {
     *outDataPtr = 0;
     // Skip stray startup-complete trap exceptions.
-    CdbExceptionLoggerEventCallback exLogger(LogWarning, true, m_manager);
-    EventCallbackRedirector eventRedir(m_cif->debugClient, &exLogger);
+    QSharedPointer<CdbExceptionLoggerEventCallback> exLogger(new CdbExceptionLoggerEventCallback(LogWarning, true, m_manager));
+    CdbCore::EventCallbackRedirector eventRedir(m_coreEngine, exLogger);
+    Q_UNUSED(eventRedir)
     // write input buffer
     if (!inBuffer.isEmpty()) {
-        if (!writeToDebuggee(m_cif->debugDataSpaces, inBuffer, m_inBufferAddress, errorMessage))
+        if (!m_coreEngine->writeToDebuggee(inBuffer, m_inBufferAddress, errorMessage))
             return CallFailed;
     }
-    if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, callCmd, errorMessage)) {
+    if (!m_coreEngine->executeDebuggerCommand(callCmd, errorMessage)) {
         // Clear the outstanding call in case we triggered a debug library assert with a message box
         QString clearError;
-        if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, QLatin1String(".call /c"), &clearError)) {
+        if (!m_coreEngine->executeDebuggerCommand(QLatin1String(".call /c"), &clearError)) {
             *errorMessage += QString::fromLatin1("/Unable to clear call %1").arg(clearError);
         }
         return CallSyntaxError;
@@ -575,40 +513,40 @@ CdbDumperHelper::CallResult
     // Try to skip debuggee crash exceptions and dumper exceptions
     // by using 'gN' (go not handled -> pass handling to dumper __try/__catch block)
     for (int i = 0; i < 10; i++) {
-        const int oldExceptionCount = exLogger.exceptionCount();
+        const int oldExceptionCount = exLogger->exceptionCount();
         // Go in current thread. If an exception occurs in loop 2,
         // let the dumper handle it.
         QString goCmd = m_goCommand;
         if (i)
             goCmd = QLatin1Char('N');
-        if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, goCmd, errorMessage))
+        if (!m_coreEngine->executeDebuggerCommand(goCmd, errorMessage))
             return CallFailed;
-        HRESULT hr = m_cif->debugControl->WaitForEvent(0, waitTimeOutMS);
+        HRESULT hr = m_coreEngine->waitForEvent(waitTimeOutMS);
         if (FAILED(hr)) {
-            *errorMessage = msgComFailed("WaitForEvent", hr);
+            *errorMessage = CdbCore::msgComFailed("WaitForEvent", hr);
             return CallFailed;
         }
-        const int newExceptionCount = exLogger.exceptionCount();
+        const int newExceptionCount = exLogger->exceptionCount();
         // no new exceptions? -> break
         if (oldExceptionCount == newExceptionCount)
             break;
         // If we are to ignore EXCEPTION_ACCESS_VIOLATION, check if anything
         // else occurred.
         if (ignoreAccessViolation) {
-            const QList<ULONG> newExceptionCodes = exLogger.exceptionCodes().mid(oldExceptionCount);
+            const QList<ULONG> newExceptionCodes = exLogger->exceptionCodes().mid(oldExceptionCount);
             if (newExceptionCodes.count(EXCEPTION_ACCESS_VIOLATION) == newExceptionCodes.size())
                 break;
         }
     }
-    if (exLogger.exceptionCount()) {
-        const QString exMsgs = exLogger.exceptionMessages().join(QString(QLatin1Char(',')));
+    if (exLogger->exceptionCount()) {
+        const QString exMsgs = exLogger->exceptionMessages().join(QString(QLatin1Char(',')));
         *errorMessage = QString::fromLatin1("Exceptions occurred during the dumper call: %1").arg(exMsgs);
         return CallFailed;
     }
     // Read output
-    const HRESULT hr = m_cif->debugDataSpaces->ReadVirtual(m_outBufferAddress, m_buffer, m_outBufferSize, 0);
+    const HRESULT hr = m_coreEngine->interfaces().debugDataSpaces->ReadVirtual(m_outBufferAddress, m_buffer, m_outBufferSize, 0);
     if (FAILED(hr)) {
-        *errorMessage = msgComFailed("ReadVirtual", hr);
+        *errorMessage = CdbCore::msgComFailed("ReadVirtual", hr);
         return CallFailed;
     }
     // see QDumper implementation
@@ -742,7 +680,7 @@ CdbDumperHelper::DumpExecuteResult
         qDebug() << "Query: " << wd.toString() << "\nwith: " << callCmd << '\n';
     const char *outputData;
     // Completely ignore EXCEPTION_ACCESS_VIOLATION crashes in the dumpers.
-    ExceptionBlocker eb(m_cif->debugControl, EXCEPTION_ACCESS_VIOLATION, ExceptionBlocker::IgnoreException);
+    ExceptionBlocker eb(m_coreEngine->interfaces().debugControl, EXCEPTION_ACCESS_VIOLATION, ExceptionBlocker::IgnoreException);
     if (!eb) {
         *errorMessage = eb.errorString();
         return DumpExecuteCallFailed;
@@ -808,11 +746,10 @@ bool CdbDumperHelper::runTypeSizeQuery(const QString &typeName, int *size, QStri
     QString expression = QLatin1String("sizeof(");
     expression += typeName;
     expression += QLatin1Char(')');
-    if (!CdbDebugEnginePrivate::evaluateExpression(m_cif->debugControl,
-                                                  expression, &sizeValue, errorMessage))
+    if (!m_coreEngine->evaluateExpression(expression, &sizeValue, errorMessage))
         return false;
     qint64 size64;
-    if (!CdbSymbolGroupContext::debugValueToInteger(sizeValue, &size64)) {
+    if (!CdbCore::debugValueToInteger(sizeValue, &size64)) {
         *errorMessage = QLatin1String("Expression result is not an integer");
         return false;
     }
@@ -833,6 +770,11 @@ void CdbDumperHelper::setDumperCallThread(unsigned long t)
     }
 }
 
+const CdbCore::ComInterfaces *CdbDumperHelper::comInterfaces() const
+{
+    return &m_coreEngine->interfaces();
+}
+
 } // namespace Internal
 } // namespace Debugger
 
diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.h b/src/plugins/debugger/cdb/cdbdumperhelper.h
index be326768df63f5faffa89bd0630cdac3192acd83..b4173b5664b9f3175e56fb1815fd1313b9f6f8b9 100644
--- a/src/plugins/debugger/cdb/cdbdumperhelper.h
+++ b/src/plugins/debugger/cdb/cdbdumperhelper.h
@@ -36,11 +36,15 @@
 #include <QtCore/QStringList>
 #include <QtCore/QMap>
 
+namespace CdbCore {
+    class CoreEngine;
+    struct ComInterfaces;
+}
+
 namespace Debugger {
 class DebuggerManager;
 
 namespace Internal {
-struct CdbComInterfaces;
 class CdbDumperInitThread;
 
 /* For code clarity, all the stuff related to custom dumpers goes here.
@@ -81,8 +85,8 @@ public:
         Initialized, // List of types, etc. retrieved
     };
 
-    explicit CdbDumperHelper(DebuggerManager *manager,
-                             CdbComInterfaces *cif);
+    explicit CdbDumperHelper(DebuggerManager *manager,                             
+                             CdbCore::CoreEngine *coreEngine);
     ~CdbDumperHelper();
 
     State state() const    { return m_state; }
@@ -102,7 +106,7 @@ public:
     DumpResult dumpType(const WatchData &d, bool dumpChildren,
                         QList<WatchData> *result, QString *errorMessage);
 
-    inline CdbComInterfaces *comInterfaces() const { return m_cif; }
+    const CdbCore::ComInterfaces *comInterfaces() const;
 
     enum { InvalidDumperCallThread = 0xFFFFFFFF };
     unsigned long dumperCallThread();
@@ -131,14 +135,12 @@ private:
                                   const QtDumperHelper::TypeData& td, bool dumpChildren,
                                   QList<WatchData> *result, QString *errorMessage);
 
-    static bool writeToDebuggee(CIDebugDataSpaces *ds, const QByteArray &buffer, quint64 address, QString *errorMessage);
-
     const bool m_tryInjectLoad;
     const QString m_msgDisabled;
     const QString m_msgNotInScope;
     State m_state;
     DebuggerManager *m_manager;
-    CdbComInterfaces *m_cif;
+    CdbCore::CoreEngine *m_coreEngine;
 
     QString m_library;
     QString m_dumpObjectSymbol;
diff --git a/src/plugins/debugger/cdb/cdbexceptionutils.cpp b/src/plugins/debugger/cdb/cdbexceptionutils.cpp
index 2c9b49d413e1a2e3bdf409a2763efc0b5837a4c5..a68544f7bc3b0e1e17e467c79730db573c14ff9c 100644
--- a/src/plugins/debugger/cdb/cdbexceptionutils.cpp
+++ b/src/plugins/debugger/cdb/cdbexceptionutils.cpp
@@ -122,7 +122,7 @@ bool ExceptionBlocker::getExceptionParameters(CIDebugControl *ctrl, ULONG exCode
 {
     const HRESULT ihr = ctrl->GetExceptionFilterParameters(1, &exCode, 0, result);
     if (FAILED(ihr)) {
-        *errorMessage = msgComFailed("GetExceptionFilterParameters", ihr);
+        *errorMessage = CdbCore::msgComFailed("GetExceptionFilterParameters", ihr);
         return false;
     }
     return true;
@@ -132,7 +132,7 @@ bool ExceptionBlocker::setExceptionParameters(CIDebugControl *ctrl, const DEBUG_
 {
     const HRESULT ihr = ctrl->SetExceptionFilterParameters(1, const_cast<DEBUG_EXCEPTION_FILTER_PARAMETERS*>(&p));
     if (FAILED(ihr)) {
-        *errorMessage = msgComFailed("GetExceptionFilterParameters", ihr);
+        *errorMessage = CdbCore::msgComFailed("GetExceptionFilterParameters", ihr);
         return false;
     }
     return true;
diff --git a/src/plugins/debugger/cdb/cdbmodules.cpp b/src/plugins/debugger/cdb/cdbmodules.cpp
index fd2653cc937051877dc3fac8cb654ed5def49328..dbb12f7f0c686a9de442d31b3ff999e93c8ac047 100644
--- a/src/plugins/debugger/cdb/cdbmodules.cpp
+++ b/src/plugins/debugger/cdb/cdbmodules.cpp
@@ -43,7 +43,7 @@ static inline bool getModuleCount(CIDebugSymbols *syms, ULONG *count, QString *e
     ULONG loadedCount, unloadedCount;
     const HRESULT hr = syms->GetNumberModules(&loadedCount, &unloadedCount);
     if (FAILED(hr)) {
-        *errorMessage= msgComFailed("GetNumberModules", hr);
+        *errorMessage= CdbCore::msgComFailed("GetNumberModules", hr);
         return false;
     }
     *count = loadedCount + unloadedCount;
@@ -75,7 +75,7 @@ bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorM
     HRESULT hr = syms->GetModuleParameters(count, 0, 0u, parmPtr);
     // E_INVALIDARG indicates 'Partial results' according to docu
     if (FAILED(hr) && hr != E_INVALIDARG) {
-        *errorMessage= msgComFailed("GetModuleParameters", hr);
+        *errorMessage= CdbCore::msgComFailed("GetModuleParameters", hr);
         return false;
     }
     // fill array
@@ -91,7 +91,7 @@ bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorM
             module.endAddress = hexPrefix + QString::number((p.Base + p.Size), 16);
             hr = syms->GetModuleNameStringWide(DEBUG_MODNAME_IMAGE, m, 0, wszBuf, MAX_PATH - 1, 0);
             if (FAILED(hr) && hr != E_INVALIDARG) {
-                *errorMessage= msgComFailed("GetModuleNameStringWide", hr);
+                *errorMessage= CdbCore::msgComFailed("GetModuleNameStringWide", hr);
                 return false;
             }
             module.moduleName = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf));
@@ -116,7 +116,7 @@ bool searchSymbols(CIDebugSymbols *syms, const QString &pattern,
         return true;
     }
     if (FAILED(hr)) {
-        *errorMessage= msgComFailed("StartSymbolMatchWide", hr);
+        *errorMessage= CdbCore::msgComFailed("StartSymbolMatchWide", hr);
         return false;
     }
     WCHAR wszBuf[MAX_PATH];
diff --git a/src/plugins/debugger/cdb/cdboptions.cpp b/src/plugins/debugger/cdb/cdboptions.cpp
index 320feb74b47e734282b5ce62ccbad5b3ff3109ca..e3ecd1b5b0477d8d82ffe72599967f5e27625fa1 100644
--- a/src/plugins/debugger/cdb/cdboptions.cpp
+++ b/src/plugins/debugger/cdb/cdboptions.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "cdboptions.h"
+#include "coreengine.h"
 
 #include <QtCore/QSettings>
 #include <QtCore/QDir>
@@ -65,7 +66,7 @@ void CdbOptions::fromSettings(const QSettings *s)
     const QString enabledKey = keyRoot + QLatin1String(enabledKeyC);
     const bool firstTime = !s->contains(enabledKey);
     if (firstTime) {
-        enabled = autoDetectPath(&path);
+        enabled = CdbCore::CoreEngine::autoDetectPath(&path);
         return;
     }
     enabled = s->value(enabledKey, false).toBool();
@@ -86,46 +87,6 @@ void CdbOptions::toSettings(QSettings *s) const
     s->endGroup();
 }
 
-bool CdbOptions::autoDetectPath(QString *outPath, QStringList *checkedDirectories /* = 0 */)
-{
-    // Look for $ProgramFiles/"Debugging Tools For Windows <bit-idy>" and its
-    // " (x86)", " (x64)" variations. Qt Creator needs 64/32 bit depending
-    // on how it was built.
-#ifdef Q_OS_WIN64
-    static const char *postFixes[] = {" (x64)", " 64-bit" };
-#else
-    static const char *postFixes[] = { " (x86)", " (x32)" };
-#endif
-
-    outPath->clear();
-    const QByteArray programDirB = qgetenv("ProgramFiles");
-    if (programDirB.isEmpty())
-        return false;
-
-    const QString programDir = QString::fromLocal8Bit(programDirB) + QDir::separator();
-    const QString installDir = QLatin1String("Debugging Tools For Windows");
-
-    QString path = programDir + installDir;
-    if (checkedDirectories)
-        checkedDirectories->push_back(path);
-    if (QFileInfo(path).isDir()) {
-        *outPath = QDir::toNativeSeparators(path);
-        return true;
-    }
-    const int rootLength = path.size();
-    for (int i = 0; i < sizeof(postFixes)/sizeof(const char*); i++) {
-        path.truncate(rootLength);
-        path += QLatin1String(postFixes[i]);
-        if (checkedDirectories)
-            checkedDirectories->push_back(path);
-        if (QFileInfo(path).isDir()) {
-            *outPath = QDir::toNativeSeparators(path);
-            return true;
-        }
-    }
-    return false;
-}
-
 unsigned CdbOptions::compare(const CdbOptions &rhs) const
 {
     unsigned rc = 0;
diff --git a/src/plugins/debugger/cdb/cdboptions.h b/src/plugins/debugger/cdb/cdboptions.h
index 14709d1f86bd0024b7ff1f4edf4b164e099b6b3c..887b13c862e03339bee3ab5269db1ee2271a3c94 100644
--- a/src/plugins/debugger/cdb/cdboptions.h
+++ b/src/plugins/debugger/cdb/cdboptions.h
@@ -54,9 +54,6 @@ public:
                        SymbolOptionsChanged = 0x4 };
     unsigned compare(const CdbOptions &s) const;
 
-    // Locate the debugging tools
-    static bool autoDetectPath(QString *path, QStringList *checkedDirectories = 0);
-
     bool enabled;
     QString path;
     QStringList symbolPaths;
diff --git a/src/plugins/debugger/cdb/cdboptionspage.cpp b/src/plugins/debugger/cdb/cdboptionspage.cpp
index f8a97f4e67c06a2c04810fc25db523d080734f39..583f6d77920ebe12a717270dbed69de1f2f6fdb3 100644
--- a/src/plugins/debugger/cdb/cdboptionspage.cpp
+++ b/src/plugins/debugger/cdb/cdboptionspage.cpp
@@ -30,6 +30,7 @@
 #include "cdboptionspage.h"
 #include "cdboptions.h"
 #include "debuggerconstants.h"
+#include "coreengine.h"
 
 #include <coreplugin/icore.h>
 
@@ -102,7 +103,7 @@ void CdbOptionsPageWidget::autoDetect()
 {
     QString path;
     QStringList checkedDirectories;
-    const bool ok = CdbOptions::autoDetectPath(&path, &checkedDirectories);
+    const bool ok = CdbCore::CoreEngine::autoDetectPath(&path, &checkedDirectories);
     m_ui.cdbPathGroupBox->setChecked(ok);
     if (ok) {
         m_ui.pathChooser->setPath(path);
diff --git a/src/plugins/debugger/cdb/cdbstackframecontext.cpp b/src/plugins/debugger/cdb/cdbstackframecontext.cpp
index 46e6aadefcb3c60dde9f25e4f9422711853251d2..90d0e3e4e8090db4b7263c70a805ae5c23cc5c02 100644
--- a/src/plugins/debugger/cdb/cdbstackframecontext.cpp
+++ b/src/plugins/debugger/cdb/cdbstackframecontext.cpp
@@ -33,6 +33,7 @@
 #include "cdbdumperhelper.h"
 #include "debuggeractions.h"
 #include "watchhandler.h"
+#include "coreengine.h"
 
 #include <QtCore/QDebug>
 #include <QtCore/QCoreApplication>
diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
index 8eb1998e71dc09be95908bbce77beee2447f77e9..bc9143032ae5dfd50cfcf34b6d457ea0f96c0909 100644
--- a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
+++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "cdbstacktracecontext.h"
+#include "coreengine.h"
 #include "cdbstackframecontext.h"
 #include "cdbbreakpoint.h"
 #include "cdbsymbolgroupcontext.h"
@@ -67,7 +68,7 @@ CdbStackTraceContext *CdbStackTraceContext::create(const QSharedPointer<CdbDumpe
     const HRESULT hr = dumper->comInterfaces()->debugControl->GetStackTrace(0, 0, 0, ctx->m_cdbFrames, CdbStackTraceContext::maxFrames, &frameCount);
     if (FAILED(hr)) {
         delete ctx;
-         *errorMessage = msgComFailed("GetStackTrace", hr);
+         *errorMessage = CdbCore::msgComFailed("GetStackTrace", hr);
         return 0;
     }
     if (!ctx->init(frameCount, errorMessage)) {
@@ -189,20 +190,20 @@ CIDebugSymbolGroup *CdbStackTraceContext::createSymbolGroup(int index, QString *
     CIDebugSymbolGroup *sg = 0;
     HRESULT hr = m_cif->debugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, NULL, &sg);
     if (FAILED(hr)) {
-        *errorMessage = msgComFailed("GetScopeSymbolGroup", hr);
+        *errorMessage = CdbCore::msgComFailed("GetScopeSymbolGroup", hr);
         return 0;
     }
 
     hr = m_cif->debugSymbols->SetScope(0, m_cdbFrames + index, NULL, 0);
     if (FAILED(hr)) {
-        *errorMessage = msgComFailed("SetScope", hr);
+        *errorMessage = CdbCore::msgComFailed("SetScope", hr);
         sg->Release();
         return 0;
     }
     // refresh with current frame
     hr = m_cif->debugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, sg, &sg);
     if (FAILED(hr)) {
-        *errorMessage = msgComFailed("GetScopeSymbolGroup", hr);
+        *errorMessage = CdbCore::msgComFailed("GetScopeSymbolGroup", hr);
         sg->Release();
         return 0;
     }
@@ -247,7 +248,7 @@ static inline QString msgGetThreadStateFailed(unsigned long threadId, const QStr
 
 // Determine information about thread. This changes the
 // current thread to thread->id.
-static inline bool getStoppedThreadState(const CdbComInterfaces &cif,
+static inline bool getStoppedThreadState(const CdbCore::ComInterfaces &cif,
                                          ThreadData *t,
                                          QString *errorMessage)
 {
@@ -255,13 +256,13 @@ static inline bool getStoppedThreadState(const CdbComInterfaces &cif,
     ULONG currentThread;
     HRESULT hr = cif.debugSystemObjects->GetCurrentThreadId(&currentThread);
     if (FAILED(hr)) {
-        *errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("GetCurrentThreadId", hr));
+        *errorMessage = msgGetThreadStateFailed(t->id, CdbCore::msgComFailed("GetCurrentThreadId", hr));
         return false;
     }
     if (currentThread != t->id) {
         hr = cif.debugSystemObjects->SetCurrentThreadId(t->id);
         if (FAILED(hr)) {
-            *errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("SetCurrentThreadId", hr));
+            *errorMessage = msgGetThreadStateFailed(t->id, CdbCore::msgComFailed("SetCurrentThreadId", hr));
             return false;
         }
     }
@@ -271,7 +272,7 @@ static inline bool getStoppedThreadState(const CdbComInterfaces &cif,
     DEBUG_STACK_FRAME frames[MaxFrames];
     hr = cif.debugControl->GetStackTrace(0, 0, 0, frames, MaxFrames, &frameCount);
     if (FAILED(hr)) {
-        *errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("GetStackTrace", hr));
+        *errorMessage = msgGetThreadStateFailed(t->id, CdbCore::msgComFailed("GetStackTrace", hr));
         return false;
     }
     // Ignore the top frame if it is "ntdll!KiFastSystemCallRet", which is
@@ -307,7 +308,7 @@ static inline QString msgGetThreadsFailed(const QString &why)
     return QString::fromLatin1("Unable to determine the thread information: %1").arg(why);
 }
 
-bool CdbStackTraceContext::getThreads(const CdbComInterfaces &cif,
+bool CdbStackTraceContext::getThreads(const CdbCore::ComInterfaces &cif,
                                       bool isStopped,
                                       QList<ThreadData> *threads,
                                       ULONG *currentThreadId,
@@ -318,7 +319,7 @@ bool CdbStackTraceContext::getThreads(const CdbComInterfaces &cif,
     *currentThreadId = 0;
     HRESULT hr= cif.debugSystemObjects->GetNumberThreads(&threadCount);
     if (FAILED(hr)) {
-        *errorMessage= msgGetThreadsFailed(msgComFailed("GetNumberThreads", hr));
+        *errorMessage= msgGetThreadsFailed(CdbCore::msgComFailed("GetNumberThreads", hr));
         return false;
     }
     // Get ids and index of current
@@ -326,14 +327,14 @@ bool CdbStackTraceContext::getThreads(const CdbComInterfaces &cif,
         return true;
     hr = cif.debugSystemObjects->GetCurrentThreadId(currentThreadId);
     if (FAILED(hr)) {
-        *errorMessage= msgGetThreadsFailed(msgComFailed("GetCurrentThreadId", hr));
+        *errorMessage= msgGetThreadsFailed(CdbCore::msgComFailed("GetCurrentThreadId", hr));
         return false;
     }
 
     QVector<ULONG> threadIds(threadCount);
     hr = cif.debugSystemObjects->GetThreadIdsByIndex(0, threadCount, &(*threadIds.begin()), 0);
     if (FAILED(hr)) {
-        *errorMessage= msgGetThreadsFailed(msgComFailed("GetThreadIdsByIndex", hr));
+        *errorMessage= msgGetThreadsFailed(CdbCore::msgComFailed("GetThreadIdsByIndex", hr));
         return false;
     }
     for (ULONG i = 0; i < threadCount; i++) {
@@ -350,7 +351,7 @@ bool CdbStackTraceContext::getThreads(const CdbComInterfaces &cif,
     if (isStopped && threads->back().id != *currentThreadId) {
         hr = cif.debugSystemObjects->SetCurrentThreadId(*currentThreadId);
         if (FAILED(hr)) {
-            *errorMessage= msgGetThreadsFailed(msgComFailed("SetCurrentThreadId", hr));
+            *errorMessage= msgGetThreadsFailed(CdbCore::msgComFailed("SetCurrentThreadId", hr));
             return false;
         }
     }
diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.h b/src/plugins/debugger/cdb/cdbstacktracecontext.h
index ac9cb030b06b3f6f3ad9659708e462a2a617066b..873fa7404a0f535d34a331b1346961c28e3929a4 100644
--- a/src/plugins/debugger/cdb/cdbstacktracecontext.h
+++ b/src/plugins/debugger/cdb/cdbstacktracecontext.h
@@ -42,10 +42,13 @@ QT_BEGIN_NAMESPACE
 class QTextStream;
 QT_END_NAMESPACE
 
+namespace CdbCore {
+    struct ComInterfaces;
+}
+
 namespace Debugger {
 namespace Internal {
 
-struct CdbComInterfaces;
 class CdbSymbolGroupContext;
 class CdbStackFrameContext;
 class CdbDumperHelper;
@@ -93,7 +96,7 @@ public:
 
     // Retrieve information about threads. When stopped, add
     // current stack frame.
-    static bool getThreads(const CdbComInterfaces &cif,
+    static bool getThreads(const CdbCore::ComInterfaces &cif,
                            bool isStopped,
                            QList<ThreadData> *threads,
                            ULONG *currentThreadId,
@@ -104,7 +107,7 @@ private:
     CIDebugSymbolGroup *createSymbolGroup(int index, QString *errorMessage);
 
     const QSharedPointer<CdbDumperHelper> m_dumper;
-    CdbComInterfaces *m_cif;
+    const CdbCore::ComInterfaces *m_cif;
 
     DEBUG_STACK_FRAME m_cdbFrames[maxFrames];
     QVector <CdbStackFrameContext*> m_frameContexts;
diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
index 480c9a74438ab5d775549a176d0ab7dfdd5f1e86..dc9cf017907b5afecadd932298bbec41fa2aeb4c 100644
--- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
+++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
@@ -175,7 +175,7 @@ bool CdbSymbolGroupContext::init(QString *errorMessage)
     ULONG count;
     HRESULT hr = m_symbolGroup->GetNumberSymbols(&count);
     if (FAILED(hr)) {
-        *errorMessage = msgComFailed("GetNumberSymbols", hr);
+        *errorMessage = CdbCore::msgComFailed("GetNumberSymbols", hr);
         return false;
     }
 
@@ -185,7 +185,8 @@ bool CdbSymbolGroupContext::init(QString *errorMessage)
 
         hr = m_symbolGroup->GetSymbolParameters(0, count, symbolParameters());
         if (FAILED(hr)) {
-            *errorMessage = QString::fromLatin1("In %1: %2 (%3 symbols)").arg(QLatin1String(Q_FUNC_INFO), msgComFailed("GetSymbolParameters", hr)).arg(count);
+            *errorMessage = QString::fromLatin1("In %1: %2 (%3 symbols)").arg(QLatin1String(Q_FUNC_INFO),
+                                                                              CdbCore::msgComFailed("GetSymbolParameters", hr)).arg(count);
             return false;
         }
         populateINameIndexMap(m_prefix, DEBUG_ANY_ID, count);
@@ -355,7 +356,7 @@ bool CdbSymbolGroupContext::expandSymbol(const QString &prefix, unsigned long in
 
     HRESULT hr = m_symbolGroup->ExpandSymbol(index, TRUE);
     if (FAILED(hr)) {
-        *errorMessage = msgExpandFailed(prefix, index, msgComFailed("ExpandSymbol", hr));
+        *errorMessage = msgExpandFailed(prefix, index, CdbCore::msgComFailed("ExpandSymbol", hr));
         return false;
     }
     // Hopefully, this will never fail, else data structure will be foobar.
@@ -363,7 +364,7 @@ bool CdbSymbolGroupContext::expandSymbol(const QString &prefix, unsigned long in
     ULONG newSize;
     hr = m_symbolGroup->GetNumberSymbols(&newSize);
     if (FAILED(hr)) {
-        *errorMessage = msgExpandFailed(prefix, index, msgComFailed("GetNumberSymbols", hr));
+        *errorMessage = msgExpandFailed(prefix, index, CdbCore::msgComFailed("GetNumberSymbols", hr));
         return false;
     }
 
@@ -373,7 +374,7 @@ bool CdbSymbolGroupContext::expandSymbol(const QString &prefix, unsigned long in
 
     hr = m_symbolGroup->GetSymbolParameters(0, newSize, symbolParameters());
     if (FAILED(hr)) {
-        *errorMessage = msgExpandFailed(prefix, index, msgComFailed("GetSymbolParameters", hr));
+        *errorMessage = msgExpandFailed(prefix, index, CdbCore::msgComFailed("GetSymbolParameters", hr));
         return false;
     }
     // The new symbols are inserted after the parent symbol.
@@ -531,7 +532,7 @@ bool CdbSymbolGroupContext::assignValue(const QString &iname, const QString &val
     const HRESULT hr = m_symbolGroup->WriteSymbolWide(index, reinterpret_cast<PCWSTR>(value.utf16()));
     if (FAILED(hr)) {
         *errorMessage = QString::fromLatin1("Unable to assign '%1' to '%2': %3").
-                        arg(value, iname, msgComFailed("WriteSymbolWide", hr));
+                        arg(value, iname, CdbCore::msgComFailed("WriteSymbolWide", hr));
         return false;
     }
     if (newValue)
@@ -539,126 +540,6 @@ bool CdbSymbolGroupContext::assignValue(const QString &iname, const QString &val
     return true;
 }
 
-// format an array of integers as "0x323, 0x2322, ..."
-template <class Integer>
-static QString formatArrayHelper(const Integer *array, int size, int base = 10)
-{
-    QString rc;
-    const QString hexPrefix = QLatin1String("0x");
-    const QString separator = QLatin1String(", ");
-    const bool hex = base == 16;
-    for (int i = 0; i < size; i++) {
-        if (i)
-            rc += separator;
-        if (hex)
-            rc += hexPrefix;
-        rc += QString::number(array[i], base);
-    }
-    return rc;
-}
-
-QString CdbSymbolGroupContext::hexFormatArray(const unsigned short *array, int size)
-{
-    return formatArrayHelper(array, size, 16);
-}
-
-// Helper to format an integer with
-// a hex prefix in case base = 16
-template <class Integer>
-        inline QString formatInteger(Integer value, int base)
-{
-    QString rc;
-    if (base == 16)
-        rc = QLatin1String("0x");
-    rc += QString::number(value, base);
-    return rc;
-}
-
-QString CdbSymbolGroupContext::debugValueToString(const DEBUG_VALUE &dv, CIDebugControl *ctl,
-                                                  QString *qType,
-                                                  int integerBase)
-{
-    switch (dv.Type) {
-    case DEBUG_VALUE_INT8:
-        if (qType)
-            *qType = QLatin1String("char");
-        return formatInteger(dv.I8, integerBase);
-    case DEBUG_VALUE_INT16:
-        if (qType)
-            *qType = QLatin1String("short");
-        return formatInteger(static_cast<short>(dv.I16), integerBase);
-    case DEBUG_VALUE_INT32:
-        if (qType)
-            *qType = QLatin1String("long");
-        return formatInteger(static_cast<long>(dv.I32), integerBase);
-    case DEBUG_VALUE_INT64:
-        if (qType)
-            *qType = QLatin1String("long long");
-        return formatInteger(static_cast<long long>(dv.I64), integerBase);
-    case DEBUG_VALUE_FLOAT32:
-        if (qType)
-            *qType = QLatin1String("float");
-        return QString::number(dv.F32);
-    case DEBUG_VALUE_FLOAT64:
-        if (qType)
-            *qType = QLatin1String("double");
-        return QString::number(dv.F64);
-    case DEBUG_VALUE_FLOAT80:
-    case DEBUG_VALUE_FLOAT128: { // Convert to double
-            DEBUG_VALUE doubleValue;
-            double d = 0.0;
-            if (SUCCEEDED(ctl->CoerceValue(const_cast<DEBUG_VALUE*>(&dv), DEBUG_VALUE_FLOAT64, &doubleValue)))
-                d = dv.F64;
-            if (qType)
-                *qType = QLatin1String(dv.Type == DEBUG_VALUE_FLOAT80 ? "80bit-float" : "128bit-float");
-            return QString::number(d);
-        }
-    case DEBUG_VALUE_VECTOR64: {
-            if (qType)
-                *qType = QLatin1String("64bit-vector");
-            QString rc = QLatin1String("bytes: ");
-            rc += formatArrayHelper(dv.VI8, 8, integerBase);
-            rc += QLatin1String(" long: ");
-            rc += formatArrayHelper(dv.VI32, 2, integerBase);
-            return rc;
-        }
-    case DEBUG_VALUE_VECTOR128: {
-            if (qType)
-                *qType = QLatin1String("128bit-vector");
-            QString rc = QLatin1String("bytes: ");
-            rc += formatArrayHelper(dv.VI8, 16, integerBase);
-            rc += QLatin1String(" long long: ");
-            rc += formatArrayHelper(dv.VI64, 2, integerBase);
-            return rc;
-        }
-    }
-    if (qType)
-        *qType = QString::fromLatin1("Unknown type #%1:").arg(dv.Type);
-    return formatArrayHelper(dv.RawBytes, 24, integerBase);
-}
-
-bool CdbSymbolGroupContext::debugValueToInteger(const DEBUG_VALUE &dv, qint64 *value)
-{
-    *value = 0;
-    switch (dv.Type) {
-    case DEBUG_VALUE_INT8:
-        *value = dv.I8;
-        return true;
-    case DEBUG_VALUE_INT16:
-        *value = static_cast<short>(dv.I16);
-        return true;
-    case DEBUG_VALUE_INT32:
-        *value = static_cast<long>(dv.I32);
-        return true;
-    case DEBUG_VALUE_INT64:
-        *value = static_cast<long long>(dv.I64);
-        return true;
-    default:
-        break;
-    }
-    return false;
-}
-
 /* The special type dumpers have an integer return code meaning:
  *  0:  ok
  *  1:  Dereferencing or retrieving memory failed, this is out of scope,
diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h
index 2db042423f07f7b170af324ad1876a358f09a790..b99cbf154979bdc9c00638b8ef1d3626e0ea823b 100644
--- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h
+++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h
@@ -133,13 +133,6 @@ public:
     inline bool isExpanded(unsigned long index) const   { return symbolState(index) == ExpandedSymbol; }
     inline bool isExpanded(const QString &prefix) const { return symbolState(prefix) == ExpandedSymbol; }
 
-    // Helper to convert a DEBUG_VALUE structure to a string representation
-    static QString debugValueToString(const DEBUG_VALUE &dv, CIDebugControl *ctl, QString *type = 0, int integerBase = 10);
-    static bool debugValueToInteger(const DEBUG_VALUE &dv, qint64 *value);
-
-    // format an array of unsigned longs as "0x323, 0x2322, ..."
-    static QString hexFormatArray(const unsigned short *array, int size);
-
     // Dump
     enum DumperResult { DumperOk, DumperError, DumperNotHandled };
     DumperResult dump(CIDebugDataSpaces *ds, WatchData *wd);
diff --git a/src/plugins/debugger/cdb/coreengine.cpp b/src/plugins/debugger/cdb/coreengine.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..77ca81e8cf31ea1883a07551f67b4ef8fa1ef622
--- /dev/null
+++ b/src/plugins/debugger/cdb/coreengine.cpp
@@ -0,0 +1,944 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "coreengine.h"
+#include "debugeventcallbackbase.h"
+#include "debugoutputbase.h"
+
+#include <utils/winutils.h>
+#include <utils/abstractprocess.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QLibrary>
+#include <QtCore/QDebug>
+
+#define DBGHELP_TRANSLATE_TCHAR
+#include <inc/Dbghelp.h>
+
+static const char *dbgHelpDllC = "dbghelp";
+static const char *dbgEngineDllC = "dbgeng";
+static const char *debugCreateFuncC = "DebugCreate";
+
+enum { debug = 0 };
+
+static inline QString msgLibLoadFailed(const QString &lib, const QString &why)
+{
+    return QCoreApplication::translate("Debugger::Cdb",
+                                       "Unable to load the debugger engine library '%1': %2").
+            arg(lib, why);
+}
+
+static inline ULONG getInterruptTimeOutSecs(CIDebugControl *ctl)
+{
+    ULONG rc = 0;
+    ctl->GetInterruptTimeout(&rc);
+    return rc;
+}
+
+namespace CdbCore {
+
+QString msgDebugEngineComResult(HRESULT hr)
+{
+    switch (hr) {
+    case S_OK:
+        return QLatin1String("S_OK");
+    case S_FALSE:
+        return QLatin1String("S_FALSE");
+    case E_FAIL:
+        break;
+    case E_INVALIDARG:
+        return QLatin1String("E_INVALIDARG");
+    case E_NOINTERFACE:
+        return QLatin1String("E_NOINTERFACE");
+    case E_OUTOFMEMORY:
+        return QLatin1String("E_OUTOFMEMORY");
+    case E_UNEXPECTED:
+        return QLatin1String("E_UNEXPECTED");
+    case E_NOTIMPL:
+        return QLatin1String("E_NOTIMPL");
+    }
+    if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
+        return QLatin1String("ERROR_ACCESS_DENIED");;
+    if (hr == HRESULT_FROM_NT(STATUS_CONTROL_C_EXIT))
+        return QLatin1String("STATUS_CONTROL_C_EXIT");
+    return QLatin1String("E_FAIL ") + Utils::winErrorMessage(HRESULT_CODE(hr));
+}
+
+QString msgComFailed(const char *func, HRESULT hr)
+{
+    return QString::fromLatin1("%1 failed: %2").arg(QLatin1String(func), msgDebugEngineComResult(hr));
+}
+
+QString msgDebuggerCommandFailed(const QString &command, HRESULT hr)
+{
+    return QString::fromLatin1("Unable to execute '%1': %2").arg(command, msgDebugEngineComResult(hr));
+}
+
+const char *msgExecutionStatusString(ULONG executionStatus)
+{
+    switch (executionStatus) {
+    case DEBUG_STATUS_NO_CHANGE:
+        return "DEBUG_STATUS_NO_CHANGE";
+    case DEBUG_STATUS_GO:
+        return "DEBUG_STATUS_GO";
+    case DEBUG_STATUS_GO_HANDLED:
+        return "DEBUG_STATUS_GO_HANDLED";
+    case DEBUG_STATUS_GO_NOT_HANDLED:
+        return "DEBUG_STATUS_GO_NOT_HANDLED";
+    case DEBUG_STATUS_STEP_OVER:
+        return "DEBUG_STATUS_STEP_OVER";
+    case DEBUG_STATUS_STEP_INTO:
+        return "DEBUG_STATUS_STEP_INTO";
+    case DEBUG_STATUS_BREAK:
+        return "DEBUG_STATUS_BREAK";
+    case DEBUG_STATUS_NO_DEBUGGEE:
+        return "DEBUG_STATUS_NO_DEBUGGEE";
+    case DEBUG_STATUS_STEP_BRANCH:
+        return "DEBUG_STATUS_STEP_BRANCH";
+    case DEBUG_STATUS_IGNORE_EVENT:
+        return "DEBUG_STATUS_IGNORE_EVENT";
+    case DEBUG_STATUS_RESTART_REQUESTED:
+        return "DEBUG_STATUS_RESTART_REQUESTED";
+    case DEBUG_STATUS_REVERSE_GO:
+        return "DEBUG_STATUS_REVERSE_GO";
+          case DEBUG_STATUS_REVERSE_STEP_BRANCH:
+        return "DEBUG_STATUS_REVERSE_STEP_BRANCH";
+    case DEBUG_STATUS_REVERSE_STEP_OVER:
+        return "DEBUG_STATUS_REVERSE_STEP_OVER";
+    case DEBUG_STATUS_REVERSE_STEP_INTO:
+        return "DEBUG_STATUS_REVERSE_STEP_INTO";
+        default:
+        break;
+    }
+    return "<Unknown execution status>";
+}
+
+// ComInterfaces
+ComInterfaces::ComInterfaces() :
+    debugClient(0),
+    debugControl(0),
+    debugSystemObjects(0),
+    debugSymbols(0),
+    debugRegisters(0),
+    debugDataSpaces(0)
+{
+}
+
+// Thin wrapper around the 'DBEng' debugger engine shared library
+// which is loaded at runtime.
+
+class DebuggerEngineLibrary
+{
+public:
+    DebuggerEngineLibrary();
+    bool init(const QString &path, QString *dbgEngDLL, QString *errorMessage);
+
+    inline HRESULT debugCreate(REFIID interfaceId, PVOID *interfaceHandle) const
+        { return m_debugCreate(interfaceId, interfaceHandle); }
+
+private:
+    // The exported functions of the library
+    typedef HRESULT (STDAPICALLTYPE *DebugCreateFunction)(REFIID, PVOID *);
+
+    DebugCreateFunction m_debugCreate;
+};
+
+// --------- DebuggerEngineLibrary
+DebuggerEngineLibrary::DebuggerEngineLibrary() :
+    m_debugCreate(0)
+{
+}
+
+// Build a lib name as "Path\x.dll"
+static inline QString libPath(const QString &libName, const QString &path = QString())
+{
+    QString rc = path;
+    if (!rc.isEmpty())
+        rc += QDir::separator();
+    rc += libName;
+    rc += QLatin1String(".dll");
+    return rc;
+}
+
+bool DebuggerEngineLibrary::init(const QString &path,
+                                 QString *dbgEngDLL,
+                                 QString *errorMessage)
+{
+    // Load the dependent help lib first
+    const QString helpLibPath = libPath(QLatin1String(dbgHelpDllC), path);
+    QLibrary helpLib(helpLibPath, 0);
+    if (!helpLib.isLoaded() && !helpLib.load()) {
+        *errorMessage = msgLibLoadFailed(helpLibPath, helpLib.errorString());
+        return false;
+    }
+    // Load dbgeng lib
+    const QString engineLibPath = libPath(QLatin1String(dbgEngineDllC), path);
+    QLibrary lib(engineLibPath, 0);
+    if (!lib.isLoaded() && !lib.load()) {
+        *errorMessage = msgLibLoadFailed(engineLibPath, lib.errorString());
+        return false;
+    }
+    *dbgEngDLL = engineLibPath;
+    // Locate symbols
+    void *createFunc = lib.resolve(debugCreateFuncC);
+    if (!createFunc) {
+        *errorMessage = QCoreApplication::translate("Debugger::Cdb", "Unable to resolve '%1' in the debugger engine library '%2'").
+                        arg(QLatin1String(debugCreateFuncC), QLatin1String(dbgEngineDllC));
+        return false;
+    }
+    m_debugCreate = static_cast<DebugCreateFunction>(createFunc);
+    return true;
+}
+
+// ------ Engine
+CoreEngine::CoreEngine(QObject *parent) :
+    QObject(parent),
+    m_watchTimer(-1)
+{
+}
+
+CoreEngine::~CoreEngine()
+{
+
+    if (m_cif.debugClient) {
+        m_cif.debugClient->SetOutputCallbacksWide(0);
+        m_cif.debugClient->SetEventCallbacksWide(0);
+        m_cif.debugClient->Release();
+    }
+    if (m_cif.debugControl)
+        m_cif.debugControl->Release();
+    if (m_cif.debugSystemObjects)
+        m_cif.debugSystemObjects->Release();
+    if (m_cif.debugSymbols)
+        m_cif.debugSymbols->Release();
+    if (m_cif.debugRegisters)
+        m_cif.debugRegisters->Release();
+    if (m_cif.debugDataSpaces)
+        m_cif.debugDataSpaces->Release();
+}
+
+bool CoreEngine::init(const QString &dllEnginePath, QString *errorMessage)
+{
+    enum {  bufLen = 10240 };
+    // Load the DLL
+    DebuggerEngineLibrary lib;
+    if (!lib.init(dllEnginePath, &m_dbengDLL, errorMessage))
+        return false;
+    // Initialize the COM interfaces
+    HRESULT hr;
+    hr = lib.debugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_cif.debugClient));
+    if (FAILED(hr)) {
+        *errorMessage = QString::fromLatin1("Creation of IDebugClient5 failed: %1").arg(msgDebugEngineComResult(hr));
+        return false;
+    }
+
+    hr = lib.debugCreate( __uuidof(IDebugControl4), reinterpret_cast<void**>(&m_cif.debugControl));
+    if (FAILED(hr)) {
+        *errorMessage = QString::fromLatin1("Creation of IDebugControl4 failed: %1").arg(msgDebugEngineComResult(hr));
+        return false;
+    }
+
+    hr = lib.debugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_cif.debugSystemObjects));
+    if (FAILED(hr)) {
+        *errorMessage = QString::fromLatin1("Creation of IDebugSystemObjects4 failed: %1").arg(msgDebugEngineComResult(hr));
+        return false;
+    }
+
+    hr = lib.debugCreate( __uuidof(IDebugSymbols3), reinterpret_cast<void**>(&m_cif.debugSymbols));
+    if (FAILED(hr)) {
+        *errorMessage = QString::fromLatin1("Creation of IDebugSymbols3 failed: %1").arg(msgDebugEngineComResult(hr));
+        return false;
+    }
+
+    WCHAR buf[bufLen];
+    hr = m_cif.debugSymbols->GetImagePathWide(buf, bufLen, 0);
+    if (FAILED(hr)) {
+        *errorMessage = msgComFailed("GetImagePathWide", hr);
+        return false;
+    }
+    m_baseImagePath = QString::fromUtf16(buf);
+
+    hr = lib.debugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_cif.debugRegisters));
+    if (FAILED(hr)) {
+        *errorMessage = QString::fromLatin1("Creation of IDebugRegisters2 failed: %1").arg(msgDebugEngineComResult(hr));
+        return false;
+    }
+
+    hr = lib.debugCreate( __uuidof(IDebugDataSpaces4), reinterpret_cast<void**>(&m_cif.debugDataSpaces));
+    if (FAILED(hr)) {
+        *errorMessage = QString::fromLatin1("Creation of IDebugDataSpaces4 failed: %1").arg(msgDebugEngineComResult(hr));
+        return false;
+    }
+
+    if (debug)
+        qDebug() << QString::fromLatin1("CDB Initialization succeeded, interrupt time out %1s.").arg(getInterruptTimeOutSecs(m_cif.debugControl));
+    return true;
+}
+
+CoreEngine::DebugOutputBasePtr
+        CoreEngine::setDebugOutput(const DebugOutputBasePtr &o)
+{
+    const CoreEngine::DebugOutputBasePtr old = m_debugOutput;
+    m_debugOutput = o;
+    m_cif.debugClient->SetOutputCallbacksWide(m_debugOutput.data());
+    return old;
+}
+
+CoreEngine::DebugEventCallbackBasePtr
+        CoreEngine::setDebugEventCallback(const DebugEventCallbackBasePtr &e)
+{
+    const CoreEngine::DebugEventCallbackBasePtr old = m_debugEventCallback;
+    m_debugEventCallback = e;
+    m_cif.debugClient->SetEventCallbacksWide(m_debugEventCallback.data());
+    return old;
+}
+
+void CoreEngine::startWatchTimer()
+{
+    if (debug)
+        qDebug() << Q_FUNC_INFO;
+
+    if (m_watchTimer == -1)
+        m_watchTimer = startTimer(0);
+}
+
+void CoreEngine::killWatchTimer()
+{
+    if (debug)
+        qDebug() << Q_FUNC_INFO;
+
+    if (m_watchTimer != -1) {
+        killTimer(m_watchTimer);
+        m_watchTimer = -1;
+    }
+}
+
+HRESULT CoreEngine::waitForEvent(int timeOutMS)
+{
+    const HRESULT hr = m_cif.debugControl->WaitForEvent(0, timeOutMS);
+    if (debug)
+        if (debug > 1 || hr != S_FALSE)
+            qDebug() << Q_FUNC_INFO << "WaitForEvent" << timeOutMS << msgDebugEngineComResult(hr);
+    return hr;
+}
+
+void CoreEngine::timerEvent(QTimerEvent* te)
+{
+    // Fetch away the debug events and notify if debuggee
+    // stops. Note that IDebugEventCallback does not
+    // cover all cases of a debuggee stopping execution
+    // (such as step over,etc).
+    if (te->timerId() != m_watchTimer)
+        return;
+
+    switch (waitForEvent(1)) {
+        case S_OK:
+            killWatchTimer();
+            emit watchTimerDebugEvent();
+            break;
+        case S_FALSE:
+        case E_PENDING:
+        case E_FAIL:
+            break;
+        case E_UNEXPECTED: // Occurs on ExitProcess.
+            killWatchTimer();
+            break;
+    }
+}
+
+bool CoreEngine::startDebuggerWithExecutable(const QString &workingDirectory,
+                                             const QString &filename,
+                                             const QStringList &args,
+                                             const QStringList &envList,
+                                             bool verboseSymbolLoading,
+                                             QString *errorMessage)
+{
+    DEBUG_CREATE_PROCESS_OPTIONS dbgopts;
+    memset(&dbgopts, 0, sizeof(dbgopts));
+    dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
+
+    // Set image path
+    const QFileInfo fi(filename);
+    QString imagePath = QDir::toNativeSeparators(fi.absolutePath());
+    if (!m_baseImagePath.isEmpty()) {
+        imagePath += QLatin1Char(';');
+        imagePath += m_baseImagePath;
+    }
+    HRESULT hr = m_cif.debugSymbols->SetImagePathWide(reinterpret_cast<PCWSTR>(imagePath.utf16()));
+    if (FAILED(hr)) {
+        *errorMessage = tr("Unable to set the image path to %1: %2").arg(imagePath, msgComFailed("SetImagePathWide", hr));
+        return false;
+    }
+
+    if (debug)
+        qDebug() << Q_FUNC_INFO <<'\n' << filename << imagePath;
+
+    ULONG symbolOptions = SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS;
+    if (verboseSymbolLoading)
+        symbolOptions |= SYMOPT_DEBUG;
+    m_cif.debugSymbols->SetSymbolOptions(symbolOptions);
+
+    const QString cmd = Utils::AbstractProcess::createWinCommandline(filename, args);
+    if (debug)
+        qDebug() << "Starting " << cmd;
+    PCWSTR env = 0;
+    QByteArray envData;
+    if (!envList.empty()) {
+        envData = Utils::AbstractProcess::createWinEnvironment(Utils::AbstractProcess::fixWinEnvironment(envList));
+        env = reinterpret_cast<PCWSTR>(envData.data());
+    }
+    // The working directory cannot be empty.
+    PCWSTR workingDirC = 0;
+    const QString workingDirN = workingDirectory.isEmpty() ? QString() : QDir::toNativeSeparators(workingDirectory);
+    if (!workingDirN.isEmpty())
+        workingDirC = workingDirN.utf16();
+    hr = m_cif.debugClient->CreateProcess2Wide(NULL,
+                                               reinterpret_cast<PWSTR>(const_cast<ushort *>(cmd.utf16())),
+                                               &dbgopts, sizeof(dbgopts),
+                                               workingDirC, env);
+    if (FAILED(hr)) {
+        *errorMessage = tr("Unable to create a process '%1': %2").arg(cmd, msgDebugEngineComResult(hr));
+        return false;
+    }
+    return true;
+}
+
+bool CoreEngine::startAttachDebugger(qint64 pid,
+                                     bool suppressInitialBreakPoint,
+                                     QString *errorMessage)
+{
+    // Need to attrach invasively, otherwise, no notification signals
+    // for for CreateProcess/ExitProcess occur.
+    // Initial breakpoint occur:
+    // 1) Desired: When attaching to a crashed process
+    // 2) Undesired: When starting up a console process, in conjunction
+    //    with the 32bit Wow-engine
+    //  As of version 6.11, the flag only affects 1). 2) Still needs to be suppressed
+    // by lookup at the state of the application (startup trap). However,
+    // there is no startup trap when attaching to a process that has been
+    // running for a while. (see notifyException).
+    ULONG flags = DEBUG_ATTACH_INVASIVE_RESUME_PROCESS;
+    if (suppressInitialBreakPoint)
+        flags |= DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK;
+    const HRESULT hr = m_cif.debugClient->AttachProcess(NULL, pid, flags);
+    if (debug)
+        qDebug() << "Attaching to " << pid << " using flags" << flags << " returns " << hr;
+    if (FAILED(hr)) {
+        *errorMessage = tr("Attaching to a process failed for process id %1: %2").arg(pid).arg(msgDebugEngineComResult(hr));
+        return false;
+    }
+    return true;
+}
+
+static inline QString pathString(const QStringList &s)
+{  return s.join(QString(QLatin1Char(';')));  }
+
+QStringList CoreEngine::sourcePaths() const
+{
+    WCHAR wszBuf[MAX_PATH];
+    if (SUCCEEDED(m_cif.debugSymbols->GetSourcePathWide(wszBuf, MAX_PATH, 0)))
+        return QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)).split(QLatin1Char(';'));
+    return QStringList();
+}
+
+bool CoreEngine::setSourcePaths(const QStringList &s, QString *errorMessage)
+{
+    const HRESULT hr = m_cif.debugSymbols->SetSourcePathWide(reinterpret_cast<PCWSTR>(pathString(s).utf16()));
+    if (FAILED(hr)) {
+        if (errorMessage)
+            *errorMessage = msgComFailed("SetSourcePathWide", hr);
+        return false;
+    }
+    return true;
+}
+
+QStringList CoreEngine::symbolPaths() const
+{
+    WCHAR wszBuf[MAX_PATH];
+    if (SUCCEEDED(m_cif.debugSymbols->GetSymbolPathWide(wszBuf, MAX_PATH, 0)))
+        return QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)).split(QLatin1Char(';'));
+    return QStringList();
+}
+
+bool CoreEngine::setSymbolPaths(const QStringList &s, QString *errorMessage)
+{
+    const HRESULT hr = m_cif.debugSymbols->SetSymbolPathWide(reinterpret_cast<PCWSTR>(pathString(s).utf16()));
+    if (FAILED(hr)) {
+        if (errorMessage)
+            *errorMessage = msgComFailed("SetSymbolPathWide", hr);
+        return false;
+    }
+    return true;
+}
+
+bool CoreEngine::executeDebuggerCommand(const QString &command, QString *errorMessage)
+{
+        // output to all clients, else we do not see anything
+    const HRESULT hr = m_cif.debugControl->ExecuteWide(DEBUG_OUTCTL_ALL_CLIENTS, reinterpret_cast<PCWSTR>(command.utf16()), 0);
+    if (debug)
+        qDebug() << "executeDebuggerCommand" << command << SUCCEEDED(hr);
+    if (FAILED(hr)) {
+        *errorMessage = QString::fromLatin1("Unable to execute '%1': %2").
+                        arg(command, msgDebugEngineComResult(hr));
+        return false;
+    }
+    return true;
+}
+
+// Those should not fail
+CoreEngine::ExpressionSyntax CoreEngine::expressionSyntax() const
+{
+    ULONG expressionSyntax = DEBUG_EXPR_MASM;
+    const HRESULT hr = m_cif.debugControl->GetExpressionSyntax(&expressionSyntax);
+    if (FAILED(hr))
+        qWarning("Unable to retrieve expression syntax: %s", qPrintable(msgComFailed("GetExpressionSyntax", hr)));
+    return expressionSyntax == DEBUG_EXPR_MASM ? AssemblerExpressionSyntax : CppExpressionSyntax;
+}
+
+CoreEngine::ExpressionSyntax CoreEngine::setExpressionSyntax(ExpressionSyntax es)
+{
+    const ExpressionSyntax old = expressionSyntax();
+    if (old != es) {
+        if (debug)
+            qDebug() << "Setting expression syntax" << es;
+        const HRESULT hr = m_cif.debugControl->SetExpressionSyntax(es == AssemblerExpressionSyntax ? DEBUG_EXPR_MASM : DEBUG_EXPR_CPLUSPLUS);
+        if (FAILED(hr))
+            qWarning("Unable to set expression syntax: %s", qPrintable(msgComFailed("SetExpressionSyntax", hr)));
+    }
+    return old;
+}
+
+CoreEngine::CodeLevel CoreEngine::codeLevel() const
+{
+    ULONG currentCodeLevel = DEBUG_LEVEL_ASSEMBLY;
+    HRESULT hr = m_cif.debugControl->GetCodeLevel(&currentCodeLevel);
+    if (FAILED(hr)) {
+        qWarning("Cannot determine code level: %s", qPrintable(msgComFailed("GetCodeLevel", hr)));
+    }
+    return currentCodeLevel == DEBUG_LEVEL_ASSEMBLY ? CodeLevelAssembly : CodeLevelSource;
+}
+
+CoreEngine::CodeLevel CoreEngine::setCodeLevel(CodeLevel cl)
+{
+    const CodeLevel old = codeLevel();
+    if (old != cl) {
+        if (debug)
+            qDebug() << "Setting code level" << cl;
+        const HRESULT hr = m_cif.debugControl->SetCodeLevel(cl == CodeLevelAssembly ? DEBUG_LEVEL_ASSEMBLY : DEBUG_LEVEL_SOURCE);
+        if (FAILED(hr))
+            qWarning("Unable to set code level: %s", qPrintable(msgComFailed("SetCodeLevel", hr)));
+    }
+    return old;
+}
+
+bool CoreEngine::evaluateExpression(const QString &expression,
+                                        QString *value,
+                                        QString *type,
+                                        QString *errorMessage)
+{
+    DEBUG_VALUE debugValue;
+    if (!evaluateExpression(expression, &debugValue, errorMessage))
+        return false;
+    *value = debugValueToString(debugValue, type, 10, m_cif.debugControl);
+    return true;
+}
+
+bool CoreEngine::evaluateExpression(const QString &expression,
+                                    DEBUG_VALUE *debugValue,
+                                    QString *errorMessage)
+{
+    if (debug > 1)
+        qDebug() << Q_FUNC_INFO << expression;
+
+    memset(debugValue, 0, sizeof(DEBUG_VALUE));
+    // Use CPP syntax, original syntax must be restored, else setting breakpoints will fail.
+    SyntaxSetter syntaxSetter(this, CppExpressionSyntax);
+    Q_UNUSED(syntaxSetter)
+    ULONG errorPosition = 0;
+    const HRESULT hr = m_cif.debugControl->EvaluateWide(reinterpret_cast<PCWSTR>(expression.utf16()),
+                                                        DEBUG_VALUE_INVALID, debugValue,
+                                                        &errorPosition);
+    if (FAILED(hr)) {
+        if (HRESULT_CODE(hr) == 517) {
+            *errorMessage = QString::fromLatin1("Unable to evaluate '%1': Expression out of scope.").
+                            arg(expression);
+        } else {
+            *errorMessage = QString::fromLatin1("Unable to evaluate '%1': Error at %2: %3").
+                            arg(expression).arg(errorPosition).arg(msgDebugEngineComResult(hr));
+        }
+        return false;
+    }
+    return true;
+}
+
+ULONG CoreEngine::executionStatus() const
+{
+    ULONG ex = DEBUG_STATUS_NO_CHANGE;
+    const HRESULT hr = m_cif.debugControl->GetExecutionStatus(&ex);
+    if (FAILED(hr))
+        qWarning("Cannot determine execution status: %s", qPrintable(msgComFailed("GetExecutionStatus", hr)));
+    return ex;
+}
+
+bool CoreEngine::setExecutionStatus(ULONG ex, QString *errorMessage)
+{
+    const HRESULT hr = m_cif.debugControl->SetExecutionStatus(ex);
+    if (FAILED(hr)) {
+        *errorMessage = QString::fromLatin1("Cannot set execution status to %1: %2")
+                        .arg(QLatin1String(msgExecutionStatusString(ex)), msgComFailed("SetExecutionStatus", hr));
+        return false;
+    }
+    return true;
+}
+
+static inline void appendError(const QString &what, QString *appendableErrorMessage)
+{
+    if (!appendableErrorMessage->isEmpty())
+        appendableErrorMessage->append(QLatin1Char('\n'));
+    appendableErrorMessage->append(what);
+}
+
+bool CoreEngine::detachCurrentProcess(QString *appendableErrorMessage)
+{
+    const HRESULT hr = m_cif.debugClient->DetachCurrentProcess();
+    if (FAILED(hr)) {
+        appendError(msgComFailed("DetachCurrentProcess", hr), appendableErrorMessage);
+        return false;
+    }
+    return true;
+}
+
+bool CoreEngine::terminateCurrentProcess(QString *appendableErrorMessage)
+{
+    const HRESULT hr = m_cif.debugClient->TerminateCurrentProcess();
+    if (FAILED(hr)) {
+        appendError(msgComFailed("TerminateCurrentProcess", hr), appendableErrorMessage);
+        return false;
+    }
+    return true;
+}
+
+bool CoreEngine::terminateProcesses(QString *appendableErrorMessage)
+{
+    const HRESULT hr = m_cif.debugClient->TerminateProcesses();
+    if (FAILED(hr)) {
+        appendError(msgComFailed("TerminateProcesses", hr), appendableErrorMessage);
+        return false;
+    }
+    return true;
+}
+
+bool CoreEngine::endSession(QString *appendableErrorMessage)
+{
+    const HRESULT hr = m_cif.debugClient->EndSession(DEBUG_END_PASSIVE);
+    if (FAILED(hr)) {
+        appendError(msgComFailed("EndSession", hr), appendableErrorMessage);
+        return false;
+    }
+    return true;
+}
+
+bool CoreEngine::allocDebuggeeMemory(int size, ULONG64 *address, QString *errorMessage)
+{
+    *address = 0;
+    const QString allocCmd = QLatin1String(".dvalloc ") + QString::number(size);
+
+    QSharedPointer<StringOutputHandler> outputHandler(new StringOutputHandler);
+    OutputRedirector redir(this, outputHandler);
+    Q_UNUSED(redir)
+    if (!executeDebuggerCommand(allocCmd, errorMessage))
+        return false;
+   // "Allocated 1000 bytes starting at 003a0000" .. hopefully never localized
+    bool ok = false;
+    const QString output = outputHandler->result();
+    const int lastBlank = output.lastIndexOf(QLatin1Char(' '));
+    if (lastBlank != -1) {
+        const qint64 addri = output.mid(lastBlank + 1).toLongLong(&ok, 16);
+        if (ok)
+            *address = addri;
+    }
+     if (debug > 1)
+        qDebug() << Q_FUNC_INFO << '\n' << output << *address << ok;
+    if (!ok) {
+        *errorMessage = QString::fromLatin1("Failed to parse output '%1'").arg(output);
+        return false;
+    }
+    return true;
+}
+
+// Alloc an AscII string in debuggee
+bool CoreEngine::createDebuggeeAscIIString(const QString &s,
+                                           ULONG64 *address,
+                                           QString *errorMessage)
+{
+    QByteArray sAsciiData = s.toLocal8Bit();
+    sAsciiData += '\0';
+    if (!allocDebuggeeMemory(sAsciiData.size(), address, errorMessage))
+        return false;
+    const HRESULT hr = m_cif.debugDataSpaces->WriteVirtual(*address, sAsciiData.data(), sAsciiData.size(), 0);
+    if (FAILED(hr)) {
+        *errorMessage= msgComFailed("WriteVirtual", hr);
+        return false;
+    }
+    return true;
+}
+
+// Write to debuggee memory in chunks
+bool CoreEngine::writeToDebuggee(const QByteArray &buffer, quint64 address, QString *errorMessage)
+{
+    char *ptr = const_cast<char*>(buffer.data());
+    ULONG bytesToWrite = buffer.size();
+    while (bytesToWrite > 0) {
+        ULONG bytesWritten = 0;
+        const HRESULT hr = m_cif.debugDataSpaces->WriteVirtual(address, ptr, bytesToWrite, &bytesWritten);
+        if (FAILED(hr)) {
+            *errorMessage = msgComFailed("WriteVirtual", hr);
+            return false;
+        }
+        bytesToWrite -= bytesWritten;
+        ptr += bytesWritten;
+    }
+    return true;
+}
+
+bool CoreEngine::dissassemble(ULONG64 offset,
+                              unsigned long beforeLines,
+                              unsigned long afterLines,
+                              QString *target,
+                              QString *errorMessage)
+{
+    const ULONG flags = DEBUG_DISASM_MATCHING_SYMBOLS|DEBUG_DISASM_SOURCE_LINE_NUMBER|DEBUG_DISASM_SOURCE_FILE_NAME;
+    // Catch the output by temporarily setting another handler.
+    // We use the method that outputs to the output handler as it
+    // conveniently provides the 'beforeLines' context (stepping back
+    // in assembler code). We build a complete string first as line breaks
+    // may occur in-between messages.
+    QSharedPointer<StringOutputHandler> outputHandler(new StringOutputHandler);
+    OutputRedirector redir(this, outputHandler);
+    // For some reason, we need to output to "all clients"
+    const HRESULT hr =  m_cif.debugControl->OutputDisassemblyLines(DEBUG_OUTCTL_ALL_CLIENTS,
+                                                                   beforeLines, beforeLines + afterLines,
+                                                                   offset, flags, 0, 0, 0, 0);
+    if (FAILED(hr)) {
+        *errorMessage= QString::fromLatin1("Unable to dissamble at 0x%1: %2").
+                       arg(offset, 0, 16).arg(msgComFailed("OutputDisassemblyLines", hr));
+        return false;
+    }
+    *target = outputHandler->result();
+    return true;
+}
+
+bool CoreEngine::autoDetectPath(QString *outPath,
+                                QStringList *checkedDirectories /* = 0 */)
+{
+    // Look for $ProgramFiles/"Debugging Tools For Windows <bit-idy>" and its
+    // " (x86)", " (x64)" variations. Qt Creator needs 64/32 bit depending
+    // on how it was built.
+#ifdef Q_OS_WIN64
+    static const char *postFixes[] = {" (x64)", " 64-bit" };
+#else
+    static const char *postFixes[] = { " (x86)", " (x32)" };
+#endif
+
+    outPath->clear();
+    const QByteArray programDirB = qgetenv("ProgramFiles");
+    if (programDirB.isEmpty())
+        return false;
+
+    const QString programDir = QString::fromLocal8Bit(programDirB) + QDir::separator();
+    const QString installDir = QLatin1String("Debugging Tools For Windows");
+
+    QString path = programDir + installDir;
+    if (checkedDirectories)
+        checkedDirectories->push_back(path);
+    if (QFileInfo(path).isDir()) {
+        *outPath = QDir::toNativeSeparators(path);
+        return true;
+    }
+    const int rootLength = path.size();
+    for (int i = 0; i < sizeof(postFixes)/sizeof(const char*); i++) {
+        path.truncate(rootLength);
+        path += QLatin1String(postFixes[i]);
+        if (checkedDirectories)
+            checkedDirectories->push_back(path);
+        if (QFileInfo(path).isDir()) {
+            *outPath = QDir::toNativeSeparators(path);
+            return true;
+        }
+    }
+    return false;
+}
+
+bool CoreEngine::debugBreakProcess(HANDLE hProcess, QString *errorMessage)
+{
+    const bool rc = DebugBreakProcess(hProcess);
+    if (!rc)
+        *errorMessage = QString::fromLatin1("DebugBreakProcess failed: %1").arg(Utils::winErrorMessage(GetLastError()));
+    return rc;
+}
+
+bool CoreEngine::setInterrupt(QString *errorMessage)
+{
+    const HRESULT hr = interfaces().debugControl->SetInterrupt(DEBUG_INTERRUPT_ACTIVE|DEBUG_INTERRUPT_EXIT);
+    if (FAILED(hr)) {
+        *errorMessage = QString::fromLatin1("Unable to interrupt debuggee after %1s: %2").
+                        arg(getInterruptTimeOutSecs(interfaces().debugControl)).arg(msgComFailed("SetInterrupt", hr));
+        return false;
+    }
+    return true;
+}
+
+// ------------- DEBUG_VALUE formatting helpers
+
+// format an array of integers as "0x323, 0x2322, ..."
+template <class Integer>
+static QString formatArrayHelper(const Integer *array, int size, int base = 10)
+{
+    QString rc;
+    const QString hexPrefix = QLatin1String("0x");
+    const QString separator = QLatin1String(", ");
+    const bool hex = base == 16;
+    for (int i = 0; i < size; i++) {
+        if (i)
+            rc += separator;
+        if (hex)
+            rc += hexPrefix;
+        rc += QString::number(array[i], base);
+    }
+    return rc;
+}
+
+QString hexFormatArray(const unsigned short *array, int size)
+{
+    return formatArrayHelper(array, size, 16);
+}
+
+// Helper to format an integer with
+// a hex prefix in case base = 16
+template <class Integer>
+        inline QString formatInteger(Integer value, int base)
+{
+    QString rc;
+    if (base == 16)
+        rc = QLatin1String("0x");
+    rc += QString::number(value, base);
+    return rc;
+}
+
+QString debugValueToString(const DEBUG_VALUE &dv,
+                           QString *qType /* =0 */,
+                           int integerBase,
+                           CIDebugControl *ctl /* =0 */)
+{
+    switch (dv.Type) {
+    case DEBUG_VALUE_INT8:
+        if (qType)
+            *qType = QLatin1String("char");
+        return formatInteger(dv.I8, integerBase);
+    case DEBUG_VALUE_INT16:
+        if (qType)
+            *qType = QLatin1String("short");
+        return formatInteger(static_cast<short>(dv.I16), integerBase);
+    case DEBUG_VALUE_INT32:
+        if (qType)
+            *qType = QLatin1String("long");
+        return formatInteger(static_cast<long>(dv.I32), integerBase);
+    case DEBUG_VALUE_INT64:
+        if (qType)
+            *qType = QLatin1String("long long");
+        return formatInteger(static_cast<long long>(dv.I64), integerBase);
+    case DEBUG_VALUE_FLOAT32:
+        if (qType)
+            *qType = QLatin1String("float");
+        return QString::number(dv.F32);
+    case DEBUG_VALUE_FLOAT64:
+        if (qType)
+            *qType = QLatin1String("double");
+        return QString::number(dv.F64);
+    case DEBUG_VALUE_FLOAT80:
+    case DEBUG_VALUE_FLOAT128: { // Convert to double
+            DEBUG_VALUE doubleValue;
+            double d = 0.0;
+            if (ctl && SUCCEEDED(ctl->CoerceValue(const_cast<DEBUG_VALUE*>(&dv), DEBUG_VALUE_FLOAT64, &doubleValue))) {
+                d = dv.F64;
+            } else {
+                qWarning("Unable to convert DEBUG_VALUE_FLOAT80/DEBUG_VALUE_FLOAT128 values");
+            }
+            if (qType)
+                *qType = QLatin1String(dv.Type == DEBUG_VALUE_FLOAT80 ? "80bit-float" : "128bit-float");
+            return QString::number(d);
+        }
+    case DEBUG_VALUE_VECTOR64: {
+            if (qType)
+                *qType = QLatin1String("64bit-vector");
+            QString rc = QLatin1String("bytes: ");
+            rc += formatArrayHelper(dv.VI8, 8, integerBase);
+            rc += QLatin1String(" long: ");
+            rc += formatArrayHelper(dv.VI32, 2, integerBase);
+            return rc;
+        }
+    case DEBUG_VALUE_VECTOR128: {
+            if (qType)
+                *qType = QLatin1String("128bit-vector");
+            QString rc = QLatin1String("bytes: ");
+            rc += formatArrayHelper(dv.VI8, 16, integerBase);
+            rc += QLatin1String(" long long: ");
+            rc += formatArrayHelper(dv.VI64, 2, integerBase);
+            return rc;
+        }
+    }
+    if (qType)
+        *qType = QString::fromLatin1("Unknown type #%1:").arg(dv.Type);
+    return formatArrayHelper(dv.RawBytes, 24, integerBase);
+}
+
+bool debugValueToInteger(const DEBUG_VALUE &dv, qint64 *value)
+{
+    *value = 0;
+    switch (dv.Type) {
+    case DEBUG_VALUE_INT8:
+        *value = dv.I8;
+        return true;
+    case DEBUG_VALUE_INT16:
+        *value = static_cast<short>(dv.I16);
+        return true;
+    case DEBUG_VALUE_INT32:
+        *value = static_cast<long>(dv.I32);
+        return true;
+    case DEBUG_VALUE_INT64:
+        *value = static_cast<long long>(dv.I64);
+        return true;
+    default:
+        break;
+    }
+    return false;
+}
+
+} // namespace CdbCore
diff --git a/src/plugins/debugger/cdb/coreengine.h b/src/plugins/debugger/cdb/coreengine.h
new file mode 100644
index 0000000000000000000000000000000000000000..00c8dd0096e9594d4f054865fe40ddf87eb05a69
--- /dev/null
+++ b/src/plugins/debugger/cdb/coreengine.h
@@ -0,0 +1,191 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef COREENGINE_H
+#define COREENGINE_H
+
+#include "cdbcom.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QSharedPointer>
+
+namespace CdbCore {
+
+class DebugOutputBase;
+class DebugEventCallbackBase;
+
+// helper struct to pass interfaces around
+struct ComInterfaces
+{
+    ComInterfaces();
+
+    CIDebugClient*          debugClient;
+    CIDebugControl*         debugControl;
+    CIDebugSystemObjects*   debugSystemObjects;
+    CIDebugSymbols*         debugSymbols;
+    CIDebugRegisters*       debugRegisters;
+    CIDebugDataSpaces*      debugDataSpaces;
+};
+
+class CoreEngine : public QObject
+{
+    Q_DISABLE_COPY(CoreEngine)
+    Q_OBJECT
+public:
+    enum ExpressionSyntax { AssemblerExpressionSyntax, CppExpressionSyntax };
+    enum CodeLevel { CodeLevelAssembly, CodeLevelSource };
+
+   typedef QSharedPointer<DebugOutputBase> DebugOutputBasePtr;
+   typedef QSharedPointer<DebugEventCallbackBase> DebugEventCallbackBasePtr;
+
+    explicit CoreEngine(QObject *parent = 0);
+    virtual ~CoreEngine();
+
+    bool init(const QString &dllEnginePath, QString *errorMessage);
+    // code level/output
+
+    inline const ComInterfaces &interfaces() const { return m_cif; }
+
+    // Set handlers
+    DebugOutputBasePtr setDebugOutput(const DebugOutputBasePtr &);
+    DebugEventCallbackBasePtr setDebugEventCallback(const DebugEventCallbackBasePtr &);
+
+    // Start functions
+    bool startDebuggerWithExecutable(const QString &workingDirectory,
+                                     const QString &filename,
+                                     const QStringList &args,
+                                     const QStringList &env,
+                                     bool verboseSymbolLoading,
+                                     QString *errorMessage);
+
+    bool startAttachDebugger(qint64 pid, bool suppressInitialBreakPoint,
+                             QString *errorMessage);
+
+    ULONG executionStatus() const;
+    bool setExecutionStatus(ULONG ex, QString *errorMessage);
+
+    // break & interrupt
+    bool debugBreakProcess(HANDLE hProcess, QString *errorMessage);
+    // Currently does not interrupt debuggee
+    bool setInterrupt(QString *errorMessage);
+
+    // Helpers for terminating the debuggees and ending the session
+    bool detachCurrentProcess(QString *appendableErrorMessage);
+    bool terminateCurrentProcess(QString *appendableErrorMessage);
+    bool terminateProcesses(QString *appendableErrorMessage);
+    bool endSession(QString *appendableErrorMessage);
+
+    // Watch timer: Listen for debug events and emit watchTimerDebugEvent() should one
+    // occur.
+    void startWatchTimer();
+    void killWatchTimer();
+    inline bool isWatchTimerRunning() const { return m_watchTimer != -1; }
+    // Synchronous wait
+    HRESULT waitForEvent(int timeOutMS);
+
+    // Commands and expressions
+    bool executeDebuggerCommand(const QString &command, QString *errorMessage);
+
+    bool evaluateExpression(const QString &expression,
+                            DEBUG_VALUE *debugValue,
+                            QString *errorMessage);
+    bool evaluateExpression(const QString &expression, QString *value,
+                            QString *type /* =0 */, QString *errorMessage);
+
+    // Path getters/setters
+    QStringList sourcePaths() const;
+    bool setSourcePaths(const QStringList &s, QString *errorMessage);
+    QStringList symbolPaths() const;
+    bool setSymbolPaths(const QStringList &s, QString *errorMessage);
+
+    // Options
+    ExpressionSyntax expressionSyntax() const;
+    ExpressionSyntax setExpressionSyntax(ExpressionSyntax es);
+
+    CodeLevel codeLevel() const;
+    CodeLevel setCodeLevel(CodeLevel);
+
+    QString dbengDLL() const { return m_dbengDLL; }
+
+    // Debuggee memory conveniences
+    bool allocDebuggeeMemory(int size, ULONG64 *address, QString *errorMessage);
+    bool createDebuggeeAscIIString(const QString &s, ULONG64 *address, QString *errorMessage);
+    bool writeToDebuggee(const QByteArray &buffer, quint64 address, QString *errorMessage);
+    // Write to debuggee memory in chunks
+    bool dissassemble(ULONG64 offset, unsigned long beforeLines, unsigned long afterLines,
+                      QString *target, QString *errorMessage);
+
+    static bool autoDetectPath(QString *outPath,
+                               QStringList *checkedDirectories = 0);
+
+signals:
+    void watchTimerDebugEvent();
+
+protected:
+    virtual void timerEvent(QTimerEvent* te);
+
+private:
+    ComInterfaces m_cif;
+    DebugOutputBasePtr m_debugOutput;
+    DebugEventCallbackBasePtr m_debugEventCallback;
+    QString m_dbengDLL;
+    QString m_baseImagePath;
+    int m_watchTimer;
+};
+
+// Utility messages
+QString msgDebugEngineComResult(HRESULT hr);
+QString msgComFailed(const char *func, HRESULT hr);
+QString msgDebuggerCommandFailed(const QString &command, HRESULT hr);
+const char *msgExecutionStatusString(ULONG executionStatus);
+
+// A class that sets an expression syntax on the debug control while in scope.
+// Can be nested as it checks for the old value.
+class SyntaxSetter {
+    Q_DISABLE_COPY(SyntaxSetter)
+public:
+    explicit inline SyntaxSetter(CoreEngine *engine, CoreEngine::ExpressionSyntax es) :
+                        m_oldSyntax(engine->setExpressionSyntax(es)),
+                        m_engine(engine) {}
+    inline  ~SyntaxSetter() { m_engine->setExpressionSyntax(m_oldSyntax); }
+
+private:
+    const CoreEngine::ExpressionSyntax m_oldSyntax;
+    CoreEngine *m_engine;
+};
+
+// Helpers to convert DEBUG_VALUE structs. The optional control is required to
+// convert large floating values.
+QString debugValueToString(const DEBUG_VALUE &dv, QString *qType =0, int integerBase = 10, CIDebugControl *ctl = 0);
+bool debugValueToInteger(const DEBUG_VALUE &dv, qint64 *value);
+
+} // namespace CdbCore
+
+#endif // COREENGINE_H
diff --git a/src/plugins/debugger/cdb/debugeventcallbackbase.cpp b/src/plugins/debugger/cdb/debugeventcallbackbase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..36e5e0d45c9cc85576582147c70b5aee4f476097
--- /dev/null
+++ b/src/plugins/debugger/cdb/debugeventcallbackbase.cpp
@@ -0,0 +1,219 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "debugeventcallbackbase.h"
+#include "coreengine.h"
+
+namespace CdbCore {
+
+// DebugEventCallbackBase
+DebugEventCallbackBase::DebugEventCallbackBase()
+{
+}
+
+DebugEventCallbackBase::~DebugEventCallbackBase()
+{
+}
+
+STDMETHODIMP DebugEventCallbackBase::QueryInterface(
+    THIS_
+    IN REFIID InterfaceId,
+    OUT PVOID* Interface)
+{
+    *Interface = NULL;
+
+    if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
+        IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))  {
+        *Interface = (IDebugOutputCallbacks *)this;
+        AddRef();
+        return S_OK;
+    } else {
+        return E_NOINTERFACE;
+    }
+}
+
+STDMETHODIMP_(ULONG) DebugEventCallbackBase::AddRef(THIS)
+{
+    // This class is designed to be static so
+    // there's no true refcount.
+    return 1;
+}
+
+STDMETHODIMP_(ULONG) DebugEventCallbackBase::Release(THIS)
+{
+    // This class is designed to be static so
+    // there's no true refcount.
+    return 0;
+}
+
+STDMETHODIMP DebugEventCallbackBase::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT2)
+{
+    return S_OK;
+}
+STDMETHODIMP DebugEventCallbackBase::Exception(
+    THIS_
+    __in PEXCEPTION_RECORD64,
+    __in ULONG /* FirstChance */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::CreateThread(
+    THIS_
+    __in ULONG64 /* Handle */,
+    __in ULONG64 /* DataOffset */,
+    __in ULONG64 /* StartOffset */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::ExitThread(
+    THIS_
+    __in ULONG /* ExitCode */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::CreateProcess(
+    THIS_
+    __in ULONG64 /* ImageFileHandle */,
+    __in ULONG64 /* Handle */,
+    __in ULONG64 /* BaseOffset */,
+    __in ULONG /* ModuleSize */,
+    __in_opt PCWSTR /* ModuleName */,
+    __in_opt PCWSTR /* ImageName */,
+    __in ULONG /* CheckSum */,
+    __in ULONG /* TimeDateStamp */,
+    __in ULONG64 /* InitialThreadHandle */,
+    __in ULONG64 /* ThreadDataOffset */,
+    __in ULONG64 /* StartOffset */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::ExitProcess(
+    THIS_
+    __in ULONG /* ExitCode */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::LoadModule(
+    THIS_
+    __in ULONG64 /* ImageFileHandle */,
+    __in ULONG64 /* BaseOffset */,
+    __in ULONG /* ModuleSize */,
+    __in_opt PCWSTR /* ModuleName */,
+    __in_opt PCWSTR /* ImageName */,
+    __in ULONG /* CheckSum */,
+    __in ULONG /* TimeDateStamp */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::UnloadModule(
+    THIS_
+    __in_opt PCWSTR /* ImageBaseName */,
+    __in ULONG64 /* BaseOffset */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::SystemError(
+    THIS_
+    __in ULONG /* Error */,
+    __in ULONG /* Level */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::SessionStatus(
+    THIS_
+    __in ULONG /* Status */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::ChangeDebuggeeState(
+    THIS_
+    __in ULONG /* Flags */,
+    __in ULONG64 /* Argument */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::ChangeEngineState(
+    THIS_
+    __in ULONG /* Flags */,
+    __in ULONG64 /* Argument */
+    )
+{
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallbackBase::ChangeSymbolState(
+    THIS_
+    __in ULONG /* Flags */,
+    __in ULONG64 /* Argument */
+    )
+{
+    return S_OK;
+}
+
+IDebugEventCallbacksWide *DebugEventCallbackBase::getEventCallback(CIDebugClient *clnt)
+{
+    IDebugEventCallbacksWide *rc = 0;
+    if (SUCCEEDED(clnt->GetEventCallbacksWide(&rc)))
+        return rc;
+    return 0;
+}
+
+EventCallbackRedirector::EventCallbackRedirector(CoreEngine *engine,
+                                                 const DebugEventCallbackBasePtr &cb) :
+    m_engine(engine),
+    m_oldCallback(engine->setDebugEventCallback(cb))
+{
+}
+
+EventCallbackRedirector::~EventCallbackRedirector()
+{
+    m_engine->setDebugEventCallback(m_oldCallback);
+}
+
+} // namespace CdbCore
diff --git a/src/plugins/debugger/cdb/debugeventcallbackbase.h b/src/plugins/debugger/cdb/debugeventcallbackbase.h
new file mode 100644
index 0000000000000000000000000000000000000000..78832c4c0affe2d0be5188a04ec92b4db3f5a689
--- /dev/null
+++ b/src/plugins/debugger/cdb/debugeventcallbackbase.h
@@ -0,0 +1,174 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DEBUGEVENTCALLBACKBASE_H
+#define DEBUGEVENTCALLBACKBASE_H
+
+#include "cdbcom.h"
+
+#include <QtCore/QSharedPointer>
+
+namespace CdbCore {
+
+class CoreEngine;
+
+// Base class for event callbacks that takes care
+// Active X magic. Provides base implementations with
+// the exception of GetInterestMask
+class DebugEventCallbackBase : public IDebugEventCallbacksWide
+{
+protected:
+    DebugEventCallbackBase();
+public:
+    virtual ~DebugEventCallbackBase();
+    // IUnknown.
+    STDMETHOD(QueryInterface)(
+            THIS_
+            IN REFIID InterfaceId,
+            OUT PVOID* Interface
+            );
+    STDMETHOD_(ULONG, AddRef)(
+            THIS
+            );
+    STDMETHOD_(ULONG, Release)(
+            THIS
+            );
+
+    // IDebugEventCallbacks.
+
+    STDMETHOD(Breakpoint)(
+            THIS_
+            __in PDEBUG_BREAKPOINT2 Bp
+            );
+
+    STDMETHOD(Exception)(
+            THIS_
+            __in PEXCEPTION_RECORD64 Exception,
+            __in ULONG FirstChance
+            );
+
+    STDMETHOD(CreateThread)(
+            THIS_
+            __in ULONG64 Handle,
+            __in ULONG64 DataOffset,
+            __in ULONG64 StartOffset
+            );
+    STDMETHOD(ExitThread)(
+            THIS_
+            __in ULONG ExitCode
+            );
+
+    STDMETHOD(CreateProcess)(
+            THIS_
+            __in ULONG64 ImageFileHandle,
+            __in ULONG64 Handle,
+            __in ULONG64 BaseOffset,
+            __in ULONG ModuleSize,
+            __in_opt PCWSTR ModuleName,
+            __in_opt PCWSTR ImageName,
+            __in ULONG CheckSum,
+            __in ULONG TimeDateStamp,
+            __in ULONG64 InitialThreadHandle,
+            __in ULONG64 ThreadDataOffset,
+            __in ULONG64 StartOffset
+            );
+
+    STDMETHOD(ExitProcess)(
+            THIS_
+            __in ULONG ExitCode
+            );
+
+    STDMETHOD(LoadModule)(
+            THIS_
+            __in ULONG64 ImageFileHandle,
+            __in ULONG64 BaseOffset,
+            __in ULONG ModuleSize,
+            __in_opt PCWSTR ModuleName,
+            __in_opt PCWSTR ImageName,
+            __in ULONG CheckSum,
+            __in ULONG TimeDateStamp
+            );
+
+    STDMETHOD(UnloadModule)(
+            THIS_
+            __in_opt PCWSTR ImageBaseName,
+            __in ULONG64 BaseOffset
+            );
+
+    STDMETHOD(SystemError)(
+            THIS_
+            __in ULONG Error,
+            __in ULONG Level
+            );
+
+    STDMETHOD(SessionStatus)(
+            THIS_
+            __in ULONG Status
+            );
+
+    STDMETHOD(ChangeDebuggeeState)(
+            THIS_
+            __in ULONG Flags,
+            __in ULONG64 Argument
+            );
+
+    STDMETHOD(ChangeEngineState)(
+            THIS_
+            __in ULONG Flags,
+            __in ULONG64 Argument
+            );
+
+    STDMETHOD(ChangeSymbolState)(
+            THIS_
+            __in ULONG Flags,
+            __in ULONG64 Argument
+            );
+
+
+    static IDebugEventCallbacksWide *getEventCallback(CIDebugClient *clnt);
+};
+
+// Utility class to temporarily redirect events to another handler
+// as long as in scope
+class EventCallbackRedirector {
+    Q_DISABLE_COPY(EventCallbackRedirector)
+public:
+    typedef QSharedPointer<DebugEventCallbackBase> DebugEventCallbackBasePtr;
+
+    explicit EventCallbackRedirector(CoreEngine *engine, const DebugEventCallbackBasePtr &cb);
+    ~EventCallbackRedirector();
+
+private:
+    CoreEngine *m_engine;
+    const DebugEventCallbackBasePtr m_oldCallback;
+};
+
+} // namespace CdbCore
+
+#endif // DEBUGEVENTCALLBACKBASE_H
diff --git a/src/plugins/debugger/cdb/debugoutputbase.cpp b/src/plugins/debugger/cdb/debugoutputbase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..25e278c1c8e70aedd93a97e8a84f6489e348a425
--- /dev/null
+++ b/src/plugins/debugger/cdb/debugoutputbase.cpp
@@ -0,0 +1,134 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "debugoutputbase.h"
+#include "coreengine.h"
+#include <QtCore/QDebug>
+
+namespace CdbCore {
+
+DebugOutputBase::DebugOutputBase()
+{
+}
+
+DebugOutputBase::~DebugOutputBase() // must be present to avoid exit crashes
+{
+}
+
+STDMETHODIMP DebugOutputBase::QueryInterface(
+        THIS_
+        IN REFIID InterfaceId,
+        OUT PVOID* Interface
+        )
+{
+    *Interface = NULL;
+
+    if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
+        IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacksWide)))
+    {
+        *Interface = (IDebugOutputCallbacksWide*)this;
+        AddRef();
+        return S_OK;
+    } else {
+        return E_NOINTERFACE;
+    }
+}
+
+STDMETHODIMP_(ULONG) DebugOutputBase::AddRef(THIS)
+{
+    // This class is designed to be static so
+    // there's no true refcount.
+    return 1;
+}
+
+STDMETHODIMP_(ULONG) DebugOutputBase::Release(THIS)
+{
+    // This class is designed to be static so
+    // there's no true refcount.
+    return 0;
+}
+
+STDMETHODIMP DebugOutputBase::Output(
+        THIS_
+        IN ULONG mask,
+        IN PCWSTR text
+        )
+{
+    const QString msg = QString::fromUtf16(reinterpret_cast<const ushort *>(text));
+    output(mask, msg);
+    return S_OK;
+}
+
+IDebugOutputCallbacksWide *DebugOutputBase::getOutputCallback(CIDebugClient *client)
+{
+    IDebugOutputCallbacksWide *rc;
+    if (FAILED(client->GetOutputCallbacksWide(&rc)))
+        return 0;
+    return rc;
+}
+
+const char *DebugOutputBase::maskDescription(ULONG m)
+{
+    switch (m) {
+    case DEBUG_OUTPUT_NORMAL:
+        break;
+    case DEBUG_OUTPUT_ERROR:
+        return "error";
+    case DEBUG_OUTPUT_WARNING:
+        return "warn";
+    case DEBUG_OUTPUT_VERBOSE:
+        return "verbose";
+    case DEBUG_OUTPUT_PROMPT_REGISTERS:
+        return "register";
+    case DEBUG_OUTPUT_EXTENSION_WARNING:
+        return "extwarn";
+    case DEBUG_OUTPUT_DEBUGGEE:
+        return "target";
+    case DEBUG_OUTPUT_DEBUGGEE_PROMPT:
+        return "input";
+    case DEBUG_OUTPUT_SYMBOLS:
+        return "symbol";
+    default:
+        break;
+    }
+    return "misc";
+}
+
+OutputRedirector::OutputRedirector(CoreEngine *engine, const DebugOutputBasePtr &o) :
+    m_engine(engine),
+    m_oldOutput(engine->setDebugOutput(o))
+{
+}
+
+OutputRedirector::~OutputRedirector()
+{
+    m_engine->setDebugOutput(m_oldOutput);
+}
+
+} // namespace CdbCore
diff --git a/src/plugins/debugger/cdb/debugoutputbase.h b/src/plugins/debugger/cdb/debugoutputbase.h
new file mode 100644
index 0000000000000000000000000000000000000000..029c3c4e37b85cce3cb23aea47680bda1abbe541
--- /dev/null
+++ b/src/plugins/debugger/cdb/debugoutputbase.h
@@ -0,0 +1,111 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DEBUGOUTPUTBASE_H
+#define DEBUGOUTPUTBASE_H
+
+#include "cdbcom.h"
+
+#include <QtCore/QString>
+#include <QtCore/QSharedPointer>
+
+namespace CdbCore {
+
+class CoreEngine;
+
+// CdbDebugOutputBase is a base class for output handlers
+// that takes care of the Active X magic and conversion to QString.
+
+class DebugOutputBase : public IDebugOutputCallbacksWide
+{
+public:
+    virtual ~DebugOutputBase();
+    // IUnknown.
+    STDMETHOD(QueryInterface)(
+            THIS_
+            IN REFIID InterfaceId,
+            OUT PVOID* Interface
+            );
+    STDMETHOD_(ULONG, AddRef)(
+            THIS
+            );
+    STDMETHOD_(ULONG, Release)(
+            THIS
+            );
+
+    // IDebugOutputCallbacks.
+    STDMETHOD(Output)(
+            THIS_
+            IN ULONG mask,
+            IN PCWSTR text
+            );
+
+    // Helpers to retrieve the output callbacks IF
+    static IDebugOutputCallbacksWide *getOutputCallback(CIDebugClient *client);
+    static const char *maskDescription(ULONG m);
+
+protected:
+    DebugOutputBase();
+    virtual void output(ULONG mask, const QString &message) = 0;
+};
+
+// An output handler that adds lines to a string (to be
+// used for cases in which linebreaks occur in-between calls
+// to output).
+class StringOutputHandler : public DebugOutputBase
+{
+public:
+    StringOutputHandler() {}
+    QString result() const { return m_result; }
+
+protected:
+    virtual void output(ULONG, const QString &message) { m_result += message; }
+
+private:
+    QString m_result;
+};
+
+// Utility class to temporarily redirect output to another handler
+// as long as in scope
+class OutputRedirector {
+    Q_DISABLE_COPY(OutputRedirector)
+public:
+    typedef QSharedPointer<DebugOutputBase> DebugOutputBasePtr;
+
+    explicit OutputRedirector(CoreEngine *engine, const DebugOutputBasePtr &o);
+    ~OutputRedirector();
+
+private:
+    CoreEngine *m_engine;
+    const DebugOutputBasePtr m_oldOutput;
+};
+
+} // namespace CdbCore
+
+#endif // DEBUGOUTPUTBASE_H
diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h
index 9763b362d92a5246ebf768ce3309361d8865a20e..bda011154345fad13ac70b2223088eac3aa952c1 100644
--- a/src/plugins/debugger/debuggermanager.h
+++ b/src/plugins/debugger/debuggermanager.h
@@ -85,7 +85,7 @@ class IDebuggerEngine;
 class GdbEngine;
 class ScriptEngine;
 class CdbDebugEngine;
-struct CdbDebugEnginePrivate;
+class CdbDebugEnginePrivate;
 struct DebuggerManagerActions;
 class DebuggerPlugin;
 class CdbDebugEventCallback;
@@ -94,7 +94,7 @@ class CdbDumperInitThread;
 class CdbExceptionLoggerEventCallback;
 class GdbEngine;
 class CdbDebugEngine;
-struct CdbDebugEnginePrivate;
+class CdbDebugEnginePrivate;
 } // namespace Internal
 
 class DEBUGGER_EXPORT DebuggerStartParameters
@@ -169,7 +169,7 @@ public:
     friend class Internal::GdbEngine;
     friend class Internal::ScriptEngine;
     friend class Internal::CdbDebugEngine;
-    friend struct Internal::CdbDebugEnginePrivate;
+    friend class Internal::CdbDebugEnginePrivate;
 
     DebuggerState state() const;
     QList<Core::IOptionsPage*> initializeEngines(unsigned enabledTypeFlags);
diff --git a/tests/manual/ccdb/README b/tests/manual/ccdb/README
new file mode 100644
index 0000000000000000000000000000000000000000..56e3426f2f4241dd4cf39b4424ccd67203eb7e0e
--- /dev/null
+++ b/tests/manual/ccdb/README
@@ -0,0 +1,2 @@
+This directory contains a command line tool to the Debugging Tools for
+Windows for testing/scripting purposes.
diff --git a/tests/manual/ccdb/ccdb.pro b/tests/manual/ccdb/ccdb.pro
new file mode 100644
index 0000000000000000000000000000000000000000..6021878be3e2b5ef48b931166e79332a8f3b5eb8
--- /dev/null
+++ b/tests/manual/ccdb/ccdb.pro
@@ -0,0 +1,29 @@
+# -------------------------------------------------
+# Project created by QtCreator 2010-01-22T10:11:10
+# -------------------------------------------------
+QT += core
+TARGET = ccdb
+CONFIG += console
+CONFIG -= app_bundle
+TEMPLATE = app
+
+# -- Add CDB core engine
+CDB_CORE = ../../../src/plugins/debugger/cdb
+include($$CDB_CORE/cdbcore.pri)
+INCLUDEPATH *= $$CDB_CORE
+
+# -- Add creator 'utils' lib
+CREATOR_LIB_LIB = ../../../lib/qtcreator
+LIBS *= -L$$CREATOR_LIB_LIB
+LIBS *= -l$$qtLibraryTarget(Utilsd)
+CREATOR_LIB_SRC = ../../../src/libs
+INCLUDEPATH *= $$CREATOR_LIB_SRC
+
+# -- App sources
+SOURCES += main.cpp \
+    cdbapplication.cpp \
+    debugeventcallback.cpp \
+    cdbpromptthread.cpp
+HEADERS += cdbapplication.h \
+    debugeventcallback.h \
+    cdbpromptthread.h
diff --git a/tests/manual/ccdb/cdbapplication.cpp b/tests/manual/ccdb/cdbapplication.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..426cd0172adce174e17e0973f57111d223baa092
--- /dev/null
+++ b/tests/manual/ccdb/cdbapplication.cpp
@@ -0,0 +1,213 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "cdbapplication.h"
+#include "coreengine.h"
+#include "cdbdebugoutput.h"
+#include "cdbpromptthread.h"
+#include "debugeventcallback.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QTimer>
+
+#include <cstdio>
+
+const char usage[] =
+"CDB command line test tool\n\n"
+"ccdb <Options>\n"
+"Options: -p engine path\n";
+
+class PrintfOutputHandler : public CdbCore::DebugOutputBase
+{
+public:
+    PrintfOutputHandler() {}
+
+protected:
+    virtual void output(ULONG mask, const QString &message)
+    { std::printf("%10s: %s\n", maskDescription(mask), qPrintable(message)); }
+};
+
+
+// -------------- CdbApplication
+CdbApplication::CdbApplication(int argc, char *argv[]) :
+        QCoreApplication(argc, argv),
+        m_engine(new CdbCore::CoreEngine),
+        m_promptThread(0),
+        m_processHandle(0)
+{
+}
+
+CdbApplication::~CdbApplication()
+{
+}
+
+CdbApplication::InitResult CdbApplication::init()
+{
+    if (!parseOptions()) {
+        printf(usage);
+        return InitUsageShown;
+    }
+    QString errorMessage;
+    std::printf("Initializing engine %s...\n", qPrintable(m_engineDll));
+    if (!m_engine->init(m_engineDll, &errorMessage)) {
+        std::fprintf(stderr, "Failed: %s\n", qPrintable(errorMessage));
+        return InitFailed;
+    }
+    m_engine->setDebugOutput(CdbCore::CoreEngine::DebugOutputBasePtr(new PrintfOutputHandler));
+    DebugEventCallback *evt = new DebugEventCallback;
+    connect(evt, SIGNAL(processAttached(void*)), this, SLOT(processAttached(void*)));
+    m_engine->setDebugEventCallback(CdbCore::CoreEngine::DebugEventCallbackBasePtr(evt));
+    m_engine->setExpressionSyntax(CdbCore::CoreEngine::CppExpressionSyntax);
+    m_engine->setCodeLevel(CdbCore::CoreEngine::CodeLevelSource);
+    connect(m_engine.data(), SIGNAL(watchTimerDebugEvent()), this, SLOT(debugEvent()));
+    std::printf("Succeded.\n");
+    // Prompt
+    m_promptThread = new CdbPromptThread(this);
+    connect(m_promptThread, SIGNAL(finished()), this, SLOT(promptThreadTerminated()));
+    connect(m_promptThread, SIGNAL(asyncCommand(int,QString)),
+            this, SLOT(asyncCommand(int,QString)), Qt::QueuedConnection);
+    connect(m_promptThread, SIGNAL(syncCommand(int,QString)),
+            this, SLOT(syncCommand(int,QString)), Qt::BlockingQueuedConnection);
+    connect(m_promptThread, SIGNAL(executionCommand(int,QString)),
+            this, SLOT(executionCommand(int,QString)), Qt::BlockingQueuedConnection);
+
+    m_promptThread->start();
+    return InitOk;
+}
+
+void CdbApplication::promptThreadTerminated()
+{
+    QString errorMessage;
+    m_engine->endSession(&errorMessage);
+    std::printf("Terminating.\n");
+    m_promptThread->wait();
+    quit();
+}
+
+bool CdbApplication::parseOptions()
+{
+    const QStringList args = QCoreApplication::arguments();
+    const QStringList::const_iterator cend = args.constEnd();
+    QStringList::const_iterator it = args.constBegin();
+    for (++it; it != cend ; ++it) {
+        const QString &a = *it;
+        if (a == QLatin1String("-p")) {
+            ++it;
+            if (it == cend) {
+                std::fprintf(stderr, "Option -p is missing an argument.\n");
+                return false;
+            }
+            m_engineDll = *it;
+        } else {
+            std::fprintf(stderr, "Invalid option %s\n", qPrintable(a));
+            return false;
+        }
+    }
+    return true;
+}
+
+void CdbApplication::asyncCommand(int command, const QString &arg)
+{
+    Q_UNUSED(arg)
+    QString errorMessage;
+    switch (command) {
+    case Async_Interrupt:
+        if (m_processHandle) {
+            if (m_engine->debugBreakProcess(m_processHandle, &errorMessage)) {
+                std::printf("Stopped\n");
+            } else {
+                std::printf("%s\n", qPrintable(errorMessage));
+            }
+        }
+        break;
+    }
+}
+
+void CdbApplication::syncCommand(int command, const QString &arg)
+{
+    QString errorMessage;
+    switch (command) {
+    case Sync_EvalExpression: {
+            QString value;
+            QString type;
+            if (m_engine->evaluateExpression(arg, &value, &type, &errorMessage)) {
+                std::printf("[%s] %s\n", qPrintable(type), qPrintable(value));
+            } else {
+                std::printf("%s\n", qPrintable(errorMessage));
+            }
+        }
+        break;
+    case Unknown:
+        if (!m_engine->executeDebuggerCommand(arg, &errorMessage))
+            std::printf("%s\n", qPrintable(errorMessage));
+        break;
+    }
+}
+
+void CdbApplication::executionCommand(int command, const QString &arg)
+{
+    bool ok = false;
+    QString errorMessage;
+    switch (command) {
+    case Execution_StartBinary: {
+            QStringList args = arg.split(QLatin1Char(' '), QString::SkipEmptyParts);
+            if (args.isEmpty()) {
+                errorMessage = QLatin1String("Specify executable.");
+            } else {
+                std::printf("Starting\n");
+                const QString binary = args.front();
+                args.pop_front();                
+                ok = m_engine->startDebuggerWithExecutable(QString(), binary, args,
+                                                           QStringList(), false,
+                                                           &errorMessage);
+            }
+        }
+        break;
+    case Execution_Go:
+        std::printf("Go\n");
+        ok = m_engine->setExecutionStatus(DEBUG_STATUS_GO, &errorMessage);
+        break;
+    }
+    if (ok) {
+        m_engine->startWatchTimer();
+    } else {
+        std::fprintf(stderr, "%s\n", qPrintable(errorMessage));
+    }
+}
+
+void CdbApplication::debugEvent()
+{
+    std::printf("Debug event\n");
+}
+
+void CdbApplication::processAttached(void *handle)
+{
+    std::printf("pe\n");
+    m_processHandle = handle;
+}
diff --git a/tests/manual/ccdb/cdbapplication.h b/tests/manual/ccdb/cdbapplication.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ee35b24c253bb9c8808a8ac4091ed447a8c879d
--- /dev/null
+++ b/tests/manual/ccdb/cdbapplication.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CDBAPPLICATION_H
+#define CDBAPPLICATION_H
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QSharedPointer>
+
+namespace CdbCore {
+    class CoreEngine;
+}
+
+class CdbPromptThread;
+
+class CdbApplication : public QCoreApplication
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(CdbApplication)
+public:
+    enum InitResult { InitFailed, InitUsageShown, InitOk };
+
+    CdbApplication(int argc, char *argv[]);
+    ~CdbApplication();
+
+    InitResult init();
+
+private slots:
+    void promptThreadTerminated();
+    void asyncCommand(int command, const QString &arg);
+    void syncCommand(int command, const QString &arg);
+    void executionCommand(int command, const QString &arg);
+    void debugEvent();
+    void processAttached(void *handle);
+
+private:
+    bool parseOptions();
+
+    QString m_engineDll;
+    QSharedPointer<CdbCore::CoreEngine> m_engine;
+    CdbPromptThread *m_promptThread;
+    void *m_processHandle;
+};
+
+#endif // CDBAPPLICATION_H
diff --git a/tests/manual/ccdb/cdbpromptthread.cpp b/tests/manual/ccdb/cdbpromptthread.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..66a13b28942f48f092ece474508838f939b7b259
--- /dev/null
+++ b/tests/manual/ccdb/cdbpromptthread.cpp
@@ -0,0 +1,135 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "cdbpromptthread.h"
+
+#include <cstdio>
+#include <QtCore/QDebug>
+
+static const char help[] =
+"Special commands:\n\n"
+"H                        Display Help\n"
+"q                        Quit\n"
+"E expression             Evaluate C++expression\n"
+"S binary args            Start binary\n"
+"I                        Interrupt\n"
+"G                        Go\n"
+"\nThe remaining commands are passed to CDB.\n";
+
+CdbPromptThread::CdbPromptThread(QObject *parent) :
+        QThread(parent)
+{
+}
+
+void CdbPromptThread::run()
+{
+    enum { bufSize =1024 };
+
+    QString cmd;
+    char buf[bufSize];
+    std::putc('>', stdout);
+    while (true) {
+        if (std::fgets(buf, bufSize, stdin) == NULL)
+            break;
+        cmd += QString::fromLatin1(buf);
+        if (cmd.endsWith(QLatin1Char('\n'))) {
+            cmd.truncate(cmd.size() - 1);            
+            if (!cmd.isEmpty() && !handleCommand(cmd.trimmed()))
+                break;
+            cmd.clear();
+        }
+        std::putc('>', stdout);
+    }
+}
+
+// Determine the command
+static Command evaluateCommand(const QString &cmdToken)
+{
+    if (cmdToken.size() == 1) {
+        switch(cmdToken.at(0).toAscii()) {
+        case 'I':
+            return Async_Interrupt;
+        case 'E':
+            return Sync_EvalExpression;
+        case 'G':
+            return Execution_Go;
+        case 'S':
+            return Execution_StartBinary;
+        default:
+            break;
+        }
+        return UnknownCommand;
+    }
+    return UnknownCommand;
+}
+
+// Chop off command and return argument list
+static Command parseCommand(QString *s)
+{
+    if (s->isEmpty())
+        return UnknownCommand;
+    int firstBlank = s->indexOf(QLatin1Char(' '));
+    // No further arguments
+    if (firstBlank == -1) {
+        const Command rc1 = evaluateCommand(*s);
+        if (rc1 != UnknownCommand) // pass through debugger cmds
+            s->clear();
+        return rc1;
+    }
+    // Chop
+    const Command rc = evaluateCommand(s->left(firstBlank));
+    if (rc != UnknownCommand) { // pass through debugger cmds)
+        int nextToken = firstBlank + 1;
+        for ( ;  nextToken < s->size() && s->at(nextToken).isSpace(); nextToken++) ;
+        s->remove(0, nextToken);
+    }
+    return rc;
+}
+
+bool CdbPromptThread::handleCommand(QString cmd)
+{
+    if (cmd == QLatin1String("q"))
+        return false;
+    if (cmd == QLatin1String("H")) {
+        std::fputs(help, stdout);
+        return true;
+    }
+    const Command c = parseCommand(&cmd);
+    if (c & AsyncCommand) {
+        emit asyncCommand(c, cmd);
+        return true;
+    }
+    if (c & ExecutionCommand) {
+        emit executionCommand(c, cmd);
+        return true;
+    }
+    // Let Unknown default to sync exeute
+    emit syncCommand(c, cmd);
+    return true;
+}
diff --git a/tests/manual/ccdb/cdbpromptthread.h b/tests/manual/ccdb/cdbpromptthread.h
new file mode 100644
index 0000000000000000000000000000000000000000..09df8452a597f334bfaed1b20bb7995858ce7854
--- /dev/null
+++ b/tests/manual/ccdb/cdbpromptthread.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef PROMPTTHREAD_H
+#define PROMPTTHREAD_H
+
+#include <QtCore/QThread>
+
+enum CommandTypeFlags {
+    // Interrupt or something.
+    AsyncCommand      = 0x0010000,
+    // Synchronous execution before next prompt,
+    // eg eval expression. Connect with blocking slot.
+    SyncCommand       = 0x0020000,
+    // Starts debuggee. Requires starting the debug event
+    // watch timer afterwards.
+    ExecutionCommand  = 0x0040000
+};
+
+enum Command {
+    UnknownCommand        = 0,
+    Async_Interrupt       = AsyncCommand|1,
+    Sync_EvalExpression   = SyncCommand|1,
+    Execution_Go          = ExecutionCommand|1,
+    Execution_StartBinary = ExecutionCommand|2
+};
+
+class CdbPromptThread : public QThread
+{
+    Q_OBJECT
+public:
+    explicit CdbPromptThread(QObject *parent = 0);
+
+    virtual void run();
+
+signals:
+    void asyncCommand(int command, const QString &arg);
+    void syncCommand(int command, const QString &arg);
+    void executionCommand(int command, const QString &arg);
+
+private:
+    bool handleCommand(QString);
+};
+
+#endif // PROMPTTHREAD_H
diff --git a/tests/manual/ccdb/debugeventcallback.cpp b/tests/manual/ccdb/debugeventcallback.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1caaf2f8069cf5b3b67ba8926b128633cd4ec0cb
--- /dev/null
+++ b/tests/manual/ccdb/debugeventcallback.cpp
@@ -0,0 +1,156 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "debugeventcallback.h"
+
+#include <cstdio>
+
+DebugEventCallback::DebugEventCallback()
+{
+}
+
+STDMETHODIMP DebugEventCallback::GetInterestMask(THIS_ __out PULONG mask)
+{
+    *mask = DEBUG_EVENT_CREATE_PROCESS  | DEBUG_EVENT_EXIT_PROCESS
+             | DEBUG_EVENT_LOAD_MODULE   | DEBUG_EVENT_UNLOAD_MODULE
+             | DEBUG_EVENT_CREATE_THREAD | DEBUG_EVENT_EXIT_THREAD
+             | DEBUG_EVENT_BREAKPOINT
+             | DEBUG_EVENT_EXCEPTION;
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT2)
+{
+    printf("Breakpoint hit\n");
+    return S_OK;
+}
+STDMETHODIMP DebugEventCallback::Exception(
+    THIS_
+    __in PEXCEPTION_RECORD64 exc,
+    __in ULONG firstChance
+    )
+{
+    printf("Exception %ul occurred first-chance: %ul\n", exc->ExceptionCode,  firstChance);
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallback::CreateThread(
+    THIS_
+    __in ULONG64 /* Handle */,
+    __in ULONG64 /* DataOffset */,
+    __in ULONG64 /* StartOffset */
+    )
+{
+    printf("Thread created\n");
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallback::ExitThread(
+    THIS_
+    __in ULONG /* ExitCode */
+    )
+{
+    printf("Thread quit\n");
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallback::CreateProcess(
+    THIS_
+    __in ULONG64 /* ImageFileHandle */,
+    __in ULONG64 Handle,
+    __in ULONG64 /* Offset */,
+    __in ULONG /* ModuleSize */,
+    __in_opt PCWSTR /* ModuleName */,
+    __in_opt PCWSTR /* ImageName */,
+    __in ULONG /* CheckSum */,
+    __in ULONG /* TimeDateStamp */,
+    __in ULONG64 /* InitialThreadHandle */,
+    __in ULONG64 /* ThreadDataOffset */,
+    __in ULONG64 /* StartOffset */
+    )
+{
+    printf("Process created %Ld\n", Handle);
+    emit processAttached(reinterpret_cast<void*>(Handle));
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallback::ExitProcess(
+    THIS_
+    __in ULONG /* ExitCode */
+    )
+{
+    printf("Process quit\n");
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallback::LoadModule(
+    THIS_
+    __in ULONG64 /* ImageFileHandle */,
+    __in ULONG64 /* Offset */,
+    __in ULONG /* ModuleSize */,
+    __in_opt PCWSTR /* ModuleName */,
+    __in_opt PCWSTR /* ImageName */,
+    __in ULONG /* CheckSum */,
+    __in ULONG /* TimeDateStamp */
+    )
+{
+    printf("Module loaded\n");
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallback::UnloadModule(
+    THIS_
+    __in_opt PCWSTR /* ImageName */,
+    __in ULONG64 /* Offset */
+    )
+{
+    printf("Module unloaded\n");
+    return S_OK;
+}
+
+STDMETHODIMP DebugEventCallback::SystemError(
+    THIS_
+    __in ULONG Error,
+    __in ULONG Level
+    )
+{
+    printf("System error %ul at %ul\n", Error, Level);
+    return S_OK;
+}
+
+
+STDMETHODIMP DebugEventCallback::ChangeDebuggeeState(
+    THIS_
+    __in ULONG Flags,
+    __in ULONG64 Argument
+    )
+{
+    printf("Debuggee state changed %ul %ul\n", Flags, Argument);
+    return S_OK;
+}
diff --git a/tests/manual/ccdb/debugeventcallback.h b/tests/manual/ccdb/debugeventcallback.h
new file mode 100644
index 0000000000000000000000000000000000000000..357224eadcc0cfea7b729035e98a198abd7a5266
--- /dev/null
+++ b/tests/manual/ccdb/debugeventcallback.h
@@ -0,0 +1,125 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DEBUGEVENTCALLBACK_H
+#define DEBUGEVENTCALLBACK_H
+
+#include "debugeventcallbackbase.h"
+#include <QtCore/QObject>
+
+class DebugEventCallback :
+        public QObject,
+        public CdbCore::DebugEventCallbackBase
+
+{
+    Q_OBJECT
+public:
+    DebugEventCallback();
+
+    STDMETHOD(GetInterestMask)(
+          THIS_
+          __out PULONG mask
+          );
+
+    STDMETHOD(Breakpoint)(
+            THIS_
+            __in PDEBUG_BREAKPOINT2 Bp
+            );
+
+    STDMETHOD(Exception)(
+            THIS_
+            __in PEXCEPTION_RECORD64 Exception,
+            __in ULONG FirstChance
+            );
+
+    STDMETHOD(CreateThread)(
+            THIS_
+            __in ULONG64 Handle,
+            __in ULONG64 DataOffset,
+            __in ULONG64 StartOffset
+            );
+    STDMETHOD(ExitThread)(
+            THIS_
+            __in ULONG ExitCode
+            );
+
+    STDMETHOD(CreateProcess)(
+            THIS_
+            __in ULONG64 ImageFileHandle,
+            __in ULONG64 Handle,
+            __in ULONG64 BaseOffset,
+            __in ULONG ModuleSize,
+            __in_opt PCWSTR ModuleName,
+            __in_opt PCWSTR ImageName,
+            __in ULONG CheckSum,
+            __in ULONG TimeDateStamp,
+            __in ULONG64 InitialThreadHandle,
+            __in ULONG64 ThreadDataOffset,
+            __in ULONG64 StartOffset
+            );
+
+    STDMETHOD(ExitProcess)(
+            THIS_
+            __in ULONG ExitCode
+            );
+
+    STDMETHOD(LoadModule)(
+            THIS_
+            __in ULONG64 ImageFileHandle,
+            __in ULONG64 BaseOffset,
+            __in ULONG ModuleSize,
+            __in_opt PCWSTR ModuleName,
+            __in_opt PCWSTR ImageName,
+            __in ULONG CheckSum,
+            __in ULONG TimeDateStamp
+            );
+
+    STDMETHOD(UnloadModule)(
+            THIS_
+            __in_opt PCWSTR ImageBaseName,
+            __in ULONG64 BaseOffset
+            );
+
+    STDMETHOD(SystemError)(
+            THIS_
+            __in ULONG Error,
+            __in ULONG Level
+            );
+
+    STDMETHOD(ChangeDebuggeeState)(
+            THIS_
+            __in ULONG Flags,
+            __in ULONG64 Argument
+            );
+
+signals:
+    void processAttached(void *h);
+};
+
+#endif // DEBUGEVENTCALLBACK_H
diff --git a/tests/manual/ccdb/main.cpp b/tests/manual/ccdb/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9ccb6d93ca1ee2313c690971eea13b3f43c43d0
--- /dev/null
+++ b/tests/manual/ccdb/main.cpp
@@ -0,0 +1,49 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "cdbapplication.h"
+#include <QtCore/QString>
+
+int main(int argc, char *argv[])
+{
+    CdbApplication app(argc, argv);
+    int rc = 0;
+
+    switch (app.init()) {
+    case CdbApplication::InitOk:
+        rc = app.exec();
+        break;
+    case CdbApplication::InitFailed:
+        rc = 1;
+        break;
+    case CdbApplication::InitUsageShown:
+        break;
+    }
+    return rc;
+}