[COMDLG32]
[reactos.git] / reactos / dll / win32 / comdlg32 / filedlg31.c
index cd485f3..29c6310 100644 (file)
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 #include <ctype.h>
 #include <stdlib.h>
 #include "winuser.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
-#include "cderr.h"
 #include "winreg.h"
 #include "winternl.h"
-#include "winuser.h"
 #include "commdlg.h"
-#include "cderr.h"
-#include "winreg.h"
-#include "winternl.h"
 #include "shlwapi.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
@@ -111,29 +106,72 @@ static void FD31_StripEditControl(HWND hwnd)
  *
  *      Call the appropriate hook
  */
-BOOL FD31_CallWindowProc(PFD31_DATA lfs, UINT wMsg, WPARAM wParam,
+BOOL FD31_CallWindowProc(const FD31_DATA *lfs, UINT wMsg, WPARAM wParam,
                          LPARAM lParam)
 {
-    return lfs->callbacks->CWP(lfs, wMsg, wParam, lParam);
+    BOOL ret;
+
+    if (lfs->ofnA)
+    {
+        TRACE("Call hookA %p (%p, %04x, %08lx, %08lx)\n",
+               lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+        ret = lfs->ofnA->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
+        TRACE("ret hookA %p (%p, %04x, %08lx, %08lx)\n",
+               lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+        return ret;
+    }
+
+    TRACE("Call hookW %p (%p, %04x, %08lx, %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, %08lx, %08lx)\n",
+           lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+    return ret;
+}
+
+/***********************************************************************
+ *                             FD31_GetFileType                [internal]
+ */
+static LPCWSTR FD31_GetFileType(LPCWSTR cfptr, LPCWSTR fptr, const WORD index)
+{
+  int n, i;
+  i = 0;
+  if (cfptr)
+    for ( ;(n = lstrlenW(cfptr)) != 0; i++)
+      {
+       cfptr += n + 1;
+       if (i == index)
+         return cfptr;
+       cfptr += lstrlenW(cfptr) + 1;
+      }
+  if (fptr)
+    for ( ;(n = lstrlenW(fptr)) != 0; i++)
+      {
+       fptr += n + 1;
+       if (i == index)
+         return fptr;
+       fptr += lstrlenW(fptr) + 1;
+    }
+  return FILE_star; /* FIXME */
 }
 
 /***********************************************************************
  *                             FD31_ScanDir                 [internal]
  */
-static BOOL FD31_ScanDir(HWND hWnd, LPWSTR newPath)
+static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath)
 {
-    WCHAR              buffer[BUFFILE];
-    HWND               hdlg, hdlgDir;
-    LRESULT             lRet = TRUE;
-    HCURSOR             hCursorWait, oldCursor;
+    WCHAR   buffer[BUFFILE];
+    HWND    hdlg;
+    LRESULT lRet = TRUE;
+    HCURSOR hCursorWait, oldCursor;
 
     TRACE("Trying to change to %s\n", debugstr_w(newPath));
     if  ( newPath[0] && !SetCurrentDirectoryW( newPath ))
         return FALSE;
-    lstrcpynW(buffer, newPath, sizeof(buffer)/sizeof(WCHAR));
 
     /* get the list of spec files */
-    GetDlgItemTextW(hWnd, edt1, buffer, sizeof(buffer)/sizeof(WCHAR));
+    lstrcpynW(buffer, FD31_GetFileType(ofn->lpstrCustomFilter,
+              ofn->lpstrFilter, ofn->nFilterIndex - 1), BUFFILE);
 
     hCursorWait = LoadCursorA(0, (LPSTR)IDC_WAIT);
     oldCursor = SetCursor(hCursorWait);
@@ -150,8 +188,7 @@ static BOOL FD31_ScanDir(HWND hWnd, LPWSTR newPath)
            if (scptr)  *scptr = 0;
             while (*filter == ' ') filter++;
            TRACE("Using file spec %s\n", debugstr_w(filter));
-           if (SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
-               return FALSE;
+           SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter);
            if (scptr) *scptr = ';';
                filter = (scptr) ? (scptr + 1) : 0;
         }
@@ -160,45 +197,18 @@ static BOOL FD31_ScanDir(HWND hWnd, LPWSTR newPath)
     /* list of directories */
     strcpyW(buffer, FILE_star);
 
-    if ((hdlgDir = GetDlgItem(hWnd, lst2)) != 0) {
+    if (GetDlgItem(hWnd, lst2) != 0) {
         lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
     }
     SetCursor(oldCursor);
     return lRet;
 }
 
-/***********************************************************************
- *                             FD31_GetFileType                [internal]
- */
-
-static LPWSTR FD31_GetFileType(LPWSTR cfptr, LPWSTR fptr, WORD index)
-{
-  int n, i;
-  i = 0;
-  if (cfptr)
-    for ( ;(n = lstrlenW(cfptr)) != 0; i++)
-      {
-       cfptr += n + 1;
-       if (i == index)
-         return cfptr;
-       cfptr += lstrlenW(cfptr) + 1;
-      }
-  if (fptr)
-    for ( ;(n = lstrlenW(fptr)) != 0; i++)
-      {
-       fptr += n + 1;
-       if (i == index)
-         return fptr;
-       fptr += lstrlenW(fptr) + 1;
-    }
-  return (LPWSTR) FILE_star; /* FIXME */
-}
-
 /***********************************************************************
  *                              FD31_WMDrawItem              [internal]
  */
 LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
-       int savedlg, LPDRAWITEMSTRUCT lpdis)
+       int savedlg, const DRAWITEMSTRUCT *lpdis)
 {
     WCHAR *str;
     HICON hIcon;
@@ -258,7 +268,7 @@ LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
            SetBkColor( lpdis->hDC, oldBk );
            SetTextColor( lpdis->hDC, oldText );
        }
-       DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
+       DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder, 16, 16, 0, 0, DI_NORMAL );
         HeapFree(GetProcessHeap(), 0, str);
        return TRUE;
     }
