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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 LRESULT
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
= FindResourceW(COMDLG32_hInstance
,MAKEINTRESOURCEW(NEWFILEOPENORD
),(LPCWSTR
)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 if (fodInfos
->unicode
)
289 lRes
= DialogBoxIndirectParamW(COMDLG32_hInstance
,
291 fodInfos
->ofnInfos
->hwndOwner
,
295 lRes
= DialogBoxIndirectParamA(COMDLG32_hInstance
,
296 (LPCDLGTEMPLATEA
) template,
297 fodInfos
->ofnInfos
->hwndOwner
,
303 /* Unable to create the dialog */
310 /***********************************************************************
313 * Call GetFileName95 with this structure and clean the memory.
315 * IN : The OPENFILENAMEA initialisation structure passed to
316 * GetOpenFileNameA win api function (see filedlg.c)
318 BOOL WINAPI
GetFileDialog95A(LPOPENFILENAMEA ofn
,UINT iDlgType
)
321 FileOpenDlgInfos fodInfos
;
322 LPSTR lpstrSavDir
= NULL
;
324 LPWSTR defext
= NULL
;
325 LPWSTR filter
= NULL
;
326 LPWSTR customfilter
= NULL
;
328 /* Initialize FileOpenDlgInfos structure */
329 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
331 /* Pass in the original ofn */
332 fodInfos
.ofnInfos
= (LPOPENFILENAMEW
)ofn
;
334 /* save current directory */
335 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
337 lpstrSavDir
= MemAlloc(MAX_PATH
);
338 GetCurrentDirectoryA(MAX_PATH
, lpstrSavDir
);
341 fodInfos
.unicode
= FALSE
;
343 /* convert all the input strings to unicode */
344 if(ofn
->lpstrInitialDir
)
346 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, NULL
, 0 );
347 fodInfos
.initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
348 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, fodInfos
.initdir
, len
);
351 fodInfos
.initdir
= NULL
;
355 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
356 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFile
, -1, fodInfos
.filename
, ofn
->nMaxFile
);
359 fodInfos
.filename
= NULL
;
363 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, NULL
, 0 );
364 defext
= MemAlloc((len
+1)*sizeof(WCHAR
));
365 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, defext
, len
);
367 fodInfos
.defext
= defext
;
371 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, NULL
, 0 );
372 title
= MemAlloc((len
+1)*sizeof(WCHAR
));
373 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, title
, len
);
375 fodInfos
.title
= title
;
377 if (ofn
->lpstrFilter
)
382 /* filter is a list... title\0ext\0......\0\0 */
383 s
= ofn
->lpstrFilter
;
384 while (*s
) s
= s
+strlen(s
)+1;
386 n
= s
- ofn
->lpstrFilter
;
387 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, NULL
, 0 );
388 filter
= MemAlloc(len
*sizeof(WCHAR
));
389 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, filter
, len
);
391 fodInfos
.filter
= filter
;
393 /* convert lpstrCustomFilter */
394 if (ofn
->lpstrCustomFilter
)
399 /* customfilter contains a pair of strings... title\0ext\0 */
400 s
= ofn
->lpstrCustomFilter
;
401 if (*s
) s
= s
+strlen(s
)+1;
402 if (*s
) s
= s
+strlen(s
)+1;
403 n
= s
- ofn
->lpstrCustomFilter
;
404 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, NULL
, 0 );
405 customfilter
= MemAlloc(len
*sizeof(WCHAR
));
406 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, customfilter
, len
);
408 fodInfos
.customfilter
= customfilter
;
410 /* Initialize the dialog property */
411 fodInfos
.DlgInfos
.dwDlgProp
= 0;
412 fodInfos
.DlgInfos
.hwndCustomDlg
= NULL
;
417 ret
= GetFileName95(&fodInfos
);
420 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
421 ret
= GetFileName95(&fodInfos
);
429 SetCurrentDirectoryA(lpstrSavDir
);
430 MemFree(lpstrSavDir
);
436 MemFree(customfilter
);
437 MemFree(fodInfos
.initdir
);
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
)
742 hinst
= COMDLG32_hInstance
;
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 if (fodInfos
->unicode
)
775 hChildDlg
= CreateDialogIndirectParamW(hinst
, template, hwnd
,
776 IsHooked(fodInfos
) ? (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
: FileOpenDlgProcUserTemplate
,
777 (LPARAM
)fodInfos
->ofnInfos
);
779 hChildDlg
= CreateDialogIndirectParamA(hinst
, template, hwnd
,
780 IsHooked(fodInfos
) ? (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
: FileOpenDlgProcUserTemplate
,
781 (LPARAM
)fodInfos
->ofnInfos
);
784 ShowWindow(hChildDlg
,SW_SHOW
);
788 else if( IsHooked(fodInfos
))
793 WORD menu
,class,title
;
795 GetClientRect(hwnd
,&rectHwnd
);
796 temp
.tmplate
.style
= WS_CHILD
| WS_CLIPSIBLINGS
| WS_VISIBLE
| DS_CONTROL
| DS_3DLOOK
;
797 temp
.tmplate
.dwExtendedStyle
= 0;
798 temp
.tmplate
.cdit
= 0;
803 temp
.menu
= temp
.class = temp
.title
= 0;
805 hChildDlg
= CreateDialogIndirectParamA(COMDLG32_hInstance
, &temp
.tmplate
,
806 hwnd
, (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
, (LPARAM
)fodInfos
->ofnInfos
);
813 /***********************************************************************
814 * SendCustomDlgNotificationMessage
816 * Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
819 LRESULT
SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
)
821 LRESULT hook_result
= 0;
823 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwndParentDlg
,FileOpenDlgInfosStr
);
825 TRACE("%p 0x%04x\n",hwndParentDlg
, uCode
);
827 if(!fodInfos
) return 0;
829 if(fodInfos
->DlgInfos
.hwndCustomDlg
)
831 TRACE("CALL NOTIFY for %x\n", uCode
);
832 if(fodInfos
->unicode
)
835 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
836 ofnNotify
.hdr
.idFrom
=0;
837 ofnNotify
.hdr
.code
= uCode
;
838 ofnNotify
.lpOFN
= fodInfos
->ofnInfos
;
839 ofnNotify
.pszFile
= NULL
;
840 hook_result
= SendMessageW(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
845 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
846 ofnNotify
.hdr
.idFrom
=0;
847 ofnNotify
.hdr
.code
= uCode
;
848 ofnNotify
.lpOFN
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
849 ofnNotify
.pszFile
= NULL
;
850 hook_result
= SendMessageA(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
852 TRACE("RET NOTIFY\n");
854 TRACE("Retval: 0x%08lx\n", hook_result
);
858 static INT_PTR
FILEDLG95_Handle_GetFilePath(HWND hwnd
, DWORD size
, LPVOID buffer
)
860 UINT sizeUsed
= 0, n
, total
;
861 LPWSTR lpstrFileList
= NULL
;
862 WCHAR lpstrCurrentDir
[MAX_PATH
];
863 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
865 TRACE("CDM_GETFILEPATH:\n");
867 if ( ! (fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
870 /* get path and filenames */
871 COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrCurrentDir
);
872 n
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
, ' ');
874 TRACE("path >%s< filespec >%s< %d files\n",
875 debugstr_w(lpstrCurrentDir
),debugstr_w(lpstrFileList
),n
);
877 if( fodInfos
->unicode
)
879 LPWSTR bufW
= buffer
;
880 total
= strlenW(lpstrCurrentDir
) + 1 + sizeUsed
;
882 /* Prepend the current path */
883 n
= strlenW(lpstrCurrentDir
) + 1;
884 memcpy( bufW
, lpstrCurrentDir
, min(n
,size
) * sizeof(WCHAR
));
887 /* 'n' includes trailing \0 */
889 memcpy( &bufW
[n
], lpstrFileList
, (size
-n
)*sizeof(WCHAR
) );
891 TRACE("returned -> %s\n",debugstr_wn(bufW
, total
));
896 total
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
897 NULL
, 0, NULL
, NULL
);
898 total
+= WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
899 NULL
, 0, NULL
, NULL
);
901 /* Prepend the current path */
902 n
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
903 bufA
, size
, NULL
, NULL
);
907 /* 'n' includes trailing \0 */
909 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
910 &bufA
[n
], size
-n
, NULL
, NULL
);
913 TRACE("returned -> %s\n",debugstr_an(bufA
, total
));
915 MemFree(lpstrFileList
);
920 static INT_PTR
FILEDLG95_Handle_GetFileSpec(HWND hwnd
, DWORD size
, LPVOID buffer
)
923 LPWSTR lpstrFileList
= NULL
;
924 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
926 TRACE("CDM_GETSPEC:\n");
928 FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
, ' ');
929 if( fodInfos
->unicode
)
931 LPWSTR bufW
= buffer
;
932 memcpy( bufW
, lpstrFileList
, sizeof(WCHAR
)*sizeUsed
);
937 sizeUsed
= WideCharToMultiByte( CP_ACP
, 0, lpstrFileList
, sizeUsed
,
938 NULL
, 0, NULL
, NULL
);
939 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
940 bufA
, size
, NULL
, NULL
);
942 MemFree(lpstrFileList
);
947 /***********************************************************************
948 * FILEDLG95_HandleCustomDialogMessages
950 * Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
952 static INT_PTR
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
954 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
955 WCHAR lpstrPath
[MAX_PATH
];
958 if(!fodInfos
) return FALSE
;
962 case CDM_GETFILEPATH
:
963 retval
= FILEDLG95_Handle_GetFilePath(hwnd
, (UINT
)wParam
, (LPVOID
)lParam
);
966 case CDM_GETFOLDERPATH
:
967 TRACE("CDM_GETFOLDERPATH:\n");
968 COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPath
);
971 if (fodInfos
->unicode
)
972 lstrcpynW((LPWSTR
)lParam
, lpstrPath
, (int)wParam
);
974 WideCharToMultiByte(CP_ACP
, 0, lpstrPath
, -1,
975 (LPSTR
)lParam
, (int)wParam
, NULL
, NULL
);
977 retval
= strlenW(lpstrPath
);
981 retval
= FILEDLG95_Handle_GetFileSpec(hwnd
, (UINT
)wParam
, (LPSTR
)lParam
);
984 case CDM_SETCONTROLTEXT
:
985 TRACE("CDM_SETCONTROLTEXT:\n");
988 if( fodInfos
->unicode
)
989 SetDlgItemTextW( hwnd
, (UINT
) wParam
, (LPWSTR
) lParam
);
991 SetDlgItemTextA( hwnd
, (UINT
) wParam
, (LPSTR
) lParam
);
996 case CDM_HIDECONTROL
:
997 /* MSDN states that it should fail for not OFN_EXPLORER case */
998 if (fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
)
1000 HWND control
= GetDlgItem( hwnd
, wParam
);
1001 if (control
) ShowWindow( control
, SW_HIDE
);
1004 else retval
= FALSE
;
1008 if (uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
1009 FIXME("message CDM_FIRST+%04x not implemented\n", uMsg
- CDM_FIRST
);
1012 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, retval
);
1016 /***********************************************************************
1019 * File open dialog procedure
1021 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1024 TRACE("0x%04x 0x%04x\n", hwnd
, uMsg
);
1031 FileOpenDlgInfos
* fodInfos
= (FileOpenDlgInfos
*)lParam
;
1033 /* Adds the FileOpenDlgInfos in the property list of the dialog
1034 so it will be easily accessible through a GetPropA(...) */
1035 SetPropA(hwnd
, FileOpenDlgInfosStr
, (HANDLE
) fodInfos
);
1037 fodInfos
->DlgInfos
.hwndCustomDlg
=
1038 CreateTemplateDialog((FileOpenDlgInfos
*)lParam
, hwnd
);
1040 FILEDLG95_InitControls(hwnd
);
1042 if (fodInfos
->DlgInfos
.hwndCustomDlg
)
1045 UINT flags
= SWP_NOACTIVATE
;
1047 ArrangeCtrlPositions(fodInfos
->DlgInfos
.hwndCustomDlg
, hwnd
,
1048 (fodInfos
->ofnInfos
->Flags
& (OFN_HIDEREADONLY
| OFN_SHOWHELP
)) == OFN_HIDEREADONLY
);
1050 /* resize the custom dialog to the parent size */
1051 if (fodInfos
->ofnInfos
->Flags
& (OFN_ENABLETEMPLATE
| OFN_ENABLETEMPLATEHANDLE
))
1052 GetClientRect(hwnd
, &rc
);
1055 /* our own fake template is zero sized and doesn't have
1056 * children, so there is no need to resize it.
1057 * Picasa depends on it.
1059 flags
|= SWP_NOSIZE
;
1062 SetWindowPos(fodInfos
->DlgInfos
.hwndCustomDlg
, HWND_BOTTOM
,
1063 0, 0, rc
.right
, rc
.bottom
, flags
);
1066 FILEDLG95_FillControls(hwnd
, wParam
, lParam
);
1068 SendCustomDlgNotificationMessage(hwnd
,CDN_INITDONE
);
1069 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
1070 SendCustomDlgNotificationMessage(hwnd
,CDN_SELCHANGE
);
1074 return FILEDLG95_OnWMCommand(hwnd
, wParam
, lParam
);
1077 switch(((LPDRAWITEMSTRUCT
)lParam
)->CtlID
)
1080 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT
) lParam
);
1086 case WM_GETISHELLBROWSER
:
1087 return FILEDLG95_OnWMGetIShellBrowser(hwnd
);
1090 RemovePropA(hwnd
, FileOpenDlgInfosStr
);
1095 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
1098 /* set up the button tooltips strings */
1099 if(TTN_GETDISPINFOA
== lpnmh
->code
)
1101 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
1102 switch(lpnmh
->idFrom
)
1104 /* Up folder button */
1105 case FCIDM_TB_UPFOLDER
:
1106 stringId
= IDS_UPFOLDER
;
1108 /* New folder button */
1109 case FCIDM_TB_NEWFOLDER
:
1110 stringId
= IDS_NEWFOLDER
;
1112 /* List option button */
1113 case FCIDM_TB_SMALLICON
:
1114 stringId
= IDS_LISTVIEW
;
1116 /* Details option button */
1117 case FCIDM_TB_REPORTVIEW
:
1118 stringId
= IDS_REPORTVIEW
;
1120 /* Desktop button */
1121 case FCIDM_TB_DESKTOP
:
1122 stringId
= IDS_TODESKTOP
;
1127 lpdi
->hinst
= COMDLG32_hInstance
;
1128 lpdi
->lpszText
= MAKEINTRESOURCEA(stringId
);
1133 if(uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
1134 return FILEDLG95_HandleCustomDialogMessages(hwnd
, uMsg
, wParam
, lParam
);
1139 /***********************************************************************
1140 * FILEDLG95_InitControls
1142 * WM_INITDIALOG message handler (before hook notification)
1144 static LRESULT
FILEDLG95_InitControls(HWND hwnd
)
1146 int win2000plus
= 0;
1148 int handledPath
= FALSE
;
1149 OSVERSIONINFOA osVi
;
1150 static const WCHAR szwSlash
[] = { '\\', 0 };
1151 static const WCHAR szwStar
[] = { '*',0 };
1155 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1156 {VIEW_PARENTFOLDER
, FCIDM_TB_UPFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1157 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1158 {VIEW_NEWFOLDER
+1, FCIDM_TB_DESKTOP
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1159 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1160 {VIEW_NEWFOLDER
, FCIDM_TB_NEWFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1161 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1162 {VIEW_LIST
, FCIDM_TB_SMALLICON
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1163 {VIEW_DETAILS
, FCIDM_TB_REPORTVIEW
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1168 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1170 tba
[0].hInst
= HINST_COMMCTRL
;
1171 tba
[0].nID
= IDB_VIEW_SMALL_COLOR
;
1172 tba
[1].hInst
= COMDLG32_hInstance
;
1175 TRACE("%p\n", fodInfos
);
1177 /* Get windows version emulating */
1178 osVi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
1179 GetVersionExA(&osVi
);
1180 if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
) {
1181 win98plus
= ((osVi
.dwMajorVersion
> 4) || ((osVi
.dwMajorVersion
== 4) && (osVi
.dwMinorVersion
> 0)));
1182 } else if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1183 win2000plus
= (osVi
.dwMajorVersion
> 4);
1184 if (win2000plus
) win98plus
= TRUE
;
1186 TRACE("Running on 2000+ %d, 98+ %d\n", win2000plus
, win98plus
);
1188 /* Get the hwnd of the controls */
1189 fodInfos
->DlgInfos
.hwndFileName
= GetDlgItem(hwnd
,IDC_FILENAME
);
1190 fodInfos
->DlgInfos
.hwndFileTypeCB
= GetDlgItem(hwnd
,IDC_FILETYPE
);
1191 fodInfos
->DlgInfos
.hwndLookInCB
= GetDlgItem(hwnd
,IDC_LOOKIN
);
1193 GetWindowRect( fodInfos
->DlgInfos
.hwndLookInCB
,&rectlook
);
1194 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectlook
,2);
1196 /* construct the toolbar */
1197 GetWindowRect(GetDlgItem(hwnd
,IDC_TOOLBARSTATIC
),&rectTB
);
1198 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectTB
,2);
1200 rectTB
.right
= rectlook
.right
+ rectTB
.right
- rectTB
.left
;
1201 rectTB
.bottom
= rectlook
.top
- 1 + rectTB
.bottom
- rectTB
.top
;
1202 rectTB
.left
= rectlook
.right
;
1203 rectTB
.top
= rectlook
.top
-1;
1205 if (fodInfos
->unicode
)
1206 fodInfos
->DlgInfos
.hwndTB
= CreateWindowExW(0, TOOLBARCLASSNAMEW
, NULL
,
1207 WS_CHILD
| WS_GROUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NORESIZE
,
1208 rectTB
.left
, rectTB
.top
,
1209 rectTB
.right
- rectTB
.left
, rectTB
.bottom
- rectTB
.top
,
1210 hwnd
, (HMENU
)IDC_TOOLBAR
, COMDLG32_hInstance
, NULL
);
1212 fodInfos
->DlgInfos
.hwndTB
= CreateWindowExA(0, TOOLBARCLASSNAMEA
, NULL
,
1213 WS_CHILD
| WS_GROUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NORESIZE
,
1214 rectTB
.left
, rectTB
.top
,
1215 rectTB
.right
- rectTB
.left
, rectTB
.bottom
- rectTB
.top
,
1216 hwnd
, (HMENU
)IDC_TOOLBAR
, COMDLG32_hInstance
, NULL
);
1218 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_BUTTONSTRUCTSIZE
, (WPARAM
) sizeof(TBBUTTON
), 0);
1220 /* FIXME: use TB_LOADIMAGES when implemented */
1221 /* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1222 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 12, (LPARAM
) &tba
[0]);
1223 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 1, (LPARAM
) &tba
[1]);
1225 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBUTTONSA
, (WPARAM
) 9,(LPARAM
) &tbb
);
1226 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_AUTOSIZE
, 0, 0);
1228 /* Set the window text with the text specified in the OPENFILENAME structure */
1231 SetWindowTextW(hwnd
,fodInfos
->title
);
1233 else if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1236 LoadStringW(COMDLG32_hInstance
, IDS_SAVE
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1237 SetWindowTextW(hwnd
, buf
);
1240 /* Initialise the file name edit control */
1241 handledPath
= FALSE
;
1242 TRACE("Before manipilation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1244 if(fodInfos
->filename
)
1246 /* 1. If win2000 or higher and filename contains a path, use it
1247 in preference over the lpstrInitialDir */
1248 if (win2000plus
&& *fodInfos
->filename
&& strpbrkW(fodInfos
->filename
, szwSlash
)) {
1249 WCHAR tmpBuf
[MAX_PATH
];
1253 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
, tmpBuf
, &nameBit
);
1256 /* nameBit is always shorter than the original filename */
1257 strcpyW(fodInfos
->filename
,nameBit
);
1260 if (fodInfos
->initdir
== NULL
)
1261 MemFree(fodInfos
->initdir
);
1262 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf
) + 1)*sizeof(WCHAR
));
1263 strcpyW(fodInfos
->initdir
, tmpBuf
);
1265 TRACE("Value in Filename includes path, overriding InitialDir: %s, %s\n",
1266 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1268 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1271 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1275 /* 2. (All platforms) If initdir is not null, then use it */
1276 if ((handledPath
== FALSE
) && (fodInfos
->initdir
!=NULL
) &&
1277 (*fodInfos
->initdir
!=0x00))
1279 /* Work out the proper path as supplied one might be relative */
1280 /* (Here because supplying '.' as dir browses to My Computer) */
1281 if (handledPath
==FALSE
) {
1282 WCHAR tmpBuf
[MAX_PATH
];
1283 WCHAR tmpBuf2
[MAX_PATH
];
1287 strcpyW(tmpBuf
, fodInfos
->initdir
);
1288 if( PathFileExistsW(tmpBuf
) ) {
1289 /* initdir does not have to be a directory. If a file is
1290 * specified, the dir part is taken */
1291 if( PathIsDirectoryW(tmpBuf
)) {
1292 if (tmpBuf
[strlenW(tmpBuf
)-1] != '\\') {
1293 strcatW(tmpBuf
, szwSlash
);
1295 strcatW(tmpBuf
, szwStar
);
1297 result
= GetFullPathNameW(tmpBuf
, MAX_PATH
, tmpBuf2
, &nameBit
);
1300 MemFree(fodInfos
->initdir
);
1301 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf2
) + 1)*sizeof(WCHAR
));
1302 strcpyW(fodInfos
->initdir
, tmpBuf2
);
1304 TRACE("Value in InitDir changed to %s\n", debugstr_w(fodInfos
->initdir
));
1307 else if (fodInfos
->initdir
)
1309 MemFree(fodInfos
->initdir
);
1310 fodInfos
->initdir
= NULL
;
1311 TRACE("Value in InitDir is not an existing path, changed to (nil)\n");
1316 if ((handledPath
== FALSE
) && ((fodInfos
->initdir
==NULL
) ||
1317 (*fodInfos
->initdir
==0x00)))
1319 /* 3. All except w2k+: if filename contains a path use it */
1320 if (!win2000plus
&& fodInfos
->filename
&&
1321 *fodInfos
->filename
&&
1322 strpbrkW(fodInfos
->filename
, szwSlash
)) {
1323 WCHAR tmpBuf
[MAX_PATH
];
1327 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
,
1332 /* nameBit is always shorter than the original filename */
1333 strcpyW(fodInfos
->filename
, nameBit
);
1336 len
= strlenW(tmpBuf
);
1337 MemFree(fodInfos
->initdir
);
1338 fodInfos
->initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
1339 strcpyW(fodInfos
->initdir
, tmpBuf
);
1342 TRACE("Value in Filename includes path, overriding initdir: %s, %s\n",
1343 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1345 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1348 /* 4. win98+ and win2000+ if any files of specified filter types in
1349 current directory, use it */
1350 if ( win98plus
&& handledPath
== FALSE
&&
1351 fodInfos
->filter
&& *fodInfos
->filter
) {
1353 BOOL searchMore
= TRUE
;
1354 LPCWSTR lpstrPos
= fodInfos
->filter
;
1355 WIN32_FIND_DATAW FindFileData
;
1360 /* filter is a list... title\0ext\0......\0\0 */
1362 /* Skip the title */
1363 if(! *lpstrPos
) break; /* end */
1364 lpstrPos
+= strlenW(lpstrPos
) + 1;
1366 /* See if any files exist in the current dir with this extension */
1367 if(! *lpstrPos
) break; /* end */
1369 hFind
= FindFirstFileW(lpstrPos
, &FindFileData
);
1371 if (hFind
== INVALID_HANDLE_VALUE
) {
1372 /* None found - continue search */
1373 lpstrPos
+= strlenW(lpstrPos
) + 1;
1378 MemFree(fodInfos
->initdir
);
1379 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1380 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1383 TRACE("No initial dir specified, but files of type %s found in current, so using it\n",
1384 debugstr_w(lpstrPos
));
1390 /* 5. Win2000+: FIXME: Next, Recently used? Not sure how windows does this */
1392 /* 6. Win98+ and 2000+: Use personal files dir, others use current dir */
1393 if (handledPath
== FALSE
&& (win2000plus
|| win98plus
)) {
1394 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1396 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_PERSONAL
, 0, 0, fodInfos
->initdir
)))
1398 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_DESKTOPDIRECTORY
|CSIDL_FLAG_CREATE
, 0, 0, fodInfos
->initdir
)))
1401 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1402 TRACE("No personal or desktop dir, using cwd as failsafe: %s\n", debugstr_w(fodInfos
->initdir
));
1404 TRACE("No personal dir, using desktop instead: %s\n", debugstr_w(fodInfos
->initdir
));
1407 TRACE("No initial dir specified, using personal files dir of %s\n", debugstr_w(fodInfos
->initdir
));
1410 } else if (handledPath
==FALSE
) {
1411 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1412 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1414 TRACE("No initial dir specified, using current dir of %s\n", debugstr_w(fodInfos
->initdir
));
1417 SetFocus(GetDlgItem(hwnd
, IDC_FILENAME
));
1418 TRACE("After manipulation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1420 /* Must the open as read only check box be checked ?*/
1421 if(fodInfos
->ofnInfos
->Flags
& OFN_READONLY
)
1423 SendDlgItemMessageA(hwnd
,IDC_OPENREADONLY
,BM_SETCHECK
,(WPARAM
)TRUE
,0);
1426 /* Must the open as read only check box be hidden? */
1427 if(fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
)
1429 ShowWindow(GetDlgItem(hwnd
,IDC_OPENREADONLY
),SW_HIDE
);
1430 EnableWindow(GetDlgItem(hwnd
, IDC_OPENREADONLY
), FALSE
);
1433 /* Must the help button be hidden? */
1434 if (!(fodInfos
->ofnInfos
->Flags
& OFN_SHOWHELP
))
1436 ShowWindow(GetDlgItem(hwnd
, pshHelp
), SW_HIDE
);
1437 EnableWindow(GetDlgItem(hwnd
, pshHelp
), FALSE
);
1440 /* Resize the height, if open as read only checkbox ad help button
1441 are hidden and we are not using a custom template nor a customDialog
1443 if ( (fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
) &&
1444 (!(fodInfos
->ofnInfos
->Flags
&
1445 (OFN_SHOWHELP
|OFN_ENABLETEMPLATE
|OFN_ENABLETEMPLATEHANDLE
))) &&
1446 (!fodInfos
->DlgInfos
.hwndCustomDlg
))
1448 RECT rectDlg
, rectHelp
, rectCancel
;
1449 GetWindowRect(hwnd
, &rectDlg
);
1450 GetWindowRect(GetDlgItem(hwnd
, pshHelp
), &rectHelp
);
1451 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rectCancel
);
1452 /* subtract the height of the help button plus the space between
1453 the help button and the cancel button to the height of the dialog */
1454 SetWindowPos(hwnd
, 0, 0, 0, rectDlg
.right
-rectDlg
.left
,
1455 (rectDlg
.bottom
-rectDlg
.top
) - (rectHelp
.bottom
- rectCancel
.bottom
),
1456 SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
);
1458 /* change Open to Save */
1459 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1462 LoadStringW(COMDLG32_hInstance
, IDS_SAVE_BUTTON
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1463 SetDlgItemTextW(hwnd
, IDOK
, buf
);
1464 LoadStringW(COMDLG32_hInstance
, IDS_SAVE_IN
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1465 SetDlgItemTextW(hwnd
, IDC_LOOKINSTATIC
, buf
);
1470 /***********************************************************************
1471 * FILEDLG95_FillControls
1473 * WM_INITDIALOG message handler (after hook notification)
1475 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1477 LPITEMIDLIST pidlItemId
= NULL
;
1479 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) lParam
;
1481 TRACE("dir=%s file=%s\n",
1482 debugstr_w(fodInfos
->initdir
), debugstr_w(fodInfos
->filename
));
1484 /* Get the initial directory pidl */
1486 if(!(pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,fodInfos
->initdir
)))
1488 WCHAR path
[MAX_PATH
];
1490 GetCurrentDirectoryW(MAX_PATH
,path
);
1491 pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, path
);
1494 /* Initialise shell objects */
1495 FILEDLG95_SHELL_Init(hwnd
);
1497 /* Initialize the Look In combo box */
1498 FILEDLG95_LOOKIN_Init(fodInfos
->DlgInfos
.hwndLookInCB
);
1500 /* Initialize the filter combo box */
1501 FILEDLG95_FILETYPE_Init(hwnd
);
1503 /* Browse to the initial directory */
1504 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,pidlItemId
, SBSP_ABSOLUTE
);
1506 /* Free pidlItem memory */
1507 COMDLG32_SHFree(pidlItemId
);
1511 /***********************************************************************
1514 * Regroups all the cleaning functions of the filedlg
1516 void FILEDLG95_Clean(HWND hwnd
)
1518 FILEDLG95_FILETYPE_Clean(hwnd
);
1519 FILEDLG95_LOOKIN_Clean(hwnd
);
1520 FILEDLG95_SHELL_Clean(hwnd
);
1522 /***********************************************************************
1523 * FILEDLG95_OnWMCommand
1525 * WM_COMMAND message handler
1527 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1529 WORD wNotifyCode
= HIWORD(wParam
); /* notification code */
1530 WORD wID
= LOWORD(wParam
); /* item, control, or accelerator identifier */
1531 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1537 FILEDLG95_OnOpen(hwnd
);
1541 FILEDLG95_Clean(hwnd
);
1542 EndDialog(hwnd
, FALSE
);
1544 /* Filetype combo box */
1546 FILEDLG95_FILETYPE_OnCommand(hwnd
,wNotifyCode
);
1548 /* LookIn combo box */
1550 FILEDLG95_LOOKIN_OnCommand(hwnd
,wNotifyCode
);
1553 /* --- toolbar --- */
1554 /* Up folder button */
1555 case FCIDM_TB_UPFOLDER
:
1556 FILEDLG95_SHELL_UpFolder(hwnd
);
1558 /* New folder button */
1559 case FCIDM_TB_NEWFOLDER
:
1560 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_NEWFOLDERA
);
1562 /* List option button */
1563 case FCIDM_TB_SMALLICON
:
1564 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWLISTA
);
1566 /* Details option button */
1567 case FCIDM_TB_REPORTVIEW
:
1568 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWDETAILSA
);
1570 /* Details option button */
1571 case FCIDM_TB_DESKTOP
:
1572 FILEDLG95_SHELL_BrowseToDesktop(hwnd
);
1579 /* Do not use the listview selection anymore */
1580 fodInfos
->DlgInfos
.dwDlgProp
&= ~FODPROP_USEVIEW
;
1584 /***********************************************************************
1585 * FILEDLG95_OnWMGetIShellBrowser
1587 * WM_GETISHELLBROWSER message handler
1589 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
)
1592 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1596 SetWindowLongPtrW(hwnd
,DWLP_MSGRESULT
,(LONG_PTR
)fodInfos
->Shell
.FOIShellBrowser
);
1602 /***********************************************************************
1603 * FILEDLG95_SendFileOK
1605 * Sends the CDN_FILEOK notification if required
1608 * TRUE if the dialog should close
1609 * FALSE if the dialog should not be closed
1611 static BOOL
FILEDLG95_SendFileOK( HWND hwnd
, FileOpenDlgInfos
*fodInfos
)
1613 /* ask the hook if we can close */
1614 if(IsHooked(fodInfos
))
1619 /* First send CDN_FILEOK as MSDN doc says */
1620 retval
= SendCustomDlgNotificationMessage(hwnd
,CDN_FILEOK
);
1621 if (GetWindowLongPtrW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWLP_MSGRESULT
))
1623 TRACE("canceled\n");
1624 return (retval
== 0);
1627 /* fodInfos->ofnInfos points to an ASCII or UNICODE structure as appropriate */
1628 retval
= SendMessageW(fodInfos
->DlgInfos
.hwndCustomDlg
,
1629 fodInfos
->HookMsg
.fileokstring
, 0, (LPARAM
)fodInfos
->ofnInfos
);
1630 if (GetWindowLongPtrW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWLP_MSGRESULT
))
1632 TRACE("canceled\n");
1633 return (retval
== 0);
1639 /***********************************************************************
1640 * FILEDLG95_OnOpenMultipleFiles
1642 * Handles the opening of multiple files.
1645 * check destination buffer size
1647 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
)
1649 WCHAR lpstrPathSpec
[MAX_PATH
] = {0};
1650 UINT nCount
, nSizePath
;
1651 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1655 if(fodInfos
->unicode
)
1657 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
1658 ofn
->lpstrFile
[0] = '\0';
1662 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
) fodInfos
->ofnInfos
;
1663 ofn
->lpstrFile
[0] = '\0';
1666 COMDLG32_GetDisplayNameOf( fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathSpec
);
1668 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1669 ( fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1670 ! ( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1672 LPWSTR lpstrTemp
= lpstrFileList
;
1674 for ( nCount
= 0; nCount
< nFileCount
; nCount
++ )
1678 pidl
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, lpstrTemp
);
1681 WCHAR lpstrNotFound
[100];
1682 WCHAR lpstrMsg
[100];
1684 static const WCHAR nl
[] = {'\n',0};
1686 LoadStringW(COMDLG32_hInstance
, IDS_FILENOTFOUND
, lpstrNotFound
, 100);
1687 LoadStringW(COMDLG32_hInstance
, IDS_VERIFYFILE
, lpstrMsg
, 100);
1689 strcpyW(tmp
, lpstrTemp
);
1691 strcatW(tmp
, lpstrNotFound
);
1693 strcatW(tmp
, lpstrMsg
);
1695 MessageBoxW(hwnd
, tmp
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
1699 /* move to the next file in the list of files */
1700 lpstrTemp
+= strlenW(lpstrTemp
) + 1;
1701 COMDLG32_SHFree(pidl
);
1705 nSizePath
= strlenW(lpstrPathSpec
) + 1;
1706 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
1708 /* For "oldstyle" dialog the components have to
1709 be separated by blanks (not '\0'!) and short
1710 filenames have to be used! */
1711 FIXME("Components have to be separated by blanks\n");
1713 if(fodInfos
->unicode
)
1715 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
1716 strcpyW( ofn
->lpstrFile
, lpstrPathSpec
);
1717 memcpy( ofn
->lpstrFile
+ nSizePath
, lpstrFileList
, sizeUsed
*sizeof(WCHAR
) );
1721 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
1723 if (ofn
->lpstrFile
!= NULL
)
1725 nSizePath
= WideCharToMultiByte(CP_ACP
, 0, lpstrPathSpec
, -1,
1726 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
1727 if (ofn
->nMaxFile
> nSizePath
)
1729 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
1730 ofn
->lpstrFile
+ nSizePath
,
1731 ofn
->nMaxFile
- nSizePath
, NULL
, NULL
);
1736 fodInfos
->ofnInfos
->nFileOffset
= nSizePath
;
1737 fodInfos
->ofnInfos
->nFileExtension
= 0;
1739 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
1742 /* clean and exit */
1743 FILEDLG95_Clean(hwnd
);
1744 return EndDialog(hwnd
,TRUE
);
1747 /***********************************************************************
1750 * Ok button WM_COMMAND message handler
1752 * If the function succeeds, the return value is nonzero.
1754 #define ONOPEN_BROWSE 1
1755 #define ONOPEN_OPEN 2
1756 #define ONOPEN_SEARCH 3
1757 static void FILEDLG95_OnOpenMessage(HWND hwnd
, int idCaption
, int idText
)
1759 WCHAR strMsgTitle
[MAX_PATH
];
1760 WCHAR strMsgText
[MAX_PATH
];
1762 LoadStringW(COMDLG32_hInstance
, idCaption
, strMsgTitle
, sizeof(strMsgTitle
)/sizeof(WCHAR
));
1764 strMsgTitle
[0] = '\0';
1765 LoadStringW(COMDLG32_hInstance
, idText
, strMsgText
, sizeof(strMsgText
)/sizeof(WCHAR
));
1766 MessageBoxW(hwnd
,strMsgText
, strMsgTitle
, MB_OK
| MB_ICONHAND
);
1769 BOOL
FILEDLG95_OnOpen(HWND hwnd
)
1771 LPWSTR lpstrFileList
;
1772 UINT nFileCount
= 0;
1775 WCHAR lpstrPathAndFile
[MAX_PATH
];
1776 WCHAR lpstrTemp
[MAX_PATH
];
1777 LPSHELLFOLDER lpsf
= NULL
;
1779 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1781 TRACE("hwnd=%p\n", hwnd
);
1783 /* get the files from the edit control */
1784 nFileCount
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
, '\0');
1786 /* try if the user selected a folder in the shellview */
1789 BrowseSelectedFolder(hwnd
);
1795 ret
= FILEDLG95_OnOpenMultipleFiles(hwnd
, lpstrFileList
, nFileCount
, sizeUsed
);
1799 TRACE("count=%u len=%u file=%s\n", nFileCount
, sizeUsed
, debugstr_w(lpstrFileList
));
1802 Step 1: Build a complete path name from the current folder and
1803 the filename or path in the edit box.
1805 - the path in the edit box is a root path
1806 (with or without drive letter)
1807 - the edit box contains ".." (or a path with ".." in it)
1810 /* Get the current directory name */
1811 if (!COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathAndFile
))
1814 GetCurrentDirectoryW(MAX_PATH
, lpstrPathAndFile
);
1816 PathAddBackslashW(lpstrPathAndFile
);
1818 TRACE("current directory=%s\n", debugstr_w(lpstrPathAndFile
));
1820 /* if the user specifyed a fully qualified path use it */
1821 if(PathIsRelativeW(lpstrFileList
))
1823 strcatW(lpstrPathAndFile
, lpstrFileList
);
1827 /* does the path have a drive letter? */
1828 if (PathGetDriveNumberW(lpstrFileList
) == -1)
1829 strcpyW(lpstrPathAndFile
+2, lpstrFileList
);
1831 strcpyW(lpstrPathAndFile
, lpstrFileList
);
1834 /* resolve "." and ".." */
1835 PathCanonicalizeW(lpstrTemp
, lpstrPathAndFile
);
1836 strcpyW(lpstrPathAndFile
, lpstrTemp
);
1837 TRACE("canon=%s\n", debugstr_w(lpstrPathAndFile
));
1839 MemFree(lpstrFileList
);
1842 Step 2: here we have a cleaned up path
1844 We have to parse the path step by step to see if we have to browse
1845 to a folder if the path points to a directory or the last
1846 valid element is a directory.
1849 lpstrPathAndFile: cleaned up path
1853 (fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1854 !(fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
))
1855 nOpenAction
= ONOPEN_OPEN
;
1857 nOpenAction
= ONOPEN_BROWSE
;
1859 /* don't apply any checks with OFN_NOVALIDATE */
1861 LPWSTR lpszTemp
, lpszTemp1
;
1862 LPITEMIDLIST pidl
= NULL
;
1863 static const WCHAR szwInvalid
[] = { '/',':','<','>','|', 0};
1865 /* check for invalid chars */
1866 if((strpbrkW(lpstrPathAndFile
+3, szwInvalid
) != NULL
) && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1868 FILEDLG95_OnOpenMessage(hwnd
, IDS_INVALID_FILENAME_TITLE
, IDS_INVALID_FILENAME
);
1873 if (FAILED (SHGetDesktopFolder(&lpsf
))) return FALSE
;
1875 lpszTemp1
= lpszTemp
= lpstrPathAndFile
;
1878 LPSHELLFOLDER lpsfChild
;
1879 WCHAR lpwstrTemp
[MAX_PATH
];
1880 DWORD dwEaten
, dwAttributes
;
1883 strcpyW(lpwstrTemp
, lpszTemp
);
1884 p
= PathFindNextComponentW(lpwstrTemp
);
1886 if (!p
) break; /* end of path */
1889 lpszTemp
= lpszTemp
+ strlenW(lpwstrTemp
);
1891 /* There are no wildcards when OFN_NOVALIDATE is set */
1892 if(*lpszTemp
==0 && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1894 static const WCHAR wszWild
[] = { '*', '?', 0 };
1895 /* if the last element is a wildcard do a search */
1896 if(strpbrkW(lpszTemp1
, wszWild
) != NULL
)
1898 nOpenAction
= ONOPEN_SEARCH
;
1902 lpszTemp1
= lpszTemp
;
1904 TRACE("parse now=%s next=%s sf=%p\n",debugstr_w(lpwstrTemp
), debugstr_w(lpszTemp
), lpsf
);
1906 /* append a backslash to drive letters */
1907 if(lstrlenW(lpwstrTemp
)==2 && lpwstrTemp
[1] == ':' &&
1908 ((lpwstrTemp
[0] >= 'a' && lpwstrTemp
[0] <= 'z') ||
1909 (lpwstrTemp
[0] >= 'A' && lpwstrTemp
[0] <= 'Z')))
1911 PathAddBackslashW(lpwstrTemp
);
1914 dwAttributes
= SFGAO_FOLDER
;
1915 if(SUCCEEDED(IShellFolder_ParseDisplayName(lpsf
, hwnd
, NULL
, lpwstrTemp
, &dwEaten
, &pidl
, &dwAttributes
)))
1917 /* the path component is valid, we have a pidl of the next path component */
1918 TRACE("parse OK attr=0x%08lx pidl=%p\n", dwAttributes
, pidl
);
1919 if(dwAttributes
& SFGAO_FOLDER
)
1921 if(FAILED(IShellFolder_BindToObject(lpsf
, pidl
, 0, &IID_IShellFolder
, (LPVOID
*)&lpsfChild
)))
1923 ERR("bind to failed\n"); /* should not fail */
1926 IShellFolder_Release(lpsf
);
1934 /* end dialog, return value */
1935 nOpenAction
= ONOPEN_OPEN
;
1938 COMDLG32_SHFree(pidl
);
1941 else if (!(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1943 if(*lpszTemp
) /* points to trailing null for last path element */
1945 if(fodInfos
->ofnInfos
->Flags
& OFN_PATHMUSTEXIST
)
1947 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_PATHNOTEXISTING
);
1953 if( (fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1954 !( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1956 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_FILENOTEXISTING
);
1960 /* change to the current folder */
1961 nOpenAction
= ONOPEN_OPEN
;
1966 nOpenAction
= ONOPEN_OPEN
;
1970 if(pidl
) COMDLG32_SHFree(pidl
);
1974 Step 3: here we have a cleaned up and validated path
1977 lpsf: ShellFolder bound to the rightmost valid path component
1978 lpstrPathAndFile: cleaned up path
1979 nOpenAction: action to do
1981 TRACE("end validate sf=%p\n", lpsf
);
1985 case ONOPEN_SEARCH
: /* set the current filter to the file mask and refresh */
1986 TRACE("ONOPEN_SEARCH %s\n", debugstr_w(lpstrPathAndFile
));
1989 LPWSTR lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
1992 /* replace the current filter */
1993 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1994 len
= strlenW(lpszTemp
)+1;
1995 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc(len
* sizeof(WCHAR
));
1996 strcpyW( fodInfos
->ShellInfos
.lpstrCurrentFilter
, lpszTemp
);
1998 /* set the filter cb to the extension when possible */
1999 if(-1 < (iPos
= FILEDLG95_FILETYPE_SearchExt(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpszTemp
)))
2000 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, iPos
);
2003 case ONOPEN_BROWSE
: /* browse to the highest folder we could bind to */
2004 TRACE("ONOPEN_BROWSE\n");
2006 IPersistFolder2
* ppf2
;
2007 if(SUCCEEDED(IShellFolder_QueryInterface( lpsf
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
)))
2009 LPITEMIDLIST pidlCurrent
;
2010 IPersistFolder2_GetCurFolder(ppf2
, &pidlCurrent
);
2011 IPersistFolder2_Release(ppf2
);
2012 if( ! COMDLG32_PIDL_ILIsEqual(pidlCurrent
, fodInfos
->ShellInfos
.pidlAbsCurrent
))
2014 if (SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidlCurrent
, SBSP_ABSOLUTE
)))
2016 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2019 else if( nOpenAction
== ONOPEN_SEARCH
)
2021 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
2023 COMDLG32_SHFree(pidlCurrent
);
2028 case ONOPEN_OPEN
: /* fill in the return struct and close the dialog */
2029 TRACE("ONOPEN_OPEN %s\n", debugstr_w(lpstrPathAndFile
));
2033 /* update READONLY check box flag */
2034 if ((SendMessageA(GetDlgItem(hwnd
,IDC_OPENREADONLY
),BM_GETCHECK
,0,0) & 0x03) == BST_CHECKED
)
2035 fodInfos
->ofnInfos
->Flags
|= OFN_READONLY
;
2037 fodInfos
->ofnInfos
->Flags
&= ~OFN_READONLY
;
2039 /* Attach the file extension with file name*/
2040 ext
= PathFindExtensionW(lpstrPathAndFile
);
2043 /* if no extension is specified with file name, then */
2044 /* attach the extension from file filter or default one */
2046 WCHAR
*filterExt
= NULL
;
2047 LPWSTR lpstrFilter
= NULL
;
2048 static const WCHAR szwDot
[] = {'.',0};
2049 int PathLength
= strlenW(lpstrPathAndFile
);
2052 strcatW(lpstrPathAndFile
, szwDot
);
2054 /*Get the file extension from file type filter*/
2055 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2056 fodInfos
->ofnInfos
->nFilterIndex
-1);
2058 if (lpstrFilter
!= (LPWSTR
)CB_ERR
) /* control is not empty */
2059 filterExt
= PathFindExtensionW(lpstrFilter
);
2061 if ( filterExt
&& *filterExt
) /* attach the file extension from file type filter*/
2062 strcatW(lpstrPathAndFile
, filterExt
+ 1);
2063 else if ( fodInfos
->defext
) /* attach the default file extension*/
2064 strcatW(lpstrPathAndFile
, fodInfos
->defext
);
2066 /* In Open dialog: if file does not exist try without extension */
2067 if (!(fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) && !PathFileExistsW(lpstrPathAndFile
))
2068 lpstrPathAndFile
[PathLength
] = '\0';
2071 if (fodInfos
->defext
) /* add default extension */
2073 /* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
2076 if (!lstrcmpiW(fodInfos
->defext
, ext
))
2077 fodInfos
->ofnInfos
->Flags
&= ~OFN_EXTENSIONDIFFERENT
;
2079 fodInfos
->ofnInfos
->Flags
|= OFN_EXTENSIONDIFFERENT
;
2082 /* In Save dialog: check if the file already exists */
2083 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
2084 && fodInfos
->ofnInfos
->Flags
& OFN_OVERWRITEPROMPT
2085 && PathFileExistsW(lpstrPathAndFile
))
2087 WCHAR lpstrOverwrite
[100];
2090 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, lpstrOverwrite
, 100);
2091 answer
= MessageBoxW(hwnd
, lpstrOverwrite
, fodInfos
->title
,
2092 MB_YESNO
| MB_ICONEXCLAMATION
);
2100 /* Check that the size of the file does not exceed buffer size.
2101 (Allow for extra \0 if OFN_MULTISELECT is set.) */
2102 if(strlenW(lpstrPathAndFile
) < fodInfos
->ofnInfos
->nMaxFile
-
2103 ((fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
) ? 1 : 0))
2107 /* fill destination buffer */
2108 if (fodInfos
->ofnInfos
->lpstrFile
)
2110 if(fodInfos
->unicode
)
2112 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
2114 lstrcpynW(ofn
->lpstrFile
, lpstrPathAndFile
, ofn
->nMaxFile
);
2115 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
2116 ofn
->lpstrFile
[lstrlenW(ofn
->lpstrFile
) + 1] = '\0';
2120 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2122 WideCharToMultiByte(CP_ACP
, 0, lpstrPathAndFile
, -1,
2123 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
2124 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
2125 ofn
->lpstrFile
[lstrlenA(ofn
->lpstrFile
) + 1] = '\0';
2129 /* set filename offset */
2130 lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
2131 fodInfos
->ofnInfos
->nFileOffset
= (lpszTemp
- lpstrPathAndFile
);
2133 /* set extension offset */
2134 lpszTemp
= PathFindExtensionW(lpstrPathAndFile
);
2135 fodInfos
->ofnInfos
->nFileExtension
= (*lpszTemp
) ? (lpszTemp
- lpstrPathAndFile
) + 1 : 0;
2137 /* set the lpstrFileTitle */
2138 if(fodInfos
->ofnInfos
->lpstrFileTitle
)
2140 LPWSTR lpstrFileTitle
= PathFindFileNameW(lpstrPathAndFile
);
2141 if(fodInfos
->unicode
)
2143 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
2144 lstrcpynW(ofn
->lpstrFileTitle
, lpstrFileTitle
, ofn
->nMaxFileTitle
);
2148 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2149 WideCharToMultiByte(CP_ACP
, 0, lpstrFileTitle
, -1,
2150 ofn
->lpstrFileTitle
, ofn
->nMaxFileTitle
, NULL
, NULL
);
2154 /* copy currently selected filter to lpstrCustomFilter */
2155 if (fodInfos
->ofnInfos
->lpstrCustomFilter
)
2157 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2158 int len
= WideCharToMultiByte(CP_ACP
, 0, fodInfos
->ShellInfos
.lpstrCurrentFilter
, -1,
2159 NULL
, 0, NULL
, NULL
);
2160 if (len
+ strlen(ofn
->lpstrCustomFilter
) + 1 <= ofn
->nMaxCustFilter
)
2162 LPSTR s
= ofn
->lpstrCustomFilter
;
2163 s
+= strlen(ofn
->lpstrCustomFilter
)+1;
2164 WideCharToMultiByte(CP_ACP
, 0, fodInfos
->ShellInfos
.lpstrCurrentFilter
, -1,
2165 s
, len
, NULL
, NULL
);
2170 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
2174 FILEDLG95_Clean(hwnd
);
2175 ret
= EndDialog(hwnd
, TRUE
);
2181 size
= strlenW(lpstrPathAndFile
) + 1;
2182 if (fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
)
2184 /* return needed size in first two bytes of lpstrFile */
2185 *(WORD
*)fodInfos
->ofnInfos
->lpstrFile
= size
;
2186 FILEDLG95_Clean(hwnd
);
2187 ret
= EndDialog(hwnd
, FALSE
);
2188 COMDLG32_SetCommDlgExtendedError(FNERR_BUFFERTOOSMALL
);
2196 if(lpsf
) IShellFolder_Release(lpsf
);
2200 /***********************************************************************
2201 * FILEDLG95_SHELL_Init
2203 * Initialisation of the shell objects
2205 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
)
2207 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2212 * Initialisation of the FileOpenDialogInfos structure
2218 fodInfos
->ShellInfos
.hwndOwner
= hwnd
;
2220 /* Disable multi-select if flag not set */
2221 if (!(fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
))
2223 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_SINGLESEL
;
2225 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_AUTOARRANGE
| FWF_ALIGNLEFT
;
2226 fodInfos
->ShellInfos
.folderSettings
.ViewMode
= FVM_LIST
;
2228 /* Construct the IShellBrowser interface */
2229 fodInfos
->Shell
.FOIShellBrowser
= IShellBrowserImpl_Construct(hwnd
);
2234 /***********************************************************************
2235 * FILEDLG95_SHELL_ExecuteCommand
2237 * Change the folder option and refresh the view
2238 * If the function succeeds, the return value is nonzero.
2240 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
)
2242 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2245 TRACE("(%p,%p)\n", hwnd
, lpVerb
);
2247 if(SUCCEEDED(IShellView_GetItemObject(fodInfos
->Shell
.FOIShellView
,
2252 CMINVOKECOMMANDINFO ci
;
2253 ZeroMemory(&ci
, sizeof(CMINVOKECOMMANDINFO
));
2254 ci
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
2258 IContextMenu_InvokeCommand(pcm
, &ci
);
2259 IContextMenu_Release(pcm
);
2265 /***********************************************************************
2266 * FILEDLG95_SHELL_UpFolder
2268 * Browse to the specified object
2269 * If the function succeeds, the return value is nonzero.
2271 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
)
2273 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2277 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2281 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2287 /***********************************************************************
2288 * FILEDLG95_SHELL_BrowseToDesktop
2290 * Browse to the Desktop
2291 * If the function succeeds, the return value is nonzero.
2293 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
)
2295 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2301 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidl
);
2302 hres
= IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidl
, SBSP_ABSOLUTE
);
2303 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2304 COMDLG32_SHFree(pidl
);
2305 return SUCCEEDED(hres
);
2307 /***********************************************************************
2308 * FILEDLG95_SHELL_Clean
2310 * Cleans the memory used by shell objects
2312 static void FILEDLG95_SHELL_Clean(HWND hwnd
)
2314 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2318 COMDLG32_SHFree(fodInfos
->ShellInfos
.pidlAbsCurrent
);
2320 /* clean Shell interfaces */
2321 IShellView_DestroyViewWindow(fodInfos
->Shell
.FOIShellView
);
2322 IShellView_Release(fodInfos
->Shell
.FOIShellView
);
2323 IShellFolder_Release(fodInfos
->Shell
.FOIShellFolder
);
2324 IShellBrowser_Release(fodInfos
->Shell
.FOIShellBrowser
);
2325 if (fodInfos
->Shell
.FOIDataObject
)
2326 IDataObject_Release(fodInfos
->Shell
.FOIDataObject
);
2329 /***********************************************************************
2330 * FILEDLG95_FILETYPE_Init
2332 * Initialisation of the file type combo box
2334 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
)
2336 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2337 int nFilters
= 0; /* number of filters */
2342 if(fodInfos
->customfilter
)
2344 /* customfilter has one entry... title\0ext\0
2345 * Set first entry of combo box item with customfilter
2348 LPCWSTR lpstrPos
= fodInfos
->customfilter
;
2351 lpstrPos
+= strlenW(fodInfos
->customfilter
) + 1;
2353 /* Copy the extensions */
2354 if (! *lpstrPos
) return E_FAIL
; /* malformed filter */
2355 if (!(lpstrExt
= MemAlloc((strlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2356 strcpyW(lpstrExt
,lpstrPos
);
2358 /* Add the item at the end of the combo */
2359 CBAddStringW(fodInfos
->DlgInfos
.hwndFileTypeCB
, fodInfos
->customfilter
);
2360 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
, lpstrExt
);
2363 if(fodInfos
->filter
)
2365 LPCWSTR lpstrPos
= fodInfos
->filter
;
2369 /* filter is a list... title\0ext\0......\0\0
2370 * Set the combo item text to the title and the item data
2373 LPCWSTR lpstrDisplay
;
2377 if(! *lpstrPos
) break; /* end */
2378 lpstrDisplay
= lpstrPos
;
2379 lpstrPos
+= strlenW(lpstrPos
) + 1;
2381 CBAddStringW(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpstrDisplay
);
2385 /* Copy the extensions */
2386 if (!(lpstrExt
= MemAlloc((strlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2387 strcpyW(lpstrExt
,lpstrPos
);
2388 lpstrPos
+= strlenW(lpstrPos
) + 1;
2390 /* Add the item at the end of the combo */
2391 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
-1, lpstrExt
);
2393 /* malformed filters are added anyway... */
2394 if (!*lpstrExt
) break;
2399 * Set the current filter to the one specified
2400 * in the initialisation structure
2402 if (fodInfos
->filter
|| fodInfos
->customfilter
)
2406 /* Check to make sure our index isn't out of bounds. */
2407 if ( fodInfos
->ofnInfos
->nFilterIndex
>
2408 nFilters
- (fodInfos
->customfilter
== NULL
? 0 : 1) )
2409 fodInfos
->ofnInfos
->nFilterIndex
= (fodInfos
->customfilter
== NULL
? 1 : 0);
2411 /* set default filter index */
2412 if(fodInfos
->ofnInfos
->nFilterIndex
== 0 && fodInfos
->customfilter
== NULL
)
2413 fodInfos
->ofnInfos
->nFilterIndex
= 1;
2415 /* calculate index of Combo Box item */
2416 nFilterIndexCB
= fodInfos
->ofnInfos
->nFilterIndex
;
2417 if (fodInfos
->customfilter
== NULL
)
2420 /* Set the current index selection. */
2421 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilterIndexCB
);
2423 /* Get the corresponding text string from the combo box. */
2424 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2427 if ((INT_PTR
)lpstrFilter
== CB_ERR
) /* control is empty */
2433 CharLowerW(lpstrFilter
); /* lowercase */
2434 len
= strlenW(lpstrFilter
)+1;
2435 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2436 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2439 fodInfos
->ofnInfos
->nFilterIndex
= 0;
2443 /***********************************************************************
2444 * FILEDLG95_FILETYPE_OnCommand
2446 * WM_COMMAND of the file type combo box
2447 * If the function succeeds, the return value is nonzero.
2449 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2451 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2459 /* Get the current item of the filetype combo box */
2460 int iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2462 /* set the current filter index */
2463 fodInfos
->ofnInfos
->nFilterIndex
= iItem
+
2464 (fodInfos
->customfilter
== NULL
? 1 : 0);
2466 /* Set the current filter with the current selection */
2467 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2469 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2471 if((INT_PTR
)lpstrFilter
!= CB_ERR
)
2474 CharLowerW(lpstrFilter
); /* lowercase */
2475 len
= strlenW(lpstrFilter
)+1;
2476 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2477 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2478 SendCustomDlgNotificationMessage(hwnd
,CDN_TYPECHANGE
);
2481 /* Refresh the actual view to display the included items*/
2482 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
2487 /***********************************************************************
2488 * FILEDLG95_FILETYPE_SearchExt
2490 * searches for an extension in the filetype box
2492 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
)
2494 int i
, iCount
= CBGetCount(hwnd
);
2496 TRACE("%s\n", debugstr_w(lpstrExt
));
2498 if(iCount
!= CB_ERR
)
2500 for(i
=0;i
<iCount
;i
++)
2502 if(!lstrcmpiW(lpstrExt
,(LPWSTR
)CBGetItemDataPtr(hwnd
,i
)))
2509 /***********************************************************************
2510 * FILEDLG95_FILETYPE_Clean
2512 * Clean the memory used by the filetype combo box
2514 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
)
2516 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2518 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2522 /* Delete each string of the combo and their associated data */
2523 if(iCount
!= CB_ERR
)
2525 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2527 MemFree((LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
));
2528 CBDeleteString(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
2531 /* Current filter */
2532 MemFree(fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2536 /***********************************************************************
2537 * FILEDLG95_LOOKIN_Init
2539 * Initialisation of the look in combo box
2542 /* Small helper function, to determine if the unixfs shell extension is rooted
2543 * at the desktop. Copied from dlls/shell32/shfldr_unixfs.c.
2545 static inline BOOL
FILEDLG95_unixfs_is_rooted_at_desktop(void) {
2547 static const WCHAR wszRootedAtDesktop
[] = { 'S','o','f','t','w','a','r','e','\\',
2548 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2549 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2550 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
2551 'N','a','m','e','S','p','a','c','e','\\','{','9','D','2','0','A','A','E','8',
2552 '-','0','6','2','5','-','4','4','B','0','-','9','C','A','7','-',
2553 '7','1','8','8','9','C','2','2','5','4','D','9','}',0 };
2555 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, wszRootedAtDesktop
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
2562 static void FILEDLG95_LOOKIN_Init(HWND hwndCombo
)
2564 IShellFolder
*psfRoot
, *psfDrives
;
2565 IEnumIDList
*lpeRoot
, *lpeDrives
;
2566 LPITEMIDLIST pidlDrives
, pidlTmp
, pidlTmp1
, pidlAbsTmp
;
2568 LookInInfos
*liInfos
= MemAlloc(sizeof(LookInInfos
));
2572 liInfos
->iMaxIndentation
= 0;
2574 SetPropA(hwndCombo
, LookInInfosStr
, (HANDLE
) liInfos
);
2576 /* set item height for both text field and listbox */
2577 CBSetItemHeight(hwndCombo
,-1,GetSystemMetrics(SM_CYSMICON
));
2578 CBSetItemHeight(hwndCombo
,0,GetSystemMetrics(SM_CYSMICON
));
2580 /* Turn on the extended UI for the combo box like Windows does */
2581 CBSetExtendedUI(hwndCombo
, TRUE
);
2583 /* Initialise data of Desktop folder */
2584 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidlTmp
);
2585 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2586 COMDLG32_SHFree(pidlTmp
);
2588 SHGetSpecialFolderLocation(0,CSIDL_DRIVES
,&pidlDrives
);
2590 SHGetDesktopFolder(&psfRoot
);
2594 /* enumerate the contents of the desktop */
2595 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot
, hwndCombo
, SHCONTF_FOLDERS
, &lpeRoot
)))
2597 while (S_OK
== IEnumIDList_Next(lpeRoot
, 1, &pidlTmp
, NULL
))
2599 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2601 /* If the unixfs extension is rooted, we don't expand the drives by default */
2602 if (!FILEDLG95_unixfs_is_rooted_at_desktop())
2604 /* special handling for CSIDL_DRIVES */
2605 if (COMDLG32_PIDL_ILIsEqual(pidlTmp
, pidlDrives
))
2607 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot
, pidlTmp
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfDrives
)))
2609 /* enumerate the drives */
2610 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives
, hwndCombo
,SHCONTF_FOLDERS
, &lpeDrives
)))
2612 while (S_OK
== IEnumIDList_Next(lpeDrives
, 1, &pidlTmp1
, NULL
))
2614 pidlAbsTmp
= COMDLG32_PIDL_ILCombine(pidlTmp
, pidlTmp1
);
2615 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlAbsTmp
,LISTEND
);
2616 COMDLG32_SHFree(pidlAbsTmp
);
2617 COMDLG32_SHFree(pidlTmp1
);
2619 IEnumIDList_Release(lpeDrives
);
2621 IShellFolder_Release(psfDrives
);
2626 COMDLG32_SHFree(pidlTmp
);
2628 IEnumIDList_Release(lpeRoot
);
2630 IShellFolder_Release(psfRoot
);
2633 COMDLG32_SHFree(pidlDrives
);
2636 /***********************************************************************
2637 * FILEDLG95_LOOKIN_DrawItem
2639 * WM_DRAWITEM message handler
2641 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
)
2643 COLORREF crWin
= GetSysColor(COLOR_WINDOW
);
2644 COLORREF crHighLight
= GetSysColor(COLOR_HIGHLIGHT
);
2645 COLORREF crText
= GetSysColor(COLOR_WINDOWTEXT
);
2649 HIMAGELIST ilItemImage
;
2652 LPSFOLDER tmpFolder
;
2655 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(pDIStruct
->hwndItem
,LookInInfosStr
);
2659 if(pDIStruct
->itemID
== -1)
2662 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(pDIStruct
->hwndItem
,
2663 pDIStruct
->itemID
)))
2667 if(pDIStruct
->itemID
== liInfos
->uSelectedItem
)
2669 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2672 sizeof (SHFILEINFOA
),
2673 SHGFI_PIDL
| SHGFI_SMALLICON
|
2674 SHGFI_OPENICON
| SHGFI_SYSICONINDEX
|
2675 SHGFI_DISPLAYNAME
);
2679 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2682 sizeof (SHFILEINFOA
),
2683 SHGFI_PIDL
| SHGFI_SMALLICON
|
2684 SHGFI_SYSICONINDEX
|
2688 /* Is this item selected ? */
2689 if(pDIStruct
->itemState
& ODS_SELECTED
)
2691 SetTextColor(pDIStruct
->hDC
,(0x00FFFFFF & ~(crText
)));
2692 SetBkColor(pDIStruct
->hDC
,crHighLight
);
2693 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_HIGHLIGHT
));
2697 SetTextColor(pDIStruct
->hDC
,crText
);
2698 SetBkColor(pDIStruct
->hDC
,crWin
);
2699 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_WINDOW
));
2702 /* Do not indent item if drawing in the edit of the combo */
2703 if(pDIStruct
->itemState
& ODS_COMBOBOXEDIT
)
2706 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2709 sizeof (SHFILEINFOA
),
2710 SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_OPENICON
2711 | SHGFI_SYSICONINDEX
| SHGFI_DISPLAYNAME
);
2716 iIndentation
= tmpFolder
->m_iIndent
;
2718 /* Draw text and icon */
2720 /* Initialise the icon display area */
2721 rectIcon
.left
= pDIStruct
->rcItem
.left
+ ICONWIDTH
/2 * iIndentation
;
2722 rectIcon
.top
= pDIStruct
->rcItem
.top
;
2723 rectIcon
.right
= rectIcon
.left
+ ICONWIDTH
;
2724 rectIcon
.bottom
= pDIStruct
->rcItem
.bottom
;
2726 /* Initialise the text display area */
2727 GetTextMetricsA(pDIStruct
->hDC
, &tm
);
2728 rectText
.left
= rectIcon
.right
;
2730 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
- tm
.tmHeight
) / 2;
2731 rectText
.right
= pDIStruct
->rcItem
.right
+ XTEXTOFFSET
;
2733 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
+ tm
.tmHeight
) / 2;
2735 /* Draw the icon from the image list */
2736 ImageList_Draw(ilItemImage
,
2743 /* Draw the associated text */
2744 if(sfi
.szDisplayName
)
2745 TextOutA(pDIStruct
->hDC
,rectText
.left
,rectText
.top
,sfi
.szDisplayName
,strlen(sfi
.szDisplayName
));
2751 /***********************************************************************
2752 * FILEDLG95_LOOKIN_OnCommand
2754 * LookIn combo box WM_COMMAND message handler
2755 * If the function succeeds, the return value is nonzero.
2757 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2759 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2761 TRACE("%p\n", fodInfos
);
2767 LPSFOLDER tmpFolder
;
2770 iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndLookInCB
);
2772 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,
2777 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2778 tmpFolder
->pidlItem
,
2781 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2791 /***********************************************************************
2792 * FILEDLG95_LOOKIN_AddItem
2794 * Adds an absolute pidl item to the lookin combo box
2795 * returns the index of the inserted item
2797 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
)
2799 LPITEMIDLIST pidlNext
;
2802 LookInInfos
*liInfos
;
2804 TRACE("%08x\n", iInsertId
);
2809 if(!(liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
)))
2812 tmpFolder
= MemAlloc(sizeof(SFOLDER
));
2813 tmpFolder
->m_iIndent
= 0;
2815 /* Calculate the indentation of the item in the lookin*/
2817 while( (pidlNext
=COMDLG32_PIDL_ILGetNext(pidlNext
)) )
2819 tmpFolder
->m_iIndent
++;
2822 tmpFolder
->pidlItem
= COMDLG32_PIDL_ILClone(pidl
);
2824 if(tmpFolder
->m_iIndent
> liInfos
->iMaxIndentation
)
2825 liInfos
->iMaxIndentation
= tmpFolder
->m_iIndent
;
2827 sfi
.dwAttributes
= SFGAO_FILESYSANCESTOR
| SFGAO_FILESYSTEM
;
2828 SHGetFileInfoA((LPSTR
)pidl
,
2832 SHGFI_DISPLAYNAME
| SHGFI_SYSICONINDEX
2833 | SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_ATTRIBUTES
| SHGFI_ATTR_SPECIFIED
);
2835 TRACE("-- Add %s attr=%08lx\n", sfi
.szDisplayName
, sfi
.dwAttributes
);
2837 if((sfi
.dwAttributes
& SFGAO_FILESYSANCESTOR
) || (sfi
.dwAttributes
& SFGAO_FILESYSTEM
))
2841 TRACE("-- Add %s at %u\n", sfi
.szDisplayName
, tmpFolder
->m_iIndent
);
2843 /* Add the item at the end of the list */
2846 iItemID
= CBAddString(hwnd
,sfi
.szDisplayName
);
2848 /* Insert the item at the iInsertId position*/
2851 iItemID
= CBInsertString(hwnd
,sfi
.szDisplayName
,iInsertId
);
2854 CBSetItemDataPtr(hwnd
,iItemID
,tmpFolder
);
2858 COMDLG32_SHFree( tmpFolder
->pidlItem
);
2859 MemFree( tmpFolder
);
2864 /***********************************************************************
2865 * FILEDLG95_LOOKIN_InsertItemAfterParent
2867 * Insert an item below its parent
2869 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
)
2872 LPITEMIDLIST pidlParent
= GetParentPidl(pidl
);
2877 iParentPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidlParent
,SEARCH_PIDL
);
2881 iParentPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidlParent
);
2884 /* Free pidlParent memory */
2885 COMDLG32_SHFree((LPVOID
)pidlParent
);
2887 return FILEDLG95_LOOKIN_AddItem(hwnd
,pidl
,iParentPos
+ 1);
2890 /***********************************************************************
2891 * FILEDLG95_LOOKIN_SelectItem
2893 * Adds an absolute pidl item to the lookin combo box
2894 * returns the index of the inserted item
2896 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
)
2899 LookInInfos
*liInfos
;
2903 iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidl
,SEARCH_PIDL
);
2905 liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2909 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
) > -1);
2910 iItemPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidl
);
2915 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2916 while(liInfos
->iMaxIndentation
> tmpFolder
->m_iIndent
)
2920 if(-1 == (iRemovedItem
= FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
)))
2922 if(iRemovedItem
< iItemPos
)
2927 CBSetCurSel(hwnd
,iItemPos
);
2928 liInfos
->uSelectedItem
= iItemPos
;
2934 /***********************************************************************
2935 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2937 * Remove the item with an expansion level over iExpansionLevel
2939 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
)
2943 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2947 if(liInfos
->iMaxIndentation
<= 2)
2950 if((iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)liInfos
->iMaxIndentation
,SEARCH_EXP
)) >=0)
2952 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2953 COMDLG32_SHFree(tmpFolder
->pidlItem
);
2955 CBDeleteString(hwnd
,iItemPos
);
2956 liInfos
->iMaxIndentation
--;
2964 /***********************************************************************
2965 * FILEDLG95_LOOKIN_SearchItem
2967 * Search for pidl in the lookin combo box
2968 * returns the index of the found item
2970 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
)
2973 int iCount
= CBGetCount(hwnd
);
2975 TRACE("0x%08x 0x%x\n",searchArg
, iSearchMethod
);
2977 if (iCount
!= CB_ERR
)
2981 LPSFOLDER tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,i
);
2983 if(iSearchMethod
== SEARCH_PIDL
&& COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST
)searchArg
,tmpFolder
->pidlItem
))
2985 if(iSearchMethod
== SEARCH_EXP
&& tmpFolder
->m_iIndent
== (int)searchArg
)
2993 /***********************************************************************
2994 * FILEDLG95_LOOKIN_Clean
2996 * Clean the memory used by the lookin combo box
2998 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
)
3000 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3002 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndLookInCB
);
3006 /* Delete each string of the combo and their associated data */
3007 if (iCount
!= CB_ERR
)
3009 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
3011 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
3012 COMDLG32_SHFree(tmpFolder
->pidlItem
);
3014 CBDeleteString(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
3018 /* LookInInfos structure */
3019 RemovePropA(fodInfos
->DlgInfos
.hwndLookInCB
,LookInInfosStr
);
3022 /***********************************************************************
3023 * FILEDLG95_FILENAME_FillFromSelection
3025 * fills the edit box from the cached DataObject
3027 void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd
)
3029 FileOpenDlgInfos
*fodInfos
;
3031 UINT nFiles
= 0, nFileToOpen
, nFileSelected
, nLength
= 0;
3032 char lpstrTemp
[MAX_PATH
];
3033 LPSTR lpstrAllFile
= NULL
, lpstrCurrFile
= NULL
;
3036 fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3038 /* Count how many files we have */
3039 nFileSelected
= GetNumSelected( fodInfos
->Shell
.FOIDataObject
);
3041 /* calculate the string length, count files */
3042 if (nFileSelected
>= 1)
3044 nLength
+= 3; /* first and last quotes, trailing \0 */
3045 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
3047 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
3051 /* get the total length of the selected file names */
3052 lpstrTemp
[0] = '\0';
3053 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
3055 if ( ! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
) ) /* Ignore folders */
3057 nLength
+= strlen( lpstrTemp
) + 3;
3060 COMDLG32_SHFree( pidl
);
3065 /* allocate the buffer */
3066 if (nFiles
<= 1) nLength
= MAX_PATH
;
3067 lpstrAllFile
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nLength
);
3068 lpstrAllFile
[0] = '\0';
3070 /* Generate the string for the edit control */
3073 lpstrCurrFile
= lpstrAllFile
;
3074 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
3076 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
3080 /* get the file name */
3081 lpstrTemp
[0] = '\0';
3082 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
3084 if (! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
)) /* Ignore folders */
3088 *lpstrCurrFile
++ = '\"';
3089 strcpy( lpstrCurrFile
, lpstrTemp
);
3090 lpstrCurrFile
+= strlen( lpstrTemp
);
3091 strcpy( lpstrCurrFile
, "\" " );
3096 strcpy( lpstrAllFile
, lpstrTemp
);
3099 COMDLG32_SHFree( (LPVOID
) pidl
);
3102 SetWindowTextA( fodInfos
->DlgInfos
.hwndFileName
, lpstrAllFile
);
3104 /* Select the file name like Windows does */
3105 SendMessageA(fodInfos
->DlgInfos
.hwndFileName
, EM_SETSEL
, (WPARAM
)0, (LPARAM
)-1);
3107 HeapFree(GetProcessHeap(),0, lpstrAllFile
);
3111 /* copied from shell32 to avoid linking to it
3112 * FIXME: why? shell32 is already linked
3114 static HRESULT
COMDLG32_StrRetToStrNA (LPVOID dest
, DWORD len
, LPSTRRET src
, LPITEMIDLIST pidl
)
3119 WideCharToMultiByte(CP_ACP
, 0, src
->u
.pOleStr
, -1, (LPSTR
)dest
, len
, NULL
, NULL
);
3120 COMDLG32_SHFree(src
->u
.pOleStr
);
3124 lstrcpynA((LPSTR
)dest
, src
->u
.cStr
, len
);
3128 lstrcpynA((LPSTR
)dest
, ((LPCSTR
)&pidl
->mkid
)+src
->u
.uOffset
, len
);
3132 FIXME("unknown type!\n");
3135 *(LPSTR
)dest
= '\0';
3142 /***********************************************************************
3143 * FILEDLG95_FILENAME_GetFileNames
3145 * Copies the filenames to a delimited string list.
3146 * The delimiter is specified by the parameter 'separator',
3147 * usually either a space or a nul
3149 static int FILEDLG95_FILENAME_GetFileNames (HWND hwnd
, LPWSTR
* lpstrFileList
, UINT
* sizeUsed
, char separator
)
3151 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3152 UINT nStrCharCount
= 0; /* index in src buffer */
3153 UINT nFileIndex
= 0; /* index in dest buffer */
3154 UINT nFileCount
= 0; /* number of files */
3155 UINT nStrLen
= 0; /* length of string in edit control */
3156 LPWSTR lpstrEdit
; /* buffer for string from edit control */
3160 /* get the filenames from the edit control */
3161 nStrLen
= SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXTLENGTH
, 0, 0);
3162 lpstrEdit
= MemAlloc( (nStrLen
+1)*sizeof(WCHAR
) );
3163 GetDlgItemTextW(hwnd
, IDC_FILENAME
, lpstrEdit
, nStrLen
+1);
3165 TRACE("nStrLen=%u str=%s\n", nStrLen
, debugstr_w(lpstrEdit
));
3167 /* we might get single filename without any '"',
3168 * so we need nStrLen + terminating \0 + end-of-list \0 */
3169 *lpstrFileList
= MemAlloc( (nStrLen
+2)*sizeof(WCHAR
) );
3172 /* build delimited file list from filenames */
3173 while ( nStrCharCount
<= nStrLen
)
3175 if ( lpstrEdit
[nStrCharCount
]=='"' )
3178 while ((lpstrEdit
[nStrCharCount
]!='"') && (nStrCharCount
<= nStrLen
))
3180 (*lpstrFileList
)[nFileIndex
++] = lpstrEdit
[nStrCharCount
];
3184 (*lpstrFileList
)[nFileIndex
++] = separator
;
3191 /* single, unquoted string */
3192 if ((nStrLen
> 0) && (*sizeUsed
== 0) )
3194 strcpyW(*lpstrFileList
, lpstrEdit
);
3195 nFileIndex
= strlenW(lpstrEdit
) + 1;
3196 (*sizeUsed
) = nFileIndex
;
3201 (*lpstrFileList
)[nFileIndex
] = '\0';
3208 #define SETDefFormatEtc(fe,cf,med) \
3210 (fe).cfFormat = cf;\
3211 (fe).dwAspect = DVASPECT_CONTENT; \
3218 * DATAOBJECT Helper functions
3221 /***********************************************************************
3222 * COMCTL32_ReleaseStgMedium
3224 * like ReleaseStgMedium from ole32
3226 static void COMCTL32_ReleaseStgMedium (STGMEDIUM medium
)
3228 if(medium
.pUnkForRelease
)
3230 IUnknown_Release(medium
.pUnkForRelease
);
3234 GlobalUnlock(medium
.u
.hGlobal
);
3235 GlobalFree(medium
.u
.hGlobal
);
3239 /***********************************************************************
3240 * GetPidlFromDataObject
3242 * Return pidl(s) by number from the cached DataObject
3244 * nPidlIndex=0 gets the fully qualified root path
3246 LPITEMIDLIST
GetPidlFromDataObject ( IDataObject
*doSelected
, UINT nPidlIndex
)
3250 FORMATETC formatetc
;
3251 LPITEMIDLIST pidl
= NULL
;
3253 TRACE("sv=%p index=%u\n", doSelected
, nPidlIndex
);
3258 /* Set the FORMATETC structure*/
3259 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
3261 /* Get the pidls from IDataObject */
3262 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3264 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3265 if(nPidlIndex
<= cida
->cidl
)
3267 pidl
= COMDLG32_PIDL_ILClone((LPITEMIDLIST
)(&((LPBYTE
)cida
)[cida
->aoffset
[nPidlIndex
]]));
3269 COMCTL32_ReleaseStgMedium(medium
);
3274 /***********************************************************************
3277 * Return the number of selected items in the DataObject.
3280 UINT
GetNumSelected( IDataObject
*doSelected
)
3284 FORMATETC formatetc
;
3286 TRACE("sv=%p\n", doSelected
);
3288 if (!doSelected
) return 0;
3290 /* Set the FORMATETC structure*/
3291 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
3293 /* Get the pidls from IDataObject */
3294 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3296 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3297 retVal
= cida
->cidl
;
3298 COMCTL32_ReleaseStgMedium(medium
);
3308 /***********************************************************************
3311 * Get the pidl's display name (relative to folder) and
3312 * put it in lpstrFileName.
3314 * Return NOERROR on success,
3318 static HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
)
3323 TRACE("sf=%p pidl=%p\n", lpsf
, pidl
);
3327 SHGetDesktopFolder(&lpsf
);
3328 hRes
= GetName(lpsf
,pidl
,dwFlags
,lpstrFileName
);
3329 IShellFolder_Release(lpsf
);
3333 /* Get the display name of the pidl relative to the folder */
3334 if (SUCCEEDED(hRes
= IShellFolder_GetDisplayNameOf(lpsf
, pidl
, dwFlags
, &str
)))
3336 return COMDLG32_StrRetToStrNA(lpstrFileName
, MAX_PATH
, &str
, pidl
);
3341 /***********************************************************************
3342 * GetShellFolderFromPidl
3344 * pidlRel is the item pidl relative
3345 * Return the IShellFolder of the absolute pidl
3347 IShellFolder
*GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
)
3349 IShellFolder
*psf
= NULL
,*psfParent
;
3351 TRACE("%p\n", pidlAbs
);
3353 if(SUCCEEDED(SHGetDesktopFolder(&psfParent
)))
3356 if(pidlAbs
&& pidlAbs
->mkid
.cb
)
3358 if(SUCCEEDED(IShellFolder_BindToObject(psfParent
, pidlAbs
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psf
)))
3360 IShellFolder_Release(psfParent
);
3364 /* return the desktop */
3370 /***********************************************************************
3373 * Return the LPITEMIDLIST to the parent of the pidl in the list
3375 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
)
3377 LPITEMIDLIST pidlParent
;
3379 TRACE("%p\n", pidl
);
3381 pidlParent
= COMDLG32_PIDL_ILClone(pidl
);
3382 COMDLG32_PIDL_ILRemoveLastID(pidlParent
);
3387 /***********************************************************************
3390 * returns the pidl of the file name relative to folder
3391 * NULL if an error occurred
3393 LPITEMIDLIST
GetPidlFromName(IShellFolder
*lpsf
,LPWSTR lpcstrFileName
)
3395 LPITEMIDLIST pidl
= NULL
;
3398 TRACE("sf=%p file=%s\n", lpsf
, debugstr_w(lpcstrFileName
));
3400 if(!lpcstrFileName
) return NULL
;
3401 if(!*lpcstrFileName
) return NULL
;
3405 if (SUCCEEDED(SHGetDesktopFolder(&lpsf
))) {
3406 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3407 IShellFolder_Release(lpsf
);
3412 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3419 BOOL
IsPidlFolder (LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
)
3421 ULONG uAttr
= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
;
3424 TRACE("%p, %p\n", psf
, pidl
);
3426 ret
= IShellFolder_GetAttributesOf( psf
, 1, &pidl
, &uAttr
);
3428 TRACE("-- 0x%08lx 0x%08lx\n", uAttr
, ret
);
3429 /* see documentation shell 4.1*/
3430 return uAttr
& (SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
);
3433 /***********************************************************************
3434 * BrowseSelectedFolder
3436 static BOOL
BrowseSelectedFolder(HWND hwnd
)
3438 BOOL bBrowseSelFolder
= FALSE
;
3439 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3443 if (GetNumSelected(fodInfos
->Shell
.FOIDataObject
) == 1)
3445 LPITEMIDLIST pidlSelection
;
3447 /* get the file selected */
3448 pidlSelection
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, 1);
3449 if (IsPidlFolder (fodInfos
->Shell
.FOIShellFolder
, pidlSelection
))
3451 if ( FAILED( IShellBrowser_BrowseObject( fodInfos
->Shell
.FOIShellBrowser
,
3452 pidlSelection
, SBSP_RELATIVE
) ) )
3454 static const WCHAR notexist
[] = {'P','a','t','h',' ','d','o','e','s',
3455 ' ','n','o','t',' ','e','x','i','s','t',0};
3456 MessageBoxW( hwnd
, notexist
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
3458 bBrowseSelFolder
= TRUE
;
3459 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
3461 COMDLG32_SHFree( pidlSelection
);
3464 return bBrowseSelFolder
;
3468 * Memory allocation methods */
3469 static void *MemAlloc(UINT size
)
3471 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
3474 static void MemFree(void *mem
)
3476 HeapFree(GetProcessHeap(),0,mem
);
3480 * Old-style (win3.1) dialogs */
3482 /***********************************************************************
3483 * FD32_GetTemplate [internal]
3485 * Get a template (or FALSE if failure) when 16 bits dialogs are used
3486 * by a 32 bits application
3489 static BOOL
FD32_GetTemplate(PFD31_DATA lfs
)
3491 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3492 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3495 if (ofnW
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
3497 if (!(lfs
->template = LockResource( ofnW
->hInstance
)))
3499 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3503 else if (ofnW
->Flags
& OFN_ENABLETEMPLATE
)
3507 hResInfo
= FindResourceA(priv
->ofnA
->hInstance
,
3508 priv
->ofnA
->lpTemplateName
,
3511 hResInfo
= FindResourceW(ofnW
->hInstance
,
3512 ofnW
->lpTemplateName
,
3516 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
3519 if (!(hDlgTmpl
= LoadResource(ofnW
->hInstance
,
3521 !(lfs
->template = LockResource(hDlgTmpl
)))
3523 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3526 } else { /* get it from internal Wine resource */
3528 if (!(hResInfo
= FindResourceA(COMDLG32_hInstance
,
3529 lfs
->open
? "OPEN_FILE":"SAVE_FILE", (LPSTR
)RT_DIALOG
)))
3531 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
3534 if (!(hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
)) ||
3535 !(lfs
->template = LockResource( hDlgTmpl
)))
3537 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3545 /************************************************************************
3546 * FD32_Init [internal]
3547 * called from the common 16/32 code to initialize 32 bit data
3549 static BOOL CALLBACK
FD32_Init(LPARAM lParam
, PFD31_DATA lfs
, DWORD data
)
3551 BOOL IsUnicode
= (BOOL
) data
;
3554 priv
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FD32_PRIVATE
));
3555 lfs
->private1632
= priv
;
3556 if (NULL
== lfs
->private1632
) return FALSE
;
3559 lfs
->ofnW
= (LPOPENFILENAMEW
) lParam
;
3560 if (lfs
->ofnW
->Flags
& OFN_ENABLEHOOK
)
3561 if (lfs
->ofnW
->lpfnHook
)
3566 priv
->ofnA
= (LPOPENFILENAMEA
) lParam
;
3567 if (priv
->ofnA
->Flags
& OFN_ENABLEHOOK
)
3568 if (priv
->ofnA
->lpfnHook
)
3570 lfs
->ofnW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*lfs
->ofnW
));
3571 FD31_MapOfnStructA(priv
->ofnA
, lfs
->ofnW
, lfs
->open
);
3574 if (! FD32_GetTemplate(lfs
)) return FALSE
;
3579 /***********************************************************************
3580 * FD32_CallWindowProc [internal]
3582 * called from the common 16/32 code to call the appropriate hook
3584 static BOOL CALLBACK
FD32_CallWindowProc(PFD31_DATA lfs
, UINT wMsg
, WPARAM wParam
,
3588 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3592 TRACE("Call hookA %p (%p, %04x, %08x, %08lx)\n",
3593 priv
->ofnA
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3594 ret
= priv
->ofnA
->lpfnHook(lfs
->hwnd
, wMsg
, wParam
, lParam
);
3595 TRACE("ret hookA %p (%p, %04x, %08x, %08lx)\n",
3596 priv
->ofnA
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3600 TRACE("Call hookW %p (%p, %04x, %08x, %08lx)\n",
3601 lfs
->ofnW
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3602 ret
= lfs
->ofnW
->lpfnHook(lfs
->hwnd
, wMsg
, wParam
, lParam
);
3603 TRACE("Ret hookW %p (%p, %04x, %08x, %08lx)\n",
3604 lfs
->ofnW
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3608 /***********************************************************************
3609 * FD32_UpdateResult [internal]
3610 * update the real client structures if any
3612 static void CALLBACK
FD32_UpdateResult(PFD31_DATA lfs
)
3614 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3615 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3619 if (ofnW
->nMaxFile
&&
3620 !WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFile
, -1,
3621 priv
->ofnA
->lpstrFile
, ofnW
->nMaxFile
, NULL
, NULL
))
3622 priv
->ofnA
->lpstrFile
[ofnW
->nMaxFile
-1] = 0;
3623 priv
->ofnA
->nFileOffset
= ofnW
->nFileOffset
;
3624 priv
->ofnA
->nFileExtension
= ofnW
->nFileExtension
;
3628 /***********************************************************************
3629 * FD32_UpdateFileTitle [internal]
3630 * update the real client structures if any
3632 static void CALLBACK
FD32_UpdateFileTitle(PFD31_DATA lfs
)
3634 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3635 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3639 if (!WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFileTitle
, -1,
3640 priv
->ofnA
->lpstrFileTitle
, ofnW
->nMaxFileTitle
, NULL
, NULL
))
3641 priv
->ofnA
->lpstrFileTitle
[ofnW
->nMaxFileTitle
-1] = 0;
3646 /***********************************************************************
3647 * FD32_SendLbGetCurSel [internal]
3648 * retrieve selected listbox item
3650 static LRESULT CALLBACK
FD32_SendLbGetCurSel(PFD31_DATA lfs
)
3652 return SendDlgItemMessageW(lfs
->hwnd
, lst1
, LB_GETCURSEL
, 0, 0);
3656 /************************************************************************
3657 * FD32_Destroy [internal]
3658 * called from the common 16/32 code to cleanup 32 bit data
3660 static void CALLBACK
FD32_Destroy(PFD31_DATA lfs
)
3662 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3664 /* if ofnW has been allocated, have to free everything in it */
3665 if (NULL
!= priv
&& NULL
!= priv
->ofnA
)
3667 FD31_FreeOfnW(lfs
->ofnW
);
3668 HeapFree(GetProcessHeap(), 0, lfs
->ofnW
);
3672 static void FD32_SetupCallbacks(PFD31_CALLBACKS callbacks
)
3674 callbacks
->Init
= FD32_Init
;
3675 callbacks
->CWP
= FD32_CallWindowProc
;
3676 callbacks
->UpdateResult
= FD32_UpdateResult
;
3677 callbacks
->UpdateFileTitle
= FD32_UpdateFileTitle
;
3678 callbacks
->SendLbGetCurSel
= FD32_SendLbGetCurSel
;
3679 callbacks
->Destroy
= FD32_Destroy
;
3682 /***********************************************************************
3683 * FD32_WMMeasureItem [internal]
3685 static LONG
FD32_WMMeasureItem(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
3687 LPMEASUREITEMSTRUCT lpmeasure
;
3689 lpmeasure
= (LPMEASUREITEMSTRUCT
)lParam
;
3690 lpmeasure
->itemHeight
= FD31_GetFldrHeight();
3695 /***********************************************************************
3696 * FileOpenDlgProc [internal]
3697 * Used for open and save, in fact.
3699 static INT_PTR CALLBACK
FD32_FileOpenDlgProc(HWND hWnd
, UINT wMsg
,
3700 WPARAM wParam
, LPARAM lParam
)
3702 PFD31_DATA lfs
= (PFD31_DATA
)GetPropA(hWnd
,FD31_OFN_PROP
);
3704 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg
, wParam
, lParam
);
3705 if ((wMsg
!= WM_INITDIALOG
) && lfs
&& lfs
->hook
)
3708 lRet
= (INT_PTR
)FD31_CallWindowProc(lfs
, wMsg
, wParam
, lParam
);
3710 return lRet
; /* else continue message processing */
3715 return FD31_WMInitDialog(hWnd
, wParam
, lParam
);
3717 case WM_MEASUREITEM
:
3718 return FD32_WMMeasureItem(hWnd
, wParam
, lParam
);
3721 return FD31_WMDrawItem(hWnd
, wParam
, lParam
, !lfs
->open
, (DRAWITEMSTRUCT
*)lParam
);
3724 return FD31_WMCommand(hWnd
, lParam
, HIWORD(wParam
), LOWORD(wParam
), lfs
);
3727 SetBkColor((HDC16
)wParam
, 0x00C0C0C0);
3728 switch (HIWORD(lParam
))
3731 SetTextColor((HDC16
)wParam
, 0x00000000);
3733 case CTLCOLOR_STATIC
:
3734 SetTextColor((HDC16
)wParam
, 0x00000000);
3744 /***********************************************************************
3745 * GetFileName31A [internal]
3747 * Creates a win31 style dialog box for the user to select a file to open/save.
3749 static BOOL
GetFileName31A(LPOPENFILENAMEA lpofn
, /* addess of structure with data*/
3750 UINT dlgType
/* type dialogue : open/save */
3756 FD31_CALLBACKS callbacks
;
3758 if (!lpofn
|| !FD31_Init()) return FALSE
;
3760 TRACE("ofn flags %08lx\n", lpofn
->Flags
);
3761 FD32_SetupCallbacks(&callbacks
);
3762 lfs
= FD31_AllocPrivate((LPARAM
) lpofn
, dlgType
, &callbacks
, (DWORD
) FALSE
);
3765 hInst
= (HINSTANCE
)GetWindowLongPtrA( lpofn
->hwndOwner
, GWLP_HINSTANCE
);
3766 bRet
= DialogBoxIndirectParamA( hInst
, lfs
->template, lpofn
->hwndOwner
,
3767 FD32_FileOpenDlgProc
, (LPARAM
)lfs
);
3768 FD31_DestroyPrivate(lfs
);
3771 TRACE("return lpstrFile='%s' !\n", lpofn
->lpstrFile
);
3775 /***********************************************************************
3776 * GetFileName31W [internal]
3778 * Creates a win31 style dialog box for the user to select a file to open/save
3780 static BOOL
GetFileName31W(LPOPENFILENAMEW lpofn
, /* addess of structure with data*/
3781 UINT dlgType
/* type dialogue : open/save */
3787 FD31_CALLBACKS callbacks
;
3789 if (!lpofn
|| !FD31_Init()) return FALSE
;
3791 FD32_SetupCallbacks(&callbacks
);
3792 lfs
= FD31_AllocPrivate((LPARAM
) lpofn
, dlgType
, &callbacks
, (DWORD
) TRUE
);
3795 hInst
= (HINSTANCE
)GetWindowLongPtrW( lpofn
->hwndOwner
, GWLP_HINSTANCE
);
3796 bRet
= DialogBoxIndirectParamW( hInst
, lfs
->template, lpofn
->hwndOwner
,
3797 FD32_FileOpenDlgProc
, (LPARAM
)lfs
);
3798 FD31_DestroyPrivate(lfs
);
3801 TRACE("file %s, file offset %d, ext offset %d\n",
3802 debugstr_w(lpofn
->lpstrFile
), lpofn
->nFileOffset
, lpofn
->nFileExtension
);
3806 /* ------------------ APIs ---------------------- */
3808 /***********************************************************************
3809 * GetOpenFileNameA (COMDLG32.@)
3811 * Creates a dialog box for the user to select a file to open.
3814 * TRUE on success: user enters a valid file
3815 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3818 BOOL WINAPI
GetOpenFileNameA(
3819 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3821 BOOL win16look
= FALSE
;
3823 TRACE("flags %08lx\n", ofn
->Flags
);
3825 /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
3826 if (ofn
->Flags
& OFN_FILEMUSTEXIST
)
3827 ofn
->Flags
|= OFN_PATHMUSTEXIST
;
3829 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3830 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3833 return GetFileName31A(ofn
, OPEN_DIALOG
);
3835 return GetFileDialog95A(ofn
, OPEN_DIALOG
);
3838 /***********************************************************************
3839 * GetOpenFileNameW (COMDLG32.@)
3841 * Creates a dialog box for the user to select a file to open.
3844 * TRUE on success: user enters a valid file
3845 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3848 BOOL WINAPI
GetOpenFileNameW(
3849 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3851 BOOL win16look
= FALSE
;
3853 TRACE("flags %08lx\n", ofn
->Flags
);
3855 /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
3856 if (ofn
->Flags
& OFN_FILEMUSTEXIST
)
3857 ofn
->Flags
|= OFN_PATHMUSTEXIST
;
3859 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3860 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3863 return GetFileName31W(ofn
, OPEN_DIALOG
);
3865 return GetFileDialog95W(ofn
, OPEN_DIALOG
);
3869 /***********************************************************************
3870 * GetSaveFileNameA (COMDLG32.@)
3872 * Creates a dialog box for the user to select a file to save.
3875 * TRUE on success: user enters a valid file
3876 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3879 BOOL WINAPI
GetSaveFileNameA(
3880 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3882 BOOL win16look
= FALSE
;
3884 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3885 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3888 return GetFileName31A(ofn
, SAVE_DIALOG
);
3890 return GetFileDialog95A(ofn
, SAVE_DIALOG
);
3893 /***********************************************************************
3894 * GetSaveFileNameW (COMDLG32.@)
3896 * Creates a dialog box for the user to select a file to save.
3899 * TRUE on success: user enters a valid file
3900 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3903 BOOL WINAPI
GetSaveFileNameW(
3904 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3906 BOOL win16look
= FALSE
;
3908 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3909 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3912 return GetFileName31W(ofn
, SAVE_DIALOG
);
3914 return GetFileDialog95W(ofn
, SAVE_DIALOG
);