comdlg32: Fix a problem with the returned value of a CDN_FILEOK notification.

Rein Klazes wijn at online.nl
Tue Jun 30 01:41:10 CDT 2009


fixes bug #19079

The application of this bug report subclasses the window proc of the file
dialog. It does not return the result in the DWLP_MSGRESULT dialog
property but the return code of the window proc. Tests are provided to
show correct behaviour in all cases, subclassed or not.
---
 dlls/comdlg32/filedlg.c       |    8 ++--
 dlls/comdlg32/tests/filedlg.c |  112 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+), 4 deletions(-)

diff --git a/dlls/comdlg32/filedlg.c b/dlls/comdlg32/filedlg.c
index 6e7f985..6f89697 100644
--- a/dlls/comdlg32/filedlg.c
+++ b/dlls/comdlg32/filedlg.c
@@ -1760,19 +1760,19 @@ static BOOL FILEDLG95_SendFileOK( HWND hwnd, FileOpenDlgInfos *fodInfos )
         /* First send CDN_FILEOK as MSDN doc says */
         if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
             retval = SendCustomDlgNotificationMessage(hwnd,CDN_FILEOK);
-        if (GetWindowLongPtrW(fodInfos->DlgInfos.hwndCustomDlg, DWLP_MSGRESULT))
+        if( retval)
         {
             TRACE("canceled\n");
-            return (retval == 0);
+            return FALSE;
         }
 
         /* fodInfos->ofnInfos points to an ASCII or UNICODE structure as appropriate */
         retval = SendMessageW(fodInfos->DlgInfos.hwndCustomDlg,
                               fodInfos->HookMsg.fileokstring, 0, (LPARAM)fodInfos->ofnInfos);
-        if (GetWindowLongPtrW(fodInfos->DlgInfos.hwndCustomDlg, DWLP_MSGRESULT))
+        if( retval)
         {
             TRACE("canceled\n");
-            return (retval == 0);
+            return FALSE;
         }
     }
     return TRUE;
diff --git a/dlls/comdlg32/tests/filedlg.c b/dlls/comdlg32/tests/filedlg.c
index 0cd1e63..0b1561e 100644
--- a/dlls/comdlg32/tests/filedlg.c
+++ b/dlls/comdlg32/tests/filedlg.c
@@ -399,10 +399,122 @@ static void test_resize(void)
     }
 }
 
