2 * COMMDLG - File Open Dialogs Win95 look and feel
4 * Copyright 1999 Francois Boisvert
5 * Copyright 1999, 2000 Juergen Schmied
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * FIXME: The whole concept of handling unicode is badly broken.
22 * many hook-messages expect a pointer to a
23 * OPENFILENAMEA or W structure. With the current architecture
24 * we would have to convert the beast at every call to a hook.
25 * we have to find a better solution but it would likely cause
26 * a complete rewrite after which we should handle the
27 * OPENFILENAME structure without any converting (jsch).
29 * FIXME: any hook gets a OPENFILENAMEA structure
31 * FIXME: CDN_FILEOK is wrong implemented, other CDN_ messages likely too
33 * FIXME: old style hook messages are not implemented (except FILEOKSTRING)
35 * FIXME: algorithm for selecting the initial directory is too simple
37 * FIXME: add to recent docs
39 * FIXME: flags not implemented: OFN_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
72 #include "filedlg31.h"
76 #include "filedlgbrowser.h"
79 #include "wine/unicode.h"
80 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
84 #define UNIMPLEMENTED_FLAGS \
85 (OFN_DONTADDTORECENT |\
86 OFN_ENABLEINCLUDENOTIFY | OFN_ENABLESIZING |\
87 OFN_NODEREFERENCELINKS | OFN_NOREADONLYRETURN |\
88 OFN_NOTESTFILECREATE /*| OFN_USEMONIKERS*/)
90 #define IsHooked(fodInfos) \
91 ((fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
92 /***********************************************************************
93 * Data structure and global variables
95 typedef struct SFolder
97 int m_iImageIndex
; /* Index of picture in image list */
99 int m_iIndent
; /* Indentation index */
100 LPITEMIDLIST pidlItem
; /* absolute pidl of the item */
102 } SFOLDER
,*LPSFOLDER
;
104 typedef struct tagLookInInfo
110 typedef struct tagFD32_PRIVATE
112 OPENFILENAMEA
*ofnA
; /* original structure if 32bits ansi dialog */
113 } FD32_PRIVATE
, *PFD32_PRIVATE
;
116 /***********************************************************************
117 * Defines and global variables
120 /* Draw item constant */
122 #define XTEXTOFFSET 3
127 /* SearchItem methods */
128 #define SEARCH_PIDL 1
130 #define ITEM_NOTFOUND -1
132 /* Undefined windows message sent by CreateViewObject*/
133 #define WM_GETISHELLBROWSER WM_USER+7
136 * Those macros exist in windowsx.h. However, you can't really use them since
137 * they rely on the UNICODE defines and can't be used inside Wine itself.
140 /* Combo box macros */
141 #define CBAddString(hwnd,str) \
142 SendMessageW(hwnd, CB_ADDSTRING, 0, (LPARAM)(str));
144 #define CBInsertString(hwnd,str,pos) \
145 SendMessageW(hwnd, CB_INSERTSTRING, (WPARAM)(pos), (LPARAM)(str));
147 #define CBDeleteString(hwnd,pos) \
148 SendMessageW(hwnd, CB_DELETESTRING, (WPARAM)(pos), 0);
150 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
151 SendMessageW(hwnd, CB_SETITEMDATA, (WPARAM)(iItemId), (LPARAM)(dataPtr));
153 #define CBGetItemDataPtr(hwnd,iItemId) \
154 SendMessageW(hwnd, CB_GETITEMDATA, (WPARAM)(iItemId), 0)
156 #define CBGetLBText(hwnd,iItemId,str) \
157 SendMessageW(hwnd, CB_GETLBTEXT, (WPARAM)(iItemId), (LPARAM)(str));
159 #define CBGetCurSel(hwnd) \
160 SendMessageW(hwnd, CB_GETCURSEL, 0, 0);
162 #define CBSetCurSel(hwnd,pos) \
163 SendMessageW(hwnd, CB_SETCURSEL, (WPARAM)(pos), 0);
165 #define CBGetCount(hwnd) \
166 SendMessageW(hwnd, CB_GETCOUNT, 0, 0);
167 #define CBShowDropDown(hwnd,show) \
168 SendMessageW(hwnd, CB_SHOWDROPDOWN, (WPARAM)(show), 0);
169 #define CBSetItemHeight(hwnd,index,height) \
170 SendMessageW(hwnd, CB_SETITEMHEIGHT, (WPARAM)(index), (LPARAM)(height));
172 #define CBSetExtendedUI(hwnd,flag) \
173 SendMessageW(hwnd, CB_SETEXTENDEDUI, (WPARAM)(flag), 0)
175 const char FileOpenDlgInfosStr
[] = "FileOpenDlgInfos"; /* windows property description string */
176 static const char LookInInfosStr
[] = "LookInInfos"; /* LOOKIN combo box property */
178 /***********************************************************************
182 /* Internal functions used by the dialog */
183 static LRESULT
FILEDLG95_ResizeControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
184 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
185 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
186 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
);
187 static BOOL
FILEDLG95_OnOpen(HWND hwnd
);
188 static LRESULT
FILEDLG95_InitControls(HWND hwnd
);
189 static void FILEDLG95_Clean(HWND hwnd
);
191 /* Functions used by the shell navigation */
192 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
);
193 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
);
194 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
);
195 static void FILEDLG95_SHELL_Clean(HWND hwnd
);
196 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
);
198 /* Functions used by the EDIT box */
199 static int FILEDLG95_FILENAME_GetFileNames (HWND hwnd
, LPWSTR
* lpstrFileList
, UINT
* sizeUsed
);
201 /* Functions used by the filetype combo box */
202 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
);
203 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
);
204 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
);
205 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
);
207 /* Functions used by the Look In combo box */
208 static void FILEDLG95_LOOKIN_Init(HWND hwndCombo
);
209 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
);
210 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
);
211 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
);
212 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
);
213 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
);
214 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
);
215 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
);
216 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
);
218 /* Miscellaneous tool functions */
219 static HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPWSTR lpstrFileName
);
220 IShellFolder
* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
);
221 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
);
222 static LPITEMIDLIST
GetPidlFromName(IShellFolder
*psf
,LPWSTR lpcstrFileName
);
224 /* Shell memory allocation */
225 static void *MemAlloc(UINT size
);
226 static void MemFree(void *mem
);
228 static INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
229 static INT_PTR
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
230 static BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
);
231 static BOOL
BrowseSelectedFolder(HWND hwnd
);
233 /***********************************************************************
236 * Creates an Open common dialog box that lets the user select
237 * the drive, directory, and the name of a file or set of files to open.
239 * IN : The FileOpenDlgInfos structure associated with the dialog
240 * OUT : TRUE on success
241 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
243 static BOOL WINAPI
GetFileName95(FileOpenDlgInfos
*fodInfos
)
252 /* test for missing functionality */
253 if (fodInfos
->ofnInfos
->Flags
& UNIMPLEMENTED_FLAGS
)
255 FIXME("Flags 0x%08x not yet implemented\n",
256 fodInfos
->ofnInfos
->Flags
& UNIMPLEMENTED_FLAGS
);
259 /* Create the dialog from a template */
261 if(!(hRes
= FindResourceW(COMDLG32_hInstance
,MAKEINTRESOURCEW(NEWFILEOPENORD
),(LPCWSTR
)RT_DIALOG
)))
263 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
266 if (!(hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hRes
)) ||
267 !(template = LockResource( hDlgTmpl
)))
269 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
273 /* old style hook messages */
274 if (IsHooked(fodInfos
))
276 fodInfos
->HookMsg
.fileokstring
= RegisterWindowMessageW(FILEOKSTRINGW
);
277 fodInfos
->HookMsg
.lbselchstring
= RegisterWindowMessageW(LBSELCHSTRINGW
);
278 fodInfos
->HookMsg
.helpmsgstring
= RegisterWindowMessageW(HELPMSGSTRINGW
);
279 fodInfos
->HookMsg
.sharevistring
= RegisterWindowMessageW(SHAREVISTRINGW
);
282 /* Some shell namespace extensions depend on COM being initialized. */
283 hr
= OleInitialize(NULL
);
285 if (fodInfos
->unicode
)
286 lRes
= DialogBoxIndirectParamW(COMDLG32_hInstance
,
288 fodInfos
->ofnInfos
->hwndOwner
,
292 lRes
= DialogBoxIndirectParamA(COMDLG32_hInstance
,
293 (LPCDLGTEMPLATEA
) template,
294 fodInfos
->ofnInfos
->hwndOwner
,
300 /* Unable to create the dialog */
307 /***********************************************************************
310 * Call GetFileName95 with this structure and clean the memory.
312 * IN : The OPENFILENAMEA initialisation structure passed to
313 * GetOpenFileNameA win api function (see filedlg.c)
315 BOOL WINAPI
GetFileDialog95A(LPOPENFILENAMEA ofn
,UINT iDlgType
)
318 FileOpenDlgInfos fodInfos
;
319 LPSTR lpstrSavDir
= NULL
;
321 LPWSTR defext
= NULL
;
322 LPWSTR filter
= NULL
;
323 LPWSTR customfilter
= NULL
;
325 /* Initialize CommDlgExtendedError() */
326 COMDLG32_SetCommDlgExtendedError(0);
328 /* Initialize FileOpenDlgInfos structure */
329 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
331 /* Pass in the original ofn */
332 fodInfos
.ofnInfos
= (LPOPENFILENAMEW
)ofn
;
334 /* save current directory */
335 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
337 lpstrSavDir
= MemAlloc(MAX_PATH
);
338 GetCurrentDirectoryA(MAX_PATH
, lpstrSavDir
);
341 fodInfos
.unicode
= FALSE
;
343 /* convert all the input strings to unicode */
344 if(ofn
->lpstrInitialDir
)
346 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, NULL
, 0 );
347 fodInfos
.initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
348 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, fodInfos
.initdir
, len
);
351 fodInfos
.initdir
= NULL
;
355 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
356 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFile
, -1, fodInfos
.filename
, ofn
->nMaxFile
);
359 fodInfos
.filename
= NULL
;
363 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, NULL
, 0 );
364 defext
= MemAlloc((len
+1)*sizeof(WCHAR
));
365 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, defext
, len
);
367 fodInfos
.defext
= defext
;
371 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, NULL
, 0 );
372 title
= MemAlloc((len
+1)*sizeof(WCHAR
));
373 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, title
, len
);
375 fodInfos
.title
= title
;
377 if (ofn
->lpstrFilter
)
382 /* filter is a list... title\0ext\0......\0\0 */
383 s
= ofn
->lpstrFilter
;
384 while (*s
) s
= s
+strlen(s
)+1;
386 n
= s
- ofn
->lpstrFilter
;
387 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, NULL
, 0 );
388 filter
= MemAlloc(len
*sizeof(WCHAR
));
389 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, filter
, len
);
391 fodInfos
.filter
= filter
;
393 /* convert lpstrCustomFilter */
394 if (ofn
->lpstrCustomFilter
)
399 /* customfilter contains a pair of strings... title\0ext\0 */
400 s
= ofn
->lpstrCustomFilter
;
401 if (*s
) s
= s
+strlen(s
)+1;
402 if (*s
) s
= s
+strlen(s
)+1;
403 n
= s
- ofn
->lpstrCustomFilter
;
404 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, NULL
, 0 );
405 customfilter
= MemAlloc(len
*sizeof(WCHAR
));
406 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, customfilter
, len
);
408 fodInfos
.customfilter
= customfilter
;
410 /* Initialize the dialog property */
411 fodInfos
.DlgInfos
.dwDlgProp
= 0;
412 fodInfos
.DlgInfos
.hwndCustomDlg
= NULL
;
417 ret
= GetFileName95(&fodInfos
);
420 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
421 ret
= GetFileName95(&fodInfos
);
429 SetCurrentDirectoryA(lpstrSavDir
);
430 MemFree(lpstrSavDir
);
436 MemFree(customfilter
);
437 MemFree(fodInfos
.initdir
);
438 MemFree(fodInfos
.filename
);
440 TRACE("selected file: %s\n",ofn
->lpstrFile
);
445 /***********************************************************************
448 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
449 * Call GetFileName95 with this structure and clean the memory.
452 BOOL WINAPI
GetFileDialog95W(LPOPENFILENAMEW ofn
,UINT iDlgType
)
455 FileOpenDlgInfos fodInfos
;
456 LPWSTR lpstrSavDir
= NULL
;
458 /* Initialize CommDlgExtendedError() */
459 COMDLG32_SetCommDlgExtendedError(0);
461 /* Initialize FileOpenDlgInfos structure */
462 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
464 /* Pass in the original ofn */
465 fodInfos
.ofnInfos
= ofn
;
467 fodInfos
.title
= ofn
->lpstrTitle
;
468 fodInfos
.defext
= ofn
->lpstrDefExt
;
469 fodInfos
.filter
= ofn
->lpstrFilter
;
470 fodInfos
.customfilter
= ofn
->lpstrCustomFilter
;
472 /* convert string arguments, save others */
475 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
476 lstrcpynW(fodInfos
.filename
,ofn
->lpstrFile
,ofn
->nMaxFile
);
479 fodInfos
.filename
= NULL
;
481 if(ofn
->lpstrInitialDir
)
483 /* fodInfos.initdir = strdupW(ofn->lpstrInitialDir); */
484 DWORD len
= lstrlenW(ofn
->lpstrInitialDir
)+1;
485 fodInfos
.initdir
= MemAlloc(len
*sizeof(WCHAR
));
486 memcpy(fodInfos
.initdir
,ofn
->lpstrInitialDir
,len
*sizeof(WCHAR
));
489 fodInfos
.initdir
= NULL
;
491 /* save current directory */
492 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
494 lpstrSavDir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
495 GetCurrentDirectoryW(MAX_PATH
, lpstrSavDir
);
498 fodInfos
.unicode
= TRUE
;
503 ret
= GetFileName95(&fodInfos
);
506 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
507 ret
= GetFileName95(&fodInfos
);
515 SetCurrentDirectoryW(lpstrSavDir
);
516 MemFree(lpstrSavDir
);
519 /* restore saved IN arguments and convert OUT arguments back */
520 MemFree(fodInfos
.filename
);
521 MemFree(fodInfos
.initdir
);
525 /******************************************************************************
526 * COMDLG32_GetDisplayNameOf [internal]
528 * Helper function to get the display name for a pidl.
530 static BOOL
COMDLG32_GetDisplayNameOf(LPCITEMIDLIST pidl
, LPWSTR pwszPath
) {
531 LPSHELLFOLDER psfDesktop
;
534 if (FAILED(SHGetDesktopFolder(&psfDesktop
)))
537 if (FAILED(IShellFolder_GetDisplayNameOf(psfDesktop
, pidl
, SHGDN_FORPARSING
, &strret
))) {
538 IShellFolder_Release(psfDesktop
);
542 IShellFolder_Release(psfDesktop
);
543 return SUCCEEDED(StrRetToBufW(&strret
, pidl
, pwszPath
, MAX_PATH
));
546 /***********************************************************************
547 * ArrangeCtrlPositions [internal]
549 * NOTE: Do not change anything here without a lot of testing.
551 static void ArrangeCtrlPositions(HWND hwndChildDlg
, HWND hwndParentDlg
, BOOL hide_help
)
553 HWND hwndChild
, hwndStc32
;
554 RECT rectParent
, rectChild
, rectStc32
;
555 INT help_fixup
= 0, child_height_fixup
= 0, child_width_fixup
= 0;
557 /* Take into account if open as read only checkbox and help button
562 RECT rectHelp
, rectCancel
;
563 GetWindowRect(GetDlgItem(hwndParentDlg
, pshHelp
), &rectHelp
);
564 GetWindowRect(GetDlgItem(hwndParentDlg
, IDCANCEL
), &rectCancel
);
565 /* subtract the height of the help button plus the space between
566 * the help button and the cancel button to the height of the dialog
568 help_fixup
= rectHelp
.bottom
- rectCancel
.bottom
;
572 There are two possibilities to add components to the default file dialog box.
574 By default, all the new components are added below the standard dialog box (the else case).
576 However, if there is a static text component with the stc32 id, a special case happens.
577 The x and y coordinates of stc32 indicate the top left corner where to place the standard file dialog box
578 in the window and the cx and cy indicate how to size the window.
579 Moreover, if the new component's coordinates are on the left of the stc32 , it is placed on the left
580 of the standard file dialog box. If they are above the stc32 component, it is placed above and so on....
584 GetClientRect(hwndParentDlg
, &rectParent
);
586 /* when arranging controls we have to use fixed parent size */
587 rectParent
.bottom
-= help_fixup
;
589 hwndStc32
= GetDlgItem(hwndChildDlg
, stc32
);
592 GetWindowRect(hwndStc32
, &rectStc32
);
593 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectStc32
, 2);
595 /* set the size of the stc32 control according to the size of
596 * client area of the parent dialog
598 SetWindowPos(hwndStc32
, 0,
600 rectParent
.right
, rectParent
.bottom
,
601 SWP_NOMOVE
| SWP_NOZORDER
);
604 SetRectEmpty(&rectStc32
);
606 /* this part moves controls of the child dialog */
607 hwndChild
= GetWindow(hwndChildDlg
, GW_CHILD
);
610 if (hwndChild
!= hwndStc32
)
612 GetWindowRect(hwndChild
, &rectChild
);
613 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectChild
, 2);
615 /* move only if stc32 exist */
616 if (hwndStc32
&& rectChild
.left
> rectStc32
.right
)
618 LONG old_left
= rectChild
.left
;
620 /* move to the right of visible controls of the parent dialog */
621 rectChild
.left
+= rectParent
.right
;
622 rectChild
.left
-= rectStc32
.right
;
624 child_width_fixup
= rectChild
.left
- old_left
;
626 /* move even if stc32 doesn't exist */
627 if (rectChild
.top
>= rectStc32
.bottom
)
629 LONG old_top
= rectChild
.top
;
631 /* move below visible controls of the parent dialog */
632 rectChild
.top
+= rectParent
.bottom
;
633 rectChild
.top
-= rectStc32
.bottom
- rectStc32
.top
;
635 child_height_fixup
= rectChild
.top
- old_top
;
638 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
639 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
641 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
644 /* this part moves controls of the parent dialog */
645 hwndChild
= GetWindow(hwndParentDlg
, GW_CHILD
);
648 if (hwndChild
!= hwndChildDlg
)
650 GetWindowRect(hwndChild
, &rectChild
);
651 MapWindowPoints(0, hwndParentDlg
, (LPPOINT
)&rectChild
, 2);
653 /* left,top of stc32 marks the position of controls
654 * from the parent dialog
656 rectChild
.left
+= rectStc32
.left
;
657 rectChild
.top
+= rectStc32
.top
;
659 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
660 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
662 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
665 /* calculate the size of the resulting dialog */
667 /* here we have to use original parent size */
668 GetClientRect(hwndParentDlg
, &rectParent
);
669 GetClientRect(hwndChildDlg
, &rectChild
);
673 rectChild
.right
+= child_width_fixup
;
674 rectChild
.bottom
+= child_height_fixup
;
676 if (rectParent
.right
> rectChild
.right
)
678 rectParent
.right
+= rectChild
.right
;
679 rectParent
.right
-= rectStc32
.right
- rectStc32
.left
;
683 rectParent
.right
= rectChild
.right
;
686 if (rectParent
.bottom
> rectChild
.bottom
)
688 rectParent
.bottom
+= rectChild
.bottom
;
689 rectParent
.bottom
-= rectStc32
.bottom
- rectStc32
.top
;
693 /* child dialog is higher, unconditionally set new dialog
694 * height to its size (help_fixup will be subtracted below)
696 rectParent
.bottom
= rectChild
.bottom
+ help_fixup
;
701 rectParent
.bottom
+= rectChild
.bottom
;
704 /* finally use fixed parent size */
705 rectParent
.bottom
-= help_fixup
;
707 /* set the size of the parent dialog */
708 AdjustWindowRectEx(&rectParent
, GetWindowLongW(hwndParentDlg
, GWL_STYLE
),
709 FALSE
, GetWindowLongW(hwndParentDlg
, GWL_EXSTYLE
));
710 SetWindowPos(hwndParentDlg
, 0,
712 rectParent
.right
- rectParent
.left
,
713 rectParent
.bottom
- rectParent
.top
,
714 SWP_NOMOVE
| SWP_NOZORDER
);
717 static INT_PTR CALLBACK
FileOpenDlgProcUserTemplate(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
726 static HWND
CreateTemplateDialog(FileOpenDlgInfos
*fodInfos
, HWND hwnd
)
736 * If OFN_ENABLETEMPLATEHANDLE is specified, the OPENFILENAME
737 * structure's hInstance parameter is not a HINSTANCE, but
738 * instead a pointer to a template resource to use.
740 if (fodInfos
->ofnInfos
->Flags
& (OFN_ENABLETEMPLATE
| OFN_ENABLETEMPLATEHANDLE
))
743 if (fodInfos
->ofnInfos
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
745 hinst
= COMDLG32_hInstance
;
746 if( !(template = LockResource( fodInfos
->ofnInfos
->hInstance
)))
748 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
754 hinst
= fodInfos
->ofnInfos
->hInstance
;
755 if(fodInfos
->unicode
)
757 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
758 hRes
= FindResourceW( hinst
, ofn
->lpTemplateName
, (LPWSTR
)RT_DIALOG
);
762 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
763 hRes
= FindResourceA( hinst
, ofn
->lpTemplateName
, (LPSTR
)RT_DIALOG
);
767 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
770 if (!(hDlgTmpl
= LoadResource( hinst
, hRes
)) ||
771 !(template = LockResource( hDlgTmpl
)))
773 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
777 if (fodInfos
->unicode
)
778 hChildDlg
= CreateDialogIndirectParamW(hinst
, template, hwnd
,
779 IsHooked(fodInfos
) ? (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
: FileOpenDlgProcUserTemplate
,
780 (LPARAM
)fodInfos
->ofnInfos
);
782 hChildDlg
= CreateDialogIndirectParamA(hinst
, template, hwnd
,
783 IsHooked(fodInfos
) ? (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
: FileOpenDlgProcUserTemplate
,
784 (LPARAM
)fodInfos
->ofnInfos
);
787 ShowWindow(hChildDlg
,SW_SHOW
);
791 else if( IsHooked(fodInfos
))
796 WORD menu
,class,title
;
798 GetClientRect(hwnd
,&rectHwnd
);
799 temp
.tmplate
.style
= WS_CHILD
| WS_CLIPSIBLINGS
| WS_VISIBLE
| DS_CONTROL
| DS_3DLOOK
;
800 temp
.tmplate
.dwExtendedStyle
= 0;
801 temp
.tmplate
.cdit
= 0;
806 temp
.menu
= temp
.class = temp
.title
= 0;
808 hChildDlg
= CreateDialogIndirectParamA(COMDLG32_hInstance
, &temp
.tmplate
,
809 hwnd
, (DLGPROC
)fodInfos
->ofnInfos
->lpfnHook
, (LPARAM
)fodInfos
->ofnInfos
);
816 /***********************************************************************
817 * SendCustomDlgNotificationMessage
819 * Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
822 LRESULT
SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
)
824 LRESULT hook_result
= 0;
826 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwndParentDlg
,FileOpenDlgInfosStr
);
828 TRACE("%p 0x%04x\n",hwndParentDlg
, uCode
);
830 if(!fodInfos
) return 0;
832 if(fodInfos
->DlgInfos
.hwndCustomDlg
)
834 TRACE("CALL NOTIFY for %x\n", uCode
);
835 if(fodInfos
->unicode
)
838 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
839 ofnNotify
.hdr
.idFrom
=0;
840 ofnNotify
.hdr
.code
= uCode
;
841 ofnNotify
.lpOFN
= fodInfos
->ofnInfos
;
842 ofnNotify
.pszFile
= NULL
;
843 hook_result
= SendMessageW(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
848 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
849 ofnNotify
.hdr
.idFrom
=0;
850 ofnNotify
.hdr
.code
= uCode
;
851 ofnNotify
.lpOFN
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
852 ofnNotify
.pszFile
= NULL
;
853 hook_result
= SendMessageA(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
855 TRACE("RET NOTIFY\n");
857 TRACE("Retval: 0x%08lx\n", hook_result
);
861 static INT_PTR
FILEDLG95_Handle_GetFilePath(HWND hwnd
, DWORD size
, LPVOID result
)
865 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
867 TRACE("CDM_GETFILEPATH:\n");
869 if ( ! (fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
872 /* get path and filenames */
873 len
= SendMessageW( fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXTLENGTH
, 0, 0 );
874 buffer
= HeapAlloc( GetProcessHeap(), 0, (len
+ 2 + MAX_PATH
) * sizeof(WCHAR
) );
875 COMDLG32_GetDisplayNameOf( fodInfos
->ShellInfos
.pidlAbsCurrent
, buffer
);
878 p
= buffer
+ strlenW(buffer
);
880 SendMessageW( fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXT
, len
+ 1, (LPARAM
)p
);
882 if (fodInfos
->unicode
)
884 total
= strlenW( buffer
) + 1;
885 if (result
) lstrcpynW( result
, buffer
, size
);
886 TRACE( "CDM_GETFILEPATH: returning %u %s\n", total
, debugstr_w(result
));
890 total
= WideCharToMultiByte( CP_ACP
, 0, buffer
, -1, NULL
, 0, NULL
, NULL
);
891 if (total
<= size
) WideCharToMultiByte( CP_ACP
, 0, buffer
, -1, result
, size
, NULL
, NULL
);
892 TRACE( "CDM_GETFILEPATH: returning %u %s\n", total
, debugstr_a(result
));
894 HeapFree( GetProcessHeap(), 0, buffer
);
898 /***********************************************************************
899 * FILEDLG95_HandleCustomDialogMessages
901 * Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
903 static INT_PTR
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
905 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
906 WCHAR lpstrPath
[MAX_PATH
];
909 if(!fodInfos
) return FALSE
;
913 case CDM_GETFILEPATH
:
914 retval
= FILEDLG95_Handle_GetFilePath(hwnd
, (UINT
)wParam
, (LPVOID
)lParam
);
917 case CDM_GETFOLDERPATH
:
918 TRACE("CDM_GETFOLDERPATH:\n");
919 COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPath
);
922 if (fodInfos
->unicode
)
923 lstrcpynW((LPWSTR
)lParam
, lpstrPath
, (int)wParam
);
925 WideCharToMultiByte(CP_ACP
, 0, lpstrPath
, -1,
926 (LPSTR
)lParam
, (int)wParam
, NULL
, NULL
);
928 retval
= lstrlenW(lpstrPath
);
931 case CDM_GETFOLDERIDLIST
:
932 retval
= COMDLG32_PIDL_ILGetSize(fodInfos
->ShellInfos
.pidlAbsCurrent
);
933 if (retval
<= wParam
)
934 memcpy((void*)lParam
, fodInfos
->ShellInfos
.pidlAbsCurrent
, retval
);
938 TRACE("CDM_GETSPEC:\n");
939 retval
= SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXTLENGTH
, 0, 0) + 1;
942 if (fodInfos
->unicode
)
943 SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXT
, wParam
, lParam
);
945 SendMessageA(fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXT
, wParam
, lParam
);
949 case CDM_SETCONTROLTEXT
:
950 TRACE("CDM_SETCONTROLTEXT:\n");
953 if( fodInfos
->unicode
)
954 SetDlgItemTextW( hwnd
, (UINT
) wParam
, (LPWSTR
) lParam
);
956 SetDlgItemTextA( hwnd
, (UINT
) wParam
, (LPSTR
) lParam
);
961 case CDM_HIDECONTROL
:
962 /* MSDN states that it should fail for not OFN_EXPLORER case */
963 if (fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
)
965 HWND control
= GetDlgItem( hwnd
, wParam
);
966 if (control
) ShowWindow( control
, SW_HIDE
);
973 if (uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
974 FIXME("message CDM_FIRST+%04x not implemented\n", uMsg
- CDM_FIRST
);
977 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, retval
);
981 /***********************************************************************
984 * File open dialog procedure
986 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
989 TRACE("0x%04x 0x%04x\n", hwnd
, uMsg
);
996 FileOpenDlgInfos
* fodInfos
= (FileOpenDlgInfos
*)lParam
;
998 /* Adds the FileOpenDlgInfos in the property list of the dialog
999 so it will be easily accessible through a GetPropA(...) */
1000 SetPropA(hwnd
, FileOpenDlgInfosStr
, (HANDLE
) fodInfos
);
1002 FILEDLG95_InitControls(hwnd
);
1004 fodInfos
->DlgInfos
.hwndCustomDlg
=
1005 CreateTemplateDialog((FileOpenDlgInfos
*)lParam
, hwnd
);
1007 FILEDLG95_ResizeControls(hwnd
, wParam
, lParam
);
1008 FILEDLG95_FillControls(hwnd
, wParam
, lParam
);
1010 SendCustomDlgNotificationMessage(hwnd
,CDN_INITDONE
);
1011 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
1012 SendCustomDlgNotificationMessage(hwnd
,CDN_SELCHANGE
);
1016 return FILEDLG95_OnWMCommand(hwnd
, wParam
, lParam
);
1019 switch(((LPDRAWITEMSTRUCT
)lParam
)->CtlID
)
1022 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT
) lParam
);
1028 case WM_GETISHELLBROWSER
:
1029 return FILEDLG95_OnWMGetIShellBrowser(hwnd
);
1032 RemovePropA(hwnd
, FileOpenDlgInfosStr
);
1037 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
1040 /* set up the button tooltips strings */
1041 if(TTN_GETDISPINFOA
== lpnmh
->code
)
1043 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
1044 switch(lpnmh
->idFrom
)
1046 /* Up folder button */
1047 case FCIDM_TB_UPFOLDER
:
1048 stringId
= IDS_UPFOLDER
;
1050 /* New folder button */
1051 case FCIDM_TB_NEWFOLDER
:
1052 stringId
= IDS_NEWFOLDER
;
1054 /* List option button */
1055 case FCIDM_TB_SMALLICON
:
1056 stringId
= IDS_LISTVIEW
;
1058 /* Details option button */
1059 case FCIDM_TB_REPORTVIEW
:
1060 stringId
= IDS_REPORTVIEW
;
1062 /* Desktop button */
1063 case FCIDM_TB_DESKTOP
:
1064 stringId
= IDS_TODESKTOP
;
1069 lpdi
->hinst
= COMDLG32_hInstance
;
1070 lpdi
->lpszText
= MAKEINTRESOURCEA(stringId
);
1075 if(uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
1076 return FILEDLG95_HandleCustomDialogMessages(hwnd
, uMsg
, wParam
, lParam
);
1081 /***********************************************************************
1082 * FILEDLG95_InitControls
1084 * WM_INITDIALOG message handler (before hook notification)
1086 static LRESULT
FILEDLG95_InitControls(HWND hwnd
)
1088 int win2000plus
= 0;
1090 int handledPath
= FALSE
;
1091 OSVERSIONINFOW osVi
;
1092 static const WCHAR szwSlash
[] = { '\\', 0 };
1093 static const WCHAR szwStar
[] = { '*',0 };
1095 static const TBBUTTON tbb
[] =
1097 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1098 {VIEW_PARENTFOLDER
, FCIDM_TB_UPFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1099 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1100 {VIEW_NEWFOLDER
+1, FCIDM_TB_DESKTOP
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1101 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1102 {VIEW_NEWFOLDER
, FCIDM_TB_NEWFOLDER
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1103 {0, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0, 0}, 0, 0 },
1104 {VIEW_LIST
, FCIDM_TB_SMALLICON
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1105 {VIEW_DETAILS
, FCIDM_TB_REPORTVIEW
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0, 0}, 0, 0 },
1110 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1112 tba
[0].hInst
= HINST_COMMCTRL
;
1113 tba
[0].nID
= IDB_VIEW_SMALL_COLOR
;
1114 tba
[1].hInst
= COMDLG32_hInstance
;
1117 TRACE("%p\n", fodInfos
);
1119 /* Get windows version emulating */
1120 osVi
.dwOSVersionInfoSize
= sizeof(osVi
);
1121 GetVersionExW(&osVi
);
1122 if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
) {
1123 win98plus
= ((osVi
.dwMajorVersion
> 4) || ((osVi
.dwMajorVersion
== 4) && (osVi
.dwMinorVersion
> 0)));
1124 } else if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1125 win2000plus
= (osVi
.dwMajorVersion
> 4);
1126 if (win2000plus
) win98plus
= TRUE
;
1128 TRACE("Running on 2000+ %d, 98+ %d\n", win2000plus
, win98plus
);
1130 /* Get the hwnd of the controls */
1131 fodInfos
->DlgInfos
.hwndFileName
= GetDlgItem(hwnd
,IDC_FILENAME
);
1132 fodInfos
->DlgInfos
.hwndFileTypeCB
= GetDlgItem(hwnd
,IDC_FILETYPE
);
1133 fodInfos
->DlgInfos
.hwndLookInCB
= GetDlgItem(hwnd
,IDC_LOOKIN
);
1135 GetWindowRect( fodInfos
->DlgInfos
.hwndLookInCB
,&rectlook
);
1136 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectlook
,2);
1138 /* construct the toolbar */
1139 GetWindowRect(GetDlgItem(hwnd
,IDC_TOOLBARSTATIC
),&rectTB
);
1140 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectTB
,2);
1142 rectTB
.right
= rectlook
.right
+ rectTB
.right
- rectTB
.left
;
1143 rectTB
.bottom
= rectlook
.top
- 1 + rectTB
.bottom
- rectTB
.top
;
1144 rectTB
.left
= rectlook
.right
;
1145 rectTB
.top
= rectlook
.top
-1;
1147 if (fodInfos
->unicode
)
1148 fodInfos
->DlgInfos
.hwndTB
= CreateWindowExW(0, TOOLBARCLASSNAMEW
, NULL
,
1149 WS_CHILD
| WS_GROUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NORESIZE
,
1150 rectTB
.left
, rectTB
.top
,
1151 rectTB
.right
- rectTB
.left
, rectTB
.bottom
- rectTB
.top
,
1152 hwnd
, (HMENU
)IDC_TOOLBAR
, COMDLG32_hInstance
, NULL
);
1154 fodInfos
->DlgInfos
.hwndTB
= CreateWindowExA(0, TOOLBARCLASSNAMEA
, NULL
,
1155 WS_CHILD
| WS_GROUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NORESIZE
,
1156 rectTB
.left
, rectTB
.top
,
1157 rectTB
.right
- rectTB
.left
, rectTB
.bottom
- rectTB
.top
,
1158 hwnd
, (HMENU
)IDC_TOOLBAR
, COMDLG32_hInstance
, NULL
);
1160 SendMessageW(fodInfos
->DlgInfos
.hwndTB
, TB_BUTTONSTRUCTSIZE
, sizeof(TBBUTTON
), 0);
1162 /* FIXME: use TB_LOADIMAGES when implemented */
1163 /* SendMessageW(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1164 SendMessageW(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, 12, (LPARAM
) &tba
[0]);
1165 SendMessageW(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, 1, (LPARAM
) &tba
[1]);
1167 SendMessageW(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBUTTONSW
, 9, (LPARAM
) tbb
);
1168 SendMessageW(fodInfos
->DlgInfos
.hwndTB
, TB_AUTOSIZE
, 0, 0);
1170 /* Set the window text with the text specified in the OPENFILENAME structure */
1173 SetWindowTextW(hwnd
,fodInfos
->title
);
1175 else if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1178 LoadStringW(COMDLG32_hInstance
, IDS_SAVE
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1179 SetWindowTextW(hwnd
, buf
);
1182 /* Initialise the file name edit control */
1183 handledPath
= FALSE
;
1184 TRACE("Before manipilation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1186 if(fodInfos
->filename
)
1188 /* 1. If win2000 or higher and filename contains a path, use it
1189 in preference over the lpstrInitialDir */
1190 if (win2000plus
&& *fodInfos
->filename
&& strpbrkW(fodInfos
->filename
, szwSlash
)) {
1191 WCHAR tmpBuf
[MAX_PATH
];
1195 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
, tmpBuf
, &nameBit
);
1198 /* nameBit is always shorter than the original filename */
1199 lstrcpyW(fodInfos
->filename
,nameBit
);
1202 if (fodInfos
->initdir
== NULL
)
1203 MemFree(fodInfos
->initdir
);
1204 fodInfos
->initdir
= MemAlloc((lstrlenW(tmpBuf
) + 1)*sizeof(WCHAR
));
1205 lstrcpyW(fodInfos
->initdir
, tmpBuf
);
1207 TRACE("Value in Filename includes path, overriding InitialDir: %s, %s\n",
1208 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1210 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1213 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1217 /* 2. (All platforms) If initdir is not null, then use it */
1218 if ((handledPath
== FALSE
) && (fodInfos
->initdir
!=NULL
) &&
1219 (*fodInfos
->initdir
!=0x00))
1221 /* Work out the proper path as supplied one might be relative */
1222 /* (Here because supplying '.' as dir browses to My Computer) */
1223 if (handledPath
==FALSE
) {
1224 WCHAR tmpBuf
[MAX_PATH
];
1225 WCHAR tmpBuf2
[MAX_PATH
];
1229 lstrcpyW(tmpBuf
, fodInfos
->initdir
);
1230 if( PathFileExistsW(tmpBuf
) ) {
1231 /* initdir does not have to be a directory. If a file is
1232 * specified, the dir part is taken */
1233 if( PathIsDirectoryW(tmpBuf
)) {
1234 if (tmpBuf
[lstrlenW(tmpBuf
)-1] != '\\') {
1235 lstrcatW(tmpBuf
, szwSlash
);
1237 lstrcatW(tmpBuf
, szwStar
);
1239 result
= GetFullPathNameW(tmpBuf
, MAX_PATH
, tmpBuf2
, &nameBit
);
1242 MemFree(fodInfos
->initdir
);
1243 fodInfos
->initdir
= MemAlloc((lstrlenW(tmpBuf2
) + 1)*sizeof(WCHAR
));
1244 lstrcpyW(fodInfos
->initdir
, tmpBuf2
);
1246 TRACE("Value in InitDir changed to %s\n", debugstr_w(fodInfos
->initdir
));
1249 else if (fodInfos
->initdir
)
1251 MemFree(fodInfos
->initdir
);
1252 fodInfos
->initdir
= NULL
;
1253 TRACE("Value in InitDir is not an existing path, changed to (nil)\n");
1258 if ((handledPath
== FALSE
) && ((fodInfos
->initdir
==NULL
) ||
1259 (*fodInfos
->initdir
==0x00)))
1261 /* 3. All except w2k+: if filename contains a path use it */
1262 if (!win2000plus
&& fodInfos
->filename
&&
1263 *fodInfos
->filename
&&
1264 strpbrkW(fodInfos
->filename
, szwSlash
)) {
1265 WCHAR tmpBuf
[MAX_PATH
];
1269 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
,
1274 /* nameBit is always shorter than the original filename */
1275 lstrcpyW(fodInfos
->filename
, nameBit
);
1278 len
= lstrlenW(tmpBuf
);
1279 MemFree(fodInfos
->initdir
);
1280 fodInfos
->initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
1281 lstrcpyW(fodInfos
->initdir
, tmpBuf
);
1284 TRACE("Value in Filename includes path, overriding initdir: %s, %s\n",
1285 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1287 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1290 /* 4. win98+ and win2000+ if any files of specified filter types in
1291 current directory, use it */
1292 if ( win98plus
&& handledPath
== FALSE
&&
1293 fodInfos
->filter
&& *fodInfos
->filter
) {
1295 BOOL searchMore
= TRUE
;
1296 LPCWSTR lpstrPos
= fodInfos
->filter
;
1297 WIN32_FIND_DATAW FindFileData
;
1302 /* filter is a list... title\0ext\0......\0\0 */
1304 /* Skip the title */
1305 if(! *lpstrPos
) break; /* end */
1306 lpstrPos
+= lstrlenW(lpstrPos
) + 1;
1308 /* See if any files exist in the current dir with this extension */
1309 if(! *lpstrPos
) break; /* end */
1311 hFind
= FindFirstFileW(lpstrPos
, &FindFileData
);
1313 if (hFind
== INVALID_HANDLE_VALUE
) {
1314 /* None found - continue search */
1315 lpstrPos
+= lstrlenW(lpstrPos
) + 1;
1320 MemFree(fodInfos
->initdir
);
1321 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1322 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1325 TRACE("No initial dir specified, but files of type %s found in current, so using it\n",
1326 debugstr_w(lpstrPos
));
1332 /* 5. Win2000+: FIXME: Next, Recently used? Not sure how windows does this */
1334 /* 6. Win98+ and 2000+: Use personal files dir, others use current dir */
1335 if (handledPath
== FALSE
&& (win2000plus
|| win98plus
)) {
1336 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1338 if(!COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_PERSONAL
, 0, 0, fodInfos
->initdir
))
1340 if(!COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_DESKTOPDIRECTORY
|CSIDL_FLAG_CREATE
, 0, 0, fodInfos
->initdir
))
1343 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1344 TRACE("No personal or desktop dir, using cwd as failsafe: %s\n", debugstr_w(fodInfos
->initdir
));
1346 TRACE("No personal dir, using desktop instead: %s\n", debugstr_w(fodInfos
->initdir
));
1349 TRACE("No initial dir specified, using personal files dir of %s\n", debugstr_w(fodInfos
->initdir
));
1352 } else if (handledPath
==FALSE
) {
1353 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1354 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1356 TRACE("No initial dir specified, using current dir of %s\n", debugstr_w(fodInfos
->initdir
));
1359 SetFocus(GetDlgItem(hwnd
, IDC_FILENAME
));
1360 TRACE("After manipulation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1362 /* Must the open as read only check box be checked ?*/
1363 if(fodInfos
->ofnInfos
->Flags
& OFN_READONLY
)
1365 SendDlgItemMessageW(hwnd
,IDC_OPENREADONLY
,BM_SETCHECK
,TRUE
,0);
1368 /* Must the open as read only check box be hidden? */
1369 if(fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
)
1371 ShowWindow(GetDlgItem(hwnd
,IDC_OPENREADONLY
),SW_HIDE
);
1372 EnableWindow(GetDlgItem(hwnd
, IDC_OPENREADONLY
), FALSE
);
1375 /* Must the help button be hidden? */
1376 if (!(fodInfos
->ofnInfos
->Flags
& OFN_SHOWHELP
))
1378 ShowWindow(GetDlgItem(hwnd
, pshHelp
), SW_HIDE
);
1379 EnableWindow(GetDlgItem(hwnd
, pshHelp
), FALSE
);
1382 /* change Open to Save */
1383 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1386 LoadStringW(COMDLG32_hInstance
, IDS_SAVE_BUTTON
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1387 SetDlgItemTextW(hwnd
, IDOK
, buf
);
1388 LoadStringW(COMDLG32_hInstance
, IDS_SAVE_IN
, buf
, sizeof(buf
)/sizeof(WCHAR
));
1389 SetDlgItemTextW(hwnd
, IDC_LOOKINSTATIC
, buf
);
1392 /* Initialize the filter combo box */
1393 FILEDLG95_FILETYPE_Init(hwnd
);
1398 /***********************************************************************
1399 * FILEDLG95_ResizeControls
1401 * WM_INITDIALOG message handler (after hook notification)
1403 static LRESULT
FILEDLG95_ResizeControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1405 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) lParam
;
1407 if (fodInfos
->DlgInfos
.hwndCustomDlg
)
1410 UINT flags
= SWP_NOACTIVATE
;
1412 ArrangeCtrlPositions(fodInfos
->DlgInfos
.hwndCustomDlg
, hwnd
,
1413 (fodInfos
->ofnInfos
->Flags
& (OFN_HIDEREADONLY
| OFN_SHOWHELP
)) == OFN_HIDEREADONLY
);
1415 /* resize the custom dialog to the parent size */
1416 if (fodInfos
->ofnInfos
->Flags
& (OFN_ENABLETEMPLATE
| OFN_ENABLETEMPLATEHANDLE
))
1417 GetClientRect(hwnd
, &rc
);
1420 /* our own fake template is zero sized and doesn't have children, so
1421 * there is no need to resize it. Picasa depends on it.
1423 flags
|= SWP_NOSIZE
;
1426 SetWindowPos(fodInfos
->DlgInfos
.hwndCustomDlg
, HWND_BOTTOM
,
1427 0, 0, rc
.right
, rc
.bottom
, flags
);
1431 /* Resize the height, if open as read only checkbox ad help button are
1432 * hidden and we are not using a custom template nor a customDialog
1434 if ( (fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
) &&
1435 (!(fodInfos
->ofnInfos
->Flags
&
1436 (OFN_SHOWHELP
|OFN_ENABLETEMPLATE
|OFN_ENABLETEMPLATEHANDLE
))))
1438 RECT rectDlg
, rectHelp
, rectCancel
;
1439 GetWindowRect(hwnd
, &rectDlg
);
1440 GetWindowRect(GetDlgItem(hwnd
, pshHelp
), &rectHelp
);
1441 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rectCancel
);
1442 /* subtract the height of the help button plus the space between the help
1443 * button and the cancel button to the height of the dialog
1445 SetWindowPos(hwnd
, 0, 0, 0, rectDlg
.right
-rectDlg
.left
,
1446 (rectDlg
.bottom
-rectDlg
.top
) - (rectHelp
.bottom
- rectCancel
.bottom
),
1447 SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
);
1453 /***********************************************************************
1454 * FILEDLG95_FillControls
1456 * WM_INITDIALOG message handler (after hook notification)
1458 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1460 LPITEMIDLIST pidlItemId
= NULL
;
1462 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) lParam
;
1464 TRACE("dir=%s file=%s\n",
1465 debugstr_w(fodInfos
->initdir
), debugstr_w(fodInfos
->filename
));
1467 /* Get the initial directory pidl */
1469 if(!(pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,fodInfos
->initdir
)))
1471 WCHAR path
[MAX_PATH
];
1473 GetCurrentDirectoryW(MAX_PATH
,path
);
1474 pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, path
);
1477 /* Initialise shell objects */
1478 FILEDLG95_SHELL_Init(hwnd
);
1480 /* Initialize the Look In combo box */
1481 FILEDLG95_LOOKIN_Init(fodInfos
->DlgInfos
.hwndLookInCB
);
1483 /* Browse to the initial directory */
1484 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,pidlItemId
, SBSP_ABSOLUTE
);
1486 /* Free pidlItem memory */
1487 COMDLG32_SHFree(pidlItemId
);
1491 /***********************************************************************
1494 * Regroups all the cleaning functions of the filedlg
1496 void FILEDLG95_Clean(HWND hwnd
)
1498 FILEDLG95_FILETYPE_Clean(hwnd
);
1499 FILEDLG95_LOOKIN_Clean(hwnd
);
1500 FILEDLG95_SHELL_Clean(hwnd
);
1502 /***********************************************************************
1503 * FILEDLG95_OnWMCommand
1505 * WM_COMMAND message handler
1507 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1509 WORD wNotifyCode
= HIWORD(wParam
); /* notification code */
1510 WORD wID
= LOWORD(wParam
); /* item, control, or accelerator identifier */
1511 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1517 FILEDLG95_OnOpen(hwnd
);
1521 FILEDLG95_Clean(hwnd
);
1522 EndDialog(hwnd
, FALSE
);
1524 /* Filetype combo box */
1526 FILEDLG95_FILETYPE_OnCommand(hwnd
,wNotifyCode
);
1528 /* LookIn combo box */
1530 FILEDLG95_LOOKIN_OnCommand(hwnd
,wNotifyCode
);
1533 /* --- toolbar --- */
1534 /* Up folder button */
1535 case FCIDM_TB_UPFOLDER
:
1536 FILEDLG95_SHELL_UpFolder(hwnd
);
1538 /* New folder button */
1539 case FCIDM_TB_NEWFOLDER
:
1540 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_NEWFOLDERA
);
1542 /* List option button */
1543 case FCIDM_TB_SMALLICON
:
1544 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWLISTA
);
1546 /* Details option button */
1547 case FCIDM_TB_REPORTVIEW
:
1548 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWDETAILSA
);
1550 /* Details option button */
1551 case FCIDM_TB_DESKTOP
:
1552 FILEDLG95_SHELL_BrowseToDesktop(hwnd
);
1559 /* Do not use the listview selection anymore */
1560 fodInfos
->DlgInfos
.dwDlgProp
&= ~FODPROP_USEVIEW
;
1564 /***********************************************************************
1565 * FILEDLG95_OnWMGetIShellBrowser
1567 * WM_GETISHELLBROWSER message handler
1569 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
)
1572 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1576 SetWindowLongPtrW(hwnd
,DWLP_MSGRESULT
,(LONG_PTR
)fodInfos
->Shell
.FOIShellBrowser
);
1582 /***********************************************************************
1583 * FILEDLG95_SendFileOK
1585 * Sends the CDN_FILEOK notification if required
1588 * TRUE if the dialog should close
1589 * FALSE if the dialog should not be closed
1591 static BOOL
FILEDLG95_SendFileOK( HWND hwnd
, FileOpenDlgInfos
*fodInfos
)
1593 /* ask the hook if we can close */
1594 if(IsHooked(fodInfos
))
1599 /* First send CDN_FILEOK as MSDN doc says */
1600 retval
= SendCustomDlgNotificationMessage(hwnd
,CDN_FILEOK
);
1601 if (GetWindowLongPtrW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWLP_MSGRESULT
))
1603 TRACE("canceled\n");
1604 return (retval
== 0);
1607 /* fodInfos->ofnInfos points to an ASCII or UNICODE structure as appropriate */
1608 retval
= SendMessageW(fodInfos
->DlgInfos
.hwndCustomDlg
,
1609 fodInfos
->HookMsg
.fileokstring
, 0, (LPARAM
)fodInfos
->ofnInfos
);
1610 if (GetWindowLongPtrW(fodInfos
->DlgInfos
.hwndCustomDlg
, DWLP_MSGRESULT
))
1612 TRACE("canceled\n");
1613 return (retval
== 0);
1619 /***********************************************************************
1620 * FILEDLG95_OnOpenMultipleFiles
1622 * Handles the opening of multiple files.
1625 * check destination buffer size
1627 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
)
1629 WCHAR lpstrPathSpec
[MAX_PATH
] = {0};
1630 UINT nCount
, nSizePath
;
1631 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1635 if(fodInfos
->unicode
)
1637 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
1638 ofn
->lpstrFile
[0] = '\0';
1642 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
) fodInfos
->ofnInfos
;
1643 ofn
->lpstrFile
[0] = '\0';
1646 COMDLG32_GetDisplayNameOf( fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathSpec
);
1648 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1649 ( fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1650 ! ( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1652 LPWSTR lpstrTemp
= lpstrFileList
;
1654 for ( nCount
= 0; nCount
< nFileCount
; nCount
++ )
1658 pidl
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, lpstrTemp
);
1661 WCHAR lpstrNotFound
[100];
1662 WCHAR lpstrMsg
[100];
1664 static const WCHAR nl
[] = {'\n',0};
1666 LoadStringW(COMDLG32_hInstance
, IDS_FILENOTFOUND
, lpstrNotFound
, 100);
1667 LoadStringW(COMDLG32_hInstance
, IDS_VERIFYFILE
, lpstrMsg
, 100);
1669 lstrcpyW(tmp
, lpstrTemp
);
1671 lstrcatW(tmp
, lpstrNotFound
);
1673 lstrcatW(tmp
, lpstrMsg
);
1675 MessageBoxW(hwnd
, tmp
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
1679 /* move to the next file in the list of files */
1680 lpstrTemp
+= lstrlenW(lpstrTemp
) + 1;
1681 COMDLG32_SHFree(pidl
);
1685 nSizePath
= lstrlenW(lpstrPathSpec
) + 1;
1686 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
1688 /* For "oldstyle" dialog the components have to
1689 be separated by blanks (not '\0'!) and short
1690 filenames have to be used! */
1691 FIXME("Components have to be separated by blanks\n");
1693 if(fodInfos
->unicode
)
1695 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
1696 lstrcpyW( ofn
->lpstrFile
, lpstrPathSpec
);
1697 memcpy( ofn
->lpstrFile
+ nSizePath
, lpstrFileList
, sizeUsed
*sizeof(WCHAR
) );
1701 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
1703 if (ofn
->lpstrFile
!= NULL
)
1705 nSizePath
= WideCharToMultiByte(CP_ACP
, 0, lpstrPathSpec
, -1,
1706 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
1707 if (ofn
->nMaxFile
> nSizePath
)
1709 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
1710 ofn
->lpstrFile
+ nSizePath
,
1711 ofn
->nMaxFile
- nSizePath
, NULL
, NULL
);
1716 fodInfos
->ofnInfos
->nFileOffset
= nSizePath
;
1717 fodInfos
->ofnInfos
->nFileExtension
= 0;
1719 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
1722 /* clean and exit */
1723 FILEDLG95_Clean(hwnd
);
1724 return EndDialog(hwnd
,TRUE
);
1727 /***********************************************************************
1730 * Ok button WM_COMMAND message handler
1732 * If the function succeeds, the return value is nonzero.
1734 #define ONOPEN_BROWSE 1
1735 #define ONOPEN_OPEN 2
1736 #define ONOPEN_SEARCH 3
1737 static void FILEDLG95_OnOpenMessage(HWND hwnd
, int idCaption
, int idText
)
1739 WCHAR strMsgTitle
[MAX_PATH
];
1740 WCHAR strMsgText
[MAX_PATH
];
1742 LoadStringW(COMDLG32_hInstance
, idCaption
, strMsgTitle
, sizeof(strMsgTitle
)/sizeof(WCHAR
));
1744 strMsgTitle
[0] = '\0';
1745 LoadStringW(COMDLG32_hInstance
, idText
, strMsgText
, sizeof(strMsgText
)/sizeof(WCHAR
));
1746 MessageBoxW(hwnd
,strMsgText
, strMsgTitle
, MB_OK
| MB_ICONHAND
);
1749 BOOL
FILEDLG95_OnOpen(HWND hwnd
)
1751 LPWSTR lpstrFileList
;
1752 UINT nFileCount
= 0;
1755 WCHAR lpstrPathAndFile
[MAX_PATH
];
1756 WCHAR lpstrTemp
[MAX_PATH
];
1757 LPSHELLFOLDER lpsf
= NULL
;
1759 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1761 TRACE("hwnd=%p\n", hwnd
);
1763 /* get the files from the edit control */
1764 nFileCount
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
);
1766 /* try if the user selected a folder in the shellview */
1769 BrowseSelectedFolder(hwnd
);
1775 ret
= FILEDLG95_OnOpenMultipleFiles(hwnd
, lpstrFileList
, nFileCount
, sizeUsed
);
1779 TRACE("count=%u len=%u file=%s\n", nFileCount
, sizeUsed
, debugstr_w(lpstrFileList
));
1782 Step 1: Build a complete path name from the current folder and
1783 the filename or path in the edit box.
1785 - the path in the edit box is a root path
1786 (with or without drive letter)
1787 - the edit box contains ".." (or a path with ".." in it)
1790 /* Get the current directory name */
1791 if (!COMDLG32_GetDisplayNameOf(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathAndFile
))
1794 GetCurrentDirectoryW(MAX_PATH
, lpstrPathAndFile
);
1796 PathAddBackslashW(lpstrPathAndFile
);
1798 TRACE("current directory=%s\n", debugstr_w(lpstrPathAndFile
));
1800 /* if the user specified a fully qualified path use it */
1801 if(PathIsRelativeW(lpstrFileList
))
1803 lstrcatW(lpstrPathAndFile
, lpstrFileList
);
1807 /* does the path have a drive letter? */
1808 if (PathGetDriveNumberW(lpstrFileList
) == -1)
1809 lstrcpyW(lpstrPathAndFile
+2, lpstrFileList
);
1811 lstrcpyW(lpstrPathAndFile
, lpstrFileList
);
1814 /* resolve "." and ".." */
1815 PathCanonicalizeW(lpstrTemp
, lpstrPathAndFile
);
1816 lstrcpyW(lpstrPathAndFile
, lpstrTemp
);
1817 TRACE("canon=%s\n", debugstr_w(lpstrPathAndFile
));
1819 MemFree(lpstrFileList
);
1822 Step 2: here we have a cleaned up path
1824 We have to parse the path step by step to see if we have to browse
1825 to a folder if the path points to a directory or the last
1826 valid element is a directory.
1829 lpstrPathAndFile: cleaned up path
1833 (fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1834 !(fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
))
1835 nOpenAction
= ONOPEN_OPEN
;
1837 nOpenAction
= ONOPEN_BROWSE
;
1839 /* don't apply any checks with OFN_NOVALIDATE */
1841 LPWSTR lpszTemp
, lpszTemp1
;
1842 LPITEMIDLIST pidl
= NULL
;
1843 static const WCHAR szwInvalid
[] = { '/',':','<','>','|', 0};
1845 /* check for invalid chars */
1846 if((strpbrkW(lpstrPathAndFile
+3, szwInvalid
) != NULL
) && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1848 FILEDLG95_OnOpenMessage(hwnd
, IDS_INVALID_FILENAME_TITLE
, IDS_INVALID_FILENAME
);
1853 if (FAILED (SHGetDesktopFolder(&lpsf
))) return FALSE
;
1855 lpszTemp1
= lpszTemp
= lpstrPathAndFile
;
1858 LPSHELLFOLDER lpsfChild
;
1859 WCHAR lpwstrTemp
[MAX_PATH
];
1860 DWORD dwEaten
, dwAttributes
;
1863 lstrcpyW(lpwstrTemp
, lpszTemp
);
1864 p
= PathFindNextComponentW(lpwstrTemp
);
1866 if (!p
) break; /* end of path */
1869 lpszTemp
= lpszTemp
+ lstrlenW(lpwstrTemp
);
1871 /* There are no wildcards when OFN_NOVALIDATE is set */
1872 if(*lpszTemp
==0 && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1874 static const WCHAR wszWild
[] = { '*', '?', 0 };
1875 /* if the last element is a wildcard do a search */
1876 if(strpbrkW(lpszTemp1
, wszWild
) != NULL
)
1878 nOpenAction
= ONOPEN_SEARCH
;
1882 lpszTemp1
= lpszTemp
;
1884 TRACE("parse now=%s next=%s sf=%p\n",debugstr_w(lpwstrTemp
), debugstr_w(lpszTemp
), lpsf
);
1886 /* append a backslash to drive letters */
1887 if(lstrlenW(lpwstrTemp
)==2 && lpwstrTemp
[1] == ':' &&
1888 ((lpwstrTemp
[0] >= 'a' && lpwstrTemp
[0] <= 'z') ||
1889 (lpwstrTemp
[0] >= 'A' && lpwstrTemp
[0] <= 'Z')))
1891 PathAddBackslashW(lpwstrTemp
);
1894 dwAttributes
= SFGAO_FOLDER
;
1895 if(SUCCEEDED(IShellFolder_ParseDisplayName(lpsf
, hwnd
, NULL
, lpwstrTemp
, &dwEaten
, &pidl
, &dwAttributes
)))
1897 /* the path component is valid, we have a pidl of the next path component */
1898 TRACE("parse OK attr=0x%08x pidl=%p\n", dwAttributes
, pidl
);
1899 if(dwAttributes
& SFGAO_FOLDER
)
1901 if(FAILED(IShellFolder_BindToObject(lpsf
, pidl
, 0, &IID_IShellFolder
, (LPVOID
*)&lpsfChild
)))
1903 ERR("bind to failed\n"); /* should not fail */
1906 IShellFolder_Release(lpsf
);
1914 /* end dialog, return value */
1915 nOpenAction
= ONOPEN_OPEN
;
1918 COMDLG32_SHFree(pidl
);
1921 else if (!(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1923 if(*lpszTemp
|| /* points to trailing null for last path element */
1924 (lpwstrTemp
[strlenW(lpwstrTemp
)-1] == '\\')) /* or if last element ends in '\' */
1926 if(fodInfos
->ofnInfos
->Flags
& OFN_PATHMUSTEXIST
)
1928 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_PATHNOTEXISTING
);
1934 if( (fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1935 !( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1937 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_FILENOTEXISTING
);
1941 /* change to the current folder */
1942 nOpenAction
= ONOPEN_OPEN
;
1947 nOpenAction
= ONOPEN_OPEN
;
1951 if(pidl
) COMDLG32_SHFree(pidl
);
1955 Step 3: here we have a cleaned up and validated path
1958 lpsf: ShellFolder bound to the rightmost valid path component
1959 lpstrPathAndFile: cleaned up path
1960 nOpenAction: action to do
1962 TRACE("end validate sf=%p\n", lpsf
);
1966 case ONOPEN_SEARCH
: /* set the current filter to the file mask and refresh */
1967 TRACE("ONOPEN_SEARCH %s\n", debugstr_w(lpstrPathAndFile
));
1970 LPWSTR lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
1973 /* replace the current filter */
1974 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1975 len
= lstrlenW(lpszTemp
)+1;
1976 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc(len
* sizeof(WCHAR
));
1977 lstrcpyW( fodInfos
->ShellInfos
.lpstrCurrentFilter
, lpszTemp
);
1979 /* set the filter cb to the extension when possible */
1980 if(-1 < (iPos
= FILEDLG95_FILETYPE_SearchExt(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpszTemp
)))
1981 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, iPos
);
1984 case ONOPEN_BROWSE
: /* browse to the highest folder we could bind to */
1985 TRACE("ONOPEN_BROWSE\n");
1987 IPersistFolder2
* ppf2
;
1988 if(SUCCEEDED(IShellFolder_QueryInterface( lpsf
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
)))
1990 LPITEMIDLIST pidlCurrent
;
1991 IPersistFolder2_GetCurFolder(ppf2
, &pidlCurrent
);
1992 IPersistFolder2_Release(ppf2
);
1993 if( ! COMDLG32_PIDL_ILIsEqual(pidlCurrent
, fodInfos
->ShellInfos
.pidlAbsCurrent
))
1995 if (SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidlCurrent
, SBSP_ABSOLUTE
)))
1997 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2000 else if( nOpenAction
== ONOPEN_SEARCH
)
2002 if (fodInfos
->Shell
.FOIShellView
)
2003 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
2005 COMDLG32_SHFree(pidlCurrent
);
2006 SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, EM_SETSEL
, 0, -1);
2011 case ONOPEN_OPEN
: /* fill in the return struct and close the dialog */
2012 TRACE("ONOPEN_OPEN %s\n", debugstr_w(lpstrPathAndFile
));
2016 /* update READONLY check box flag */
2017 if ((SendMessageW(GetDlgItem(hwnd
,IDC_OPENREADONLY
),BM_GETCHECK
,0,0) & 0x03) == BST_CHECKED
)
2018 fodInfos
->ofnInfos
->Flags
|= OFN_READONLY
;
2020 fodInfos
->ofnInfos
->Flags
&= ~OFN_READONLY
;
2022 /* Attach the file extension with file name*/
2023 ext
= PathFindExtensionW(lpstrPathAndFile
);
2026 /* if no extension is specified with file name, then */
2027 /* attach the extension from file filter or default one */
2029 WCHAR
*filterExt
= NULL
;
2030 LPWSTR lpstrFilter
= NULL
;
2031 static const WCHAR szwDot
[] = {'.',0};
2032 int PathLength
= lstrlenW(lpstrPathAndFile
);
2035 lstrcatW(lpstrPathAndFile
, szwDot
);
2037 /*Get the file extension from file type filter*/
2038 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2039 fodInfos
->ofnInfos
->nFilterIndex
-1);
2041 if (lpstrFilter
!= (LPWSTR
)CB_ERR
) /* control is not empty */
2042 filterExt
= PathFindExtensionW(lpstrFilter
);
2044 if ( filterExt
&& *filterExt
) /* attach the file extension from file type filter*/
2045 lstrcatW(lpstrPathAndFile
, filterExt
+ 1);
2046 else if ( fodInfos
->defext
) /* attach the default file extension*/
2047 lstrcatW(lpstrPathAndFile
, fodInfos
->defext
);
2049 /* In Open dialog: if file does not exist try without extension */
2050 if (!(fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) && !PathFileExistsW(lpstrPathAndFile
))
2051 lpstrPathAndFile
[PathLength
] = '\0';
2054 if (fodInfos
->defext
) /* add default extension */
2056 /* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
2059 if (!lstrcmpiW(fodInfos
->defext
, ext
))
2060 fodInfos
->ofnInfos
->Flags
&= ~OFN_EXTENSIONDIFFERENT
;
2062 fodInfos
->ofnInfos
->Flags
|= OFN_EXTENSIONDIFFERENT
;
2065 /* In Save dialog: check if the file already exists */
2066 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
2067 && fodInfos
->ofnInfos
->Flags
& OFN_OVERWRITEPROMPT
2068 && PathFileExistsW(lpstrPathAndFile
))
2070 WCHAR lpstrOverwrite
[100];
2073 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, lpstrOverwrite
, 100);
2074 answer
= MessageBoxW(hwnd
, lpstrOverwrite
, fodInfos
->title
,
2075 MB_YESNO
| MB_ICONEXCLAMATION
);
2083 /* In Open dialog: check if it should be created if it doesn't exist */
2084 if (!(fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
2085 && fodInfos
->ofnInfos
->Flags
& OFN_CREATEPROMPT
2086 && !PathFileExistsW(lpstrPathAndFile
))
2088 WCHAR lpstrCreate
[100];
2091 LoadStringW(COMDLG32_hInstance
, IDS_CREATEFILE
, lpstrCreate
, 100);
2092 answer
= MessageBoxW(hwnd
, lpstrCreate
, fodInfos
->title
,
2093 MB_YESNO
| MB_ICONEXCLAMATION
);
2101 /* Check that the size of the file does not exceed buffer size.
2102 (Allow for extra \0 if OFN_MULTISELECT is set.) */
2103 if(lstrlenW(lpstrPathAndFile
) < fodInfos
->ofnInfos
->nMaxFile
-
2104 ((fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
) ? 1 : 0))
2107 /* fill destination buffer */
2108 if (fodInfos
->ofnInfos
->lpstrFile
)
2110 if(fodInfos
->unicode
)
2112 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
2114 lstrcpynW(ofn
->lpstrFile
, lpstrPathAndFile
, ofn
->nMaxFile
);
2115 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
2116 ofn
->lpstrFile
[lstrlenW(ofn
->lpstrFile
) + 1] = '\0';
2120 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2122 WideCharToMultiByte(CP_ACP
, 0, lpstrPathAndFile
, -1,
2123 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
2124 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
2125 ofn
->lpstrFile
[lstrlenA(ofn
->lpstrFile
) + 1] = '\0';
2129 if(fodInfos
->unicode
)
2133 /* set filename offset */
2134 lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
2135 fodInfos
->ofnInfos
->nFileOffset
= (lpszTemp
- lpstrPathAndFile
);
2137 /* set extension offset */
2138 lpszTemp
= PathFindExtensionW(lpstrPathAndFile
);
2139 fodInfos
->ofnInfos
->nFileExtension
= (*lpszTemp
) ? (lpszTemp
- lpstrPathAndFile
) + 1 : 0;
2144 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2146 /* set filename offset */
2147 lpszTemp
= PathFindFileNameA(ofn
->lpstrFile
);
2148 fodInfos
->ofnInfos
->nFileOffset
= (lpszTemp
- ofn
->lpstrFile
);
2150 /* set extension offset */
2151 lpszTemp
= PathFindExtensionA(ofn
->lpstrFile
);
2152 fodInfos
->ofnInfos
->nFileExtension
= (*lpszTemp
) ? (lpszTemp
- ofn
->lpstrFile
) + 1 : 0;
2155 /* set the lpstrFileTitle */
2156 if(fodInfos
->ofnInfos
->lpstrFileTitle
)
2158 LPWSTR lpstrFileTitle
= PathFindFileNameW(lpstrPathAndFile
);
2159 if(fodInfos
->unicode
)
2161 LPOPENFILENAMEW ofn
= fodInfos
->ofnInfos
;
2162 lstrcpynW(ofn
->lpstrFileTitle
, lpstrFileTitle
, ofn
->nMaxFileTitle
);
2166 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2167 WideCharToMultiByte(CP_ACP
, 0, lpstrFileTitle
, -1,
2168 ofn
->lpstrFileTitle
, ofn
->nMaxFileTitle
, NULL
, NULL
);
2172 /* copy currently selected filter to lpstrCustomFilter */
2173 if (fodInfos
->ofnInfos
->lpstrCustomFilter
)
2175 LPOPENFILENAMEA ofn
= (LPOPENFILENAMEA
)fodInfos
->ofnInfos
;
2176 int len
= WideCharToMultiByte(CP_ACP
, 0, fodInfos
->ShellInfos
.lpstrCurrentFilter
, -1,
2177 NULL
, 0, NULL
, NULL
);
2178 if (len
+ strlen(ofn
->lpstrCustomFilter
) + 1 <= ofn
->nMaxCustFilter
)
2180 LPSTR s
= ofn
->lpstrCustomFilter
;
2181 s
+= strlen(ofn
->lpstrCustomFilter
)+1;
2182 WideCharToMultiByte(CP_ACP
, 0, fodInfos
->ShellInfos
.lpstrCurrentFilter
, -1,
2183 s
, len
, NULL
, NULL
);
2188 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
2192 FILEDLG95_Clean(hwnd
);
2193 ret
= EndDialog(hwnd
, TRUE
);
2199 size
= lstrlenW(lpstrPathAndFile
) + 1;
2200 if (fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
)
2202 /* return needed size in first two bytes of lpstrFile */
2203 *(WORD
*)fodInfos
->ofnInfos
->lpstrFile
= size
;
2204 FILEDLG95_Clean(hwnd
);
2205 ret
= EndDialog(hwnd
, FALSE
);
2206 COMDLG32_SetCommDlgExtendedError(FNERR_BUFFERTOOSMALL
);
2214 if(lpsf
) IShellFolder_Release(lpsf
);
2218 /***********************************************************************
2219 * FILEDLG95_SHELL_Init
2221 * Initialisation of the shell objects
2223 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
)
2225 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2230 * Initialisation of the FileOpenDialogInfos structure
2236 fodInfos
->ShellInfos
.hwndOwner
= hwnd
;
2238 /* Disable multi-select if flag not set */
2239 if (!(fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
))
2241 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_SINGLESEL
;
2243 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_AUTOARRANGE
| FWF_ALIGNLEFT
;
2244 fodInfos
->ShellInfos
.folderSettings
.ViewMode
= FVM_LIST
;
2246 /* Construct the IShellBrowser interface */
2247 fodInfos
->Shell
.FOIShellBrowser
= IShellBrowserImpl_Construct(hwnd
);
2252 /***********************************************************************
2253 * FILEDLG95_SHELL_ExecuteCommand
2255 * Change the folder option and refresh the view
2256 * If the function succeeds, the return value is nonzero.
2258 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
)
2260 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2263 TRACE("(%p,%p)\n", hwnd
, lpVerb
);
2265 if(SUCCEEDED(IShellView_GetItemObject(fodInfos
->Shell
.FOIShellView
,
2270 CMINVOKECOMMANDINFO ci
;
2271 ZeroMemory(&ci
, sizeof(CMINVOKECOMMANDINFO
));
2272 ci
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
2276 IContextMenu_InvokeCommand(pcm
, &ci
);
2277 IContextMenu_Release(pcm
);
2283 /***********************************************************************
2284 * FILEDLG95_SHELL_UpFolder
2286 * Browse to the specified object
2287 * If the function succeeds, the return value is nonzero.
2289 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
)
2291 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2295 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2299 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2305 /***********************************************************************
2306 * FILEDLG95_SHELL_BrowseToDesktop
2308 * Browse to the Desktop
2309 * If the function succeeds, the return value is nonzero.
2311 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
)
2313 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2319 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidl
);
2320 hres
= IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidl
, SBSP_ABSOLUTE
);
2321 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2322 COMDLG32_SHFree(pidl
);
2323 return SUCCEEDED(hres
);
2325 /***********************************************************************
2326 * FILEDLG95_SHELL_Clean
2328 * Cleans the memory used by shell objects
2330 static void FILEDLG95_SHELL_Clean(HWND hwnd
)
2332 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2336 COMDLG32_SHFree(fodInfos
->ShellInfos
.pidlAbsCurrent
);
2338 /* clean Shell interfaces */
2339 if (fodInfos
->Shell
.FOIShellView
)
2341 IShellView_DestroyViewWindow(fodInfos
->Shell
.FOIShellView
);
2342 IShellView_Release(fodInfos
->Shell
.FOIShellView
);
2344 IShellFolder_Release(fodInfos
->Shell
.FOIShellFolder
);
2345 IShellBrowser_Release(fodInfos
->Shell
.FOIShellBrowser
);
2346 if (fodInfos
->Shell
.FOIDataObject
)
2347 IDataObject_Release(fodInfos
->Shell
.FOIDataObject
);
2350 /***********************************************************************
2351 * FILEDLG95_FILETYPE_Init
2353 * Initialisation of the file type combo box
2355 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
)
2357 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2358 int nFilters
= 0; /* number of filters */
2363 if(fodInfos
->customfilter
)
2365 /* customfilter has one entry... title\0ext\0
2366 * Set first entry of combo box item with customfilter
2369 LPCWSTR lpstrPos
= fodInfos
->customfilter
;
2372 lpstrPos
+= lstrlenW(fodInfos
->customfilter
) + 1;
2374 /* Copy the extensions */
2375 if (! *lpstrPos
) return E_FAIL
; /* malformed filter */
2376 if (!(lpstrExt
= MemAlloc((lstrlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2377 lstrcpyW(lpstrExt
,lpstrPos
);
2379 /* Add the item at the end of the combo */
2380 CBAddString(fodInfos
->DlgInfos
.hwndFileTypeCB
, fodInfos
->customfilter
);
2381 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
, lpstrExt
);
2384 if(fodInfos
->filter
)
2386 LPCWSTR lpstrPos
= fodInfos
->filter
;
2390 /* filter is a list... title\0ext\0......\0\0
2391 * Set the combo item text to the title and the item data
2394 LPCWSTR lpstrDisplay
;
2398 if(! *lpstrPos
) break; /* end */
2399 lpstrDisplay
= lpstrPos
;
2400 lpstrPos
+= lstrlenW(lpstrPos
) + 1;
2402 CBAddString(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpstrDisplay
);
2406 /* Copy the extensions */
2407 if (!(lpstrExt
= MemAlloc((lstrlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2408 lstrcpyW(lpstrExt
,lpstrPos
);
2409 lpstrPos
+= lstrlenW(lpstrPos
) + 1;
2411 /* Add the item at the end of the combo */
2412 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
-1, lpstrExt
);
2414 /* malformed filters are added anyway... */
2415 if (!*lpstrExt
) break;
2420 * Set the current filter to the one specified
2421 * in the initialisation structure
2423 if (fodInfos
->filter
|| fodInfos
->customfilter
)
2427 /* Check to make sure our index isn't out of bounds. */
2428 if ( fodInfos
->ofnInfos
->nFilterIndex
>
2429 nFilters
- (fodInfos
->customfilter
== NULL
? 0 : 1) )
2430 fodInfos
->ofnInfos
->nFilterIndex
= (fodInfos
->customfilter
== NULL
? 1 : 0);
2432 /* set default filter index */
2433 if(fodInfos
->ofnInfos
->nFilterIndex
== 0 && fodInfos
->customfilter
== NULL
)
2434 fodInfos
->ofnInfos
->nFilterIndex
= 1;
2436 /* calculate index of Combo Box item */
2437 nFilterIndexCB
= fodInfos
->ofnInfos
->nFilterIndex
;
2438 if (fodInfos
->customfilter
== NULL
)
2441 /* Set the current index selection. */
2442 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilterIndexCB
);
2444 /* Get the corresponding text string from the combo box. */
2445 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2448 if ((INT_PTR
)lpstrFilter
== CB_ERR
) /* control is empty */
2454 CharLowerW(lpstrFilter
); /* lowercase */
2455 len
= lstrlenW(lpstrFilter
)+1;
2456 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2457 lstrcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2460 fodInfos
->ofnInfos
->nFilterIndex
= 0;
2464 /***********************************************************************
2465 * FILEDLG95_FILETYPE_OnCommand
2467 * WM_COMMAND of the file type combo box
2468 * If the function succeeds, the return value is nonzero.
2470 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2472 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2480 /* Get the current item of the filetype combo box */
2481 int iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2483 /* set the current filter index */
2484 fodInfos
->ofnInfos
->nFilterIndex
= iItem
+
2485 (fodInfos
->customfilter
== NULL
? 1 : 0);
2487 /* Set the current filter with the current selection */
2488 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2490 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2492 if((INT_PTR
)lpstrFilter
!= CB_ERR
)
2495 CharLowerW(lpstrFilter
); /* lowercase */
2496 len
= lstrlenW(lpstrFilter
)+1;
2497 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2498 lstrcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2499 SendCustomDlgNotificationMessage(hwnd
,CDN_TYPECHANGE
);
2502 /* Refresh the actual view to display the included items*/
2503 if (fodInfos
->Shell
.FOIShellView
)
2504 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
2509 /***********************************************************************
2510 * FILEDLG95_FILETYPE_SearchExt
2512 * searches for an extension in the filetype box
2514 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
)
2516 int i
, iCount
= CBGetCount(hwnd
);
2518 TRACE("%s\n", debugstr_w(lpstrExt
));
2520 if(iCount
!= CB_ERR
)
2522 for(i
=0;i
<iCount
;i
++)
2524 if(!lstrcmpiW(lpstrExt
,(LPWSTR
)CBGetItemDataPtr(hwnd
,i
)))
2531 /***********************************************************************
2532 * FILEDLG95_FILETYPE_Clean
2534 * Clean the memory used by the filetype combo box
2536 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
)
2538 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2540 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2544 /* Delete each string of the combo and their associated data */
2545 if(iCount
!= CB_ERR
)
2547 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2549 MemFree((LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
));
2550 CBDeleteString(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
2553 /* Current filter */
2554 MemFree(fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2558 /***********************************************************************
2559 * FILEDLG95_LOOKIN_Init
2561 * Initialisation of the look in combo box
2564 /* Small helper function, to determine if the unixfs shell extension is rooted
2565 * at the desktop. Copied from dlls/shell32/shfldr_unixfs.c.
2567 static inline BOOL
FILEDLG95_unixfs_is_rooted_at_desktop(void) {
2569 static const WCHAR wszRootedAtDesktop
[] = { 'S','o','f','t','w','a','r','e','\\',
2570 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2571 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2572 'E','x','p','l','o','r','e','r','\\','D','e','s','k','t','o','p','\\',
2573 'N','a','m','e','S','p','a','c','e','\\','{','9','D','2','0','A','A','E','8',
2574 '-','0','6','2','5','-','4','4','B','0','-','9','C','A','7','-',
2575 '7','1','8','8','9','C','2','2','5','4','D','9','}',0 };
2577 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, wszRootedAtDesktop
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
2584 static void FILEDLG95_LOOKIN_Init(HWND hwndCombo
)
2586 IShellFolder
*psfRoot
, *psfDrives
;
2587 IEnumIDList
*lpeRoot
, *lpeDrives
;
2588 LPITEMIDLIST pidlDrives
, pidlTmp
, pidlTmp1
, pidlAbsTmp
;
2590 LookInInfos
*liInfos
= MemAlloc(sizeof(LookInInfos
));
2594 liInfos
->iMaxIndentation
= 0;
2596 SetPropA(hwndCombo
, LookInInfosStr
, (HANDLE
) liInfos
);
2598 /* set item height for both text field and listbox */
2599 CBSetItemHeight(hwndCombo
,-1,GetSystemMetrics(SM_CYSMICON
));
2600 CBSetItemHeight(hwndCombo
,0,GetSystemMetrics(SM_CYSMICON
));
2602 /* Turn on the extended UI for the combo box like Windows does */
2603 CBSetExtendedUI(hwndCombo
, TRUE
);
2605 /* Initialise data of Desktop folder */
2606 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidlTmp
);
2607 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2608 COMDLG32_SHFree(pidlTmp
);
2610 SHGetSpecialFolderLocation(0,CSIDL_DRIVES
,&pidlDrives
);
2612 SHGetDesktopFolder(&psfRoot
);
2616 /* enumerate the contents of the desktop */
2617 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot
, hwndCombo
, SHCONTF_FOLDERS
, &lpeRoot
)))
2619 while (S_OK
== IEnumIDList_Next(lpeRoot
, 1, &pidlTmp
, NULL
))
2621 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2623 /* If the unixfs extension is rooted, we don't expand the drives by default */
2624 if (!FILEDLG95_unixfs_is_rooted_at_desktop())
2626 /* special handling for CSIDL_DRIVES */
2627 if (COMDLG32_PIDL_ILIsEqual(pidlTmp
, pidlDrives
))
2629 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot
, pidlTmp
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfDrives
)))
2631 /* enumerate the drives */
2632 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives
, hwndCombo
,SHCONTF_FOLDERS
, &lpeDrives
)))
2634 while (S_OK
== IEnumIDList_Next(lpeDrives
, 1, &pidlTmp1
, NULL
))
2636 pidlAbsTmp
= COMDLG32_PIDL_ILCombine(pidlTmp
, pidlTmp1
);
2637 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlAbsTmp
,LISTEND
);
2638 COMDLG32_SHFree(pidlAbsTmp
);
2639 COMDLG32_SHFree(pidlTmp1
);
2641 IEnumIDList_Release(lpeDrives
);
2643 IShellFolder_Release(psfDrives
);
2648 COMDLG32_SHFree(pidlTmp
);
2650 IEnumIDList_Release(lpeRoot
);
2652 IShellFolder_Release(psfRoot
);
2655 COMDLG32_SHFree(pidlDrives
);
2658 /***********************************************************************
2659 * FILEDLG95_LOOKIN_DrawItem
2661 * WM_DRAWITEM message handler
2663 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
)
2665 COLORREF crWin
= GetSysColor(COLOR_WINDOW
);
2666 COLORREF crHighLight
= GetSysColor(COLOR_HIGHLIGHT
);
2667 COLORREF crText
= GetSysColor(COLOR_WINDOWTEXT
);
2671 HIMAGELIST ilItemImage
;
2674 LPSFOLDER tmpFolder
;
2677 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(pDIStruct
->hwndItem
,LookInInfosStr
);
2681 if(pDIStruct
->itemID
== -1)
2684 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(pDIStruct
->hwndItem
,
2685 pDIStruct
->itemID
)))
2689 if(pDIStruct
->itemID
== liInfos
->uSelectedItem
)
2691 ilItemImage
= (HIMAGELIST
) SHGetFileInfoW ((LPCWSTR
) tmpFolder
->pidlItem
,
2695 SHGFI_PIDL
| SHGFI_SMALLICON
|
2696 SHGFI_OPENICON
| SHGFI_SYSICONINDEX
|
2697 SHGFI_DISPLAYNAME
);
2701 ilItemImage
= (HIMAGELIST
) SHGetFileInfoW ((LPCWSTR
) tmpFolder
->pidlItem
,
2705 SHGFI_PIDL
| SHGFI_SMALLICON
|
2706 SHGFI_SYSICONINDEX
|
2710 /* Is this item selected ? */
2711 if(pDIStruct
->itemState
& ODS_SELECTED
)
2713 SetTextColor(pDIStruct
->hDC
,(0x00FFFFFF & ~(crText
)));
2714 SetBkColor(pDIStruct
->hDC
,crHighLight
);
2715 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_HIGHLIGHT
));
2719 SetTextColor(pDIStruct
->hDC
,crText
);
2720 SetBkColor(pDIStruct
->hDC
,crWin
);
2721 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_WINDOW
));
2724 /* Do not indent item if drawing in the edit of the combo */
2725 if(pDIStruct
->itemState
& ODS_COMBOBOXEDIT
)
2728 ilItemImage
= (HIMAGELIST
) SHGetFileInfoW ((LPCWSTR
) tmpFolder
->pidlItem
,
2732 SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_OPENICON
2733 | SHGFI_SYSICONINDEX
| SHGFI_DISPLAYNAME
);
2738 iIndentation
= tmpFolder
->m_iIndent
;
2740 /* Draw text and icon */
2742 /* Initialise the icon display area */
2743 rectIcon
.left
= pDIStruct
->rcItem
.left
+ ICONWIDTH
/2 * iIndentation
;
2744 rectIcon
.top
= pDIStruct
->rcItem
.top
;
2745 rectIcon
.right
= rectIcon
.left
+ ICONWIDTH
;
2746 rectIcon
.bottom
= pDIStruct
->rcItem
.bottom
;
2748 /* Initialise the text display area */
2749 GetTextMetricsW(pDIStruct
->hDC
, &tm
);
2750 rectText
.left
= rectIcon
.right
;
2752 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
- tm
.tmHeight
) / 2;
2753 rectText
.right
= pDIStruct
->rcItem
.right
+ XTEXTOFFSET
;
2755 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
+ tm
.tmHeight
) / 2;
2757 /* Draw the icon from the image list */
2758 ImageList_Draw(ilItemImage
,
2765 /* Draw the associated text */
2766 if(sfi
.szDisplayName
)
2767 TextOutW(pDIStruct
->hDC
,rectText
.left
,rectText
.top
,sfi
.szDisplayName
,lstrlenW(sfi
.szDisplayName
));
2773 /***********************************************************************
2774 * FILEDLG95_LOOKIN_OnCommand
2776 * LookIn combo box WM_COMMAND message handler
2777 * If the function succeeds, the return value is nonzero.
2779 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2781 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2783 TRACE("%p\n", fodInfos
);
2789 LPSFOLDER tmpFolder
;
2792 iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndLookInCB
);
2794 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,
2799 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2800 tmpFolder
->pidlItem
,
2803 SendCustomDlgNotificationMessage(hwnd
, CDN_FOLDERCHANGE
);
2813 /***********************************************************************
2814 * FILEDLG95_LOOKIN_AddItem
2816 * Adds an absolute pidl item to the lookin combo box
2817 * returns the index of the inserted item
2819 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
)
2821 LPITEMIDLIST pidlNext
;
2824 LookInInfos
*liInfos
;
2826 TRACE("%08x\n", iInsertId
);
2831 if(!(liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
)))
2834 tmpFolder
= MemAlloc(sizeof(SFOLDER
));
2835 tmpFolder
->m_iIndent
= 0;
2837 /* Calculate the indentation of the item in the lookin*/
2839 while( (pidlNext
=COMDLG32_PIDL_ILGetNext(pidlNext
)) )
2841 tmpFolder
->m_iIndent
++;
2844 tmpFolder
->pidlItem
= COMDLG32_PIDL_ILClone(pidl
);
2846 if(tmpFolder
->m_iIndent
> liInfos
->iMaxIndentation
)
2847 liInfos
->iMaxIndentation
= tmpFolder
->m_iIndent
;
2849 sfi
.dwAttributes
= SFGAO_FILESYSANCESTOR
| SFGAO_FILESYSTEM
;
2850 SHGetFileInfoW((LPCWSTR
)pidl
,
2854 SHGFI_DISPLAYNAME
| SHGFI_SYSICONINDEX
2855 | SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_ATTRIBUTES
| SHGFI_ATTR_SPECIFIED
);
2857 TRACE("-- Add %s attr=%08x\n", debugstr_w(sfi
.szDisplayName
), sfi
.dwAttributes
);
2859 if((sfi
.dwAttributes
& SFGAO_FILESYSANCESTOR
) || (sfi
.dwAttributes
& SFGAO_FILESYSTEM
))
2863 TRACE("-- Add %s at %u\n", debugstr_w(sfi
.szDisplayName
), tmpFolder
->m_iIndent
);
2865 /* Add the item at the end of the list */
2868 iItemID
= CBAddString(hwnd
,sfi
.szDisplayName
);
2870 /* Insert the item at the iInsertId position*/
2873 iItemID
= CBInsertString(hwnd
,sfi
.szDisplayName
,iInsertId
);
2876 CBSetItemDataPtr(hwnd
,iItemID
,tmpFolder
);
2880 COMDLG32_SHFree( tmpFolder
->pidlItem
);
2881 MemFree( tmpFolder
);
2886 /***********************************************************************
2887 * FILEDLG95_LOOKIN_InsertItemAfterParent
2889 * Insert an item below its parent
2891 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
)
2894 LPITEMIDLIST pidlParent
= GetParentPidl(pidl
);
2899 iParentPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidlParent
,SEARCH_PIDL
);
2903 iParentPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidlParent
);
2906 /* Free pidlParent memory */
2907 COMDLG32_SHFree((LPVOID
)pidlParent
);
2909 return FILEDLG95_LOOKIN_AddItem(hwnd
,pidl
,iParentPos
+ 1);
2912 /***********************************************************************
2913 * FILEDLG95_LOOKIN_SelectItem
2915 * Adds an absolute pidl item to the lookin combo box
2916 * returns the index of the inserted item
2918 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
)
2921 LookInInfos
*liInfos
;
2925 iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidl
,SEARCH_PIDL
);
2927 liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2931 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
) > -1);
2932 iItemPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidl
);
2937 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2938 while(liInfos
->iMaxIndentation
> tmpFolder
->m_iIndent
)
2942 if(-1 == (iRemovedItem
= FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
)))
2944 if(iRemovedItem
< iItemPos
)
2949 CBSetCurSel(hwnd
,iItemPos
);
2950 liInfos
->uSelectedItem
= iItemPos
;
2956 /***********************************************************************
2957 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2959 * Remove the item with an expansion level over iExpansionLevel
2961 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
)
2965 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2969 if(liInfos
->iMaxIndentation
<= 2)
2972 if((iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)liInfos
->iMaxIndentation
,SEARCH_EXP
)) >=0)
2974 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2975 COMDLG32_SHFree(tmpFolder
->pidlItem
);
2977 CBDeleteString(hwnd
,iItemPos
);
2978 liInfos
->iMaxIndentation
--;
2986 /***********************************************************************
2987 * FILEDLG95_LOOKIN_SearchItem
2989 * Search for pidl in the lookin combo box
2990 * returns the index of the found item
2992 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
)
2995 int iCount
= CBGetCount(hwnd
);
2997 TRACE("0x%08lx 0x%x\n",searchArg
, iSearchMethod
);
2999 if (iCount
!= CB_ERR
)
3003 LPSFOLDER tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,i
);
3005 if(iSearchMethod
== SEARCH_PIDL
&& COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST
)searchArg
,tmpFolder
->pidlItem
))
3007 if(iSearchMethod
== SEARCH_EXP
&& tmpFolder
->m_iIndent
== (int)searchArg
)
3015 /***********************************************************************
3016 * FILEDLG95_LOOKIN_Clean
3018 * Clean the memory used by the lookin combo box
3020 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
)
3022 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3024 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndLookInCB
);
3028 /* Delete each string of the combo and their associated data */
3029 if (iCount
!= CB_ERR
)
3031 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
3033 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
3034 COMDLG32_SHFree(tmpFolder
->pidlItem
);
3036 CBDeleteString(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
3040 /* LookInInfos structure */
3041 RemovePropA(fodInfos
->DlgInfos
.hwndLookInCB
,LookInInfosStr
);
3044 /***********************************************************************
3045 * FILEDLG95_FILENAME_FillFromSelection
3047 * fills the edit box from the cached DataObject
3049 void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd
)
3051 FileOpenDlgInfos
*fodInfos
;
3053 UINT nFiles
= 0, nFileToOpen
, nFileSelected
, nLength
= 0;
3054 WCHAR lpstrTemp
[MAX_PATH
];
3055 LPWSTR lpstrAllFile
, lpstrCurrFile
;
3058 fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3060 /* Count how many files we have */
3061 nFileSelected
= GetNumSelected( fodInfos
->Shell
.FOIDataObject
);
3063 /* calculate the string length, count files */
3064 if (nFileSelected
>= 1)
3066 nLength
+= 3; /* first and last quotes, trailing \0 */
3067 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
3069 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
3073 /* get the total length of the selected file names */
3074 lpstrTemp
[0] = '\0';
3075 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
3077 if ( ! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
) ) /* Ignore folders */
3079 nLength
+= lstrlenW( lpstrTemp
) + 3;
3082 COMDLG32_SHFree( pidl
);
3087 /* allocate the buffer */
3088 if (nFiles
<= 1) nLength
= MAX_PATH
;
3089 lpstrAllFile
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nLength
* sizeof(WCHAR
));
3091 /* Generate the string for the edit control */
3094 lpstrCurrFile
= lpstrAllFile
;
3095 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
3097 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
3101 /* get the file name */
3102 lpstrTemp
[0] = '\0';
3103 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
3105 if (! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
)) /* Ignore folders */
3109 *lpstrCurrFile
++ = '\"';
3110 lstrcpyW( lpstrCurrFile
, lpstrTemp
);
3111 lpstrCurrFile
+= lstrlenW( lpstrTemp
);
3112 *lpstrCurrFile
++ = '\"';
3113 *lpstrCurrFile
++ = ' ';
3118 lstrcpyW( lpstrAllFile
, lpstrTemp
);
3121 COMDLG32_SHFree( (LPVOID
) pidl
);
3124 SetWindowTextW( fodInfos
->DlgInfos
.hwndFileName
, lpstrAllFile
);
3126 /* Select the file name like Windows does */
3127 SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, EM_SETSEL
, 0, (LPARAM
)-1);
3129 HeapFree(GetProcessHeap(),0, lpstrAllFile
);
3133 /* copied from shell32 to avoid linking to it
3134 * Although shell32 is already linked the behaviour of exported StrRetToStrN
3135 * is dependent on whether emulated OS is unicode or not.
3137 static HRESULT
COMDLG32_StrRetToStrNW (LPWSTR dest
, DWORD len
, LPSTRRET src
, LPITEMIDLIST pidl
)
3142 lstrcpynW(dest
, src
->u
.pOleStr
, len
);
3143 COMDLG32_SHFree(src
->u
.pOleStr
);
3147 if (!MultiByteToWideChar( CP_ACP
, 0, src
->u
.cStr
, -1, dest
, len
) && len
)
3152 if (!MultiByteToWideChar( CP_ACP
, 0, ((LPCSTR
)&pidl
->mkid
)+src
->u
.uOffset
, -1, dest
, len
) && len
)
3157 FIXME("unknown type %x!\n", src
->uType
);
3158 if (len
) *dest
= '\0';
3164 /***********************************************************************
3165 * FILEDLG95_FILENAME_GetFileNames
3167 * Copies the filenames to a delimited string list.
3168 * The delimiter is specified by the parameter 'separator',
3169 * usually either a space or a nul
3171 static int FILEDLG95_FILENAME_GetFileNames (HWND hwnd
, LPWSTR
* lpstrFileList
, UINT
* sizeUsed
)
3173 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3174 UINT nStrCharCount
= 0; /* index in src buffer */
3175 UINT nFileIndex
= 0; /* index in dest buffer */
3176 UINT nFileCount
= 0; /* number of files */
3177 UINT nStrLen
= 0; /* length of string in edit control */
3178 LPWSTR lpstrEdit
; /* buffer for string from edit control */
3182 /* get the filenames from the edit control */
3183 nStrLen
= SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXTLENGTH
, 0, 0);
3184 lpstrEdit
= MemAlloc( (nStrLen
+1)*sizeof(WCHAR
) );
3185 GetDlgItemTextW(hwnd
, IDC_FILENAME
, lpstrEdit
, nStrLen
+1);
3187 TRACE("nStrLen=%u str=%s\n", nStrLen
, debugstr_w(lpstrEdit
));
3189 /* we might get single filename without any '"',
3190 * so we need nStrLen + terminating \0 + end-of-list \0 */
3191 *lpstrFileList
= MemAlloc( (nStrLen
+2)*sizeof(WCHAR
) );
3194 /* build delimited file list from filenames */
3195 while ( nStrCharCount
<= nStrLen
)
3197 if ( lpstrEdit
[nStrCharCount
]=='"' )
3200 while ((lpstrEdit
[nStrCharCount
]!='"') && (nStrCharCount
<= nStrLen
))
3202 (*lpstrFileList
)[nFileIndex
++] = lpstrEdit
[nStrCharCount
];
3205 (*lpstrFileList
)[nFileIndex
++] = 0;
3211 /* single, unquoted string */
3212 if ((nStrLen
> 0) && (nFileIndex
== 0) )
3214 lstrcpyW(*lpstrFileList
, lpstrEdit
);
3215 nFileIndex
= lstrlenW(lpstrEdit
) + 1;
3220 (*lpstrFileList
)[nFileIndex
++] = '\0';
3222 *sizeUsed
= nFileIndex
;
3227 #define SETDefFormatEtc(fe,cf,med) \
3229 (fe).cfFormat = cf;\
3230 (fe).dwAspect = DVASPECT_CONTENT; \
3237 * DATAOBJECT Helper functions
3240 /***********************************************************************
3241 * COMCTL32_ReleaseStgMedium
3243 * like ReleaseStgMedium from ole32
3245 static void COMCTL32_ReleaseStgMedium (STGMEDIUM medium
)
3247 if(medium
.pUnkForRelease
)
3249 IUnknown_Release(medium
.pUnkForRelease
);
3253 GlobalUnlock(medium
.u
.hGlobal
);
3254 GlobalFree(medium
.u
.hGlobal
);
3258 /***********************************************************************
3259 * GetPidlFromDataObject
3261 * Return pidl(s) by number from the cached DataObject
3263 * nPidlIndex=0 gets the fully qualified root path
3265 LPITEMIDLIST
GetPidlFromDataObject ( IDataObject
*doSelected
, UINT nPidlIndex
)
3269 FORMATETC formatetc
;
3270 LPITEMIDLIST pidl
= NULL
;
3272 TRACE("sv=%p index=%u\n", doSelected
, nPidlIndex
);
3277 /* Set the FORMATETC structure*/
3278 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLISTA
), TYMED_HGLOBAL
);
3280 /* Get the pidls from IDataObject */
3281 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3283 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3284 if(nPidlIndex
<= cida
->cidl
)
3286 pidl
= COMDLG32_PIDL_ILClone((LPITEMIDLIST
)(&((LPBYTE
)cida
)[cida
->aoffset
[nPidlIndex
]]));
3288 COMCTL32_ReleaseStgMedium(medium
);
3293 /***********************************************************************
3296 * Return the number of selected items in the DataObject.
3299 UINT
GetNumSelected( IDataObject
*doSelected
)
3303 FORMATETC formatetc
;
3305 TRACE("sv=%p\n", doSelected
);
3307 if (!doSelected
) return 0;
3309 /* Set the FORMATETC structure*/
3310 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLISTA
), TYMED_HGLOBAL
);
3312 /* Get the pidls from IDataObject */
3313 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3315 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3316 retVal
= cida
->cidl
;
3317 COMCTL32_ReleaseStgMedium(medium
);
3327 /***********************************************************************
3330 * Get the pidl's display name (relative to folder) and
3331 * put it in lpstrFileName.
3333 * Return NOERROR on success,
3337 static HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPWSTR lpstrFileName
)
3342 TRACE("sf=%p pidl=%p\n", lpsf
, pidl
);
3346 SHGetDesktopFolder(&lpsf
);
3347 hRes
= GetName(lpsf
,pidl
,dwFlags
,lpstrFileName
);
3348 IShellFolder_Release(lpsf
);
3352 /* Get the display name of the pidl relative to the folder */
3353 if (SUCCEEDED(hRes
= IShellFolder_GetDisplayNameOf(lpsf
, pidl
, dwFlags
, &str
)))
3355 return COMDLG32_StrRetToStrNW(lpstrFileName
, MAX_PATH
, &str
, pidl
);
3360 /***********************************************************************
3361 * GetShellFolderFromPidl
3363 * pidlRel is the item pidl relative
3364 * Return the IShellFolder of the absolute pidl
3366 IShellFolder
*GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
)
3368 IShellFolder
*psf
= NULL
,*psfParent
;
3370 TRACE("%p\n", pidlAbs
);
3372 if(SUCCEEDED(SHGetDesktopFolder(&psfParent
)))
3375 if(pidlAbs
&& pidlAbs
->mkid
.cb
)
3377 if(SUCCEEDED(IShellFolder_BindToObject(psfParent
, pidlAbs
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psf
)))
3379 IShellFolder_Release(psfParent
);
3383 /* return the desktop */
3389 /***********************************************************************
3392 * Return the LPITEMIDLIST to the parent of the pidl in the list
3394 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
)
3396 LPITEMIDLIST pidlParent
;
3398 TRACE("%p\n", pidl
);
3400 pidlParent
= COMDLG32_PIDL_ILClone(pidl
);
3401 COMDLG32_PIDL_ILRemoveLastID(pidlParent
);
3406 /***********************************************************************
3409 * returns the pidl of the file name relative to folder
3410 * NULL if an error occurred
3412 static LPITEMIDLIST
GetPidlFromName(IShellFolder
*lpsf
,LPWSTR lpcstrFileName
)
3414 LPITEMIDLIST pidl
= NULL
;
3417 TRACE("sf=%p file=%s\n", lpsf
, debugstr_w(lpcstrFileName
));
3419 if(!lpcstrFileName
) return NULL
;
3420 if(!*lpcstrFileName
) return NULL
;
3424 if (SUCCEEDED(SHGetDesktopFolder(&lpsf
))) {
3425 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3426 IShellFolder_Release(lpsf
);
3431 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3438 BOOL
IsPidlFolder (LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
)
3440 ULONG uAttr
= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
;
3443 TRACE("%p, %p\n", psf
, pidl
);
3445 ret
= IShellFolder_GetAttributesOf( psf
, 1, &pidl
, &uAttr
);
3447 TRACE("-- 0x%08x 0x%08x\n", uAttr
, ret
);
3448 /* see documentation shell 4.1*/
3449 return uAttr
& (SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
);
3452 /***********************************************************************
3453 * BrowseSelectedFolder
3455 static BOOL
BrowseSelectedFolder(HWND hwnd
)
3457 BOOL bBrowseSelFolder
= FALSE
;
3458 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3462 if (GetNumSelected(fodInfos
->Shell
.FOIDataObject
) == 1)
3464 LPITEMIDLIST pidlSelection
;
3466 /* get the file selected */
3467 pidlSelection
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, 1);
3468 if (IsPidlFolder (fodInfos
->Shell
.FOIShellFolder
, pidlSelection
))
3470 if ( FAILED( IShellBrowser_BrowseObject( fodInfos
->Shell
.FOIShellBrowser
,
3471 pidlSelection
, SBSP_RELATIVE
) ) )
3473 static const WCHAR notexist
[] = {'P','a','t','h',' ','d','o','e','s',
3474 ' ','n','o','t',' ','e','x','i','s','t',0};
3475 MessageBoxW( hwnd
, notexist
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
3477 bBrowseSelFolder
= TRUE
;
3478 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
3480 COMDLG32_SHFree( pidlSelection
);
3483 return bBrowseSelFolder
;
3487 * Memory allocation methods */
3488 static void *MemAlloc(UINT size
)
3490 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
3493 static void MemFree(void *mem
)
3495 HeapFree(GetProcessHeap(),0,mem
);
3499 * Old-style (win3.1) dialogs */
3501 /***********************************************************************
3502 * FD32_GetTemplate [internal]
3504 * Get a template (or FALSE if failure) when 16 bits dialogs are used
3505 * by a 32 bits application
3508 static BOOL
FD32_GetTemplate(PFD31_DATA lfs
)
3510 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3511 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3514 if (ofnW
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
3516 if (!(lfs
->template = LockResource( ofnW
->hInstance
)))
3518 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3522 else if (ofnW
->Flags
& OFN_ENABLETEMPLATE
)
3526 hResInfo
= FindResourceA(priv
->ofnA
->hInstance
,
3527 priv
->ofnA
->lpTemplateName
,
3530 hResInfo
= FindResourceW(ofnW
->hInstance
,
3531 ofnW
->lpTemplateName
,
3535 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
3538 if (!(hDlgTmpl
= LoadResource(ofnW
->hInstance
,
3540 !(lfs
->template = LockResource(hDlgTmpl
)))
3542 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3545 } else { /* get it from internal Wine resource */
3547 if (!(hResInfo
= FindResourceA(COMDLG32_hInstance
,
3548 lfs
->open
? "OPEN_FILE":"SAVE_FILE", (LPSTR
)RT_DIALOG
)))
3550 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
3553 if (!(hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hResInfo
)) ||
3554 !(lfs
->template = LockResource( hDlgTmpl
)))
3556 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
3564 /************************************************************************
3565 * FD32_Init [internal]
3566 * called from the common 16/32 code to initialize 32 bit data
3568 static BOOL CALLBACK
FD32_Init(LPARAM lParam
, PFD31_DATA lfs
, DWORD data
)
3570 BOOL IsUnicode
= (BOOL
) data
;
3573 priv
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FD32_PRIVATE
));
3574 lfs
->private1632
= priv
;
3575 if (NULL
== lfs
->private1632
) return FALSE
;
3578 lfs
->ofnW
= (LPOPENFILENAMEW
) lParam
;
3579 if (lfs
->ofnW
->Flags
& OFN_ENABLEHOOK
)
3580 if (lfs
->ofnW
->lpfnHook
)
3585 priv
->ofnA
= (LPOPENFILENAMEA
) lParam
;
3586 if (priv
->ofnA
->Flags
& OFN_ENABLEHOOK
)
3587 if (priv
->ofnA
->lpfnHook
)
3589 lfs
->ofnW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*lfs
->ofnW
));
3590 FD31_MapOfnStructA(priv
->ofnA
, lfs
->ofnW
, lfs
->open
);
3593 if (! FD32_GetTemplate(lfs
)) return FALSE
;
3598 /***********************************************************************
3599 * FD32_CallWindowProc [internal]
3601 * called from the common 16/32 code to call the appropriate hook
3603 static BOOL CALLBACK
FD32_CallWindowProc(const FD31_DATA
*lfs
, UINT wMsg
, WPARAM wParam
,
3607 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3611 TRACE("Call hookA %p (%p, %04x, %08lx, %08lx)\n",
3612 priv
->ofnA
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3613 ret
= priv
->ofnA
->lpfnHook(lfs
->hwnd
, wMsg
, wParam
, lParam
);
3614 TRACE("ret hookA %p (%p, %04x, %08lx, %08lx)\n",
3615 priv
->ofnA
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3619 TRACE("Call hookW %p (%p, %04x, %08lx, %08lx)\n",
3620 lfs
->ofnW
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3621 ret
= lfs
->ofnW
->lpfnHook(lfs
->hwnd
, wMsg
, wParam
, lParam
);
3622 TRACE("Ret hookW %p (%p, %04x, %08lx, %08lx)\n",
3623 lfs
->ofnW
->lpfnHook
, lfs
->hwnd
, wMsg
, wParam
, lParam
);
3627 /***********************************************************************
3628 * FD32_UpdateResult [internal]
3629 * update the real client structures if any
3631 static void CALLBACK
FD32_UpdateResult(const FD31_DATA
*lfs
)
3633 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3634 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3639 if (ofnW
->nMaxFile
&&
3640 !WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFile
, -1,
3641 priv
->ofnA
->lpstrFile
, ofnW
->nMaxFile
, NULL
, NULL
))
3642 priv
->ofnA
->lpstrFile
[ofnW
->nMaxFile
-1] = 0;
3644 /* offsets are not guaranteed to be the same in WCHAR to MULTIBYTE conversion */
3645 /* set filename offset */
3646 lpszTemp
= PathFindFileNameA(priv
->ofnA
->lpstrFile
);
3647 priv
->ofnA
->nFileOffset
= (lpszTemp
- priv
->ofnA
->lpstrFile
);
3649 /* set extension offset */
3650 lpszTemp
= PathFindExtensionA(priv
->ofnA
->lpstrFile
);
3651 priv
->ofnA
->nFileExtension
= (*lpszTemp
) ? (lpszTemp
- priv
->ofnA
->lpstrFile
) + 1 : 0;
3655 /***********************************************************************
3656 * FD32_UpdateFileTitle [internal]
3657 * update the real client structures if any
3659 static void CALLBACK
FD32_UpdateFileTitle(const FD31_DATA
*lfs
)
3661 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3662 LPOPENFILENAMEW ofnW
= lfs
->ofnW
;
3666 if (!WideCharToMultiByte( CP_ACP
, 0, ofnW
->lpstrFileTitle
, -1,
3667 priv
->ofnA
->lpstrFileTitle
, ofnW
->nMaxFileTitle
, NULL
, NULL
))
3668 priv
->ofnA
->lpstrFileTitle
[ofnW
->nMaxFileTitle
-1] = 0;
3673 /***********************************************************************
3674 * FD32_SendLbGetCurSel [internal]
3675 * retrieve selected listbox item
3677 static LRESULT CALLBACK
FD32_SendLbGetCurSel(const FD31_DATA
*lfs
)
3679 return SendDlgItemMessageW(lfs
->hwnd
, lst1
, LB_GETCURSEL
, 0, 0);
3683 /************************************************************************
3684 * FD32_Destroy [internal]
3685 * called from the common 16/32 code to cleanup 32 bit data
3687 static void CALLBACK
FD32_Destroy(const FD31_DATA
*lfs
)
3689 PFD32_PRIVATE priv
= (PFD32_PRIVATE
) lfs
->private1632
;
3691 /* if ofnW has been allocated, have to free everything in it */
3692 if (NULL
!= priv
&& NULL
!= priv
->ofnA
)
3694 FD31_FreeOfnW(lfs
->ofnW
);
3695 HeapFree(GetProcessHeap(), 0, lfs
->ofnW
);
3699 static void FD32_SetupCallbacks(PFD31_CALLBACKS callbacks
)
3701 callbacks
->Init
= FD32_Init
;
3702 callbacks
->CWP
= FD32_CallWindowProc
;
3703 callbacks
->UpdateResult
= FD32_UpdateResult
;
3704 callbacks
->UpdateFileTitle
= FD32_UpdateFileTitle
;
3705 callbacks
->SendLbGetCurSel
= FD32_SendLbGetCurSel
;
3706 callbacks
->Destroy
= FD32_Destroy
;
3709 /***********************************************************************
3710 * FD32_WMMeasureItem [internal]
3712 static LONG
FD32_WMMeasureItem(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
3714 LPMEASUREITEMSTRUCT lpmeasure
;
3716 lpmeasure
= (LPMEASUREITEMSTRUCT
)lParam
;
3717 lpmeasure
->itemHeight
= FD31_GetFldrHeight();
3722 /***********************************************************************
3723 * FileOpenDlgProc [internal]
3724 * Used for open and save, in fact.
3726 static INT_PTR CALLBACK
FD32_FileOpenDlgProc(HWND hWnd
, UINT wMsg
,
3727 WPARAM wParam
, LPARAM lParam
)
3729 PFD31_DATA lfs
= (PFD31_DATA
)GetPropA(hWnd
,FD31_OFN_PROP
);
3731 TRACE("msg=%x wparam=%lx lParam=%lx\n", wMsg
, wParam
, lParam
);
3732 if ((wMsg
!= WM_INITDIALOG
) && lfs
&& lfs
->hook
)
3735 lRet
= (INT_PTR
)FD31_CallWindowProc(lfs
, wMsg
, wParam
, lParam
);
3737 return lRet
; /* else continue message processing */
3742 return FD31_WMInitDialog(hWnd
, wParam
, lParam
);
3744 case WM_MEASUREITEM
:
3745 return FD32_WMMeasureItem(hWnd
, wParam
, lParam
);
3748 return FD31_WMDrawItem(hWnd
, wParam
, lParam
, !lfs
->open
, (DRAWITEMSTRUCT
*)lParam
);
3751 return FD31_WMCommand(hWnd
, lParam
, HIWORD(wParam
), LOWORD(wParam
), lfs
);
3754 SetBkColor((HDC16
)wParam
, 0x00C0C0C0);
3755 switch (HIWORD(lParam
))
3758 SetTextColor((HDC16
)wParam
, 0x00000000);
3760 case CTLCOLOR_STATIC
:
3761 SetTextColor((HDC16
)wParam
, 0x00000000);
3771 /***********************************************************************
3772 * GetFileName31A [internal]
3774 * Creates a win31 style dialog box for the user to select a file to open/save.
3776 static BOOL
GetFileName31A(LPOPENFILENAMEA lpofn
, /* address of structure with data*/
3777 UINT dlgType
/* type dialogue : open/save */
3783 FD31_CALLBACKS callbacks
;
3785 if (!lpofn
|| !FD31_Init()) return FALSE
;
3787 TRACE("ofn flags %08x\n", lpofn
->Flags
);
3788 FD32_SetupCallbacks(&callbacks
);
3789 lfs
= FD31_AllocPrivate((LPARAM
) lpofn
, dlgType
, &callbacks
, (DWORD
) FALSE
);
3792 hInst
= (HINSTANCE
)GetWindowLongPtrW( lpofn
->hwndOwner
, GWLP_HINSTANCE
);
3793 bRet
= DialogBoxIndirectParamA( hInst
, lfs
->template, lpofn
->hwndOwner
,
3794 FD32_FileOpenDlgProc
, (LPARAM
)lfs
);
3795 FD31_DestroyPrivate(lfs
);
3798 TRACE("return lpstrFile='%s' !\n", lpofn
->lpstrFile
);
3802 /***********************************************************************
3803 * GetFileName31W [internal]
3805 * Creates a win31 style dialog box for the user to select a file to open/save
3807 static BOOL
GetFileName31W(LPOPENFILENAMEW lpofn
, /* address of structure with data*/
3808 UINT dlgType
/* type dialogue : open/save */
3814 FD31_CALLBACKS callbacks
;
3816 if (!lpofn
|| !FD31_Init()) return FALSE
;
3818 FD32_SetupCallbacks(&callbacks
);
3819 lfs
= FD31_AllocPrivate((LPARAM
) lpofn
, dlgType
, &callbacks
, (DWORD
) TRUE
);
3822 hInst
= (HINSTANCE
)GetWindowLongPtrW( lpofn
->hwndOwner
, GWLP_HINSTANCE
);
3823 bRet
= DialogBoxIndirectParamW( hInst
, lfs
->template, lpofn
->hwndOwner
,
3824 FD32_FileOpenDlgProc
, (LPARAM
)lfs
);
3825 FD31_DestroyPrivate(lfs
);
3828 TRACE("file %s, file offset %d, ext offset %d\n",
3829 debugstr_w(lpofn
->lpstrFile
), lpofn
->nFileOffset
, lpofn
->nFileExtension
);
3833 /* ------------------ APIs ---------------------- */
3835 /***********************************************************************
3836 * GetOpenFileNameA (COMDLG32.@)
3838 * Creates a dialog box for the user to select a file to open.
3841 * TRUE on success: user enters a valid file
3842 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3845 BOOL WINAPI
GetOpenFileNameA(
3846 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3848 BOOL win16look
= FALSE
;
3850 TRACE("flags %08x\n", ofn
->Flags
);
3852 /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
3853 if (ofn
->Flags
& OFN_FILEMUSTEXIST
)
3854 ofn
->Flags
|= OFN_PATHMUSTEXIST
;
3856 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3857 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3860 return GetFileName31A(ofn
, OPEN_DIALOG
);
3862 return GetFileDialog95A(ofn
, OPEN_DIALOG
);
3865 /***********************************************************************
3866 * GetOpenFileNameW (COMDLG32.@)
3868 * Creates a dialog box for the user to select a file to open.
3871 * TRUE on success: user enters a valid file
3872 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3875 BOOL WINAPI
GetOpenFileNameW(
3876 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3878 BOOL win16look
= FALSE
;
3880 TRACE("flags %08x\n", ofn
->Flags
);
3882 /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */
3883 if (ofn
->Flags
& OFN_FILEMUSTEXIST
)
3884 ofn
->Flags
|= OFN_PATHMUSTEXIST
;
3886 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3887 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3890 return GetFileName31W(ofn
, OPEN_DIALOG
);
3892 return GetFileDialog95W(ofn
, OPEN_DIALOG
);
3896 /***********************************************************************
3897 * GetSaveFileNameA (COMDLG32.@)
3899 * Creates a dialog box for the user to select a file to save.
3902 * TRUE on success: user enters a valid file
3903 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3906 BOOL WINAPI
GetSaveFileNameA(
3907 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3909 BOOL win16look
= FALSE
;
3911 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3912 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3915 return GetFileName31A(ofn
, SAVE_DIALOG
);
3917 return GetFileDialog95A(ofn
, SAVE_DIALOG
);
3920 /***********************************************************************
3921 * GetSaveFileNameW (COMDLG32.@)
3923 * Creates a dialog box for the user to select a file to save.
3926 * TRUE on success: user enters a valid file
3927 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3930 BOOL WINAPI
GetSaveFileNameW(
3931 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3933 BOOL win16look
= FALSE
;
3935 if (ofn
->Flags
& (OFN_ALLOWMULTISELECT
|OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
))
3936 win16look
= (ofn
->Flags
& OFN_EXPLORER
) ? FALSE
: TRUE
;
3939 return GetFileName31W(ofn
, SAVE_DIALOG
);
3941 return GetFileDialog95W(ofn
, SAVE_DIALOG
);
3944 /***********************************************************************
3945 * GetFileTitleA (COMDLG32.@)
3947 * See GetFileTitleW.
3949 short WINAPI
GetFileTitleA(LPCSTR lpFile
, LPSTR lpTitle
, WORD cbBuf
)
3952 UNICODE_STRING strWFile
;
3955 RtlCreateUnicodeStringFromAsciiz(&strWFile
, lpFile
);
3956 lpWTitle
= RtlAllocateHeap( GetProcessHeap(), 0, cbBuf
*sizeof(WCHAR
));
3957 ret
= GetFileTitleW(strWFile
.Buffer
, lpWTitle
, cbBuf
);
3958 if (!ret
) WideCharToMultiByte( CP_ACP
, 0, lpWTitle
, -1, lpTitle
, cbBuf
, NULL
, NULL
);
3959 RtlFreeUnicodeString( &strWFile
);
3960 RtlFreeHeap( GetProcessHeap(), 0, lpWTitle
);
3965 /***********************************************************************
3966 * GetFileTitleW (COMDLG32.@)
3968 * Get the name of a file.
3971 * lpFile [I] name and location of file
3972 * lpTitle [O] returned file name
3973 * cbBuf [I] buffer size of lpTitle
3977 * Failure: negative number.
3979 short WINAPI
GetFileTitleW(LPCWSTR lpFile
, LPWSTR lpTitle
, WORD cbBuf
)
3982 static const WCHAR brkpoint
[] = {'*','[',']',0};
3983 TRACE("(%p %p %d);\n", lpFile
, lpTitle
, cbBuf
);
3985 if(lpFile
== NULL
|| lpTitle
== NULL
)
3988 len
= lstrlenW(lpFile
);
3993 if(strpbrkW(lpFile
, brkpoint
))
3998 if(lpFile
[len
] == '/' || lpFile
[len
] == '\\' || lpFile
[len
] == ':')
4001 for(i
= len
; i
>= 0; i
--)
4003 if (lpFile
[i
] == '/' || lpFile
[i
] == '\\' || lpFile
[i
] == ':')
4013 TRACE("---> %s\n", debugstr_w(&lpFile
[i
]));
4015 len
= lstrlenW(lpFile
+i
)+1;
4019 lstrcpyW(lpTitle
, &lpFile
[i
]);