[PATCH 3/8] comdlg32: Support some events in the item dialog.

David Hedberg david.hedberg at gmail.com
Tue May 24 14:09:48 CDT 2011


TODO: Add some real tests (with a thread that does _Close if nothing happens?)
---
 dlls/comdlg32/itemdlg.c       |   94 ++++++++++++++++++++++++++++++++++++++++-
 dlls/comdlg32/tests/itemdlg.c |   49 ++++++++++++++++++----
 2 files changed, 134 insertions(+), 9 deletions(-)

diff --git a/dlls/comdlg32/itemdlg.c b/dlls/comdlg32/itemdlg.c
index 69d9661..dc447c2 100644
--- a/dlls/comdlg32/itemdlg.c
+++ b/dlls/comdlg32/itemdlg.c
@@ -93,6 +93,73 @@ typedef struct FileDialogImpl {
 } FileDialogImpl;
 
 /**************************************************************************
+ * Event wrappers.
+ */
+static HRESULT events_OnFileOk(FileDialogImpl *This)
+{
+    events_client *cursor;
+    HRESULT hr = S_OK;
+    TRACE("%p\n", This);
+
+    LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
+    {
+        TRACE("Notifying %p\n", cursor);
+        hr = IFileDialogEvents_OnFileOk(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
+        if(FAILED(hr) && hr != E_NOTIMPL)
+            break;
+    }
+
+    if(hr == E_NOTIMPL)
+        hr = S_OK;
+
+    return hr;
+}
+
+static HRESULT events_OnFolderChanging(FileDialogImpl *This, IShellItem *folder)
+{
+    events_client *cursor;
+    HRESULT hr = S_OK;
+    TRACE("%p (%p)\n", This, folder);
+
+    LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
+    {
+        TRACE("Notifying %p\n", cursor);
+        hr = IFileDialogEvents_OnFolderChanging(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface, folder);
+        if(FAILED(hr) && hr != E_NOTIMPL)
+            break;
+    }
+
+    if(hr == E_NOTIMPL)
+        hr = S_OK;
+
+    return hr;
+}
+
+static void events_OnFolderChange(FileDialogImpl *This)
+{
+    events_client *cursor;
+    TRACE("%p\n", This);
+
+    LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
+    {
+        TRACE("Notifying %p\n", cursor);
+        IFileDialogEvents_OnFolderChange(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
+    }
+}
+
+static void events_OnSelectionChange(FileDialogImpl *This)
+{
+    events_client *cursor;
+    TRACE("%p\n", This);
+
+    LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
+    {
+        TRACE("Notifying %p\n", cursor);
+        IFileDialogEvents_OnSelectionChange(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
+    }
+}
+
+/**************************************************************************
  * Helper functions.
  */
 static UINT get_file_name(FileDialogImpl *This, LPWSTR *str)
@@ -280,6 +347,9 @@ static HRESULT on_default_action(FileDialogImpl *This)
         break;
 
     case ONOPEN_OPEN:
+        if(events_OnFileOk(This) != S_OK)
+            break;
+
         hr = SHGetDesktopFolder(&psf_desktop);
         if(SUCCEEDED(hr))
         {
@@ -288,7 +358,6 @@ static HRESULT on_default_action(FileDialogImpl *This)
 
             hr = SHCreateShellItemArray(NULL, psf_desktop, file_count, (PCUITEMID_CHILD_ARRAY)pidla,
                                         &This->psia_results);
-
             if(SUCCEEDED(hr))
                 ret = S_OK;
 
@@ -1818,7 +1887,25 @@ static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrow
                                                                    PCIDLIST_ABSOLUTE pidlFolder)
 {
     FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
+    IShellItem *psi;
+    HRESULT hr;
     TRACE("%p (%p)\n", This, pidlFolder);
+
+    hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&psi);
+    if(SUCCEEDED(hr))
+    {
+        hr = events_OnFolderChanging(This, psi);
+        IShellItem_Release(psi);
+
+        /* The ExplorerBrowser treats S_FALSE as S_OK, we don't. */
+        if(hr == S_FALSE)
+            hr = E_FAIL;
+
+        return hr;
+    }
+    else
+        ERR("Failed to convert pidl (%p) to a shellitem.\n", pidlFolder);
+
     return S_OK;
 }
 
@@ -1847,6 +1934,8 @@ static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBro
         This->psi_folder = NULL;
     }
 
+    events_OnFolderChange(This);
+
     return S_OK;
 }
 
@@ -1993,7 +2082,10 @@ static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
             hr = SHCreateShellItemArrayFromDataObject(new_selection, &IID_IShellItemArray,
                                                       (void**)&This->psia_selection);
             if(SUCCEEDED(hr))
+            {
                 fill_filename_from_selection(This);
+                events_OnSelectionChange(This);
+            }
 
             IDataObject_Release(new_selection);
         }
diff --git a/dlls/comdlg32/tests/itemdlg.c b/dlls/comdlg32/tests/itemdlg.c
index 4dafa9b..fcd0e50 100644
--- a/dlls/comdlg32/tests/itemdlg.c
+++ b/dlls/comdlg32/tests/itemdlg.c
@@ -44,6 +44,10 @@ static void init_function_pointers(void)
 typedef struct {
     IFileDialogEvents IFileDialogEvents_iface;
     LONG ref;
+    LONG QueryInterface;
+    LONG OnFileOk, OnFolderChanging, OnFolderChange;
+    LONG OnSelectionChange, OnShareViolation, OnTypeChange;
+    LONG OnOverwrite;
 } IFileDialogEventsImpl;
 
 static inline IFileDialogEventsImpl *impl_from_IFileDialogEvents(IFileDialogEvents *iface)
