2 * COMMDLG - File Open Dialogs Win95 look and feel
4 * Copyright 1999 Francois Boisvert
5 * Copyright 1999, 2000 Juergen Schmied
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * FIXME: The whole concept of handling unicode is badly broken.
22 * many hook-messages expect a pointer to a
23 * OPENFILENAMEA or W structure. With the current architecture
24 * we would have to convert the beast at every call to a hook.
25 * we have to find a better solution but it would likely cause
26 * a complete rewrite after which we should handle the
27 * OPENFILENAME structure without any converting (jsch).
29 * FIXME: any hook gets a OPENFILENAMEA structure
31 * FIXME: CDN_FILEOK is wrong implemented, other CDN_ messages likely too
33 * FIXME: old style hook messages are not implemented (except FILEOKSTRING)
35 * FIXME: algorithm for selecting the initial directory is too simple
37 * FIXME: add to recent docs
39 * FIXME: flags not implemented: OFN_CREATEPROMPT, OFN_DONTADDTORECENT,
40 * OFN_ENABLEINCLUDENOTIFY, OFN_ENABLESIZING,
41 * OFN_NODEREFERENCELINKS, OFN_NOREADONLYRETURN,
42 * OFN_NOTESTFILECREATE, OFN_USEMONIKERS
44 * FIXME: lCustData for lpfnHook (WM_INITDIALOG)
50 #include "wine/port.h"
59 #define NONAMELESSUNION
60 #define NONAMELESSSTRUCT
67 #include "wine/unicode.h"
74 #include "filedlg31.h"
75 #include "wine/debug.h"
80 #include "filedlgbrowser.h"
83 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
85 #define UNIMPLEMENTED_FLAGS \
86 (OFN_CREATEPROMPT | OFN_DONTADDTORECENT |\
87 OFN_ENABLEINCLUDENOTIFY | OFN_ENABLESIZING |\
88 OFN_NODEREFERENCELINKS | OFN_NOREADONLYRETURN |\
89 OFN_NOTESTFILECREATE /*| OFN_USEMONIKERS*/)
91 #define IsHooked(fodInfos) \
92 ((fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
93 /***********************************************************************
94 * Data structure and global variables
96 typedef struct SFolder
98 int m_iImageIndex
; /* Index of picture in image list */
100 int m_iIndent
; /* Indentation index */
101 LPITEMIDLIST pidlItem
; /* absolute pidl of the item */
103 } SFOLDER
,*LPSFOLDER
;
105 typedef struct tagLookInInfo
111 typedef struct tagFD32_PRIVATE
113 OPENFILENAMEA
*ofnA
; /* original structure if 32bits ansi dialog */
114 } FD32_PRIVATE
, *PFD32_PRIVATE
;
117 /***********************************************************************
118 * Defines and global variables
121 /* Draw item constant */
123 #define XTEXTOFFSET 3
128 /* SearchItem methods */
129 #define SEARCH_PIDL 1
131 #define ITEM_NOTFOUND -1
133 /* Undefined windows message sent by CreateViewObject*/
134 #define WM_GETISHELLBROWSER WM_USER+7
137 * Those macros exist in windowsx.h. However, you can't really use them since
138 * they rely on the UNICODE defines and can't be used inside Wine itself.
141 /* Combo box macros */
142 #define CBAddString(hwnd,str) \
143 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
144 #define CBAddStringW(hwnd,str) \
145 SendMessageW(hwnd,CB_ADDSTRING,0,(LPARAM)str);
147 #define CBInsertString(hwnd,str,pos) \
148 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
150 #define CBDeleteString(hwnd,pos) \
151 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
153 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
154 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
156 #define CBGetItemDataPtr(hwnd,iItemId) \
157 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
159 #define CBGetLBText(hwnd,iItemId,str) \
160 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
162 #define CBGetCurSel(hwnd) \
163 SendMessageA(hwnd,CB_GETCURSEL,0,0);
165 #define CBSetCurSel(hwnd,pos) \
166 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
168 #define CBGetCount(hwnd) \
169 SendMessageA(hwnd,CB_GETCOUNT,0,0);
170 #define CBShowDropDown(hwnd,show) \
171 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
172 #define CBSetItemHeight(hwnd,index,height) \
173 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
175 #define CBSetExtendedUI(hwnd,flag) \
176 SendMessageA(hwnd,CB_SETEXTENDEDUI,(WPARAM)(flag),0)
178 const char *FileOpenDlgInfosStr
= "FileOpenDlgInfos"; /* windows property description string */
179 const char *LookInInfosStr
= "LookInInfos"; /* LOOKIN combo box property */
181 /***********************************************************************
185 /* Internal functions used by the dialog */
186 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
187 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
188 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
);
189 BOOL
FILEDLG95_OnOpen(HWND hwnd
);
190 static LRESULT
FILEDLG95_InitControls(HWND hwnd
);
191 static void FILEDLG95_Clean(HWND hwnd
);
193 /* Functions used by the shell navigation */
194 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
);
195 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
);
196 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
);
197 static void FILEDLG95_SHELL_Clean(HWND hwnd
);
198 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
);
200 /* Functions used by the EDIT box */
201 static int FILEDLG95_FILENAME_GetFileNames (HWND hwnd
, LPWSTR
* lpstrFileList
, UINT
* sizeUsed
, char separator
);
203 /* Functions used by the filetype combo box */
204 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
);
205 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
);
206 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
);
207 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
);
209 /* Functions used by the Look In combo box */
210 static void FILEDLG95_LOOKIN_Init(HWND hwndCombo
);
211 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
);
212 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
);
213 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
);
214 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
);
215 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
);
216 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
);
217 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
);
218 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
);
220 /* Miscellaneous tool functions */
221 static HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
);
222 IShellFolder
* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
);
223 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
);
224 LPITEMIDLIST
GetPidlFromName(IShellFolder
*psf
,LPWSTR lpcstrFileName
);
226 /* Shell memory allocation */
227 static void *MemAlloc(UINT size
);
228 static void MemFree(void *mem
);
230 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
231 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
= FindResourceA(COMDLG32_hInstance
,MAKEINTRESOURCEA(NEWFILEOPENORD
),(LPSTR
)RT_DIALOG
)))
266 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
269 if (!(hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hRes
)) ||
270 !(template = LockResource( hDlgTmpl
)))
272 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
276 /* old style hook messages */
277 if (IsHooked(fodInfos
))
279 fodInfos
->HookMsg
.fileokstring
= RegisterWindowMessageA(FILEOKSTRINGA
);
280 fodInfos
->HookMsg
.lbselchstring
= RegisterWindowMessageA(LBSELCHSTRINGA
);
281 fodInfos
->HookMsg
.helpmsgstring
= RegisterWindowMessageA(HELPMSGSTRINGA
);
282 fodInfos
->HookMsg
.sharevistring
= RegisterWindowMessageA(SHAREVISTRINGA
);
285 /* Some shell namespace extensions depend on COM being initialized. */
286 hr
= OleInitialize(NULL
);
288 lRes
= DialogBoxIndirectParamA(COMDLG32_hInstance
,
289 (LPDLGTEMPLATEA
) template,
290 fodInfos
->ofnInfos
->hwndOwner
,
296 /* Unable to create the dialog */
303 /***********************************************************************
306 * Call GetFileName95 with this structure and clean the memory.
308 * IN : The OPENFILENAMEA initialisation structure passed to
309 * GetOpenFileNameA win api function (see filedlg.c)
311 BOOL WINAPI
GetFileDialog95A(LPOPENFILENAMEA ofn
,UINT iDlgType
)
314 FileOpenDlgInfos fodInfos
;
315 LPSTR lpstrSavDir
= NULL
;
317 LPWSTR defext
= NULL
;
318 LPWSTR filter
= NULL
;
319 LPWSTR customfilter
= NULL
;
321 /* Initialize FileOpenDlgInfos structure */
322 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
324 /* Pass in the original ofn */
325 fodInfos
.ofnInfos
= (LPOPENFILENAMEW
)ofn
;
327 /* save current directory */
328 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
330 lpstrSavDir
= MemAlloc(MAX_PATH
);
331 GetCurrentDirectoryA(MAX_PATH
, lpstrSavDir
);
334 fodInfos
.unicode
= FALSE
;
336 /* convert all the input strings to unicode */
337 if(ofn
->lpstrInitialDir
)
339 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, NULL
, 0 );
340 fodInfos
.initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
341 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, fodInfos
.initdir
, len
);
344 fodInfos
.initdir
= NULL
;
348 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
349 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFile
, -1, fodInfos
.filename
, ofn
->nMaxFile
);
352 fodInfos
.filename
= NULL
;
356 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, NULL
, 0 );
357 defext
= MemAlloc((len
+1)*sizeof(WCHAR
));
358 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, defext
, len
);
360 fodInfos
.defext
= defext
;
364 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, NULL
, 0 );
365 title
= MemAlloc((len
+1)*sizeof(WCHAR
));
366 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, title
, len
);
368 fodInfos
.title
= title
;
370 if (ofn
->lpstrFilter
)
375 /* filter is a list... title\0ext\0......\0\0 */
376 s
= ofn
->lpstrFilter
;
377 while (*s
) s
= s
+strlen(s
)+1;
379 n
= s
- ofn
->lpstrFilter
;
380 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, NULL
, 0 );
381 filter
= MemAlloc(len
*sizeof(WCHAR
));
382 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, filter
, len
);
384 fodInfos
.filter
= filter
;
386 /* convert lpstrCustomFilter */
387 if (ofn
->lpstrCustomFilter
)
392 /* customfilter contains a pair of strings... title\0ext\0 */
393 s
= ofn
->lpstrCustomFilter
;
394 if (*s
) s
= s
+strlen(s
)+1;
395 if (*s
) s
= s
+strlen(s
)+1;
396 n
= s
- ofn
->lpstrCustomFilter
;
397 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, NULL
, 0 );
398 customfilter
= MemAlloc(len
*sizeof(WCHAR
));
399 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, customfilter
, len
);
401 fodInfos
.customfilter
= customfilter
;
403 /* Initialize the dialog property */
404 fodInfos
.DlgInfos
.dwDlgProp
= 0;
405 fodInfos
.DlgInfos
.hwndCustomDlg
= NULL
;
410 ret
= GetFileName95(&fodInfos
);
413 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
414 ret
= GetFileName95(&fodInfos
);
422 SetCurrentDirectoryA(lpstrSavDir
);
423 MemFree(lpstrSavDir
);
433 MemFree(customfilter
);
435 MemFree(fodInfos
.initdir
);
437 if(fodInfos
.filename
)
438 MemFree(fodInfos
.filename
);
440 TRACE("selected file: %s\n",ofn
->lpstrFile
);
445 /***********************************************************************
448 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
449 * Call GetFileName95 with this structure and clean the memory.
452 BOOL WINAPI
GetFileDialog95W(LPOPENFILENAMEW ofn
,UINT iDlgType
)
455 FileOpenDlgInfos fodInfos
;
456 LPWSTR lpstrSavDir
= NULL
;
458 /* Initialize FileOpenDlgInfos structure */
459 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
461 /* Pass in the original ofn */
462 fodInfos
.ofnInfos
= ofn
;
464 fodInfos
.title
= ofn
->lpstrTitle
;
465 fodInfos
.defext
= ofn
->lpstrDefExt
;
466 fodInfos
.filter
= ofn
->lpstrFilter
;
467 fodInfos
.customfilter
= ofn
->lpstrCustomFilter
;
469 /* convert string arguments, save others */
472 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
473 lstrcpynW(fodInfos
.filename
,ofn
->lpstrFile
,ofn
->nMaxFile
);
476 fodInfos
.filename
= NULL
;
478 if(ofn
->lpstrInitialDir
)
480 /* fodInfos.initdir = strdupW(ofn->lpstrInitialDir); */
481 DWORD len
= strlenW(ofn
->lpstrInitialDir
)+1;
482 fodInfos
.initdir
= MemAlloc(len
*sizeof(WCHAR
));
483 memcpy(fodInfos
.initdir
,ofn
->lpstrInitialDir
,len
*sizeof(WCHAR
));
486 fodInfos
.initdir
= NULL
;
488 /* save current directory */
489 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
491 lpstrSavDir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
492 GetCurrentDirectoryW(MAX_PATH
, lpstrSavDir
);
495 fodInfos
.unicode
= TRUE
;
500 ret
= GetFileName95(&fodInfos
);
503 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
504 ret
= GetFileName95(&fodInfos
);
512 SetCurrentDirectoryW(lpstrSavDir
);
513 MemFree(lpstrSavDir
);
516 /* restore saved IN arguments and convert OUT arguments back */
517 MemFree(fodInfos
.filename
);
518 MemFree(fodInfos
.initdir
);
522 /******************************************************************************
523 * COMDLG32_GetDisplayNameOf [internal]
525 * Helper function to get the display name for a pidl.
527 static BOOL
COMDLG32_GetDisplayNameOf(LPCITEMIDLIST pidl
, LPWSTR pwszPath
) {
528 LPSHELLFOLDER psfDesktop
;
531 if (FAILED(SHGetDesktopFolder(&psfDesktop
)))
534 if (FAILED(IShellFolder_GetDisplayNameOf(psfDesktop
, pidl
, SHGDN_FORPARSING
, &strret
))) {
535 IShellFolder_Release(psfDesktop
);
539 IShellFolder_Release(psfDesktop
);
540 return SUCCEEDED(StrRetToBufW(&strret
, pidl
, pwszPath
, MAX_PATH
));
543 /***********************************************************************
544 * ArrangeCtrlPositions [internal]
546 * NOTE: Do not change anything here without a lot of testing.
548 static void ArrangeCtrlPositions(HWND hwndChildDlg
, HWND hwndParentDlg
, BOOL hide_help
)
550 HWND hwndChild
, hwndStc32
;
551 RECT rectParent
, rectChild
, rectStc32
;
552 INT help_fixup
= 0, child_height_fixup
= 0, child_width_fixup
= 0;
554 /* Take into account if open as read only checkbox and help button
559 RECT rectHelp
, rectCancel
;
560 GetWindowRect(GetDlgItem(hwndParentDlg
, pshHelp
), &rectHelp
);
561 GetWindowRect(GetDlgItem(hwndParentDlg
, IDCANCEL
), &rectCancel
);
562 /* subtract the height of the help button plus the space between
563 * the help button and the cancel button to the height of the dialog
565 help_fixup
= rectHelp
.bottom
- rectCancel
.bottom
;
569 There are two possibilities to add components to the default file dialog box.
571 By default, all the new components are added below the standard dialog box (the else case).
573 However, if there is a static text component with the stc32 id, a special case happens.
574 The x and y coordinates of stc32 indicate the top left corner where to place the standard file dialog box
575 in the window and the cx and cy indicate how to size the window.
576 Moreover, if the new component's coordinates are on the left of the stc32 , it is placed on the left
577 of the standard file dialog box. If they are above the stc32 component, it is placed above and so on....
581 GetClientRect(hwndParentDlg
, &rectParent
);
583 /* when arranging controls we have to use fixed parent size */
584 rectParent
.bottom
-= help_fixup
;
586 hwndStc32
= GetDlgItem(hwndChildDlg
, stc32
);
589 GetWindowRect(hwndStc32
, &rectStc32
);
590 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectStc32
, 2);
592 /* set the size of the stc32 control according to the size of
593 * client area of the parent dialog
595 SetWindowPos(hwndStc32
, 0,
597 rectParent
.right
, rectParent
.bottom
,
598 SWP_NOMOVE
| SWP_NOZORDER
);
601 SetRectEmpty(&rectStc32
);
603 /* this part moves controls of the child dialog */
604 hwndChild
= GetWindow(hwndChildDlg
, GW_CHILD
);
607 if (hwndChild
!= hwndStc32
)
609 GetWindowRect(hwndChild
, &rectChild
);
610 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectChild
, 2);
612 /* move only if stc32 exist */
613 if (hwndStc32
&& rectChild
.left
> rectStc32
.right
)
615 LONG old_left
= rectChild
.left
;
617 /* move to the right of visible controls of the parent dialog */
618 rectChild
.left
+= rectParent
.right
;
619 rectChild
.left
-= rectStc32
.right
;
621 child_width_fixup
= rectChild
.left
- old_left
;
623 /* move even if stc32 doesn't exist */
624 if (rectChild
.top
>= rectStc32
.bottom
)
626 LONG old_top
= rectChild
.top
;
628 /* move below visible controls of the parent dialog */
629 rectChild
.top
+= rectParent
.bottom
;
630 rectChild
.top
-= rectStc32
.bottom
- rectStc32
.top
;
632 child_height_fixup
= rectChild
.top
- old_top
;
635 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
636 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
638 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
641 /* this part moves controls of the parent dialog */
642 hwndChild
= GetWindow(hwndParentDlg
, GW_CHILD
);
645 if (hwndChild
!= hwndChildDlg
)
647 GetWindowRect(hwndChild
, &rectChild
);
648 MapWindowPoints(0, hwndParentDlg
, (LPPOINT
)&rectChild
, 2);
650 /* left,top of stc32 marks the position of controls
651 * from the parent dialog
653 rectChild
.left
+= rectStc32
.left
;
654 rectChild
.top
+= rectStc32
.top
;
656 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
657 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
659 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
662 /* calculate the size of the resulting dialog */
664 /* here we have to use original parent size */
665 GetClientRect(hwndParentDlg
, &rectParent
);
666 GetClientRect(hwndChildDlg
, &rectChild
);
670 rectChild
.right
+= child_width_fixup
;
671 rectChild
.bottom
+= child_height_fixup
;
673 if (rectParent
.right
> rectChild
.right
)
675 rectParent
.right
+= rectChild
.right
;
676 rectParent
.right
-= rectStc32
.right
- rectStc32
.left
;
680 rectParent
.right
= rectChild
.right
;
683 if (rectParent
.bottom
> rectChild
.bottom
)
685 rectParent
.bottom
+= rectChild
.bottom
;
686 rectParent
.bottom
-= rectStc32
.bottom
- rectStc32
.top
;
690 /* child dialog is higher, unconditionally set new dialog
691 * height to its size (help_fixup will be subtracted below)
693 rectParent
.bottom
= rectChild
.bottom
+ help_fixup
;
698 rectParent
.bottom
+= rectChild
.bottom
;
701 /* finally use fixed parent size */
702 rectParent
.bottom
-= help_fixup
;
704 /* set the size of the parent dialog */
705 AdjustWindowRectEx(&rectParent
, GetWindowLongW(hwndParentDlg
, GWL_STYLE
),
706 FALSE
, GetWindowLongW(hwndParentDlg
, GWL_EXSTYLE
));
707 SetWindowPos(hwndParentDlg
, 0,
709 rectParent
.right
- rectParent
.left
,
710 rectParent
.bottom
- rectParent
.top
,
711 SWP_NOMOVE
| SWP_NOZORDER
);
714 static INT_PTR CALLBACK
FileOpenDlgProcUserTemplate(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
723 static HWND
CreateTemplateDialog(FileOpenDlgInfos
*fodInfos
, HWND hwnd
)
733 * If OFN_ENABLETEMPLATEHANDLE is specified, the OPENFILENAME
734 * structure's hInstance parameter is not a HINSTANCE, but
735 * instead a pointer to a template resource to use.
737 if (fodInfos
->ofnInfos
->Flags
& (OFN_ENABLETEMPLATE
| OFN_ENABLETEMPLATEHANDLE
))
740 if (fodInfos
->ofnInfos
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
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 hChildDlg
= CreateDialogIndirectParamA(hinst
, template, hwnd
,
775 IsHooked(fodInfos
) ? (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
: FileOpenDlgProcUserTemplate
,
776 (LPARAM
)fodInfos
->ofnInfos
);
779 ShowWindow(hChildDlg
,SW_SHOW
);
783 else if( IsHooked(fodInfos
))
788 WORD menu
,class,title
;
790 GetClientRect(hwnd
,&rectHwnd
);
791 temp
.tmplate
.style
= WS_CHILD
| WS_CLIPSIBLINGS
| WS_VISIBLE
| DS_CONTROL
| DS_3DLOOK
;
792 temp
.tmplate
.dwExtendedStyle
= 0;
793 temp
.tmplate
.cdit
= 0;
798 temp
.menu
= temp
.class = temp
.title
= 0;
800 hChildDlg
= CreateDialogIndirectParamA(COMDLG32_hInstance
, &temp
.tmplate
,
801 hwnd
, (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
, (LPARAM
)fodInfos
->ofnInfos
);
808 /***********************************************************************
809 * SendCustomDlgNotificationMessage
811 * Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
814 LRESULT
SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
)
816 LRESULT hook_result
= 0;
818 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwndParentDlg
,FileOpenDlgInfosStr
);
820 TRACE("%p 0x%04x\n",hwndParentDlg
, uCode
);
822 if(!fodInfos
) return 0;
824 if(fodInfos
->DlgInfos
.hwndCustomDlg
)
826 TRACE("CALL NOTIFY for %x\n", uCode
);
827 if(fodInfos
->unicode
)
830 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
831 ofnNotify
.hdr
.idFrom
=0;
832 ofnNotify
.hdr
.code
= uCode
;
833 ofnNotify
.lpOFN
= fodInfos
->ofnInfos
;
834 ofnNotify
.pszFile
= NULL
;
835 hook_result
= SendMessageW(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
840 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
841 ofnNotify
.hdr
.idFrom
=0;
842 ofnNotify
.hdr
.code
= uCode
;
843 ofnNotify
.lpOFN
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
844 ofnNotify
.pszFile
= NULL
;
845 hook_result
= SendMessageA(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
847 TRACE("RET NOTIFY\n");
849 TRACE("Retval: 0x%08lx\n", hook_result
);
853 static INT_PTR
FILEDLG95_Handle_GetFilePath(HWND hwnd
, DWORD size
, LPVOID buffer
)
855 UINT sizeUsed
= 0, n
, total
;
856 LPWSTR lpstrFileList
= NULL
;
857 WCHAR lpstrCurrentDir
[MAX_PATH
];
858 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
860 TRACE("CDM_GETFILEPATH:\n");
862 if ( ! (fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
865 /* get path and filenames */
866 COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrCurrentDir
);
867 n
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
, ' ');
869 TRACE("path >%s< filespec >%s< %d files\n",
870 debugstr_w(lpstrCurrentDir
),debugstr_w(lpstrFileList
),n
);
872 if( fodInfos
->unicode
)
874 LPWSTR bufW
= buffer
;
875 total
= strlenW(lpstrCurrentDir
) + 1 + sizeUsed
;
877 /* Prepend the current path */
878 n
= strlenW(lpstrCurrentDir
) + 1;
879 memcpy( bufW
, lpstrCurrentDir
, min(n
,size
) * sizeof(WCHAR
));
882 /* 'n' includes trailing \0 */
884 memcpy( &bufW
[n
], lpstrFileList
, (size
-n
)*sizeof(WCHAR
) );
886 TRACE("returned -> %s\n",debugstr_wn(bufW
, total
));
891 total
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
892 NULL
, 0, NULL
, NULL
);
893 total
+= WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
894 NULL
, 0, NULL
, NULL
);
896 /* Prepend the current path */
897 n
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
898 bufA
, size
, NULL
, NULL
);
902 /* 'n' includes trailing \0 */
904 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
905 &bufA
[n
], size
-n
, NULL
, NULL
);
908 TRACE("returned -> %s\n",debugstr_an(bufA
, total
));
910 MemFree(lpstrFileList
);
915 static INT_PTR
FILEDLG95_Handle_GetFileSpec(HWND hwnd
, DWORD size
, LPVOID buffer
)
918 LPWSTR lpstrFileList
= NULL
;
919 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
921 TRACE("CDM_GETSPEC:\n");
923 FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
, ' ');
924 if( fodInfos
->unicode
)
926 LPWSTR bufW
= buffer
;
927 memcpy( bufW
, lpstrFileList
, sizeof(WCHAR
)*sizeUsed
);
932 sizeUsed
= WideCharToMultiByte( CP_ACP
, 0, lpstrFileList
, sizeUsed
,
933 NULL
, 0, NULL
, NULL
);
934 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
935 bufA
, size
, NULL
, NULL
);
937 MemFree(lpstrFileList
);
942 /***********************************************************************
943 * FILEDLG95_HandleCustomDialogMessages
945 * Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
947 static INT_PTR
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
949 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
950 WCHAR lpstrPath
[MAX_PATH
];
953 if(!fodInfos
) return FALSE
;
957 case CDM_GETFILEPATH
:
958 retval
= FILEDLG95_Handle_GetFilePath(hwnd
, (UINT
)wParam
, (LPVOID
)lParam
);
961 case CDM_GETFOLDERPATH
:
962 TRACE("CDM_GETFOLDERPATH:\n");
963 COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPath
);
966 if (fodInfos
->unicode
)
967 lstrcpynW((LPWSTR
)lParam
, lpstrPath
, (int)wParam
);
969 WideCharToMultiByte(CP_ACP
, 0, lpstrPath
, -1,
970 (LPSTR
)lParam
, (int)wParam
, NULL
, NULL
);
972 retval
= strlenW(lpstrPath
);
976 retval
= FILEDLG95_Handle_GetFileSpec(hwnd
, (UINT
)wParam
, (LPSTR
)lParam
);
979 case CDM_SETCONTROLTEXT
:
980 TRACE("CDM_SETCONTROLTEXT:\n");
983 if( fodInfos
->unicode
)
984 SetDlgItemTextW( hwnd
, (UINT
) wParam
, (LPWSTR
) lParam
);
986 SetDlgItemTextA( hwnd
, (UINT
) wParam
, (LPSTR
) lParam
);
991 case CDM_HIDECONTROL
:
992 /* MSDN states that it should fail for not OFN_EXPLORER case */
993 if (fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
)
995 HWND control
= GetDlgItem( hwnd
, wParam
);
996 if (control
) ShowWindow( control
, SW_HIDE
);
1003 if (uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
1004 FIXME("message CDM_FIRST+%04x not implemented\n", uMsg
- CDM_FIRST
);
1007 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, retval
);
1011 /***********************************************************************
1014 * File open dialog procedure
1016 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1019 TRACE("0x%04x 0x%04x\n", hwnd
, uMsg
);
1026 FileOpenDlgInfos
* fodInfos
= (FileOpenDlgInfos
*)lParam
;
1028 /* Adds the FileOpenDlgInfos in the property list of the dialog
1029 so it will be easily accessible through a GetPropA(...) */
1030 SetPropA(hwnd
, FileOpenDlgInfosStr
, (HANDLE
) fodInfos
);
1032 fodInfos
->DlgInfos
.hwndCustomDlg
=
1033 CreateTemplateDialog((FileOpenDlgInfos
*)lParam
, hwnd
);
1035 FILEDLG95_InitControls(hwnd
);
1037 if (fodInfos
->DlgInfos
.hwndCustomDlg
)
1040 UINT flags
= SWP_NOACTIVATE
;
1042 ArrangeCtrlPositions(fodInfos
->DlgInfos
.hwndCustomDlg
, hwnd
,
1043 (fodInfos
->ofnInfos
->Flags
& (OFN_HIDEREADONLY
| OFN_SHOWHELP
)) == OFN_HIDEREADONLY
);
1045 /* resize the custom dialog to the parent size */
1046 if (fodInfos
->ofnInfos
->Flags
& (OFN_ENABLETEMPLATE
| OFN_ENABLETEMPLATEHANDLE
))
1047 GetClientRect(hwnd
, &rc
);
1050 /* our own fake template is zero sized and doesn't have
1051 * children, so there is no need to resize it.
1052 * Picasa depends on it.
1054 flags
|= SWP_NOSIZE
;
1057 SetWindowPos(fodInfos
->DlgInfos
.hwndCustomDlg
, HWND_BOTTOM
,
1058 0, 0, rc
.right
, rc
.bottom
, flags
);
1061 FILEDLG95_FillControls(hwnd
, wParam
, lParam
);
1063 SendCustomDlgNotificationMessage(hwnd
,CDN_INITDONE
);
1064 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
1065 SendCustomDlgNotificationMessage(hwnd
,CDN_SELCHANGE
);
1069 return FILEDLG95_OnWMCommand(hwnd
, wParam
, lParam
);
1072 switch(((LPDRAWITEMSTRUCT
)lParam
)->CtlID
)
1075 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT
) lParam
);
1081 case WM_GETISHELLBROWSER
:
1082 return FILEDLG95_OnWMGetIShellBrowser(hwnd
);
1085 RemovePropA(hwnd
, FileOpenDlgInfosStr
);
1090 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
1093 /* set up the button tooltips strings */
1094 if(TTN_GETDISPINFOA
== lpnmh
->code
)
1096 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
1097 switch(lpnmh
->idFrom
)
1099 /* Up folder button */
1100 case FCIDM_TB_UPFOLDER
:
1101 stringId
= IDS_UPFOLDER
;
1103 /* New folder button */
1104 case FCIDM_TB_NEWFOLDER
:
1105 stringId
= IDS_NEWFOLDER
;
1107 /* List option button */
1108 case FCIDM_TB_SMALLICON
:
1109 stringId
= IDS_LISTVIEW
;
1111 /* Details option button */
1112 case FCIDM_TB_REPORTVIEW
:
1113 stringId
= IDS_REPORTVIEW
;
1115 /* Desktop button */
1116 case FCIDM_TB_DESKTOP
:
1117 stringId
= IDS_TODESKTOP
;
1122 lpdi
->hinst
= COMDLG32_hInstance
;
1123 lpdi
->lpszText
= MAKEINTRESOURCEA(stringId
);
1128 if(uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
1129 return FILEDLG95_HandleCustomDialogMessages(hwnd
, uMsg
, wParam
, lParam
);
1134 /***********************************************************************
1135 * FILEDLG95_InitControls
1137 * WM_INITDIALOG message handler (before hook notification)
1139 static LRESULT
FILEDLG95_InitControls(HWND hwnd
)
1141 int win2000plus
= 0;
1143 int handledPath
= FALSE
;
1144 OSVERSIONINFOA osVi
;
1145 static const WCHAR szwSlash
[] = { '\\', 0 };
1146 static const WCHAR szwStar
[] = { '*',0 };
1150 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1151 {VIEW_PARENTFOLDER
, FCIDM_TB_UPFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1152 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1153 {VIEW_NEWFOLDER
+1, FCIDM_TB_DESKTOP
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1154 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1155 {VIEW_NEWFOLDER
, FCIDM_TB_NEWFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1156 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1157 {VIEW_LIST
, FCIDM_TB_SMALLICON
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1158 {VIEW_DETAILS
, FCIDM_TB_REPORTVIEW
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1163 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1165 tba
[0].hInst
= HINST_COMMCTRL
;
1166 tba
[0].nID
= IDB_VIEW_SMALL_COLOR
;
1167 tba
[1].hInst
= COMDLG32_hInstance
;
1170 TRACE("%p\n", fodInfos
);
1172 /* Get windows version emulating */
1173 osVi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
1174 GetVersionExA(&osVi
);
1175 if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
) {
1176 win98plus
= ((osVi
.dwMajorVersion
> 4) || ((osVi
.dwMajorVersion
== 4) && (osVi
.dwMinorVersion
> 0)));
1177 } else if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1178 win2000plus
= (osVi
.dwMajorVersion
> 4);
1179 if (win2000plus
) win98plus
= TRUE
;
1181 TRACE("Running on 2000+ %d, 98+ %d\n", win2000plus
, win98plus
);
1183 /* Get the hwnd of the controls */
1184 fodInfos
->DlgInfos
.hwndFileName
= GetDlgItem(hwnd
,IDC_FILENAME
);
1185 fodInfos
->DlgInfos
.hwndFileTypeCB
= GetDlgItem(hwnd
,IDC_FILETYPE
);
1186 fodInfos
->DlgInfos
.hwndLookInCB
= GetDlgItem(hwnd
,IDC_LOOKIN
);
1188 GetWindowRect( fodInfos
->DlgInfos
.hwndLookInCB
,&rectlook
);
1189 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectlook
,2);
1191 /* construct the toolbar */
1192 GetWindowRect(GetDlgItem(hwnd
,IDC_TOOLBARSTATIC
),&rectTB
);
1193 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectTB
,2);
1195 rectTB
.right
= rectlook
.right
+ rectTB
.right
- rectTB
.left
;
1196 rectTB
.bottom
= rectlook
.top
- 1 + rectTB
.bottom
- rectTB
.top
;
1197 rectTB
.left
= rectlook
.right
;
1198 rectTB
.top
= rectlook
.top
-1;
1200 fodInfos
->DlgInfos
.hwndTB
= CreateWindowExA(0, TOOLBARCLASSNAMEA
, NULL
,
1201 WS_CHILD
| WS_GROUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NORESIZE
,
1202 rectTB
.left
, rectTB
.top
,
1203 rectTB
.right
- rectTB
.left
, rectTB
.bottom
- rectTB
.top
,
1204 hwnd
, (HMENU
)IDC_TOOLBAR
, COMDLG32_hInstance
, NULL
);
1206 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_BUTTONSTRUCTSIZE
, (WPARAM
) sizeof(TBBUTTON
), 0);
1208 /* FIXME: use TB_LOADIMAGES when implemented */
1209 /* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1210 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 12, (LPARAM
) &tba
[0]);
1211 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 1, (LPARAM
) &tba
[1]);
1213 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBUTTONSA
, (WPARAM
) 9,(LPARAM
) &tbb
);
1214 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_AUTOSIZE
, 0, 0);
1216 /* Set the window text with the text specified in the OPENFILENAME structure */
1219 SetWindowTextW(hwnd
,fodInfos
->title
);
1221 else if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1224 LoadStringW(COMDLG32_hInstance
, IDS_SAVE
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1225 SetWindowTextW(hwnd
, buf
);
1228 /* Initialise the file name edit control */
1229 handledPath
= FALSE
;
1230 TRACE("Before manipilation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1232 if(fodInfos
->filename
)
1234 /* 1. If win2000 or higher and filename contains a path, use it
1235 in preference over the lpstrInitialDir */
1236 if (win2000plus
&& *fodInfos
->filename
&& strpbrkW(fodInfos
->filename
, szwSlash
)) {
1237 WCHAR tmpBuf
[MAX_PATH
];
1241 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
, tmpBuf
, &nameBit
);
1244 /* nameBit is always shorter than the original filename */
1245 strcpyW(fodInfos
->filename
,nameBit
);
1248 if (fodInfos
->initdir
== NULL
)
1249 MemFree(fodInfos
->initdir
);
1250 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf
) + 1)*sizeof(WCHAR
));
1251 strcpyW(fodInfos
->initdir
, tmpBuf
);
1253 TRACE("Value in Filename includes path, overriding InitialDir: %s, %s\n",
1254 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1256 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1259 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1263 /* 2. (All platforms) If initdir is not null, then use it */
1264 if ((handledPath
== FALSE
) && (fodInfos
->initdir
!=NULL
) &&
1265 (*fodInfos
->initdir
!=0x00))
1267 /* Work out the proper path as supplied one might be relative */
1268 /* (Here because supplying '.' as dir browses to My Computer) */
1269 if (handledPath
==FALSE
) {
1270 WCHAR tmpBuf
[MAX_PATH
];
1271 WCHAR tmpBuf2
[MAX_PATH
];
1275 strcpyW(tmpBuf
, fodInfos
->initdir
);
1276 if( PathFileExistsW(tmpBuf
) ) {
1277 /* initdir does not have to be a directory. If a file is
1278 * specified, the dir part is taken */
1279 if( PathIsDirectoryW(tmpBuf
)) {
1280 if (tmpBuf
[strlenW(tmpBuf
)-1] != '\\') {
1281 strcatW(tmpBuf
, szwSlash
);
1283 strcatW(tmpBuf
, szwStar
);
1285 result
= GetFullPathNameW(tmpBuf
, MAX_PATH
, tmpBuf2
, &nameBit
);
1288 if (fodInfos
->initdir
)
1289 MemFree(fodInfos
->initdir
);
1290 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf2
) + 1)*sizeof(WCHAR
));
1291 strcpyW(fodInfos
->initdir
, tmpBuf2
);
1294 * This is a picasa change to help resolve link issues
1295 * this allows the file open dialog which starts in My Pictures
1296 * to not have a long path into C: as its startup location
1300 char real_path
[1024];
1302 path
= wine_get_unix_file_name(fodInfos
->initdir
);
1303 realpath(path
,real_path
);
1304 fodInfos
->initdir
= wine_get_dos_file_name(real_path
);
1310 TRACE("Value in InitDir changed to %s\n", debugstr_w(fodInfos
->initdir
));
1313 else if (fodInfos
->initdir
)
1315 MemFree(fodInfos
->initdir
);
1316 fodInfos
->initdir
= NULL
;
1317 TRACE("Value in InitDir is not an existing path, changed to (nil)\n");
1322 if ((handledPath
== FALSE
) && ((fodInfos
->initdir
==NULL
) ||
1323 (*fodInfos
->initdir
==0x00)))
1325 /* 3. All except w2k+: if filename contains a path use it */
1326 if (!win2000plus
&& fodInfos
->filename
&&
1327 *fodInfos
->filename
&&
1328 strpbrkW(fodInfos
->filename
, szwSlash
)) {
1329 WCHAR tmpBuf
[MAX_PATH
];
1333 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
,
1338 /* nameBit is always shorter than the original filename */
1339 strcpyW(fodInfos
->filename
, nameBit
);
1342 len
= strlenW(tmpBuf
);
1343 if(fodInfos
->initdir
)
1344 MemFree(fodInfos
->initdir
);
1345 fodInfos
->initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
1346 strcpyW(fodInfos
->initdir
, tmpBuf
);
1349 TRACE("Value in Filename includes path, overriding initdir: %s, %s\n",
1350 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1352 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1355 /* 4. win98+ and win2000+ if any files of specified filter types in
1356 current directory, use it */
1357 if ( win98plus
&& handledPath
== FALSE
&&
1358 fodInfos
->filter
&& *fodInfos
->filter
) {
1360 BOOL searchMore
= TRUE
;
1361 LPCWSTR lpstrPos
= fodInfos
->filter
;
1362 WIN32_FIND_DATAW FindFileData
;
1367 /* filter is a list... title\0ext\0......\0\0 */
1369 /* Skip the title */
1370 if(! *lpstrPos
) break; /* end */
1371 lpstrPos
+= strlenW(lpstrPos
) + 1;
1373 /* See if any files exist in the current dir with this extension */
1374 if(! *lpstrPos
) break; /* end */
1376 hFind
= FindFirstFileW(lpstrPos
, &FindFileData
);
1378 if (hFind
== INVALID_HANDLE_VALUE
) {
1379 /* None found - continue search */
1380 lpstrPos
+= strlenW(lpstrPos
) + 1;
1385 if(fodInfos
->initdir
)
1386 MemFree(fodInfos
->initdir
);
1387 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1388 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1391 TRACE("No initial dir specified, but files of type %s found in current, so using it\n",
1392 debugstr_w(lpstrPos
));
1398 /* 5. Win2000+: FIXME: Next, Recently used? Not sure how windows does this */
1400 /* 6. Win98+ and 2000+: Use personal files dir, others use current dir */
1401 if (handledPath
== FALSE
&& (win2000plus
|| win98plus
)) {
1402 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1404 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_PERSONAL
, 0, 0, fodInfos
->initdir
)))
1406 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_DESKTOPDIRECTORY
|CSIDL_FLAG_CREATE
, 0, 0, fodInfos
->initdir
)))
1409 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1410 TRACE("No personal or desktop dir, using cwd as failsafe: %s\n", debugstr_w(fodInfos
->initdir
));
1412 TRACE("No personal dir, using desktop instead: %s\n", debugstr_w(fodInfos
->initdir
));
1415 TRACE("No initial dir specified, using personal files dir of %s\n", debugstr_w(fodInfos
->initdir
));
1418 } else if (handledPath
==FALSE
) {
1419 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1420 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1422 TRACE("No initial dir specified, using current dir of %s\n", debugstr_w(fodInfos
->initdir
));
1425 SetFocus(GetDlgItem(hwnd
, IDC_FILENAME
));
1426 TRACE("After manipulation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1428 /* Must the open as read only check box be checked ?*/
1429 if(fodInfos
->ofnInfos
->Flags
& OFN_READONLY
)
1431 SendDlgItemMessageA(hwnd
,IDC_OPENREADONLY
,BM_SETCHECK
,(WPARAM
)TRUE
,0);
1434 /* Must the open as read only check box be hidden? */
1435 if(fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
)
1437 ShowWindow(GetDlgItem(hwnd
,IDC_OPENREADONLY
),SW_HIDE
);
1438 EnableWindow(GetDlgItem(hwnd
, IDC_OPENREADONLY
), FALSE
);
1441 /* Must the help button be hidden? */
1442 if (!(fodInfos
->ofnInfos
->Flags
& OFN_SHOWHELP
))
1444 ShowWindow(GetDlgItem(hwnd
, pshHelp
), SW_HIDE
);
1445 EnableWindow(GetDlgItem(hwnd
, pshHelp
), FALSE
);
1448 /* Resize the height, if open as read only checkbox ad help button
1449 are hidden and we are not using a custom template nor a customDialog
1451 if ( (fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
) &&
1452 (!(fodInfos
->ofnInfos
->Flags
&
1453 (OFN_SHOWHELP
|OFN_ENABLETEMPLATE
|OFN_ENABLETEMPLATEHANDLE
))) &&
1454 (!fodInfos
->DlgInfos
.hwndCustomDlg
))
1456 RECT rectDlg
, rectHelp
, rectCancel
;
1457 GetWindowRect(hwnd
, &rectDlg
);
1458 GetWindowRect(GetDlgItem(hwnd
, pshHelp
), &rectHelp
);
1459 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rectCancel
);
1460 /* subtract the height of the help button plus the space between
1461 the help button and the cancel button to the height of the dialog */
1462 SetWindowPos(hwnd
, 0, 0, 0, rectDlg
.right
-rectDlg
.left
,
1463 (rectDlg
.bottom
-rectDlg
.top
) - (rectHelp
.bottom
- rectCancel
.bottom
),
1464 SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
);
1466 /* change Open to Save */
1467 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1470 LoadStringW(COMDLG32_hInstance
, IDS_SAVE_BUTTON
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1471 SetDlgItemTextW(hwnd
, IDOK
, buf
);
1472 LoadStringW(COMDLG32_hInstance
, IDS_SAVE_IN
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1473 SetDlgItemTextW(hwnd
, IDC_LOOKINSTATIC
, buf
);
1478 /***********************************************************************
1479 * FILEDLG95_FillControls
1481 * WM_INITDIALOG message handler (after hook notification)
1483 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1485 LPITEMIDLIST pidlItemId
= NULL
;
1487 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) lParam
;
1489 TRACE("dir=%s file=%s\n",
1490 debugstr_w(fodInfos
->initdir
), debugstr_w(fodInfos
->filename
));
1492 /* Get the initial directory pidl */
1494 if(!(pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,fodInfos
->initdir
)))
1496 WCHAR path
[MAX_PATH
];
1498 GetCurrentDirectoryW(MAX_PATH
,path
);
1499 pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, path
);
1502 /* Initialise shell objects */
1503 FILEDLG95_SHELL_Init(hwnd
);
1505 /* Initialize the Look In combo box */
1506 FILEDLG95_LOOKIN_Init(fodInfos
->DlgInfos
.hwndLookInCB
);
1508 /* Initialize the filter combo box */
1509 FILEDLG95_FILETYPE_Init(hwnd
);
1511 /* Browse to the initial directory */
1512 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,pidlItemId
, SBSP_ABSOLUTE
);
1514 /* Free pidlItem memory */
1515 COMDLG32_SHFree(pidlItemId
);
1519 /***********************************************************************
1522 * Regroups all the cleaning functions of the filedlg
1524 void FILEDLG95_Clean(HWND hwnd
)
1526 FILEDLG95_FILETYPE_Clean(hwnd
);
1527 FILEDLG95_LOOKIN_Clean(hwnd
);
1528 FILEDLG95_SHELL_Clean(hwnd
);
1530 /***********************************************************************
1531 * FILEDLG95_OnWMCommand
1533 * WM_COMMAND message handler
1535 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1537 WORD wNotifyCode
= HIWORD(wParam
); /* notification code */
1538 WORD wID
= LOWORD(wParam
); /* item, control, or accelerator identifier */
1539 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1545 FILEDLG95_OnOpen(hwnd
);
1549 FILEDLG95_Clean(hwnd
);
1550 EndDialog(hwnd
, FALSE
);
1552 /* Filetype combo box */
1554 FILEDLG95_FILETYPE_OnCommand(hwnd
,wNotifyCode
);
1556 /* LookIn combo box */
1558 FILEDLG95_LOOKIN_OnCommand(hwnd
,wNotifyCode
);
1561 /* --- toolbar --- */
1562 /* Up folder button */
1563 case FCIDM_TB_UPFOLDER
:
1564 FILEDLG95_SHELL_UpFolder(hwnd
);
1566 /* New folder button */
1567 case FCIDM_TB_NEWFOLDER
:
1568 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_NEWFOLDERA
);
1570 /* List option button */
1571 case FCIDM_TB_SMALLICON
:
1572 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWLISTA
);
1574 /* Details option button */
1575 case FCIDM_TB_REPORTVIEW
:
1576 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWDETAILSA
);
1578 /* Details option button */
1579 case FCIDM_TB_DESKTOP
:
1580 FILEDLG95_SHELL_BrowseToDesktop(hwnd
);
1587 /* Do not use the listview selection anymore */
1588 fodInfos
->DlgInfos
.dwDlgProp
&= ~FODPROP_USEVIEW
;
1592 /***********************************************************************
1593 * FILEDLG95_OnWMGetIShellBrowser
1595 * WM_GETISHELLBROWSER message handler
1597 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
)
1600 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1604 SetWindowLongPtrW(hwnd
,DWLP_MSGRESULT
,(LONG_PTR
)fodInfos
->Shell
.FOIShellBrowser
);
1610 /***********************************************************************
1611 * FILEDLG95_SendFileOK
1613 * Sends the CDN_FILEOK notification if required
1616 * TRUE if the dialog should close
1617 * FALSE if the dialog should not be closed
1619 static BOOL
FILEDLG95_SendFileOK( HWND hwnd
, FileOpenDlgInfos
*fodInfos
)
1621 /* ask the hook if we can close */
1622 if(IsHooked(fodInfos
))
1627 /* First send CDN_FILEOK as MSDN doc says */
1628 retval
= SendCustomDlgNotificationMessage(hwnd
,CDN_FILEOK
);
1629 if (GetWindowLongPtrW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWLP_MSGRESULT
))
1631 TRACE("canceled\n");
1632 return (retval
== 0);
1635 /* fodInfos->ofnInfos points to an ASCII or UNICODE structure as appropriate */
1636 retval
= SendMessageW(fodInfos
->DlgInfos
.hwndCustomDlg
,
1637 fodInfos
->HookMsg
.fileokstring
, 0, (LPARAM
)fodInfos
->ofnInfos
);
1638 if (GetWindowLongPtrW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWLP_MSGRESULT
))
1640 TRACE("canceled\n");
1641 return (retval
== 0);
1647 /***********************************************************************
1648 * FILEDLG95_OnOpenMultipleFiles
1650 * Handles the opening of multiple files.
1653 * check destination buffer size
1655 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
)
1657 WCHAR lpstrPathSpec
[MAX_PATH
] = {0};
1658 UINT nCount
, nSizePath
;
1659 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1663 if(fodInfos
->unicode
)
1665 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
1666 ofn
->lpstrFile
[0] = '\0';
1670 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
) fodInfos
->ofnInfos
;
1671 ofn
->lpstrFile
[0] = '\0';
1674 COMDLG32_GetDisplayNameOf( fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathSpec
);
1676 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1677 ( fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1678 ! ( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1680 LPWSTR lpstrTemp
= lpstrFileList
;
1682 for ( nCount
= 0; nCount
< nFileCount
; nCount
++ )
1686 pidl
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, lpstrTemp
);
1689 WCHAR lpstrNotFound
[100];
1690 WCHAR lpstrMsg
[100];
1692 static const WCHAR nl
[] = {'\n',0};
1694 LoadStringW(COMDLG32_hInstance
, IDS_FILENOTFOUND
, lpstrNotFound
, 100);
1695 LoadStringW(COMDLG32_hInstance
, IDS_VERIFYFILE
, lpstrMsg
, 100);
1697 strcpyW(tmp
, lpstrTemp
);
1699 strcatW(tmp
, lpstrNotFound
);
1701 strcatW(tmp
, lpstrMsg
);
1703 MessageBoxW(hwnd
, tmp
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
1707 /* move to the next file in the list of files */
1708 lpstrTemp
+= strlenW(lpstrTemp
) + 1;
1709 COMDLG32_SHFree(pidl
);
1713 nSizePath
= strlenW(lpstrPathSpec
) + 1;
1714 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
1716 /* For "oldstyle" dialog the components have to
1717 be separated by blanks (not '\0'!) and short
1718 filenames have to be used! */
1719 FIXME("Components have to be separated by blanks\n");
1721 if(fodInfos
->unicode
)
1723 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
1724 if (nSizePath
+sizeUsed
> ofn
->nMaxFile
)
1726 *((WORD
*)ofn
->lpstrFile
)=nSizePath
+sizeUsed
;
1727 FILEDLG95_Clean(hwnd
);
1728 EndDialog(hwnd
,FALSE
);
1729 COMDLG32_SetCommDlgExtendedError(FNERR_BUFFERTOOSMALL
);
1734 strcpyW( ofn
->lpstrFile
, lpstrPathSpec
);
1735 memcpy( ofn
->lpstrFile
+ nSizePath
, lpstrFileList
, sizeUsed
*sizeof(WCHAR
) );
1740 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
1742 if (ofn
->lpstrFile
!= NULL
)
1744 nSizePath
= WideCharToMultiByte(CP_ACP
, 0, lpstrPathSpec
, -1,
1745 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
1746 if (ofn
->nMaxFile
> nSizePath
)
1748 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
1749 ofn
->lpstrFile
+ nSizePath
,
1750 ofn
->nMaxFile
- nSizePath
, NULL
, NULL
);
1755 fodInfos
->ofnInfos
->nFileOffset
= nSizePath
;
1756 fodInfos
->ofnInfos
->nFileExtension
= 0;
1758 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
1761 /* clean and exit */
1762 FILEDLG95_Clean(hwnd
);
1763 return EndDialog(hwnd
,TRUE
);
1766 /***********************************************************************
1769 * Ok button WM_COMMAND message handler
1771 * If the function succeeds, the return value is nonzero.
1773 #define ONOPEN_BROWSE 1
1774 #define ONOPEN_OPEN 2
1775 #define ONOPEN_SEARCH 3
1776 static void FILEDLG95_OnOpenMessage(HWND hwnd
, int idCaption
, int idText
)
1778 WCHAR strMsgTitle
[MAX_PATH
];
1779 WCHAR strMsgText
[MAX_PATH
];
1781 LoadStringW(COMDLG32_hInstance
, idCaption
, strMsgTitle
, sizeof(strMsgTitle
)/sizeof(WCHAR
));
1783 strMsgTitle
[0] = '\0';
1784 LoadStringW(COMDLG32_hInstance
, idText
, strMsgText
, sizeof(strMsgText
)/sizeof(WCHAR
));
1785 MessageBoxW(hwnd
,strMsgText
, strMsgTitle
, MB_OK
| MB_ICONHAND
);
1788 BOOL
FILEDLG95_OnOpen(HWND hwnd
)
1790 LPWSTR lpstrFileList
;
1791 UINT nFileCount
= 0;
1794 WCHAR lpstrPathAndFile
[MAX_PATH
];
1795 WCHAR lpstrTemp
[MAX_PATH
];
1796 LPSHELLFOLDER lpsf
= NULL
;
1798 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1800 TRACE("hwnd=%p\n", hwnd
);
1802 /* get the files from the edit control */
1803 nFileCount
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
, '\0');
1805 /* try if the user selected a folder in the shellview */
1808 BrowseSelectedFolder(hwnd
);
1814 ret
= FILEDLG95_OnOpenMultipleFiles(hwnd
, lpstrFileList
, nFileCount
, sizeUsed
);
1818 TRACE("count=%u len=%u file=%s\n", nFileCount
, sizeUsed
, debugstr_w(lpstrFileList
));
1821 Step 1: Build a complete path name from the current folder and
1822 the filename or path in the edit box.
1824 - the path in the edit box is a root path
1825 (with or without drive letter)
1826 - the edit box contains ".." (or a path with ".." in it)
1829 /* Get the current directory name */
1830 if (!COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathAndFile
))
1833 GetCurrentDirectoryW(MAX_PATH
, lpstrPathAndFile
);
1835 PathAddBackslashW(lpstrPathAndFile
);
1837 TRACE("current directory=%s\n", debugstr_w(lpstrPathAndFile
));
1839 /* if the user specifyed a fully qualified path use it */
1840 if(PathIsRelativeW(lpstrFileList
))
1842 strcatW(lpstrPathAndFile
, lpstrFileList
);
1846 /* does the path have a drive letter? */
1847 if (PathGetDriveNumberW(lpstrFileList
) == -1)
1848 strcpyW(lpstrPathAndFile
+2, lpstrFileList
);
1850 strcpyW(lpstrPathAndFile
, lpstrFileList
);
1853 /* resolve "." and ".." */
1854 PathCanonicalizeW(lpstrTemp
, lpstrPathAndFile
);
1855 strcpyW(lpstrPathAndFile
, lpstrTemp
);
1856 TRACE("canon=%s\n", debugstr_w(lpstrPathAndFile
));
1858 MemFree(lpstrFileList
);
1861 Step 2: here we have a cleaned up path
1863 We have to parse the path step by step to see if we have to browse
1864 to a folder if the path points to a directory or the last
1865 valid element is a directory.
1868 lpstrPathAndFile: cleaned up path
1872 (fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1873 !(fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
))
1874 nOpenAction
= ONOPEN_OPEN
;
1876 nOpenAction
= ONOPEN_BROWSE
;
1878 /* don't apply any checks with OFN_NOVALIDATE */
1880 LPWSTR lpszTemp
, lpszTemp1
;
1881 LPITEMIDLIST pidl
= NULL
;
1882 static const WCHAR szwInvalid
[] = { '/',':','<','>','|', 0};
1884 /* check for invalid chars */
1885 if((strpbrkW(lpstrPathAndFile
+3, szwInvalid
) != NULL
) && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1887 FILEDLG95_OnOpenMessage(hwnd
, IDS_INVALID_FILENAME_TITLE
, IDS_INVALID_FILENAME
);
1892 if (FAILED (SHGetDesktopFolder(&lpsf
))) return FALSE
;
1894 lpszTemp1
= lpszTemp
= lpstrPathAndFile
;
1897 LPSHELLFOLDER lpsfChild
;
1898 WCHAR lpwstrTemp
[MAX_PATH
];
1899 DWORD dwEaten
, dwAttributes
;
1902 strcpyW(lpwstrTemp
, lpszTemp
);
1903 p
= PathFindNextComponentW(lpwstrTemp
);
1905 if (!p
) break; /* end of path */
1908 lpszTemp
= lpszTemp
+ strlenW(lpwstrTemp
);
1910 /* There are no wildcards when OFN_NOVALIDATE is set */
1911 if(*lpszTemp
==0 && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1913 static const WCHAR wszWild
[] = { '*', '?', 0 };
1914 /* if the last element is a wildcard do a search */
1915 if(strpbrkW(lpszTemp1
, wszWild
) != NULL
)
1917 nOpenAction
= ONOPEN_SEARCH
;
1921 lpszTemp1
= lpszTemp
;
1923 TRACE("parse now=%s next=%s sf=%p\n",debugstr_w(lpwstrTemp
), debugstr_w(lpszTemp
), lpsf
);
1925 /* append a backslash to drive letters */
1926 if(lstrlenW(lpwstrTemp
)==2 && lpwstrTemp
[1] == ':' &&
1927 ((lpwstrTemp
[0] >= 'a' && lpwstrTemp
[0] <= 'z') ||
1928 (lpwstrTemp
[0] >= 'A' && lpwstrTemp
[0] <= 'Z')))
1930 PathAddBackslashW(lpwstrTemp
);
1933 dwAttributes
= SFGAO_FOLDER
;
1934 if(SUCCEEDED(IShellFolder_ParseDisplayName(lpsf
, hwnd
, NULL
, lpwstrTemp
, &dwEaten
, &pidl
, &dwAttributes
)))
1936 /* the path component is valid, we have a pidl of the next path component */
1937 TRACE("parse OK attr=0x%08lx pidl=%p\n", dwAttributes
, pidl
);
1938 if(dwAttributes
& SFGAO_FOLDER
)
1940 if(FAILED(IShellFolder_BindToObject(lpsf
, pidl
, 0, &IID_IShellFolder
, (LPVOID
*)&lpsfChild
)))
1942 ERR("bind to failed\n"); /* should not fail */
1945 IShellFolder_Release(lpsf
);
1953 /* end dialog, return value */
1954 nOpenAction
= ONOPEN_OPEN
;
1957 COMDLG32_SHFree(pidl
);
1960 else if (!(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1962 if(*lpszTemp
) /* points to trailing null for last path element */
1964 if(fodInfos
->ofnInfos
->Flags
& OFN_PATHMUSTEXIST
)
1966 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_PATHNOTEXISTING
);
1972 if( (fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1973 !( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1975 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_FILENOTEXISTING
);
1979 /* change to the current folder */
1980 nOpenAction
= ONOPEN_OPEN
;
1985 nOpenAction
= ONOPEN_OPEN
;
1989 if(pidl
) COMDLG32_SHFree(pidl
);
1993 Step 3: here we have a cleaned up and validated path
1996 lpsf: ShellFolder bound to the rightmost valid path component
1997 lpstrPathAndFile: cleaned up path
1998 nOpenAction: action to do
2000 TRACE("end validate sf=%p\n", lpsf
);
2004 case ONOPEN_SEARCH
: /* set the current filter to the file mask and refresh */
2005 TRACE("ONOPEN_SEARCH %s\n", debugstr_w(lpstrPathAndFile
));
2008 LPWSTR lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
2011 /* replace the current filter */
2012 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
2013 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2014 len
= strlenW(lpszTemp
)+1;
2015 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc(len
* sizeof(WCHAR
));
2016 strcpyW( fodInfos
->ShellInfos
.lpstrCurrentFilter
, lpszTemp
);
2018 /* set the filter cb to the extension when possible */
2019 if(-1 < (iPos
= FILEDLG95_FILETYPE_SearchExt(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpszTemp
)))
2020 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, iPos
);
2023 case ONOPEN_BROWSE
: /* browse to the highest folder we could bind to */
2024 TRACE("ONOPEN_BROWSE\n");
2026 IPersistFolder2
* ppf2
;
2027 if(SUCCEEDED(IShellFolder_QueryInterface( lpsf
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
)))
2029 LPITEMIDLIST pidlCurrent
;
2030 IPersistFolder2_GetCurFolder(ppf2
, &pidlCurrent
);
2031 IPersistFolder2_Release(ppf2
);
2032 if( ! COMDLG32_PIDL_ILIsEqual(pidlCurrent
, fodInfos
->ShellInfos
.pidlAbsCurrent
))
2034 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidlCurrent
, SBSP_ABSOLUTE
);
2036 else if( nOpenAction
== ONOPEN_SEARCH
)
2038 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
2040 COMDLG32_SHFree(pidlCurrent
);
2045 case ONOPEN_OPEN
: /* fill in the return struct and close the dialog */
2046 TRACE("ONOPEN_OPEN %s\n", debugstr_w(lpstrPathAndFile
));
2050 /* update READONLY check box flag */
2051 if ((SendMessageA(GetDlgItem(hwnd
,IDC_OPENREADONLY
),BM_GETCHECK
,0,0) & 0x03) == BST_CHECKED
)
2052 fodInfos
->ofnInfos
->Flags
|= OFN_READONLY
;
2054 fodInfos
->ofnInfos
->Flags
&= ~OFN_READONLY
;
2056 /* Attach the file extension with file name*/
2057 ext
= PathFindExtensionW(lpstrPathAndFile
);
2060 /* if no extension is specified with file name, then */
2061 /* attach the extension from file filter or default one */
2063 WCHAR
*filterExt
= NULL
;
2064 LPWSTR lpstrFilter
= NULL
;
2065 static const WCHAR szwDot
[] = {'.',0};
2066 int PathLength
= strlenW(lpstrPathAndFile
);
2069 strcatW(lpstrPathAndFile
, szwDot
);
2071 /*Get the file extension from file type filter*/
2072 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2073 fodInfos
->ofnInfos
->nFilterIndex
-1);
2075 if (lpstrFilter
!= (LPWSTR
)CB_ERR
) /* control is not empty */
2076 filterExt
= PathFindExtensionW(lpstrFilter
);
2078 if ( filterExt
&& *filterExt
) /* attach the file extension from file type filter*/
2079 strcatW(lpstrPathAndFile
, filterExt
+ 1);
2080 else if ( fodInfos
->defext
) /* attach the default file extension*/
2081 strcatW(lpstrPathAndFile
, fodInfos
->defext
);
2083 /* In Open dialog: if file does not exist try without extension */
2084 if (!(fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) && !PathFileExistsW(lpstrPathAndFile
))
2085 lpstrPathAndFile
[PathLength
] = '\0';
2088 if (fodInfos
->defext
) /* add default extension */
2090 /* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
2093 if (!lstrcmpiW(fodInfos
->defext
, ext
))
2094 fodInfos
->ofnInfos
->Flags
&= ~OFN_EXTENSIONDIFFERENT
;
2096 fodInfos
->ofnInfos
->Flags
|= OFN_EXTENSIONDIFFERENT
;
2099 /* In Save dialog: check if the file already exists */
2100 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
2101 && fodInfos
->ofnInfos
->Flags
& OFN_OVERWRITEPROMPT
2102 && PathFileExistsW(lpstrPathAndFile
))
2104 WCHAR lpstrOverwrite
[100];
2107 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, lpstrOverwrite
, 100);
2108 answer
= MessageBoxW(hwnd
, lpstrOverwrite
, fodInfos
->title
,
2109 MB_YESNO
| MB_ICONEXCLAMATION
);
2117 /* Check that the size of the file does not exceed buffer size.
2118 (Allow for extra \0 if OFN_MULTISELECT is set.) */
2119 if(strlenW(lpstrPathAndFile
) < fodInfos
->ofnInfos
->nMaxFile
-
2120 ((fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
) ? 1 : 0))
2124 /* fill destination buffer */
2125 if (fodInfos
->ofnInfos
->lpstrFile
)
2127 if(fodInfos
->unicode
)
2129 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
2131 lstrcpynW(ofn
->lpstrFile
, lpstrPathAndFile
, ofn
->nMaxFile
);
2132 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
2133 ofn
->lpstrFile
[lstrlenW(ofn
->lpstrFile
) + 1] = '\0';
2137 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2139 WideCharToMultiByte(CP_ACP
, 0, lpstrPathAndFile
, -1,
2140 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
2141 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
2142 ofn
->lpstrFile
[lstrlenA(ofn
->lpstrFile
) + 1] = '\0';
2146 /* set filename offset */
2147 lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
2148 fodInfos
->ofnInfos
->nFileOffset
= (lpszTemp
- lpstrPathAndFile
);
2150 /* set extension offset */
2151 lpszTemp
= PathFindExtensionW(lpstrPathAndFile
);
2152 fodInfos
->ofnInfos
->nFileExtension
= (*lpszTemp
) ? (lpszTemp
- lpstrPathAndFile
) + 1 : 0;
2154 /* set the lpstrFileTitle */
2155 if(fodInfos
->ofnInfos
->lpstrFileTitle
)
2157 LPWSTR lpstrFileTitle
= PathFindFileNameW(lpstrPathAndFile
);
2158 if(fodInfos
->unicode
)
2160 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
2161 lstrcpynW(ofn
->lpstrFileTitle
, lpstrFileTitle
, ofn
->nMaxFileTitle
);
2165 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2166 WideCharToMultiByte(CP_ACP
, 0, lpstrFileTitle
, -1,
2167 ofn
->lpstrFileTitle
, ofn
->nMaxFileTitle
, NULL
, NULL
);
2171 /* copy currently selected filter to lpstrCustomFilter */
2172 if (fodInfos
->ofnInfos
->lpstrCustomFilter
)
2174 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2175 int len
= WideCharToMultiByte(CP_ACP
, 0, fodInfos
->ShellInfos
.lpstrCurrentFilter
, -1,
2176 NULL
, 0, NULL
, NULL
);
2177 if (len
+ strlen(ofn
->lpstrCustomFilter
) + 1 <= ofn
->nMaxCustFilter
)
2179 LPSTR s
= ofn
->lpstrCustomFilter
;
2180 s
+= strlen(ofn
->lpstrCustomFilter
)+1;
2181 WideCharToMultiByte(CP_ACP
, 0, fodInfos
->ShellInfos
.lpstrCurrentFilter
, -1,
2182 s
, len
, NULL
, NULL
);
2187 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
2191 FILEDLG95_Clean(hwnd
);
2192 ret
= EndDialog(hwnd
, TRUE
);
2198 size
= strlenW(lpstrPathAndFile
) + 1;
2199 if (fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
)
2201 /* return needed size in first two bytes of lpstrFile */
2202 *(WORD
*)fodInfos
->ofnInfos
->lpstrFile
= size
;
2203 FILEDLG95_Clean(hwnd
);
2204 ret
= EndDialog(hwnd
, FALSE
);
2205 COMDLG32_SetCommDlgExtendedError(FNERR_BUFFERTOOSMALL
);
2213 if(lpsf
) IShellFolder_Release(lpsf
);
2217 /***********************************************************************
2218 * FILEDLG95_SHELL_Init
2220 * Initialisation of the shell objects
2222 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
)
2224 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2229 * Initialisation of the FileOpenDialogInfos structure
2235 fodInfos
->ShellInfos
.hwndOwner
= hwnd
;
2237 /* Disable multi-select if flag not set */
2238 if (!(fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
))
2240 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_SINGLESEL
;
2242 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_AUTOARRANGE
| FWF_ALIGNLEFT
;
2243 fodInfos
->ShellInfos
.folderSettings
.ViewMode
= FVM_LIST
;
2245 /* Construct the IShellBrowser interface */
2246 fodInfos
->Shell
.FOIShellBrowser
= IShellBrowserImpl_Construct(hwnd
);
2251 /***********************************************************************
2252 * FILEDLG95_SHELL_ExecuteCommand
2254 * Change the folder option and refresh the view
2255 * If the function succeeds, the return value is nonzero.
2257 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
)
2259 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2262 TRACE("(%p,%p)\n", hwnd
, lpVerb
);
2264 if(SUCCEEDED(IShellView_GetItemObject(fodInfos
->Shell
.FOIShellView
,
2269 CMINVOKECOMMANDINFO ci
;
2270 ZeroMemory(&ci
, sizeof(CMINVOKECOMMANDINFO
));
2271 ci
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
2275 IContextMenu_InvokeCommand(pcm
, &ci
);
2276 IContextMenu_Release(pcm
);
2282 /***********************************************************************
2283 * FILEDLG95_SHELL_UpFolder
2285 * Browse to the specified object
2286 * If the function succeeds, the return value is nonzero.
2288 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
)
2290 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2294 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2298 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2304 /***********************************************************************
2305 * FILEDLG95_SHELL_BrowseToDesktop
2307 * Browse to the Desktop
2308 * If the function succeeds, the return value is nonzero.
2310 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
)
2312 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2318 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidl
);
2319 hres
= IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidl
, SBSP_ABSOLUTE
);
2320 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2321 COMDLG32_SHFree(pidl
);
2322 return SUCCEEDED(hres
);
2324 /***********************************************************************
2325 * FILEDLG95_SHELL_Clean
2327 * Cleans the memory used by shell objects
2329 static void FILEDLG95_SHELL_Clean(HWND hwnd
)
2331 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2335 COMDLG32_SHFree(fodInfos
->ShellInfos
.pidlAbsCurrent
);
2337 /* clean Shell interfaces */
2338 IShellView_DestroyViewWindow(fodInfos
->Shell
.FOIShellView
);
2339 IShellView_Release(fodInfos
->Shell
.FOIShellView
);
2340 IShellFolder_Release(fodInfos
->Shell
.FOIShellFolder
);
2341 IShellBrowser_Release(fodInfos
->Shell
.FOIShellBrowser
);
2342 if (fodInfos
->Shell
.FOIDataObject
)
2343 IDataObject_Release(fodInfos
->Shell
.FOIDataObject
);
2346 /***********************************************************************
2347 * FILEDLG95_FILETYPE_Init
2349 * Initialisation of the file type combo box
2351 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
)
2353 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2354 int nFilters
= 0; /* number of filters */
2359 if(fodInfos
->customfilter
)
2361 /* customfilter has one entry... title\0ext\0
2362 * Set first entry of combo box item with customfilter
2365 LPCWSTR lpstrPos
= fodInfos
->customfilter
;
2368 lpstrPos
+= strlenW(fodInfos
->customfilter
) + 1;
2370 /* Copy the extensions */
2371 if (! *lpstrPos
) return E_FAIL
; /* malformed filter */
2372 if (!(lpstrExt
= MemAlloc((strlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2373 strcpyW(lpstrExt
,lpstrPos
);
2375 /* Add the item at the end of the combo */
2376 CBAddStringW(fodInfos
->DlgInfos
.hwndFileTypeCB
, fodInfos
->customfilter
);
2377 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
, lpstrExt
);
2380 if(fodInfos
->filter
)
2382 LPCWSTR lpstrPos
= fodInfos
->filter
;
2386 /* filter is a list... title\0ext\0......\0\0
2387 * Set the combo item text to the title and the item data
2390 LPCWSTR lpstrDisplay
;
2394 if(! *lpstrPos
) break; /* end */
2395 lpstrDisplay
= lpstrPos
;
2396 lpstrPos
+= strlenW(lpstrPos
) + 1;
2398 /* Copy the extensions */
2399 if (! *lpstrPos
) return E_FAIL
; /* malformed filter */
2400 if (!(lpstrExt
= MemAlloc((strlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2401 strcpyW(lpstrExt
,lpstrPos
);
2402 lpstrPos
+= strlenW(lpstrPos
) + 1;
2404 /* Add the item at the end of the combo */
2405 CBAddStringW(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpstrDisplay
);
2406 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
, lpstrExt
);
2412 * Set the current filter to the one specified
2413 * in the initialisation structure
2415 if (fodInfos
->filter
|| fodInfos
->customfilter
)
2419 /* Check to make sure our index isn't out of bounds. */
2420 if ( fodInfos
->ofnInfos
->nFilterIndex
>
2421 nFilters
- (fodInfos
->customfilter
== NULL
? 0 : 1) )
2422 fodInfos
->ofnInfos
->nFilterIndex
= (fodInfos
->customfilter
== NULL
? 1 : 0);
2424 /* set default filter index */
2425 if(fodInfos
->ofnInfos
->nFilterIndex
== 0 && fodInfos
->customfilter
== NULL
)
2426 fodInfos
->ofnInfos
->nFilterIndex
= 1;
2428 /* calculate index of Combo Box item */
2429 nFilterIndexCB
= fodInfos
->ofnInfos
->nFilterIndex
;
2430 if (fodInfos
->customfilter
== NULL
)
2433 /* Set the current index selection. */
2434 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilterIndexCB
);
2436 /* Get the corresponding text string from the combo box. */
2437 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2440 if ((INT_PTR
)lpstrFilter
== CB_ERR
) /* control is empty */
2446 CharLowerW(lpstrFilter
); /* lowercase */
2447 len
= strlenW(lpstrFilter
)+1;
2448 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2449 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2452 fodInfos
->ofnInfos
->nFilterIndex
= 0;
2456 /***********************************************************************
2457 * FILEDLG95_FILETYPE_OnCommand
2459 * WM_COMMAND of the file type combo box
2460 * If the function succeeds, the return value is nonzero.
2462 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2464 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2472 /* Get the current item of the filetype combo box */
2473 int iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2475 /* set the current filter index */
2476 fodInfos
->ofnInfos
->nFilterIndex
= iItem
+
2477 (fodInfos
->customfilter
== NULL
? 1 : 0);
2479 /* Set the current filter with the current selection */
2480 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
2481 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2483 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2485 if((INT_PTR
)lpstrFilter
!= CB_ERR
)
2488 CharLowerW(lpstrFilter
); /* lowercase */
2489 len
= strlenW(lpstrFilter
)+1;
2490 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2491 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2492 SendCustomDlgNotificationMessage(hwnd
,CDN_TYPECHANGE
);
2495 /* Refresh the actual view to display the included items*/
2496 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
2501 /***********************************************************************
2502 * FILEDLG95_FILETYPE_SearchExt
2504 * searches for an extension in the filetype box
2506 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
)
2508 int i
, iCount
= CBGetCount(hwnd
);
2510 TRACE("%s\n", debugstr_w(lpstrExt
));
2512 if(iCount
!= CB_ERR
)
2514 for(i
=0;i
<iCount
;i
++)
2516 if(!lstrcmpiW(lpstrExt
,(LPWSTR
)CBGetItemDataPtr(hwnd
,i
)))
2523 /***********************************************************************
2524 * FILEDLG95_FILETYPE_Clean
2526 * Clean the memory used by the filetype combo box
2528 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
)
2530 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2532 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2536 /* Delete each string of the combo and their associated data */
2537 if(iCount
!= CB_ERR
)
2539 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2541 MemFree((LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
));
2542 CBDeleteString(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
2545 /* Current filter */
2546 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
2547 MemFree(fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2551 /***********************************************************************
2552 * FILEDLG95_LOOKIN_Init
2554 * Initialisation of the look in combo box
2557 /* Small helper function, to determine if the unixfs shell extension is rooted
2558 * at the desktop. Copied from dlls/shell32/shfldr_unixfs.c.
2560 static inline BOOL
FILEDLG95_unixfs_is_rooted_at_desktop(void) {
2562 static const WCHAR wszRootedAtDesktop
[] = { 'S','o','f','t','w','a','r','e','\\',
2563 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2564 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2565 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
2566 'N','a','m','e','S','p','a','c','e','\\','{','9','D','2','0','A','A','E','8',
2567 '-','0','6','2','5','-','4','4','B','0','-','9','C','A','7','-',
2568 '7','1','8','8','9','C','2','2','5','4','D','9','}',0 };
2570 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, wszRootedAtDesktop
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
2577 static void FILEDLG95_LOOKIN_Init(HWND hwndCombo
)
2579 IShellFolder
*psfRoot
, *psfDrives
;
2580 IEnumIDList
*lpeRoot
, *lpeDrives
;
2581 LPITEMIDLIST pidlDrives
, pidlTmp
, pidlTmp1
, pidlAbsTmp
;
2583 LookInInfos
*liInfos
= MemAlloc(sizeof(LookInInfos
));
2587 liInfos
->iMaxIndentation
= 0;
2589 SetPropA(hwndCombo
, LookInInfosStr
, (HANDLE
) liInfos
);
2591 /* set item height for both text field and listbox */
2592 CBSetItemHeight(hwndCombo
,-1,GetSystemMetrics(SM_CYSMICON
));
2593 CBSetItemHeight(hwndCombo
,0,GetSystemMetrics(SM_CYSMICON
));
2595 /* Turn on the extended UI for the combo box like Windows does */
2596 CBSetExtendedUI(hwndCombo
, TRUE
);
2598 /* Initialise data of Desktop folder */
2599 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidlTmp
);
2600 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2601 COMDLG32_SHFree(pidlTmp
);
2603 SHGetSpecialFolderLocation(0,CSIDL_DRIVES
,&pidlDrives
);
2605 SHGetDesktopFolder(&psfRoot
);
2609 /* enumerate the contents of the desktop */
2610 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot
, hwndCombo
, SHCONTF_FOLDERS
, &lpeRoot
)))
2612 while (S_OK
== IEnumIDList_Next(lpeRoot
, 1, &pidlTmp
, NULL
))
2614 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2616 /* If the unixfs extension is rooted, we don't expand the drives by default */
2617 if (!FILEDLG95_unixfs_is_rooted_at_desktop())
2619 /* special handling for CSIDL_DRIVES */
2620 if (COMDLG32_PIDL_ILIsEqual(pidlTmp
, pidlDrives
))
2622 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot
, pidlTmp
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfDrives
)))
2624 /* enumerate the drives */
2625 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives
, hwndCombo
,SHCONTF_FOLDERS
, &lpeDrives
)))
2627 while (S_OK
== IEnumIDList_Next(lpeDrives
, 1, &pidlTmp1
, NULL
))
2629 pidlAbsTmp
= COMDLG32_PIDL_ILCombine(pidlTmp
, pidlTmp1
);
2630 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlAbsTmp
,LISTEND
);
2631 COMDLG32_SHFree(pidlAbsTmp
);
2632 COMDLG32_SHFree(pidlTmp1
);
2634 IEnumIDList_Release(lpeDrives
);
2636 IShellFolder_Release(psfDrives
);
2641 COMDLG32_SHFree(pidlTmp
);
2643 IEnumIDList_Release(lpeRoot
);
2645 IShellFolder_Release(psfRoot
);
2648 COMDLG32_SHFree(pidlDrives
);
2651 /***********************************************************************
2652 * FILEDLG95_LOOKIN_DrawItem
2654 * WM_DRAWITEM message handler
2656 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
)
2658 COLORREF crWin
= GetSysColor(COLOR_WINDOW
);
2659 COLORREF crHighLight
= GetSysColor(COLOR_HIGHLIGHT
);
2660 COLORREF crText
= GetSysColor(COLOR_WINDOWTEXT
);
2664 HIMAGELIST ilItemImage
;
2667 LPSFOLDER tmpFolder
;
2670 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(pDIStruct
->hwndItem
,LookInInfosStr
);
2674 if(pDIStruct
->itemID
== -1)
2677 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(pDIStruct
->hwndItem
,
2678 pDIStruct
->itemID
)))
2682 if(pDIStruct
->itemID
== liInfos
->uSelectedItem
)
2684 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2687 sizeof (SHFILEINFOA
),
2688 SHGFI_PIDL
| SHGFI_SMALLICON
|
2689 SHGFI_OPENICON
| SHGFI_SYSICONINDEX
|
2690 SHGFI_DISPLAYNAME
);
2694 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2697 sizeof (SHFILEINFOA
),
2698 SHGFI_PIDL
| SHGFI_SMALLICON
|
2699 SHGFI_SYSICONINDEX
|
2703 /* Is this item selected ? */
2704 if(pDIStruct
->itemState
& ODS_SELECTED
)
2706 SetTextColor(pDIStruct
->hDC
,(0x00FFFFFF & ~(crText
)));
2707 SetBkColor(pDIStruct
->hDC
,crHighLight
);
2708 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_HIGHLIGHT
));
2712 SetTextColor(pDIStruct
->hDC
,crText
);
2713 SetBkColor(pDIStruct
->hDC
,crWin
);
2714 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_WINDOW
));
2717 /* Do not indent item if drawing in the edit of the combo */
2718 if(pDIStruct
->itemState
& ODS_COMBOBOXEDIT
)
2721 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2724 sizeof (SHFILEINFOA
),
2725 SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_OPENICON
2726 | SHGFI_SYSICONINDEX
| SHGFI_DISPLAYNAME
);
2731 iIndentation
= tmpFolder
->m_iIndent
;
2733 /* Draw text and icon */
2735 /* Initialise the icon display area */
2736 rectIcon
.left
= pDIStruct
->rcItem
.left
+ ICONWIDTH
/2 * iIndentation
;
2737 rectIcon
.top
= pDIStruct
->rcItem
.top
;
2738 rectIcon
.right
= rectIcon
.left
+ ICONWIDTH
;
2739 rectIcon
.bottom
= pDIStruct
->rcItem
.bottom
;
2741 /* Initialise the text display area */
2742 GetTextMetricsA(pDIStruct
->hDC
, &tm
);
2743 rectText
.left
= rectIcon
.right
;
2745 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
- tm
.tmHeight
) / 2;
2746 rectText
.right
= pDIStruct
->rcItem
.right
+ XTEXTOFFSET
;
2748 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
+ tm
.tmHeight
) / 2;
2750 /* Draw the icon from the image list */
2751 ImageList_Draw(ilItemImage
,
2758 /* Draw the associated text */
2759 if(sfi
.szDisplayName
)
2760 TextOutA(pDIStruct
->hDC
,rectText
.left
,rectText
.top
,sfi
.szDisplayName
,strlen(sfi
.szDisplayName
));
2766 /***********************************************************************
2767 * FILEDLG95_LOOKIN_OnCommand
2769 * LookIn combo box WM_COMMAND message handler
2770 * If the function succeeds, the return value is nonzero.
2772 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2774 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2776 TRACE("%p\n", fodInfos
);
2782 LPSFOLDER tmpFolder
;
2785 iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndLookInCB
);
2787 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,
2792 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2793 tmpFolder
->pidlItem
,
2796 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2806 /***********************************************************************
2807 * FILEDLG95_LOOKIN_AddItem
2809 * Adds an absolute pidl item to the lookin combo box
2810 * returns the index of the inserted item
2812 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
)
2814 LPITEMIDLIST pidlNext
;
2817 LookInInfos
*liInfos
;
2819 TRACE("%08x\n", iInsertId
);
2824 if(!(liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
)))
2827 tmpFolder
= MemAlloc(sizeof(SFOLDER
));
2828 tmpFolder
->m_iIndent
= 0;
2830 /* Calculate the indentation of the item in the lookin*/
2832 while( (pidlNext
=COMDLG32_PIDL_ILGetNext(pidlNext
)) )
2834 tmpFolder
->m_iIndent
++;
2837 tmpFolder
->pidlItem
= COMDLG32_PIDL_ILClone(pidl
);
2839 if(tmpFolder
->m_iIndent
> liInfos
->iMaxIndentation
)
2840 liInfos
->iMaxIndentation
= tmpFolder
->m_iIndent
;
2842 sfi
.dwAttributes
= SFGAO_FILESYSANCESTOR
| SFGAO_FILESYSTEM
;
2843 SHGetFileInfoA((LPSTR
)pidl
,
2847 SHGFI_DISPLAYNAME
| SHGFI_SYSICONINDEX
2848 | SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_ATTRIBUTES
| SHGFI_ATTR_SPECIFIED
);
2850 TRACE("-- Add %s attr=%08lx\n", sfi
.szDisplayName
, sfi
.dwAttributes
);
2852 if((sfi
.dwAttributes
& SFGAO_FILESYSANCESTOR
) || (sfi
.dwAttributes
& SFGAO_FILESYSTEM
))
2856 TRACE("-- Add %s at %u\n", sfi
.szDisplayName
, tmpFolder
->m_iIndent
);
2858 /* Add the item at the end of the list */
2861 iItemID
= CBAddString(hwnd
,sfi
.szDisplayName
);
2863 /* Insert the item at the iInsertId position*/
2866 iItemID
= CBInsertString(hwnd
,sfi
.szDisplayName
,iInsertId
);
2869 CBSetItemDataPtr(hwnd
,iItemID
,tmpFolder
);
2873 COMDLG32_SHFree( tmpFolder
->pidlItem
);
2874 MemFree( tmpFolder
);
2879 /***********************************************************************
2880 * FILEDLG95_LOOKIN_InsertItemAfterParent
2882 * Insert an item below its parent
2884 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
)
2887 LPITEMIDLIST pidlParent
= GetParentPidl(pidl
);
2892 iParentPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidlParent
,SEARCH_PIDL
);
2896 iParentPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidlParent
);
2899 /* Free pidlParent memory */
2900 COMDLG32_SHFree((LPVOID
)pidlParent
);
2902 return FILEDLG95_LOOKIN_AddItem(hwnd
,pidl
,iParentPos
+ 1);
2905 /***********************************************************************
2906 * FILEDLG95_LOOKIN_SelectItem
2908 * Adds an absolute pidl item to the lookin combo box
2909 * returns the index of the inserted item
2911 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
)
2914 LookInInfos
*liInfos
;
2918 iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidl
,SEARCH_PIDL
);
2920 liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2924 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
) > -1);
2925 iItemPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidl
);
2930 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2931 while(liInfos
->iMaxIndentation
> tmpFolder
->m_iIndent
)
2935 if(-1 == (iRemovedItem
= FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
)))
2937 if(iRemovedItem
< iItemPos
)
2942 CBSetCurSel(hwnd
,iItemPos
);
2943 liInfos
->uSelectedItem
= iItemPos
;
2949 /***********************************************************************
2950 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2952 * Remove the item with an expansion level over iExpansionLevel
2954 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
)
2958 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2962 if(liInfos
->iMaxIndentation
<= 2)
2965 if((iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)liInfos
->iMaxIndentation
,SEARCH_EXP
)) >=0)
2967 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2968 COMDLG32_SHFree(tmpFolder
->pidlItem
);
2970 CBDeleteString(hwnd
,iItemPos
);
2971 liInfos
->iMaxIndentation
--;
2979 /***********************************************************************
2980 * FILEDLG95_LOOKIN_SearchItem
2982 * Search for pidl in the lookin combo box
2983 * returns the index of the found item
2985 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
)
2988 int iCount
= CBGetCount(hwnd
);
2990 TRACE("0x%08x 0x%x\n",searchArg
, iSearchMethod
);
2992 if (iCount
!= CB_ERR
)
2996 LPSFOLDER tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,i
);
2998 if(iSearchMethod
== SEARCH_PIDL
&& COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST
)searchArg
,tmpFolder
->pidlItem
))
3000 if(iSearchMethod
== SEARCH_EXP
&& tmpFolder
->m_iIndent
== (int)searchArg
)
3008 /***********************************************************************
3009 * FILEDLG95_LOOKIN_Clean
3011 * Clean the memory used by the lookin combo box
3013 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
)
3015 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3017 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndLookInCB
);
3021 /* Delete each string of the combo and their associated data */
3022 if (iCount
!= CB_ERR
)
3024 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
3026 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
3027 COMDLG32_SHFree(tmpFolder
->pidlItem
);
3029 CBDeleteString(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
3033 /* LookInInfos structure */
3034 RemovePropA(fodInfos
->DlgInfos
.hwndLookInCB
,LookInInfosStr
);
3037 /***********************************************************************
3038 * FILEDLG95_FILENAME_FillFromSelection
3040 * fills the edit box from the cached DataObject
3042 void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd
)
3044 FileOpenDlgInfos
*fodInfos
;
3046 UINT nFiles
= 0, nFileToOpen
, nFileSelected
, nLength
= 0;
3047 char lpstrTemp
[MAX_PATH
];
3048 LPSTR lpstrAllFile
= NULL
, lpstrCurrFile
= NULL
;
3051 fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3053 /* Count how many files we have */
3054 nFileSelected
= GetNumSelected( fodInfos
->Shell
.FOIDataObject
);
3056 /* calculate the string length, count files */
3057 if (nFileSelected
>= 1)
3059 nLength
+= 3; /* first and last quotes, trailing \0 */
3060 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
3062 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
3066 /* get the total length of the selected file names */
3067 lpstrTemp
[0] = '\0';
3068 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
3070 if ( ! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
) ) /* Ignore folders */
3072 nLength
+= strlen( lpstrTemp
) + 3;
3075 COMDLG32_SHFree( pidl
);
3080 /* allocate the buffer */
3081 if (nFiles
<= 1) nLength
= MAX_PATH
;
3082 lpstrAllFile
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nLength
);
3083 lpstrAllFile
[0] = '\0';
3085 /* Generate the string for the edit control */
3088 lpstrCurrFile
= lpstrAllFile
;
3089 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
3091 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
3095 /* get the file name */
3096 lpstrTemp
[0] = '\0';
3097 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
3099 if (! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
)) /* Ignore folders */
3103 *lpstrCurrFile
++ = '\"';
3104 strcpy( lpstrCurrFile
, lpstrTemp
);
3105 lpstrCurrFile
+= strlen( lpstrTemp
);
3106 strcpy( lpstrCurrFile
, "\" " );
3111 strcpy( lpstrAllFile
, lpstrTemp
);
3114 COMDLG32_SHFree( (LPVOID
) pidl
);
3117 SetWindowTextA( fodInfos
->DlgInfos
.hwndFileName
, lpstrAllFile
);
3119 /* Select the file name like Windows does */
3120 SendMessageA(fodInfos
->DlgInfos
.hwndFileName
, EM_SETSEL
, (WPARAM
)0, (LPARAM
)-1);
3122 HeapFree(GetProcessHeap(),0, lpstrAllFile
);
3126 /* copied from shell32 to avoid linking to it
3127 * FIXME: why? shell32 is already linked
3129 static HRESULT
COMDLG32_StrRetToStrNA (LPVOID dest
, DWORD len
, LPSTRRET src
, LPITEMIDLIST pidl
)
3134 WideCharToMultiByte(CP_ACP
, 0, src
->u
.pOleStr
, -1, (LPSTR
)dest
, len
, NULL
, NULL
);
3135 COMDLG32_SHFree(src
->u
.pOleStr
);
3139 lstrcpynA((LPSTR
)dest
, src
->u
.cStr
, len
);
3143 lstrcpynA((LPSTR
)dest
, ((LPCSTR
)&pidl
->mkid
)+src
->u
.uOffset
, len
);
3147 FIXME("unknown type!\n");
3150 *(LPSTR
)dest
= '\0';
3157 /***********************************************************************
3158 * FILEDLG95_FILENAME_GetFileNames
3160 * Copies the filenames to a delimited string list.
3161 * The delimiter is specified by the parameter 'separator',
3162 * usually either a space or a nul
3164 static int FILEDLG95_FILENAME_GetFileNames (HWND hwnd
, LPWSTR
* lpstrFileList
, UINT
* sizeUsed
, char separator
)
3166 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3167 UINT nStrCharCount
= 0; /* index in src buffer */
3168 UINT nFileIndex
= 0; /* index in dest buffer */
3169 UINT nFileCount
= 0; /* number of files */
3170 UINT nStrLen
= 0; /* length of string in edit control */
3171 LPWSTR lpstrEdit
; /* buffer for string from edit control */
3175 /* get the filenames from the edit control */
3176 nStrLen
= SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXTLENGTH
, 0, 0);
3177 lpstrEdit
= MemAlloc( (nStrLen
+1)*sizeof(WCHAR
) );
3178 GetDlgItemTextW(hwnd
, IDC_FILENAME
, lpstrEdit
, nStrLen
+1);
3180 TRACE("nStrLen=%u str=%s\n", nStrLen
, debugstr_w(lpstrEdit
));
3182 /* we might get single filename without any '"',
3183 * so we need nStrLen + terminating \0 + end-of-list \0 */
3184 *lpstrFileList
= MemAlloc( (nStrLen
+2)*sizeof(WCHAR
) );
3187 /* build delimited file list from filenames */
3188 while ( nStrCharCount
<= nStrLen
)
3190 if ( lpstrEdit
[nStrCharCount
]=='"' )
3193 while ((lpstrEdit
[nStrCharCount
]!='"') && (nStrCharCount
<= nStrLen
))
3195 (*lpstrFileList
)[nFileIndex
++] = lpstrEdit
[nStrCharCount
];
3199 (*lpstrFileList
)[nFileIndex
++] = separator
;
3206 /* single, unquoted string */
3207 if ((nStrLen
> 0) && (*sizeUsed
== 0) )
3209 strcpyW(*lpstrFileList
, lpstrEdit
);
3210 nFileIndex
= strlenW(lpstrEdit
) + 1;
3211 (*sizeUsed
) = nFileIndex
;
3216 (*lpstrFileList
)[nFileIndex
] = '\0';
3223 #define SETDefFormatEtc(fe,cf,med) \
3225 (fe).cfFormat = cf;\
3226 (fe).dwAspect = DVASPECT_CONTENT; \
3233 * DATAOBJECT Helper functions
3236 /***********************************************************************
3237 * COMCTL32_ReleaseStgMedium
3239 * like ReleaseStgMedium from ole32
3241 static void COMCTL32_ReleaseStgMedium (STGMEDIUM medium
)
3243 if(medium
.pUnkForRelease
)
3245 IUnknown_Release(medium
.pUnkForRelease
);
3249 GlobalUnlock(medium
.u
.hGlobal
);
3250 GlobalFree(medium
.u
.hGlobal
);
3254 /***********************************************************************
3255 * GetPidlFromDataObject
3257 * Return pidl(s) by number from the cached DataObject
3259 * nPidlIndex=0 gets the fully qualified root path
3261 LPITEMIDLIST
GetPidlFromDataObject ( IDataObject
*doSelected
, UINT nPidlIndex
)
3265 FORMATETC formatetc
;
3266 LPITEMIDLIST pidl
= NULL
;
3268 TRACE("sv=%p index=%u\n", doSelected
, nPidlIndex
);
3273 /* Set the FORMATETC structure*/
3274 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
3276 /* Get the pidls from IDataObject */
3277 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3279 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3280 if(nPidlIndex
<= cida
->cidl
)
3282 pidl
= COMDLG32_PIDL_ILClone((LPITEMIDLIST
)(&((LPBYTE
)cida
)[cida
->aoffset
[nPidlIndex
]]));
3284 COMCTL32_ReleaseStgMedium(medium
);
3289 /***********************************************************************
3292 * Return the number of selected items in the DataObject.
3295 UINT
GetNumSelected( IDataObject
*doSelected
)
3299 FORMATETC formatetc
;
3301 TRACE("sv=%p\n", doSelected
);
3303 if (!doSelected
) return 0;
3305 /* Set the FORMATETC structure*/
3306 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
3308 /* Get the pidls from IDataObject */
3309 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3311 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3312 retVal
= cida
->cidl
;
3313 COMCTL32_ReleaseStgMedium(medium
);
3323 /***********************************************************************
3326 * Get the pidl's display name (relative to folder) and
3327 * put it in lpstrFileName.
3329 * Return NOERROR on success,
3333 static HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
)
3338 TRACE("sf=%p pidl=%p\n", lpsf
, pidl
);
3342 SHGetDesktopFolder(&lpsf
);
3343 hRes
= GetName(lpsf
,pidl
,dwFlags
,lpstrFileName
);
3344 IShellFolder_Release(lpsf
);
3348 /* Get the display name of the pidl relative to the folder */
3349 if (SUCCEEDED(hRes
= IShellFolder_GetDisplayNameOf(lpsf
, pidl
, dwFlags
, &str
)))
3351 return COMDLG32_StrRetToStrNA(lpstrFileName
, MAX_PATH
, &str
, pidl
);
3356 /***********************************************************************
3357 * GetShellFolderFromPidl
3359 * pidlRel is the item pidl relative
3360 * Return the IShellFolder of the absolute pidl
3362 IShellFolder
*GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
)
3364 IShellFolder
*psf
= NULL
,*psfParent
;
3366 TRACE("%p\n", pidlAbs
);
3368 if(SUCCEEDED(SHGetDesktopFolder(&psfParent
)))
3371 if(pidlAbs
&& pidlAbs
->mkid
.cb
)
3373 if(SUCCEEDED(IShellFolder_BindToObject(psfParent
, pidlAbs
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psf
)))
3375 IShellFolder_Release(psfParent
);
3379 /* return the desktop */
3385 /***********************************************************************
3388 * Return the LPITEMIDLIST to the parent of the pidl in the list
3390 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
)
3392 LPITEMIDLIST pidlParent
;
3394 TRACE("%p\n", pidl
);
3396 pidlParent
= COMDLG32_PIDL_ILClone(pidl
);
3397 COMDLG32_PIDL_ILRemoveLastID(pidlParent
);
3402 /***********************************************************************
3405 * returns the pidl of the file name relative to folder
3406 * NULL if an error occurred
3408 LPITEMIDLIST
GetPidlFromName(IShellFolder
*lpsf
,LPWSTR lpcstrFileName
)
3410 LPITEMIDLIST pidl
= NULL
;
3413 TRACE("sf=%p file=%s\n", lpsf
, debugstr_w(lpcstrFileName
));
3415 if(!lpcstrFileName
) return NULL
;
3416 if(!*lpcstrFileName
) return NULL
;
3420 if (SUCCEEDED(SHGetDesktopFolder(&lpsf
))) {
3421 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3422 IShellFolder_Release(lpsf
);
3427 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3434 BOOL
IsPidlFolder (LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
)
3436 ULONG uAttr
= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
;
3439 TRACE("%p, %p\n", psf
, pidl
);
3441 ret
= IShellFolder_GetAttributesOf( psf
, 1, &pidl
, &uAttr
);
3443 TRACE("-- 0x%08lx 0x%08lx\n", uAttr
, ret
);
3444 /* see documentation shell 4.1*/
3445 return uAttr
& (SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
);
3448 /***********************************************************************
3449 * BrowseSelectedFolder
3451 static BOOL
BrowseSelectedFolder(HWND hwnd
)
3453 BOOL bBrowseSelFolder
= FALSE
;
3454 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3458 if (GetNumSelected(fodInfos
->Shell
.FOIDataObject
) == 1)
3460 LPITEMIDLIST pidlSelection
;
3462 /* get the file selected */
3463 pidlSelection
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, 1);
3464 if (IsPidlFolder (fodInfos
->Shell
.FOIShellFolder
, pidlSelection
))
3466 if ( FAILED( IShellBrowser_BrowseObject( fodInfos
->Shell
.FOIShellBrowser
,
3467 pidlSelection
, SBSP_RELATIVE
) ) )
3469 static const WCHAR notexist
[] = {'P','a','t','h',' ','d','o','e','s',
3470 ' ','n','o','t',' ','e','x','i','s','t',0};
3471 MessageBoxW( hwnd
, notexist
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
3473 bBrowseSelFolder
= TRUE
;
3474 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
3476 COMDLG32_SHFree( pidlSelection
);
3479 return bBrowseSelFolder
;
3483 * Memory allocation methods */
3484 static void *MemAlloc(UINT size
)
3486 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
3489 static void MemFree(void *mem
)
3491 HeapFree(GetProcessHeap(),0,mem
);
3495 * Old-style (win3.1) dialogs */
3497 /***********************************************************************
3498 * FD32_GetTemplate [internal]
3500 * Get a template (or FALSE if failure) when 16 bits dialogs are used
3501 * by a 32 bits application
3504 static BOOL
FD32_GetTemplate(PFD31_DATA lfs
)
3506 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3507 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3510 if (ofnW
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
3512 if (!(lfs
->template = LockResource( ofnW
->hInstance
)))
3514 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3518 else if (ofnW
->Flags
& OFN_ENABLETEMPLATE
)
3522 hResInfo
= FindResourceA(priv
->ofnA
->hInstance
,
3523 priv
->ofnA
->lpTemplateName
,
3526 hResInfo
= FindResourceW(ofnW
->hInstance
,
3527 ofnW
->lpTemplateName
,
3531 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
3534 if (!(hDlgTmpl
= LoadResource(ofnW
->hInstance
,
3536 !(lfs
->template = LockResource(hDlgTmpl
)))
3538 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3541 } else { /* get it from internal Wine resource */
3543 if (!(hResInfo
= FindResourceA(COMDLG32_hInstance
,
3544 lfs
->open
? "OPEN_FILE":"SAVE_FILE", (LPSTR
)RT_DIALOG
)))
3546 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
3549 if (!(hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
)) ||
3550 !(lfs
->template = LockResource( hDlgTmpl
)))
3552 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3560 /************************************************************************
3561 * FD32_Init [internal]
3562 * called from the common 16/32 code to initialize 32 bit data
3564 static BOOL CALLBACK
FD32_Init(LPARAM lParam
, PFD31_DATA lfs
, DWORD data
)
3566 BOOL IsUnicode
= (BOOL
) data
;
3569 priv
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FD32_PRIVATE
));
3570 lfs
->private1632
= priv
;
3571 if (NULL
== lfs
->private1632
) return FALSE
;
3574 lfs
->ofnW
= (LPOPENFILENAMEW
) lParam
;
3575 if (lfs
->ofnW
->Flags
& OFN_ENABLEHOOK
)
3576 if (lfs
->ofnW
->lpfnHook
)
3581 priv
->ofnA
= (LPOPENFILENAMEA
) lParam
;
3582 if (priv
->ofnA
->Flags
& OFN_ENABLEHOOK
)
3583 if (priv
->ofnA
->lpfnHook
)
3585 lfs
->ofnW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*lfs
->ofnW
));
3586 FD31_MapOfnStructA(priv
->ofnA
, lfs
->ofnW
, lfs
->open
);
3589 if (! FD32_GetTemplate(lfs
)) return FALSE
;
3594 /***********************************************************************
3595 * FD32_CallWindowProc [internal]
3597 * called from the common 16/32 code to call the appropriate hook
3599 static BOOL CALLBACK
FD32_CallWindowProc(PFD31_DATA lfs
, UINT wMsg
, WPARAM wParam
,
3603 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3607 TRACE("Call hookA %p (%p, %04x, %08x, %08lx)\n",
3608 priv
->ofnA
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3609 ret
= priv
->ofnA
->lpfnHook(lfs
->hwnd
, wMsg
, wParam
, lParam
);
3610 TRACE("ret hookA %p (%p, %04x, %08x, %08lx)\n",
3611 priv
->ofnA
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3615 TRACE("Call hookW %p (%p, %04x, %08x, %08lx)\n",
3616 lfs
->ofnW
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3617 ret
= lfs
->ofnW
->lpfnHook(lfs
->hwnd
, wMsg
, wParam
, lParam
);
3618 TRACE("Ret hookW %p (%p, %04x, %08x, %08lx)\n",
3619 lfs
->ofnW
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3623 /***********************************************************************
3624 * FD32_UpdateResult [internal]
3625 * update the real client structures if any
3627 static void CALLBACK
FD32_UpdateResult(PFD31_DATA lfs
)
3629 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3630 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3634 if (ofnW
->nMaxFile
&&
3635 !WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFile
, -1,
3636 priv
->ofnA
->lpstrFile
, ofnW
->nMaxFile
, NULL
, NULL
))
3637 priv
->ofnA
->lpstrFile
[ofnW
->nMaxFile
-1] = 0;
3638 priv
->ofnA
->nFileOffset
= ofnW
->nFileOffset
;
3639 priv
->ofnA
->nFileExtension
= ofnW
->nFileExtension
;
3643 /***********************************************************************
3644 * FD32_UpdateFileTitle [internal]
3645 * update the real client structures if any
3647 static void CALLBACK
FD32_UpdateFileTitle(PFD31_DATA lfs
)
3649 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3650 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3654 if (!WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFileTitle
, -1,
3655 priv
->ofnA
->lpstrFileTitle
, ofnW
->nMaxFileTitle
, NULL
, NULL
))
3656 priv
->ofnA
->lpstrFileTitle
[ofnW
->nMaxFileTitle
-1] = 0;
3661 /***********************************************************************
3662 * FD32_SendLbGetCurSel [internal]
3663 * retrieve selected listbox item
3665 static LRESULT CALLBACK
FD32_SendLbGetCurSel(PFD31_DATA lfs
)
3667 return SendDlgItemMessageW(lfs
->hwnd
, lst1
, LB_GETCURSEL
, 0, 0);
3671 /************************************************************************
3672 * FD32_Destroy [internal]
3673 * called from the common 16/32 code to cleanup 32 bit data
3675 static void CALLBACK
FD32_Destroy(PFD31_DATA lfs
)
3677 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3679 /* if ofnW has been allocated, have to free everything in it */
3680 if (NULL
!= priv
&& NULL
!= priv
->ofnA
)
3682 FD31_FreeOfnW(lfs
->ofnW
);
3683 HeapFree(GetProcessHeap(), 0, lfs
->ofnW
);
3687 static void FD32_SetupCallbacks(PFD31_CALLBACKS callbacks
)
3689 callbacks
->Init
= FD32_Init
;
3690 callbacks
->CWP
= FD32_CallWindowProc
;
3691 callbacks
->UpdateResult
= FD32_UpdateResult
;
3692 callbacks
->UpdateFileTitle
= FD32_UpdateFileTitle
;
3693 callbacks
->SendLbGetCurSel
= FD32_SendLbGetCurSel
;
3694 callbacks
->Destroy
= FD32_Destroy
;
3697 /***********************************************************************
3698 * FD32_WMMeasureItem [internal]
3700 static LONG
FD32_WMMeasureItem(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
3702 LPMEASUREITEMSTRUCT lpmeasure
;
3704 lpmeasure
= (LPMEASUREITEMSTRUCT
)lParam
;
3705 lpmeasure
->itemHeight
= FD31_GetFldrHeight();
3710 /***********************************************************************
3711 * FileOpenDlgProc [internal]
3712 * Used for open and save, in fact.
3714 static INT_PTR CALLBACK
FD32_FileOpenDlgProc(HWND hWnd
, UINT wMsg
,
3715 WPARAM wParam
, LPARAM lParam
)
3717 PFD31_DATA lfs
= (PFD31_DATA
)GetPropA(hWnd
,FD31_OFN_PROP
);
3719 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg
, wParam
, lParam
);
3720 if ((wMsg
!= WM_INITDIALOG
) && lfs
&& lfs
->hook
)
3723 lRet
= (INT_PTR
)FD31_CallWindowProc(lfs
, wMsg
, wParam
, lParam
);
3725 return lRet
; /* else continue message processing */
3730 return FD31_WMInitDialog(hWnd
, wParam
, lParam
);
3732 case WM_MEASUREITEM
:
3733 return FD32_WMMeasureItem(hWnd
, wParam
, lParam
);
3736 return FD31_WMDrawItem(hWnd
, wParam
, lParam
, !lfs
->open
, (DRAWITEMSTRUCT
*)lParam
);
3739 return FD31_WMCommand(hWnd
, lParam
, HIWORD(wParam
), LOWORD(wParam
), lfs
);
3742 SetBkColor((HDC16
)wParam
, 0x00C0C0C0);
3743 switch (HIWORD(lParam
))
3746 SetTextColor((HDC16
)wParam
, 0x00000000);
3748 case CTLCOLOR_STATIC
:
3749 SetTextColor((HDC16
)wParam
, 0x00000000);
3759 /***********************************************************************
3760 * GetFileName31A [internal]
3762 * Creates a win31 style dialog box for the user to select a file to open/save.
3764 static BOOL
GetFileName31A(LPOPENFILENAMEA lpofn
, /* addess of structure with data*/
3765 UINT dlgType
/* type dialogue : open/save */
3771 FD31_CALLBACKS callbacks
;
3773 if (!lpofn
|| !FD31_Init()) return FALSE
;
3775 TRACE("ofn flags %08lx\n", lpofn
->Flags
);
3776 FD32_SetupCallbacks(&callbacks
);
3777 lfs
= FD31_AllocPrivate((LPARAM
) lpofn
, dlgType
, &callbacks
, (DWORD
) FALSE
);
3780 hInst
= (HINSTANCE
)GetWindowLongPtrA( lpofn
->hwndOwner
, GWLP_HINSTANCE
);
3781 bRet
= DialogBoxIndirectParamA( hInst
, lfs
->template, lpofn
->hwndOwner
,
3782 FD32_FileOpenDlgProc
, (LPARAM
)lfs
);
3783 FD31_DestroyPrivate(lfs
);
3786 TRACE("return lpstrFile='%s' !\n", lpofn
->lpstrFile
);
3790 /***********************************************************************
3791 * GetFileName31W [internal]
3793 * Creates a win31 style dialog box for the user to select a file to open/save
3795 static BOOL
GetFileName31W(LPOPENFILENAMEW lpofn
, /* addess of structure with data*/
3796 UINT dlgType
/* type dialogue : open/save */
3802 FD31_CALLBACKS callbacks
;
3804 if (!lpofn
|| !FD31_Init()) return FALSE
;
3806 FD32_SetupCallbacks(&callbacks
);
3807 lfs
= FD31_AllocPrivate((LPARAM
) lpofn
, dlgType
, &callbacks
, (DWORD
) TRUE
);
3810 hInst
= (HINSTANCE
)GetWindowLongPtrW( lpofn
->hwndOwner
, GWLP_HINSTANCE
);
3811 bRet
= DialogBoxIndirectParamW( hInst
, lfs
->template, lpofn
->hwndOwner
,
3812 FD32_FileOpenDlgProc
, (LPARAM
)lfs
);
3813 FD31_DestroyPrivate(lfs
);
3816 TRACE("file %s, file offset %d, ext offset %d\n",
3817 debugstr_w(lpofn
->lpstrFile
), lpofn
->nFileOffset
, lpofn
->nFileExtension
);
3821 /* ------------------ APIs ---------------------- */
3823 /***********************************************************************
3824 * GetOpenFileNameA (COMDLG32.@)
3826 * Creates a dialog box for the user to select a file to open.
3829 * TRUE on success: user enters a valid file
3830 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3833 BOOL WINAPI
GetOpenFileNameA(
3834 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3836 BOOL win16look
= FALSE
;
3838 TRACE("flags %08lx\n", ofn
->Flags
);
3840 /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
3841 if (ofn
->Flags
& OFN_FILEMUSTEXIST
)
3842 ofn
->Flags
|= OFN_PATHMUSTEXIST
;
3844 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3845 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3848 return GetFileName31A(ofn
, OPEN_DIALOG
);
3850 return GetFileDialog95A(ofn
, OPEN_DIALOG
);
3853 /***********************************************************************
3854 * GetOpenFileNameW (COMDLG32.@)
3856 * Creates a dialog box for the user to select a file to open.
3859 * TRUE on success: user enters a valid file
3860 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3863 BOOL WINAPI
GetOpenFileNameW(
3864 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3866 BOOL win16look
= FALSE
;
3868 TRACE("flags %08lx\n", ofn
->Flags
);
3870 /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
3871 if (ofn
->Flags
& OFN_FILEMUSTEXIST
)
3872 ofn
->Flags
|= OFN_PATHMUSTEXIST
;
3874 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3875 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3878 return GetFileName31W(ofn
, OPEN_DIALOG
);
3880 return GetFileDialog95W(ofn
, OPEN_DIALOG
);
3884 /***********************************************************************
3885 * GetSaveFileNameA (COMDLG32.@)
3887 * Creates a dialog box for the user to select a file to save.
3890 * TRUE on success: user enters a valid file
3891 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3894 BOOL WINAPI
GetSaveFileNameA(
3895 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3897 BOOL win16look
= FALSE
;
3899 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3900 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3903 return GetFileName31A(ofn
, SAVE_DIALOG
);
3905 return GetFileDialog95A(ofn
, SAVE_DIALOG
);
3908 /***********************************************************************
3909 * GetSaveFileNameW (COMDLG32.@)
3911 * Creates a dialog box for the user to select a file to save.
3914 * TRUE on success: user enters a valid file
3915 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3918 BOOL WINAPI
GetSaveFileNameW(
3919 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3921 BOOL win16look
= FALSE
;
3923 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3924 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3927 return GetFileName31W(ofn
, SAVE_DIALOG
);
3929 return GetFileDialog95W(ofn
, SAVE_DIALOG
);