@@ -292,7 +302,7 @@ LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
            SetBkColor( lpdis->hDC, oldBk );
            SetTextColor( lpdis->hDC, oldText );
        }
-       DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
+       DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon, 16, 16, 0, 0, DI_NORMAL );
         HeapFree(GetProcessHeap(), 0, str);
        return TRUE;
     }
@@ -303,10 +313,11 @@ LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
  *                              FD31_UpdateResult            [internal]
  *      update the displayed file name (with path)
  */
-static void FD31_UpdateResult(PFD31_DATA lfs, WCHAR *tmpstr)
+static void FD31_UpdateResult(const FD31_DATA *lfs, const WCHAR *tmpstr)
 {
     int lenstr2;
     LPOPENFILENAMEW ofnW = lfs->ofnW;
+    LPOPENFILENAMEA ofnA = lfs->ofnA;
     WCHAR tmpstr2[BUFFILE];
     WCHAR *p;
 
@@ -319,8 +330,10 @@ static void FD31_UpdateResult(PFD31_DATA lfs, WCHAR *tmpstr)
     if (lenstr2 > 3)
         tmpstr2[lenstr2++]='\\';
     lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
-    if (ofnW->lpstrFile)
-        lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
+    if (!ofnW->lpstrFile)
+        return;
+
+    lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
 
     /* set filename offset */
     p = PathFindFileNameW(ofnW->lpstrFile);
@@ -334,30 +347,53 @@ static void FD31_UpdateResult(PFD31_DATA lfs, WCHAR *tmpstr)
           debugstr_w(ofnW->lpstrFile), ofnW->nFileOffset, ofnW->nFileExtension);
 
     /* update the real client structures if any */
