[PATCH 2/5] explorer: Implement IShellWindows::Register() and IShellWindows::Revoke().

Zebediah Figura z.figura12 at gmail.com
Sun May 17 23:29:41 CDT 2020


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/shell32/tests/shelldispatch.c | 15 +----
 programs/explorer/desktop.c        | 93 ++++++++++++++++++++++++++++--
 2 files changed, 90 insertions(+), 18 deletions(-)

diff --git a/dlls/shell32/tests/shelldispatch.c b/dlls/shell32/tests/shelldispatch.c
index c1e3fbcdaf1..eea505ff61d 100644
--- a/dlls/shell32/tests/shelldispatch.c
+++ b/dlls/shell32/tests/shelldispatch.c
@@ -1035,15 +1035,12 @@ static void test_ShellWindows(void)
     ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "got 0x%08x\n", hr);
 
     hr = IShellWindows_Register(shellwindows, NULL, 0, SWC_EXPLORER, &cookie);
-todo_wine
     ok(hr == E_POINTER, "got 0x%08x\n", hr);
 
     hr = IShellWindows_Register(shellwindows, (IDispatch*)shellwindows, 0, SWC_EXPLORER, &cookie);
-todo_wine
     ok(hr == E_POINTER, "got 0x%08x\n", hr);
 
     hr = IShellWindows_Register(shellwindows, (IDispatch*)shellwindows, 0, SWC_EXPLORER, &cookie);
