>From 938e284216e40fe648ee9815e440f21b523fa809 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Tue, 27 Sep 2011 09:06:18 +1000
Subject: [PATCH] Add ICorDebug interface support
To: wine-patches <wine-patches@winehq.org>

---
 dlls/mscoree/Makefile.in       |    1 +
 dlls/mscoree/cordebug.c        |  212 ++++++++++++++++++++++++++++++++++++++++
 dlls/mscoree/mscoree_main.c    |   29 +++++-
 dlls/mscoree/mscoree_private.h |    2 +
 dlls/mscoree/tests/Makefile.in |    1 +
 include/cordebug.idl           |    1 +
 6 files changed, 243 insertions(+), 3 deletions(-)
 create mode 100644 dlls/mscoree/cordebug.c

diff --git a/dlls/mscoree/Makefile.in b/dlls/mscoree/Makefile.in
index 914aff4..a39c696 100644
--- a/dlls/mscoree/Makefile.in
+++ b/dlls/mscoree/Makefile.in
@@ -4,6 +4,7 @@ IMPORTS   = dbghelp uuid shell32 advapi32 ole32 oleaut32 shlwapi
 C_SRCS = \
 	assembly.c \
 	config.c \
+	cordebug.c \
 	corruntimehost.c \
 	metadata.c \
 	metahost.c \
diff --git a/dlls/mscoree/cordebug.c b/dlls/mscoree/cordebug.c
new file mode 100644
index 0000000..8d97de8
--- /dev/null
+++ b/dlls/mscoree/cordebug.c
@@ -0,0 +1,212 @@
+/*
+ *
+ * Copyright 2011 Alistair Leslie-Hughes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+
+#include "winuser.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "ole2.h"
+#include "shellapi.h"
+
+#include "cor.h"
+#include "mscoree.h"
+#include "metahost.h"
+#include "corhdr.h"
+
+#include "wine/list.h"
+#include "mscoree_private.h"
+#include "wine/debug.h"
+
+#include "initguid.h"
+/* We need to undefine the MACRO CreateProcess since the ICorDebug interface
+    has a function with this name. (Stops a compile issue).
+ */
+#undef CreateProcess
+#include "cordebug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
+
+
+typedef struct _CorDebug
+{
+    ICorDebug ICorDebug_iface;
+
+    LONG ref;
+} CorDebug;
+
+static inline CorDebug *impl_from_ICorDebug( ICorDebug *iface )
+{
+    return CONTAINING_RECORD(iface, CorDebug, ICorDebug_iface);
+}
+
+/*** IUnknown methods ***/
+static HRESULT WINAPI CorDebug_QueryInterface(ICorDebug *iface, REFIID riid, void **ppvObject)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+
+    TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
+
+    if ( IsEqualGUID( riid, &IID_ICorDebug ) ||
+         IsEqualGUID( riid, &IID_IUnknown ) )
+    {
+        *ppvObject = iface;
+    }
+    else
+    {
+        FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+        return E_NOINTERFACE;
+    }
+
+    ICorDebug_AddRef( iface );
+
+    return S_OK;
+}
+
+static ULONG WINAPI CorDebug_AddRef(ICorDebug *iface)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    ULONG ref = InterlockedIncrement( &This->ref );
+    TRACE("(%p)->(%d)\n", This, ref);
+    return ref;
+}
+
+static ULONG WINAPI CorDebug_Release(ICorDebug *iface)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    ULONG ref = InterlockedDecrement( &This->ref );
+
+    TRACE("(%p)->(%d)\n", This, ref);
+    if ( ref == 0 )
+    {
+        HeapFree( GetProcessHeap(), 0, This );
+    }
+
+    return ref;
+}
+
+/*** ICorDebug methods ***/
+static HRESULT WINAPI CorDebug_Initialize(ICorDebug *iface)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    FIXME("stub %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_Terminate(ICorDebug *iface)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    FIXME("stub %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_SetManagedHandler(ICorDebug *iface, ICorDebugManagedCallback *pCallback)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    FIXME("stub %p %p\n", This, pCallback);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_SetUnmanagedHandler(ICorDebug *iface, ICorDebugUnmanagedCallback *pCallback)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    FIXME("stub %p %p\n", This, pCallback);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_CreateProcess(ICorDebug *iface, LPCWSTR lpApplicationName,
+            LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
+            LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
+            DWORD dwCreationFlags, PVOID lpEnvironment,LPCWSTR lpCurrentDirectory, 
+            LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation,
+            CorDebugCreateProcessFlags debuggingFlags, ICorDebugProcess **ppProcess)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    FIXME("stub %p %s %s %p %p %d %d %p %s %p %p %d %p\n", This, debugstr_w(lpApplicationName),
+            debugstr_w(lpCommandLine), lpProcessAttributes, lpThreadAttributes,
+            bInheritHandles, dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory), 
+            lpStartupInfo, lpProcessInformation, debuggingFlags, ppProcess);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_DebugActiveProcess(ICorDebug *iface, DWORD id, BOOL win32Attach,
+            ICorDebugProcess **ppProcess)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    FIXME("stub %p %d %d %p\n", This, id, win32Attach, ppProcess);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_EnumerateProcesses( ICorDebug *iface, ICorDebugProcessEnum **ppProcess)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    FIXME("stub %p %p\n", This, ppProcess);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_GetProcess(ICorDebug *iface, DWORD dwProcessId, ICorDebugProcess **ppProcess)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    FIXME("stub %p %d %p\n", This, dwProcessId, ppProcess);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_CanLaunchOrAttach(ICorDebug *iface, DWORD dwProcessId, 
+            BOOL win32DebuggingEnabled)
+{
+    CorDebug *This = impl_from_ICorDebug( iface );
+    FIXME("stub %p %d %d\n", This, dwProcessId, win32DebuggingEnabled);
+    return E_NOTIMPL;
+}
+
+static const struct ICorDebugVtbl cordebug_vtbl =
+{
+    CorDebug_QueryInterface,
+    CorDebug_AddRef,
+    CorDebug_Release,
+    CorDebug_Initialize,
+    CorDebug_Terminate,
+    CorDebug_SetManagedHandler,
+    CorDebug_SetUnmanagedHandler,
+    CorDebug_CreateProcess,
+    CorDebug_DebugActiveProcess,
+    CorDebug_EnumerateProcesses,
+    CorDebug_GetProcess,
+    CorDebug_CanLaunchOrAttach
+};
+
+
+IUnknown* create_CorDebug(void)
+{
+    CorDebug *This;
+
+    This = HeapAlloc( GetProcessHeap(), 0, sizeof(CorDebug) );
+    if ( !This )
+        return NULL;
+
+    This->ICorDebug_iface.lpVtbl = &cordebug_vtbl;
+    This->ref = 1;
+
+    return (IUnknown*)&This->ICorDebug_iface;
+}
diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c
index 9e37eae..dd4bd23 100644
--- a/dlls/mscoree/mscoree_main.c
+++ b/dlls/mscoree/mscoree_main.c
@@ -444,10 +444,33 @@ HRESULT WINAPI CreateConfigStream(LPCWSTR filename, IStream **stream)
     return E_NOTIMPL;
 }
 