@@ -77,7 +81,8 @@ static ULONG WINAPI IFileDialogEvents_fnRelease(IFileDialogEvents *iface)
 
 static HRESULT WINAPI IFileDialogEvents_fnOnFileOk(IFileDialogEvents *iface, IFileDialog *pfd)
 {
-    ok(0, "Unexpectedly called.\n");
+    IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
+    This->OnFileOk++;
     return S_OK;
 }
 
@@ -85,19 +90,22 @@ static HRESULT WINAPI IFileDialogEvents_fnOnFolderChanging(IFileDialogEvents *if
                                                            IFileDialog *pfd,
                                                            IShellItem *psiFolder)
 {
-    ok(0, "Unexpectedly called.\n");
+    IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
+    This->OnFolderChanging++;
     return S_OK;
 }
 
 static HRESULT WINAPI IFileDialogEvents_fnOnFolderChange(IFileDialogEvents *iface, IFileDialog *pfd)
 {
-    ok(0, "Unexpectedly called.\n");
+    IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
+    This->OnFolderChange++;
     return S_OK;
 }
 
 static HRESULT WINAPI IFileDialogEvents_fnOnSelectionChange(IFileDialogEvents *iface, IFileDialog *pfd)
 {
-    ok(0, "Unexpectedly called.\n");
+    IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
+    This->OnSelectionChange++;
     return S_OK;
 }
 
@@ -106,13 +114,15 @@ static HRESULT WINAPI IFileDialogEvents_fnOnShareViolation(IFileDialogEvents *if
                                                            IShellItem *psi,
                                                            FDE_SHAREVIOLATION_RESPONSE *pResponse)
 {
-    ok(0, "Unexpectedly called.\n");
+    IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
+    This->OnShareViolation++;
     return S_OK;
 }
 
 static HRESULT WINAPI IFileDialogEvents_fnOnTypeChange(IFileDialogEvents *iface, IFileDialog *pfd)
 {
-    ok(0, "Unexpectedly called.\n");
+    IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
+    This->OnTypeChange++;
     return S_OK;
 }
 
@@ -121,7 +131,8 @@ static HRESULT WINAPI IFileDialogEvents_fnOnOverwrite(IFileDialogEvents *iface,
                                                       IShellItem *psi,
                                                       FDE_OVERWRITE_RESPONSE *pResponse)
 {
-    ok(0, "Unexpectedly called.\n");
+    IFileDialogEventsImpl *This = impl_from_IFileDialogEvents(iface);
+    This->OnOverwrite++;
     return S_OK;
 }
 
@@ -142,7 +153,7 @@ static IFileDialogEvents *IFileDialogEvents_Constructor(void)
 {
     IFileDialogEventsImpl *This;
 
-    This = HeapAlloc(GetProcessHeap(), 0, sizeof(IFileDialogEventsImpl));
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IFileDialogEventsImpl));
     This->IFileDialogEvents_iface.lpVtbl = &vt_IFileDialogEvents;
     This->ref = 1;
 
@@ -745,6 +756,21 @@ static void test_basics(void)
     ok(!ref, "Got refcount %d, should have been released.\n", ref);
 }
 
+void ensure_zero_events_(const char *file, int line, IFileDialogEventsImpl *impl)
+{
+    ok_(file, line)(!impl->OnFileOk, "OnFileOk: %d\n", impl->OnFileOk);
+    ok_(file, line)(!impl->OnFolderChanging, "OnFolderChanging: %d\n", impl->OnFolderChanging);
+    ok_(file, line)(!impl->OnFolderChange, "OnFolderChange: %d\n", impl->OnFolderChange);
+    ok_(file, line)(!impl->OnSelectionChange, "OnSelectionChange: %d\n", impl->OnSelectionChange);
+    ok_(file, line)(!impl->OnShareViolation, "OnShareViolation: %d\n", impl->OnShareViolation);
+    ok_(file, line)(!impl->OnTypeChange, "OnTypeChange: %d\n", impl->OnTypeChange);
+    ok_(file, line)(!impl->OnOverwrite, "OnOverwrite: %d\n", impl->OnOverwrite);
+    impl->OnFileOk = impl->OnFolderChanging = impl->OnFolderChange = 0;
+    impl->OnSelectionChange = impl->OnShareViolation = impl->OnTypeChange = 0;
+    impl->OnOverwrite = 0;
+}
+#define ensure_zero_events(impl) ensure_zero_events_(__FILE__, __LINE__, impl)
+
 static void test_advise_helper(IFileDialog *pfd)
 {
     IFileDialogEventsImpl *pfdeimpl;
@@ -763,6 +789,7 @@ static void test_advise_helper(IFileDialog *pfd)
     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);
+    ensure_zero_events(pfdeimpl);
 
     hr = IFileDialog_Unadvise(pfd, 0);
     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
@@ -772,33 +799,39 @@ static void test_advise_helper(IFileDialog *pfd)
         ok(cookie[i] == i+1, "Got cookie: %d\n", cookie[i]);
     }
     ok(pfdeimpl->ref == 10+1, "got ref %d\n", pfdeimpl->ref);
+    ensure_zero_events(pfdeimpl);
 
     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);
+    ensure_zero_events(pfdeimpl);
 
     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);
+    ensure_zero_events(pfdeimpl);
 
     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);
+    ensure_zero_events(pfdeimpl);
 
     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);
+    ensure_zero_events(pfdeimpl);
 
     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);
+    ensure_zero_events(pfdeimpl);
 
     hr = IFileDialog_Unadvise(pfd, cookie[0]);
 
-- 
1.7.5.rc3




More information about the wine-patches mailing list