[PATCH 6/6] comdlg32: Implement Advise/Unadvise for the Item Dialog.

David Hedberg david.hedberg at gmail.com
Tue Mar 29 14:13:23 CDT 2011


---
 dlls/comdlg32/itemdlg.c       |   54 ++++++++++-
 dlls/comdlg32/tests/itemdlg.c |  201 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 251 insertions(+), 4 deletions(-)

diff --git a/dlls/comdlg32/itemdlg.c b/dlls/comdlg32/itemdlg.c
index e9cb8b7..e155ce4 100644
--- a/dlls/comdlg32/itemdlg.c
+++ b/dlls/comdlg32/itemdlg.c
@@ -35,6 +35,7 @@
 #include "cdlg.h"
 
 #include "wine/debug.h"
+#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
 
@@ -43,6 +44,12 @@ enum ITEMDLG_TYPE {
     ITEMDLG_TYPE_SAVE
 };
 
+typedef struct {
+    struct list entry;
+    IFileDialogEvents *pfde;
+    DWORD cookie;
+} events_client;
+
 typedef struct FileDialogImpl {
     IFileDialog2 IFileDialog2_iface;
     union {
@@ -57,6 +64,9 @@ typedef struct FileDialogImpl {
     UINT filterspec_count;
     UINT filetypeindex;
 
+    struct list events_clients;
+    DWORD events_next_cookie;
+
     IShellItemArray *psia_selection;
     IShellItemArray *psia_results;
     IShellItem *psi_defaultfolder;
@@ -209,15 +219,48 @@ static HRESULT WINAPI IFileDialog2_fnGetFileTypeIndex(IFileDialog2 *iface, UINT
 static HRESULT WINAPI IFileDialog2_fnAdvise(IFileDialog2 *iface, IFileDialogEvents *pfde, DWORD *pdwCookie)
 {
     FileDialogImpl *This = impl_from_IFileDialog2(iface);
-    FIXME("stub - %p (%p, %p)\n", This, pfde, pdwCookie);
-    return E_NOTIMPL;
+    events_client *client;
+    TRACE("%p (%p, %p)\n", This, pfde, pdwCookie);
+
+    if(!pfde || !pdwCookie)
+        return E_INVALIDARG;
+
+    client = HeapAlloc(GetProcessHeap(), 0, sizeof(events_client));
+    client->pfde = pfde;
+    client->cookie = ++This->events_next_cookie;
+
+    IFileDialogEvents_AddRef(pfde);
+    *pdwCookie = client->cookie;
+
+    list_add_tail(&This->events_clients, &client->entry);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI IFileDialog2_fnUnadvise(IFileDialog2 *iface, DWORD dwCookie)
 {
     FileDialogImpl *This = impl_from_IFileDialog2(iface);
-    FIXME("stub - %p (%d)\n", This, dwCookie);
-    return E_NOTIMPL;
+    events_client *client, *found = NULL;
+    TRACE("%p (%d)\n", This, dwCookie);
+
+    LIST_FOR_EACH_ENTRY(client, &This->events_clients, events_client, entry)
+    {
+        if(client->cookie == dwCookie)
+        {
+            found = client;
+            break;
+        }
+    }
+
+    if(found)
+    {
+        list_remove(&found->entry);
+        IFileDialogEvents_Release(found->pfde);
+        HeapFree(GetProcessHeap(), 0, found);
+        return S_OK;
+    }
+
+    return E_INVALIDARG;
 }
 
 static HRESULT WINAPI IFileDialog2_fnSetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS fos)
@@ -997,6 +1040,9 @@ static HRESULT FileDialog_constructor(IUnknown *pUnkOuter, REFIID riid, void **p
     fdimpl->psia_selection = fdimpl->psia_results = NULL;
     fdimpl->psi_setfolder = fdimpl->psi_folder = NULL;
 
+    list_init(&fdimpl->events_clients);
+    fdimpl->events_next_cookie = 0;
+
     /* FIXME: The default folder setting should be restored for the
      * application if it was previously set. */
     SHGetDesktopFolder(&psf);
diff --git a/dlls/comdlg32/tests/itemdlg.c b/dlls/comdlg32/tests/itemdlg.c
index e5f5439..2e26186 100644
--- a/dlls/comdlg32/tests/itemdlg.c
+++ b/dlls/comdlg32/tests/itemdlg.c
@@ -20,6 +20,7 @@
  */
 
 #define COBJMACROS
+#define CONST_VTABLE
 
 #include "shlobj.h"
 #include "wine/test.h"
@@ -37,6 +38,117 @@ static void init_function_pointers(void)
 #undef MAKEFUNC
 }
 
+/**************************************************************************
+ * IFileDialogEvents implementation
+ */
+typedef struct {
+    IFileDialogEvents IFileDialogEvents_iface;
+    LONG ref;
+} IFileDialogEventsImpl;
+
+static inline IFileDialogEventsImpl *impl_from_IFileDialogEvents(IFileDialogEvents *iface)
+{
+    return CONTAINING_RECORD(iface, IFileDialogEventsImpl, IFileDialogEvents_iface);
+}
+
+static HRESULT WINAPI IFileDialogEvents_fnQueryInterface(IFileDialogEvents *iface, REFIID riid, void **ppv)
+{
+    /* Not called. */
+    ok(0, "Unexpectedly called.\n");
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI IFileDialogEvents_fnAddRef(IFileDialogEvents *iface)
+{
+    IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI IFileDialogEvents_fnRelease(IFileDialogEvents *iface)
+{
+    IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
+    LONG ref = InterlockedDecrement(&This->ref);
+
+    if(!ref)
+        HeapFree(GetProcessHeap(), 0, This);
+
+    return ref;
+}
+
+static HRESULT WINAPI IFileDialogEvents_fnOnFileOk(IFileDialogEvents *iface, IFileDialog *pfd)
+{
+    ok(0, "Unexpectedly called.\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI IFileDialogEvents_fnOnFolderChanging(IFileDialogEvents *iface,
+                                                           IFileDialog *pfd,
+                                                           IShellItem *psiFolder)
+{
+    ok(0, "Unexpectedly called.\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI IFileDialogEvents_fnOnFolderChange(IFileDialogEvents *iface, IFileDialog *pfd)
+{
+    ok(0, "Unexpectedly called.\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI IFileDialogEvents_fnOnSelectionChange(IFileDialogEvents *iface, IFileDialog *pfd)
+{
+    ok(0, "Unexpectedly called.\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI IFileDialogEvents_fnOnShareViolation(IFileDialogEvents *iface,
+                                                           IFileDialog *pfd,
+                                                           IShellItem *psi,
+                                                           FDE_SHAREVIOLATION_RESPONSE *pResponse)
+{
+    ok(0, "Unexpectedly called.\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI IFileDialogEvents_fnOnTypeChange(IFileDialogEvents *iface, IFileDialog *pfd)
+{
+    ok(0, "Unexpectedly called.\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI IFileDialogEvents_fnOnOverwrite(IFileDialogEvents *iface,
+                                                      IFileDialog *pfd,
+                                                      IShellItem *psi,
+                                                      FDE_OVERWRITE_RESPONSE *pResponse)
+{
+    ok(0, "Unexpectedly called.\n");
+    return S_OK;
+}
+
+static const IFileDialogEventsVtbl vt_IFileDialogEvents = {
+    IFileDialogEvents_fnQueryInterface,
+    IFileDialogEvents_fnAddRef,
+    IFileDialogEvents_fnRelease,
+    IFileDialogEvents_fnOnFileOk,
+    IFileDialogEvents_fnOnFolderChanging,
+    IFileDialogEvents_fnOnFolderChange,
+    IFileDialogEvents_fnOnSelectionChange,
+    IFileDialogEvents_fnOnShareViolation,
+    IFileDialogEvents_fnOnTypeChange,
+    IFileDialogEvents_fnOnOverwrite
+};
+
+static IFileDialogEvents *IFileDialogEvents_Constructor(void)
+{
+    IFileDialogEventsImpl *This;
+
+    This = HeapAlloc(GetProcessHeap(), 0, sizeof(IFileDialogEventsImpl));
+    This->IFileDialogEvents_iface.lpVtbl = &vt_IFileDialogEvents;
+    This->ref = 1;
+
+    return &This->IFileDialogEvents_iface;
+}
+
 static BOOL test_instantiation(void)
 {
     IFileDialog *pfd;
@@ -635,6 +747,94 @@ static void test_basics(void)
     IFileSaveDialog_Release(pfsd);
 }
 
+static void test_advise_helper(IFileDialog *pfd)
+{
+    IFileDialogEventsImpl *pfdeimpl;
+    IFileDialogEvents *pfde;
+    DWORD cookie[10];
+    UINT i;
+    HRESULT hr;
+
+    pfde = IFileDialogEvents_Constructor();
+    pfdeimpl = impl_from_IFileDialogEvents(pfde);
+
+    hr = IFileDialog_Advise(pfd, NULL, NULL);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    hr = IFileDialog_Advise(pfd, pfde, NULL);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    hr = IFileDialog_Advise(pfd, NULL, &cookie[0]);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(pfdeimpl->ref == 1, "got ref %d\n", pfdeimpl->ref);
+
+    hr = IFileDialog_Unadvise(pfd, 0);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    for(i = 0; i < 10; i++) {
+        hr = IFileDialog_Advise(pfd, pfde, &cookie[i]);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(cookie[i] == i+1, "Got cookie: %d\n", cookie[i]);
+    }
+    ok(pfdeimpl->ref == 10+1, "got ref %d\n", pfdeimpl->ref);
+
+    for(i = 3; i < 7; i++) {
+        hr = IFileDialog_Unadvise(pfd, cookie[i]);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+    }
+    ok(pfdeimpl->ref == 6+1, "got ref %d\n", pfdeimpl->ref);
+
+    for(i = 0; i < 3; i++) {
+        hr = IFileDialog_Unadvise(pfd, cookie[i]);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+    }
+    ok(pfdeimpl->ref == 3+1, "got ref %d\n", pfdeimpl->ref);
+
+    for(i = 7; i < 10; i++) {
+        hr = IFileDialog_Unadvise(pfd, cookie[i]);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+    }
+    ok(pfdeimpl->ref == 1, "got ref %d\n", pfdeimpl->ref);
+
+    hr = IFileDialog_Unadvise(pfd, cookie[9]+1);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(pfdeimpl->ref == 1, "got ref %d\n", pfdeimpl->ref);
+
+    hr = IFileDialog_Advise(pfd, pfde, &cookie[0]);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    todo_wine ok(cookie[0] == 1, "got cookie: %d\n", cookie[0]);
+    ok(pfdeimpl->ref == 1+1, "got ref %d\n", pfdeimpl->ref);
+
+    hr = IFileDialog_Unadvise(pfd, cookie[0]);
+
+    if(0)
+    {
+        /* Unadvising already unadvised cookies crashes on
+           Windows 7. */
+        IFileDialog_Unadvise(pfd, cookie[0]);
+    }
+
+
+    IFileDialogEvents_Release(pfde);
+}
+
+static void test_advise(void)
+{
+    IFileDialog *pfd;
+    HRESULT hr;
+
+    trace("Testing FileOpenDialog (advise)\n");
+    hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_IFileDialog, (void**)&pfd);
+    ok(hr == S_OK, "got 0x%08x.\n", hr);
+    test_advise_helper(pfd);
+    IFileDialog_Release(pfd);
+
+    trace("Testing FileSaveDialog (advise)\n");
+    hr = CoCreateInstance(&CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_IFileDialog, (void**)&pfd);
+    ok(hr == S_OK, "got 0x%08x.\n", hr);
+    test_advise_helper(pfd);
+    IFileDialog_Release(pfd);
+}
+
 START_TEST(itemdlg)
 {
     OleInitialize(NULL);
@@ -643,6 +843,7 @@ START_TEST(itemdlg)
     if(test_instantiation())
     {
         test_basics();
+        test_advise();
     }
     else
         skip("Skipping all Item Dialog tests.\n");
-- 
1.7.4.1




More information about the wine-patches mailing list