-HRESULT WINAPI CreateDebuggingInterfaceFromVersion(int nDebugVersion, LPCWSTR version, IUnknown **ppIUnk)
+HRESULT WINAPI CreateDebuggingInterfaceFromVersion(int nDebugVersion, LPCWSTR version, IUnknown **ppv)
 {
-    FIXME("(%d %s, %p): stub\n", nDebugVersion, debugstr_w(version), ppIUnk);
-    return E_NOTIMPL;
+    const WCHAR v2_0[] = {'v','2','.','0','.','5','0','7','2','7',0};
+
+    if(nDebugVersion < 1 || nDebugVersion > 4)
+        return E_INVALIDARG;
+
+    TRACE("(%d %s, %p): stub\n", nDebugVersion, debugstr_w(version), ppv);
+
+    if(!ppv)
+        return E_INVALIDARG;
+
+    if(strcmpW(version, v2_0) != 0)
+    {
+        FIXME("Currently .NET Version '%s' not support.\n", debugstr_w(version));
+        return E_INVALIDARG;
+    }
+    
+    if(nDebugVersion != 3)
+        return E_INVALIDARG;
+
+    *ppv = create_CorDebug();
+
+    if(!*ppv)
+        return E_FAIL;
+
+    return S_OK;
 }
 
 HRESULT WINAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, LPVOID *ppInterface)
diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
index 5cbf8df..d6333fc 100644
--- a/dlls/mscoree/mscoree_private.h
+++ b/dlls/mscoree/mscoree_private.h
@@ -145,4 +145,6 @@ extern HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name
 
 extern HRESULT RuntimeHost_Destroy(RuntimeHost *This) DECLSPEC_HIDDEN;
 
+extern IUnknown* create_CorDebug(void) DECLSPEC_HIDDEN;
+
 #endif   /* __MSCOREE_PRIVATE__ */
diff --git a/dlls/mscoree/tests/Makefile.in b/dlls/mscoree/tests/Makefile.in
index e336f0d..20dfd88 100644
--- a/dlls/mscoree/tests/Makefile.in
+++ b/dlls/mscoree/tests/Makefile.in
@@ -2,6 +2,7 @@ TESTDLL   = mscoree.dll
 IMPORTS   = shlwapi
 
 C_SRCS = \
+	debugging.c \
 	metahost.c \
 	mscoree.c
 
diff --git a/include/cordebug.idl b/include/cordebug.idl
index 9cde077..85c1f60 100644
--- a/include/cordebug.idl
+++ b/include/cordebug.idl
@@ -51,6 +51,7 @@ interface ICorDebugStepper;
 interface ICorDebugStepperEnum;
 interface ICorDebugThreadEnum;
 interface ICorDebugUnmanagedCallback;
+interface ICorDebugValue;
 interface ICorDebugValueBreakpoint;
 
 
-- 
1.7.4.1