+/* test cases for control message IDOK */
+/* Show case for bug #19079 */
+static struct {
+    int  retval;        /* return code of the message handler */
+    BOOL setmsgresult;  /* set the result in the DWLP_MSGRESULT */
+    BOOL usemsgokstr;   /* use the FILEOKSTRING message instead of WM_NOTIFY:CDN_FILEOK */
+    BOOL do_subclass;   /* subclass the dialog hook procedure */
+    BOOL expclose;      /* is the dialog expected to close ? */
+    BOOL actclose;      /* has the dialog actually closed ? */
+} ok_testcases[] = {
+    { 0,        FALSE,  FALSE,  FALSE,  TRUE},
+    { 0,         TRUE,  FALSE,  FALSE,  TRUE},
+    { 0,        FALSE,  FALSE,   TRUE,  TRUE},
+    { 0,         TRUE,  FALSE,   TRUE,  TRUE},
+    { 1,        FALSE,  FALSE,  FALSE,  TRUE},
+    { 1,         TRUE,  FALSE,  FALSE, FALSE},
+    { 1,        FALSE,  FALSE,   TRUE, FALSE},
+    { 1,         TRUE,  FALSE,   TRUE, FALSE},
+    /* FILEOKSTRING tests */
+    { 1,         TRUE,   TRUE,  FALSE, FALSE},
+    { 1,        FALSE,   TRUE,   TRUE, FALSE},
+    /* mark the end */
+    { -1 }
+};
+
+/* test_ok_wndproc can be used as hook procedure or a subclass
+ * window proc for the file dialog */
+static LONG_PTR WINAPI test_ok_wndproc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    HWND parent = GetParent( dlg);
+    static int index;
+    static UINT msgFILEOKSTRING;
+    if (msg == WM_INITDIALOG)
+    {
+        index = ((OPENFILENAME*)lParam)->lCustData;
+        ok_testcases[index].actclose = TRUE;
+        msgFILEOKSTRING = RegisterWindowMessageA( FILEOKSTRING);
+    }
+    if( msg == WM_NOTIFY) {
+        if(((LPNMHDR)lParam)->code == CDN_INITDONE) {
+            SetTimer( dlg, 0, 100, 0);
+            PostMessage( parent, WM_COMMAND, IDOK, 0);
+            return FALSE;
+        } else if(((LPNMHDR)lParam)->code == CDN_FILEOK) {
+            if( ok_testcases[index].usemsgokstr)
+                return FALSE;
+            if( ok_testcases[index].setmsgresult)
+                SetWindowLongPtrA( dlg, DWLP_MSGRESULT, ok_testcases[index].retval);
+            return ok_testcases[index].retval;
+        }
+    }
+    if( msg == msgFILEOKSTRING) {
+        if( !ok_testcases[index].usemsgokstr)
+            return FALSE;
+        if( ok_testcases[index].setmsgresult)
+            SetWindowLongPtrA( dlg, DWLP_MSGRESULT, ok_testcases[index].retval);
+        return ok_testcases[index].retval;
+    }
+    if( msg == WM_TIMER) {
+        /* the dialog did not close automatically */
+        ok_testcases[index].actclose = FALSE;
+        KillTimer( dlg, 0);
+        PostMessage( parent, WM_COMMAND, IDCANCEL, 0);
+        return FALSE;
+    }
+    if( ok_testcases[index].do_subclass)
+        return DefWindowProc( dlg, msg, wParam, lParam);
+    return FALSE;
+}
+
+static LONG_PTR WINAPI ok_template_hook(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    if (msg == WM_SETFONT)
+        SetWindowLongPtrA( dlg, GWLP_WNDPROC, (LONG_PTR) test_ok_wndproc);
+    return FALSE;
+}
+
+static void test_ok(void)
+{
+    OPENFILENAME ofn = { sizeof(OPENFILENAME)};
+    char filename[1024] = {0};
+    char tmpfilename[ MAX_PATH];
+    int i;
+    DWORD ret;
+
+    if (!GetTempFileNameA(".", "tmp", 0, tmpfilename)) {
+        skip("Failed to create a temporary file name\n");
+        return;
+    }
+    ofn.lpstrFile = filename;
+    ofn.nMaxFile = 1024;
+    ofn.hInstance = GetModuleHandle(NULL);
+    ofn.lpTemplateName = "template1";
+    ofn.Flags =  OFN_ENABLEHOOK | OFN_EXPLORER| OFN_ENABLETEMPLATE ;
+    for( i = 0; ok_testcases[i].retval != -1; i++) {
+        strcpy( filename, tmpfilename);
+        ofn.lCustData = i;
+        ofn.lpfnHook = ok_testcases[i].do_subclass
+            ? (LPOFNHOOKPROC) ok_template_hook
+            : (LPOFNHOOKPROC) test_ok_wndproc;
+        ret = GetOpenFileNameA(&ofn);
+        ok( ok_testcases[i].expclose == ok_testcases[i].actclose,
+                "Open File dialog should %shave closed.\n",
+                ok_testcases[i].expclose ? "" : "NOT ");
+        ok(ret == ok_testcases[i].expclose, "GetOpenFileName returned %#x\n", ret);
+        ret = CommDlgExtendedError();
+        ok(!ret, "CommDlgExtendedError returned %#x\n", ret);
+    }
+    ok( DeleteFileA( tmpfilename), "Failed to delete temporary file\n");
+}
+
 START_TEST(filedlg)
 {
     test_DialogCancel();
     test_create_view_window2();
     test_create_view_template();
     test_resize();
+    test_ok();
 }
-- 
1.6.3.1




More information about the wine-patches mailing list