-    lfs->callbacks->UpdateResult(lfs);
+    if (ofnA)
+    {
+        LPSTR lpszTemp;
+        if (ofnW->nMaxFile &&
+            !WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
+                                  ofnA->lpstrFile, ofnA->nMaxFile, NULL, NULL ))
+            ofnA->lpstrFile[ofnA->nMaxFile-1] = 0;
+
+        /* offsets are not guaranteed to be the same in WCHAR to MULTIBYTE conversion */
+        /* set filename offset */
+        lpszTemp = PathFindFileNameA(ofnA->lpstrFile);
+        ofnA->nFileOffset = (lpszTemp - ofnA->lpstrFile);
+
+        /* set extension offset */
+        lpszTemp = PathFindExtensionA(ofnA->lpstrFile);
+        ofnA->nFileExtension = (*lpszTemp) ? (lpszTemp - ofnA->lpstrFile) + 1 : 0;
+    }
 }
 
 /***********************************************************************
  *                              FD31_UpdateFileTitle         [internal]
  *      update the displayed file name (without path)
  */
-static void FD31_UpdateFileTitle(PFD31_DATA lfs)
+static void FD31_UpdateFileTitle(const FD31_DATA *lfs)
 {
   LONG lRet;
   LPOPENFILENAMEW ofnW = lfs->ofnW;
+  LPOPENFILENAMEA ofnA = lfs->ofnA;
+
   if (ofnW->lpstrFileTitle != NULL)
   {
     lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
     SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
                              (LPARAM)ofnW->lpstrFileTitle );
-    lfs->callbacks->UpdateFileTitle(lfs);
+    if (ofnA)
+    {
+        if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
+                                  ofnA->lpstrFileTitle, ofnA->nMaxFileTitle, NULL, NULL ))
+            ofnA->lpstrFileTitle[ofnA->nMaxFileTitle-1] = 0;
+    }
   }
 }
 
 /***********************************************************************
  *                              FD31_DirListDblClick         [internal]
  */
-static LRESULT FD31_DirListDblClick( PFD31_DATA lfs )
+static LRESULT FD31_DirListDblClick( const FD31_DATA *lfs )
 {
   LONG lRet;
   HWND hWnd = lfs->hwnd;
@@ -380,7 +416,7 @@ static LRESULT FD31_DirListDblClick( PFD31_DATA lfs )
     }
   strcatW(tmpstr, FILE_bslash);
 
-  FD31_ScanDir(hWnd, tmpstr);
+  FD31_ScanDir(lfs->ofnW, hWnd, tmpstr);
   /* notify the app */
   if (lfs->hook)
     {
@@ -395,13 +431,13 @@ static LRESULT FD31_DirListDblClick( PFD31_DATA lfs )
  *                              FD31_FileListSelect         [internal]
  *    called when a new item is picked in the file list
  */
-static LRESULT FD31_FileListSelect( PFD31_DATA lfs )
+static LRESULT FD31_FileListSelect( const FD31_DATA *lfs )
 {
     LONG lRet;
     HWND hWnd = lfs->hwnd;
     LPWSTR pstr;
 
-    lRet = lfs->callbacks->SendLbGetCurSel(lfs);
+    lRet =  SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
     if (lRet == LB_ERR)
         return TRUE;
 
@@ -428,7 +464,7 @@ static LRESULT FD31_FileListSelect( PFD31_DATA lfs )
  *      before accepting the file name, test if it includes wild cards
  *      tries to scan the directory and returns TRUE if no error.
  */
-static LRESULT FD31_TestPath( PFD31_DATA lfs, LPWSTR path )
+static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
 {
     HWND hWnd = lfs->hwnd;
     LPWSTR pBeginFileName, pstr2;
@@ -455,7 +491,7 @@ static LRESULT FD31_TestPath( PFD31_DATA lfs, LPWSTR path )
 
         TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
         SetDlgItemTextW( hWnd, edt1, tmpstr2 );
-        FD31_ScanDir(hWnd, path);
+        FD31_ScanDir(lfs->ofnW, hWnd, path);
         return (lfs->ofnW->Flags & OFN_NOVALIDATE) ? TRUE : FALSE;
     }
 
@@ -467,7 +503,7 @@ static LRESULT FD31_TestPath( PFD31_DATA lfs, LPWSTR path )
         strcatW(path, FILE_bslash);
 
     /* if ScanDir succeeds, we have changed the directory */
-    if (FD31_ScanDir(hWnd, path))
+    if (FD31_ScanDir(lfs->ofnW, hWnd, path))
         return FALSE; /* and path is not a valid file name */
 
     /* if not, this must be a filename */
@@ -482,7 +518,7 @@ static LRESULT FD31_TestPath( PFD31_DATA lfs, LPWSTR path )
 
         lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) );
         /* Should we MessageBox() if this fails? */
