2 * COMMDLG - File Open Dialogs Win95 look and feel
4 * Copyright 1999 Francois Boisvert
5 * Copyright 1999, 2000 Juergen Schmied
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * FIXME: The whole concept of handling unicode is badly broken.
22 * many hook-messages expect a pointer to a
23 * OPENFILENAMEA or W structure. With the current architecture
24 * we would have to convert the beast at every call to a hook.
25 * we have to find a better solution but it would likely cause
26 * a complete rewrite after which we should handle the
27 * OPENFILENAME structure without any converting (jsch).
29 * FIXME: any hook gets a OPENFILENAMEA structure
31 * FIXME: CDN_FILEOK is wrong implemented, other CDN_ messages likely too
33 * FIXME: old style hook messages are not implemented (except FILEOKSTRING)
35 * FIXME: algorithm for selecting the initial directory is too simple
37 * FIXME: add to recent docs
39 * FIXME: flags not implemented: OFN_CREATEPROMPT, OFN_DONTADDTORECENT,
40 * OFN_ENABLEINCLUDENOTIFY, OFN_ENABLESIZING,
41 * OFN_NODEREFERENCELINKS, OFN_NOREADONLYRETURN,
42 * OFN_NOTESTFILECREATE, OFN_USEMONIKERS
44 * FIXME: lCustData for lpfnHook (WM_INITDIALOG)
50 #include "wine/port.h"
59 #define NONAMELESSUNION
60 #define NONAMELESSSTRUCT
67 #include "wine/unicode.h"
74 #include "filedlg31.h"
75 #include "wine/debug.h"
80 #include "filedlgbrowser.h"
83 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
85 #define UNIMPLEMENTED_FLAGS \
86 (OFN_CREATEPROMPT | OFN_DONTADDTORECENT |\
87 OFN_ENABLEINCLUDENOTIFY | OFN_ENABLESIZING |\
88 OFN_NODEREFERENCELINKS | OFN_NOREADONLYRETURN |\
89 OFN_NOTESTFILECREATE /*| OFN_USEMONIKERS*/)
91 #define IsHooked(fodInfos) \
92 ((fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
93 /***********************************************************************
94 * Data structure and global variables
96 typedef struct SFolder
98 int m_iImageIndex
; /* Index of picture in image list */
100 int m_iIndent
; /* Indentation index */
101 LPITEMIDLIST pidlItem
; /* absolute pidl of the item */
103 } SFOLDER
,*LPSFOLDER
;
105 typedef struct tagLookInInfo
111 typedef struct tagFD32_PRIVATE
113 OPENFILENAMEA
*ofnA
; /* original structure if 32bits ansi dialog */
114 } FD32_PRIVATE
, *PFD32_PRIVATE
;
117 /***********************************************************************
118 * Defines and global variables
121 /* Draw item constant */
123 #define XTEXTOFFSET 3
128 /* SearchItem methods */
129 #define SEARCH_PIDL 1
131 #define ITEM_NOTFOUND -1
133 /* Undefined windows message sent by CreateViewObject*/
134 #define WM_GETISHELLBROWSER WM_USER+7
137 * Those macros exist in windowsx.h. However, you can't really use them since
138 * they rely on the UNICODE defines and can't be used inside Wine itself.
141 /* Combo box macros */
142 #define CBAddString(hwnd,str) \
143 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
144 #define CBAddStringW(hwnd,str) \
145 SendMessageW(hwnd,CB_ADDSTRING,0,(LPARAM)str);
147 #define CBInsertString(hwnd,str,pos) \
148 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
150 #define CBDeleteString(hwnd,pos) \
151 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
153 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
154 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
156 #define CBGetItemDataPtr(hwnd,iItemId) \
157 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
159 #define CBGetLBText(hwnd,iItemId,str) \
160 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
162 #define CBGetCurSel(hwnd) \
163 SendMessageA(hwnd,CB_GETCURSEL,0,0);
165 #define CBSetCurSel(hwnd,pos) \
166 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
168 #define CBGetCount(hwnd) \
169 SendMessageA(hwnd,CB_GETCOUNT,0,0);
170 #define CBShowDropDown(hwnd,show) \
171 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
172 #define CBSetItemHeight(hwnd,index,height) \
173 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
175 #define CBSetExtendedUI(hwnd,flag) \
176 SendMessageA(hwnd,CB_SETEXTENDEDUI,(WPARAM)(flag),0)
178 const char *FileOpenDlgInfosStr
= "FileOpenDlgInfos"; /* windows property description string */
179 const char *LookInInfosStr
= "LookInInfos"; /* LOOKIN combo box property */
181 /***********************************************************************
185 /* Internal functions used by the dialog */
186 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
187 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
188 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
);
189 BOOL
FILEDLG95_OnOpen(HWND hwnd
);
190 static LRESULT
FILEDLG95_InitControls(HWND hwnd
);
191 static void FILEDLG95_Clean(HWND hwnd
);
193 /* Functions used by the shell navigation */
194 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
);
195 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
);
196 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
);
197 static void FILEDLG95_SHELL_Clean(HWND hwnd
);
198 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
);
200 /* Functions used by the EDIT box */
201 static int FILEDLG95_FILENAME_GetFileNames (HWND hwnd
, LPWSTR
* lpstrFileList
, UINT
* sizeUsed
, char separator
);
203 /* Functions used by the filetype combo box */
204 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
);
205 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
);
206 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
);
207 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
);
209 /* Functions used by the Look In combo box */
210 static void FILEDLG95_LOOKIN_Init(HWND hwndCombo
);
211 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
);
212 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
);
213 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
);
214 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
);
215 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
);
216 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
);
217 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
);
218 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
);
220 /* Miscellaneous tool functions */
221 static HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
);
222 IShellFolder
* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
);
223 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
);
224 LPITEMIDLIST
GetPidlFromName(IShellFolder
*psf
,LPWSTR lpcstrFileName
);
226 /* Shell memory allocation */
227 static void *MemAlloc(UINT size
);
228 static void MemFree(void *mem
);
230 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
231 void SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
);
232 static INT_PTR
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
233 static BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
);
234 static BOOL
BrowseSelectedFolder(HWND hwnd
);
236 /***********************************************************************
239 * Creates an Open common dialog box that lets the user select
240 * the drive, directory, and the name of a file or set of files to open.
242 * IN : The FileOpenDlgInfos structure associated with the dialog
243 * OUT : TRUE on success
244 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
246 static BOOL WINAPI
GetFileName95(FileOpenDlgInfos
*fodInfos
)
255 /* test for missing functionality */
256 if (fodInfos
->ofnInfos
->Flags
& UNIMPLEMENTED_FLAGS
)
258 FIXME("Flags 0x%08lx not yet implemented\n",
259 fodInfos
->ofnInfos
->Flags
& UNIMPLEMENTED_FLAGS
);
262 /* Create the dialog from a template */
264 if(!(hRes
= FindResourceA(COMDLG32_hInstance
,MAKEINTRESOURCEA(NEWFILEOPENORD
),(LPSTR
)RT_DIALOG
)))
266 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
269 if (!(hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hRes
)) ||
270 !(template = LockResource( hDlgTmpl
)))
272 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
276 /* old style hook messages */
277 if (IsHooked(fodInfos
))
279 fodInfos
->HookMsg
.fileokstring
= RegisterWindowMessageA(FILEOKSTRINGA
);
280 fodInfos
->HookMsg
.lbselchstring
= RegisterWindowMessageA(LBSELCHSTRINGA
);
281 fodInfos
->HookMsg
.helpmsgstring
= RegisterWindowMessageA(HELPMSGSTRINGA
);
282 fodInfos
->HookMsg
.sharevistring
= RegisterWindowMessageA(SHAREVISTRINGA
);
285 /* Some shell namespace extensions depend on COM being initialized. */
286 hr
= OleInitialize(NULL
);
288 lRes
= DialogBoxIndirectParamA(COMDLG32_hInstance
,
289 (LPDLGTEMPLATEA
) template,
290 fodInfos
->ofnInfos
->hwndOwner
,
296 /* Unable to create the dialog */
303 /***********************************************************************
306 * Call GetFileName95 with this structure and clean the memory.
308 * IN : The OPENFILENAMEA initialisation structure passed to
309 * GetOpenFileNameA win api function (see filedlg.c)
311 BOOL WINAPI
GetFileDialog95A(LPOPENFILENAMEA ofn
,UINT iDlgType
)
314 FileOpenDlgInfos fodInfos
;
315 LPSTR lpstrSavDir
= NULL
;
317 LPWSTR defext
= NULL
;
318 LPWSTR filter
= NULL
;
319 LPWSTR customfilter
= NULL
;
321 /* Initialize FileOpenDlgInfos structure */
322 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
324 /* Pass in the original ofn */
325 fodInfos
.ofnInfos
= (LPOPENFILENAMEW
)ofn
;
327 /* save current directory */
328 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
330 lpstrSavDir
= MemAlloc(MAX_PATH
);
331 GetCurrentDirectoryA(MAX_PATH
, lpstrSavDir
);
334 fodInfos
.unicode
= FALSE
;
336 /* convert all the input strings to unicode */
337 if(ofn
->lpstrInitialDir
)
339 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, NULL
, 0 );
340 fodInfos
.initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
341 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, fodInfos
.initdir
, len
);
344 fodInfos
.initdir
= NULL
;
348 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
349 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFile
, -1, fodInfos
.filename
, ofn
->nMaxFile
);
352 fodInfos
.filename
= NULL
;
356 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, NULL
, 0 );
357 defext
= MemAlloc((len
+1)*sizeof(WCHAR
));
358 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, defext
, len
);
360 fodInfos
.defext
= defext
;
364 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, NULL
, 0 );
365 title
= MemAlloc((len
+1)*sizeof(WCHAR
));
366 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, title
, len
);
368 fodInfos
.title
= title
;
370 if (ofn
->lpstrFilter
)
375 /* filter is a list... title\0ext\0......\0\0 */
376 s
= ofn
->lpstrFilter
;
377 while (*s
) s
= s
+strlen(s
)+1;
379 n
= s
- ofn
->lpstrFilter
;
380 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, NULL
, 0 );
381 filter
= MemAlloc(len
*sizeof(WCHAR
));
382 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, filter
, len
);
384 fodInfos
.filter
= filter
;
386 /* convert lpstrCustomFilter */
387 if (ofn
->lpstrCustomFilter
)
392 /* customfilter contains a pair of strings... title\0ext\0 */
393 s
= ofn
->lpstrCustomFilter
;
394 if (*s
) s
= s
+strlen(s
)+1;
395 if (*s
) s
= s
+strlen(s
)+1;
396 n
= s
- ofn
->lpstrCustomFilter
;
397 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, NULL
, 0 );
398 customfilter
= MemAlloc(len
*sizeof(WCHAR
));
399 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, customfilter
, len
);
401 fodInfos
.customfilter
= customfilter
;
403 /* Initialize the dialog property */
404 fodInfos
.DlgInfos
.dwDlgProp
= 0;
405 fodInfos
.DlgInfos
.hwndCustomDlg
= NULL
;
410 ret
= GetFileName95(&fodInfos
);
413 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
414 ret
= GetFileName95(&fodInfos
);
422 SetCurrentDirectoryA(lpstrSavDir
);
423 MemFree(lpstrSavDir
);
433 MemFree(customfilter
);
435 MemFree(fodInfos
.initdir
);
437 if(fodInfos
.filename
)
438 MemFree(fodInfos
.filename
);
440 TRACE("selected file: %s\n",ofn
->lpstrFile
);
445 /***********************************************************************
448 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
449 * Call GetFileName95 with this structure and clean the memory.
452 BOOL WINAPI
GetFileDialog95W(LPOPENFILENAMEW ofn
,UINT iDlgType
)
455 FileOpenDlgInfos fodInfos
;
456 LPWSTR lpstrSavDir
= NULL
;
458 /* Initialize FileOpenDlgInfos structure */
459 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
461 /* Pass in the original ofn */
462 fodInfos
.ofnInfos
= ofn
;
464 fodInfos
.title
= ofn
->lpstrTitle
;
465 fodInfos
.defext
= ofn
->lpstrDefExt
;
466 fodInfos
.filter
= ofn
->lpstrFilter
;
467 fodInfos
.customfilter
= ofn
->lpstrCustomFilter
;
469 /* convert string arguments, save others */
472 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
473 lstrcpynW(fodInfos
.filename
,ofn
->lpstrFile
,ofn
->nMaxFile
);
476 fodInfos
.filename
= NULL
;
478 if(ofn
->lpstrInitialDir
)
480 /* fodInfos.initdir = strdupW(ofn->lpstrInitialDir); */
481 DWORD len
= strlenW(ofn
->lpstrInitialDir
)+1;
482 fodInfos
.initdir
= MemAlloc(len
*sizeof(WCHAR
));
483 memcpy(fodInfos
.initdir
,ofn
->lpstrInitialDir
,len
*sizeof(WCHAR
));
486 fodInfos
.initdir
= NULL
;
488 /* save current directory */
489 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
491 lpstrSavDir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
492 GetCurrentDirectoryW(MAX_PATH
, lpstrSavDir
);
495 fodInfos
.unicode
= TRUE
;
500 ret
= GetFileName95(&fodInfos
);
503 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
504 ret
= GetFileName95(&fodInfos
);
512 SetCurrentDirectoryW(lpstrSavDir
);
513 MemFree(lpstrSavDir
);
516 /* restore saved IN arguments and convert OUT arguments back */
517 MemFree(fodInfos
.filename
);
518 MemFree(fodInfos
.initdir
);
522 /******************************************************************************
523 * COMDLG32_GetDisplayNameOf [internal]
525 * Helper function to get the display name for a pidl.
527 static BOOL
COMDLG32_GetDisplayNameOf(LPCITEMIDLIST pidl
, LPWSTR pwszPath
) {
528 LPSHELLFOLDER psfDesktop
;
531 if (FAILED(SHGetDesktopFolder(&psfDesktop
)))
534 if (FAILED(IShellFolder_GetDisplayNameOf(psfDesktop
, pidl
, SHGDN_FORPARSING
, &strret
))) {
535 IShellFolder_Release(psfDesktop
);
539 IShellFolder_Release(psfDesktop
);
540 return SUCCEEDED(StrRetToBufW(&strret
, pidl
, pwszPath
, MAX_PATH
));
543 /***********************************************************************
544 * ArrangeCtrlPositions [internal]
546 * NOTE: Do not change anything here without a lot of testing.
548 static void ArrangeCtrlPositions(HWND hwndChildDlg
, HWND hwndParentDlg
, BOOL hide_help
)
550 HWND hwndChild
, hwndStc32
;
551 RECT rectParent
, rectChild
, rectStc32
;
552 INT help_fixup
= 0, child_height_fixup
= 0, child_width_fixup
= 0;
554 /* Take into account if open as read only checkbox and help button
559 RECT rectHelp
, rectCancel
;
560 GetWindowRect(GetDlgItem(hwndParentDlg
, pshHelp
), &rectHelp
);
561 GetWindowRect(GetDlgItem(hwndParentDlg
, IDCANCEL
), &rectCancel
);
562 /* subtract the height of the help button plus the space between
563 * the help button and the cancel button to the height of the dialog
565 help_fixup
= rectHelp
.bottom
- rectCancel
.bottom
;
569 There are two possibilities to add components to the default file dialog box.
571 By default, all the new components are added below the standard dialog box (the else case).
573 However, if there is a static text component with the stc32 id, a special case happens.
574 The x and y coordinates of stc32 indicate the top left corner where to place the standard file dialog box
575 in the window and the cx and cy indicate how to size the window.
576 Moreover, if the new component's coordinates are on the left of the stc32 , it is placed on the left
577 of the standard file dialog box. If they are above the stc32 component, it is placed above and so on....
581 GetClientRect(hwndParentDlg
, &rectParent
);
583 /* when arranging controls we have to use fixed parent size */
584 rectParent
.bottom
-= help_fixup
;
586 hwndStc32
= GetDlgItem(hwndChildDlg
, stc32
);
589 GetWindowRect(hwndStc32
, &rectStc32
);
590 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectStc32
, 2);
592 /* set the size of the stc32 control according to the size of
593 * client area of the parent dialog
595 SetWindowPos(hwndStc32
, 0,
597 rectParent
.right
, rectParent
.bottom
,
598 SWP_NOMOVE
| SWP_NOZORDER
);
601 SetRectEmpty(&rectStc32
);
603 /* this part moves controls of the child dialog */
604 hwndChild
= GetWindow(hwndChildDlg
, GW_CHILD
);
607 if (hwndChild
!= hwndStc32
)
609 GetWindowRect(hwndChild
, &rectChild
);
610 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectChild
, 2);
612 /* move only if stc32 exist */
613 if (hwndStc32
&& rectChild
.left
> rectStc32
.right
)
615 LONG old_left
= rectChild
.left
;
617 /* move to the right of visible controls of the parent dialog */
618 rectChild
.left
+= rectParent
.right
;
619 rectChild
.left
-= rectStc32
.right
;
621 child_width_fixup
= rectChild
.left
- old_left
;
623 /* move even if stc32 doesn't exist */
624 if (rectChild
.top
>= rectStc32
.bottom
)
626 LONG old_top
= rectChild
.top
;
628 /* move below visible controls of the parent dialog */
629 rectChild
.top
+= rectParent
.bottom
;
630 rectChild
.top
-= rectStc32
.bottom
- rectStc32
.top
;
632 child_height_fixup
= rectChild
.top
- old_top
;
635 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
636 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
638 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
641 /* this part moves controls of the parent dialog */
642 hwndChild
= GetWindow(hwndParentDlg
, GW_CHILD
);
645 if (hwndChild
!= hwndChildDlg
)
647 GetWindowRect(hwndChild
, &rectChild
);
648 MapWindowPoints(0, hwndParentDlg
, (LPPOINT
)&rectChild
, 2);
650 /* left,top of stc32 marks the position of controls
651 * from the parent dialog
653 rectChild
.left
+= rectStc32
.left
;
654 rectChild
.top
+= rectStc32
.top
;
656 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
657 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
659 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
662 /* calculate the size of the resulting dialog */
664 /* here we have to use original parent size */
665 GetClientRect(hwndParentDlg
, &rectParent
);
666 GetClientRect(hwndChildDlg
, &rectChild
);
670 rectChild
.right
+= child_width_fixup
;
671 rectChild
.bottom
+= child_height_fixup
;
673 if (rectParent
.right
> rectChild
.right
)
675 rectParent
.right
+= rectChild
.right
;
676 rectParent
.right
-= rectStc32
.right
- rectStc32
.left
;
680 rectParent
.right
= rectChild
.right
;
683 if (rectParent
.bottom
> rectChild
.bottom
)
685 rectParent
.bottom
+= rectChild
.bottom
;
686 rectParent
.bottom
-= rectStc32
.bottom
- rectStc32
.top
;
690 /* child dialog is higher, unconditionally set new dialog
691 * height to its size (help_fixup will be subtracted below)
693 rectParent
.bottom
= rectChild
.bottom
+ help_fixup
;
698 rectParent
.bottom
+= rectChild
.bottom
;
701 /* finally use fixed parent size */
702 rectParent
.bottom
-= help_fixup
;
704 /* set the size of the parent dialog */
705 AdjustWindowRectEx(&rectParent
, GetWindowLongW(hwndParentDlg
, GWL_STYLE
),
706 FALSE
, GetWindowLongW(hwndParentDlg
, GWL_EXSTYLE
));
707 SetWindowPos(hwndParentDlg
, 0,
709 rectParent
.right
- rectParent
.left
,
710 rectParent
.bottom
- rectParent
.top
,
711 SWP_NOMOVE
| SWP_NOZORDER
);
714 static INT_PTR CALLBACK
FileOpenDlgProcUserTemplate(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
723 static HWND
CreateTemplateDialog(FileOpenDlgInfos
*fodInfos
, HWND hwnd
)
733 * If OFN_ENABLETEMPLATEHANDLE is specified, the OPENFILENAME
734 * structure's hInstance parameter is not a HINSTANCE, but
735 * instead a pointer to a template resource to use.
737 if (fodInfos
->ofnInfos
->Flags
& (OFN_ENABLETEMPLATE
| OFN_ENABLETEMPLATEHANDLE
))
740 if (fodInfos
->ofnInfos
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
743 if( !(template = LockResource( fodInfos
->ofnInfos
->hInstance
)))
745 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
751 hinst
= fodInfos
->ofnInfos
->hInstance
;
752 if(fodInfos
->unicode
)
754 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
755 hRes
= FindResourceW( hinst
, ofn
->lpTemplateName
, (LPWSTR
)RT_DIALOG
);
759 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
760 hRes
= FindResourceA( hinst
, ofn
->lpTemplateName
, (LPSTR
)RT_DIALOG
);
764 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
767 if (!(hDlgTmpl
= LoadResource( hinst
, hRes
)) ||
768 !(template = LockResource( hDlgTmpl
)))
770 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
774 hChildDlg
= CreateDialogIndirectParamA(COMDLG32_hInstance
, template, hwnd
,
775 IsHooked(fodInfos
) ? (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
: FileOpenDlgProcUserTemplate
,
776 (LPARAM
)fodInfos
->ofnInfos
);
779 ShowWindow(hChildDlg
,SW_SHOW
);
783 else if( IsHooked(fodInfos
))
788 WORD menu
,class,title
;
790 GetClientRect(hwnd
,&rectHwnd
);
791 temp
.tmplate
.style
= WS_CHILD
| WS_CLIPSIBLINGS
| WS_VISIBLE
| DS_CONTROL
| DS_3DLOOK
;
792 temp
.tmplate
.dwExtendedStyle
= 0;
793 temp
.tmplate
.cdit
= 0;
798 temp
.menu
= temp
.class = temp
.title
= 0;
800 hChildDlg
= CreateDialogIndirectParamA(COMDLG32_hInstance
, &temp
.tmplate
,
801 hwnd
, (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
, (LPARAM
)fodInfos
->ofnInfos
);
808 /***********************************************************************
809 * SendCustomDlgNotificationMessage
811 * Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
814 void SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
)
816 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwndParentDlg
,FileOpenDlgInfosStr
);
818 TRACE("%p 0x%04x\n",hwndParentDlg
, uCode
);
820 if(!fodInfos
) return;
822 if(fodInfos
->DlgInfos
.hwndCustomDlg
)
824 TRACE("CALL NOTIFY for %x\n", uCode
);
825 if(fodInfos
->unicode
)
828 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
829 ofnNotify
.hdr
.idFrom
=0;
830 ofnNotify
.hdr
.code
= uCode
;
831 ofnNotify
.lpOFN
= fodInfos
->ofnInfos
;
832 ofnNotify
.pszFile
= NULL
;
833 SendMessageW(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
838 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
839 ofnNotify
.hdr
.idFrom
=0;
840 ofnNotify
.hdr
.code
= uCode
;
841 ofnNotify
.lpOFN
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
842 ofnNotify
.pszFile
= NULL
;
843 SendMessageA(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
845 TRACE("RET NOTIFY\n");
849 static INT_PTR
FILEDLG95_Handle_GetFilePath(HWND hwnd
, DWORD size
, LPVOID buffer
)
851 UINT sizeUsed
= 0, n
, total
;
852 LPWSTR lpstrFileList
= NULL
;
853 WCHAR lpstrCurrentDir
[MAX_PATH
];
854 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
856 TRACE("CDM_GETFILEPATH:\n");
858 if ( ! (fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
861 /* get path and filenames */
862 COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrCurrentDir
);
863 n
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
, ' ');
865 TRACE("path >%s< filespec >%s< %d files\n",
866 debugstr_w(lpstrCurrentDir
),debugstr_w(lpstrFileList
),n
);
868 if( fodInfos
->unicode
)
870 LPWSTR bufW
= buffer
;
871 total
= strlenW(lpstrCurrentDir
) + 1 + sizeUsed
;
873 /* Prepend the current path */
874 n
= strlenW(lpstrCurrentDir
) + 1;
875 memcpy( bufW
, lpstrCurrentDir
, min(n
,size
) * sizeof(WCHAR
));
878 /* 'n' includes trailing \0 */
880 memcpy( &bufW
[n
], lpstrFileList
, (size
-n
)*sizeof(WCHAR
) );
882 TRACE("returned -> %s\n",debugstr_wn(bufW
, total
));
887 total
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
888 NULL
, 0, NULL
, NULL
);
889 total
+= WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
890 NULL
, 0, NULL
, NULL
);
892 /* Prepend the current path */
893 n
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
894 bufA
, size
, NULL
, NULL
);
898 /* 'n' includes trailing \0 */
900 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
901 &bufA
[n
], size
-n
, NULL
, NULL
);
904 TRACE("returned -> %s\n",debugstr_an(bufA
, total
));
906 MemFree(lpstrFileList
);
911 static INT_PTR
FILEDLG95_Handle_GetFileSpec(HWND hwnd
, DWORD size
, LPVOID buffer
)
914 LPWSTR lpstrFileList
= NULL
;
915 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
917 TRACE("CDM_GETSPEC:\n");
919 FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
, ' ');
920 if( fodInfos
->unicode
)
922 LPWSTR bufW
= buffer
;
923 memcpy( bufW
, lpstrFileList
, sizeof(WCHAR
)*sizeUsed
);
928 sizeUsed
= WideCharToMultiByte( CP_ACP
, 0, lpstrFileList
, sizeUsed
,
929 NULL
, 0, NULL
, NULL
);
930 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
931 bufA
, size
, NULL
, NULL
);
933 MemFree(lpstrFileList
);
938 /***********************************************************************
939 * FILEDLG95_HandleCustomDialogMessages
941 * Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
943 static INT_PTR
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
945 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
946 WCHAR lpstrPath
[MAX_PATH
];
949 if(!fodInfos
) return FALSE
;
953 case CDM_GETFILEPATH
:
954 retval
= FILEDLG95_Handle_GetFilePath(hwnd
, (UINT
)wParam
, (LPVOID
)lParam
);
957 case CDM_GETFOLDERPATH
:
958 TRACE("CDM_GETFOLDERPATH:\n");
959 COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPath
);
962 if (fodInfos
->unicode
)
963 lstrcpynW((LPWSTR
)lParam
, lpstrPath
, (int)wParam
);
965 WideCharToMultiByte(CP_ACP
, 0, lpstrPath
, -1,
966 (LPSTR
)lParam
, (int)wParam
, NULL
, NULL
);
968 retval
= strlenW(lpstrPath
);
972 retval
= FILEDLG95_Handle_GetFileSpec(hwnd
, (UINT
)wParam
, (LPSTR
)lParam
);
975 case CDM_SETCONTROLTEXT
:
976 TRACE("CDM_SETCONTROLTEXT:\n");
979 if( fodInfos
->unicode
)
980 SetDlgItemTextW( hwnd
, (UINT
) wParam
, (LPWSTR
) lParam
);
982 SetDlgItemTextA( hwnd
, (UINT
) wParam
, (LPSTR
) lParam
);
987 case CDM_HIDECONTROL
:
989 FIXME("CDM_HIDECONTROL,CDM_SETCONTROLTEXT,CDM_SETDEFEXT not implemented\n");
996 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, retval
);
1000 /***********************************************************************
1003 * File open dialog procedure
1005 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1008 TRACE("0x%04x 0x%04x\n", hwnd
, uMsg
);
1015 FileOpenDlgInfos
* fodInfos
= (FileOpenDlgInfos
*)lParam
;
1017 /* Adds the FileOpenDlgInfos in the property list of the dialog
1018 so it will be easily accessible through a GetPropA(...) */
1019 SetPropA(hwnd
, FileOpenDlgInfosStr
, (HANDLE
) fodInfos
);
1021 fodInfos
->DlgInfos
.hwndCustomDlg
=
1022 CreateTemplateDialog((FileOpenDlgInfos
*)lParam
, hwnd
);
1024 FILEDLG95_InitControls(hwnd
);
1026 if (fodInfos
->DlgInfos
.hwndCustomDlg
)
1029 UINT flags
= SWP_NOACTIVATE
;
1031 ArrangeCtrlPositions(fodInfos
->DlgInfos
.hwndCustomDlg
, hwnd
,
1032 (fodInfos
->ofnInfos
->Flags
& (OFN_HIDEREADONLY
| OFN_SHOWHELP
)) == OFN_HIDEREADONLY
);
1034 /* resize the custom dialog to the parent size */
1035 if (fodInfos
->ofnInfos
->Flags
& (OFN_ENABLETEMPLATE
| OFN_ENABLETEMPLATEHANDLE
))
1036 GetClientRect(hwnd
, &rc
);
1039 /* our own fake template is zero sized and doesn't have
1040 * children, so there is no need to resize it.
1041 * Picasa depends on it.
1043 flags
|= SWP_NOSIZE
;
1046 SetWindowPos(fodInfos
->DlgInfos
.hwndCustomDlg
, HWND_BOTTOM
,
1047 0, 0, rc
.right
, rc
.bottom
, flags
);
1050 FILEDLG95_FillControls(hwnd
, wParam
, lParam
);
1052 SendCustomDlgNotificationMessage(hwnd
,CDN_INITDONE
);
1053 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
1054 SendCustomDlgNotificationMessage(hwnd
,CDN_SELCHANGE
);
1058 return FILEDLG95_OnWMCommand(hwnd
, wParam
, lParam
);
1061 switch(((LPDRAWITEMSTRUCT
)lParam
)->CtlID
)
1064 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT
) lParam
);
1070 case WM_GETISHELLBROWSER
:
1071 return FILEDLG95_OnWMGetIShellBrowser(hwnd
);
1074 RemovePropA(hwnd
, FileOpenDlgInfosStr
);
1079 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
1082 /* set up the button tooltips strings */
1083 if(TTN_GETDISPINFOA
== lpnmh
->code
)
1085 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
1086 switch(lpnmh
->idFrom
)
1088 /* Up folder button */
1089 case FCIDM_TB_UPFOLDER
:
1090 stringId
= IDS_UPFOLDER
;
1092 /* New folder button */
1093 case FCIDM_TB_NEWFOLDER
:
1094 stringId
= IDS_NEWFOLDER
;
1096 /* List option button */
1097 case FCIDM_TB_SMALLICON
:
1098 stringId
= IDS_LISTVIEW
;
1100 /* Details option button */
1101 case FCIDM_TB_REPORTVIEW
:
1102 stringId
= IDS_REPORTVIEW
;
1104 /* Desktop button */
1105 case FCIDM_TB_DESKTOP
:
1106 stringId
= IDS_TODESKTOP
;
1111 lpdi
->hinst
= COMDLG32_hInstance
;
1112 lpdi
->lpszText
= MAKEINTRESOURCEA(stringId
);
1117 if(uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
1118 return FILEDLG95_HandleCustomDialogMessages(hwnd
, uMsg
, wParam
, lParam
);
1123 /***********************************************************************
1124 * FILEDLG95_InitControls
1126 * WM_INITDIALOG message handler (before hook notification)
1128 static LRESULT
FILEDLG95_InitControls(HWND hwnd
)
1130 int win2000plus
= 0;
1132 int handledPath
= FALSE
;
1133 OSVERSIONINFOA osVi
;
1134 static const WCHAR szwSlash
[] = { '\\', 0 };
1135 static const WCHAR szwStar
[] = { '*',0 };
1139 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1140 {VIEW_PARENTFOLDER
, FCIDM_TB_UPFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1141 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1142 {VIEW_NEWFOLDER
+1, FCIDM_TB_DESKTOP
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1143 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1144 {VIEW_NEWFOLDER
, FCIDM_TB_NEWFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1145 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1146 {VIEW_LIST
, FCIDM_TB_SMALLICON
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1147 {VIEW_DETAILS
, FCIDM_TB_REPORTVIEW
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1152 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1154 tba
[0].hInst
= HINST_COMMCTRL
;
1155 tba
[0].nID
= IDB_VIEW_SMALL_COLOR
;
1156 tba
[1].hInst
= COMDLG32_hInstance
;
1159 TRACE("%p\n", fodInfos
);
1161 /* Get windows version emulating */
1162 osVi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
1163 GetVersionExA(&osVi
);
1164 if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
) {
1165 win98plus
= ((osVi
.dwMajorVersion
> 4) || ((osVi
.dwMajorVersion
== 4) && (osVi
.dwMinorVersion
> 0)));
1166 } else if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1167 win2000plus
= (osVi
.dwMajorVersion
> 4);
1168 if (win2000plus
) win98plus
= TRUE
;
1170 TRACE("Running on 2000+ %d, 98+ %d\n", win2000plus
, win98plus
);
1172 /* Get the hwnd of the controls */
1173 fodInfos
->DlgInfos
.hwndFileName
= GetDlgItem(hwnd
,IDC_FILENAME
);
1174 fodInfos
->DlgInfos
.hwndFileTypeCB
= GetDlgItem(hwnd
,IDC_FILETYPE
);
1175 fodInfos
->DlgInfos
.hwndLookInCB
= GetDlgItem(hwnd
,IDC_LOOKIN
);
1177 GetWindowRect( fodInfos
->DlgInfos
.hwndLookInCB
,&rectlook
);
1178 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectlook
,2);
1180 /* construct the toolbar */
1181 GetWindowRect(GetDlgItem(hwnd
,IDC_TOOLBARSTATIC
),&rectTB
);
1182 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectTB
,2);
1184 rectTB
.right
= rectlook
.right
+ rectTB
.right
- rectTB
.left
;
1185 rectTB
.bottom
= rectlook
.top
- 1 + rectTB
.bottom
- rectTB
.top
;
1186 rectTB
.left
= rectlook
.right
;
1187 rectTB
.top
= rectlook
.top
-1;
1189 fodInfos
->DlgInfos
.hwndTB
= CreateWindowExA(0, TOOLBARCLASSNAMEA
, NULL
,
1190 WS_CHILD
| WS_GROUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NORESIZE
,
1191 rectTB
.left
, rectTB
.top
,
1192 rectTB
.right
- rectTB
.left
, rectTB
.bottom
- rectTB
.top
,
1193 hwnd
, (HMENU
)IDC_TOOLBAR
, COMDLG32_hInstance
, NULL
);
1195 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_BUTTONSTRUCTSIZE
, (WPARAM
) sizeof(TBBUTTON
), 0);
1197 /* FIXME: use TB_LOADIMAGES when implemented */
1198 /* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1199 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 12, (LPARAM
) &tba
[0]);
1200 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 1, (LPARAM
) &tba
[1]);
1202 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBUTTONSA
, (WPARAM
) 9,(LPARAM
) &tbb
);
1203 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_AUTOSIZE
, 0, 0);
1205 /* Set the window text with the text specified in the OPENFILENAME structure */
1208 SetWindowTextW(hwnd
,fodInfos
->title
);
1210 else if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1213 LoadStringW(COMDLG32_hInstance
, IDS_SAVE
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1214 SetWindowTextW(hwnd
, buf
);
1217 /* Initialise the file name edit control */
1218 handledPath
= FALSE
;
1219 TRACE("Before manipilation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1221 if(fodInfos
->filename
)
1223 /* 1. If win2000 or higher and filename contains a path, use it
1224 in preference over the lpstrInitialDir */
1225 if (win2000plus
&& *fodInfos
->filename
&& strpbrkW(fodInfos
->filename
, szwSlash
)) {
1226 WCHAR tmpBuf
[MAX_PATH
];
1230 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
, tmpBuf
, &nameBit
);
1233 /* nameBit is always shorter than the original filename */
1234 strcpyW(fodInfos
->filename
,nameBit
);
1237 if (fodInfos
->initdir
== NULL
)
1238 MemFree(fodInfos
->initdir
);
1239 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf
) + 1)*sizeof(WCHAR
));
1240 strcpyW(fodInfos
->initdir
, tmpBuf
);
1242 TRACE("Value in Filename includes path, overriding InitialDir: %s, %s\n",
1243 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1245 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1248 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1252 /* 2. (All platforms) If initdir is not null, then use it */
1253 if ((handledPath
== FALSE
) && (fodInfos
->initdir
!=NULL
) &&
1254 (*fodInfos
->initdir
!=0x00))
1256 /* Work out the proper path as supplied one might be relative */
1257 /* (Here because supplying '.' as dir browses to My Computer) */
1258 if (handledPath
==FALSE
) {
1259 WCHAR tmpBuf
[MAX_PATH
];
1260 WCHAR tmpBuf2
[MAX_PATH
];
1264 strcpyW(tmpBuf
, fodInfos
->initdir
);
1265 if( PathFileExistsW(tmpBuf
) ) {
1266 /* initdir does not have to be a directory. If a file is
1267 * specified, the dir part is taken */
1268 if( PathIsDirectoryW(tmpBuf
)) {
1269 if (tmpBuf
[strlenW(tmpBuf
)-1] != '\\') {
1270 strcatW(tmpBuf
, szwSlash
);
1272 strcatW(tmpBuf
, szwStar
);
1274 result
= GetFullPathNameW(tmpBuf
, MAX_PATH
, tmpBuf2
, &nameBit
);
1277 if (fodInfos
->initdir
)
1278 MemFree(fodInfos
->initdir
);
1279 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf2
) + 1)*sizeof(WCHAR
));
1280 strcpyW(fodInfos
->initdir
, tmpBuf2
);
1282 TRACE("Value in InitDir changed to %s\n", debugstr_w(fodInfos
->initdir
));
1285 else if (fodInfos
->initdir
)
1287 MemFree(fodInfos
->initdir
);
1288 fodInfos
->initdir
= NULL
;
1289 TRACE("Value in InitDir is not an existing path, changed to (nil)\n");
1294 if ((handledPath
== FALSE
) && ((fodInfos
->initdir
==NULL
) ||
1295 (*fodInfos
->initdir
==0x00)))
1297 /* 3. All except w2k+: if filename contains a path use it */
1298 if (!win2000plus
&& fodInfos
->filename
&&
1299 *fodInfos
->filename
&&
1300 strpbrkW(fodInfos
->filename
, szwSlash
)) {
1301 WCHAR tmpBuf
[MAX_PATH
];
1305 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
,
1310 /* nameBit is always shorter than the original filename */
1311 strcpyW(fodInfos
->filename
, nameBit
);
1314 len
= strlenW(tmpBuf
);
1315 if(fodInfos
->initdir
)
1316 MemFree(fodInfos
->initdir
);
1317 fodInfos
->initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
1318 strcpyW(fodInfos
->initdir
, tmpBuf
);
1321 TRACE("Value in Filename includes path, overriding initdir: %s, %s\n",
1322 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1324 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1327 /* 4. win98+ and win2000+ if any files of specified filter types in
1328 current directory, use it */
1329 if ( win98plus
&& handledPath
== FALSE
&&
1330 fodInfos
->filter
&& *fodInfos
->filter
) {
1332 BOOL searchMore
= TRUE
;
1333 LPCWSTR lpstrPos
= fodInfos
->filter
;
1334 WIN32_FIND_DATAW FindFileData
;
1339 /* filter is a list... title\0ext\0......\0\0 */
1341 /* Skip the title */
1342 if(! *lpstrPos
) break; /* end */
1343 lpstrPos
+= strlenW(lpstrPos
) + 1;
1345 /* See if any files exist in the current dir with this extension */
1346 if(! *lpstrPos
) break; /* end */
1348 hFind
= FindFirstFileW(lpstrPos
, &FindFileData
);
1350 if (hFind
== INVALID_HANDLE_VALUE
) {
1351 /* None found - continue search */
1352 lpstrPos
+= strlenW(lpstrPos
) + 1;
1357 if(fodInfos
->initdir
)
1358 MemFree(fodInfos
->initdir
);
1359 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1360 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1363 TRACE("No initial dir specified, but files of type %s found in current, so using it\n",
1364 debugstr_w(lpstrPos
));
1370 /* 5. Win2000+: FIXME: Next, Recently used? Not sure how windows does this */
1372 /* 6. Win98+ and 2000+: Use personal files dir, others use current dir */
1373 if (handledPath
== FALSE
&& (win2000plus
|| win98plus
)) {
1374 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1376 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_PERSONAL
, 0, 0, fodInfos
->initdir
)))
1378 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_DESKTOPDIRECTORY
|CSIDL_FLAG_CREATE
, 0, 0, fodInfos
->initdir
)))
1381 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1382 TRACE("No personal or desktop dir, using cwd as failsafe: %s\n", debugstr_w(fodInfos
->initdir
));
1384 TRACE("No personal dir, using desktop instead: %s\n", debugstr_w(fodInfos
->initdir
));
1387 TRACE("No initial dir specified, using personal files dir of %s\n", debugstr_w(fodInfos
->initdir
));
1390 } else if (handledPath
==FALSE
) {
1391 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1392 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1394 TRACE("No initial dir specified, using current dir of %s\n", debugstr_w(fodInfos
->initdir
));
1397 SetFocus(GetDlgItem(hwnd
, IDC_FILENAME
));
1398 TRACE("After manipulation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1400 /* Must the open as read only check box be checked ?*/
1401 if(fodInfos
->ofnInfos
->Flags
& OFN_READONLY
)
1403 SendDlgItemMessageA(hwnd
,IDC_OPENREADONLY
,BM_SETCHECK
,(WPARAM
)TRUE
,0);
1406 /* Must the open as read only check box be hidden? */
1407 if(fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
)
1409 ShowWindow(GetDlgItem(hwnd
,IDC_OPENREADONLY
),SW_HIDE
);
1410 EnableWindow(GetDlgItem(hwnd
, IDC_OPENREADONLY
), FALSE
);
1413 /* Must the help button be hidden? */
1414 if (!(fodInfos
->ofnInfos
->Flags
& OFN_SHOWHELP
))
1416 ShowWindow(GetDlgItem(hwnd
, pshHelp
), SW_HIDE
);
1417 EnableWindow(GetDlgItem(hwnd
, pshHelp
), FALSE
);
1420 /* Resize the height, if open as read only checkbox ad help button
1421 are hidden and we are not using a custom template nor a customDialog
1423 if ( (fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
) &&
1424 (!(fodInfos
->ofnInfos
->Flags
&
1425 (OFN_SHOWHELP
|OFN_ENABLETEMPLATE
|OFN_ENABLETEMPLATEHANDLE
))) &&
1426 (!fodInfos
->DlgInfos
.hwndCustomDlg
))
1428 RECT rectDlg
, rectHelp
, rectCancel
;
1429 GetWindowRect(hwnd
, &rectDlg
);
1430 GetWindowRect(GetDlgItem(hwnd
, pshHelp
), &rectHelp
);
1431 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rectCancel
);
1432 /* subtract the height of the help button plus the space between
1433 the help button and the cancel button to the height of the dialog */
1434 SetWindowPos(hwnd
, 0, 0, 0, rectDlg
.right
-rectDlg
.left
,
1435 (rectDlg
.bottom
-rectDlg
.top
) - (rectHelp
.bottom
- rectCancel
.bottom
),
1436 SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
);
1438 /* change Open to Save */
1439 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1442 LoadStringW(COMDLG32_hInstance
, IDS_SAVE_BUTTON
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1443 SetDlgItemTextW(hwnd
, IDOK
, buf
);
1444 LoadStringW(COMDLG32_hInstance
, IDS_SAVE_IN
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1445 SetDlgItemTextW(hwnd
, IDC_LOOKINSTATIC
, buf
);
1450 /***********************************************************************
1451 * FILEDLG95_FillControls
1453 * WM_INITDIALOG message handler (after hook notification)
1455 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1457 LPITEMIDLIST pidlItemId
= NULL
;
1459 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) lParam
;
1461 TRACE("dir=%s file=%s\n",
1462 debugstr_w(fodInfos
->initdir
), debugstr_w(fodInfos
->filename
));
1464 /* Get the initial directory pidl */
1466 if(!(pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,fodInfos
->initdir
)))
1468 WCHAR path
[MAX_PATH
];
1470 GetCurrentDirectoryW(MAX_PATH
,path
);
1471 pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, path
);
1474 /* Initialise shell objects */
1475 FILEDLG95_SHELL_Init(hwnd
);
1477 /* Initialize the Look In combo box */
1478 FILEDLG95_LOOKIN_Init(fodInfos
->DlgInfos
.hwndLookInCB
);
1480 /* Initialize the filter combo box */
1481 FILEDLG95_FILETYPE_Init(hwnd
);
1483 /* Browse to the initial directory */
1484 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,pidlItemId
, SBSP_ABSOLUTE
);
1486 /* Free pidlItem memory */
1487 COMDLG32_SHFree(pidlItemId
);
1491 /***********************************************************************
1494 * Regroups all the cleaning functions of the filedlg
1496 void FILEDLG95_Clean(HWND hwnd
)
1498 FILEDLG95_FILETYPE_Clean(hwnd
);
1499 FILEDLG95_LOOKIN_Clean(hwnd
);
1500 FILEDLG95_SHELL_Clean(hwnd
);
1502 /***********************************************************************
1503 * FILEDLG95_OnWMCommand
1505 * WM_COMMAND message handler
1507 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1509 WORD wNotifyCode
= HIWORD(wParam
); /* notification code */
1510 WORD wID
= LOWORD(wParam
); /* item, control, or accelerator identifier */
1511 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1517 FILEDLG95_OnOpen(hwnd
);
1521 FILEDLG95_Clean(hwnd
);
1522 EndDialog(hwnd
, FALSE
);
1524 /* Filetype combo box */
1526 FILEDLG95_FILETYPE_OnCommand(hwnd
,wNotifyCode
);
1528 /* LookIn combo box */
1530 FILEDLG95_LOOKIN_OnCommand(hwnd
,wNotifyCode
);
1533 /* --- toolbar --- */
1534 /* Up folder button */
1535 case FCIDM_TB_UPFOLDER
:
1536 FILEDLG95_SHELL_UpFolder(hwnd
);
1538 /* New folder button */
1539 case FCIDM_TB_NEWFOLDER
:
1540 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_NEWFOLDERA
);
1542 /* List option button */
1543 case FCIDM_TB_SMALLICON
:
1544 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWLISTA
);
1546 /* Details option button */
1547 case FCIDM_TB_REPORTVIEW
:
1548 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWDETAILSA
);
1550 /* Details option button */
1551 case FCIDM_TB_DESKTOP
:
1552 FILEDLG95_SHELL_BrowseToDesktop(hwnd
);
1559 /* Do not use the listview selection anymore */
1560 fodInfos
->DlgInfos
.dwDlgProp
&= ~FODPROP_USEVIEW
;
1564 /***********************************************************************
1565 * FILEDLG95_OnWMGetIShellBrowser
1567 * WM_GETISHELLBROWSER message handler
1569 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
)
1572 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1576 SetWindowLongPtrW(hwnd
,DWLP_MSGRESULT
,(LONG_PTR
)fodInfos
->Shell
.FOIShellBrowser
);
1582 /***********************************************************************
1583 * FILEDLG95_SendFileOK
1585 * Sends the CDN_FILEOK notification if required
1588 * TRUE if the dialog should close
1589 * FALSE if the dialog should not be closed
1591 static BOOL
FILEDLG95_SendFileOK( HWND hwnd
, FileOpenDlgInfos
*fodInfos
)
1593 /* ask the hook if we can close */
1594 if(IsHooked(fodInfos
))
1597 /* First send CDN_FILEOK as MSDN doc says */
1598 SendCustomDlgNotificationMessage(hwnd
,CDN_FILEOK
);
1599 if (GetWindowLongPtrW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWLP_MSGRESULT
))
1601 TRACE("canceled\n");
1605 /* fodInfos->ofnInfos points to an ASCII or UNICODE structure as appropriate */
1606 SendMessageW(fodInfos
->DlgInfos
.hwndCustomDlg
,
1607 fodInfos
->HookMsg
.fileokstring
, 0, (LPARAM
)fodInfos
->ofnInfos
);
1608 if (GetWindowLongPtrW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWLP_MSGRESULT
))
1610 TRACE("canceled\n");
1617 /***********************************************************************
1618 * FILEDLG95_OnOpenMultipleFiles
1620 * Handles the opening of multiple files.
1623 * check destination buffer size
1625 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
)
1627 WCHAR lpstrPathSpec
[MAX_PATH
] = {0};
1628 UINT nCount
, nSizePath
;
1629 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1633 if(fodInfos
->unicode
)
1635 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
1636 ofn
->lpstrFile
[0] = '\0';
1640 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
) fodInfos
->ofnInfos
;
1641 ofn
->lpstrFile
[0] = '\0';
1644 COMDLG32_GetDisplayNameOf( fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathSpec
);
1646 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1647 ( fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1648 ! ( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1650 LPWSTR lpstrTemp
= lpstrFileList
;
1652 for ( nCount
= 0; nCount
< nFileCount
; nCount
++ )
1656 pidl
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, lpstrTemp
);
1659 WCHAR lpstrNotFound
[100];
1660 WCHAR lpstrMsg
[100];
1662 static const WCHAR nl
[] = {'\n',0};
1664 LoadStringW(COMDLG32_hInstance
, IDS_FILENOTFOUND
, lpstrNotFound
, 100);
1665 LoadStringW(COMDLG32_hInstance
, IDS_VERIFYFILE
, lpstrMsg
, 100);
1667 strcpyW(tmp
, lpstrTemp
);
1669 strcatW(tmp
, lpstrNotFound
);
1671 strcatW(tmp
, lpstrMsg
);
1673 MessageBoxW(hwnd
, tmp
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
1677 /* move to the next file in the list of files */
1678 lpstrTemp
+= strlenW(lpstrTemp
) + 1;
1679 COMDLG32_SHFree(pidl
);
1683 nSizePath
= strlenW(lpstrPathSpec
) + 1;
1684 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
1686 /* For "oldstyle" dialog the components have to
1687 be separated by blanks (not '\0'!) and short
1688 filenames have to be used! */
1689 FIXME("Components have to be separated by blanks\n");
1691 if(fodInfos
->unicode
)
1693 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
1694 strcpyW( ofn
->lpstrFile
, lpstrPathSpec
);
1695 memcpy( ofn
->lpstrFile
+ nSizePath
, lpstrFileList
, sizeUsed
*sizeof(WCHAR
) );
1699 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
1701 if (ofn
->lpstrFile
!= NULL
)
1703 nSizePath
= WideCharToMultiByte(CP_ACP
, 0, lpstrPathSpec
, -1,
1704 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
1705 if (ofn
->nMaxFile
> nSizePath
)
1707 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
1708 ofn
->lpstrFile
+ nSizePath
,
1709 ofn
->nMaxFile
- nSizePath
, NULL
, NULL
);
1714 fodInfos
->ofnInfos
->nFileOffset
= nSizePath
;
1715 fodInfos
->ofnInfos
->nFileExtension
= 0;
1717 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
1720 /* clean and exit */
1721 FILEDLG95_Clean(hwnd
);
1722 return EndDialog(hwnd
,TRUE
);
1725 /***********************************************************************
1728 * Ok button WM_COMMAND message handler
1730 * If the function succeeds, the return value is nonzero.
1732 #define ONOPEN_BROWSE 1
1733 #define ONOPEN_OPEN 2
1734 #define ONOPEN_SEARCH 3
1735 static void FILEDLG95_OnOpenMessage(HWND hwnd
, int idCaption
, int idText
)
1737 WCHAR strMsgTitle
[MAX_PATH
];
1738 WCHAR strMsgText
[MAX_PATH
];
1740 LoadStringW(COMDLG32_hInstance
, idCaption
, strMsgTitle
, sizeof(strMsgTitle
)/sizeof(WCHAR
));
1742 strMsgTitle
[0] = '\0';
1743 LoadStringW(COMDLG32_hInstance
, idText
, strMsgText
, sizeof(strMsgText
)/sizeof(WCHAR
));
1744 MessageBoxW(hwnd
,strMsgText
, strMsgTitle
, MB_OK
| MB_ICONHAND
);
1747 BOOL
FILEDLG95_OnOpen(HWND hwnd
)
1749 LPWSTR lpstrFileList
;
1750 UINT nFileCount
= 0;
1753 WCHAR lpstrPathAndFile
[MAX_PATH
];
1754 WCHAR lpstrTemp
[MAX_PATH
];
1755 LPSHELLFOLDER lpsf
= NULL
;
1757 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1759 TRACE("hwnd=%p\n", hwnd
);
1761 /* get the files from the edit control */
1762 nFileCount
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
, '\0');
1764 /* try if the user selected a folder in the shellview */
1767 BrowseSelectedFolder(hwnd
);
1773 ret
= FILEDLG95_OnOpenMultipleFiles(hwnd
, lpstrFileList
, nFileCount
, sizeUsed
);
1777 TRACE("count=%u len=%u file=%s\n", nFileCount
, sizeUsed
, debugstr_w(lpstrFileList
));
1780 Step 1: Build a complete path name from the current folder and
1781 the filename or path in the edit box.
1783 - the path in the edit box is a root path
1784 (with or without drive letter)
1785 - the edit box contains ".." (or a path with ".." in it)
1788 /* Get the current directory name */
1789 if (!COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathAndFile
))
1792 GetCurrentDirectoryW(MAX_PATH
, lpstrPathAndFile
);
1794 PathAddBackslashW(lpstrPathAndFile
);
1796 TRACE("current directory=%s\n", debugstr_w(lpstrPathAndFile
));
1798 /* if the user specifyed a fully qualified path use it */
1799 if(PathIsRelativeW(lpstrFileList
))
1801 strcatW(lpstrPathAndFile
, lpstrFileList
);
1805 /* does the path have a drive letter? */
1806 if (PathGetDriveNumberW(lpstrFileList
) == -1)
1807 strcpyW(lpstrPathAndFile
+2, lpstrFileList
);
1809 strcpyW(lpstrPathAndFile
, lpstrFileList
);
1812 /* resolve "." and ".." */
1813 PathCanonicalizeW(lpstrTemp
, lpstrPathAndFile
);
1814 strcpyW(lpstrPathAndFile
, lpstrTemp
);
1815 TRACE("canon=%s\n", debugstr_w(lpstrPathAndFile
));
1817 MemFree(lpstrFileList
);
1820 Step 2: here we have a cleaned up path
1822 We have to parse the path step by step to see if we have to browse
1823 to a folder if the path points to a directory or the last
1824 valid element is a directory.
1827 lpstrPathAndFile: cleaned up path
1831 (fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1832 !(fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
))
1833 nOpenAction
= ONOPEN_OPEN
;
1835 nOpenAction
= ONOPEN_BROWSE
;
1837 /* don't apply any checks with OFN_NOVALIDATE */
1839 LPWSTR lpszTemp
, lpszTemp1
;
1840 LPITEMIDLIST pidl
= NULL
;
1841 static const WCHAR szwInvalid
[] = { '/',':','<','>','|', 0};
1843 /* check for invalid chars */
1844 if((strpbrkW(lpstrPathAndFile
+3, szwInvalid
) != NULL
) && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1846 FILEDLG95_OnOpenMessage(hwnd
, IDS_INVALID_FILENAME_TITLE
, IDS_INVALID_FILENAME
);
1851 if (FAILED (SHGetDesktopFolder(&lpsf
))) return FALSE
;
1853 lpszTemp1
= lpszTemp
= lpstrPathAndFile
;
1856 LPSHELLFOLDER lpsfChild
;
1857 WCHAR lpwstrTemp
[MAX_PATH
];
1858 DWORD dwEaten
, dwAttributes
;
1861 strcpyW(lpwstrTemp
, lpszTemp
);
1862 p
= PathFindNextComponentW(lpwstrTemp
);
1864 if (!p
) break; /* end of path */
1867 lpszTemp
= lpszTemp
+ strlenW(lpwstrTemp
);
1869 /* There are no wildcards when OFN_NOVALIDATE is set */
1870 if(*lpszTemp
==0 && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1872 static const WCHAR wszWild
[] = { '*', '?', 0 };
1873 /* if the last element is a wildcard do a search */
1874 if(strpbrkW(lpszTemp1
, wszWild
) != NULL
)
1876 nOpenAction
= ONOPEN_SEARCH
;
1880 lpszTemp1
= lpszTemp
;
1882 TRACE("parse now=%s next=%s sf=%p\n",debugstr_w(lpwstrTemp
), debugstr_w(lpszTemp
), lpsf
);
1884 /* append a backslash to drive letters */
1885 if(lstrlenW(lpwstrTemp
)==2 && lpwstrTemp
[1] == ':' &&
1886 ((lpwstrTemp
[0] >= 'a' && lpwstrTemp
[0] <= 'z') ||
1887 (lpwstrTemp
[0] >= 'A' && lpwstrTemp
[0] <= 'Z')))
1889 PathAddBackslashW(lpwstrTemp
);
1892 dwAttributes
= SFGAO_FOLDER
;
1893 if(SUCCEEDED(IShellFolder_ParseDisplayName(lpsf
, hwnd
, NULL
, lpwstrTemp
, &dwEaten
, &pidl
, &dwAttributes
)))
1895 /* the path component is valid, we have a pidl of the next path component */
1896 TRACE("parse OK attr=0x%08lx pidl=%p\n", dwAttributes
, pidl
);
1897 if(dwAttributes
& SFGAO_FOLDER
)
1899 if(FAILED(IShellFolder_BindToObject(lpsf
, pidl
, 0, &IID_IShellFolder
, (LPVOID
*)&lpsfChild
)))
1901 ERR("bind to failed\n"); /* should not fail */
1904 IShellFolder_Release(lpsf
);
1912 /* end dialog, return value */
1913 nOpenAction
= ONOPEN_OPEN
;
1916 COMDLG32_SHFree(pidl
);
1919 else if (!(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1921 if(*lpszTemp
) /* points to trailing null for last path element */
1923 if(fodInfos
->ofnInfos
->Flags
& OFN_PATHMUSTEXIST
)
1925 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_PATHNOTEXISTING
);
1931 if( (fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1932 !( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1934 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_FILENOTEXISTING
);
1938 /* change to the current folder */
1939 nOpenAction
= ONOPEN_OPEN
;
1944 nOpenAction
= ONOPEN_OPEN
;
1948 if(pidl
) COMDLG32_SHFree(pidl
);
1952 Step 3: here we have a cleaned up and validated path
1955 lpsf: ShellFolder bound to the rightmost valid path component
1956 lpstrPathAndFile: cleaned up path
1957 nOpenAction: action to do
1959 TRACE("end validate sf=%p\n", lpsf
);
1963 case ONOPEN_SEARCH
: /* set the current filter to the file mask and refresh */
1964 TRACE("ONOPEN_SEARCH %s\n", debugstr_w(lpstrPathAndFile
));
1967 LPWSTR lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
1970 /* replace the current filter */
1971 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
1972 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1973 len
= strlenW(lpszTemp
)+1;
1974 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc(len
* sizeof(WCHAR
));
1975 strcpyW( fodInfos
->ShellInfos
.lpstrCurrentFilter
, lpszTemp
);
1977 /* set the filter cb to the extension when possible */
1978 if(-1 < (iPos
= FILEDLG95_FILETYPE_SearchExt(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpszTemp
)))
1979 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, iPos
);
1982 case ONOPEN_BROWSE
: /* browse to the highest folder we could bind to */
1983 TRACE("ONOPEN_BROWSE\n");
1985 IPersistFolder2
* ppf2
;
1986 if(SUCCEEDED(IShellFolder_QueryInterface( lpsf
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
)))
1988 LPITEMIDLIST pidlCurrent
;
1989 IPersistFolder2_GetCurFolder(ppf2
, &pidlCurrent
);
1990 IPersistFolder2_Release(ppf2
);
1991 if( ! COMDLG32_PIDL_ILIsEqual(pidlCurrent
, fodInfos
->ShellInfos
.pidlAbsCurrent
))
1993 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidlCurrent
, SBSP_ABSOLUTE
);
1995 else if( nOpenAction
== ONOPEN_SEARCH
)
1997 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
1999 COMDLG32_SHFree(pidlCurrent
);
2004 case ONOPEN_OPEN
: /* fill in the return struct and close the dialog */
2005 TRACE("ONOPEN_OPEN %s\n", debugstr_w(lpstrPathAndFile
));
2009 /* update READONLY check box flag */
2010 if ((SendMessageA(GetDlgItem(hwnd
,IDC_OPENREADONLY
),BM_GETCHECK
,0,0) & 0x03) == BST_CHECKED
)
2011 fodInfos
->ofnInfos
->Flags
|= OFN_READONLY
;
2013 fodInfos
->ofnInfos
->Flags
&= ~OFN_READONLY
;
2015 /* Attach the file extension with file name*/
2016 ext
= PathFindExtensionW(lpstrPathAndFile
);
2019 /* if no extension is specified with file name, then */
2020 /* attach the extension from file filter or default one */
2022 WCHAR
*filterExt
= NULL
;
2023 LPWSTR lpstrFilter
= NULL
;
2024 static const WCHAR szwDot
[] = {'.',0};
2025 int PathLength
= strlenW(lpstrPathAndFile
);
2028 strcatW(lpstrPathAndFile
, szwDot
);
2030 /*Get the file extension from file type filter*/
2031 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2032 fodInfos
->ofnInfos
->nFilterIndex
-1);
2034 if (lpstrFilter
!= (LPWSTR
)CB_ERR
) /* control is not empty */
2035 filterExt
= PathFindExtensionW(lpstrFilter
);
2037 if ( filterExt
&& *filterExt
) /* attach the file extension from file type filter*/
2038 strcatW(lpstrPathAndFile
, filterExt
+ 1);
2039 else if ( fodInfos
->defext
) /* attach the default file extension*/
2040 strcatW(lpstrPathAndFile
, fodInfos
->defext
);
2042 /* In Open dialog: if file does not exist try without extension */
2043 if (!(fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) && !PathFileExistsW(lpstrPathAndFile
))
2044 lpstrPathAndFile
[PathLength
] = '\0';
2047 if (fodInfos
->defext
) /* add default extension */
2049 /* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
2052 if (!lstrcmpiW(fodInfos
->defext
, ext
))
2053 fodInfos
->ofnInfos
->Flags
&= ~OFN_EXTENSIONDIFFERENT
;
2055 fodInfos
->ofnInfos
->Flags
|= OFN_EXTENSIONDIFFERENT
;
2058 /* In Save dialog: check if the file already exists */
2059 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
2060 && fodInfos
->ofnInfos
->Flags
& OFN_OVERWRITEPROMPT
2061 && PathFileExistsW(lpstrPathAndFile
))
2063 WCHAR lpstrOverwrite
[100];
2066 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, lpstrOverwrite
, 100);
2067 answer
= MessageBoxW(hwnd
, lpstrOverwrite
, fodInfos
->title
,
2068 MB_YESNO
| MB_ICONEXCLAMATION
);
2076 /* Check that the size of the file does not exceed buffer size.
2077 (Allow for extra \0 if OFN_MULTISELECT is set.) */
2078 if(strlenW(lpstrPathAndFile
) < fodInfos
->ofnInfos
->nMaxFile
-
2079 ((fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
) ? 1 : 0))
2083 /* fill destination buffer */
2084 if (fodInfos
->ofnInfos
->lpstrFile
)
2086 if(fodInfos
->unicode
)
2088 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
2090 lstrcpynW(ofn
->lpstrFile
, lpstrPathAndFile
, ofn
->nMaxFile
);
2091 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
2092 ofn
->lpstrFile
[lstrlenW(ofn
->lpstrFile
) + 1] = '\0';
2096 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2098 WideCharToMultiByte(CP_ACP
, 0, lpstrPathAndFile
, -1,
2099 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
2100 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
2101 ofn
->lpstrFile
[lstrlenA(ofn
->lpstrFile
) + 1] = '\0';
2105 /* set filename offset */
2106 lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
2107 fodInfos
->ofnInfos
->nFileOffset
= (lpszTemp
- lpstrPathAndFile
);
2109 /* set extension offset */
2110 lpszTemp
= PathFindExtensionW(lpstrPathAndFile
);
2111 fodInfos
->ofnInfos
->nFileExtension
= (*lpszTemp
) ? (lpszTemp
- lpstrPathAndFile
) + 1 : 0;
2113 /* set the lpstrFileTitle */
2114 if(fodInfos
->ofnInfos
->lpstrFileTitle
)
2116 LPWSTR lpstrFileTitle
= PathFindFileNameW(lpstrPathAndFile
);
2117 if(fodInfos
->unicode
)
2119 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
2120 lstrcpynW(ofn
->lpstrFileTitle
, lpstrFileTitle
, ofn
->nMaxFileTitle
);
2124 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2125 WideCharToMultiByte(CP_ACP
, 0, lpstrFileTitle
, -1,
2126 ofn
->lpstrFileTitle
, ofn
->nMaxFileTitle
, NULL
, NULL
);
2130 /* copy currently selected filter to lpstrCustomFilter */
2131 if (fodInfos
->ofnInfos
->lpstrCustomFilter
)
2133 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2134 int len
= WideCharToMultiByte(CP_ACP
, 0, fodInfos
->ShellInfos
.lpstrCurrentFilter
, -1,
2135 NULL
, 0, NULL
, NULL
);
2136 if (len
+ strlen(ofn
->lpstrCustomFilter
) + 1 <= ofn
->nMaxCustFilter
)
2138 LPSTR s
= ofn
->lpstrCustomFilter
;
2139 s
+= strlen(ofn
->lpstrCustomFilter
)+1;
2140 WideCharToMultiByte(CP_ACP
, 0, fodInfos
->ShellInfos
.lpstrCurrentFilter
, -1,
2141 s
, len
, NULL
, NULL
);
2146 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
2150 FILEDLG95_Clean(hwnd
);
2151 ret
= EndDialog(hwnd
, TRUE
);
2157 size
= strlenW(lpstrPathAndFile
) + 1;
2158 if (fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
)
2160 /* return needed size in first two bytes of lpstrFile */
2161 *(WORD
*)fodInfos
->ofnInfos
->lpstrFile
= size
;
2162 FILEDLG95_Clean(hwnd
);
2163 ret
= EndDialog(hwnd
, FALSE
);
2164 COMDLG32_SetCommDlgExtendedError(FNERR_BUFFERTOOSMALL
);
2172 if(lpsf
) IShellFolder_Release(lpsf
);
2176 /***********************************************************************
2177 * FILEDLG95_SHELL_Init
2179 * Initialisation of the shell objects
2181 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
)
2183 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2188 * Initialisation of the FileOpenDialogInfos structure
2194 fodInfos
->ShellInfos
.hwndOwner
= hwnd
;
2196 /* Disable multi-select if flag not set */
2197 if (!(fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
))
2199 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_SINGLESEL
;
2201 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_AUTOARRANGE
| FWF_ALIGNLEFT
;
2202 fodInfos
->ShellInfos
.folderSettings
.ViewMode
= FVM_LIST
;
2204 /* Construct the IShellBrowser interface */
2205 fodInfos
->Shell
.FOIShellBrowser
= IShellBrowserImpl_Construct(hwnd
);
2210 /***********************************************************************
2211 * FILEDLG95_SHELL_ExecuteCommand
2213 * Change the folder option and refresh the view
2214 * If the function succeeds, the return value is nonzero.
2216 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
)
2218 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2221 TRACE("(%p,%p)\n", hwnd
, lpVerb
);
2223 if(SUCCEEDED(IShellView_GetItemObject(fodInfos
->Shell
.FOIShellView
,
2228 CMINVOKECOMMANDINFO ci
;
2229 ZeroMemory(&ci
, sizeof(CMINVOKECOMMANDINFO
));
2230 ci
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
2234 IContextMenu_InvokeCommand(pcm
, &ci
);
2235 IContextMenu_Release(pcm
);
2241 /***********************************************************************
2242 * FILEDLG95_SHELL_UpFolder
2244 * Browse to the specified object
2245 * If the function succeeds, the return value is nonzero.
2247 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
)
2249 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2253 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2257 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2263 /***********************************************************************
2264 * FILEDLG95_SHELL_BrowseToDesktop
2266 * Browse to the Desktop
2267 * If the function succeeds, the return value is nonzero.
2269 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
)
2271 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2277 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidl
);
2278 hres
= IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidl
, SBSP_ABSOLUTE
);
2279 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2280 COMDLG32_SHFree(pidl
);
2281 return SUCCEEDED(hres
);
2283 /***********************************************************************
2284 * FILEDLG95_SHELL_Clean
2286 * Cleans the memory used by shell objects
2288 static void FILEDLG95_SHELL_Clean(HWND hwnd
)
2290 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2294 COMDLG32_SHFree(fodInfos
->ShellInfos
.pidlAbsCurrent
);
2296 /* clean Shell interfaces */
2297 IShellView_DestroyViewWindow(fodInfos
->Shell
.FOIShellView
);
2298 IShellView_Release(fodInfos
->Shell
.FOIShellView
);
2299 IShellFolder_Release(fodInfos
->Shell
.FOIShellFolder
);
2300 IShellBrowser_Release(fodInfos
->Shell
.FOIShellBrowser
);
2301 if (fodInfos
->Shell
.FOIDataObject
)
2302 IDataObject_Release(fodInfos
->Shell
.FOIDataObject
);
2305 /***********************************************************************
2306 * FILEDLG95_FILETYPE_Init
2308 * Initialisation of the file type combo box
2310 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
)
2312 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2313 int nFilters
= 0; /* number of filters */
2318 if(fodInfos
->customfilter
)
2320 /* customfilter has one entry... title\0ext\0
2321 * Set first entry of combo box item with customfilter
2324 LPCWSTR lpstrPos
= fodInfos
->customfilter
;
2327 lpstrPos
+= strlenW(fodInfos
->customfilter
) + 1;
2329 /* Copy the extensions */
2330 if (! *lpstrPos
) return E_FAIL
; /* malformed filter */
2331 if (!(lpstrExt
= MemAlloc((strlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2332 strcpyW(lpstrExt
,lpstrPos
);
2334 /* Add the item at the end of the combo */
2335 CBAddStringW(fodInfos
->DlgInfos
.hwndFileTypeCB
, fodInfos
->customfilter
);
2336 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
, lpstrExt
);
2339 if(fodInfos
->filter
)
2341 LPCWSTR lpstrPos
= fodInfos
->filter
;
2345 /* filter is a list... title\0ext\0......\0\0
2346 * Set the combo item text to the title and the item data
2349 LPCWSTR lpstrDisplay
;
2353 if(! *lpstrPos
) break; /* end */
2354 lpstrDisplay
= lpstrPos
;
2355 lpstrPos
+= strlenW(lpstrPos
) + 1;
2357 /* Copy the extensions */
2358 if (! *lpstrPos
) return E_FAIL
; /* malformed filter */
2359 if (!(lpstrExt
= MemAlloc((strlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2360 strcpyW(lpstrExt
,lpstrPos
);
2361 lpstrPos
+= strlenW(lpstrPos
) + 1;
2363 /* Add the item at the end of the combo */
2364 CBAddStringW(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpstrDisplay
);
2365 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
, lpstrExt
);
2371 * Set the current filter to the one specified
2372 * in the initialisation structure
2374 if (fodInfos
->filter
|| fodInfos
->customfilter
)
2378 /* Check to make sure our index isn't out of bounds. */
2379 if ( fodInfos
->ofnInfos
->nFilterIndex
>
2380 nFilters
- (fodInfos
->customfilter
== NULL
? 0 : 1) )
2381 fodInfos
->ofnInfos
->nFilterIndex
= (fodInfos
->customfilter
== NULL
? 1 : 0);
2383 /* set default filter index */
2384 if(fodInfos
->ofnInfos
->nFilterIndex
== 0 && fodInfos
->customfilter
== NULL
)
2385 fodInfos
->ofnInfos
->nFilterIndex
= 1;
2387 /* calculate index of Combo Box item */
2388 nFilterIndexCB
= fodInfos
->ofnInfos
->nFilterIndex
;
2389 if (fodInfos
->customfilter
== NULL
)
2392 /* Set the current index selection. */
2393 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilterIndexCB
);
2395 /* Get the corresponding text string from the combo box. */
2396 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2399 if ((INT_PTR
)lpstrFilter
== CB_ERR
) /* control is empty */
2405 CharLowerW(lpstrFilter
); /* lowercase */
2406 len
= strlenW(lpstrFilter
)+1;
2407 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2408 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2411 fodInfos
->ofnInfos
->nFilterIndex
= 0;
2415 /***********************************************************************
2416 * FILEDLG95_FILETYPE_OnCommand
2418 * WM_COMMAND of the file type combo box
2419 * If the function succeeds, the return value is nonzero.
2421 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2423 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2431 /* Get the current item of the filetype combo box */
2432 int iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2434 /* set the current filter index */
2435 fodInfos
->ofnInfos
->nFilterIndex
= iItem
+
2436 (fodInfos
->customfilter
== NULL
? 1 : 0);
2438 /* Set the current filter with the current selection */
2439 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
2440 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2442 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2444 if((INT_PTR
)lpstrFilter
!= CB_ERR
)
2447 CharLowerW(lpstrFilter
); /* lowercase */
2448 len
= strlenW(lpstrFilter
)+1;
2449 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2450 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2451 SendCustomDlgNotificationMessage(hwnd
,CDN_TYPECHANGE
);
2454 /* Refresh the actual view to display the included items*/
2455 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
2460 /***********************************************************************
2461 * FILEDLG95_FILETYPE_SearchExt
2463 * searches for an extension in the filetype box
2465 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
)
2467 int i
, iCount
= CBGetCount(hwnd
);
2469 TRACE("%s\n", debugstr_w(lpstrExt
));
2471 if(iCount
!= CB_ERR
)
2473 for(i
=0;i
<iCount
;i
++)
2475 if(!lstrcmpiW(lpstrExt
,(LPWSTR
)CBGetItemDataPtr(hwnd
,i
)))
2482 /***********************************************************************
2483 * FILEDLG95_FILETYPE_Clean
2485 * Clean the memory used by the filetype combo box
2487 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
)
2489 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2491 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2495 /* Delete each string of the combo and their associated data */
2496 if(iCount
!= CB_ERR
)
2498 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2500 MemFree((LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
));
2501 CBDeleteString(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
2504 /* Current filter */
2505 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
2506 MemFree(fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2510 /***********************************************************************
2511 * FILEDLG95_LOOKIN_Init
2513 * Initialisation of the look in combo box
2516 /* Small helper function, to determine if the unixfs shell extension is rooted
2517 * at the desktop. Copied from dlls/shell32/shfldr_unixfs.c.
2519 static inline BOOL
FILEDLG95_unixfs_is_rooted_at_desktop(void) {
2521 static const WCHAR wszRootedAtDesktop
[] = { 'S','o','f','t','w','a','r','e','\\',
2522 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2523 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2524 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
2525 'N','a','m','e','S','p','a','c','e','\\','{','9','D','2','0','A','A','E','8',
2526 '-','0','6','2','5','-','4','4','B','0','-','9','C','A','7','-',
2527 '7','1','8','8','9','C','2','2','5','4','D','9','}',0 };
2529 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, wszRootedAtDesktop
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
2536 static void FILEDLG95_LOOKIN_Init(HWND hwndCombo
)
2538 IShellFolder
*psfRoot
, *psfDrives
;
2539 IEnumIDList
*lpeRoot
, *lpeDrives
;
2540 LPITEMIDLIST pidlDrives
, pidlTmp
, pidlTmp1
, pidlAbsTmp
;
2542 LookInInfos
*liInfos
= MemAlloc(sizeof(LookInInfos
));
2546 liInfos
->iMaxIndentation
= 0;
2548 SetPropA(hwndCombo
, LookInInfosStr
, (HANDLE
) liInfos
);
2550 /* set item height for both text field and listbox */
2551 CBSetItemHeight(hwndCombo
,-1,GetSystemMetrics(SM_CYSMICON
));
2552 CBSetItemHeight(hwndCombo
,0,GetSystemMetrics(SM_CYSMICON
));
2554 /* Turn on the extended UI for the combo box like Windows does */
2555 CBSetExtendedUI(hwndCombo
, TRUE
);
2557 /* Initialise data of Desktop folder */
2558 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidlTmp
);
2559 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2560 COMDLG32_SHFree(pidlTmp
);
2562 SHGetSpecialFolderLocation(0,CSIDL_DRIVES
,&pidlDrives
);
2564 SHGetDesktopFolder(&psfRoot
);
2568 /* enumerate the contents of the desktop */
2569 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot
, hwndCombo
, SHCONTF_FOLDERS
, &lpeRoot
)))
2571 while (S_OK
== IEnumIDList_Next(lpeRoot
, 1, &pidlTmp
, NULL
))
2573 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2575 /* If the unixfs extension is rooted, we don't expand the drives by default */
2576 if (!FILEDLG95_unixfs_is_rooted_at_desktop())
2578 /* special handling for CSIDL_DRIVES */
2579 if (COMDLG32_PIDL_ILIsEqual(pidlTmp
, pidlDrives
))
2581 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot
, pidlTmp
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfDrives
)))
2583 /* enumerate the drives */
2584 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives
, hwndCombo
,SHCONTF_FOLDERS
, &lpeDrives
)))
2586 while (S_OK
== IEnumIDList_Next(lpeDrives
, 1, &pidlTmp1
, NULL
))
2588 pidlAbsTmp
= COMDLG32_PIDL_ILCombine(pidlTmp
, pidlTmp1
);
2589 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlAbsTmp
,LISTEND
);
2590 COMDLG32_SHFree(pidlAbsTmp
);
2591 COMDLG32_SHFree(pidlTmp1
);
2593 IEnumIDList_Release(lpeDrives
);
2595 IShellFolder_Release(psfDrives
);
2600 COMDLG32_SHFree(pidlTmp
);
2602 IEnumIDList_Release(lpeRoot
);
2604 IShellFolder_Release(psfRoot
);
2607 COMDLG32_SHFree(pidlDrives
);
2610 /***********************************************************************
2611 * FILEDLG95_LOOKIN_DrawItem
2613 * WM_DRAWITEM message handler
2615 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
)
2617 COLORREF crWin
= GetSysColor(COLOR_WINDOW
);
2618 COLORREF crHighLight
= GetSysColor(COLOR_HIGHLIGHT
);
2619 COLORREF crText
= GetSysColor(COLOR_WINDOWTEXT
);
2623 HIMAGELIST ilItemImage
;
2626 LPSFOLDER tmpFolder
;
2629 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(pDIStruct
->hwndItem
,LookInInfosStr
);
2633 if(pDIStruct
->itemID
== -1)
2636 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(pDIStruct
->hwndItem
,
2637 pDIStruct
->itemID
)))
2641 if(pDIStruct
->itemID
== liInfos
->uSelectedItem
)
2643 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2646 sizeof (SHFILEINFOA
),
2647 SHGFI_PIDL
| SHGFI_SMALLICON
|
2648 SHGFI_OPENICON
| SHGFI_SYSICONINDEX
|
2649 SHGFI_DISPLAYNAME
);
2653 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2656 sizeof (SHFILEINFOA
),
2657 SHGFI_PIDL
| SHGFI_SMALLICON
|
2658 SHGFI_SYSICONINDEX
|
2662 /* Is this item selected ? */
2663 if(pDIStruct
->itemState
& ODS_SELECTED
)
2665 SetTextColor(pDIStruct
->hDC
,(0x00FFFFFF & ~(crText
)));
2666 SetBkColor(pDIStruct
->hDC
,crHighLight
);
2667 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_HIGHLIGHT
));
2671 SetTextColor(pDIStruct
->hDC
,crText
);
2672 SetBkColor(pDIStruct
->hDC
,crWin
);
2673 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_WINDOW
));
2676 /* Do not indent item if drawing in the edit of the combo */
2677 if(pDIStruct
->itemState
& ODS_COMBOBOXEDIT
)
2680 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2683 sizeof (SHFILEINFOA
),
2684 SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_OPENICON
2685 | SHGFI_SYSICONINDEX
| SHGFI_DISPLAYNAME
);
2690 iIndentation
= tmpFolder
->m_iIndent
;
2692 /* Draw text and icon */
2694 /* Initialise the icon display area */
2695 rectIcon
.left
= pDIStruct
->rcItem
.left
+ ICONWIDTH
/2 * iIndentation
;
2696 rectIcon
.top
= pDIStruct
->rcItem
.top
;
2697 rectIcon
.right
= rectIcon
.left
+ ICONWIDTH
;
2698 rectIcon
.bottom
= pDIStruct
->rcItem
.bottom
;
2700 /* Initialise the text display area */
2701 GetTextMetricsA(pDIStruct
->hDC
, &tm
);
2702 rectText
.left
= rectIcon
.right
;
2704 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
- tm
.tmHeight
) / 2;
2705 rectText
.right
= pDIStruct
->rcItem
.right
+ XTEXTOFFSET
;
2707 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
+ tm
.tmHeight
) / 2;
2709 /* Draw the icon from the image list */
2710 ImageList_Draw(ilItemImage
,
2717 /* Draw the associated text */
2718 if(sfi
.szDisplayName
)
2719 TextOutA(pDIStruct
->hDC
,rectText
.left
,rectText
.top
,sfi
.szDisplayName
,strlen(sfi
.szDisplayName
));
2725 /***********************************************************************
2726 * FILEDLG95_LOOKIN_OnCommand
2728 * LookIn combo box WM_COMMAND message handler
2729 * If the function succeeds, the return value is nonzero.
2731 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2733 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2735 TRACE("%p\n", fodInfos
);
2741 LPSFOLDER tmpFolder
;
2744 iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndLookInCB
);
2746 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,
2751 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2752 tmpFolder
->pidlItem
,
2755 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2765 /***********************************************************************
2766 * FILEDLG95_LOOKIN_AddItem
2768 * Adds an absolute pidl item to the lookin combo box
2769 * returns the index of the inserted item
2771 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
)
2773 LPITEMIDLIST pidlNext
;
2776 LookInInfos
*liInfos
;
2778 TRACE("%08x\n", iInsertId
);
2783 if(!(liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
)))
2786 tmpFolder
= MemAlloc(sizeof(SFOLDER
));
2787 tmpFolder
->m_iIndent
= 0;
2789 /* Calculate the indentation of the item in the lookin*/
2791 while( (pidlNext
=COMDLG32_PIDL_ILGetNext(pidlNext
)) )
2793 tmpFolder
->m_iIndent
++;
2796 tmpFolder
->pidlItem
= COMDLG32_PIDL_ILClone(pidl
);
2798 if(tmpFolder
->m_iIndent
> liInfos
->iMaxIndentation
)
2799 liInfos
->iMaxIndentation
= tmpFolder
->m_iIndent
;
2801 sfi
.dwAttributes
= SFGAO_FILESYSANCESTOR
| SFGAO_FILESYSTEM
;
2802 SHGetFileInfoA((LPSTR
)pidl
,
2806 SHGFI_DISPLAYNAME
| SHGFI_SYSICONINDEX
2807 | SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_ATTRIBUTES
| SHGFI_ATTR_SPECIFIED
);
2809 TRACE("-- Add %s attr=%08lx\n", sfi
.szDisplayName
, sfi
.dwAttributes
);
2811 if((sfi
.dwAttributes
& SFGAO_FILESYSANCESTOR
) || (sfi
.dwAttributes
& SFGAO_FILESYSTEM
))
2815 TRACE("-- Add %s at %u\n", sfi
.szDisplayName
, tmpFolder
->m_iIndent
);
2817 /* Add the item at the end of the list */
2820 iItemID
= CBAddString(hwnd
,sfi
.szDisplayName
);
2822 /* Insert the item at the iInsertId position*/
2825 iItemID
= CBInsertString(hwnd
,sfi
.szDisplayName
,iInsertId
);
2828 CBSetItemDataPtr(hwnd
,iItemID
,tmpFolder
);
2832 COMDLG32_SHFree( tmpFolder
->pidlItem
);
2833 MemFree( tmpFolder
);
2838 /***********************************************************************
2839 * FILEDLG95_LOOKIN_InsertItemAfterParent
2841 * Insert an item below its parent
2843 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
)
2846 LPITEMIDLIST pidlParent
= GetParentPidl(pidl
);
2851 iParentPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidlParent
,SEARCH_PIDL
);
2855 iParentPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidlParent
);
2858 /* Free pidlParent memory */
2859 COMDLG32_SHFree((LPVOID
)pidlParent
);
2861 return FILEDLG95_LOOKIN_AddItem(hwnd
,pidl
,iParentPos
+ 1);
2864 /***********************************************************************
2865 * FILEDLG95_LOOKIN_SelectItem
2867 * Adds an absolute pidl item to the lookin combo box
2868 * returns the index of the inserted item
2870 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
)
2873 LookInInfos
*liInfos
;
2877 iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidl
,SEARCH_PIDL
);
2879 liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2883 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
) > -1);
2884 iItemPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidl
);
2889 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2890 while(liInfos
->iMaxIndentation
> tmpFolder
->m_iIndent
)
2894 if(-1 == (iRemovedItem
= FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
)))
2896 if(iRemovedItem
< iItemPos
)
2901 CBSetCurSel(hwnd
,iItemPos
);
2902 liInfos
->uSelectedItem
= iItemPos
;
2908 /***********************************************************************
2909 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2911 * Remove the item with an expansion level over iExpansionLevel
2913 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
)
2917 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2921 if(liInfos
->iMaxIndentation
<= 2)
2924 if((iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)liInfos
->iMaxIndentation
,SEARCH_EXP
)) >=0)
2926 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2927 COMDLG32_SHFree(tmpFolder
->pidlItem
);
2929 CBDeleteString(hwnd
,iItemPos
);
2930 liInfos
->iMaxIndentation
--;
2938 /***********************************************************************
2939 * FILEDLG95_LOOKIN_SearchItem
2941 * Search for pidl in the lookin combo box
2942 * returns the index of the found item
2944 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
)
2947 int iCount
= CBGetCount(hwnd
);
2949 TRACE("0x%08x 0x%x\n",searchArg
, iSearchMethod
);
2951 if (iCount
!= CB_ERR
)
2955 LPSFOLDER tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,i
);
2957 if(iSearchMethod
== SEARCH_PIDL
&& COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST
)searchArg
,tmpFolder
->pidlItem
))
2959 if(iSearchMethod
== SEARCH_EXP
&& tmpFolder
->m_iIndent
== (int)searchArg
)
2967 /***********************************************************************
2968 * FILEDLG95_LOOKIN_Clean
2970 * Clean the memory used by the lookin combo box
2972 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
)
2974 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2976 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndLookInCB
);
2980 /* Delete each string of the combo and their associated data */
2981 if (iCount
!= CB_ERR
)
2983 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2985 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
2986 COMDLG32_SHFree(tmpFolder
->pidlItem
);
2988 CBDeleteString(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
2992 /* LookInInfos structure */
2993 RemovePropA(fodInfos
->DlgInfos
.hwndLookInCB
,LookInInfosStr
);
2996 /***********************************************************************
2997 * FILEDLG95_FILENAME_FillFromSelection
2999 * fills the edit box from the cached DataObject
3001 void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd
)
3003 FileOpenDlgInfos
*fodInfos
;
3005 UINT nFiles
= 0, nFileToOpen
, nFileSelected
, nLength
= 0;
3006 char lpstrTemp
[MAX_PATH
];
3007 LPSTR lpstrAllFile
= NULL
, lpstrCurrFile
= NULL
;
3010 fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3012 /* Count how many files we have */
3013 nFileSelected
= GetNumSelected( fodInfos
->Shell
.FOIDataObject
);
3015 /* calculate the string length, count files */
3016 if (nFileSelected
>= 1)
3018 nLength
+= 3; /* first and last quotes, trailing \0 */
3019 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
3021 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
3025 /* get the total length of the selected file names */
3026 lpstrTemp
[0] = '\0';
3027 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
3029 if ( ! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
) ) /* Ignore folders */
3031 nLength
+= strlen( lpstrTemp
) + 3;
3034 COMDLG32_SHFree( pidl
);
3039 /* allocate the buffer */
3040 if (nFiles
<= 1) nLength
= MAX_PATH
;
3041 lpstrAllFile
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nLength
);
3042 lpstrAllFile
[0] = '\0';
3044 /* Generate the string for the edit control */
3047 lpstrCurrFile
= lpstrAllFile
;
3048 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
3050 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
3054 /* get the file name */
3055 lpstrTemp
[0] = '\0';
3056 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
3058 if (! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
)) /* Ignore folders */
3062 *lpstrCurrFile
++ = '\"';
3063 strcpy( lpstrCurrFile
, lpstrTemp
);
3064 lpstrCurrFile
+= strlen( lpstrTemp
);
3065 strcpy( lpstrCurrFile
, "\" " );
3070 strcpy( lpstrAllFile
, lpstrTemp
);
3073 COMDLG32_SHFree( (LPVOID
) pidl
);
3076 SetWindowTextA( fodInfos
->DlgInfos
.hwndFileName
, lpstrAllFile
);
3078 /* Select the file name like Windows does */
3079 SendMessageA(fodInfos
->DlgInfos
.hwndFileName
, EM_SETSEL
, (WPARAM
)0, (LPARAM
)-1);
3081 HeapFree(GetProcessHeap(),0, lpstrAllFile
);
3085 /* copied from shell32 to avoid linking to it
3086 * FIXME: why? shell32 is already linked
3088 static HRESULT
COMDLG32_StrRetToStrNA (LPVOID dest
, DWORD len
, LPSTRRET src
, LPITEMIDLIST pidl
)
3093 WideCharToMultiByte(CP_ACP
, 0, src
->u
.pOleStr
, -1, (LPSTR
)dest
, len
, NULL
, NULL
);
3094 COMDLG32_SHFree(src
->u
.pOleStr
);
3098 lstrcpynA((LPSTR
)dest
, src
->u
.cStr
, len
);
3102 lstrcpynA((LPSTR
)dest
, ((LPCSTR
)&pidl
->mkid
)+src
->u
.uOffset
, len
);
3106 FIXME("unknown type!\n");
3109 *(LPSTR
)dest
= '\0';
3116 /***********************************************************************
3117 * FILEDLG95_FILENAME_GetFileNames
3119 * Copies the filenames to a delimited string list.
3120 * The delimiter is specified by the parameter 'separator',
3121 * usually either a space or a nul
3123 static int FILEDLG95_FILENAME_GetFileNames (HWND hwnd
, LPWSTR
* lpstrFileList
, UINT
* sizeUsed
, char separator
)
3125 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3126 UINT nStrCharCount
= 0; /* index in src buffer */
3127 UINT nFileIndex
= 0; /* index in dest buffer */
3128 UINT nFileCount
= 0; /* number of files */
3129 UINT nStrLen
= 0; /* length of string in edit control */
3130 LPWSTR lpstrEdit
; /* buffer for string from edit control */
3134 /* get the filenames from the edit control */
3135 nStrLen
= SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXTLENGTH
, 0, 0);
3136 lpstrEdit
= MemAlloc( (nStrLen
+1)*sizeof(WCHAR
) );
3137 GetDlgItemTextW(hwnd
, IDC_FILENAME
, lpstrEdit
, nStrLen
+1);
3139 TRACE("nStrLen=%u str=%s\n", nStrLen
, debugstr_w(lpstrEdit
));
3141 /* we might get single filename without any '"',
3142 * so we need nStrLen + terminating \0 + end-of-list \0 */
3143 *lpstrFileList
= MemAlloc( (nStrLen
+2)*sizeof(WCHAR
) );
3146 /* build delimited file list from filenames */
3147 while ( nStrCharCount
<= nStrLen
)
3149 if ( lpstrEdit
[nStrCharCount
]=='"' )
3152 while ((lpstrEdit
[nStrCharCount
]!='"') && (nStrCharCount
<= nStrLen
))
3154 (*lpstrFileList
)[nFileIndex
++] = lpstrEdit
[nStrCharCount
];
3158 (*lpstrFileList
)[nFileIndex
++] = separator
;
3165 /* single, unquoted string */
3166 if ((nStrLen
> 0) && (*sizeUsed
== 0) )
3168 strcpyW(*lpstrFileList
, lpstrEdit
);
3169 nFileIndex
= strlenW(lpstrEdit
) + 1;
3170 (*sizeUsed
) = nFileIndex
;
3175 (*lpstrFileList
)[nFileIndex
] = '\0';
3182 #define SETDefFormatEtc(fe,cf,med) \
3184 (fe).cfFormat = cf;\
3185 (fe).dwAspect = DVASPECT_CONTENT; \
3192 * DATAOBJECT Helper functions
3195 /***********************************************************************
3196 * COMCTL32_ReleaseStgMedium
3198 * like ReleaseStgMedium from ole32
3200 static void COMCTL32_ReleaseStgMedium (STGMEDIUM medium
)
3202 if(medium
.pUnkForRelease
)
3204 IUnknown_Release(medium
.pUnkForRelease
);
3208 GlobalUnlock(medium
.u
.hGlobal
);
3209 GlobalFree(medium
.u
.hGlobal
);
3213 /***********************************************************************
3214 * GetPidlFromDataObject
3216 * Return pidl(s) by number from the cached DataObject
3218 * nPidlIndex=0 gets the fully qualified root path
3220 LPITEMIDLIST
GetPidlFromDataObject ( IDataObject
*doSelected
, UINT nPidlIndex
)
3224 FORMATETC formatetc
;
3225 LPITEMIDLIST pidl
= NULL
;
3227 TRACE("sv=%p index=%u\n", doSelected
, nPidlIndex
);
3232 /* Set the FORMATETC structure*/
3233 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
3235 /* Get the pidls from IDataObject */
3236 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3238 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3239 if(nPidlIndex
<= cida
->cidl
)
3241 pidl
= COMDLG32_PIDL_ILClone((LPITEMIDLIST
)(&((LPBYTE
)cida
)[cida
->aoffset
[nPidlIndex
]]));
3243 COMCTL32_ReleaseStgMedium(medium
);
3248 /***********************************************************************
3251 * Return the number of selected items in the DataObject.
3254 UINT
GetNumSelected( IDataObject
*doSelected
)
3258 FORMATETC formatetc
;
3260 TRACE("sv=%p\n", doSelected
);
3262 if (!doSelected
) return 0;
3264 /* Set the FORMATETC structure*/
3265 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
3267 /* Get the pidls from IDataObject */
3268 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3270 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3271 retVal
= cida
->cidl
;
3272 COMCTL32_ReleaseStgMedium(medium
);
3282 /***********************************************************************
3285 * Get the pidl's display name (relative to folder) and
3286 * put it in lpstrFileName.
3288 * Return NOERROR on success,
3292 static HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
)
3297 TRACE("sf=%p pidl=%p\n", lpsf
, pidl
);
3301 SHGetDesktopFolder(&lpsf
);
3302 hRes
= GetName(lpsf
,pidl
,dwFlags
,lpstrFileName
);
3303 IShellFolder_Release(lpsf
);
3307 /* Get the display name of the pidl relative to the folder */
3308 if (SUCCEEDED(hRes
= IShellFolder_GetDisplayNameOf(lpsf
, pidl
, dwFlags
, &str
)))
3310 return COMDLG32_StrRetToStrNA(lpstrFileName
, MAX_PATH
, &str
, pidl
);
3315 /***********************************************************************
3316 * GetShellFolderFromPidl
3318 * pidlRel is the item pidl relative
3319 * Return the IShellFolder of the absolute pidl
3321 IShellFolder
*GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
)
3323 IShellFolder
*psf
= NULL
,*psfParent
;
3325 TRACE("%p\n", pidlAbs
);
3327 if(SUCCEEDED(SHGetDesktopFolder(&psfParent
)))
3330 if(pidlAbs
&& pidlAbs
->mkid
.cb
)
3332 if(SUCCEEDED(IShellFolder_BindToObject(psfParent
, pidlAbs
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psf
)))
3334 IShellFolder_Release(psfParent
);
3338 /* return the desktop */
3344 /***********************************************************************
3347 * Return the LPITEMIDLIST to the parent of the pidl in the list
3349 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
)
3351 LPITEMIDLIST pidlParent
;
3353 TRACE("%p\n", pidl
);
3355 pidlParent
= COMDLG32_PIDL_ILClone(pidl
);
3356 COMDLG32_PIDL_ILRemoveLastID(pidlParent
);
3361 /***********************************************************************
3364 * returns the pidl of the file name relative to folder
3365 * NULL if an error occurred
3367 LPITEMIDLIST
GetPidlFromName(IShellFolder
*lpsf
,LPWSTR lpcstrFileName
)
3369 LPITEMIDLIST pidl
= NULL
;
3372 TRACE("sf=%p file=%s\n", lpsf
, debugstr_w(lpcstrFileName
));
3374 if(!lpcstrFileName
) return NULL
;
3375 if(!*lpcstrFileName
) return NULL
;
3379 if (SUCCEEDED(SHGetDesktopFolder(&lpsf
))) {
3380 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3381 IShellFolder_Release(lpsf
);
3386 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3393 BOOL
IsPidlFolder (LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
)
3395 ULONG uAttr
= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
;
3398 TRACE("%p, %p\n", psf
, pidl
);
3400 ret
= IShellFolder_GetAttributesOf( psf
, 1, &pidl
, &uAttr
);
3402 TRACE("-- 0x%08lx 0x%08lx\n", uAttr
, ret
);
3403 /* see documentation shell 4.1*/
3404 return uAttr
& (SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
);
3407 /***********************************************************************
3408 * BrowseSelectedFolder
3410 static BOOL
BrowseSelectedFolder(HWND hwnd
)
3412 BOOL bBrowseSelFolder
= FALSE
;
3413 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3417 if (GetNumSelected(fodInfos
->Shell
.FOIDataObject
) == 1)
3419 LPITEMIDLIST pidlSelection
;
3421 /* get the file selected */
3422 pidlSelection
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, 1);
3423 if (IsPidlFolder (fodInfos
->Shell
.FOIShellFolder
, pidlSelection
))
3425 if ( FAILED( IShellBrowser_BrowseObject( fodInfos
->Shell
.FOIShellBrowser
,
3426 pidlSelection
, SBSP_RELATIVE
) ) )
3428 static const WCHAR notexist
[] = {'P','a','t','h',' ','d','o','e','s',
3429 ' ','n','o','t',' ','e','x','i','s','t',0};
3430 MessageBoxW( hwnd
, notexist
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
3432 bBrowseSelFolder
= TRUE
;
3433 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
3435 COMDLG32_SHFree( pidlSelection
);
3438 return bBrowseSelFolder
;
3442 * Memory allocation methods */
3443 static void *MemAlloc(UINT size
)
3445 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
3448 static void MemFree(void *mem
)
3450 HeapFree(GetProcessHeap(),0,mem
);
3454 * Old-style (win3.1) dialogs */
3456 /***********************************************************************
3457 * FD32_GetTemplate [internal]
3459 * Get a template (or FALSE if failure) when 16 bits dialogs are used
3460 * by a 32 bits application
3463 static BOOL
FD32_GetTemplate(PFD31_DATA lfs
)
3465 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3466 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3469 if (ofnW
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
3471 if (!(lfs
->template = LockResource( ofnW
->hInstance
)))
3473 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3477 else if (ofnW
->Flags
& OFN_ENABLETEMPLATE
)
3481 hResInfo
= FindResourceA(priv
->ofnA
->hInstance
,
3482 priv
->ofnA
->lpTemplateName
,
3485 hResInfo
= FindResourceW(ofnW
->hInstance
,
3486 ofnW
->lpTemplateName
,
3490 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
3493 if (!(hDlgTmpl
= LoadResource(ofnW
->hInstance
,
3495 !(lfs
->template = LockResource(hDlgTmpl
)))
3497 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3500 } else { /* get it from internal Wine resource */
3502 if (!(hResInfo
= FindResourceA(COMDLG32_hInstance
,
3503 lfs
->open
? "OPEN_FILE":"SAVE_FILE", (LPSTR
)RT_DIALOG
)))
3505 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
3508 if (!(hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
)) ||
3509 !(lfs
->template = LockResource( hDlgTmpl
)))
3511 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3519 /************************************************************************
3520 * FD32_Init [internal]
3521 * called from the common 16/32 code to initialize 32 bit data
3523 static BOOL CALLBACK
FD32_Init(LPARAM lParam
, PFD31_DATA lfs
, DWORD data
)
3525 BOOL IsUnicode
= (BOOL
) data
;
3528 priv
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FD32_PRIVATE
));
3529 lfs
->private1632
= priv
;
3530 if (NULL
== lfs
->private1632
) return FALSE
;
3533 lfs
->ofnW
= (LPOPENFILENAMEW
) lParam
;
3534 if (lfs
->ofnW
->Flags
& OFN_ENABLEHOOK
)
3535 if (lfs
->ofnW
->lpfnHook
)
3540 priv
->ofnA
= (LPOPENFILENAMEA
) lParam
;
3541 if (priv
->ofnA
->Flags
& OFN_ENABLEHOOK
)
3542 if (priv
->ofnA
->lpfnHook
)
3544 lfs
->ofnW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*lfs
->ofnW
));
3545 FD31_MapOfnStructA(priv
->ofnA
, lfs
->ofnW
, lfs
->open
);
3548 if (! FD32_GetTemplate(lfs
)) return FALSE
;
3553 /***********************************************************************
3554 * FD32_CallWindowProc [internal]
3556 * called from the common 16/32 code to call the appropriate hook
3558 static BOOL CALLBACK
FD32_CallWindowProc(PFD31_DATA lfs
, UINT wMsg
, WPARAM wParam
,
3562 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3566 TRACE("Call hookA %p (%p, %04x, %08x, %08lx)\n",
3567 priv
->ofnA
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3568 ret
= priv
->ofnA
->lpfnHook(lfs
->hwnd
, wMsg
, wParam
, lParam
);
3569 TRACE("ret hookA %p (%p, %04x, %08x, %08lx)\n",
3570 priv
->ofnA
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3574 TRACE("Call hookW %p (%p, %04x, %08x, %08lx)\n",
3575 lfs
->ofnW
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3576 ret
= lfs
->ofnW
->lpfnHook(lfs
->hwnd
, wMsg
, wParam
, lParam
);
3577 TRACE("Ret hookW %p (%p, %04x, %08x, %08lx)\n",
3578 lfs
->ofnW
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3582 /***********************************************************************
3583 * FD32_UpdateResult [internal]
3584 * update the real client structures if any
3586 static void CALLBACK
FD32_UpdateResult(PFD31_DATA lfs
)
3588 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3589 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3593 if (ofnW
->nMaxFile
&&
3594 !WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFile
, -1,
3595 priv
->ofnA
->lpstrFile
, ofnW
->nMaxFile
, NULL
, NULL
))
3596 priv
->ofnA
->lpstrFile
[ofnW
->nMaxFile
-1] = 0;
3597 priv
->ofnA
->nFileOffset
= ofnW
->nFileOffset
;
3598 priv
->ofnA
->nFileExtension
= ofnW
->nFileExtension
;
3602 /***********************************************************************
3603 * FD32_UpdateFileTitle [internal]
3604 * update the real client structures if any
3606 static void CALLBACK
FD32_UpdateFileTitle(PFD31_DATA lfs
)
3608 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3609 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3613 if (!WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFileTitle
, -1,
3614 priv
->ofnA
->lpstrFileTitle
, ofnW
->nMaxFileTitle
, NULL
, NULL
))
3615 priv
->ofnA
->lpstrFileTitle
[ofnW
->nMaxFileTitle
-1] = 0;
3620 /***********************************************************************
3621 * FD32_SendLbGetCurSel [internal]
3622 * retrieve selected listbox item
3624 static LRESULT CALLBACK
FD32_SendLbGetCurSel(PFD31_DATA lfs
)
3626 return SendDlgItemMessageW(lfs
->hwnd
, lst1
, LB_GETCURSEL
, 0, 0);
3630 /************************************************************************
3631 * FD32_Destroy [internal]
3632 * called from the common 16/32 code to cleanup 32 bit data
3634 static void CALLBACK
FD32_Destroy(PFD31_DATA lfs
)
3636 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3638 /* if ofnW has been allocated, have to free everything in it */
3639 if (NULL
!= priv
&& NULL
!= priv
->ofnA
)
3641 FD31_FreeOfnW(lfs
->ofnW
);
3642 HeapFree(GetProcessHeap(), 0, lfs
->ofnW
);
3646 static void FD32_SetupCallbacks(PFD31_CALLBACKS callbacks
)
3648 callbacks
->Init
= FD32_Init
;
3649 callbacks
->CWP
= FD32_CallWindowProc
;
3650 callbacks
->UpdateResult
= FD32_UpdateResult
;
3651 callbacks
->UpdateFileTitle
= FD32_UpdateFileTitle
;
3652 callbacks
->SendLbGetCurSel
= FD32_SendLbGetCurSel
;
3653 callbacks
->Destroy
= FD32_Destroy
;
3656 /***********************************************************************
3657 * FD32_WMMeasureItem [internal]
3659 static LONG
FD32_WMMeasureItem(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
3661 LPMEASUREITEMSTRUCT lpmeasure
;
3663 lpmeasure
= (LPMEASUREITEMSTRUCT
)lParam
;
3664 lpmeasure
->itemHeight
= FD31_GetFldrHeight();
3669 /***********************************************************************
3670 * FileOpenDlgProc [internal]
3671 * Used for open and save, in fact.
3673 static INT_PTR CALLBACK
FD32_FileOpenDlgProc(HWND hWnd
, UINT wMsg
,
3674 WPARAM wParam
, LPARAM lParam
)
3676 PFD31_DATA lfs
= (PFD31_DATA
)GetPropA(hWnd
,FD31_OFN_PROP
);
3678 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg
, wParam
, lParam
);
3679 if ((wMsg
!= WM_INITDIALOG
) && lfs
&& lfs
->hook
)
3682 lRet
= (INT_PTR
)FD31_CallWindowProc(lfs
, wMsg
, wParam
, lParam
);
3684 return lRet
; /* else continue message processing */
3689 return FD31_WMInitDialog(hWnd
, wParam
, lParam
);
3691 case WM_MEASUREITEM
:
3692 return FD32_WMMeasureItem(hWnd
, wParam
, lParam
);
3695 return FD31_WMDrawItem(hWnd
, wParam
, lParam
, !lfs
->open
, (DRAWITEMSTRUCT
*)lParam
);
3698 return FD31_WMCommand(hWnd
, lParam
, HIWORD(wParam
), LOWORD(wParam
), lfs
);
3701 SetBkColor((HDC16
)wParam
, 0x00C0C0C0);
3702 switch (HIWORD(lParam
))
3705 SetTextColor((HDC16
)wParam
, 0x00000000);
3707 case CTLCOLOR_STATIC
:
3708 SetTextColor((HDC16
)wParam
, 0x00000000);
3718 /***********************************************************************
3719 * GetFileName31A [internal]
3721 * Creates a win31 style dialog box for the user to select a file to open/save.
3723 static BOOL
GetFileName31A(LPOPENFILENAMEA lpofn
, /* addess of structure with data*/
3724 UINT dlgType
/* type dialogue : open/save */
3730 FD31_CALLBACKS callbacks
;
3732 if (!lpofn
|| !FD31_Init()) return FALSE
;
3734 TRACE("ofn flags %08lx\n", lpofn
->Flags
);
3735 FD32_SetupCallbacks(&callbacks
);
3736 lfs
= FD31_AllocPrivate((LPARAM
) lpofn
, dlgType
, &callbacks
, (DWORD
) FALSE
);
3739 hInst
= (HINSTANCE
)GetWindowLongPtrA( lpofn
->hwndOwner
, GWLP_HINSTANCE
);
3740 bRet
= DialogBoxIndirectParamA( hInst
, lfs
->template, lpofn
->hwndOwner
,
3741 FD32_FileOpenDlgProc
, (LPARAM
)lfs
);
3742 FD31_DestroyPrivate(lfs
);
3745 TRACE("return lpstrFile='%s' !\n", lpofn
->lpstrFile
);
3749 /***********************************************************************
3750 * GetFileName31W [internal]
3752 * Creates a win31 style dialog box for the user to select a file to open/save
3754 static BOOL
GetFileName31W(LPOPENFILENAMEW lpofn
, /* addess of structure with data*/
3755 UINT dlgType
/* type dialogue : open/save */
3761 FD31_CALLBACKS callbacks
;
3763 if (!lpofn
|| !FD31_Init()) return FALSE
;
3765 FD32_SetupCallbacks(&callbacks
);
3766 lfs
= FD31_AllocPrivate((LPARAM
) lpofn
, dlgType
, &callbacks
, (DWORD
) TRUE
);
3769 hInst
= (HINSTANCE
)GetWindowLongPtrW( lpofn
->hwndOwner
, GWLP_HINSTANCE
);
3770 bRet
= DialogBoxIndirectParamW( hInst
, lfs
->template, lpofn
->hwndOwner
,
3771 FD32_FileOpenDlgProc
, (LPARAM
)lfs
);
3772 FD31_DestroyPrivate(lfs
);
3775 TRACE("file %s, file offset %d, ext offset %d\n",
3776 debugstr_w(lpofn
->lpstrFile
), lpofn
->nFileOffset
, lpofn
->nFileExtension
);
3780 /* ------------------ APIs ---------------------- */
3782 /***********************************************************************
3783 * GetOpenFileNameA (COMDLG32.@)
3785 * Creates a dialog box for the user to select a file to open.
3788 * TRUE on success: user enters a valid file
3789 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3792 BOOL WINAPI
GetOpenFileNameA(
3793 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3795 BOOL win16look
= FALSE
;
3797 TRACE("flags %08lx\n", ofn
->Flags
);
3799 /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
3800 if (ofn
->Flags
& OFN_FILEMUSTEXIST
)
3801 ofn
->Flags
|= OFN_PATHMUSTEXIST
;
3803 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3804 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3807 return GetFileName31A(ofn
, OPEN_DIALOG
);
3809 return GetFileDialog95A(ofn
, OPEN_DIALOG
);
3812 /***********************************************************************
3813 * GetOpenFileNameW (COMDLG32.@)
3815 * Creates a dialog box for the user to select a file to open.
3818 * TRUE on success: user enters a valid file
3819 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3822 BOOL WINAPI
GetOpenFileNameW(
3823 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3825 BOOL win16look
= FALSE
;
3827 TRACE("flags %08lx\n", ofn
->Flags
);
3829 /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
3830 if (ofn
->Flags
& OFN_FILEMUSTEXIST
)
3831 ofn
->Flags
|= OFN_PATHMUSTEXIST
;
3833 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3834 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3837 return GetFileName31W(ofn
, OPEN_DIALOG
);
3839 return GetFileDialog95W(ofn
, OPEN_DIALOG
);
3843 /***********************************************************************
3844 * GetSaveFileNameA (COMDLG32.@)
3846 * Creates a dialog box for the user to select a file to save.
3849 * TRUE on success: user enters a valid file
3850 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3853 BOOL WINAPI
GetSaveFileNameA(
3854 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3856 BOOL win16look
= FALSE
;
3858 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3859 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3862 return GetFileName31A(ofn
, SAVE_DIALOG
);
3864 return GetFileDialog95A(ofn
, SAVE_DIALOG
);
3867 /***********************************************************************
3868 * GetSaveFileNameW (COMDLG32.@)
3870 * Creates a dialog box for the user to select a file to save.
3873 * TRUE on success: user enters a valid file
3874 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3877 BOOL WINAPI
GetSaveFileNameW(
3878 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3880 BOOL win16look
= FALSE
;
3882 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3883 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3886 return GetFileName31W(ofn
, SAVE_DIALOG
);
3888 return GetFileDialog95W(ofn
, SAVE_DIALOG
);