Make GetOpenFileNameW with an old style open file dialog work with the original OPENFILENAMEW structure

Dmitry Timoshkov dmitry at baikal.ru
Thu Feb 3 09:40:43 CST 2005


Hello,

this patch fixes a crash in MS Query. The app call GetOpenFileNameW with
a 3.1 style custom dialog and expects that nFileOffset and nFileExtension
will be correctly set. But our GetFileName31W implementation has its own
internal file dialog structure it works with and it never passes updated
results to the caller. The fact that GetFileName31W works with its own
structure is strange since A variant and 16-bit one work with an original
structure. I modified GetFileName31W to work on the original structure
as well, also I made some minor changes which make traces of builtin
GetOpenFileNameW better match a native one.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Make GetOpenFileNameW with an old style open file dialog work
    with the original OPENFILENAMEW structure, making sure that all
    changes are passed back to the caller.

diff -up cvs/hq/wine/dlls/commdlg/filedlg16.c wine/dlls/commdlg/filedlg16.c
--- cvs/hq/wine/dlls/commdlg/filedlg16.c	2004-10-11 13:21:41.000000000 +0900
+++ wine/dlls/commdlg/filedlg16.c	2005-02-03 23:04:35.000000000 +0800
@@ -170,7 +170,7 @@ static BOOL CALLBACK FD16_Init(LPARAM lP
         if (priv->ofn16->lpfnHook)
             lfs->hook = TRUE;
 
-    FD16_MapOfnStruct16(priv->ofn16, &lfs->ofnW, lfs->open);
+    FD16_MapOfnStruct16(priv->ofn16, lfs->ofnW, lfs->open);
 
     if (! FD16_GetTemplate(lfs)) return FALSE;
 
@@ -204,7 +204,7 @@ BOOL CALLBACK FD16_CallWindowProc(PFD31_
 static void CALLBACK FD16_UpdateResult(PFD31_DATA lfs)
 {
     PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;
-    LPOPENFILENAMEW ofnW = &lfs->ofnW;
+    LPOPENFILENAMEW ofnW = lfs->ofnW;
 
     if (priv->ofn16)
     { /* we have to convert to short (8.3) path */
@@ -240,7 +240,7 @@ static void CALLBACK FD16_UpdateResult(P
 static void CALLBACK FD16_UpdateFileTitle(PFD31_DATA lfs)
 {
     PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;
-    LPOPENFILENAMEW ofnW = &lfs->ofnW;
+    LPOPENFILENAMEW ofnW = lfs->ofnW;
 
     if (priv->ofn16)
     {
@@ -279,7 +279,7 @@ static void CALLBACK FD16_Destroy(PFD31_
             GlobalUnlock16(priv->hGlobal16);
             GlobalFree16(priv->hGlobal16);
         }
-        FD31_FreeOfnW(&lfs->ofnW);
+        FD31_FreeOfnW(lfs->ofnW);
     }
 }
 
diff -up cvs/hq/wine/dlls/commdlg/filedlg31.c wine/dlls/commdlg/filedlg31.c
--- cvs/hq/wine/dlls/commdlg/filedlg31.c	2005-01-10 13:55:48.000000000 +0800
+++ wine/dlls/commdlg/filedlg31.c	2005-02-03 23:13:56.000000000 +0800
@@ -38,6 +38,7 @@
 #include "cderr.h"
 #include "winreg.h"
 #include "winternl.h"
+#include "shlwapi.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
 
@@ -305,9 +306,9 @@ LONG FD31_WMDrawItem(HWND hWnd, WPARAM w
 void FD31_UpdateResult(PFD31_DATA lfs, WCHAR *tmpstr)
 {
     int lenstr2;
-    LPOPENFILENAMEW ofnW = &lfs->ofnW;
+    LPOPENFILENAMEW ofnW = lfs->ofnW;
     WCHAR tmpstr2[BUFFILE];
-    WCHAR *bs;
+    WCHAR *p;
 
     TRACE("%s\n", debugstr_w(tmpstr));
     if(ofnW->Flags & OFN_NOVALIDATE)
@@ -320,17 +321,18 @@ void FD31_UpdateResult(PFD31_DATA lfs, W
     lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
     if (ofnW->lpstrFile)
         lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
-    if((bs = strrchrW(tmpstr2, '\\')) != NULL)
-        ofnW->nFileOffset = bs - tmpstr2 +1;
-    else
-        ofnW->nFileOffset = 0;
-    ofnW->nFileExtension = 0;
-    while(tmpstr2[ofnW->nFileExtension] != '.' && tmpstr2[ofnW->nFileExtension] != '\0')
-        ofnW->nFileExtension++;
-    if (tmpstr2[ofnW->nFileExtension] == '\0')
-        ofnW->nFileExtension = 0;
-    else
-        ofnW->nFileExtension++;
+
+    /* set filename offset */
+    p = PathFindFileNameW(ofnW->lpstrFile);
+    ofnW->nFileOffset = (p - ofnW->lpstrFile);
+
+    /* set extension offset */
+    p = PathFindExtensionW(ofnW->lpstrFile);
+    ofnW->nFileExtension = (*p) ? (p - ofnW->lpstrFile) + 1 : 0;
+
+    TRACE("file %s, file offset %d, ext offset %d\n",
+          debugstr_w(ofnW->lpstrFile), ofnW->nFileOffset, ofnW->nFileExtension);
+
     /* update the real client structures if any */
     lfs->callbacks->UpdateResult(lfs);
 }
@@ -342,7 +344,7 @@ void FD31_UpdateResult(PFD31_DATA lfs, W
 void FD31_UpdateFileTitle(PFD31_DATA lfs)
 {
   LONG lRet;
-  LPOPENFILENAMEW ofnW = &lfs->ofnW;
+  LPOPENFILENAMEW ofnW = lfs->ofnW;
   if (ofnW->lpstrFileTitle != NULL)
   {
     lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
@@ -447,14 +449,14 @@ static LRESULT FD31_TestPath( PFD31_DATA
 	else
 	{
 	    strcpyW(tmpstr2, path);
-            if(!(lfs->ofnW.Flags & OFN_NOVALIDATE))
+            if(!(lfs->ofnW->Flags & OFN_NOVALIDATE))
                 *path = 0;
         }
 
         TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
         SetDlgItemTextW( hWnd, edt1, tmpstr2 );
         FD31_ScanDir(hWnd, path);
-        return (lfs->ofnW.Flags & OFN_NOVALIDATE) ? TRUE : FALSE;
+        return (lfs->ofnW->Flags & OFN_NOVALIDATE) ? TRUE : FALSE;
     }
 
     /* no wildcards, we might have a directory or a filename */
@@ -501,7 +503,7 @@ static LRESULT FD31_Validate( PFD31_DATA
     LONG lRet;
     HWND hWnd = lfs->hwnd;
     OPENFILENAMEW ofnsav;
-    LPOPENFILENAMEW ofnW = &lfs->ofnW;
+    LPOPENFILENAMEW ofnW = lfs->ofnW;
     WCHAR filename[BUFFILE];
 
     ofnsav = *ofnW; /* for later restoring */
@@ -610,9 +612,7 @@ LRESULT FD31_WMCommand(HWND hWnd, LPARAM
         FD31_StripEditControl(hWnd);
         if (notification == LBN_DBLCLK)
         {
-            if (FD31_Validate( lfs, NULL, control, 0, FALSE ))
-                EndDialog(hWnd, TRUE);
-            return TRUE;
+            return SendMessageW(hWnd, WM_COMMAND, IDOK, 0);
         }
         else if (notification == LBN_SELCHANGE)
             return FD31_FileListSelect( lfs );
@@ -700,7 +700,7 @@ static LPWSTR FD31_DupToW(LPCSTR str, DW
  *                              FD31_MapOfnStructA          [internal]
  *      map a 32 bits Ansi structure to an Unicode one
  */
-void FD31_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
+void FD31_MapOfnStructA(const LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
 {
     UNICODE_STRING usBuffer;
 
@@ -828,7 +828,7 @@ LONG FD31_WMInitDialog(HWND hWnd, WPARAM
   if (!lfs) return FALSE;
   SetPropA(hWnd, FD31_OFN_PROP, (HANDLE)lfs);
   lfs->hwnd = hWnd;
-  ofn = &lfs->ofnW;
+  ofn = lfs->ofnW;
 
   TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
 
diff -up cvs/hq/wine/dlls/commdlg/filedlg31.h wine/dlls/commdlg/filedlg31.h
--- cvs/hq/wine/dlls/commdlg/filedlg31.h	2004-07-14 09:39:10.000000000 +0900
+++ wine/dlls/commdlg/filedlg31.h	2005-02-03 23:20:54.000000000 +0800
@@ -44,7 +44,8 @@ typedef struct tagFD31_DATA
     LPARAM lParam; /* save original lparam */
     LPCVOID template; /* template for 32 bits resource */
     BOOL open; /* TRUE if open dialog, FALSE if save dialog */
-    OPENFILENAMEW ofnW; /* copy of original structure or work struct */
+    LPOPENFILENAMEW ofnW; /* pointer either to the original structure or
+                             a W copy for A/16 API */
     LPVOID private1632; /* 16/32 bit caller private data */
     PFD31_CALLBACKS callbacks; /* callbacks to handle 16/32 bit differences */
 } FD31_DATA;
diff -up cvs/hq/wine/dlls/commdlg/filedlg.c wine/dlls/commdlg/filedlg.c
--- cvs/hq/wine/dlls/commdlg/filedlg.c	2005-01-19 14:21:06.000000000 +0800
+++ wine/dlls/commdlg/filedlg.c	2005-02-03 23:23:59.000000000 +0800
@@ -3377,7 +3377,7 @@ static void MemFree(void *mem)
  */
 static BOOL FD32_GetTemplate(PFD31_DATA lfs)
 {
-    LPOPENFILENAMEW ofnW = &lfs->ofnW;
+    LPOPENFILENAMEW ofnW = lfs->ofnW;
     PFD32_PRIVATE priv = (PFD32_PRIVATE) lfs->private1632;
     HANDLE hDlgTmpl;
 
@@ -3445,9 +3445,9 @@ static BOOL CALLBACK FD32_Init(LPARAM lP
     if (NULL == lfs->private1632) return FALSE;
     if (IsUnicode)
     {
-        lfs->ofnW = *((LPOPENFILENAMEW) lParam);
-        if (lfs->ofnW.Flags & OFN_ENABLEHOOK)
-            if (lfs->ofnW.lpfnHook)
+        lfs->ofnW = (LPOPENFILENAMEW) lParam;
+        if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
+            if (lfs->ofnW->lpfnHook)
                 lfs->hook = TRUE;
     }
     else
@@ -3456,7 +3456,8 @@ static BOOL CALLBACK FD32_Init(LPARAM lP
         if (priv->ofnA->Flags & OFN_ENABLEHOOK)
             if (priv->ofnA->lpfnHook)
                 lfs->hook = TRUE;
-        FD31_MapOfnStructA(priv->ofnA, &lfs->ofnW, lfs->open);
+        lfs->ofnW = HeapAlloc(GetProcessHeap(), 0, sizeof(*lfs->ofnW));
+        FD31_MapOfnStructA(priv->ofnA, lfs->ofnW, lfs->open);
     }
 
     if (! FD32_GetTemplate(lfs)) return FALSE;
@@ -3472,18 +3473,25 @@ static BOOL CALLBACK FD32_Init(LPARAM lP
 BOOL CALLBACK FD32_CallWindowProc(PFD31_DATA lfs, UINT wMsg, WPARAM wParam,
                                  LPARAM lParam)
 {
+    BOOL ret;
     PFD32_PRIVATE priv = (PFD32_PRIVATE) lfs->private1632;
 
     if (priv->ofnA)
     {
-        return (BOOL) CallWindowProcA(
-          (WNDPROC)priv->ofnA->lpfnHook, lfs->hwnd,
-          wMsg, wParam, lParam);
+        TRACE("Call hookA %p (%p, %04x, %08x, %08lx)\n",
+               priv->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+        ret = priv->ofnA->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
+        TRACE("ret hookA %p (%p, %04x, %08x, %08lx)\n",
+               priv->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+        return ret;
     }
 
-    return (BOOL) CallWindowProcW(
-          (WNDPROC)lfs->ofnW.lpfnHook, lfs->hwnd,
-          wMsg, wParam, lParam);
+    TRACE("Call hookW %p (%p, %04x, %08x, %08lx)\n",
+           lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+    ret = lfs->ofnW->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
+    TRACE("Ret hookW %p (%p, %04x, %08x, %08lx)\n",
+           lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+    return ret;
 }
 
 /***********************************************************************
@@ -3493,7 +3501,7 @@ BOOL CALLBACK FD32_CallWindowProc(PFD31_
 static void CALLBACK FD32_UpdateResult(PFD31_DATA lfs)
 {
     PFD32_PRIVATE priv = (PFD32_PRIVATE) lfs->private1632;
-    LPOPENFILENAMEW ofnW = &lfs->ofnW;
+    LPOPENFILENAMEW ofnW = lfs->ofnW;
 
     if (priv->ofnA)
     {
@@ -3513,7 +3521,7 @@ static void CALLBACK FD32_UpdateResult(P
 static void CALLBACK FD32_UpdateFileTitle(PFD31_DATA lfs)
 {
     PFD32_PRIVATE priv = (PFD32_PRIVATE) lfs->private1632;
-    LPOPENFILENAMEW ofnW = &lfs->ofnW;
+    LPOPENFILENAMEW ofnW = lfs->ofnW;
 
     if (priv->ofnA)
     {
@@ -3544,7 +3552,10 @@ static void CALLBACK FD32_Destroy(PFD31_
 
     /* if ofnW has been allocated, have to free everything in it */
     if (NULL != priv && NULL != priv->ofnA)
-        FD31_FreeOfnW(&lfs->ofnW);
+    {
+        FD31_FreeOfnW(lfs->ofnW);
+        HeapFree(GetProcessHeap(), 0, lfs->ofnW);
+    }
 }
 
 static void FD32_SetupCallbacks(PFD31_CALLBACKS callbacks)
@@ -3676,7 +3687,8 @@ static BOOL GetFileName31W(LPOPENFILENAM
         FD31_DestroyPrivate(lfs);
     }
 
-    TRACE("return lpstrFile=%s !\n", debugstr_w(lpofn->lpstrFile));
+    TRACE("file %s, file offset %d, ext offset %d\n",
+          debugstr_w(lpofn->lpstrFile), lpofn->nFileOffset, lpofn->nFileExtension);
     return bRet;
 }
 
@@ -3697,6 +3709,10 @@ BOOL WINAPI GetOpenFileNameA(
 {
     BOOL win16look = FALSE;
 
+    /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
+    if (ofn->Flags & OFN_FILEMUSTEXIST)
+        ofn->Flags |= OFN_PATHMUSTEXIST;
+
     if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
         win16look = (ofn->Flags & OFN_EXPLORER) ? FALSE : TRUE;
 






More information about the wine-patches mailing list