-        if (!FD31_ScanDir(hWnd, path))
+        if (!FD31_ScanDir(lfs->ofnW, hWnd, path))
         {
             return FALSE;
         }
@@ -497,7 +533,7 @@ static LRESULT FD31_TestPath( PFD31_DATA lfs, LPWSTR path )
  *                              FD31_Validate               [internal]
  *   called on: click Ok button, Enter in edit, DoubleClick in file list
  */
-static LRESULT FD31_Validate( PFD31_DATA lfs, LPWSTR path, UINT control, INT itemIndex,
+static LRESULT FD31_Validate( const FD31_DATA *lfs, LPCWSTR path, UINT control, INT itemIndex,
                                  BOOL internalUse )
 {
     LONG lRet;
@@ -536,7 +572,7 @@ static LRESULT FD31_Validate( PFD31_DATA lfs, LPWSTR path, UINT control, INT ite
     FD31_UpdateFileTitle(lfs);
     if (lfs->hook)
     {
-        lRet = (BOOL)FD31_CallWindowProc(lfs, lfs->fileokstring,
+        lRet = FD31_CallWindowProc(lfs, lfs->fileokstring,
                   0, lfs->lParam );
         if (lRet)
         {
@@ -548,7 +584,7 @@ static LRESULT FD31_Validate( PFD31_DATA lfs, LPWSTR path, UINT control, INT ite
     {
         if (ofnW->lpstrFile)
         {
-            LPWSTR str = (LPWSTR)ofnW->lpstrFile;
+            LPWSTR str = ofnW->lpstrFile;
             LPWSTR ptr = strrchrW(str, '\\');
            str[lstrlenW(str) + 1] = '\0';
            *ptr = 0;
@@ -561,7 +597,7 @@ static LRESULT FD31_Validate( PFD31_DATA lfs, LPWSTR path, UINT control, INT ite
  *                              FD31_DiskChange             [internal]
  *    called when a new item is picked in the disk selection combo
  */
-static LRESULT FD31_DiskChange( PFD31_DATA lfs )
+static LRESULT FD31_DiskChange( const FD31_DATA *lfs )
 {
     LONG lRet;
     HWND hWnd = lfs->hwnd;
@@ -585,7 +621,7 @@ static LRESULT FD31_DiskChange( PFD31_DATA lfs )
  *                              FD31_FileTypeChange         [internal]
  *    called when a new item is picked in the file type combo
  */
-static LRESULT FD31_FileTypeChange( PFD31_DATA lfs )
+static LRESULT FD31_FileTypeChange( const FD31_DATA *lfs )
 {
     LONG lRet;
     LPWSTR pstr;
@@ -595,7 +631,6 @@ static LRESULT FD31_FileTypeChange( PFD31_DATA lfs )
         return TRUE;
     pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
     TRACE("Selected filter : %s\n", debugstr_w(pstr));
-    SetDlgItemTextW( lfs->hwnd, edt1, pstr );
 
     return FD31_Validate( lfs, NULL, cmb1, lRet, TRUE );
 }
@@ -604,7 +639,7 @@ static LRESULT FD31_FileTypeChange( PFD31_DATA lfs )
  *                              FD31_WMCommand               [internal]
  */
 LRESULT FD31_WMCommand(HWND hWnd, LPARAM lParam, UINT notification,
-       UINT control, PFD31_DATA lfs )
+       UINT control, const FD31_DATA *lfs )
 {
     switch (control)
     {
@@ -698,9 +733,9 @@ static LPWSTR FD31_DupToW(LPCSTR str, DWORD size)
 
 /************************************************************************
  *                              FD31_MapOfnStructA          [internal]
- *      map a 32 bits Ansi structure to an Unicode one
+ *      map a 32 bits Ansi structure to a Unicode one
  */
-void FD31_MapOfnStructA(const LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
+void FD31_MapOfnStructA(const OPENFILENAMEA *ofnA, LPOPENFILENAMEW ofnW, BOOL open)
 {
     UNICODE_STRING usBuffer;
 
@@ -728,12 +763,14 @@ void FD31_MapOfnStructA(const LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL o
         ofnW->lpstrTitle = usBuffer.Buffer;
     } else {
         WCHAR buf[16];
+        LPWSTR title_tmp;
         int len;
         LoadStringW(COMDLG32_hInstance, open ? IDS_OPEN_FILE : IDS_SAVE_AS,
                     buf, sizeof(buf)/sizeof(WCHAR));
         len = lstrlenW(buf)+1;
-        ofnW->lpstrTitle = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
-        memcpy((void*)ofnW->lpstrTitle, buf, len*sizeof(WCHAR));
+        title_tmp = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
+        memcpy(title_tmp, buf, len * sizeof(WCHAR));
+        ofnW->lpstrTitle = title_tmp;
     }
     ofnW->Flags = ofnA->Flags;
     ofnW->nFileOffset = ofnA->nFileOffset;
@@ -741,13 +778,13 @@ void FD31_MapOfnStructA(const LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL o
     ofnW->lpstrDefExt = FD31_DupToW(ofnA->lpstrDefExt, 3);
     if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
     {
-        if (HIWORD(ofnA->lpTemplateName))
+        if (!IS_INTRESOURCE(ofnA->lpTemplateName))
         {
             RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpTemplateName);
             ofnW->lpTemplateName = usBuffer.Buffer;
         }
         else /* numbered resource */
-            ofnW->lpTemplateName = (LPWSTR) ofnA->lpTemplateName;
+            ofnW->lpTemplateName = (LPCWSTR) ofnA->lpTemplateName;
     }
 }
 
@@ -756,7 +793,7 @@ void FD31_MapOfnStructA(const LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL o
  *                              FD31_FreeOfnW          [internal]
  *      Undo all allocations done by FD31_MapOfnStructA
  */
-void FD31_FreeOfnW(LPOPENFILENAMEW ofnW)
+void FD31_FreeOfnW(OPENFILENAMEW *ofnW)
 {
    HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter);
    HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter);
@@ -764,7 +801,7 @@ void FD31_FreeOfnW(LPOPENFILENAMEW ofnW)
    HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
    HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
    HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
-   if ((ofnW->lpTemplateName) && (HIWORD(ofnW->lpTemplateName)))
+   if (!IS_INTRESOURCE(ofnW->lpTemplateName))
        HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
 }
 
@@ -778,7 +815,13 @@ void FD31_DestroyPrivate(PFD31_DATA lfs)
     if (!lfs) return;
     hwnd = lfs->hwnd;
     TRACE("destroying private allocation %p\n", lfs);
-    lfs->callbacks->Destroy(lfs);
+
+    /* if ofnW has been allocated, have to free everything in it */
+    if (lfs->ofnA)
+    {
+        FD31_FreeOfnW(lfs->ofnW);
+        HeapFree(GetProcessHeap(), 0, lfs->ofnW);
+    }
     HeapFree(GetProcessHeap(), 0, lfs);
     RemovePropA(hwnd, FD31_OFN_PROP);
 }
@@ -786,13 +829,12 @@ void FD31_DestroyPrivate(PFD31_DATA lfs)
 /************************************************************************
  *                              FD31_AllocPrivate            [internal]
  *      allocate a private object to hold 32 bits Unicode
- *      structure that will be used throughtout the calls, while
+ *      structure that will be used throughout the calls, while
  *      keeping available the original structures and a few variables
  *      On entry : type = dialog procedure type (16,32A,32W)
  *                 dlgType = dialog type (open or save)
  */
-PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType,
-                             PFD31_CALLBACKS callbacks, DWORD data)
+PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType, BOOL IsUnicode)
 {
     PFD31_DATA lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FD31_DATA));
 
@@ -801,8 +843,26 @@ PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType,
     lfs->hook = FALSE;
     lfs->lParam = lParam;
     lfs->open = (dlgType == OPEN_DIALOG);
-    lfs->callbacks = callbacks;
-    if (! lfs->callbacks->Init(lParam, lfs, data))
+
+    if (IsUnicode)
+    {
+        lfs->ofnA = NULL;
+        lfs->ofnW = (LPOPENFILENAMEW) lParam;
+        if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
+            if (lfs->ofnW->lpfnHook)
+                lfs->hook = TRUE;
+    }
+    else
+    {
+        lfs->ofnA = (LPOPENFILENAMEA) lParam;
+        if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
+            if (lfs->ofnA->lpfnHook)
+                lfs->hook = TRUE;
+        lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lfs->ofnW));
+        FD31_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
+    }
+
+    if (! FD32_GetTemplate(lfs))
     {
         FD31_DestroyPrivate(lfs);
         return NULL;
@@ -826,11 +886,11 @@ LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
   PFD31_DATA lfs = (PFD31_DATA) lParam;
 
   if (!lfs) return FALSE;
-  SetPropA(hWnd, FD31_OFN_PROP, (HANDLE)lfs);
+  SetPropA(hWnd, FD31_OFN_PROP, lfs);
   lfs->hwnd = hWnd;
   ofn = lfs->ofnW;
 
-  TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
+  TRACE("flags=%x initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
 
   SetWindowTextW( hWnd, ofn->lpstrTitle );
   /* read custom filter information */
@@ -874,11 +934,19 @@ LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
   if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
        ofn->nFilterIndex = 1;
   SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
-  lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter,
-            (LPWSTR)ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
-  TRACE("nFilterIndex = %ld, SetText of edt1 to %s\n",
+  if (ofn->lpstrFile && ofn->lpstrFile[0])
+  {
+    TRACE( "SetText of edt1 to %s\n", debugstr_w(ofn->lpstrFile) );
+    SetDlgItemTextW( hWnd, edt1, ofn->lpstrFile );
+  }
+  else
+  {
+    lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter,
+            ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
+    TRACE("nFilterIndex = %d, SetText of edt1 to %s\n",
                        ofn->nFilterIndex, debugstr_w(tmpstr));
-  SetDlgItemTextW( hWnd, edt1, tmpstr );
+    SetDlgItemTextW( hWnd, edt1, tmpstr );
+  }
   /* get drive list */
   *tmpstr = 0;
   DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
@@ -899,9 +967,9 @@ LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
     }
   else
     *tmpstr = 0;
-  if (!FD31_ScanDir(hWnd, tmpstr)) {
+  if (!FD31_ScanDir(ofn, hWnd, tmpstr)) {
     *tmpstr = 0;
-    if (!FD31_ScanDir(hWnd, tmpstr))
+    if (!FD31_ScanDir(ofn, hWnd, tmpstr))
       WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
   }
   /* select current drive in combo 2, omit missing drives */
@@ -922,7 +990,7 @@ LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
   if (ofn->Flags & OFN_HIDEREADONLY)
     ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
   if (lfs->hook)
-      return (BOOL) FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
+      return FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
   return TRUE;
 }