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: lpstrCustomFilter not handled
37 * FIXME: if the size of lpstrFile (nMaxFile) is too small the first
38 * two bytes of lpstrFile should contain the needed size
40 * FIXME: algorithm for selecting the initial directory is too simple
42 * FIXME: add to recent docs
44 * FIXME: flags not implemented: OFN_CREATEPROMPT, OFN_DONTADDTORECENT,
45 * OFN_ENABLEINCLUDENOTIFY, OFN_ENABLESIZING,
46 * OFN_NODEREFERENCELINKS, OFN_NOREADONLYRETURN,
47 * OFN_NOTESTFILECREATE, OFN_USEMONIKERS
49 * FIXME: lCustData for lpfnHook (WM_INITDIALOG)
55 #include "wine/port.h"
63 #define NONAMELESSUNION
64 #define NONAMELESSSTRUCT
70 #include "wine/unicode.h"
76 #include "wine/debug.h"
81 #include "filedlgbrowser.h"
84 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
86 #define UNIMPLEMENTED_FLAGS \
87 (OFN_CREATEPROMPT | OFN_DONTADDTORECENT |\
88 OFN_ENABLEINCLUDENOTIFY | OFN_ENABLESIZING |\
89 OFN_NODEREFERENCELINKS | OFN_NOREADONLYRETURN |\
90 OFN_NOTESTFILECREATE /*| OFN_USEMONIKERS*/)
92 #define IsHooked(fodInfos) \
93 ((fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
94 /***********************************************************************
95 * Data structure and global variables
97 typedef struct SFolder
99 int m_iImageIndex
; /* Index of picture in image list */
101 int m_iIndent
; /* Indentation index */
102 LPITEMIDLIST pidlItem
; /* absolute pidl of the item */
104 } SFOLDER
,*LPSFOLDER
;
106 typedef struct tagLookInInfo
113 /***********************************************************************
114 * Defines and global variables
117 /* Draw item constant */
119 #define XTEXTOFFSET 3
124 /* SearchItem methods */
125 #define SEARCH_PIDL 1
127 #define ITEM_NOTFOUND -1
129 /* Undefined windows message sent by CreateViewObject*/
130 #define WM_GETISHELLBROWSER WM_USER+7
133 * Those macros exist in windowsx.h. However, you can't really use them since
134 * they rely on the UNICODE defines and can't be used inside Wine itself.
137 /* Combo box macros */
138 #define CBAddString(hwnd,str) \
139 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
140 #define CBAddStringW(hwnd,str) \
141 SendMessageW(hwnd,CB_ADDSTRING,0,(LPARAM)str);
143 #define CBInsertString(hwnd,str,pos) \
144 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
146 #define CBDeleteString(hwnd,pos) \
147 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
149 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
150 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
152 #define CBGetItemDataPtr(hwnd,iItemId) \
153 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
155 #define CBGetLBText(hwnd,iItemId,str) \
156 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
158 #define CBGetCurSel(hwnd) \
159 SendMessageA(hwnd,CB_GETCURSEL,0,0);
161 #define CBSetCurSel(hwnd,pos) \
162 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
164 #define CBGetCount(hwnd) \
165 SendMessageA(hwnd,CB_GETCOUNT,0,0);
166 #define CBShowDropDown(hwnd,show) \
167 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
168 #define CBSetItemHeight(hwnd,index,height) \
169 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
171 #define CBSetExtendedUI(hwnd,flag) \
172 SendMessageA(hwnd,CB_SETEXTENDEDUI,(WPARAM)(flag),0)
174 const char *FileOpenDlgInfosStr
= "FileOpenDlgInfos"; /* windows property description string */
175 const char *LookInInfosStr
= "LookInInfos"; /* LOOKIN combo box property */
177 /***********************************************************************
181 /* Internal functions used by the dialog */
182 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
183 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
184 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
);
185 BOOL
FILEDLG95_OnOpen(HWND hwnd
);
186 static LRESULT
FILEDLG95_InitControls(HWND hwnd
);
187 static void FILEDLG95_Clean(HWND hwnd
);
189 /* Functions used by the shell navigation */
190 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
);
191 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
);
192 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
);
193 static void FILEDLG95_SHELL_Clean(HWND hwnd
);
194 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
);
196 /* Functions used by the filetype combo box */
197 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
);
198 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
);
199 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
);
200 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
);
202 /* Functions used by the Look In combo box */
203 static HRESULT
FILEDLG95_LOOKIN_Init(HWND hwndCombo
);
204 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
);
205 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
);
206 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
);
207 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
);
208 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
);
209 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
);
210 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
);
211 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
);
213 /* Miscellaneous tool functions */
214 HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
);
215 HRESULT
GetFileName(HWND hwnd
, LPITEMIDLIST pidl
, LPSTR lpstrFileName
);
216 IShellFolder
* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
);
217 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
);
218 LPITEMIDLIST
GetPidlFromName(IShellFolder
*psf
,LPWSTR lpcstrFileName
);
220 /* Shell memory allocation */
221 static void *MemAlloc(UINT size
);
222 static void MemFree(void *mem
);
224 BOOL WINAPI
GetFileName95(FileOpenDlgInfos
*fodInfos
);
225 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
226 HRESULT
SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
);
227 HRESULT
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
228 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
);
229 static BOOL
BrowseSelectedFolder(HWND hwnd
);
231 /***********************************************************************
234 * Creates an Open common dialog box that lets the user select
235 * the drive, directory, and the name of a file or set of files to open.
237 * IN : The FileOpenDlgInfos structure associated with the dialog
238 * OUT : TRUE on success
239 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
241 BOOL WINAPI
GetFileName95(FileOpenDlgInfos
*fodInfos
)
249 /* test for missing functionality */
250 if (fodInfos
->ofnInfos
->Flags
& UNIMPLEMENTED_FLAGS
)
252 FIXME("Flags 0x%08lx not yet implemented\n",
253 fodInfos
->ofnInfos
->Flags
& UNIMPLEMENTED_FLAGS
);
256 /* Create the dialog from a template */
258 if(!(hRes
= FindResourceA(COMDLG32_hInstance
,MAKEINTRESOURCEA(NEWFILEOPENORD
),(LPSTR
)RT_DIALOG
)))
260 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
263 if (!(hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hRes
)) ||
264 !(template = LockResource( hDlgTmpl
)))
266 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
270 /* old style hook messages */
271 if (IsHooked(fodInfos
))
273 fodInfos
->HookMsg
.fileokstring
= RegisterWindowMessageA(FILEOKSTRINGA
);
274 fodInfos
->HookMsg
.lbselchstring
= RegisterWindowMessageA(LBSELCHSTRINGA
);
275 fodInfos
->HookMsg
.helpmsgstring
= RegisterWindowMessageA(HELPMSGSTRINGA
);
276 fodInfos
->HookMsg
.sharevistring
= RegisterWindowMessageA(SHAREVISTRINGA
);
279 lRes
= DialogBoxIndirectParamA(COMDLG32_hInstance
,
280 (LPDLGTEMPLATEA
) template,
281 fodInfos
->ofnInfos
->hwndOwner
,
285 /* Unable to create the dialog */
292 /***********************************************************************
295 * Call GetFileName95 with this structure and clean the memory.
297 * IN : The OPENFILENAMEA initialisation structure passed to
298 * GetOpenFileNameA win api function (see filedlg.c)
300 BOOL WINAPI
GetFileDialog95A(LPOPENFILENAMEA ofn
,UINT iDlgType
)
303 FileOpenDlgInfos fodInfos
;
304 LPSTR lpstrSavDir
= NULL
;
306 LPWSTR defext
= NULL
;
307 LPWSTR filter
= NULL
;
308 LPWSTR customfilter
= NULL
;
310 /* Initialize FileOpenDlgInfos structure */
311 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
313 /* Pass in the original ofn */
314 fodInfos
.ofnInfos
= ofn
;
316 /* save current directory */
317 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
319 lpstrSavDir
= MemAlloc(MAX_PATH
);
320 GetCurrentDirectoryA(MAX_PATH
, lpstrSavDir
);
323 fodInfos
.unicode
= FALSE
;
325 /* convert all the input strings to unicode */
326 if(ofn
->lpstrInitialDir
)
328 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, NULL
, 0 );
329 fodInfos
.initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
330 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, fodInfos
.initdir
, len
);
333 fodInfos
.initdir
= NULL
;
337 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
338 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFile
, -1, fodInfos
.filename
, ofn
->nMaxFile
);
341 fodInfos
.filename
= NULL
;
345 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, NULL
, 0 );
346 defext
= MemAlloc((len
+1)*sizeof(WCHAR
));
347 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, defext
, len
);
349 fodInfos
.defext
= defext
;
353 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, NULL
, 0 );
354 title
= MemAlloc((len
+1)*sizeof(WCHAR
));
355 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, title
, len
);
357 fodInfos
.title
= title
;
359 if (ofn
->lpstrFilter
)
364 /* filter is a list... title\0ext\0......\0\0 */
365 s
= ofn
->lpstrFilter
;
366 while (*s
) s
= s
+strlen(s
)+1;
368 n
= s
- ofn
->lpstrFilter
;
369 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, NULL
, 0 );
370 filter
= MemAlloc(len
*sizeof(WCHAR
));
371 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, filter
, len
);
373 fodInfos
.filter
= filter
;
375 /* convert lpstrCustomFilter */
376 if (ofn
->lpstrCustomFilter
)
381 /* filter is a list... title\0ext\0......\0\0 */
382 s
= ofn
->lpstrCustomFilter
;
383 while (*s
) s
= s
+strlen(s
)+1;
385 n
= s
- ofn
->lpstrCustomFilter
;
386 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, NULL
, 0 );
387 customfilter
= MemAlloc(len
*sizeof(WCHAR
));
388 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, customfilter
, len
);
390 fodInfos
.customfilter
= customfilter
;
392 /* Initialize the dialog property */
393 fodInfos
.DlgInfos
.dwDlgProp
= 0;
394 fodInfos
.DlgInfos
.hwndCustomDlg
= NULL
;
399 ret
= GetFileName95(&fodInfos
);
402 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
403 ret
= GetFileName95(&fodInfos
);
411 SetCurrentDirectoryA(lpstrSavDir
);
412 MemFree(lpstrSavDir
);
422 MemFree(customfilter
);
424 MemFree(fodInfos
.initdir
);
426 if(fodInfos
.filename
)
427 MemFree(fodInfos
.filename
);
429 TRACE("selected file: %s\n",ofn
->lpstrFile
);
434 /***********************************************************************
437 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
438 * Call GetFileName95 with this structure and clean the memory.
440 * FIXME: lpstrCustomFilter has to be converted back
443 BOOL WINAPI
GetFileDialog95W(LPOPENFILENAMEW ofn
,UINT iDlgType
)
446 FileOpenDlgInfos fodInfos
;
447 LPSTR lpstrSavDir
= NULL
;
449 /* Initialize FileOpenDlgInfos structure */
450 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
452 /* Pass in the original ofn */
453 fodInfos
.ofnInfos
= (LPOPENFILENAMEA
) ofn
;
455 fodInfos
.title
= ofn
->lpstrTitle
;
456 fodInfos
.defext
= ofn
->lpstrDefExt
;
457 fodInfos
.filter
= ofn
->lpstrFilter
;
458 fodInfos
.customfilter
= ofn
->lpstrCustomFilter
;
460 /* convert string arguments, save others */
463 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
464 strncpyW(fodInfos
.filename
,ofn
->lpstrFile
,ofn
->nMaxFile
);
467 fodInfos
.filename
= NULL
;
469 if(ofn
->lpstrInitialDir
)
471 DWORD len
= strlenW(ofn
->lpstrInitialDir
);
472 fodInfos
.initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
473 strcpyW(fodInfos
.initdir
,ofn
->lpstrInitialDir
);
476 fodInfos
.initdir
= NULL
;
478 /* save current directory */
479 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
481 lpstrSavDir
= MemAlloc(MAX_PATH
);
482 GetCurrentDirectoryA(MAX_PATH
, lpstrSavDir
);
485 fodInfos
.unicode
= TRUE
;
490 ret
= GetFileName95(&fodInfos
);
493 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
494 ret
= GetFileName95(&fodInfos
);
502 SetCurrentDirectoryA(lpstrSavDir
);
503 MemFree(lpstrSavDir
);
506 /* restore saved IN arguments and convert OUT arguments back */
507 MemFree(fodInfos
.filename
);
508 MemFree(fodInfos
.initdir
);
512 /***********************************************************************
513 * ArrangeCtrlPositions [internal]
515 * NOTE: Do not change anything here without a lot of testing.
517 static void ArrangeCtrlPositions(HWND hwndChildDlg
, HWND hwndParentDlg
, BOOL hide_help
)
519 HWND hwndChild
, hwndStc32
;
520 RECT rectParent
, rectChild
, rectStc32
;
523 /* Take into account if open as read only checkbox and help button
528 RECT rectHelp
, rectCancel
;
529 GetWindowRect(GetDlgItem(hwndParentDlg
, pshHelp
), &rectHelp
);
530 GetWindowRect(GetDlgItem(hwndParentDlg
, IDCANCEL
), &rectCancel
);
531 /* subtract the height of the help button plus the space between
532 * the help button and the cancel button to the height of the dialog
534 help_fixup
= rectHelp
.bottom
- rectCancel
.bottom
;
538 There are two possibilities to add components to the default file dialog box.
540 By default, all the new components are added below the standard dialog box (the else case).
542 However, if there is a static text component with the stc32 id, a special case happens.
543 The x and y coordinates of stc32 indicate the top left corner where to place the standard file dialog box
544 in the window and the cx and cy indicate how to size the window.
545 Moreover, if the new component's coordinates are on the left of the stc32 , it is placed on the left
546 of the standard file dialog box. If they are above the stc32 component, it is placed above and so on....
550 GetClientRect(hwndParentDlg
, &rectParent
);
552 /* when arranging controls we have to use fixed parent size */
553 rectParent
.bottom
-= help_fixup
;
555 hwndStc32
= GetDlgItem(hwndChildDlg
, stc32
);
558 GetWindowRect(hwndStc32
, &rectStc32
);
559 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectStc32
, 2);
561 /* set the size of the stc32 control according to the size of
562 * client area of the parent dialog
564 SetWindowPos(hwndStc32
, 0,
566 rectParent
.right
, rectParent
.bottom
,
567 SWP_NOMOVE
| SWP_NOZORDER
);
570 SetRectEmpty(&rectStc32
);
572 /* this part moves controls of the child dialog */
573 hwndChild
= GetWindow(hwndChildDlg
, GW_CHILD
);
576 if (hwndChild
!= hwndStc32
)
578 GetWindowRect(hwndChild
, &rectChild
);
579 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectChild
, 2);
581 /* move only if stc32 exist */
582 if (hwndStc32
&& rectChild
.left
> rectStc32
.right
)
584 /* move to the right of visible controls of the parent dialog */
585 rectChild
.left
+= rectParent
.right
;
586 rectChild
.left
-= rectStc32
.right
;
588 /* move even if stc32 doesn't exist */
589 if (rectChild
.top
> rectStc32
.bottom
)
591 /* move below visible controls of the parent dialog */
592 rectChild
.top
+= rectParent
.bottom
;
593 rectChild
.top
-= rectStc32
.bottom
- rectStc32
.top
;
596 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
597 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
599 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
602 /* this part moves controls of the parent dialog */
603 hwndChild
= GetWindow(hwndParentDlg
, GW_CHILD
);
606 if (hwndChild
!= hwndChildDlg
)
608 GetWindowRect(hwndChild
, &rectChild
);
609 MapWindowPoints(0, hwndParentDlg
, (LPPOINT
)&rectChild
, 2);
611 /* left,top of stc32 marks the position of controls
612 * from the parent dialog
614 rectChild
.left
+= rectStc32
.left
;
615 rectChild
.top
+= rectStc32
.top
;
617 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
618 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
620 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
623 /* calculate the size of the resulting dialog */
625 /* here we have to use original parent size */
626 GetClientRect(hwndParentDlg
, &rectParent
);
627 GetClientRect(hwndChildDlg
, &rectChild
);
631 if (rectParent
.right
> rectChild
.right
)
633 rectParent
.right
+= rectChild
.right
;
634 rectParent
.right
-= rectStc32
.right
- rectStc32
.left
;
638 rectParent
.right
= rectChild
.right
;
641 if (rectParent
.bottom
> rectChild
.bottom
)
643 rectParent
.bottom
+= rectChild
.bottom
;
644 rectParent
.bottom
-= rectStc32
.bottom
- rectStc32
.top
;
648 rectParent
.bottom
= rectChild
.bottom
;
653 rectParent
.bottom
+= rectChild
.bottom
;
656 /* finally use fixed parent size */
657 rectParent
.bottom
-= help_fixup
;
659 /* save the size of the parent's client area */
660 rectChild
.right
= rectParent
.right
;
661 rectChild
.bottom
= rectParent
.bottom
;
663 /* set the size of the parent dialog */
664 AdjustWindowRectEx(&rectParent
, GetWindowLongW(hwndParentDlg
, GWL_STYLE
),
665 FALSE
, GetWindowLongW(hwndParentDlg
, GWL_EXSTYLE
));
666 SetWindowPos(hwndParentDlg
, 0,
668 rectParent
.right
- rectParent
.left
,
669 rectParent
.bottom
- rectParent
.top
,
670 SWP_NOMOVE
| SWP_NOZORDER
);
672 /* set the size of the child dialog */
673 SetWindowPos(hwndChildDlg
, HWND_BOTTOM
,
674 0, 0, rectChild
.right
, rectChild
.bottom
, SWP_NOACTIVATE
);
677 INT_PTR CALLBACK
FileOpenDlgProcUserTemplate(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
686 HWND
CreateTemplateDialog(FileOpenDlgInfos
*fodInfos
, HWND hwnd
)
696 * If OFN_ENABLETEMPLATEHANDLE is specified, the OPENFILENAME
697 * structure's hInstance parameter is not a HINSTANCE, but
698 * instead a pointer to a template resource to use.
700 if (fodInfos
->ofnInfos
->Flags
& (OFN_ENABLETEMPLATE
| OFN_ENABLETEMPLATEHANDLE
))
703 if (fodInfos
->ofnInfos
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
706 if( !(template = LockResource( fodInfos
->ofnInfos
->hInstance
)))
708 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
714 hinst
= fodInfos
->ofnInfos
->hInstance
;
715 if(fodInfos
->unicode
)
717 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
718 hRes
= FindResourceW( hinst
, ofn
->lpTemplateName
, (LPWSTR
)RT_DIALOG
);
722 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
723 hRes
= FindResourceA( hinst
, ofn
->lpTemplateName
, (LPSTR
)RT_DIALOG
);
727 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
730 if (!(hDlgTmpl
= LoadResource( hinst
, hRes
)) ||
731 !(template = LockResource( hDlgTmpl
)))
733 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
737 hChildDlg
= CreateDialogIndirectParamA(COMDLG32_hInstance
, template, hwnd
,
738 IsHooked(fodInfos
) ? (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
: FileOpenDlgProcUserTemplate
,
739 (LPARAM
)fodInfos
->ofnInfos
);
742 ShowWindow(hChildDlg
,SW_SHOW
);
746 else if( IsHooked(fodInfos
))
751 WORD menu
,class,title
;
753 GetClientRect(hwnd
,&rectHwnd
);
754 temp
.tmplate
.style
= WS_CHILD
| WS_CLIPSIBLINGS
| WS_VISIBLE
| DS_CONTROL
| DS_3DLOOK
;
755 temp
.tmplate
.dwExtendedStyle
= 0;
756 temp
.tmplate
.cdit
= 0;
761 temp
.menu
= temp
.class = temp
.title
= 0;
763 hChildDlg
= CreateDialogIndirectParamA(COMDLG32_hInstance
, &temp
.tmplate
,
764 hwnd
, (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
, (LPARAM
)fodInfos
->ofnInfos
);
771 /***********************************************************************
772 * SendCustomDlgNotificationMessage
774 * Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
777 HRESULT
SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
)
779 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwndParentDlg
,FileOpenDlgInfosStr
);
781 TRACE("%p 0x%04x\n",hwndParentDlg
, uCode
);
783 if(!fodInfos
) return 0;
785 if(fodInfos
->unicode
)
786 FIXME("sending OPENFILENAMEA structure. Hook is expecting OPENFILENAMEW!\n");
788 if(fodInfos
->DlgInfos
.hwndCustomDlg
)
792 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
793 ofnNotify
.hdr
.idFrom
=0;
794 ofnNotify
.hdr
.code
= uCode
;
795 ofnNotify
.lpOFN
= fodInfos
->ofnInfos
;
796 ofnNotify
.pszFile
= NULL
;
797 TRACE("CALL NOTIFY for %x\n", uCode
);
798 ret
= SendMessageA(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
799 TRACE("RET NOTIFY\n");
805 HRESULT
FILEDLG95_Handle_GetFilePath(HWND hwnd
, DWORD size
, LPSTR buffer
)
807 UINT sizeUsed
= 0, n
, total
;
808 LPWSTR lpstrFileList
= NULL
;
809 WCHAR lpstrCurrentDir
[MAX_PATH
];
810 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
812 TRACE("CDM_GETFILEPATH:\n");
814 if ( ! (fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
817 /* get path and filenames */
818 SHGetPathFromIDListW(fodInfos
->ShellInfos
.pidlAbsCurrent
,lpstrCurrentDir
);
819 n
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
);
821 TRACE("path >%s< filespec >%s< %d files\n",
822 debugstr_w(lpstrCurrentDir
),debugstr_w(lpstrFileList
),n
);
824 total
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
825 NULL
, 0, NULL
, NULL
);
826 total
+= WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
827 NULL
, 0, NULL
, NULL
);
829 /* Prepend the current path */
830 n
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
831 buffer
, size
, NULL
, NULL
);
835 /* 'n' includes trailing \0 */
837 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
838 &buffer
[n
], size
-n
, NULL
, NULL
);
840 MemFree(lpstrFileList
);
842 TRACE("returned -> %s\n",debugstr_a(buffer
));
847 HRESULT
FILEDLG95_Handle_GetFileSpec(HWND hwnd
, DWORD size
, LPSTR buffer
)
850 LPWSTR lpstrFileList
= NULL
;
852 TRACE("CDM_GETSPEC:\n");
854 FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
);
855 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
, buffer
, size
, NULL
, NULL
);
856 MemFree(lpstrFileList
);
861 /***********************************************************************
862 * FILEDLG95_HandleCustomDialogMessages
864 * Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
866 HRESULT
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
868 char lpstrPath
[MAX_PATH
];
869 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
870 if(!fodInfos
) return -1;
874 case CDM_GETFILEPATH
:
875 return FILEDLG95_Handle_GetFilePath(hwnd
, (UINT
)wParam
, (LPSTR
)lParam
);
877 case CDM_GETFOLDERPATH
:
878 TRACE("CDM_GETFOLDERPATH:\n");
879 SHGetPathFromIDListA(fodInfos
->ShellInfos
.pidlAbsCurrent
,lpstrPath
);
880 if ((LPSTR
)lParam
!=NULL
)
881 lstrcpynA((LPSTR
)lParam
,lpstrPath
,(int)wParam
);
882 return strlen(lpstrPath
);
885 return FILEDLG95_Handle_GetFileSpec(hwnd
, (UINT
)wParam
, (LPSTR
)lParam
);
887 case CDM_SETCONTROLTEXT
:
888 TRACE("CDM_SETCONTROLTEXT:\n");
890 SetDlgItemTextA( hwnd
, (UINT
) wParam
, (LPSTR
) lParam
);
893 case CDM_HIDECONTROL
:
895 FIXME("CDM_HIDECONTROL,CDM_SETCONTROLTEXT,CDM_SETDEFEXT not implemented\n");
901 /***********************************************************************
904 * File open dialog procedure
906 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
909 TRACE("0x%04x 0x%04x\n", hwnd
, uMsg
);
916 FileOpenDlgInfos
* fodInfos
= (FileOpenDlgInfos
*)lParam
;
918 /* Adds the FileOpenDlgInfos in the property list of the dialog
919 so it will be easily accessible through a GetPropA(...) */
920 SetPropA(hwnd
, FileOpenDlgInfosStr
, (HANDLE
) fodInfos
);
922 fodInfos
->DlgInfos
.hwndCustomDlg
=
923 CreateTemplateDialog((FileOpenDlgInfos
*)lParam
, hwnd
);
925 FILEDLG95_InitControls(hwnd
);
927 if (fodInfos
->DlgInfos
.hwndCustomDlg
)
928 ArrangeCtrlPositions(fodInfos
->DlgInfos
.hwndCustomDlg
, hwnd
,
929 (fodInfos
->ofnInfos
->Flags
& (OFN_HIDEREADONLY
| OFN_SHOWHELP
)) == OFN_HIDEREADONLY
);
931 FILEDLG95_FillControls(hwnd
, wParam
, lParam
);
933 SendCustomDlgNotificationMessage(hwnd
,CDN_INITDONE
);
934 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
935 SendCustomDlgNotificationMessage(hwnd
,CDN_SELCHANGE
);
939 return FILEDLG95_OnWMCommand(hwnd
, wParam
, lParam
);
942 switch(((LPDRAWITEMSTRUCT
)lParam
)->CtlID
)
945 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT
) lParam
);
951 case WM_GETISHELLBROWSER
:
952 return FILEDLG95_OnWMGetIShellBrowser(hwnd
);
955 RemovePropA(hwnd
, FileOpenDlgInfosStr
);
960 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
963 /* set up the button tooltips strings */
964 if(TTN_GETDISPINFOA
== lpnmh
->code
)
966 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
967 switch(lpnmh
->idFrom
)
969 /* Up folder button */
970 case FCIDM_TB_UPFOLDER
:
971 stringId
= IDS_UPFOLDER
;
973 /* New folder button */
974 case FCIDM_TB_NEWFOLDER
:
975 stringId
= IDS_NEWFOLDER
;
977 /* List option button */
978 case FCIDM_TB_SMALLICON
:
979 stringId
= IDS_LISTVIEW
;
981 /* Details option button */
982 case FCIDM_TB_REPORTVIEW
:
983 stringId
= IDS_REPORTVIEW
;
986 case FCIDM_TB_DESKTOP
:
987 stringId
= IDS_TODESKTOP
;
992 lpdi
->hinst
= COMDLG32_hInstance
;
993 lpdi
->lpszText
= (LPSTR
) stringId
;
998 if(uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
999 return FILEDLG95_HandleCustomDialogMessages(hwnd
, uMsg
, wParam
, lParam
);
1004 /***********************************************************************
1005 * FILEDLG95_InitControls
1007 * WM_INITDIALOG message handler (before hook notification)
1009 static LRESULT
FILEDLG95_InitControls(HWND hwnd
)
1011 int win2000plus
= 0;
1013 int handledPath
= FALSE
;
1014 OSVERSIONINFOA osVi
;
1015 const WCHAR szwSlash
[] = { '\\', 0 };
1016 const WCHAR szwStar
[] = { '*',0 };
1020 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1021 {VIEW_PARENTFOLDER
, FCIDM_TB_UPFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1022 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1023 {VIEW_NEWFOLDER
+1, FCIDM_TB_DESKTOP
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1024 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1025 {VIEW_NEWFOLDER
, FCIDM_TB_NEWFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1026 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1027 {VIEW_LIST
, FCIDM_TB_SMALLICON
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1028 {VIEW_DETAILS
, FCIDM_TB_REPORTVIEW
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1033 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1035 tba
[0].hInst
= HINST_COMMCTRL
;
1036 tba
[0].nID
= IDB_VIEW_SMALL_COLOR
;
1037 tba
[1].hInst
= COMDLG32_hInstance
;
1040 TRACE("%p\n", fodInfos
);
1042 /* Get windows version emulating */
1043 osVi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
1044 GetVersionExA(&osVi
);
1045 if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
) {
1046 win98plus
= ((osVi
.dwMajorVersion
> 4) || ((osVi
.dwMajorVersion
== 4) && (osVi
.dwMinorVersion
> 0)));
1047 } else if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1048 win2000plus
= (osVi
.dwMajorVersion
> 4);
1049 if (win2000plus
) win98plus
= TRUE
;
1051 TRACE("Running on 2000+ %d, 98+ %d\n", win2000plus
, win98plus
);
1053 /* Get the hwnd of the controls */
1054 fodInfos
->DlgInfos
.hwndFileName
= GetDlgItem(hwnd
,IDC_FILENAME
);
1055 fodInfos
->DlgInfos
.hwndFileTypeCB
= GetDlgItem(hwnd
,IDC_FILETYPE
);
1056 fodInfos
->DlgInfos
.hwndLookInCB
= GetDlgItem(hwnd
,IDC_LOOKIN
);
1058 GetWindowRect( fodInfos
->DlgInfos
.hwndLookInCB
,&rectlook
);
1059 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectlook
,2);
1061 /* construct the toolbar */
1062 GetWindowRect(GetDlgItem(hwnd
,IDC_TOOLBARSTATIC
),&rectTB
);
1063 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectTB
,2);
1065 rectTB
.right
= rectlook
.right
+ rectTB
.right
- rectTB
.left
;
1066 rectTB
.bottom
= rectlook
.top
- 1 + rectTB
.bottom
- rectTB
.top
;
1067 rectTB
.left
= rectlook
.right
;
1068 rectTB
.top
= rectlook
.top
-1;
1070 fodInfos
->DlgInfos
.hwndTB
= CreateWindowExA(0, TOOLBARCLASSNAMEA
, NULL
,
1071 WS_CHILD
| WS_GROUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NORESIZE
,
1072 rectTB
.left
, rectTB
.top
,
1073 rectTB
.right
- rectTB
.left
, rectTB
.bottom
- rectTB
.top
,
1074 hwnd
, (HMENU
)IDC_TOOLBAR
, COMDLG32_hInstance
, NULL
);
1076 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_BUTTONSTRUCTSIZE
, (WPARAM
) sizeof(TBBUTTON
), 0);
1078 /* FIXME: use TB_LOADIMAGES when implemented */
1079 /* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1080 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 12, (LPARAM
) &tba
[0]);
1081 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 1, (LPARAM
) &tba
[1]);
1083 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBUTTONSA
, (WPARAM
) 9,(LPARAM
) &tbb
);
1084 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_AUTOSIZE
, 0, 0);
1086 /* Set the window text with the text specified in the OPENFILENAME structure */
1089 SetWindowTextW(hwnd
,fodInfos
->title
);
1091 else if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1093 SetWindowTextA(hwnd
,"Save");
1096 /* Initialise the file name edit control */
1097 handledPath
= FALSE
;
1098 TRACE("Before manipilation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1100 if(fodInfos
->filename
)
1102 /* 1. If win2000 or higher and filename contains a path, use it
1103 in preference over the lpstrInitialDir */
1104 if (win2000plus
&& *fodInfos
->filename
&& strpbrkW(fodInfos
->filename
, szwSlash
)) {
1105 WCHAR tmpBuf
[MAX_PATH
];
1109 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
, tmpBuf
, &nameBit
);
1112 /* nameBit is always shorter than the original filename */
1113 strcpyW(fodInfos
->filename
,nameBit
);
1116 if (fodInfos
->initdir
== NULL
)
1117 MemFree(fodInfos
->initdir
);
1118 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf
) + 1)*sizeof(WCHAR
));
1119 strcpyW(fodInfos
->initdir
, tmpBuf
);
1121 TRACE("Value in Filename includes path, overriding InitialDir: %s, %s\n",
1122 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1124 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1127 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1131 /* 2. (All platforms) If initdir is not null, then use it */
1132 if ((handledPath
== FALSE
) && (fodInfos
->initdir
!=NULL
) &&
1133 (*fodInfos
->initdir
!=0x00))
1135 /* Work out the proper path as supplied one might be relative */
1136 /* (Here because supplying '.' as dir browses to My Computer) */
1137 if (handledPath
==FALSE
) {
1138 WCHAR tmpBuf
[MAX_PATH
];
1139 WCHAR tmpBuf2
[MAX_PATH
];
1143 strcpyW(tmpBuf
, fodInfos
->initdir
);
1144 if( PathFileExistsW(tmpBuf
) ) {
1145 /* initdir does not have to be a directory. If a file is
1146 * specified, the dir part is taken */
1147 if( PathIsDirectoryW(tmpBuf
)) {
1148 if (tmpBuf
[strlenW(tmpBuf
)-1] != '\\') {
1149 strcatW(tmpBuf
, szwSlash
);
1151 strcatW(tmpBuf
, szwStar
);
1153 result
= GetFullPathNameW(tmpBuf
, MAX_PATH
, tmpBuf2
, &nameBit
);
1156 if (fodInfos
->initdir
)
1157 MemFree(fodInfos
->initdir
);
1158 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf2
) + 1)*sizeof(WCHAR
));
1159 strcpyW(fodInfos
->initdir
, tmpBuf2
);
1161 TRACE("Value in InitDir changed to %s\n", debugstr_w(fodInfos
->initdir
));
1164 else if (fodInfos
->initdir
)
1166 MemFree(fodInfos
->initdir
);
1167 fodInfos
->initdir
= NULL
;
1168 TRACE("Value in InitDir is not an existing path, changed to (nil)\n");
1173 if ((handledPath
== FALSE
) && ((fodInfos
->initdir
==NULL
) ||
1174 (*fodInfos
->initdir
==0x00)))
1176 /* 3. All except w2k+: if filename contains a path use it */
1177 if (!win2000plus
&& fodInfos
->filename
&&
1178 *fodInfos
->filename
&&
1179 strpbrkW(fodInfos
->filename
, szwSlash
)) {
1180 WCHAR tmpBuf
[MAX_PATH
];
1184 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
,
1189 /* nameBit is always shorter than the original filename */
1190 strcpyW(fodInfos
->filename
, nameBit
);
1193 len
= strlenW(tmpBuf
);
1194 if(fodInfos
->initdir
)
1195 MemFree(fodInfos
->initdir
);
1196 fodInfos
->initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
1197 strcpyW(fodInfos
->initdir
, tmpBuf
);
1200 TRACE("Value in Filename includes path, overriding initdir: %s, %s\n",
1201 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1203 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1206 /* 4. win98+ and win2000+ if any files of specified filter types in
1207 current directory, use it */
1208 if ( win98plus
&& handledPath
== FALSE
&&
1209 fodInfos
->filter
&& *fodInfos
->filter
) {
1211 BOOL searchMore
= TRUE
;
1212 LPCWSTR lpstrPos
= fodInfos
->filter
;
1213 WIN32_FIND_DATAW FindFileData
;
1218 /* filter is a list... title\0ext\0......\0\0 */
1220 /* Skip the title */
1221 if(! *lpstrPos
) break; /* end */
1222 lpstrPos
+= strlenW(lpstrPos
) + 1;
1224 /* See if any files exist in the current dir with this extension */
1225 if(! *lpstrPos
) break; /* end */
1227 hFind
= FindFirstFileW(lpstrPos
, &FindFileData
);
1229 if (hFind
== INVALID_HANDLE_VALUE
) {
1230 /* None found - continue search */
1231 lpstrPos
+= strlenW(lpstrPos
) + 1;
1236 if(fodInfos
->initdir
)
1237 MemFree(fodInfos
->initdir
);
1238 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1239 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1242 TRACE("No initial dir specified, but files of type %s found in current, so using it\n",
1243 debugstr_w(lpstrPos
));
1249 /* 5. Win2000+: FIXME: Next, Recently used? Not sure how windows does this */
1251 /* 6. Win98+ and 2000+: Use personal files dir, others use current dir */
1252 if (handledPath
== FALSE
&& (win2000plus
|| win98plus
)) {
1253 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1255 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_PERSONAL
, 0, 0, fodInfos
->initdir
)))
1257 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_DESKTOPDIRECTORY
|CSIDL_FLAG_CREATE
, 0, 0, fodInfos
->initdir
)))
1260 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1261 TRACE("No personal or desktop dir, using cwd as failsafe: %s\n", debugstr_w(fodInfos
->initdir
));
1263 TRACE("No personal dir, using desktop instead: %s\n", debugstr_w(fodInfos
->initdir
));
1266 TRACE("No initial dir specified, using personal files dir of %s\n", debugstr_w(fodInfos
->initdir
));
1269 } else if (handledPath
==FALSE
) {
1270 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1271 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1273 TRACE("No initial dir specified, using current dir of %s\n", debugstr_w(fodInfos
->initdir
));
1276 SetFocus(GetDlgItem(hwnd
, IDC_FILENAME
));
1277 TRACE("After manipulation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1279 /* Must the open as read only check box be checked ?*/
1280 if(fodInfos
->ofnInfos
->Flags
& OFN_READONLY
)
1282 SendDlgItemMessageA(hwnd
,IDC_OPENREADONLY
,BM_SETCHECK
,(WPARAM
)TRUE
,0);
1285 /* Must the open as read only check box be hidden? */
1286 if(fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
)
1288 ShowWindow(GetDlgItem(hwnd
,IDC_OPENREADONLY
),SW_HIDE
);
1289 EnableWindow(GetDlgItem(hwnd
, IDC_OPENREADONLY
), FALSE
);
1292 /* Must the help button be hidden? */
1293 if (!(fodInfos
->ofnInfos
->Flags
& OFN_SHOWHELP
))
1295 ShowWindow(GetDlgItem(hwnd
, pshHelp
), SW_HIDE
);
1296 EnableWindow(GetDlgItem(hwnd
, pshHelp
), FALSE
);
1299 /* Resize the height, if open as read only checkbox ad help button
1300 are hidden and we are not using a custom template nor a customDialog
1302 if ( (fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
) &&
1303 (!(fodInfos
->ofnInfos
->Flags
&
1304 (OFN_SHOWHELP
|OFN_ENABLETEMPLATE
|OFN_ENABLETEMPLATEHANDLE
))) &&
1305 (!fodInfos
->DlgInfos
.hwndCustomDlg
))
1307 RECT rectDlg
, rectHelp
, rectCancel
;
1308 GetWindowRect(hwnd
, &rectDlg
);
1309 GetWindowRect(GetDlgItem(hwnd
, pshHelp
), &rectHelp
);
1310 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rectCancel
);
1311 /* subtract the height of the help button plus the space between
1312 the help button and the cancel button to the height of the dialog */
1313 SetWindowPos(hwnd
, 0, 0, 0, rectDlg
.right
-rectDlg
.left
,
1314 (rectDlg
.bottom
-rectDlg
.top
) - (rectHelp
.bottom
- rectCancel
.bottom
),
1315 SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
);
1317 /* change Open to Save FIXME: use resources */
1318 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1320 SetDlgItemTextA(hwnd
,IDOK
,"&Save");
1321 SetDlgItemTextA(hwnd
,IDC_LOOKINSTATIC
,"Save &in");
1326 /***********************************************************************
1327 * FILEDLG95_FillControls
1329 * WM_INITDIALOG message handler (after hook notification)
1331 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1333 LPITEMIDLIST pidlItemId
= NULL
;
1335 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) lParam
;
1337 TRACE("dir=%s file=%s\n",
1338 debugstr_w(fodInfos
->initdir
), debugstr_w(fodInfos
->filename
));
1340 /* Get the initial directory pidl */
1342 if(!(pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,fodInfos
->initdir
)))
1344 WCHAR path
[MAX_PATH
];
1346 GetCurrentDirectoryW(MAX_PATH
,path
);
1347 pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, path
);
1350 /* Initialise shell objects */
1351 FILEDLG95_SHELL_Init(hwnd
);
1353 /* Initialize the Look In combo box */
1354 FILEDLG95_LOOKIN_Init(fodInfos
->DlgInfos
.hwndLookInCB
);
1356 /* Initialize the filter combo box */
1357 FILEDLG95_FILETYPE_Init(hwnd
);
1359 /* Browse to the initial directory */
1360 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,pidlItemId
, SBSP_ABSOLUTE
);
1362 /* Free pidlItem memory */
1363 COMDLG32_SHFree(pidlItemId
);
1367 /***********************************************************************
1370 * Regroups all the cleaning functions of the filedlg
1372 void FILEDLG95_Clean(HWND hwnd
)
1374 FILEDLG95_FILETYPE_Clean(hwnd
);
1375 FILEDLG95_LOOKIN_Clean(hwnd
);
1376 FILEDLG95_SHELL_Clean(hwnd
);
1378 /***********************************************************************
1379 * FILEDLG95_OnWMCommand
1381 * WM_COMMAND message handler
1383 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1385 WORD wNotifyCode
= HIWORD(wParam
); /* notification code */
1386 WORD wID
= LOWORD(wParam
); /* item, control, or accelerator identifier */
1387 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1393 FILEDLG95_OnOpen(hwnd
);
1397 FILEDLG95_Clean(hwnd
);
1398 EndDialog(hwnd
, FALSE
);
1400 /* Filetype combo box */
1402 FILEDLG95_FILETYPE_OnCommand(hwnd
,wNotifyCode
);
1404 /* LookIn combo box */
1406 FILEDLG95_LOOKIN_OnCommand(hwnd
,wNotifyCode
);
1409 /* --- toolbar --- */
1410 /* Up folder button */
1411 case FCIDM_TB_UPFOLDER
:
1412 FILEDLG95_SHELL_UpFolder(hwnd
);
1414 /* New folder button */
1415 case FCIDM_TB_NEWFOLDER
:
1416 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_NEWFOLDERA
);
1418 /* List option button */
1419 case FCIDM_TB_SMALLICON
:
1420 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWLISTA
);
1422 /* Details option button */
1423 case FCIDM_TB_REPORTVIEW
:
1424 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWDETAILSA
);
1426 /* Details option button */
1427 case FCIDM_TB_DESKTOP
:
1428 FILEDLG95_SHELL_BrowseToDesktop(hwnd
);
1435 /* Do not use the listview selection anymore */
1436 fodInfos
->DlgInfos
.dwDlgProp
&= ~FODPROP_USEVIEW
;
1440 /***********************************************************************
1441 * FILEDLG95_OnWMGetIShellBrowser
1443 * WM_GETISHELLBROWSER message handler
1445 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
)
1448 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1452 SetWindowLongA(hwnd
,DWL_MSGRESULT
,(LONG
)fodInfos
->Shell
.FOIShellBrowser
);
1458 /***********************************************************************
1459 * FILEDLG95_SendFileOK
1461 * Sends the CDN_FILEOK notification if required
1464 * TRUE if the dialog should close
1465 * FALSE if the dialog should not be closed
1467 static BOOL
FILEDLG95_SendFileOK( HWND hwnd
, FileOpenDlgInfos
*fodInfos
)
1469 /* ask the hook if we can close */
1470 if(IsHooked(fodInfos
))
1473 /* First send CDN_FILEOK as MSDN doc says */
1474 SendCustomDlgNotificationMessage(hwnd
,CDN_FILEOK
);
1475 if (GetWindowLongW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWL_MSGRESULT
))
1477 TRACE("canceled\n");
1481 /* fodInfos->ofnInfos points to an ASCII or UNICODE structure as appropriate */
1482 SendMessageW(fodInfos
->DlgInfos
.hwndCustomDlg
,
1483 fodInfos
->HookMsg
.fileokstring
, 0, (LPARAM
)fodInfos
->ofnInfos
);
1484 if (GetWindowLongW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWL_MSGRESULT
))
1486 TRACE("canceled\n");
1493 /***********************************************************************
1494 * FILEDLG95_OnOpenMultipleFiles
1496 * Handles the opening of multiple files.
1499 * check destination buffer size
1501 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
)
1503 WCHAR lpstrPathSpec
[MAX_PATH
] = {0};
1504 UINT nCount
, nSizePath
;
1505 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1509 if(fodInfos
->unicode
)
1511 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
1512 ofn
->lpstrFile
[0] = '\0';
1516 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
1517 ofn
->lpstrFile
[0] = '\0';
1520 SHGetPathFromIDListW( fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathSpec
);
1522 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1523 ( fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1524 ! ( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1526 LPWSTR lpstrTemp
= lpstrFileList
;
1528 for ( nCount
= 0; nCount
< nFileCount
; nCount
++ )
1532 pidl
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, lpstrTemp
);
1535 WCHAR lpstrNotFound
[100];
1536 WCHAR lpstrMsg
[100];
1538 WCHAR nl
[] = {'\n',0};
1540 LoadStringW(COMDLG32_hInstance
, IDS_FILENOTFOUND
, lpstrNotFound
, 100);
1541 LoadStringW(COMDLG32_hInstance
, IDS_VERIFYFILE
, lpstrMsg
, 100);
1543 strcpyW(tmp
, lpstrTemp
);
1545 strcatW(tmp
, lpstrNotFound
);
1547 strcatW(tmp
, lpstrMsg
);
1549 MessageBoxW(hwnd
, tmp
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
1553 /* move to the next file in the list of files */
1554 lpstrTemp
+= strlenW(lpstrTemp
) + 1;
1555 COMDLG32_SHFree(pidl
);
1559 nSizePath
= strlenW(lpstrPathSpec
) + 1;
1560 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
1562 /* For "oldstyle" dialog the components have to
1563 be separated by blanks (not '\0'!) and short
1564 filenames have to be used! */
1565 FIXME("Components have to be separated by blanks\n");
1567 if(fodInfos
->unicode
)
1569 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
1570 strcpyW( ofn
->lpstrFile
, lpstrPathSpec
);
1571 memcpy( ofn
->lpstrFile
+ nSizePath
, lpstrFileList
, sizeUsed
*sizeof(WCHAR
) );
1575 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
1577 if (ofn
->lpstrFile
!= NULL
)
1579 WideCharToMultiByte(CP_ACP
, 0, lpstrPathSpec
, -1,
1580 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
1581 if (ofn
->nMaxFile
> nSizePath
)
1583 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
1584 ofn
->lpstrFile
+ nSizePath
,
1585 ofn
->nMaxFile
- nSizePath
, NULL
, NULL
);
1590 fodInfos
->ofnInfos
->nFileOffset
= nSizePath
+ 1;
1591 fodInfos
->ofnInfos
->nFileExtension
= 0;
1593 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
1596 /* clean and exit */
1597 FILEDLG95_Clean(hwnd
);
1598 return EndDialog(hwnd
,TRUE
);
1601 /***********************************************************************
1604 * Ok button WM_COMMAND message handler
1606 * If the function succeeds, the return value is nonzero.
1608 #define ONOPEN_BROWSE 1
1609 #define ONOPEN_OPEN 2
1610 #define ONOPEN_SEARCH 3
1611 static void FILEDLG95_OnOpenMessage(HWND hwnd
, int idCaption
, int idText
)
1613 char strMsgTitle
[MAX_PATH
];
1614 char strMsgText
[MAX_PATH
];
1616 LoadStringA(COMDLG32_hInstance
, idCaption
, strMsgTitle
, sizeof(strMsgTitle
));
1618 strMsgTitle
[0] = '\0';
1619 LoadStringA(COMDLG32_hInstance
, idText
, strMsgText
, sizeof(strMsgText
));
1620 MessageBoxA(hwnd
,strMsgText
, strMsgTitle
, MB_OK
| MB_ICONHAND
);
1623 BOOL
FILEDLG95_OnOpen(HWND hwnd
)
1625 LPWSTR lpstrFileList
;
1626 UINT nFileCount
= 0;
1629 WCHAR lpstrPathAndFile
[MAX_PATH
];
1630 WCHAR lpstrTemp
[MAX_PATH
];
1631 LPSHELLFOLDER lpsf
= NULL
;
1633 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1635 TRACE("hwnd=%p\n", hwnd
);
1637 /* get the files from the edit control */
1638 nFileCount
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
);
1640 /* try if the user selected a folder in the shellview */
1643 BrowseSelectedFolder(hwnd
);
1649 ret
= FILEDLG95_OnOpenMultipleFiles(hwnd
, lpstrFileList
, nFileCount
, sizeUsed
);
1653 TRACE("count=%u len=%u file=%s\n", nFileCount
, sizeUsed
, debugstr_w(lpstrFileList
));
1656 Step 1: Build a complete path name from the current folder and
1657 the filename or path in the edit box.
1659 - the path in the edit box is a root path
1660 (with or without drive letter)
1661 - the edit box contains ".." (or a path with ".." in it)
1664 /* Get the current directory name */
1665 if (!SHGetPathFromIDListW(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathAndFile
))
1667 /* we are in a special folder, default to desktop */
1668 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_DESKTOPDIRECTORY
|CSIDL_FLAG_CREATE
, 0, 0, lpstrPathAndFile
)))
1671 GetCurrentDirectoryW(MAX_PATH
, lpstrPathAndFile
);
1674 PathAddBackslashW(lpstrPathAndFile
);
1676 TRACE("current directory=%s\n", debugstr_w(lpstrPathAndFile
));
1678 /* if the user specifyed a fully qualified path use it */
1679 if(PathIsRelativeW(lpstrFileList
))
1681 strcatW(lpstrPathAndFile
, lpstrFileList
);
1685 /* does the path have a drive letter? */
1686 if (PathGetDriveNumberW(lpstrFileList
) == -1)
1687 strcpyW(lpstrPathAndFile
+2, lpstrFileList
);
1689 strcpyW(lpstrPathAndFile
, lpstrFileList
);
1692 /* resolve "." and ".." */
1693 PathCanonicalizeW(lpstrTemp
, lpstrPathAndFile
);
1694 strcpyW(lpstrPathAndFile
, lpstrTemp
);
1695 TRACE("canon=%s\n", debugstr_w(lpstrPathAndFile
));
1697 MemFree(lpstrFileList
);
1700 Step 2: here we have a cleaned up path
1702 We have to parse the path step by step to see if we have to browse
1703 to a folder if the path points to a directory or the last
1704 valid element is a directory.
1707 lpstrPathAndFile: cleaned up path
1710 nOpenAction
= ONOPEN_BROWSE
;
1712 /* don't apply any checks with OFN_NOVALIDATE */
1714 LPWSTR lpszTemp
, lpszTemp1
;
1715 LPITEMIDLIST pidl
= NULL
;
1716 WCHAR szwInvalid
[] = { '/',':','<','>','|', 0};
1718 /* check for invalid chars */
1719 if((strpbrkW(lpstrPathAndFile
+3, szwInvalid
) != NULL
) && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1721 FILEDLG95_OnOpenMessage(hwnd
, IDS_INVALID_FILENAME_TITLE
, IDS_INVALID_FILENAME
);
1726 if (FAILED (SHGetDesktopFolder(&lpsf
))) return FALSE
;
1728 lpszTemp1
= lpszTemp
= lpstrPathAndFile
;
1731 LPSHELLFOLDER lpsfChild
;
1732 WCHAR lpwstrTemp
[MAX_PATH
];
1733 DWORD dwEaten
, dwAttributes
;
1736 strcpyW(lpwstrTemp
, lpszTemp
);
1737 p
= PathFindNextComponentW(lpwstrTemp
);
1739 if (!p
) break; /* end of path */
1742 lpszTemp
= lpszTemp
+ strlenW(lpwstrTemp
);
1746 WCHAR wszWild
[] = { '*', '?', 0 };
1747 /* if the last element is a wildcard do a search */
1748 if(strpbrkW(lpszTemp1
, wszWild
) != NULL
)
1750 nOpenAction
= ONOPEN_SEARCH
;
1754 lpszTemp1
= lpszTemp
;
1756 TRACE("parse now=%s next=%s sf=%p\n",debugstr_w(lpwstrTemp
), debugstr_w(lpszTemp
), lpsf
);
1758 if(lstrlenW(lpwstrTemp
)==2) PathAddBackslashW(lpwstrTemp
);
1760 dwAttributes
= SFGAO_FOLDER
;
1761 if(SUCCEEDED(IShellFolder_ParseDisplayName(lpsf
, hwnd
, NULL
, lpwstrTemp
, &dwEaten
, &pidl
, &dwAttributes
)))
1763 /* the path component is valid, we have a pidl of the next path component */
1764 TRACE("parse OK attr=0x%08lx pidl=%p\n", dwAttributes
, pidl
);
1765 if(dwAttributes
& SFGAO_FOLDER
)
1767 if(FAILED(IShellFolder_BindToObject(lpsf
, pidl
, 0, &IID_IShellFolder
, (LPVOID
*)&lpsfChild
)))
1769 ERR("bind to failed\n"); /* should not fail */
1772 IShellFolder_Release(lpsf
);
1780 /* end dialog, return value */
1781 nOpenAction
= ONOPEN_OPEN
;
1784 COMDLG32_SHFree(pidl
);
1787 else if (!(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1789 if(*lpszTemp
) /* points to trailing null for last path element */
1791 if(fodInfos
->ofnInfos
->Flags
& OFN_PATHMUSTEXIST
)
1793 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_PATHNOTEXISTING
);
1799 if( (fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1800 !( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1802 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_FILENOTEXISTING
);
1806 /* change to the current folder */
1807 nOpenAction
= ONOPEN_OPEN
;
1812 nOpenAction
= ONOPEN_OPEN
;
1816 if(pidl
) COMDLG32_SHFree(pidl
);
1820 Step 3: here we have a cleaned up and validated path
1823 lpsf: ShellFolder bound to the rightmost valid path component
1824 lpstrPathAndFile: cleaned up path
1825 nOpenAction: action to do
1827 TRACE("end validate sf=%p\n", lpsf
);
1831 case ONOPEN_SEARCH
: /* set the current filter to the file mask and refresh */
1832 TRACE("ONOPEN_SEARCH %s\n", debugstr_w(lpstrPathAndFile
));
1835 LPWSTR lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
1838 /* replace the current filter */
1839 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
1840 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1841 len
= strlenW(lpszTemp
)+1;
1842 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc(len
* sizeof(WCHAR
));
1843 strcpyW( fodInfos
->ShellInfos
.lpstrCurrentFilter
, lpszTemp
);
1845 /* set the filter cb to the extension when possible */
1846 if(-1 < (iPos
= FILEDLG95_FILETYPE_SearchExt(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpszTemp
)))
1847 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, iPos
);
1850 case ONOPEN_BROWSE
: /* browse to the highest folder we could bind to */
1851 TRACE("ONOPEN_BROWSE\n");
1853 IPersistFolder2
* ppf2
;
1854 if(SUCCEEDED(IShellFolder_QueryInterface( lpsf
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
)))
1856 LPITEMIDLIST pidlCurrent
;
1857 IPersistFolder2_GetCurFolder(ppf2
, &pidlCurrent
);
1858 IPersistFolder2_Release(ppf2
);
1859 if( ! COMDLG32_PIDL_ILIsEqual(pidlCurrent
, fodInfos
->ShellInfos
.pidlAbsCurrent
))
1861 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidlCurrent
, SBSP_ABSOLUTE
);
1863 else if( nOpenAction
== ONOPEN_SEARCH
)
1865 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
1867 COMDLG32_SHFree(pidlCurrent
);
1872 case ONOPEN_OPEN
: /* fill in the return struct and close the dialog */
1873 TRACE("ONOPEN_OPEN %s\n", debugstr_w(lpstrPathAndFile
));
1875 /* add default extension */
1876 if (fodInfos
->defext
)
1878 WCHAR
*ext
= PathFindExtensionW(lpstrPathAndFile
);
1882 /* only add "." in case a default extension does exist */
1883 if (*fodInfos
->defext
!= '\0')
1885 const WCHAR szwDot
[] = {'.',0};
1886 int PathLength
= strlenW(lpstrPathAndFile
);
1888 strcatW(lpstrPathAndFile
, szwDot
);
1889 strcatW(lpstrPathAndFile
, fodInfos
->defext
);
1891 /* In Open dialog: if file does not exist try without extension */
1892 if (!(fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1893 && !PathFileExistsW(lpstrPathAndFile
))
1894 lpstrPathAndFile
[PathLength
] = '\0';
1898 /* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
1901 if (!lstrcmpiW(fodInfos
->defext
, ext
))
1902 fodInfos
->ofnInfos
->Flags
&= ~OFN_EXTENSIONDIFFERENT
;
1904 fodInfos
->ofnInfos
->Flags
|= OFN_EXTENSIONDIFFERENT
;
1907 /* In Save dialog: check if the file already exists */
1908 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
1909 && fodInfos
->ofnInfos
->Flags
& OFN_OVERWRITEPROMPT
1910 && PathFileExistsW(lpstrPathAndFile
))
1912 WCHAR lpstrOverwrite
[100];
1915 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, lpstrOverwrite
, 100);
1916 answer
= MessageBoxW(hwnd
, lpstrOverwrite
, fodInfos
->title
,
1917 MB_YESNO
| MB_ICONEXCLAMATION
);
1925 /* Check that the size of the file does not exceed buffer size.
1926 (Allow for extra \0 if OFN_MULTISELECT is set.) */
1927 if(strlenW(lpstrPathAndFile
) < fodInfos
->ofnInfos
->nMaxFile
-
1928 ((fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
) ? 1 : 0))
1932 /* fill destination buffer */
1933 if (fodInfos
->ofnInfos
->lpstrFile
)
1935 if(fodInfos
->unicode
)
1937 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
1939 strncpyW(ofn
->lpstrFile
, lpstrPathAndFile
, ofn
->nMaxFile
);
1940 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
1941 ofn
->lpstrFile
[lstrlenW(ofn
->lpstrFile
) + 1] = '\0';
1945 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
1947 WideCharToMultiByte(CP_ACP
, 0, lpstrPathAndFile
, -1,
1948 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
1949 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
1950 ofn
->lpstrFile
[lstrlenA(ofn
->lpstrFile
) + 1] = '\0';
1954 /* set filename offset */
1955 lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
1956 fodInfos
->ofnInfos
->nFileOffset
= (lpszTemp
- lpstrPathAndFile
);
1958 /* set extension offset */
1959 lpszTemp
= PathFindExtensionW(lpstrPathAndFile
);
1960 fodInfos
->ofnInfos
->nFileExtension
= (*lpszTemp
) ? (lpszTemp
- lpstrPathAndFile
) + 1 : 0;
1962 /* set the lpstrFileTitle */
1963 if(fodInfos
->ofnInfos
->lpstrFileTitle
)
1965 LPWSTR lpstrFileTitle
= PathFindFileNameW(lpstrPathAndFile
);
1966 if(fodInfos
->unicode
)
1968 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
1969 strncpyW(ofn
->lpstrFileTitle
, lpstrFileTitle
, ofn
->nMaxFileTitle
);
1973 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
1974 WideCharToMultiByte(CP_ACP
, 0, lpstrFileTitle
, -1,
1975 ofn
->lpstrFileTitle
, ofn
->nMaxFileTitle
, NULL
, NULL
);
1979 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
1983 FILEDLG95_Clean(hwnd
);
1984 ret
= EndDialog(hwnd
, TRUE
);
1988 /* FIXME set error FNERR_BUFFERTOSMALL */
1989 FILEDLG95_Clean(hwnd
);
1990 ret
= EndDialog(hwnd
, FALSE
);
1998 if(lpsf
) IShellFolder_Release(lpsf
);
2002 /***********************************************************************
2003 * FILEDLG95_SHELL_Init
2005 * Initialisation of the shell objects
2007 static HRESULT
FILEDLG95_SHELL_Init(HWND hwnd
)
2009 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2014 * Initialisation of the FileOpenDialogInfos structure
2020 fodInfos
->ShellInfos
.hwndOwner
= hwnd
;
2022 /* Disable multi-select if flag not set */
2023 if (!(fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
))
2025 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_SINGLESEL
;
2027 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_AUTOARRANGE
| FWF_ALIGNLEFT
;
2028 fodInfos
->ShellInfos
.folderSettings
.ViewMode
= FVM_LIST
;
2030 /* Construct the IShellBrowser interface */
2031 fodInfos
->Shell
.FOIShellBrowser
= IShellBrowserImpl_Construct(hwnd
);
2036 /***********************************************************************
2037 * FILEDLG95_SHELL_ExecuteCommand
2039 * Change the folder option and refresh the view
2040 * If the function succeeds, the return value is nonzero.
2042 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
)
2044 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2047 TRACE("(%p,%p)\n", hwnd
, lpVerb
);
2049 if(SUCCEEDED(IShellView_GetItemObject(fodInfos
->Shell
.FOIShellView
,
2054 CMINVOKECOMMANDINFO ci
;
2055 ZeroMemory(&ci
, sizeof(CMINVOKECOMMANDINFO
));
2056 ci
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
2060 IContextMenu_InvokeCommand(pcm
, &ci
);
2061 IContextMenu_Release(pcm
);
2067 /***********************************************************************
2068 * FILEDLG95_SHELL_UpFolder
2070 * Browse to the specified object
2071 * If the function succeeds, the return value is nonzero.
2073 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
)
2075 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2079 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2088 /***********************************************************************
2089 * FILEDLG95_SHELL_BrowseToDesktop
2091 * Browse to the Desktop
2092 * If the function succeeds, the return value is nonzero.
2094 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
)
2096 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2102 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidl
);
2103 hres
= IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidl
, SBSP_ABSOLUTE
);
2104 COMDLG32_SHFree(pidl
);
2105 return SUCCEEDED(hres
);
2107 /***********************************************************************
2108 * FILEDLG95_SHELL_Clean
2110 * Cleans the memory used by shell objects
2112 static void FILEDLG95_SHELL_Clean(HWND hwnd
)
2114 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2118 COMDLG32_SHFree(fodInfos
->ShellInfos
.pidlAbsCurrent
);
2120 /* clean Shell interfaces */
2121 IShellView_DestroyViewWindow(fodInfos
->Shell
.FOIShellView
);
2122 IShellView_Release(fodInfos
->Shell
.FOIShellView
);
2123 IShellFolder_Release(fodInfos
->Shell
.FOIShellFolder
);
2124 IShellBrowser_Release(fodInfos
->Shell
.FOIShellBrowser
);
2125 if (fodInfos
->Shell
.FOIDataObject
)
2126 IDataObject_Release(fodInfos
->Shell
.FOIDataObject
);
2129 /***********************************************************************
2130 * FILEDLG95_FILETYPE_Init
2132 * Initialisation of the file type combo box
2134 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
)
2136 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2140 if(fodInfos
->filter
)
2142 int nFilters
= 0; /* number of filters */
2144 LPCWSTR lpstrPos
= fodInfos
->filter
;
2148 /* filter is a list... title\0ext\0......\0\0
2149 * Set the combo item text to the title and the item data
2152 LPCWSTR lpstrDisplay
;
2156 if(! *lpstrPos
) break; /* end */
2157 lpstrDisplay
= lpstrPos
;
2158 lpstrPos
+= strlenW(lpstrPos
) + 1;
2160 /* Copy the extensions */
2161 if (! *lpstrPos
) return E_FAIL
; /* malformed filter */
2162 if (!(lpstrExt
= MemAlloc((strlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2163 strcpyW(lpstrExt
,lpstrPos
);
2164 lpstrPos
+= strlenW(lpstrPos
) + 1;
2166 /* Add the item at the end of the combo */
2167 CBAddStringW(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpstrDisplay
);
2168 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
, lpstrExt
);
2172 * Set the current filter to the one specified
2173 * in the initialisation structure
2174 * FIXME: lpstrCustomFilter not handled at all
2177 /* set default filter index */
2178 if(fodInfos
->ofnInfos
->nFilterIndex
== 0 && fodInfos
->customfilter
== NULL
)
2179 fodInfos
->ofnInfos
->nFilterIndex
= 1;
2181 /* First, check to make sure our index isn't out of bounds. */
2182 if ( fodInfos
->ofnInfos
->nFilterIndex
> nFilters
)
2183 fodInfos
->ofnInfos
->nFilterIndex
= nFilters
;
2185 /* Set the current index selection. */
2186 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, fodInfos
->ofnInfos
->nFilterIndex
-1);
2188 /* Get the corresponding text string from the combo box. */
2189 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2190 fodInfos
->ofnInfos
->nFilterIndex
-1);
2192 if ((INT
)lpstrFilter
== CB_ERR
) /* control is empty */
2198 CharLowerW(lpstrFilter
); /* lowercase */
2199 len
= strlenW(lpstrFilter
)+1;
2200 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2201 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2207 /***********************************************************************
2208 * FILEDLG95_FILETYPE_OnCommand
2210 * WM_COMMAND of the file type combo box
2211 * If the function succeeds, the return value is nonzero.
2213 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2215 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2223 /* Get the current item of the filetype combo box */
2224 int iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2226 /* set the current filter index - indexed from 1 */
2227 fodInfos
->ofnInfos
->nFilterIndex
= iItem
+ 1;
2229 /* Set the current filter with the current selection */
2230 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
2231 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2233 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2235 if((int)lpstrFilter
!= CB_ERR
)
2238 CharLowerW(lpstrFilter
); /* lowercase */
2239 len
= strlenW(lpstrFilter
)+1;
2240 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2241 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2242 SendCustomDlgNotificationMessage(hwnd
,CDN_TYPECHANGE
);
2245 /* Refresh the actual view to display the included items*/
2246 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
2251 /***********************************************************************
2252 * FILEDLG95_FILETYPE_SearchExt
2254 * searches for a extension in the filetype box
2256 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
)
2258 int i
, iCount
= CBGetCount(hwnd
);
2260 TRACE("%s\n", debugstr_w(lpstrExt
));
2262 if(iCount
!= CB_ERR
)
2264 for(i
=0;i
<iCount
;i
++)
2266 if(!lstrcmpiW(lpstrExt
,(LPWSTR
)CBGetItemDataPtr(hwnd
,i
)))
2273 /***********************************************************************
2274 * FILEDLG95_FILETYPE_Clean
2276 * Clean the memory used by the filetype combo box
2278 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
)
2280 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2282 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2286 /* Delete each string of the combo and their associated data */
2287 if(iCount
!= CB_ERR
)
2289 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2291 MemFree((LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
));
2292 CBDeleteString(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
2295 /* Current filter */
2296 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
2297 MemFree(fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2301 /***********************************************************************
2302 * FILEDLG95_LOOKIN_Init
2304 * Initialisation of the look in combo box
2306 static HRESULT
FILEDLG95_LOOKIN_Init(HWND hwndCombo
)
2308 IShellFolder
*psfRoot
, *psfDrives
;
2309 IEnumIDList
*lpeRoot
, *lpeDrives
;
2310 LPITEMIDLIST pidlDrives
, pidlTmp
, pidlTmp1
, pidlAbsTmp
;
2312 LookInInfos
*liInfos
= MemAlloc(sizeof(LookInInfos
));
2316 liInfos
->iMaxIndentation
= 0;
2318 SetPropA(hwndCombo
, LookInInfosStr
, (HANDLE
) liInfos
);
2320 /* set item height for both text field and listbox */
2321 CBSetItemHeight(hwndCombo
,-1,GetSystemMetrics(SM_CYSMICON
));
2322 CBSetItemHeight(hwndCombo
,0,GetSystemMetrics(SM_CYSMICON
));
2324 /* Turn on the extended UI for the combo box like Windows does */
2325 CBSetExtendedUI(hwndCombo
, TRUE
);
2327 /* Initialise data of Desktop folder */
2328 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidlTmp
);
2329 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2330 COMDLG32_SHFree(pidlTmp
);
2332 SHGetSpecialFolderLocation(0,CSIDL_DRIVES
,&pidlDrives
);
2334 SHGetDesktopFolder(&psfRoot
);
2338 /* enumerate the contents of the desktop */
2339 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot
, hwndCombo
, SHCONTF_FOLDERS
, &lpeRoot
)))
2341 while (S_OK
== IEnumIDList_Next(lpeRoot
, 1, &pidlTmp
, NULL
))
2343 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2345 /* special handling for CSIDL_DRIVES */
2346 if (COMDLG32_PIDL_ILIsEqual(pidlTmp
, pidlDrives
))
2348 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot
, pidlTmp
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfDrives
)))
2350 /* enumerate the drives */
2351 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives
, hwndCombo
,SHCONTF_FOLDERS
, &lpeDrives
)))
2353 while (S_OK
== IEnumIDList_Next(lpeDrives
, 1, &pidlTmp1
, NULL
))
2355 pidlAbsTmp
= COMDLG32_PIDL_ILCombine(pidlTmp
, pidlTmp1
);
2356 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlAbsTmp
,LISTEND
);
2357 COMDLG32_SHFree(pidlAbsTmp
);
2358 COMDLG32_SHFree(pidlTmp1
);
2360 IEnumIDList_Release(lpeDrives
);
2362 IShellFolder_Release(psfDrives
);
2365 COMDLG32_SHFree(pidlTmp
);
2367 IEnumIDList_Release(lpeRoot
);
2369 IShellFolder_Release(psfRoot
);
2372 COMDLG32_SHFree(pidlDrives
);
2376 /***********************************************************************
2377 * FILEDLG95_LOOKIN_DrawItem
2379 * WM_DRAWITEM message handler
2381 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
)
2383 COLORREF crWin
= GetSysColor(COLOR_WINDOW
);
2384 COLORREF crHighLight
= GetSysColor(COLOR_HIGHLIGHT
);
2385 COLORREF crText
= GetSysColor(COLOR_WINDOWTEXT
);
2389 HIMAGELIST ilItemImage
;
2392 LPSFOLDER tmpFolder
;
2395 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(pDIStruct
->hwndItem
,LookInInfosStr
);
2399 if(pDIStruct
->itemID
== -1)
2402 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(pDIStruct
->hwndItem
,
2403 pDIStruct
->itemID
)))
2407 if(pDIStruct
->itemID
== liInfos
->uSelectedItem
)
2409 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2412 sizeof (SHFILEINFOA
),
2413 SHGFI_PIDL
| SHGFI_SMALLICON
|
2414 SHGFI_OPENICON
| SHGFI_SYSICONINDEX
|
2415 SHGFI_DISPLAYNAME
);
2419 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2422 sizeof (SHFILEINFOA
),
2423 SHGFI_PIDL
| SHGFI_SMALLICON
|
2424 SHGFI_SYSICONINDEX
|
2428 /* Is this item selected ? */
2429 if(pDIStruct
->itemState
& ODS_SELECTED
)
2431 SetTextColor(pDIStruct
->hDC
,(0x00FFFFFF & ~(crText
)));
2432 SetBkColor(pDIStruct
->hDC
,crHighLight
);
2433 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_HIGHLIGHT
));
2437 SetTextColor(pDIStruct
->hDC
,crText
);
2438 SetBkColor(pDIStruct
->hDC
,crWin
);
2439 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_WINDOW
));
2442 /* Do not indent item if drawing in the edit of the combo */
2443 if(pDIStruct
->itemState
& ODS_COMBOBOXEDIT
)
2446 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2449 sizeof (SHFILEINFOA
),
2450 SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_OPENICON
2451 | SHGFI_SYSICONINDEX
| SHGFI_DISPLAYNAME
);
2456 iIndentation
= tmpFolder
->m_iIndent
;
2458 /* Draw text and icon */
2460 /* Initialise the icon display area */
2461 rectIcon
.left
= pDIStruct
->rcItem
.left
+ ICONWIDTH
/2 * iIndentation
;
2462 rectIcon
.top
= pDIStruct
->rcItem
.top
;
2463 rectIcon
.right
= rectIcon
.left
+ ICONWIDTH
;
2464 rectIcon
.bottom
= pDIStruct
->rcItem
.bottom
;
2466 /* Initialise the text display area */
2467 GetTextMetricsA(pDIStruct
->hDC
, &tm
);
2468 rectText
.left
= rectIcon
.right
;
2470 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
- tm
.tmHeight
) / 2;
2471 rectText
.right
= pDIStruct
->rcItem
.right
+ XTEXTOFFSET
;
2473 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
+ tm
.tmHeight
) / 2;
2475 /* Draw the icon from the image list */
2476 ImageList_Draw(ilItemImage
,
2483 /* Draw the associated text */
2484 if(sfi
.szDisplayName
)
2485 TextOutA(pDIStruct
->hDC
,rectText
.left
,rectText
.top
,sfi
.szDisplayName
,strlen(sfi
.szDisplayName
));
2491 /***********************************************************************
2492 * FILEDLG95_LOOKIN_OnCommand
2494 * LookIn combo box WM_COMMAND message handler
2495 * If the function succeeds, the return value is nonzero.
2497 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2499 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2501 TRACE("%p\n", fodInfos
);
2507 LPSFOLDER tmpFolder
;
2510 iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndLookInCB
);
2512 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,
2517 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2518 tmpFolder
->pidlItem
,
2530 /***********************************************************************
2531 * FILEDLG95_LOOKIN_AddItem
2533 * Adds an absolute pidl item to the lookin combo box
2534 * returns the index of the inserted item
2536 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
)
2538 LPITEMIDLIST pidlNext
;
2541 LookInInfos
*liInfos
;
2543 TRACE("%08x\n", iInsertId
);
2548 if(!(liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
)))
2551 tmpFolder
= MemAlloc(sizeof(SFOLDER
));
2552 tmpFolder
->m_iIndent
= 0;
2554 /* Calculate the indentation of the item in the lookin*/
2556 while( (pidlNext
=COMDLG32_PIDL_ILGetNext(pidlNext
)) )
2558 tmpFolder
->m_iIndent
++;
2561 tmpFolder
->pidlItem
= COMDLG32_PIDL_ILClone(pidl
);
2563 if(tmpFolder
->m_iIndent
> liInfos
->iMaxIndentation
)
2564 liInfos
->iMaxIndentation
= tmpFolder
->m_iIndent
;
2566 sfi
.dwAttributes
= SFGAO_FILESYSANCESTOR
| SFGAO_FILESYSTEM
;
2567 SHGetFileInfoA((LPSTR
)pidl
,
2571 SHGFI_DISPLAYNAME
| SHGFI_SYSICONINDEX
2572 | SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_ATTRIBUTES
| SHGFI_ATTR_SPECIFIED
);
2574 TRACE("-- Add %s attr=%08lx\n", sfi
.szDisplayName
, sfi
.dwAttributes
);
2576 if((sfi
.dwAttributes
& SFGAO_FILESYSANCESTOR
) || (sfi
.dwAttributes
& SFGAO_FILESYSTEM
))
2580 TRACE("-- Add %s at %u\n", sfi
.szDisplayName
, tmpFolder
->m_iIndent
);
2582 /* Add the item at the end of the list */
2585 iItemID
= CBAddString(hwnd
,sfi
.szDisplayName
);
2587 /* Insert the item at the iInsertId position*/
2590 iItemID
= CBInsertString(hwnd
,sfi
.szDisplayName
,iInsertId
);
2593 CBSetItemDataPtr(hwnd
,iItemID
,tmpFolder
);
2597 COMDLG32_SHFree( tmpFolder
->pidlItem
);
2598 MemFree( tmpFolder
);
2603 /***********************************************************************
2604 * FILEDLG95_LOOKIN_InsertItemAfterParent
2606 * Insert an item below its parent
2608 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
)
2611 LPITEMIDLIST pidlParent
= GetParentPidl(pidl
);
2616 iParentPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidlParent
,SEARCH_PIDL
);
2620 iParentPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidlParent
);
2623 /* Free pidlParent memory */
2624 COMDLG32_SHFree((LPVOID
)pidlParent
);
2626 return FILEDLG95_LOOKIN_AddItem(hwnd
,pidl
,iParentPos
+ 1);
2629 /***********************************************************************
2630 * FILEDLG95_LOOKIN_SelectItem
2632 * Adds an absolute pidl item to the lookin combo box
2633 * returns the index of the inserted item
2635 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
)
2638 LookInInfos
*liInfos
;
2642 iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidl
,SEARCH_PIDL
);
2644 liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2648 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
) > -1);
2649 iItemPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidl
);
2654 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2655 while(liInfos
->iMaxIndentation
> tmpFolder
->m_iIndent
)
2659 if(-1 == (iRemovedItem
= FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
)))
2661 if(iRemovedItem
< iItemPos
)
2666 CBSetCurSel(hwnd
,iItemPos
);
2667 liInfos
->uSelectedItem
= iItemPos
;
2673 /***********************************************************************
2674 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2676 * Remove the item with an expansion level over iExpansionLevel
2678 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
)
2682 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2686 if(liInfos
->iMaxIndentation
<= 2)
2689 if((iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)liInfos
->iMaxIndentation
,SEARCH_EXP
)) >=0)
2691 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2692 COMDLG32_SHFree(tmpFolder
->pidlItem
);
2694 CBDeleteString(hwnd
,iItemPos
);
2695 liInfos
->iMaxIndentation
--;
2703 /***********************************************************************
2704 * FILEDLG95_LOOKIN_SearchItem
2706 * Search for pidl in the lookin combo box
2707 * returns the index of the found item
2709 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
)
2712 int iCount
= CBGetCount(hwnd
);
2714 TRACE("0x%08x 0x%x\n",searchArg
, iSearchMethod
);
2716 if (iCount
!= CB_ERR
)
2720 LPSFOLDER tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,i
);
2722 if(iSearchMethod
== SEARCH_PIDL
&& COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST
)searchArg
,tmpFolder
->pidlItem
))
2724 if(iSearchMethod
== SEARCH_EXP
&& tmpFolder
->m_iIndent
== (int)searchArg
)
2732 /***********************************************************************
2733 * FILEDLG95_LOOKIN_Clean
2735 * Clean the memory used by the lookin combo box
2737 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
)
2739 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2741 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndLookInCB
);
2745 /* Delete each string of the combo and their associated data */
2746 if (iCount
!= CB_ERR
)
2748 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2750 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
2751 COMDLG32_SHFree(tmpFolder
->pidlItem
);
2753 CBDeleteString(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
2757 /* LookInInfos structure */
2758 RemovePropA(fodInfos
->DlgInfos
.hwndLookInCB
,LookInInfosStr
);
2761 /***********************************************************************
2762 * FILEDLG95_FILENAME_FillFromSelection
2764 * fills the edit box from the cached DataObject
2766 void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd
)
2768 FileOpenDlgInfos
*fodInfos
;
2770 UINT nFiles
= 0, nFileToOpen
, nFileSelected
, nLength
= 0;
2771 char lpstrTemp
[MAX_PATH
];
2772 LPSTR lpstrAllFile
= NULL
, lpstrCurrFile
= NULL
;
2775 fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2777 /* Count how many files we have */
2778 nFileSelected
= GetNumSelected( fodInfos
->Shell
.FOIDataObject
);
2780 /* calculate the string length, count files */
2781 if (nFileSelected
>= 1)
2783 nLength
+= 3; /* first and last quotes, trailing \0 */
2784 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
2786 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
2790 /* get the total length of the selected file names */
2791 lpstrTemp
[0] = '\0';
2792 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
2794 if ( ! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
) ) /* Ignore folders */
2796 nLength
+= strlen( lpstrTemp
) + 3;
2799 COMDLG32_SHFree( pidl
);
2804 /* allocate the buffer */
2805 if (nFiles
<= 1) nLength
= MAX_PATH
;
2806 lpstrAllFile
= (LPSTR
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nLength
);
2807 lpstrAllFile
[0] = '\0';
2809 /* Generate the string for the edit control */
2812 lpstrCurrFile
= lpstrAllFile
;
2813 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
2815 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
2819 /* get the file name */
2820 lpstrTemp
[0] = '\0';
2821 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
2823 if (! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
)) /* Ignore folders */
2827 *lpstrCurrFile
++ = '\"';
2828 strcpy( lpstrCurrFile
, lpstrTemp
);
2829 lpstrCurrFile
+= strlen( lpstrTemp
);
2830 strcpy( lpstrCurrFile
, "\" " );
2835 strcpy( lpstrAllFile
, lpstrTemp
);
2838 COMDLG32_SHFree( (LPVOID
) pidl
);
2841 SetWindowTextA( fodInfos
->DlgInfos
.hwndFileName
, lpstrAllFile
);
2843 /* Select the file name like Windows does */
2844 SendMessageA(fodInfos
->DlgInfos
.hwndFileName
, EM_SETSEL
, (WPARAM
)0, (LPARAM
)-1);
2846 HeapFree(GetProcessHeap(),0, lpstrAllFile
);
2850 /* copied from shell32 to avoid linking to it */
2851 static HRESULT
COMDLG32_StrRetToStrNA (LPVOID dest
, DWORD len
, LPSTRRET src
, LPITEMIDLIST pidl
)
2856 WideCharToMultiByte(CP_ACP
, 0, src
->u
.pOleStr
, -1, (LPSTR
)dest
, len
, NULL
, NULL
);
2857 COMDLG32_SHFree(src
->u
.pOleStr
);
2861 lstrcpynA((LPSTR
)dest
, src
->u
.cStr
, len
);
2865 lstrcpynA((LPSTR
)dest
, ((LPCSTR
)&pidl
->mkid
)+src
->u
.uOffset
, len
);
2869 FIXME("unknown type!\n");
2872 *(LPSTR
)dest
= '\0';
2879 /***********************************************************************
2880 * FILEDLG95_FILENAME_GetFileNames
2882 * copies the filenames to a 0-delimited string list (A\0B\0C\0\0)
2884 int FILEDLG95_FILENAME_GetFileNames (HWND hwnd
, LPWSTR
* lpstrFileList
, UINT
* sizeUsed
)
2886 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2887 UINT nStrCharCount
= 0; /* index in src buffer */
2888 UINT nFileIndex
= 0; /* index in dest buffer */
2889 UINT nFileCount
= 0; /* number of files */
2890 UINT nStrLen
= 0; /* length of string in edit control */
2891 LPWSTR lpstrEdit
; /* buffer for string from edit control */
2895 /* get the filenames from the edit control */
2896 nStrLen
= SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXTLENGTH
, 0, 0);
2897 lpstrEdit
= MemAlloc( (nStrLen
+1)*sizeof(WCHAR
) );
2898 GetDlgItemTextW(hwnd
, IDC_FILENAME
, lpstrEdit
, nStrLen
+1);
2900 TRACE("nStrLen=%u str=%s\n", nStrLen
, debugstr_w(lpstrEdit
));
2902 /* we might get single filename without any '"',
2903 * so we need nStrLen + terminating \0 + end-of-list \0 */
2904 *lpstrFileList
= MemAlloc( (nStrLen
+2)*sizeof(WCHAR
) );
2907 /* build 0-delimited file list from filenames */
2908 while ( nStrCharCount
<= nStrLen
)
2910 if ( lpstrEdit
[nStrCharCount
]=='"' )
2913 while ((lpstrEdit
[nStrCharCount
]!='"') && (nStrCharCount
<= nStrLen
))
2915 (*lpstrFileList
)[nFileIndex
++] = lpstrEdit
[nStrCharCount
];
2919 (*lpstrFileList
)[nFileIndex
++] = '\0';
2926 /* single, unquoted string */
2927 if ((nStrLen
> 0) && (*sizeUsed
== 0) )
2929 strcpyW(*lpstrFileList
, lpstrEdit
);
2930 nFileIndex
= strlenW(lpstrEdit
) + 1;
2931 (*sizeUsed
) = nFileIndex
;
2936 (*lpstrFileList
)[nFileIndex
] = '\0';
2943 #define SETDefFormatEtc(fe,cf,med) \
2945 (fe).cfFormat = cf;\
2946 (fe).dwAspect = DVASPECT_CONTENT; \
2953 * DATAOBJECT Helper functions
2956 /***********************************************************************
2957 * COMCTL32_ReleaseStgMedium
2959 * like ReleaseStgMedium from ole32
2961 static void COMCTL32_ReleaseStgMedium (STGMEDIUM medium
)
2963 if(medium
.pUnkForRelease
)
2965 IUnknown_Release(medium
.pUnkForRelease
);
2969 GlobalUnlock(medium
.u
.hGlobal
);
2970 GlobalFree(medium
.u
.hGlobal
);
2974 /***********************************************************************
2975 * GetPidlFromDataObject
2977 * Return pidl(s) by number from the cached DataObject
2979 * nPidlIndex=0 gets the fully qualified root path
2981 LPITEMIDLIST
GetPidlFromDataObject ( IDataObject
*doSelected
, UINT nPidlIndex
)
2985 FORMATETC formatetc
;
2986 LPITEMIDLIST pidl
= NULL
;
2988 TRACE("sv=%p index=%u\n", doSelected
, nPidlIndex
);
2990 /* Set the FORMATETC structure*/
2991 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
2993 /* Get the pidls from IDataObject */
2994 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
2996 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
2997 if(nPidlIndex
<= cida
->cidl
)
2999 pidl
= COMDLG32_PIDL_ILClone((LPITEMIDLIST
)(&((LPBYTE
)cida
)[cida
->aoffset
[nPidlIndex
]]));
3001 COMCTL32_ReleaseStgMedium(medium
);
3006 /***********************************************************************
3009 * Return the number of selected items in the DataObject.
3012 UINT
GetNumSelected( IDataObject
*doSelected
)
3016 FORMATETC formatetc
;
3018 TRACE("sv=%p\n", doSelected
);
3020 if (!doSelected
) return 0;
3022 /* Set the FORMATETC structure*/
3023 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
3025 /* Get the pidls from IDataObject */
3026 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3028 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3029 retVal
= cida
->cidl
;
3030 COMCTL32_ReleaseStgMedium(medium
);
3040 /***********************************************************************
3043 * Get the pidl's display name (relative to folder) and
3044 * put it in lpstrFileName.
3046 * Return NOERROR on success,
3050 HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
)
3055 TRACE("sf=%p pidl=%p\n", lpsf
, pidl
);
3060 SHGetDesktopFolder(&lpsf
);
3061 hRes
= GetName(lpsf
,pidl
,dwFlags
,lpstrFileName
);
3062 IShellFolder_Release(lpsf
);
3066 /* Get the display name of the pidl relative to the folder */
3067 if (SUCCEEDED(hRes
= IShellFolder_GetDisplayNameOf(lpsf
, pidl
, dwFlags
, &str
)))
3069 return COMDLG32_StrRetToStrNA(lpstrFileName
, MAX_PATH
, &str
, pidl
);
3074 /***********************************************************************
3075 * GetShellFolderFromPidl
3077 * pidlRel is the item pidl relative
3078 * Return the IShellFolder of the absolute pidl
3080 IShellFolder
*GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
)
3082 IShellFolder
*psf
= NULL
,*psfParent
;
3084 TRACE("%p\n", pidlAbs
);
3086 if(SUCCEEDED(SHGetDesktopFolder(&psfParent
)))
3089 if(pidlAbs
&& pidlAbs
->mkid
.cb
)
3091 if(SUCCEEDED(IShellFolder_BindToObject(psfParent
, pidlAbs
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psf
)))
3093 IShellFolder_Release(psfParent
);
3097 /* return the desktop */
3103 /***********************************************************************
3106 * Return the LPITEMIDLIST to the parent of the pidl in the list
3108 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
)
3110 LPITEMIDLIST pidlParent
;
3112 TRACE("%p\n", pidl
);
3114 pidlParent
= COMDLG32_PIDL_ILClone(pidl
);
3115 COMDLG32_PIDL_ILRemoveLastID(pidlParent
);
3120 /***********************************************************************
3123 * returns the pidl of the file name relative to folder
3124 * NULL if an error occurred
3126 LPITEMIDLIST
GetPidlFromName(IShellFolder
*lpsf
,LPWSTR lpcstrFileName
)
3128 LPITEMIDLIST pidl
= NULL
;
3131 TRACE("sf=%p file=%s\n", lpsf
, debugstr_w(lpcstrFileName
));
3133 if(!lpcstrFileName
) return NULL
;
3134 if(!*lpcstrFileName
) return NULL
;
3138 if (SUCCEEDED(SHGetDesktopFolder(&lpsf
))) {
3139 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3140 IShellFolder_Release(lpsf
);
3145 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3152 BOOL
IsPidlFolder (LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
)
3154 ULONG uAttr
= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
;
3157 TRACE("%p, %p\n", psf
, pidl
);
3159 ret
= IShellFolder_GetAttributesOf( psf
, 1, &pidl
, &uAttr
);
3161 TRACE("-- 0x%08lx 0x%08lx\n", uAttr
, ret
);
3162 /* see documentation shell 4.1*/
3163 return uAttr
& (SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
);
3166 /***********************************************************************
3167 * BrowseSelectedFolder
3169 static BOOL
BrowseSelectedFolder(HWND hwnd
)
3171 BOOL bBrowseSelFolder
= FALSE
;
3172 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3176 if (GetNumSelected(fodInfos
->Shell
.FOIDataObject
) == 1)
3178 LPITEMIDLIST pidlSelection
;
3180 /* get the file selected */
3181 pidlSelection
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, 1);
3182 if (IsPidlFolder (fodInfos
->Shell
.FOIShellFolder
, pidlSelection
))
3184 if ( FAILED( IShellBrowser_BrowseObject( fodInfos
->Shell
.FOIShellBrowser
,
3185 pidlSelection
, SBSP_RELATIVE
) ) )
3187 WCHAR notexist
[] = {'P','a','t','h',' ','d','o','e','s',
3188 ' ','n','o','t',' ','e','x','i','s','t',0};
3189 MessageBoxW( hwnd
, notexist
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
3192 bBrowseSelFolder
= TRUE
;
3194 COMDLG32_SHFree( pidlSelection
);
3197 return bBrowseSelFolder
;
3201 * Memory allocation methods */
3202 static void *MemAlloc(UINT size
)
3204 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
3207 static void MemFree(void *mem
)
3211 HeapFree(GetProcessHeap(),0,mem
);
3215 /* ------------------ APIs ---------------------- */
3217 /***********************************************************************
3218 * GetOpenFileNameA (COMDLG32.@)
3220 * Creates a dialog box for the user to select a file to open.
3223 * TRUE on success: user enters a valid file
3224 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3227 BOOL WINAPI
GetOpenFileNameA(
3228 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3230 return GetFileDialog95A(ofn
, OPEN_DIALOG
);
3233 /***********************************************************************
3234 * GetOpenFileNameW (COMDLG32.@)
3236 * Creates a dialog box for the user to select a file to open.
3239 * TRUE on success: user enters a valid file
3240 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3243 BOOL WINAPI
GetOpenFileNameW(
3244 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3246 return GetFileDialog95W(ofn
, OPEN_DIALOG
);
3249 /***********************************************************************
3250 * GetSaveFileNameA (COMDLG32.@)
3252 * Creates a dialog box for the user to select a file to save.
3255 * TRUE on success: user enters a valid file
3256 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3259 BOOL WINAPI
GetSaveFileNameA(
3260 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3262 return GetFileDialog95A(ofn
, SAVE_DIALOG
);
3265 /***********************************************************************
3266 * GetSaveFileNameW (COMDLG32.@)
3268 * Creates a dialog box for the user to select a file to save.
3271 * TRUE on success: user enters a valid file
3272 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3275 BOOL WINAPI
GetSaveFileNameW(
3276 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3278 return GetFileDialog95W(ofn
, SAVE_DIALOG
);