-todo_wine
     ok(hr == E_POINTER, "got 0x%08x\n", hr);
 
     hwnd = CreateWindowExA(0, "button", "test", BS_CHECKBOX | WS_VISIBLE | WS_POPUP,
@@ -1052,16 +1049,13 @@ todo_wine
 
     cookie = 0;
     hr = IShellWindows_Register(shellwindows, NULL, HandleToLong(hwnd), SWC_EXPLORER, &cookie);
-todo_wine {
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ok(cookie != 0, "got %d\n", cookie);
-}
+
     cookie2 = 0;
     hr = IShellWindows_Register(shellwindows, NULL, HandleToLong(hwnd), SWC_EXPLORER, &cookie2);
-todo_wine {
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ok(cookie2 != 0 && cookie2 != cookie, "got %d\n", cookie2);
-}
 
     pidl = ILCreateFromPathA("C:\\");
     V_VT(&v) = VT_ARRAY | VT_UI1;
@@ -1083,7 +1077,6 @@ todo_wine {
     ok(!disp, "Got IDispatch %p.\n", &disp);
 
     hr = IShellWindows_Revoke(shellwindows, cookie);
-todo_wine
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
     hr = IShellWindows_FindWindowSW(shellwindows, &v, &v2, SWC_EXPLORER, &ret, 0, &disp);
@@ -1092,20 +1085,17 @@ todo_wine
     ok(!disp, "Got IDispatch %p.\n", &disp);
 
     hr = IShellWindows_Revoke(shellwindows, cookie2);
-todo_wine
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
     hr = IShellWindows_Revoke(shellwindows, 0);
-todo_wine
     ok(hr == S_FALSE, "got 0x%08x\n", hr);
 
     /* we can register ourselves as desktop, but FindWindowSW still returns real desktop window */
     cookie = 0;
     hr = IShellWindows_Register(shellwindows, NULL, HandleToLong(hwnd), SWC_DESKTOP, &cookie);
-todo_wine {
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ok(cookie != 0, "got %d\n", cookie);
-}
+
     disp = (void*)0xdeadbeef;
     ret = 0xdead;
     VariantInit(&v);
@@ -1235,7 +1225,6 @@ todo_wine
     ok(ret == 0, "got %d\n", ret);
 
     hr = IShellWindows_Revoke(shellwindows, cookie);
-todo_wine
     ok(hr == S_OK, "got 0x%08x\n", hr);
     DestroyWindow(hwnd);
     IShellWindows_Release(shellwindows);
diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
index 8f515c045f3..137544567e4 100644
--- a/programs/explorer/desktop.c
+++ b/programs/explorer/desktop.c
@@ -118,9 +118,48 @@ static HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
     return S_OK;
 }
 
+static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size)
+{
+    unsigned int new_capacity, max_capacity;
+    void *new_elements;
+
+    if (count <= *capacity)
+        return TRUE;
+
+    max_capacity = ~(SIZE_T)0 / size;
+    if (count > max_capacity)
+        return FALSE;
+
+    new_capacity = max(4, *capacity);
+    while (new_capacity < count && new_capacity <= max_capacity / 2)
+        new_capacity *= 2;
+    if (new_capacity < count)
+        new_capacity = max_capacity;
+
+    if (!(new_elements = realloc(*elements, new_capacity * size)))
+        return FALSE;
+
+    *elements = new_elements;
+    *capacity = new_capacity;
+
+    return TRUE;
+}
+
+static LONG cookie_counter;
+
+struct window
+{
+    LONG cookie, hwnd;
+    int class;
+};
+
 struct shellwindows
 {
     IShellWindows IShellWindows_iface;
+    CRITICAL_SECTION cs;
+
+    unsigned int count, max;
+    struct window *windows;
 };
 
 /* This is not limited to desktop itself, every file browser window that
@@ -1139,10 +1178,34 @@ static HRESULT WINAPI shellwindows__NewEnum(IShellWindows *iface, IUnknown **ppu
 }
 
 static HRESULT WINAPI shellwindows_Register(IShellWindows *iface,
-        IDispatch *disp, LONG hWnd, int class, LONG *cookie)
+        IDispatch *disp, LONG hwnd, int class, LONG *cookie)
 {
-    FIXME("%p 0x%x 0x%x %p\n", disp, hWnd, class, cookie);
-    return E_NOTIMPL;
+    struct shellwindows *sw = impl_from_IShellWindows(iface);
+    struct window *window;
+
+    TRACE("iface %p, disp %p, hwnd %#x, class %u, cookie %p.\n", iface, disp, hwnd, class, cookie);
+
+    if (!hwnd)
+        return E_POINTER;
+
+    if (disp)
+        FIXME("Ignoring IDispatch %p.\n", disp);
+
+    EnterCriticalSection(&sw->cs);
+
+    if (!array_reserve((void **)&sw->windows, &sw->max, sw->count + 1, sizeof(*sw->windows)))
+    {
+        LeaveCriticalSection(&sw->cs);
+        return E_OUTOFMEMORY;
+    }
+
+    window = &sw->windows[sw->count++];
+    window->hwnd = hwnd;
+    window->class = class;
+    *cookie = window->cookie = ++cookie_counter;
+
+    LeaveCriticalSection(&sw->cs);
+    return S_OK;
 }
 
 static HRESULT WINAPI shellwindows_RegisterPending(IShellWindows *iface,
@@ -1155,8 +1218,26 @@ static HRESULT WINAPI shellwindows_RegisterPending(IShellWindows *iface,
 
 static HRESULT WINAPI shellwindows_Revoke(IShellWindows *iface, LONG cookie)
 {
-    FIXME("0x%x\n", cookie);
-    return E_NOTIMPL;
+    struct shellwindows *sw = impl_from_IShellWindows(iface);
+    unsigned int i;
+
+    TRACE("iface %p, cookie %u.\n", iface, cookie);
+
+    EnterCriticalSection(&sw->cs);
+
+    for (i = 0; i < sw->count; ++i)
+    {
+        if (sw->windows[i].cookie == cookie)
+        {
+            --sw->count;
+            memmove(&sw->windows[i], &sw->windows[i + 1], (sw->count - i) * sizeof(*sw->windows));
+            LeaveCriticalSection(&sw->cs);
+            return S_OK;
+        }
+    }
+
+    LeaveCriticalSection(&sw->cs);
+    return S_FALSE;
 }
 
 static HRESULT WINAPI shellwindows_OnNavigate(IShellWindows *iface, LONG cookie, VARIANT *loc)
@@ -2156,6 +2237,8 @@ static void shellwindows_init(void)
     CoInitialize(NULL);
 
     shellwindows.IShellWindows_iface.lpVtbl = &shellwindowsvtbl;
+    InitializeCriticalSection(&shellwindows.cs);
+    shellwindows.cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": shellwindows.cs");
 
     hr = CoRegisterClassObject(&CLSID_ShellWindows,
         (IUnknown*)&shellwindows_classfactory.IClassFactory_iface,
-- 
2.26.2




More information about the wine-devel mailing list