>From f70fef413fcbb51254f6ace09a4239ab9fa6334f Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Mon, 31 Oct 2011 09:15:39 +1100
Subject: [PATCH] Implement ICorDebug EnumerateProcesses
To: wine-patches <wine-patches@winehq.org>

---
 dlls/mscoree/cordebug.c        |  122 +++++++++++++++++++++++++++++++++++++++-
 dlls/mscoree/mscoree_private.h |   10 +++
 dlls/mscoree/tests/debugging.c |   26 +++++++++
 3 files changed, 156 insertions(+), 2 deletions(-)

diff --git a/dlls/mscoree/cordebug.c b/dlls/mscoree/cordebug.c
index c5342bc..04c6e58 100644
--- a/dlls/mscoree/cordebug.c
+++ b/dlls/mscoree/cordebug.c
@@ -45,6 +45,104 @@ static inline CorDebug *impl_from_ICorDebug( ICorDebug *iface )
     return CONTAINING_RECORD(iface, CorDebug, ICorDebug_iface);
 }
 
+static inline CorDebug *impl_from_ICorDebugProcessEnum( ICorDebugProcessEnum *iface )
+{
+    return CONTAINING_RECORD(iface, CorDebug, ICorDebugProcessEnum_iface);
+}
+
+static HRESULT WINAPI process_enum_QueryInterface(ICorDebugProcessEnum *iface, REFIID riid, void **ppvObject)
+{
+    CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+
+    TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
+
+    if ( IsEqualGUID( riid, &IID_ICorDebugProcessEnum ) ||
+         IsEqualGUID( riid, &IID_ICorDebugEnum ) ||
+         IsEqualGUID( riid, &IID_IUnknown ) )
+    {
+        *ppvObject = &This->ICorDebugProcessEnum_iface;
+    }
+    else
+    {
+        FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+        return E_NOINTERFACE;
+    }
+
+    ICorDebug_AddRef(iface);
+
+    return S_OK;
+}
+
+static ULONG WINAPI process_enum_AddRef(ICorDebugProcessEnum *iface)
+{
+    CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+    TRACE("%p ref=%u\n", This, This->ref);
+
+    return ICorDebug_AddRef(&This->ICorDebug_iface);
+}
+
+static ULONG WINAPI process_enum_Release(ICorDebugProcessEnum *iface)
+{
+    CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+    TRACE("%p ref=%u\n", This, This->ref);
+
+    return ICorDebug_Release(&This->ICorDebug_iface);
+}
+
+static HRESULT WINAPI process_enum_Skip(ICorDebugProcessEnum *iface, ULONG celt)
+{
+    CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+    FIXME("stub %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI process_enum_Reset(ICorDebugProcessEnum *iface)
+{
+    CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+    FIXME("stub %p\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI process_enum_Clone(ICorDebugProcessEnum *iface, ICorDebugEnum **ppEnum)
+{
+    CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+    FIXME("stub %p %p\n", This, ppEnum);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI process_enum_GetCount(ICorDebugProcessEnum *iface, ULONG *pcelt)
+{
+    CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+    TRACE("stub %p %p\n", This, pcelt);
+
+    if(!pcelt)
+        return E_INVALIDARG;
+
+    *pcelt = list_count(&This->processes);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI process_enum_Next(ICorDebugProcessEnum *iface, ULONG celt,
+            ICorDebugProcess * processes[], ULONG *pceltFetched)
+{
+    CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+    FIXME("stub %p %d %p %p\n", This, celt, processes, pceltFetched);
+    return E_NOTIMPL;
+}
+
+static const struct ICorDebugProcessEnumVtbl processenum_vtbl =
+{
+    process_enum_QueryInterface,
+    process_enum_AddRef,
+    process_enum_Release,
+    process_enum_Skip,
+    process_enum_Reset,
+    process_enum_Clone,
+    process_enum_GetCount,
+    process_enum_Next
+};
+
 /*** IUnknown methods ***/
 static HRESULT WINAPI CorDebug_QueryInterface(ICorDebug *iface, REFIID riid, void **ppvObject)
 {
@@ -82,11 +180,21 @@ static ULONG WINAPI CorDebug_Release(ICorDebug *iface)
 {
     CorDebug *This = impl_from_ICorDebug( iface );
     ULONG ref = InterlockedDecrement(&This->ref);
+    struct CorProcess *cursor, *cursor2;
 
     TRACE("%p ref=%u\n", This, ref);
 
     if (ref == 0)
     {
+        LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->processes, struct CorProcess, entry)
+        {
+            if(cursor->pProcess)
+                ICorDebugProcess_Release(cursor->pProcess);
+
+            list_remove(&cursor->entry);
+            HeapFree(GetProcessHeap(), 0, cursor);
+        }
+
         if(This->runtimehost)
             ICLRRuntimeHost_Release(This->runtimehost);
 
@@ -183,8 +291,15 @@ static HRESULT WINAPI CorDebug_DebugActiveProcess(ICorDebug *iface, DWORD id, BO
 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;
+    TRACE("stub %p %p\n", This, ppProcess);
+
+    if(!ppProcess)
+        return E_INVALIDARG;
+
+    *ppProcess = &This->ICorDebugProcessEnum_iface;
+    ICorDebugProcessEnum_AddRef(*ppProcess);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI CorDebug_GetProcess(ICorDebug *iface, DWORD dwProcessId, ICorDebugProcess **ppProcess)
@@ -227,11 +342,14 @@ HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk)
         return E_OUTOFMEMORY;
 
     This->ICorDebug_iface.lpVtbl = &cordebug_vtbl;
+    This->ICorDebugProcessEnum_iface.lpVtbl = &processenum_vtbl;
     This->ref = 1;
     This->pCallback = NULL;
     This->pCallback2 = NULL;
     This->runtimehost = runtimehost;
 
+    list_init(&This->processes);
+
     if(This->runtimehost)
         ICLRRuntimeHost_AddRef(This->runtimehost);
 
diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
index 3c9ef1e..71bf738 100644
--- a/dlls/mscoree/mscoree_private.h
+++ b/dlls/mscoree/mscoree_private.h
@@ -72,9 +72,16 @@ struct RuntimeHost
     LONG ref;
 };
 
+typedef struct CorProcess
+{
+    struct list entry;
+    ICorDebugProcess *pProcess;
+} CorProcess;
+
 typedef struct CorDebug
 {
     ICorDebug ICorDebug_iface;
+    ICorDebugProcessEnum ICorDebugProcessEnum_iface;
     LONG ref;
 
     ICLRRuntimeHost *runtimehost;
@@ -82,6 +89,9 @@ typedef struct CorDebug
     /* ICorDebug Callback */
     ICorDebugManagedCallback *pCallback;
     ICorDebugManagedCallback2 *pCallback2;
+
+    /* Debug Processes */
+    struct list processes;
 } CorDebug;
 
 extern HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
diff --git a/dlls/mscoree/tests/debugging.c b/dlls/mscoree/tests/debugging.c
index fb5abe3..29a74e3 100644
--- a/dlls/mscoree/tests/debugging.c
+++ b/dlls/mscoree/tests/debugging.c
@@ -418,6 +418,29 @@ static BOOL init_functionpointers(void)
     return TRUE;
 }
 
+#define check_process_enum(core, e) _check_process_enum(__LINE__, core, e)
+static void _check_process_enum(unsigned line, ICorDebug *pCorDebug, ULONG nExpected)
+{
+    HRESULT hr;
+    ICorDebugProcessEnum *pProcessEnum = NULL;
+
+    hr = ICorDebug_EnumerateProcesses(pCorDebug, NULL);
+    ok_(__FILE__,line) (hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr);
+
+    hr = ICorDebug_EnumerateProcesses(pCorDebug, &pProcessEnum);
+    ok_(__FILE__,line) (hr == S_OK, "expected S_OK got %08x\n", hr);
+    if(hr == S_OK)
+    {
+        ULONG cnt;
+
+        hr = ICorDebugProcessEnum_GetCount(pProcessEnum, &cnt);
+        ok_(__FILE__,line) (hr == S_OK, "expected S_OK got %08x\n", hr);
+        ok_(__FILE__,line) (cnt == nExpected, "expected %d got %d\n", nExpected, cnt);
+
+    ICorDebugProcessEnum_Release(pProcessEnum);
+    }
+}
+
 static void test_createDebugger(void)
 {
     HRESULT hr;
@@ -455,6 +478,9 @@ static void test_createDebugger(void)
 
                 hr = ICorDebug_SetManagedHandler(pCorDebug, &ManagedCallback);
                 ok(hr == S_OK, "expected S_OK got %08x\n", hr);
+
+                /* We should have no processes */
+                check_process_enum(pCorDebug, 0);
             }
 
             ICorDebug_Release(pCorDebug);
-- 
1.7.5.4

