Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
c3c0c56c
Commit
c3c0c56c
authored
Oct 16, 2003
by
Steven Edwards
Committed by
Alexandre Julliard
Oct 16, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- Split Win16/32 file dialogs.
- Remove support for Win16 style'd Win32 dialogs.
parent
a167c3bb
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1097 additions
and
3254 deletions
+1097
-3254
Makefile.in
dlls/commdlg/Makefile.in
+0
-1
filedlg.c
dlls/commdlg/filedlg.c
+0
-0
filedlg.h
dlls/commdlg/filedlg.h
+0
-72
filedlg16.c
dlls/commdlg/filedlg16.c
+1097
-3
filedlg95.c
dlls/commdlg/filedlg95.c
+0
-3178
No files found.
dlls/commdlg/Makefile.in
View file @
c3c0c56c
...
...
@@ -13,7 +13,6 @@ C_SRCS = \
cdlg32.c
\
colordlg.c
\
filedlg.c
\
filedlg95.c
\
filedlgbrowser.c
\
finddlg32.c
\
filetitle.c
\
...
...
dlls/commdlg/filedlg.c
View file @
c3c0c56c
This source diff could not be displayed because it is too large. You can
view the blob
instead.
dlls/commdlg/filedlg.h
deleted
100644 → 0
View file @
a167c3bb
/*
* COMMDLG - File Dialogs
*
* Copyright 1994 Martin Ayotte
* Copyright 1996 Albrecht Kleine
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _WINE_FINDDLG_H
#define _WINE_FINDDLG_H
#define BUFFILE 512
#define BUFFILEALLOC 512 * sizeof(WCHAR)
struct
FSPRIVATE
{
HWND
hwnd
;
/* file dialog window handle */
BOOL
hook
;
/* TRUE if the dialog is hooked */
UINT
lbselchstring
;
/* registered message id */
UINT
fileokstring
;
/* registered message id */
LPARAM
lParam
;
/* save original lparam */
HANDLE16
hDlgTmpl16
;
/* handle for resource 16 */
HANDLE16
hResource16
;
/* handle for allocated resource 16 */
HANDLE16
hGlobal16
;
/* 16 bits mem block (resources) */
LPCVOID
template
;
/* template for 32 bits resource */
BOOL
open
;
/* TRUE if open dialog, FALSE if save dialog */
OPENFILENAMEW
*
ofnW
;
/* original structure or work struct */
OPENFILENAMEA
*
ofnA
;
/* original structure if 32bits ansi dialog */
OPENFILENAME16
*
ofn16
;
/* original structure if 16 bits dialog */
};
#define LFSPRIVATE struct FSPRIVATE *
#define LFS16 1
#define LFS32A 2
#define LFS32W 3
#define OFN_PROP "FILEDLG_OFN"
static
const
WCHAR
FILE_star
[]
=
{
'*'
,
'.'
,
'*'
,
0
};
static
const
WCHAR
FILE_bslash
[]
=
{
'\\'
,
0
};
static
const
WCHAR
FILE_specc
[]
=
{
'%'
,
'c'
,
':'
,
0
};
static
const
int
fldrHeight
=
16
;
static
const
int
fldrWidth
=
20
;
/* Internal Functions
* Do not Export to other applications or dlls
*/
LPWSTR
FILEDLG_GetFileType
(
LPWSTR
cfptr
,
LPWSTR
fptr
,
WORD
index
);
void
FILEDLG_MapDrawItemStruct
(
LPDRAWITEMSTRUCT16
lpdis16
,
LPDRAWITEMSTRUCT
lpdis
);
BOOL
FILEDLG_ScanDir
(
HWND
hWnd
,
LPWSTR
newPath
);
LONG
FILEDLG_WMDrawItem
(
HWND
hWnd
,
WPARAM
wParam
,
LPARAM
lParam
,
int
savedlg
,
LPDRAWITEMSTRUCT
lpdis
);
LRESULT
FILEDLG_WMCommand
(
HWND
hWnd
,
LPARAM
lParam
,
UINT
notification
,
UINT
control
,
LFSPRIVATE
lfs
);
BOOL
FileDlg_Init
(
void
);
void
FILEDLG_DestroyPrivate
(
LFSPRIVATE
lfs
);
LFSPRIVATE
FILEDLG_AllocPrivate
(
LPARAM
lParam
,
int
type
,
UINT
dlgType
);
#endif
/* _WINE_FINDDLG_H */
dlls/commdlg/filedlg16.c
View file @
c3c0c56c
...
...
@@ -25,14 +25,18 @@
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winnls.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/winbase16.h"
#include "wine/winuser16.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "cderr.h"
#include "winreg.h"
#include "winternl.h"
#include "winuser.h"
#include "commdlg.h"
#include "wine/debug.h"
#include "cderr.h"
#include "winreg.h"
#include "winternl.h"
...
...
@@ -40,7 +44,1097 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
commdlg
);
#include "cdlg.h"
#include "filedlg.h"
#define BUFFILE 512
#define BUFFILEALLOC 512 * sizeof(WCHAR)
struct
FSPRIVATE
{
HWND
hwnd
;
/* file dialog window handle */
BOOL
hook
;
/* TRUE if the dialog is hooked */
UINT
lbselchstring
;
/* registered message id */
UINT
fileokstring
;
/* registered message id */
LPARAM
lParam
;
/* save original lparam */
HANDLE16
hDlgTmpl16
;
/* handle for resource 16 */
HANDLE16
hResource16
;
/* handle for allocated resource 16 */
HANDLE16
hGlobal16
;
/* 16 bits mem block (resources) */
LPCVOID
template
;
/* template for 32 bits resource */
BOOL
open
;
/* TRUE if open dialog, FALSE if save dialog */
OPENFILENAMEW
*
ofnW
;
/* original structure or work struct */
OPENFILENAMEA
*
ofnA
;
/* original structure if 32bits ansi dialog */
OPENFILENAME16
*
ofn16
;
/* original structure if 16 bits dialog */
};
#define LFSPRIVATE struct FSPRIVATE *
#define LFS16 1
#define LFS32A 2
#define LFS32W 3
#define OFN_PROP "FILEDLG_OFN"
static
const
WCHAR
FILE_star
[]
=
{
'*'
,
'.'
,
'*'
,
0
};
static
const
WCHAR
FILE_bslash
[]
=
{
'\\'
,
0
};
static
const
WCHAR
FILE_specc
[]
=
{
'%'
,
'c'
,
':'
,
0
};
static
const
int
fldrHeight
=
16
;
static
const
int
fldrWidth
=
20
;
static
HICON
hFolder
=
0
;
static
HICON
hFolder2
=
0
;
static
HICON
hFloppy
=
0
;
static
HICON
hHDisk
=
0
;
static
HICON
hCDRom
=
0
;
static
HICON
hNet
=
0
;
static
char
defaultopen
[]
=
"Open File"
;
static
char
defaultsave
[]
=
"Save as"
;
/***********************************************************************
* FileDlg_Init [internal]
*/
static
BOOL
FileDlg_Init
(
void
)
{
static
BOOL
initialized
=
0
;
if
(
!
initialized
)
{
HINSTANCE
inst
=
GetModuleHandleA
(
"comdlg32.dll"
);
if
(
!
inst
)
{
ERR
(
"cannot get comdlg32.dll instance
\n
"
);
return
FALSE
;
}
hFolder
=
LoadImageA
(
inst
,
"FOLDER"
,
IMAGE_ICON
,
16
,
16
,
LR_SHARED
);
hFolder2
=
LoadImageA
(
inst
,
"FOLDER2"
,
IMAGE_ICON
,
16
,
16
,
LR_SHARED
);
hFloppy
=
LoadImageA
(
inst
,
"FLOPPY"
,
IMAGE_ICON
,
16
,
16
,
LR_SHARED
);
hHDisk
=
LoadImageA
(
inst
,
"HDISK"
,
IMAGE_ICON
,
16
,
16
,
LR_SHARED
);
hCDRom
=
LoadImageA
(
inst
,
"CDROM"
,
IMAGE_ICON
,
16
,
16
,
LR_SHARED
);
hNet
=
LoadImageA
(
inst
,
"NETWORK"
,
IMAGE_ICON
,
16
,
16
,
LR_SHARED
);
if
(
hFolder
==
0
||
hFolder2
==
0
||
hFloppy
==
0
||
hHDisk
==
0
||
hCDRom
==
0
||
hNet
==
0
)
{
ERR
(
"Error loading icons !
\n
"
);
return
FALSE
;
}
initialized
=
TRUE
;
}
return
TRUE
;
}
/***********************************************************************
* Get32BitsTemplate [internal]
*
* Get a template (or FALSE if failure) when 16 bits dialogs are used
* by a 32 bits application
*
*/
BOOL
Get32BitsTemplate
(
LFSPRIVATE
lfs
)
{
LPOPENFILENAMEW
ofnW
=
lfs
->
ofnW
;
HANDLE
hDlgTmpl
;
if
(
ofnW
->
Flags
&
OFN_ENABLETEMPLATEHANDLE
)
{
if
(
!
(
lfs
->
template
=
LockResource
(
ofnW
->
hInstance
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_LOADRESFAILURE
);
return
FALSE
;
}
}
else
if
(
ofnW
->
Flags
&
OFN_ENABLETEMPLATE
)
{
HRSRC
hResInfo
;
if
(
lfs
->
ofnA
)
hResInfo
=
FindResourceA
(
lfs
->
ofnA
->
hInstance
,
lfs
->
ofnA
->
lpTemplateName
,
(
LPSTR
)
RT_DIALOG
);
else
hResInfo
=
FindResourceW
(
ofnW
->
hInstance
,
ofnW
->
lpTemplateName
,
(
LPWSTR
)
RT_DIALOG
);
if
(
!
hResInfo
)
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_FINDRESFAILURE
);
return
FALSE
;
}
if
(
!
(
hDlgTmpl
=
LoadResource
(
ofnW
->
hInstance
,
hResInfo
))
||
!
(
lfs
->
template
=
LockResource
(
hDlgTmpl
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_LOADRESFAILURE
);
return
FALSE
;
}
}
else
{
/* get it from internal Wine resource */
HRSRC
hResInfo
;
if
(
!
(
hResInfo
=
FindResourceA
(
COMDLG32_hInstance
,
lfs
->
open
?
"OPEN_FILE"
:
"SAVE_FILE"
,
(
LPSTR
)
RT_DIALOG
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_FINDRESFAILURE
);
return
FALSE
;
}
if
(
!
(
hDlgTmpl
=
LoadResource
(
COMDLG32_hInstance
,
hResInfo
))
||
!
(
lfs
->
template
=
LockResource
(
hDlgTmpl
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_LOADRESFAILURE
);
return
FALSE
;
}
}
return
TRUE
;
}
/***********************************************************************
* Get16BitsTemplate [internal]
*
* Get a template (FALSE if failure) when 16 bits dialogs are used
* by a 16 bits application
*
*/
BOOL
Get16BitsTemplate
(
LFSPRIVATE
lfs
)
{
LPOPENFILENAME16
ofn16
=
lfs
->
ofn16
;
LPCVOID
template
;
HGLOBAL16
hGlobal16
=
0
;
if
(
ofn16
->
Flags
&
OFN_ENABLETEMPLATEHANDLE
)
lfs
->
hDlgTmpl16
=
ofn16
->
hInstance
;
else
if
(
ofn16
->
Flags
&
OFN_ENABLETEMPLATE
)
{
HANDLE16
hResInfo
;
if
(
!
(
hResInfo
=
FindResource16
(
ofn16
->
hInstance
,
MapSL
(
ofn16
->
lpTemplateName
),
(
LPSTR
)
RT_DIALOG
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_FINDRESFAILURE
);
return
FALSE
;
}
if
(
!
(
lfs
->
hDlgTmpl16
=
LoadResource16
(
ofn16
->
hInstance
,
hResInfo
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_LOADRESFAILURE
);
return
FALSE
;
}
lfs
->
hResource16
=
lfs
->
hDlgTmpl16
;
}
else
{
/* get resource from (32 bits) own Wine resource; convert it to 16 */
HRSRC
hResInfo
;
HGLOBAL
hDlgTmpl32
;
LPCVOID
template32
;
DWORD
size
;
if
(
!
(
hResInfo
=
FindResourceA
(
COMDLG32_hInstance
,
lfs
->
open
?
"OPEN_FILE"
:
"SAVE_FILE"
,
(
LPSTR
)
RT_DIALOG
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_FINDRESFAILURE
);
return
FALSE
;
}
if
(
!
(
hDlgTmpl32
=
LoadResource
(
COMDLG32_hInstance
,
hResInfo
))
||
!
(
template32
=
LockResource
(
hDlgTmpl32
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_LOADRESFAILURE
);
return
FALSE
;
}
size
=
SizeofResource
(
GetModuleHandleA
(
"COMDLG32"
),
hResInfo
);
hGlobal16
=
GlobalAlloc16
(
0
,
size
);
if
(
!
hGlobal16
)
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_MEMALLOCFAILURE
);
ERR
(
"alloc failure for %ld bytes
\n
"
,
size
);
return
FALSE
;
}
template
=
GlobalLock16
(
hGlobal16
);
if
(
!
template
)
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_MEMLOCKFAILURE
);
ERR
(
"global lock failure for %x handle
\n
"
,
hGlobal16
);
GlobalFree16
(
hGlobal16
);
return
FALSE
;
}
ConvertDialog32To16
((
LPVOID
)
template32
,
size
,
(
LPVOID
)
template
);
lfs
->
hDlgTmpl16
=
hGlobal16
;
lfs
->
hGlobal16
=
hGlobal16
;
}
return
TRUE
;
}
/***********************************************************************
* FILEDLG_StripEditControl [internal]
* Strip pathnames off the contents of the edit control.
*/
static
void
FILEDLG_StripEditControl
(
HWND
hwnd
)
{
WCHAR
temp
[
BUFFILE
],
*
cp
;
GetDlgItemTextW
(
hwnd
,
edt1
,
temp
,
sizeof
(
temp
)
/
sizeof
(
WCHAR
));
cp
=
strrchrW
(
temp
,
'\\'
);
if
(
cp
!=
NULL
)
{
strcpyW
(
temp
,
cp
+
1
);
}
cp
=
strrchrW
(
temp
,
':'
);
if
(
cp
!=
NULL
)
{
strcpyW
(
temp
,
cp
+
1
);
}
/* FIXME: shouldn't we do something with the result here? ;-) */
}
/***********************************************************************
* FILEDLG_CallWindowProc [internal]
*
* Call the appropriate hook
*/
static
BOOL
FILEDLG_CallWindowProc
(
LFSPRIVATE
lfs
,
UINT
wMsg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
if
(
lfs
->
ofnA
)
{
return
(
BOOL
)
CallWindowProcA
(
(
WNDPROC
)
lfs
->
ofnA
->
lpfnHook
,
lfs
->
hwnd
,
wMsg
,
wParam
,
lParam
);
}
if
(
lfs
->
ofnW
)
{
return
(
BOOL
)
CallWindowProcW
(
(
WNDPROC
)
lfs
->
ofnW
->
lpfnHook
,
lfs
->
hwnd
,
wMsg
,
wParam
,
lParam
);
}
return
FALSE
;
}
/***********************************************************************
* FILEDLG_ScanDir [internal]
*/
static
BOOL
FILEDLG_ScanDir
(
HWND
hWnd
,
LPWSTR
newPath
)
{
WCHAR
buffer
[
BUFFILE
];
HWND
hdlg
,
hdlgDir
;
LRESULT
lRet
=
TRUE
;
HCURSOR
hCursorWait
,
oldCursor
;
TRACE
(
"Trying to change to %s
\n
"
,
debugstr_w
(
newPath
));
if
(
!
SetCurrentDirectoryW
(
newPath
))
return
FALSE
;
lstrcpynW
(
buffer
,
newPath
,
sizeof
(
buffer
)
/
sizeof
(
WCHAR
));
/* get the list of spec files */
GetDlgItemTextW
(
hWnd
,
edt1
,
buffer
,
sizeof
(
buffer
)
/
sizeof
(
WCHAR
));
hCursorWait
=
LoadCursorA
(
0
,
(
LPSTR
)
IDC_WAIT
);
oldCursor
=
SetCursor
(
hCursorWait
);
/* list of files */
if
((
hdlg
=
GetDlgItem
(
hWnd
,
lst1
))
!=
0
)
{
WCHAR
*
scptr
;
/* ptr on semi-colon */
WCHAR
*
filter
=
buffer
;
TRACE
(
"Using filter %s
\n
"
,
debugstr_w
(
filter
));
SendMessageW
(
hdlg
,
LB_RESETCONTENT
,
0
,
0
);
while
(
filter
)
{
scptr
=
strchrW
(
filter
,
';'
);
if
(
scptr
)
*
scptr
=
0
;
while
(
*
filter
==
' '
)
filter
++
;
TRACE
(
"Using file spec %s
\n
"
,
debugstr_w
(
filter
));
if
(
SendMessageW
(
hdlg
,
LB_DIR
,
0
,
(
LPARAM
)
filter
)
==
LB_ERR
)
return
FALSE
;
if
(
scptr
)
*
scptr
=
';'
;
filter
=
(
scptr
)
?
(
scptr
+
1
)
:
0
;
}
}
/* list of directories */
strcpyW
(
buffer
,
FILE_star
);
if
((
hdlgDir
=
GetDlgItem
(
hWnd
,
lst2
))
!=
0
)
{
lRet
=
DlgDirListW
(
hWnd
,
buffer
,
lst2
,
stc1
,
DDL_EXCLUSIVE
|
DDL_DIRECTORY
);
}
SetCursor
(
oldCursor
);
return
lRet
;
}
/***********************************************************************
* FILEDLG_GetFileType [internal]
*/
static
LPWSTR
FILEDLG_GetFileType
(
LPWSTR
cfptr
,
LPWSTR
fptr
,
WORD
index
)
{
int
n
,
i
;
i
=
0
;
if
(
cfptr
)
for
(
;(
n
=
lstrlenW
(
cfptr
))
!=
0
;
i
++
)
{
cfptr
+=
n
+
1
;
if
(
i
==
index
)
return
cfptr
;
cfptr
+=
lstrlenW
(
cfptr
)
+
1
;
}
if
(
fptr
)
for
(
;(
n
=
lstrlenW
(
fptr
))
!=
0
;
i
++
)
{
fptr
+=
n
+
1
;
if
(
i
==
index
)
return
fptr
;
fptr
+=
lstrlenW
(
fptr
)
+
1
;
}
return
(
LPWSTR
)
FILE_star
;
/* FIXME */
}
/***********************************************************************
* FILEDLG_WMDrawItem [internal]
*/
static
LONG
FILEDLG_WMDrawItem
(
HWND
hWnd
,
WPARAM
wParam
,
LPARAM
lParam
,
int
savedlg
,
LPDRAWITEMSTRUCT
lpdis
)
{
WCHAR
*
str
;
HICON
hIcon
;
COLORREF
oldText
=
0
,
oldBk
=
0
;
if
(
lpdis
->
CtlType
==
ODT_LISTBOX
&&
lpdis
->
CtlID
==
lst1
)
{
if
(
!
(
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
BUFFILEALLOC
)))
return
FALSE
;
SendMessageW
(
lpdis
->
hwndItem
,
LB_GETTEXT
,
lpdis
->
itemID
,
(
LPARAM
)
str
);
if
((
lpdis
->
itemState
&
ODS_SELECTED
)
&&
!
savedlg
)
{
oldBk
=
SetBkColor
(
lpdis
->
hDC
,
GetSysColor
(
COLOR_HIGHLIGHT
)
);
oldText
=
SetTextColor
(
lpdis
->
hDC
,
GetSysColor
(
COLOR_HIGHLIGHTTEXT
));
}
if
(
savedlg
)
SetTextColor
(
lpdis
->
hDC
,
GetSysColor
(
COLOR_GRAYTEXT
)
);
ExtTextOutW
(
lpdis
->
hDC
,
lpdis
->
rcItem
.
left
+
1
,
lpdis
->
rcItem
.
top
+
1
,
ETO_OPAQUE
|
ETO_CLIPPED
,
&
(
lpdis
->
rcItem
),
str
,
lstrlenW
(
str
),
NULL
);
if
(
lpdis
->
itemState
&
ODS_SELECTED
)
DrawFocusRect
(
lpdis
->
hDC
,
&
(
lpdis
->
rcItem
)
);
if
((
lpdis
->
itemState
&
ODS_SELECTED
)
&&
!
savedlg
)
{
SetBkColor
(
lpdis
->
hDC
,
oldBk
);
SetTextColor
(
lpdis
->
hDC
,
oldText
);
}
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
TRUE
;
}
if
(
lpdis
->
CtlType
==
ODT_LISTBOX
&&
lpdis
->
CtlID
==
lst2
)
{
if
(
!
(
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
BUFFILEALLOC
)))
return
FALSE
;
SendMessageW
(
lpdis
->
hwndItem
,
LB_GETTEXT
,
lpdis
->
itemID
,
(
LPARAM
)
str
);
if
(
lpdis
->
itemState
&
ODS_SELECTED
)
{
oldBk
=
SetBkColor
(
lpdis
->
hDC
,
GetSysColor
(
COLOR_HIGHLIGHT
)
);
oldText
=
SetTextColor
(
lpdis
->
hDC
,
GetSysColor
(
COLOR_HIGHLIGHTTEXT
));
}
ExtTextOutW
(
lpdis
->
hDC
,
lpdis
->
rcItem
.
left
+
fldrWidth
,
lpdis
->
rcItem
.
top
+
1
,
ETO_OPAQUE
|
ETO_CLIPPED
,
&
(
lpdis
->
rcItem
),
str
,
lstrlenW
(
str
),
NULL
);
if
(
lpdis
->
itemState
&
ODS_SELECTED
)
DrawFocusRect
(
lpdis
->
hDC
,
&
(
lpdis
->
rcItem
)
);
if
(
lpdis
->
itemState
&
ODS_SELECTED
)
{
SetBkColor
(
lpdis
->
hDC
,
oldBk
);
SetTextColor
(
lpdis
->
hDC
,
oldText
);
}
DrawIcon
(
lpdis
->
hDC
,
lpdis
->
rcItem
.
left
,
lpdis
->
rcItem
.
top
,
hFolder
);
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
TRUE
;
}
if
(
lpdis
->
CtlType
==
ODT_COMBOBOX
&&
lpdis
->
CtlID
==
cmb2
)
{
char
root
[]
=
"a:"
;
if
(
!
(
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
BUFFILEALLOC
)))
return
FALSE
;
SendMessageW
(
lpdis
->
hwndItem
,
CB_GETLBTEXT
,
lpdis
->
itemID
,
(
LPARAM
)
str
);
root
[
0
]
+=
str
[
2
]
-
'a'
;
switch
(
GetDriveTypeA
(
root
))
{
case
DRIVE_REMOVABLE
:
hIcon
=
hFloppy
;
break
;
case
DRIVE_CDROM
:
hIcon
=
hCDRom
;
break
;
case
DRIVE_REMOTE
:
hIcon
=
hNet
;
break
;
case
DRIVE_FIXED
:
default:
hIcon
=
hHDisk
;
break
;
}
if
(
lpdis
->
itemState
&
ODS_SELECTED
)
{
oldBk
=
SetBkColor
(
lpdis
->
hDC
,
GetSysColor
(
COLOR_HIGHLIGHT
)
);
oldText
=
SetTextColor
(
lpdis
->
hDC
,
GetSysColor
(
COLOR_HIGHLIGHTTEXT
));
}
ExtTextOutW
(
lpdis
->
hDC
,
lpdis
->
rcItem
.
left
+
fldrWidth
,
lpdis
->
rcItem
.
top
+
1
,
ETO_OPAQUE
|
ETO_CLIPPED
,
&
(
lpdis
->
rcItem
),
str
,
lstrlenW
(
str
),
NULL
);
if
(
lpdis
->
itemState
&
ODS_SELECTED
)
{
SetBkColor
(
lpdis
->
hDC
,
oldBk
);
SetTextColor
(
lpdis
->
hDC
,
oldText
);
}
DrawIcon
(
lpdis
->
hDC
,
lpdis
->
rcItem
.
left
,
lpdis
->
rcItem
.
top
,
hIcon
);
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
TRUE
;
}
return
FALSE
;
}
/***********************************************************************
* FILEDLG_UpdateResult [internal]
* update the displayed file name (with path)
*/
void
FILEDLG_UpdateResult
(
LFSPRIVATE
lfs
,
WCHAR
*
tmpstr
)
{
int
lenstr2
;
LPOPENFILENAMEW
ofnW
=
lfs
->
ofnW
;
WCHAR
tmpstr2
[
BUFFILE
];
WCHAR
*
bs
;
TRACE
(
"%s
\n
"
,
debugstr_w
(
tmpstr
));
if
(
ofnW
->
Flags
&
OFN_NOVALIDATE
)
tmpstr2
[
0
]
=
'\0'
;
else
GetCurrentDirectoryW
(
BUFFILE
,
tmpstr2
);
lenstr2
=
strlenW
(
tmpstr2
);
if
(
lenstr2
>
3
)
tmpstr2
[
lenstr2
++
]
=
'\\'
;
lstrcpynW
(
tmpstr2
+
lenstr2
,
tmpstr
,
BUFFILE
-
lenstr2
);
if
(
ofnW
->
lpstrFile
)
lstrcpynW
(
ofnW
->
lpstrFile
,
tmpstr2
,
ofnW
->
nMaxFile
);
if
((
bs
=
strrchrW
(
tmpstr2
,
'\\'
))
!=
NULL
)
ofnW
->
nFileOffset
=
bs
-
tmpstr2
+
1
;
else
ofnW
->
nFileOffset
=
0
;
ofnW
->
nFileExtension
=
0
;
while
(
tmpstr2
[
ofnW
->
nFileExtension
]
!=
'.'
&&
tmpstr2
[
ofnW
->
nFileExtension
]
!=
'\0'
)
ofnW
->
nFileExtension
++
;
if
(
tmpstr2
[
ofnW
->
nFileExtension
]
==
'\0'
)
ofnW
->
nFileExtension
=
0
;
else
ofnW
->
nFileExtension
++
;
/* update the real client structures if any */
if
(
lfs
->
ofn16
)
{
/* we have to convert to short (8.3) path */
char
tmp
[
1024
];
/* MAX_PATHNAME_LEN */
LPOPENFILENAME16
ofn16
=
lfs
->
ofn16
;
char
*
dest
=
MapSL
(
ofn16
->
lpstrFile
);
char
*
bs16
;
if
(
!
WideCharToMultiByte
(
CP_ACP
,
0
,
ofnW
->
lpstrFile
,
-
1
,
tmp
,
sizeof
(
tmp
),
NULL
,
NULL
))
tmp
[
sizeof
(
tmp
)
-
1
]
=
0
;
GetShortPathNameA
(
tmp
,
dest
,
ofn16
->
nMaxFile
);
/* the same procedure as every year... */
if
((
bs16
=
strrchr
(
dest
,
'\\'
))
!=
NULL
)
ofn16
->
nFileOffset
=
bs16
-
dest
+
1
;
else
ofn16
->
nFileOffset
=
0
;
ofn16
->
nFileExtension
=
0
;
while
(
dest
[
ofn16
->
nFileExtension
]
!=
'.'
&&
dest
[
ofn16
->
nFileExtension
]
!=
'\0'
)
ofn16
->
nFileExtension
++
;
if
(
dest
[
ofn16
->
nFileExtension
]
==
'\0'
)
ofn16
->
nFileExtension
=
0
;
else
ofn16
->
nFileExtension
++
;
}
if
(
lfs
->
ofnA
)
{
if
(
ofnW
->
nMaxFile
&&
!
WideCharToMultiByte
(
CP_ACP
,
0
,
ofnW
->
lpstrFile
,
-
1
,
lfs
->
ofnA
->
lpstrFile
,
ofnW
->
nMaxFile
,
NULL
,
NULL
))
lfs
->
ofnA
->
lpstrFile
[
ofnW
->
nMaxFile
-
1
]
=
0
;
lfs
->
ofnA
->
nFileOffset
=
ofnW
->
nFileOffset
;
lfs
->
ofnA
->
nFileExtension
=
ofnW
->
nFileExtension
;
}
}
/***********************************************************************
* FILEDLG_UpdateFileTitle [internal]
* update the displayed file name (without path)
*/
void
FILEDLG_UpdateFileTitle
(
LFSPRIVATE
lfs
)
{
LONG
lRet
;
LPOPENFILENAMEW
ofnW
=
lfs
->
ofnW
;
if
(
ofnW
->
lpstrFileTitle
!=
NULL
)
{
lRet
=
SendDlgItemMessageW
(
lfs
->
hwnd
,
lst1
,
LB_GETCURSEL
,
0
,
0
);
SendDlgItemMessageW
(
lfs
->
hwnd
,
lst1
,
LB_GETTEXT
,
lRet
,
(
LPARAM
)
ofnW
->
lpstrFileTitle
);
if
(
lfs
->
ofn16
)
{
char
*
dest
=
MapSL
(
lfs
->
ofn16
->
lpstrFileTitle
);
if
(
!
WideCharToMultiByte
(
CP_ACP
,
0
,
ofnW
->
lpstrFileTitle
,
-
1
,
dest
,
ofnW
->
nMaxFileTitle
,
NULL
,
NULL
))
dest
[
ofnW
->
nMaxFileTitle
-
1
]
=
0
;
}
if
(
lfs
->
ofnA
)
{
if
(
!
WideCharToMultiByte
(
CP_ACP
,
0
,
ofnW
->
lpstrFileTitle
,
-
1
,
lfs
->
ofnA
->
lpstrFileTitle
,
ofnW
->
nMaxFileTitle
,
NULL
,
NULL
))
lfs
->
ofnA
->
lpstrFileTitle
[
ofnW
->
nMaxFileTitle
-
1
]
=
0
;
}
}
}
/***********************************************************************
* FILEDLG_DirListDblClick [internal]
*/
static
LRESULT
FILEDLG_DirListDblClick
(
LFSPRIVATE
lfs
)
{
LONG
lRet
;
HWND
hWnd
=
lfs
->
hwnd
;
LPWSTR
pstr
;
WCHAR
tmpstr
[
BUFFILE
];
/* get the raw string (with brackets) */
lRet
=
SendDlgItemMessageW
(
hWnd
,
lst2
,
LB_GETCURSEL
,
0
,
0
);
if
(
lRet
==
LB_ERR
)
return
TRUE
;
pstr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
BUFFILEALLOC
);
SendDlgItemMessageW
(
hWnd
,
lst2
,
LB_GETTEXT
,
lRet
,
(
LPARAM
)
pstr
);
strcpyW
(
tmpstr
,
pstr
);
HeapFree
(
GetProcessHeap
(),
0
,
pstr
);
/* get the selected directory in tmpstr */
if
(
tmpstr
[
0
]
==
'['
)
{
tmpstr
[
lstrlenW
(
tmpstr
)
-
1
]
=
0
;
strcpyW
(
tmpstr
,
tmpstr
+
1
);
}
strcatW
(
tmpstr
,
FILE_bslash
);
FILEDLG_ScanDir
(
hWnd
,
tmpstr
);
/* notify the app */
if
(
lfs
->
hook
)
{
if
(
FILEDLG_CallWindowProc
(
lfs
,
lfs
->
lbselchstring
,
lst2
,
MAKELONG
(
lRet
,
CD_LBSELCHANGE
)))
return
TRUE
;
}
return
TRUE
;
}
/***********************************************************************
* FILEDLG_FileListSelect [internal]
* called when a new item is picked in the file list
*/
static
LRESULT
FILEDLG_FileListSelect
(
LFSPRIVATE
lfs
)
{
LONG
lRet
;
HWND
hWnd
=
lfs
->
hwnd
;
LPWSTR
pstr
;
lRet
=
SendDlgItemMessageW
(
hWnd
,
lst1
,
LB_GETCURSEL16
,
0
,
0
);
if
(
lRet
==
LB_ERR
)
return
TRUE
;
/* set the edit control to the choosen file */
if
((
pstr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
BUFFILEALLOC
)))
{
SendDlgItemMessageW
(
hWnd
,
lst1
,
LB_GETTEXT
,
lRet
,
(
LPARAM
)
pstr
);
SetDlgItemTextW
(
hWnd
,
edt1
,
pstr
);
HeapFree
(
GetProcessHeap
(),
0
,
pstr
);
}
if
(
lfs
->
hook
)
{
FILEDLG_CallWindowProc
(
lfs
,
lfs
->
lbselchstring
,
lst1
,
MAKELONG
(
lRet
,
CD_LBSELCHANGE
));
}
/* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD,
CD_LBSELNOITEMS */
return
TRUE
;
}
/***********************************************************************
* FILEDLG_TestPath [internal]
* before accepting the file name, test if it includes wild cards
* tries to scan the directory and returns TRUE if no error.
*/
static
LRESULT
FILEDLG_TestPath
(
LFSPRIVATE
lfs
,
LPWSTR
path
)
{
HWND
hWnd
=
lfs
->
hwnd
;
LPWSTR
pBeginFileName
,
pstr2
;
WCHAR
tmpstr2
[
BUFFILE
];
pBeginFileName
=
strrchrW
(
path
,
'\\'
);
if
(
pBeginFileName
==
NULL
)
pBeginFileName
=
strrchrW
(
path
,
':'
);
if
(
strchrW
(
path
,
'*'
)
!=
NULL
||
strchrW
(
path
,
'?'
)
!=
NULL
)
{
/* edit control contains wildcards */
if
(
pBeginFileName
!=
NULL
)
{
lstrcpynW
(
tmpstr2
,
pBeginFileName
+
1
,
BUFFILE
);
*
(
pBeginFileName
+
1
)
=
0
;
}
else
{
strcpyW
(
tmpstr2
,
path
);
if
(
!
(
lfs
->
ofnW
->
Flags
&
OFN_NOVALIDATE
))
*
path
=
0
;
}
TRACE
(
"path=%s, tmpstr2=%s
\n
"
,
debugstr_w
(
path
),
debugstr_w
(
tmpstr2
));
SetDlgItemTextW
(
hWnd
,
edt1
,
tmpstr2
);
FILEDLG_ScanDir
(
hWnd
,
path
);
return
(
lfs
->
ofnW
->
Flags
&
OFN_NOVALIDATE
)
?
TRUE
:
FALSE
;
}
/* no wildcards, we might have a directory or a filename */
/* try appending a wildcard and reading the directory */
pstr2
=
path
+
lstrlenW
(
path
);
if
(
pBeginFileName
==
NULL
||
*
(
pBeginFileName
+
1
)
!=
0
)
strcatW
(
path
,
FILE_bslash
);
/* if ScanDir succeeds, we have changed the directory */
if
(
FILEDLG_ScanDir
(
hWnd
,
path
))
return
TRUE
;
/* if not, this must be a filename */
*
pstr2
=
0
;
/* remove the wildcard added before */
if
(
pBeginFileName
!=
NULL
)
{
/* strip off the pathname */
*
pBeginFileName
=
0
;
SetDlgItemTextW
(
hWnd
,
edt1
,
pBeginFileName
+
1
);
lstrcpynW
(
tmpstr2
,
pBeginFileName
+
1
,
sizeof
(
tmpstr2
)
/
sizeof
(
WCHAR
)
);
/* Should we MessageBox() if this fails? */
if
(
!
FILEDLG_ScanDir
(
hWnd
,
path
))
{
return
FALSE
;
}
strcpyW
(
path
,
tmpstr2
);
}
else
SetDlgItemTextW
(
hWnd
,
edt1
,
path
);
return
TRUE
;
}
/***********************************************************************
* FILEDLG_Validate [internal]
* called on: click Ok button, Enter in edit, DoubleClick in file list
*/
static
LRESULT
FILEDLG_Validate
(
LFSPRIVATE
lfs
,
LPWSTR
path
,
UINT
control
,
INT
itemIndex
,
BOOL
internalUse
)
{
LONG
lRet
;
HWND
hWnd
=
lfs
->
hwnd
;
OPENFILENAMEW
ofnsav
;
LPOPENFILENAMEW
ofnW
=
lfs
->
ofnW
;
WCHAR
filename
[
BUFFILE
];
ofnsav
=
*
ofnW
;
/* for later restoring */
/* get current file name */
if
(
path
)
lstrcpynW
(
filename
,
path
,
sizeof
(
filename
)
/
sizeof
(
WCHAR
));
else
GetDlgItemTextW
(
hWnd
,
edt1
,
filename
,
sizeof
(
filename
)
/
sizeof
(
WCHAR
));
TRACE
(
"got filename = %s
\n
"
,
debugstr_w
(
filename
));
/* if we did not click in file list to get there */
if
(
control
!=
lst1
)
{
if
(
!
FILEDLG_TestPath
(
lfs
,
filename
)
)
return
FALSE
;
}
FILEDLG_UpdateResult
(
lfs
,
filename
);
if
(
internalUse
)
{
/* called internally after a change in a combo */
if
(
lfs
->
hook
)
{
FILEDLG_CallWindowProc
(
lfs
,
lfs
->
lbselchstring
,
control
,
MAKELONG
(
itemIndex
,
CD_LBSELCHANGE
));
}
return
TRUE
;
}
FILEDLG_UpdateFileTitle
(
lfs
);
if
(
lfs
->
hook
)
{
lRet
=
(
BOOL
)
FILEDLG_CallWindowProc
(
lfs
,
lfs
->
fileokstring
,
0
,
lfs
->
lParam
);
if
(
lRet
)
{
*
ofnW
=
ofnsav
;
/* restore old state */
return
FALSE
;
}
}
if
((
ofnW
->
Flags
&
OFN_ALLOWMULTISELECT
)
&&
(
ofnW
->
Flags
&
OFN_EXPLORER
))
{
if
(
ofnW
->
lpstrFile
)
{
LPWSTR
str
=
(
LPWSTR
)
ofnW
->
lpstrFile
;
LPWSTR
ptr
=
strrchrW
(
str
,
'\\'
);
str
[
lstrlenW
(
str
)
+
1
]
=
'\0'
;
*
ptr
=
0
;
}
}
return
TRUE
;
}
/***********************************************************************
* FILEDLG_DiskChange [internal]
* called when a new item is picked in the disk selection combo
*/
static
LRESULT
FILEDLG_DiskChange
(
LFSPRIVATE
lfs
)
{
LONG
lRet
;
HWND
hWnd
=
lfs
->
hwnd
;
LPWSTR
pstr
;
WCHAR
diskname
[
BUFFILE
];
FILEDLG_StripEditControl
(
hWnd
);
lRet
=
SendDlgItemMessageW
(
hWnd
,
cmb2
,
CB_GETCURSEL
,
0
,
0L
);
if
(
lRet
==
LB_ERR
)
return
0
;
pstr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
BUFFILEALLOC
);
SendDlgItemMessageW
(
hWnd
,
cmb2
,
CB_GETLBTEXT
,
lRet
,
(
LPARAM
)
pstr
);
wsprintfW
(
diskname
,
FILE_specc
,
pstr
[
2
]);
HeapFree
(
GetProcessHeap
(),
0
,
pstr
);
return
FILEDLG_Validate
(
lfs
,
diskname
,
cmb2
,
lRet
,
TRUE
);
}
/***********************************************************************
* FILEDLG_FileTypeChange [internal]
* called when a new item is picked in the file type combo
*/
static
LRESULT
FILEDLG_FileTypeChange
(
LFSPRIVATE
lfs
)
{
LONG
lRet
;
WCHAR
diskname
[
BUFFILE
];
LPWSTR
pstr
;
diskname
[
0
]
=
0
;
lRet
=
SendDlgItemMessageW
(
lfs
->
hwnd
,
cmb1
,
CB_GETCURSEL
,
0
,
0
);
if
(
lRet
==
LB_ERR
)
return
TRUE
;
pstr
=
(
LPWSTR
)
SendDlgItemMessageW
(
lfs
->
hwnd
,
cmb1
,
CB_GETITEMDATA
,
lRet
,
0
);
TRACE
(
"Selected filter : %s
\n
"
,
debugstr_w
(
pstr
));
SetDlgItemTextW
(
lfs
->
hwnd
,
edt1
,
pstr
);
return
FILEDLG_Validate
(
lfs
,
NULL
,
cmb1
,
lRet
,
TRUE
);
}
/***********************************************************************
* FILEDLG_WMCommand [internal]
*/
static
LRESULT
FILEDLG_WMCommand
(
HWND
hWnd
,
LPARAM
lParam
,
UINT
notification
,
UINT
control
,
LFSPRIVATE
lfs
)
{
switch
(
control
)
{
case
lst1
:
/* file list */
FILEDLG_StripEditControl
(
hWnd
);
if
(
notification
==
LBN_DBLCLK
)
{
if
(
FILEDLG_Validate
(
lfs
,
NULL
,
control
,
0
,
FALSE
))
EndDialog
(
hWnd
,
TRUE
);
return
TRUE
;
}
else
if
(
notification
==
LBN_SELCHANGE
)
return
FILEDLG_FileListSelect
(
lfs
);
break
;
case
lst2
:
/* directory list */
FILEDLG_StripEditControl
(
hWnd
);
if
(
notification
==
LBN_DBLCLK
)
return
FILEDLG_DirListDblClick
(
lfs
);
break
;
case
cmb1
:
/* file type drop list */
if
(
notification
==
CBN_SELCHANGE
)
return
FILEDLG_FileTypeChange
(
lfs
);
break
;
case
chx1
:
break
;
case
pshHelp
:
break
;
case
cmb2
:
/* disk dropdown combo */
if
(
notification
==
CBN_SELCHANGE
)
return
FILEDLG_DiskChange
(
lfs
);
break
;
case
IDOK
:
TRACE
(
"OK pressed
\n
"
);
if
(
FILEDLG_Validate
(
lfs
,
NULL
,
control
,
0
,
FALSE
))
EndDialog
(
hWnd
,
TRUE
);
return
TRUE
;
case
IDCANCEL
:
EndDialog
(
hWnd
,
FALSE
);
return
TRUE
;
case
IDABORT
:
/* can be sent by the hook procedure */
EndDialog
(
hWnd
,
TRUE
);
return
TRUE
;
}
return
FALSE
;
}
/***********************************************************************
* FILEDLG_MapDrawItemStruct [internal]
* map a 16 bits drawitem struct to 32
*/
static
void
FILEDLG_MapDrawItemStruct
(
LPDRAWITEMSTRUCT16
lpdis16
,
LPDRAWITEMSTRUCT
lpdis
)
{
lpdis
->
CtlType
=
lpdis16
->
CtlType
;
lpdis
->
CtlID
=
lpdis16
->
CtlID
;
lpdis
->
itemID
=
lpdis16
->
itemID
;
lpdis
->
itemAction
=
lpdis16
->
itemAction
;
lpdis
->
itemState
=
lpdis16
->
itemState
;
lpdis
->
hwndItem
=
HWND_32
(
lpdis16
->
hwndItem
);
lpdis
->
hDC
=
HDC_32
(
lpdis16
->
hDC
);
lpdis
->
rcItem
.
right
=
lpdis16
->
rcItem
.
right
;
lpdis
->
rcItem
.
left
=
lpdis16
->
rcItem
.
left
;
lpdis
->
rcItem
.
top
=
lpdis16
->
rcItem
.
top
;
lpdis
->
rcItem
.
bottom
=
lpdis16
->
rcItem
.
bottom
;
lpdis
->
itemData
=
lpdis16
->
itemData
;
}
/************************************************************************
* FILEDLG_MapStringPairsToW [internal]
* map string pairs to Unicode
*/
static
LPWSTR
FILEDLG_MapStringPairsToW
(
LPCSTR
strA
,
UINT
size
)
{
LPCSTR
s
;
LPWSTR
x
;
int
n
,
len
;
s
=
strA
;
while
(
*
s
)
s
=
s
+
strlen
(
s
)
+
1
;
s
++
;
n
=
s
+
1
-
strA
;
/* Don't forget the other \0 */
if
(
n
<
size
)
n
=
size
;
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
strA
,
n
,
NULL
,
0
);
x
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
MultiByteToWideChar
(
CP_ACP
,
0
,
strA
,
n
,
x
,
len
);
return
x
;
}
/************************************************************************
* FILEDLG_DupToW [internal]
* duplicates an Ansi string to unicode, with a buffer size
*/
LPWSTR
FILEDLG_DupToW
(
LPCSTR
str
,
DWORD
size
)
{
LPWSTR
strW
=
NULL
;
if
(
str
&&
(
size
>
0
))
{
strW
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
*
sizeof
(
WCHAR
));
if
(
strW
)
MultiByteToWideChar
(
CP_ACP
,
0
,
str
,
-
1
,
strW
,
size
);
}
return
strW
;
}
/************************************************************************
* FILEDLG_MapOfnStructA [internal]
* map a 32 bits Ansi structure to an Unicode one
*/
void
FILEDLG_MapOfnStructA
(
LPOPENFILENAMEA
ofnA
,
LPOPENFILENAMEW
ofnW
,
BOOL
open
)
{
LPCSTR
str
;
UNICODE_STRING
usBuffer
;
ofnW
->
lStructSize
=
sizeof
(
OPENFILENAMEW
);
ofnW
->
hwndOwner
=
ofnA
->
hwndOwner
;
ofnW
->
hInstance
=
ofnA
->
hInstance
;
if
(
ofnA
->
lpstrFilter
)
ofnW
->
lpstrFilter
=
FILEDLG_MapStringPairsToW
(
ofnA
->
lpstrFilter
,
0
);
if
((
ofnA
->
lpstrCustomFilter
)
&&
(
*
(
ofnA
->
lpstrCustomFilter
)))
ofnW
->
lpstrCustomFilter
=
FILEDLG_MapStringPairsToW
(
ofnA
->
lpstrCustomFilter
,
ofnA
->
nMaxCustFilter
);
ofnW
->
nMaxCustFilter
=
ofnA
->
nMaxCustFilter
;
ofnW
->
nFilterIndex
=
ofnA
->
nFilterIndex
;
ofnW
->
nMaxFile
=
ofnA
->
nMaxFile
;
ofnW
->
lpstrFile
=
FILEDLG_DupToW
(
ofnA
->
lpstrFile
,
ofnW
->
nMaxFile
);
ofnW
->
nMaxFileTitle
=
ofnA
->
nMaxFileTitle
;
ofnW
->
lpstrFileTitle
=
FILEDLG_DupToW
(
ofnA
->
lpstrFileTitle
,
ofnW
->
nMaxFileTitle
);
if
(
ofnA
->
lpstrInitialDir
)
{
RtlCreateUnicodeStringFromAsciiz
(
&
usBuffer
,
ofnA
->
lpstrInitialDir
);
ofnW
->
lpstrInitialDir
=
usBuffer
.
Buffer
;
}
if
(
ofnA
->
lpstrTitle
)
str
=
ofnA
->
lpstrTitle
;
else
/* Allocates default title (FIXME : get it from resource) */
str
=
open
?
defaultopen
:
defaultsave
;
RtlCreateUnicodeStringFromAsciiz
(
&
usBuffer
,
ofnA
->
lpstrTitle
);
ofnW
->
lpstrTitle
=
usBuffer
.
Buffer
;
ofnW
->
Flags
=
ofnA
->
Flags
;
ofnW
->
nFileOffset
=
ofnA
->
nFileOffset
;
ofnW
->
nFileExtension
=
ofnA
->
nFileExtension
;
ofnW
->
lpstrDefExt
=
FILEDLG_DupToW
(
ofnA
->
lpstrDefExt
,
3
);
if
((
ofnA
->
Flags
&
OFN_ENABLETEMPLATE
)
&&
(
ofnA
->
lpTemplateName
))
{
if
(
HIWORD
(
ofnA
->
lpTemplateName
))
{
RtlCreateUnicodeStringFromAsciiz
(
&
usBuffer
,
ofnA
->
lpTemplateName
);
ofnW
->
lpTemplateName
=
usBuffer
.
Buffer
;
}
else
/* numbered resource */
ofnW
->
lpTemplateName
=
(
LPWSTR
)
ofnA
->
lpTemplateName
;
}
}
/************************************************************************
* FILEDLG_MapOfnStruct16 [internal]
* map a 16 bits structure to an Unicode one
*/
void
FILEDLG_MapOfnStruct16
(
LPOPENFILENAME16
ofn16
,
LPOPENFILENAMEW
ofnW
,
BOOL
open
)
{
OPENFILENAMEA
ofnA
;
/* first convert to linear pointers */
memset
(
&
ofnA
,
0
,
sizeof
(
OPENFILENAMEA
));
ofnA
.
lStructSize
=
sizeof
(
OPENFILENAMEA
);
ofnA
.
hwndOwner
=
HWND_32
(
ofn16
->
hwndOwner
);
ofnA
.
hInstance
=
HINSTANCE_32
(
ofn16
->
hInstance
);
if
(
ofn16
->
lpstrFilter
)
ofnA
.
lpstrFilter
=
MapSL
(
ofn16
->
lpstrFilter
);
if
(
ofn16
->
lpstrCustomFilter
)
ofnA
.
lpstrCustomFilter
=
MapSL
(
ofn16
->
lpstrCustomFilter
);
ofnA
.
nMaxCustFilter
=
ofn16
->
nMaxCustFilter
;
ofnA
.
nFilterIndex
=
ofn16
->
nFilterIndex
;
ofnA
.
lpstrFile
=
MapSL
(
ofn16
->
lpstrFile
);
ofnA
.
nMaxFile
=
ofn16
->
nMaxFile
;
ofnA
.
lpstrFileTitle
=
MapSL
(
ofn16
->
lpstrFileTitle
);
ofnA
.
nMaxFileTitle
=
ofn16
->
nMaxFileTitle
;
ofnA
.
lpstrInitialDir
=
MapSL
(
ofn16
->
lpstrInitialDir
);
ofnA
.
lpstrTitle
=
MapSL
(
ofn16
->
lpstrTitle
);
ofnA
.
Flags
=
ofn16
->
Flags
;
ofnA
.
nFileOffset
=
ofn16
->
nFileOffset
;
ofnA
.
nFileExtension
=
ofn16
->
nFileExtension
;
ofnA
.
lpstrDefExt
=
MapSL
(
ofn16
->
lpstrDefExt
);
if
(
HIWORD
(
ofn16
->
lpTemplateName
))
ofnA
.
lpTemplateName
=
MapSL
(
ofn16
->
lpTemplateName
);
else
ofnA
.
lpTemplateName
=
(
LPSTR
)
ofn16
->
lpTemplateName
;
/* ressource number */
/* now calls the 32 bits Ansi to Unicode version to complete the job */
FILEDLG_MapOfnStructA
(
&
ofnA
,
ofnW
,
open
);
}
/************************************************************************
* FILEDLG_DestroyPrivate [internal]
* destroys the private object
*/
static
void
FILEDLG_DestroyPrivate
(
LFSPRIVATE
lfs
)
{
HWND
hwnd
;
if
(
!
lfs
)
return
;
hwnd
=
lfs
->
hwnd
;
/* free resources for a 16 bits dialog */
if
(
lfs
->
hResource16
)
FreeResource16
(
lfs
->
hResource16
);
if
(
lfs
->
hGlobal16
)
{
GlobalUnlock16
(
lfs
->
hGlobal16
);
GlobalFree16
(
lfs
->
hGlobal16
);
}
/* if ofnW has been allocated, have to free everything in it */
if
(
lfs
->
ofn16
||
lfs
->
ofnA
)
{
LPOPENFILENAMEW
ofnW
=
lfs
->
ofnW
;
if
(
ofnW
->
lpstrFilter
)
HeapFree
(
GetProcessHeap
(),
0
,
(
LPWSTR
)
ofnW
->
lpstrFilter
);
if
(
ofnW
->
lpstrCustomFilter
)
HeapFree
(
GetProcessHeap
(),
0
,
ofnW
->
lpstrCustomFilter
);
if
(
ofnW
->
lpstrFile
)
HeapFree
(
GetProcessHeap
(),
0
,
ofnW
->
lpstrFile
);
if
(
ofnW
->
lpstrFileTitle
)
HeapFree
(
GetProcessHeap
(),
0
,
ofnW
->
lpstrFileTitle
);
if
(
ofnW
->
lpstrInitialDir
)
HeapFree
(
GetProcessHeap
(),
0
,
(
LPWSTR
)
ofnW
->
lpstrInitialDir
);
if
(
ofnW
->
lpstrTitle
)
HeapFree
(
GetProcessHeap
(),
0
,
(
LPWSTR
)
ofnW
->
lpstrTitle
);
if
((
ofnW
->
lpTemplateName
)
&&
(
HIWORD
(
ofnW
->
lpTemplateName
)))
HeapFree
(
GetProcessHeap
(),
0
,
(
LPWSTR
)
ofnW
->
lpTemplateName
);
HeapFree
(
GetProcessHeap
(),
0
,
ofnW
);
}
TRACE
(
"destroying private allocation %p
\n
"
,
lfs
);
HeapFree
(
GetProcessHeap
(),
0
,
lfs
);
RemovePropA
(
hwnd
,
OFN_PROP
);
}
/************************************************************************
* FILEDLG_AllocPrivate [internal]
* allocate a private object to hold 32 bits Unicode
* structure that will be used throughtout the calls, while
* keeping available the original structures and a few variables
* On entry : type = dialog procedure type (16,32A,32W)
* dlgType = dialog type (open or save)
*/
static
LFSPRIVATE
FILEDLG_AllocPrivate
(
LPARAM
lParam
,
int
type
,
UINT
dlgType
)
{
LFSPRIVATE
lfs
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
struct
FSPRIVATE
));
LFSPRIVATE
ret
;
TRACE
(
"alloc private buf %p
\n
"
,
lfs
);
if
(
!
lfs
)
return
NULL
;
lfs
->
hook
=
FALSE
;
lfs
->
lParam
=
lParam
;
if
(
dlgType
==
OPEN_DIALOG
)
lfs
->
open
=
TRUE
;
else
lfs
->
open
=
FALSE
;
lfs
->
lbselchstring
=
RegisterWindowMessageA
(
LBSELCHSTRINGA
);
lfs
->
fileokstring
=
RegisterWindowMessageA
(
FILEOKSTRINGA
);
switch
(
type
)
{
case
LFS16
:
lfs
->
ofn16
=
MapSL
(
lParam
);
if
(
lfs
->
ofn16
->
Flags
&
OFN_ENABLEHOOK
)
if
(
lfs
->
ofn16
->
lpfnHook
)
lfs
->
hook
=
TRUE
;
break
;
case
LFS32A
:
lfs
->
ofnA
=
(
LPOPENFILENAMEA
)
lParam
;
if
(
lfs
->
ofnA
->
Flags
&
OFN_ENABLEHOOK
)
if
(
lfs
->
ofnA
->
lpfnHook
)
lfs
->
hook
=
TRUE
;
break
;
case
LFS32W
:
lfs
->
ofnW
=
(
LPOPENFILENAMEW
)
lParam
;
if
(
lfs
->
ofnW
->
Flags
&
OFN_ENABLEHOOK
)
if
(
lfs
->
ofnW
->
lpfnHook
)
lfs
->
hook
=
TRUE
;
break
;
}
ret
=
lfs
;
if
(
!
lfs
->
ofnW
)
{
/* this structure is needed internally, so create it */
lfs
->
ofnW
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
OPENFILENAMEW
));
if
(
lfs
->
ofnW
)
{
if
(
lfs
->
ofn16
)
FILEDLG_MapOfnStruct16
(
lfs
->
ofn16
,
lfs
->
ofnW
,
lfs
->
open
);
if
(
lfs
->
ofnA
)
FILEDLG_MapOfnStructA
(
lfs
->
ofnA
,
lfs
->
ofnW
,
lfs
->
open
);
}
else
ret
=
NULL
;
}
if
(
lfs
->
ofn16
)
{
if
(
!
Get16BitsTemplate
(
lfs
))
ret
=
NULL
;
}
else
if
(
!
Get32BitsTemplate
(
lfs
))
ret
=
NULL
;
if
(
!
ret
)
FILEDLG_DestroyPrivate
(
lfs
);
return
ret
;
}
/***********************************************************************
* FILEDLG_CallWindowProc16 [internal]
...
...
dlls/commdlg/filedlg95.c
deleted
100644 → 0
View file @
a167c3bb
/*
* COMMDLG - File Open Dialogs Win95 look and feel
*
* Copyright 1999 Francois Boisvert
* Copyright 1999, 2000 Juergen Schmied
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FIXME: The whole concept of handling unicode is badly broken.
* many hook-messages expect a pointer to a
* OPENFILENAMEA or W structure. With the current architecture
* we would have to convert the beast at every call to a hook.
* we have to find a better solution but it would likely cause
* a complete rewrite after which we should handle the
* OPENFILENAME structure without any converting (jsch).
*
* FIXME: any hook gets a OPENFILENAMEA structure
*
* FIXME: CDN_FILEOK is wrong implemented, other CDN_ messages likely too
*
* FIXME: old style hook messages are not implemented (except FILEOKSTRING)
*
* FIXME: lpstrCustomFilter not handled
*
* FIXME: if the size of lpstrFile (nMaxFile) is too small the first
* two bytes of lpstrFile should contain the needed size
*
* FIXME: algorithm for selecting the initial directory is too simple
*
* FIXME: add to recent docs
*
* FIXME: flags not implemented: OFN_CREATEPROMPT, OFN_DONTADDTORECENT,
* OFN_ENABLEINCLUDENOTIFY, OFN_ENABLESIZING, OFN_EXTENSIONDIFFERENT,
* OFN_NODEREFERENCELINKS, OFN_NOREADONLYRETURN,
* OFN_NOTESTFILECREATE, OFN_OVERWRITEPROMPT, OFN_USEMONIKERS
*
* FIXME: lCustData for lpfnHook (WM_INITDIALOG)
*
*
*/
#include "config.h"
#include "wine/port.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winternl.h"
#include "winnls.h"
#include "wine/unicode.h"
#include "wingdi.h"
#include "winuser.h"
#include "commdlg.h"
#include "dlgs.h"
#include "cdlg.h"
#include "wine/debug.h"
#include "cderr.h"
#include "shellapi.h"
#include "shlguid.h"
#include "shlobj.h"
#include "filedlgbrowser.h"
#include "shlwapi.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
commdlg
);
#define UNIMPLEMENTED_FLAGS \
(OFN_CREATEPROMPT | OFN_DONTADDTORECENT |\
OFN_ENABLEINCLUDENOTIFY | OFN_ENABLESIZING | OFN_EXTENSIONDIFFERENT |\
OFN_NODEREFERENCELINKS | OFN_NOREADONLYRETURN |\
OFN_NOTESTFILECREATE | OFN_OVERWRITEPROMPT
/*| OFN_USEMONIKERS*/
)
#define IsHooked(fodInfos) \
((fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
/***********************************************************************
* Data structure and global variables
*/
typedef
struct
SFolder
{
int
m_iImageIndex
;
/* Index of picture in image list */
HIMAGELIST
hImgList
;
int
m_iIndent
;
/* Indentation index */
LPITEMIDLIST
pidlItem
;
/* absolute pidl of the item */
}
SFOLDER
,
*
LPSFOLDER
;
typedef
struct
tagLookInInfo
{
int
iMaxIndentation
;
UINT
uSelectedItem
;
}
LookInInfos
;
/***********************************************************************
* Defines and global variables
*/
/* Draw item constant */
#define ICONWIDTH 18
#define XTEXTOFFSET 3
/* AddItem flags*/
#define LISTEND -1
/* SearchItem methods */
#define SEARCH_PIDL 1
#define SEARCH_EXP 2
#define ITEM_NOTFOUND -1
/* Undefined windows message sent by CreateViewObject*/
#define WM_GETISHELLBROWSER WM_USER+7
/* NOTE
* Those macros exist in windowsx.h. However, you can't really use them since
* they rely on the UNICODE defines and can't be used inside Wine itself.
*/
/* Combo box macros */
#define CBAddString(hwnd,str) \
SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
#define CBAddStringW(hwnd,str) \
SendMessageW(hwnd,CB_ADDSTRING,0,(LPARAM)str);
#define CBInsertString(hwnd,str,pos) \
SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
#define CBDeleteString(hwnd,pos) \
SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
#define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
#define CBGetItemDataPtr(hwnd,iItemId) \
SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
#define CBGetLBText(hwnd,iItemId,str) \
SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
#define CBGetCurSel(hwnd) \
SendMessageA(hwnd,CB_GETCURSEL,0,0);
#define CBSetCurSel(hwnd,pos) \
SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
#define CBGetCount(hwnd) \
SendMessageA(hwnd,CB_GETCOUNT,0,0);
#define CBShowDropDown(hwnd,show) \
SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
#define CBSetItemHeight(hwnd,index,height) \
SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
const
char
*
FileOpenDlgInfosStr
=
"FileOpenDlgInfos"
;
/* windows property description string */
const
char
*
LookInInfosStr
=
"LookInInfos"
;
/* LOOKIN combo box property */
/***********************************************************************
* Prototypes
*/
/* Internal functions used by the dialog */
static
LRESULT
FILEDLG95_FillControls
(
HWND
hwnd
,
WPARAM
wParam
,
LPARAM
lParam
);
static
LRESULT
FILEDLG95_OnWMCommand
(
HWND
hwnd
,
WPARAM
wParam
,
LPARAM
lParam
);
static
LRESULT
FILEDLG95_OnWMGetIShellBrowser
(
HWND
hwnd
);
BOOL
FILEDLG95_OnOpen
(
HWND
hwnd
);
static
LRESULT
FILEDLG95_InitControls
(
HWND
hwnd
);
static
void
FILEDLG95_Clean
(
HWND
hwnd
);
/* Functions used by the shell navigation */
static
LRESULT
FILEDLG95_SHELL_Init
(
HWND
hwnd
);
static
BOOL
FILEDLG95_SHELL_UpFolder
(
HWND
hwnd
);
static
BOOL
FILEDLG95_SHELL_ExecuteCommand
(
HWND
hwnd
,
LPCSTR
lpVerb
);
static
void
FILEDLG95_SHELL_Clean
(
HWND
hwnd
);
static
BOOL
FILEDLG95_SHELL_BrowseToDesktop
(
HWND
hwnd
);
/* Functions used by the filetype combo box */
static
HRESULT
FILEDLG95_FILETYPE_Init
(
HWND
hwnd
);
static
BOOL
FILEDLG95_FILETYPE_OnCommand
(
HWND
hwnd
,
WORD
wNotifyCode
);
static
int
FILEDLG95_FILETYPE_SearchExt
(
HWND
hwnd
,
LPCWSTR
lpstrExt
);
static
void
FILEDLG95_FILETYPE_Clean
(
HWND
hwnd
);
/* Functions used by the Look In combo box */
static
HRESULT
FILEDLG95_LOOKIN_Init
(
HWND
hwndCombo
);
static
LRESULT
FILEDLG95_LOOKIN_DrawItem
(
LPDRAWITEMSTRUCT
pDIStruct
);
static
BOOL
FILEDLG95_LOOKIN_OnCommand
(
HWND
hwnd
,
WORD
wNotifyCode
);
static
int
FILEDLG95_LOOKIN_AddItem
(
HWND
hwnd
,
LPITEMIDLIST
pidl
,
int
iInsertId
);
static
int
FILEDLG95_LOOKIN_SearchItem
(
HWND
hwnd
,
WPARAM
searchArg
,
int
iSearchMethod
);
static
int
FILEDLG95_LOOKIN_InsertItemAfterParent
(
HWND
hwnd
,
LPITEMIDLIST
pidl
);
static
int
FILEDLG95_LOOKIN_RemoveMostExpandedItem
(
HWND
hwnd
);
int
FILEDLG95_LOOKIN_SelectItem
(
HWND
hwnd
,
LPITEMIDLIST
pidl
);
static
void
FILEDLG95_LOOKIN_Clean
(
HWND
hwnd
);
/* Miscellaneous tool functions */
HRESULT
GetName
(
LPSHELLFOLDER
lpsf
,
LPITEMIDLIST
pidl
,
DWORD
dwFlags
,
LPSTR
lpstrFileName
);
HRESULT
GetFileName
(
HWND
hwnd
,
LPITEMIDLIST
pidl
,
LPSTR
lpstrFileName
);
IShellFolder
*
GetShellFolderFromPidl
(
LPITEMIDLIST
pidlAbs
);
LPITEMIDLIST
GetParentPidl
(
LPITEMIDLIST
pidl
);
LPITEMIDLIST
GetPidlFromName
(
IShellFolder
*
psf
,
LPWSTR
lpcstrFileName
);
/* Shell memory allocation */
static
void
*
MemAlloc
(
UINT
size
);
static
void
MemFree
(
void
*
mem
);
BOOL
WINAPI
GetFileName95
(
FileOpenDlgInfos
*
fodInfos
);
INT_PTR
CALLBACK
FileOpenDlgProc95
(
HWND
hwnd
,
UINT
uMsg
,
WPARAM
wParam
,
LPARAM
lParam
);
HRESULT
SendCustomDlgNotificationMessage
(
HWND
hwndParentDlg
,
UINT
uCode
);
HRESULT
FILEDLG95_HandleCustomDialogMessages
(
HWND
hwnd
,
UINT
uMsg
,
WPARAM
wParam
,
LPARAM
lParam
);
BOOL
FILEDLG95_OnOpenMultipleFiles
(
HWND
hwnd
,
LPWSTR
lpstrFileList
,
UINT
nFileCount
,
UINT
sizeUsed
);
static
BOOL
BrowseSelectedFolder
(
HWND
hwnd
);
/***********************************************************************
* GetFileName95
*
* Creates an Open common dialog box that lets the user select
* the drive, directory, and the name of a file or set of files to open.
*
* IN : The FileOpenDlgInfos structure associated with the dialog
* OUT : TRUE on success
* FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
*/
BOOL
WINAPI
GetFileName95
(
FileOpenDlgInfos
*
fodInfos
)
{
LRESULT
lRes
;
LPCVOID
template
;
HRSRC
hRes
;
HANDLE
hDlgTmpl
=
0
;
/* test for missing functionality */
if
(
fodInfos
->
ofnInfos
->
Flags
&
UNIMPLEMENTED_FLAGS
)
{
FIXME
(
"Flags 0x%08lx not yet implemented
\n
"
,
fodInfos
->
ofnInfos
->
Flags
&
UNIMPLEMENTED_FLAGS
);
}
/* Create the dialog from a template */
if
(
!
(
hRes
=
FindResourceA
(
COMDLG32_hInstance
,
MAKEINTRESOURCEA
(
NEWFILEOPENORD
),(
LPSTR
)
RT_DIALOG
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_FINDRESFAILURE
);
return
FALSE
;
}
if
(
!
(
hDlgTmpl
=
LoadResource
(
COMDLG32_hInstance
,
hRes
))
||
!
(
template
=
LockResource
(
hDlgTmpl
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_LOADRESFAILURE
);
return
FALSE
;
}
/* old style hook messages */
if
(
IsHooked
(
fodInfos
))
{
fodInfos
->
HookMsg
.
fileokstring
=
RegisterWindowMessageA
(
FILEOKSTRINGA
);
fodInfos
->
HookMsg
.
lbselchstring
=
RegisterWindowMessageA
(
LBSELCHSTRINGA
);
fodInfos
->
HookMsg
.
helpmsgstring
=
RegisterWindowMessageA
(
HELPMSGSTRINGA
);
fodInfos
->
HookMsg
.
sharevistring
=
RegisterWindowMessageA
(
SHAREVISTRINGA
);
}
lRes
=
DialogBoxIndirectParamA
(
COMDLG32_hInstance
,
(
LPDLGTEMPLATEA
)
template
,
fodInfos
->
ofnInfos
->
hwndOwner
,
FileOpenDlgProc95
,
(
LPARAM
)
fodInfos
);
/* Unable to create the dialog */
if
(
lRes
==
-
1
)
return
FALSE
;
return
lRes
;
}
/***********************************************************************
* GetFileDialog95A
*
* Call GetFileName95 with this structure and clean the memory.
*
* IN : The OPENFILENAMEA initialisation structure passed to
* GetOpenFileNameA win api function (see filedlg.c)
*/
BOOL
WINAPI
GetFileDialog95A
(
LPOPENFILENAMEA
ofn
,
UINT
iDlgType
)
{
BOOL
ret
;
FileOpenDlgInfos
fodInfos
;
LPSTR
lpstrSavDir
=
NULL
;
LPWSTR
title
=
NULL
;
LPWSTR
defext
=
NULL
;
LPWSTR
filter
=
NULL
;
LPWSTR
customfilter
=
NULL
;
/* Initialize FileOpenDlgInfos structure */
ZeroMemory
(
&
fodInfos
,
sizeof
(
FileOpenDlgInfos
));
/* Pass in the original ofn */
fodInfos
.
ofnInfos
=
ofn
;
/* save current directory */
if
(
ofn
->
Flags
&
OFN_NOCHANGEDIR
)
{
lpstrSavDir
=
MemAlloc
(
MAX_PATH
);
GetCurrentDirectoryA
(
MAX_PATH
,
lpstrSavDir
);
}
fodInfos
.
unicode
=
FALSE
;
/* convert all the input strings to unicode */
if
(
ofn
->
lpstrInitialDir
)
{
DWORD
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrInitialDir
,
-
1
,
NULL
,
0
);
fodInfos
.
initdir
=
MemAlloc
((
len
+
1
)
*
sizeof
(
WCHAR
));
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrInitialDir
,
-
1
,
fodInfos
.
initdir
,
len
);
}
else
fodInfos
.
initdir
=
NULL
;
if
(
ofn
->
lpstrFile
)
{
fodInfos
.
filename
=
MemAlloc
(
ofn
->
nMaxFile
*
sizeof
(
WCHAR
));
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrFile
,
-
1
,
fodInfos
.
filename
,
ofn
->
nMaxFile
);
}
else
fodInfos
.
filename
=
NULL
;
if
(
ofn
->
lpstrDefExt
)
{
DWORD
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrDefExt
,
-
1
,
NULL
,
0
);
defext
=
MemAlloc
((
len
+
1
)
*
sizeof
(
WCHAR
));
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrDefExt
,
-
1
,
defext
,
len
);
}
fodInfos
.
defext
=
defext
;
if
(
ofn
->
lpstrTitle
)
{
DWORD
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrTitle
,
-
1
,
NULL
,
0
);
title
=
MemAlloc
((
len
+
1
)
*
sizeof
(
WCHAR
));
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrTitle
,
-
1
,
title
,
len
);
}
fodInfos
.
title
=
title
;
if
(
ofn
->
lpstrFilter
)
{
LPCSTR
s
;
int
n
,
len
;
/* filter is a list... title\0ext\0......\0\0 */
s
=
ofn
->
lpstrFilter
;
while
(
*
s
)
s
=
s
+
strlen
(
s
)
+
1
;
s
++
;
n
=
s
-
ofn
->
lpstrFilter
;
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrFilter
,
n
,
NULL
,
0
);
filter
=
MemAlloc
(
len
*
sizeof
(
WCHAR
));
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrFilter
,
n
,
filter
,
len
);
}
fodInfos
.
filter
=
filter
;
/* convert lpstrCustomFilter */
if
(
ofn
->
lpstrCustomFilter
)
{
LPCSTR
s
;
int
n
,
len
;
/* filter is a list... title\0ext\0......\0\0 */
s
=
ofn
->
lpstrCustomFilter
;
while
(
*
s
)
s
=
s
+
strlen
(
s
)
+
1
;
s
++
;
n
=
s
-
ofn
->
lpstrCustomFilter
;
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrCustomFilter
,
n
,
NULL
,
0
);
customfilter
=
MemAlloc
(
len
*
sizeof
(
WCHAR
));
MultiByteToWideChar
(
CP_ACP
,
0
,
ofn
->
lpstrCustomFilter
,
n
,
customfilter
,
len
);
}
fodInfos
.
customfilter
=
customfilter
;
/* Initialize the dialog property */
fodInfos
.
DlgInfos
.
dwDlgProp
=
0
;
fodInfos
.
DlgInfos
.
hwndCustomDlg
=
NULL
;
switch
(
iDlgType
)
{
case
OPEN_DIALOG
:
ret
=
GetFileName95
(
&
fodInfos
);
break
;
case
SAVE_DIALOG
:
fodInfos
.
DlgInfos
.
dwDlgProp
|=
FODPROP_SAVEDLG
;
ret
=
GetFileName95
(
&
fodInfos
);
break
;
default
:
ret
=
0
;
}
if
(
lpstrSavDir
)
{
SetCurrentDirectoryA
(
lpstrSavDir
);
MemFree
(
lpstrSavDir
);
}
if
(
title
)
MemFree
(
title
);
if
(
defext
)
MemFree
(
defext
);
if
(
filter
)
MemFree
(
filter
);
if
(
customfilter
)
MemFree
(
customfilter
);
if
(
fodInfos
.
initdir
)
MemFree
(
fodInfos
.
initdir
);
if
(
fodInfos
.
filename
)
MemFree
(
fodInfos
.
filename
);
TRACE
(
"selected file: %s
\n
"
,
ofn
->
lpstrFile
);
return
ret
;
}
/***********************************************************************
* GetFileDialog95W
*
* Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
* Call GetFileName95 with this structure and clean the memory.
*
* FIXME: lpstrCustomFilter has to be converted back
*
*/
BOOL
WINAPI
GetFileDialog95W
(
LPOPENFILENAMEW
ofn
,
UINT
iDlgType
)
{
BOOL
ret
;
FileOpenDlgInfos
fodInfos
;
LPSTR
lpstrSavDir
=
NULL
;
/* Initialize FileOpenDlgInfos structure */
ZeroMemory
(
&
fodInfos
,
sizeof
(
FileOpenDlgInfos
));
/* Pass in the original ofn */
fodInfos
.
ofnInfos
=
(
LPOPENFILENAMEA
)
ofn
;
fodInfos
.
title
=
ofn
->
lpstrTitle
;
fodInfos
.
defext
=
ofn
->
lpstrDefExt
;
fodInfos
.
filter
=
ofn
->
lpstrFilter
;
fodInfos
.
customfilter
=
ofn
->
lpstrCustomFilter
;
/* convert string arguments, save others */
if
(
ofn
->
lpstrFile
)
{
fodInfos
.
filename
=
MemAlloc
(
ofn
->
nMaxFile
*
sizeof
(
WCHAR
));
strncpyW
(
fodInfos
.
filename
,
ofn
->
lpstrFile
,
ofn
->
nMaxFile
);
}
else
fodInfos
.
filename
=
NULL
;
if
(
ofn
->
lpstrInitialDir
)
{
DWORD
len
=
strlenW
(
ofn
->
lpstrInitialDir
);
fodInfos
.
initdir
=
MemAlloc
((
len
+
1
)
*
sizeof
(
WCHAR
));
strcpyW
(
fodInfos
.
initdir
,
ofn
->
lpstrInitialDir
);
}
else
fodInfos
.
initdir
=
NULL
;
/* save current directory */
if
(
ofn
->
Flags
&
OFN_NOCHANGEDIR
)
{
lpstrSavDir
=
MemAlloc
(
MAX_PATH
);
GetCurrentDirectoryA
(
MAX_PATH
,
lpstrSavDir
);
}
fodInfos
.
unicode
=
TRUE
;
switch
(
iDlgType
)
{
case
OPEN_DIALOG
:
ret
=
GetFileName95
(
&
fodInfos
);
break
;
case
SAVE_DIALOG
:
fodInfos
.
DlgInfos
.
dwDlgProp
|=
FODPROP_SAVEDLG
;
ret
=
GetFileName95
(
&
fodInfos
);
break
;
default
:
ret
=
0
;
}
if
(
lpstrSavDir
)
{
SetCurrentDirectoryA
(
lpstrSavDir
);
MemFree
(
lpstrSavDir
);
}
/* restore saved IN arguments and convert OUT arguments back */
MemFree
(
fodInfos
.
filename
);
MemFree
(
fodInfos
.
initdir
);
return
ret
;
}
/***********************************************************************
* ArrangeCtrlPositions [internal]
*
* NOTE: Do not change anything here without a lot of testing.
*/
static
void
ArrangeCtrlPositions
(
HWND
hwndChildDlg
,
HWND
hwndParentDlg
,
BOOL
hide_help
)
{
HWND
hwndChild
,
hwndStc32
;
RECT
rectParent
,
rectChild
,
rectStc32
;
INT
help_fixup
=
0
;
/* Take into account if open as read only checkbox and help button
* are hidden
*/
if
(
hide_help
)
{
RECT
rectHelp
,
rectCancel
;
GetWindowRect
(
GetDlgItem
(
hwndParentDlg
,
pshHelp
),
&
rectHelp
);
GetWindowRect
(
GetDlgItem
(
hwndParentDlg
,
IDCANCEL
),
&
rectCancel
);
/* subtract the height of the help button plus the space between
* the help button and the cancel button to the height of the dialog
*/
help_fixup
=
rectHelp
.
bottom
-
rectCancel
.
bottom
;
}
/*
There are two possibilities to add components to the default file dialog box.
By default, all the new components are added below the standard dialog box (the else case).
However, if there is a static text component with the stc32 id, a special case happens.
The x and y coordinates of stc32 indicate the top left corner where to place the standard file dialog box
in the window and the cx and cy indicate how to size the window.
Moreover, if the new component's coordinates are on the left of the stc32 , it is placed on the left
of the standard file dialog box. If they are above the stc32 component, it is placed above and so on....
*/
GetClientRect
(
hwndParentDlg
,
&
rectParent
);
/* when arranging controls we have to use fixed parent size */
rectParent
.
bottom
-=
help_fixup
;
hwndStc32
=
GetDlgItem
(
hwndChildDlg
,
stc32
);
if
(
hwndStc32
)
{
GetWindowRect
(
hwndStc32
,
&
rectStc32
);
MapWindowPoints
(
0
,
hwndChildDlg
,
(
LPPOINT
)
&
rectStc32
,
2
);
/* set the size of the stc32 control according to the size of
* client area of the parent dialog
*/
SetWindowPos
(
hwndStc32
,
0
,
0
,
0
,
rectParent
.
right
,
rectParent
.
bottom
,
SWP_NOMOVE
|
SWP_NOZORDER
);
}
else
SetRectEmpty
(
&
rectStc32
);
/* this part moves controls of the child dialog */
hwndChild
=
GetWindow
(
hwndChildDlg
,
GW_CHILD
);
while
(
hwndChild
)
{
if
(
hwndChild
!=
hwndStc32
)
{
GetWindowRect
(
hwndChild
,
&
rectChild
);
MapWindowPoints
(
0
,
hwndChildDlg
,
(
LPPOINT
)
&
rectChild
,
2
);
/* move only if stc32 exist */
if
(
hwndStc32
&&
rectChild
.
left
>
rectStc32
.
right
)
{
/* move to the right of visible controls of the parent dialog */
rectChild
.
left
+=
rectParent
.
right
;
rectChild
.
left
-=
rectStc32
.
right
;
}
/* move even if stc32 doesn't exist */
if
(
rectChild
.
top
>
rectStc32
.
bottom
)
{
/* move below visible controls of the parent dialog */
rectChild
.
top
+=
rectParent
.
bottom
;
rectChild
.
top
-=
rectStc32
.
bottom
-
rectStc32
.
top
;
}
SetWindowPos
(
hwndChild
,
0
,
rectChild
.
left
,
rectChild
.
top
,
0
,
0
,
SWP_NOSIZE
|
SWP_NOZORDER
);
}
hwndChild
=
GetWindow
(
hwndChild
,
GW_HWNDNEXT
);
}
/* this part moves controls of the parent dialog */
hwndChild
=
GetWindow
(
hwndParentDlg
,
GW_CHILD
);
while
(
hwndChild
)
{
if
(
hwndChild
!=
hwndChildDlg
)
{
GetWindowRect
(
hwndChild
,
&
rectChild
);
MapWindowPoints
(
0
,
hwndParentDlg
,
(
LPPOINT
)
&
rectChild
,
2
);
/* left,top of stc32 marks the position of controls
* from the parent dialog
*/
rectChild
.
left
+=
rectStc32
.
left
;
rectChild
.
top
+=
rectStc32
.
top
;
SetWindowPos
(
hwndChild
,
0
,
rectChild
.
left
,
rectChild
.
top
,
0
,
0
,
SWP_NOSIZE
|
SWP_NOZORDER
);
}
hwndChild
=
GetWindow
(
hwndChild
,
GW_HWNDNEXT
);
}
/* calculate the size of the resulting dialog */
/* here we have to use original parent size */
GetClientRect
(
hwndParentDlg
,
&
rectParent
);
GetClientRect
(
hwndChildDlg
,
&
rectChild
);
if
(
hwndStc32
)
{
if
(
rectParent
.
right
>
rectChild
.
right
)
{
rectParent
.
right
+=
rectChild
.
right
;
rectParent
.
right
-=
rectStc32
.
right
-
rectStc32
.
left
;
}
else
{
rectParent
.
right
=
rectChild
.
right
;
}
if
(
rectParent
.
bottom
>
rectChild
.
bottom
)
{
rectParent
.
bottom
+=
rectChild
.
bottom
;
rectParent
.
bottom
-=
rectStc32
.
bottom
-
rectStc32
.
top
;
}
else
{
rectParent
.
bottom
=
rectChild
.
bottom
;
}
}
else
{
rectParent
.
bottom
+=
rectChild
.
bottom
;
}
/* finally use fixed parent size */
rectParent
.
bottom
-=
help_fixup
;
/* save the size of the parent's client area */
rectChild
.
right
=
rectParent
.
right
;
rectChild
.
bottom
=
rectParent
.
bottom
;
/* set the size of the parent dialog */
AdjustWindowRectEx
(
&
rectParent
,
GetWindowLongW
(
hwndParentDlg
,
GWL_STYLE
),
FALSE
,
GetWindowLongW
(
hwndParentDlg
,
GWL_EXSTYLE
));
SetWindowPos
(
hwndParentDlg
,
0
,
0
,
0
,
rectParent
.
right
-
rectParent
.
left
,
rectParent
.
bottom
-
rectParent
.
top
,
SWP_NOMOVE
|
SWP_NOZORDER
);
/* set the size of the child dialog */
SetWindowPos
(
hwndChildDlg
,
HWND_BOTTOM
,
0
,
0
,
rectChild
.
right
,
rectChild
.
bottom
,
SWP_NOACTIVATE
);
}
INT_PTR
CALLBACK
FileOpenDlgProcUserTemplate
(
HWND
hwnd
,
UINT
uMsg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
FileOpenDlgInfos
*
fodInfos
;
#if 0
TRACE("0x%04x\n", uMsg);
#endif
switch
(
uMsg
)
{
case
WM_INITDIALOG
:
{
fodInfos
=
(
FileOpenDlgInfos
*
)
lParam
;
lParam
=
(
LPARAM
)
fodInfos
->
ofnInfos
;
if
(
fodInfos
&&
IsHooked
(
fodInfos
))
return
CallWindowProcA
((
WNDPROC
)
fodInfos
->
ofnInfos
->
lpfnHook
,
hwnd
,
uMsg
,
wParam
,
lParam
);
return
0
;
}
}
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
GetParent
(
hwnd
),
FileOpenDlgInfosStr
);
if
(
fodInfos
&&
IsHooked
(
fodInfos
))
return
CallWindowProcA
((
WNDPROC
)
fodInfos
->
ofnInfos
->
lpfnHook
,
hwnd
,
uMsg
,
wParam
,
lParam
);
return
0
;
}
HWND
CreateTemplateDialog
(
FileOpenDlgInfos
*
fodInfos
,
HWND
hwnd
)
{
LPCVOID
template
;
HRSRC
hRes
;
HANDLE
hDlgTmpl
=
0
;
HWND
hChildDlg
=
0
;
TRACE
(
"
\n
"
);
/*
* If OFN_ENABLETEMPLATEHANDLE is specified, the OPENFILENAME
* structure's hInstance parameter is not a HINSTANCE, but
* instead a pointer to a template resource to use.
*/
if
(
fodInfos
->
ofnInfos
->
Flags
&
(
OFN_ENABLETEMPLATE
|
OFN_ENABLETEMPLATEHANDLE
))
{
HINSTANCE
hinst
;
if
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_ENABLETEMPLATEHANDLE
)
{
hinst
=
0
;
if
(
!
(
template
=
LockResource
(
fodInfos
->
ofnInfos
->
hInstance
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_LOADRESFAILURE
);
return
NULL
;
}
}
else
{
hinst
=
fodInfos
->
ofnInfos
->
hInstance
;
if
(
fodInfos
->
unicode
)
{
LPOPENFILENAMEW
ofn
=
(
LPOPENFILENAMEW
)
fodInfos
->
ofnInfos
;
hRes
=
FindResourceW
(
hinst
,
ofn
->
lpTemplateName
,
(
LPWSTR
)
RT_DIALOG
);
}
else
{
LPOPENFILENAMEA
ofn
=
fodInfos
->
ofnInfos
;
hRes
=
FindResourceA
(
hinst
,
ofn
->
lpTemplateName
,
(
LPSTR
)
RT_DIALOG
);
}
if
(
!
hRes
)
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_FINDRESFAILURE
);
return
NULL
;
}
if
(
!
(
hDlgTmpl
=
LoadResource
(
hinst
,
hRes
))
||
!
(
template
=
LockResource
(
hDlgTmpl
)))
{
COMDLG32_SetCommDlgExtendedError
(
CDERR_LOADRESFAILURE
);
return
NULL
;
}
}
hChildDlg
=
CreateDialogIndirectParamA
(
COMDLG32_hInstance
,
template
,
hwnd
,
FileOpenDlgProcUserTemplate
,
(
LPARAM
)
fodInfos
);
if
(
hChildDlg
)
{
ShowWindow
(
hChildDlg
,
SW_SHOW
);
return
hChildDlg
;
}
}
else
if
(
IsHooked
(
fodInfos
))
{
RECT
rectHwnd
;
struct
{
DLGTEMPLATE
tmplate
;
WORD
menu
,
class
,
title
;
}
temp
;
GetClientRect
(
hwnd
,
&
rectHwnd
);
temp
.
tmplate
.
style
=
WS_CHILD
|
WS_CLIPSIBLINGS
|
WS_VISIBLE
|
DS_CONTROL
|
DS_3DLOOK
;
temp
.
tmplate
.
dwExtendedStyle
=
0
;
temp
.
tmplate
.
cdit
=
0
;
temp
.
tmplate
.
x
=
0
;
temp
.
tmplate
.
y
=
0
;
temp
.
tmplate
.
cx
=
0
;
temp
.
tmplate
.
cy
=
0
;
temp
.
menu
=
temp
.
class
=
temp
.
title
=
0
;
hChildDlg
=
CreateDialogIndirectParamA
(
COMDLG32_hInstance
,
&
temp
.
tmplate
,
hwnd
,
FileOpenDlgProcUserTemplate
,
(
LPARAM
)
fodInfos
);
return
hChildDlg
;
}
return
NULL
;
}
/***********************************************************************
* SendCustomDlgNotificationMessage
*
* Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
*/
HRESULT
SendCustomDlgNotificationMessage
(
HWND
hwndParentDlg
,
UINT
uCode
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwndParentDlg
,
FileOpenDlgInfosStr
);
TRACE
(
"%p 0x%04x
\n
"
,
hwndParentDlg
,
uCode
);
if
(
!
fodInfos
)
return
0
;
if
(
fodInfos
->
unicode
)
FIXME
(
"sending OPENFILENAMEA structure. Hook is expecting OPENFILENAMEW!
\n
"
);
if
(
fodInfos
->
DlgInfos
.
hwndCustomDlg
)
{
OFNOTIFYA
ofnNotify
;
HRESULT
ret
;
ofnNotify
.
hdr
.
hwndFrom
=
hwndParentDlg
;
ofnNotify
.
hdr
.
idFrom
=
0
;
ofnNotify
.
hdr
.
code
=
uCode
;
ofnNotify
.
lpOFN
=
fodInfos
->
ofnInfos
;
ofnNotify
.
pszFile
=
NULL
;
TRACE
(
"CALL NOTIFY for %x
\n
"
,
uCode
);
ret
=
SendMessageA
(
fodInfos
->
DlgInfos
.
hwndCustomDlg
,
WM_NOTIFY
,
0
,(
LPARAM
)
&
ofnNotify
);
TRACE
(
"RET NOTIFY
\n
"
);
return
ret
;
}
return
TRUE
;
}
HRESULT
FILEDLG95_Handle_GetFilePath
(
HWND
hwnd
,
DWORD
size
,
LPSTR
buffer
)
{
UINT
sizeUsed
=
0
,
n
,
total
;
LPWSTR
lpstrFileList
=
NULL
;
WCHAR
lpstrCurrentDir
[
MAX_PATH
];
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"CDM_GETFILEPATH:
\n
"
);
if
(
!
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_EXPLORER
)
)
return
-
1
;
/* get path and filenames */
SHGetPathFromIDListW
(
fodInfos
->
ShellInfos
.
pidlAbsCurrent
,
lpstrCurrentDir
);
n
=
FILEDLG95_FILENAME_GetFileNames
(
hwnd
,
&
lpstrFileList
,
&
sizeUsed
);
TRACE
(
"path >%s< filespec >%s< %d files
\n
"
,
debugstr_w
(
lpstrCurrentDir
),
debugstr_w
(
lpstrFileList
),
n
);
total
=
WideCharToMultiByte
(
CP_ACP
,
0
,
lpstrCurrentDir
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
total
+=
WideCharToMultiByte
(
CP_ACP
,
0
,
lpstrFileList
,
sizeUsed
,
NULL
,
0
,
NULL
,
NULL
);
/* Prepend the current path */
n
=
WideCharToMultiByte
(
CP_ACP
,
0
,
lpstrCurrentDir
,
-
1
,
buffer
,
size
,
NULL
,
NULL
);
if
(
n
<
size
)
{
/* 'n' includes trailing \0 */
buffer
[
n
-
1
]
=
'\\'
;
WideCharToMultiByte
(
CP_ACP
,
0
,
lpstrFileList
,
sizeUsed
,
&
buffer
[
n
],
size
-
n
,
NULL
,
NULL
);
}
MemFree
(
lpstrFileList
);
TRACE
(
"returned -> %s
\n
"
,
debugstr_a
(
buffer
));
return
total
;
}
HRESULT
FILEDLG95_Handle_GetFileSpec
(
HWND
hwnd
,
DWORD
size
,
LPSTR
buffer
)
{
UINT
sizeUsed
=
0
;
LPWSTR
lpstrFileList
=
NULL
;
TRACE
(
"CDM_GETSPEC:
\n
"
);
FILEDLG95_FILENAME_GetFileNames
(
hwnd
,
&
lpstrFileList
,
&
sizeUsed
);
WideCharToMultiByte
(
CP_ACP
,
0
,
lpstrFileList
,
sizeUsed
,
buffer
,
size
,
NULL
,
NULL
);
MemFree
(
lpstrFileList
);
return
sizeUsed
;
}
/***********************************************************************
* FILEDLG95_HandleCustomDialogMessages
*
* Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
*/
HRESULT
FILEDLG95_HandleCustomDialogMessages
(
HWND
hwnd
,
UINT
uMsg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
char
lpstrPath
[
MAX_PATH
];
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
if
(
!
fodInfos
)
return
-
1
;
switch
(
uMsg
)
{
case
CDM_GETFILEPATH
:
return
FILEDLG95_Handle_GetFilePath
(
hwnd
,
(
UINT
)
wParam
,
(
LPSTR
)
lParam
);
case
CDM_GETFOLDERPATH
:
TRACE
(
"CDM_GETFOLDERPATH:
\n
"
);
SHGetPathFromIDListA
(
fodInfos
->
ShellInfos
.
pidlAbsCurrent
,
lpstrPath
);
if
((
LPSTR
)
lParam
!=
NULL
)
lstrcpynA
((
LPSTR
)
lParam
,
lpstrPath
,(
int
)
wParam
);
return
strlen
(
lpstrPath
);
case
CDM_GETSPEC
:
return
FILEDLG95_Handle_GetFileSpec
(
hwnd
,
(
UINT
)
wParam
,
(
LPSTR
)
lParam
);
case
CDM_SETCONTROLTEXT
:
TRACE
(
"CDM_SETCONTROLTEXT:
\n
"
);
if
(
0
!=
lParam
)
SetDlgItemTextA
(
hwnd
,
(
UINT
)
wParam
,
(
LPSTR
)
lParam
);
return
TRUE
;
case
CDM_HIDECONTROL
:
case
CDM_SETDEFEXT
:
FIXME
(
"CDM_HIDECONTROL,CDM_SETCONTROLTEXT,CDM_SETDEFEXT not implemented
\n
"
);
return
-
1
;
}
return
TRUE
;
}
/***********************************************************************
* FileOpenDlgProc95
*
* File open dialog procedure
*/
INT_PTR
CALLBACK
FileOpenDlgProc95
(
HWND
hwnd
,
UINT
uMsg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
#if 0
TRACE("0x%04x 0x%04x\n", hwnd, uMsg);
#endif
switch
(
uMsg
)
{
case
WM_INITDIALOG
:
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
lParam
;
/* Adds the FileOpenDlgInfos in the property list of the dialog
so it will be easily accessible through a GetPropA(...) */
SetPropA
(
hwnd
,
FileOpenDlgInfosStr
,
(
HANDLE
)
fodInfos
);
fodInfos
->
DlgInfos
.
hwndCustomDlg
=
CreateTemplateDialog
((
FileOpenDlgInfos
*
)
lParam
,
hwnd
);
FILEDLG95_InitControls
(
hwnd
);
if
(
fodInfos
->
DlgInfos
.
hwndCustomDlg
)
ArrangeCtrlPositions
(
fodInfos
->
DlgInfos
.
hwndCustomDlg
,
hwnd
,
(
fodInfos
->
ofnInfos
->
Flags
&
(
OFN_HIDEREADONLY
|
OFN_SHOWHELP
))
==
OFN_HIDEREADONLY
);
FILEDLG95_FillControls
(
hwnd
,
wParam
,
lParam
);
SendCustomDlgNotificationMessage
(
hwnd
,
CDN_INITDONE
);
SendCustomDlgNotificationMessage
(
hwnd
,
CDN_FOLDERCHANGE
);
SendCustomDlgNotificationMessage
(
hwnd
,
CDN_SELCHANGE
);
return
0
;
}
case
WM_COMMAND
:
return
FILEDLG95_OnWMCommand
(
hwnd
,
wParam
,
lParam
);
case
WM_DRAWITEM
:
{
switch
(((
LPDRAWITEMSTRUCT
)
lParam
)
->
CtlID
)
{
case
IDC_LOOKIN
:
FILEDLG95_LOOKIN_DrawItem
((
LPDRAWITEMSTRUCT
)
lParam
);
return
TRUE
;
}
}
return
FALSE
;
case
WM_GETISHELLBROWSER
:
return
FILEDLG95_OnWMGetIShellBrowser
(
hwnd
);
case
WM_DESTROY
:
RemovePropA
(
hwnd
,
FileOpenDlgInfosStr
);
return
FALSE
;
case
WM_NOTIFY
:
{
LPNMHDR
lpnmh
=
(
LPNMHDR
)
lParam
;
UINT
stringId
=
-
1
;
/* set up the button tooltips strings */
if
(
TTN_GETDISPINFOA
==
lpnmh
->
code
)
{
LPNMTTDISPINFOA
lpdi
=
(
LPNMTTDISPINFOA
)
lParam
;
switch
(
lpnmh
->
idFrom
)
{
/* Up folder button */
case
FCIDM_TB_UPFOLDER
:
stringId
=
IDS_UPFOLDER
;
break
;
/* New folder button */
case
FCIDM_TB_NEWFOLDER
:
stringId
=
IDS_NEWFOLDER
;
break
;
/* List option button */
case
FCIDM_TB_SMALLICON
:
stringId
=
IDS_LISTVIEW
;
break
;
/* Details option button */
case
FCIDM_TB_REPORTVIEW
:
stringId
=
IDS_REPORTVIEW
;
break
;
/* Desktop button */
case
FCIDM_TB_DESKTOP
:
stringId
=
IDS_TODESKTOP
;
break
;
default:
stringId
=
0
;
}
lpdi
->
hinst
=
COMDLG32_hInstance
;
lpdi
->
lpszText
=
(
LPSTR
)
stringId
;
}
return
FALSE
;
}
default
:
if
(
uMsg
>=
CDM_FIRST
&&
uMsg
<=
CDM_LAST
)
return
FILEDLG95_HandleCustomDialogMessages
(
hwnd
,
uMsg
,
wParam
,
lParam
);
return
FALSE
;
}
}
/***********************************************************************
* FILEDLG95_InitControls
*
* WM_INITDIALOG message handler (before hook notification)
*/
static
LRESULT
FILEDLG95_InitControls
(
HWND
hwnd
)
{
int
win2000plus
=
0
;
int
win98plus
=
0
;
int
handledPath
=
FALSE
;
OSVERSIONINFOA
osVi
;
const
WCHAR
szwSlash
[]
=
{
'\\'
,
0
};
const
WCHAR
szwStar
[]
=
{
'*'
,
0
};
TBBUTTON
tbb
[]
=
{
{
0
,
0
,
TBSTATE_ENABLED
,
TBSTYLE_SEP
,
{
0
,
0
},
0
,
0
},
{
VIEW_PARENTFOLDER
,
FCIDM_TB_UPFOLDER
,
TBSTATE_ENABLED
,
TBSTYLE_BUTTON
,
{
0
,
0
},
0
,
0
},
{
0
,
0
,
TBSTATE_ENABLED
,
TBSTYLE_SEP
,
{
0
,
0
},
0
,
0
},
{
VIEW_NEWFOLDER
+
1
,
FCIDM_TB_DESKTOP
,
TBSTATE_ENABLED
,
TBSTYLE_BUTTON
,
{
0
,
0
},
0
,
0
},
{
0
,
0
,
TBSTATE_ENABLED
,
TBSTYLE_SEP
,
{
0
,
0
},
0
,
0
},
{
VIEW_NEWFOLDER
,
FCIDM_TB_NEWFOLDER
,
TBSTATE_ENABLED
,
TBSTYLE_BUTTON
,
{
0
,
0
},
0
,
0
},
{
0
,
0
,
TBSTATE_ENABLED
,
TBSTYLE_SEP
,
{
0
,
0
},
0
,
0
},
{
VIEW_LIST
,
FCIDM_TB_SMALLICON
,
TBSTATE_ENABLED
,
TBSTYLE_BUTTON
,
{
0
,
0
},
0
,
0
},
{
VIEW_DETAILS
,
FCIDM_TB_REPORTVIEW
,
TBSTATE_ENABLED
,
TBSTYLE_BUTTON
,
{
0
,
0
},
0
,
0
},
};
TBADDBITMAP
tba
[
2
];
RECT
rectTB
;
RECT
rectlook
;
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
tba
[
0
].
hInst
=
HINST_COMMCTRL
;
tba
[
0
].
nID
=
IDB_VIEW_SMALL_COLOR
;
tba
[
1
].
hInst
=
COMDLG32_hInstance
;
tba
[
1
].
nID
=
800
;
TRACE
(
"%p
\n
"
,
fodInfos
);
/* Get windows version emulating */
osVi
.
dwOSVersionInfoSize
=
sizeof
(
OSVERSIONINFOA
);
GetVersionExA
(
&
osVi
);
if
(
osVi
.
dwPlatformId
==
VER_PLATFORM_WIN32_WINDOWS
)
{
win98plus
=
((
osVi
.
dwMajorVersion
>
4
)
||
((
osVi
.
dwMajorVersion
==
4
)
&&
(
osVi
.
dwMinorVersion
>
0
)));
}
else
if
(
osVi
.
dwPlatformId
==
VER_PLATFORM_WIN32_NT
)
{
win2000plus
=
(
osVi
.
dwMajorVersion
>
4
);
if
(
win2000plus
)
win98plus
=
TRUE
;
}
TRACE
(
"Running on 2000+ %d, 98+ %d
\n
"
,
win2000plus
,
win98plus
);
/* Get the hwnd of the controls */
fodInfos
->
DlgInfos
.
hwndFileName
=
GetDlgItem
(
hwnd
,
IDC_FILENAME
);
fodInfos
->
DlgInfos
.
hwndFileTypeCB
=
GetDlgItem
(
hwnd
,
IDC_FILETYPE
);
fodInfos
->
DlgInfos
.
hwndLookInCB
=
GetDlgItem
(
hwnd
,
IDC_LOOKIN
);
GetWindowRect
(
fodInfos
->
DlgInfos
.
hwndLookInCB
,
&
rectlook
);
MapWindowPoints
(
0
,
hwnd
,(
LPPOINT
)
&
rectlook
,
2
);
/* construct the toolbar */
GetWindowRect
(
GetDlgItem
(
hwnd
,
IDC_TOOLBARSTATIC
),
&
rectTB
);
MapWindowPoints
(
0
,
hwnd
,(
LPPOINT
)
&
rectTB
,
2
);
rectTB
.
right
=
rectlook
.
right
+
rectTB
.
right
-
rectTB
.
left
;
rectTB
.
bottom
=
rectlook
.
top
-
1
+
rectTB
.
bottom
-
rectTB
.
top
;
rectTB
.
left
=
rectlook
.
right
;
rectTB
.
top
=
rectlook
.
top
-
1
;
fodInfos
->
DlgInfos
.
hwndTB
=
CreateWindowExA
(
0
,
TOOLBARCLASSNAMEA
,
NULL
,
WS_CHILD
|
WS_GROUP
|
WS_VISIBLE
|
WS_CLIPSIBLINGS
|
TBSTYLE_TOOLTIPS
|
CCS_NODIVIDER
|
CCS_NORESIZE
,
rectTB
.
left
,
rectTB
.
top
,
rectTB
.
right
-
rectTB
.
left
,
rectTB
.
bottom
-
rectTB
.
top
,
hwnd
,
(
HMENU
)
IDC_TOOLBAR
,
COMDLG32_hInstance
,
NULL
);
SendMessageA
(
fodInfos
->
DlgInfos
.
hwndTB
,
TB_BUTTONSTRUCTSIZE
,
(
WPARAM
)
sizeof
(
TBBUTTON
),
0
);
/* FIXME: use TB_LOADIMAGES when implemented */
/* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
SendMessageA
(
fodInfos
->
DlgInfos
.
hwndTB
,
TB_ADDBITMAP
,
(
WPARAM
)
12
,
(
LPARAM
)
&
tba
[
0
]);
SendMessageA
(
fodInfos
->
DlgInfos
.
hwndTB
,
TB_ADDBITMAP
,
(
WPARAM
)
1
,
(
LPARAM
)
&
tba
[
1
]);
SendMessageA
(
fodInfos
->
DlgInfos
.
hwndTB
,
TB_ADDBUTTONSA
,
(
WPARAM
)
9
,(
LPARAM
)
&
tbb
);
SendMessageA
(
fodInfos
->
DlgInfos
.
hwndTB
,
TB_AUTOSIZE
,
0
,
0
);
/* Set the window text with the text specified in the OPENFILENAME structure */
if
(
fodInfos
->
title
)
{
SetWindowTextW
(
hwnd
,
fodInfos
->
title
);
}
else
if
(
fodInfos
->
DlgInfos
.
dwDlgProp
&
FODPROP_SAVEDLG
)
{
SetWindowTextA
(
hwnd
,
"Save"
);
}
/* Initialise the file name edit control */
handledPath
=
FALSE
;
TRACE
(
"Before manipilation, file = %s, dir = %s
\n
"
,
debugstr_w
(
fodInfos
->
filename
),
debugstr_w
(
fodInfos
->
initdir
));
if
(
fodInfos
->
filename
)
{
/* 1. If win2000 or higher and filename contains a path, use it
in preference over the lpstrInitialDir */
if
(
win2000plus
&&
*
fodInfos
->
filename
&&
strpbrkW
(
fodInfos
->
filename
,
szwSlash
))
{
WCHAR
tmpBuf
[
MAX_PATH
];
WCHAR
*
nameBit
;
DWORD
result
;
result
=
GetFullPathNameW
(
fodInfos
->
filename
,
MAX_PATH
,
tmpBuf
,
&
nameBit
);
if
(
result
)
{
/* nameBit is always shorter than the original filename */
strcpyW
(
fodInfos
->
filename
,
nameBit
);
*
nameBit
=
0x00
;
if
(
fodInfos
->
initdir
==
NULL
)
MemFree
(
fodInfos
->
initdir
);
fodInfos
->
initdir
=
MemAlloc
((
strlenW
(
tmpBuf
)
+
1
)
*
sizeof
(
WCHAR
));
strcpyW
(
fodInfos
->
initdir
,
tmpBuf
);
handledPath
=
TRUE
;
TRACE
(
"Value in Filename includes path, overriding InitialDir: %s, %s
\n
"
,
debugstr_w
(
fodInfos
->
filename
),
debugstr_w
(
fodInfos
->
initdir
));
}
SetDlgItemTextW
(
hwnd
,
IDC_FILENAME
,
fodInfos
->
filename
);
}
else
{
SetDlgItemTextW
(
hwnd
,
IDC_FILENAME
,
fodInfos
->
filename
);
}
}
/* 2. (All platforms) If initdir is not null, then use it */
if
((
handledPath
==
FALSE
)
&&
(
fodInfos
->
initdir
!=
NULL
)
&&
(
*
fodInfos
->
initdir
!=
0x00
))
{
/* Work out the proper path as supplied one might be relative */
/* (Here because supplying '.' as dir browses to My Computer) */
if
(
handledPath
==
FALSE
)
{
WCHAR
tmpBuf
[
MAX_PATH
];
WCHAR
tmpBuf2
[
MAX_PATH
];
WCHAR
*
nameBit
;
DWORD
result
;
strcpyW
(
tmpBuf
,
fodInfos
->
initdir
);
if
(
tmpBuf
[
strlenW
(
tmpBuf
)
-
1
]
!=
'\\'
)
{
strcatW
(
tmpBuf
,
szwSlash
);
}
strcatW
(
tmpBuf
,
szwStar
);
result
=
GetFullPathNameW
(
tmpBuf
,
MAX_PATH
,
tmpBuf2
,
&
nameBit
);
if
(
result
)
{
*
nameBit
=
0x00
;
if
(
fodInfos
->
initdir
)
MemFree
(
fodInfos
->
initdir
);
fodInfos
->
initdir
=
MemAlloc
((
strlenW
(
tmpBuf2
)
+
1
)
*
sizeof
(
WCHAR
));
strcpyW
(
fodInfos
->
initdir
,
tmpBuf2
);
handledPath
=
TRUE
;
TRACE
(
"Value in InitDir changed to %s
\n
"
,
debugstr_w
(
fodInfos
->
initdir
));
}
}
}
if
((
handledPath
==
FALSE
)
&&
((
fodInfos
->
initdir
==
NULL
)
||
(
*
fodInfos
->
initdir
==
0x00
)))
{
/* 3. All except w2k+: if filename contains a path use it */
if
(
!
win2000plus
&&
fodInfos
->
filename
&&
*
fodInfos
->
filename
&&
strpbrkW
(
fodInfos
->
filename
,
szwSlash
))
{
WCHAR
tmpBuf
[
MAX_PATH
];
WCHAR
*
nameBit
;
DWORD
result
;
result
=
GetFullPathNameW
(
fodInfos
->
filename
,
MAX_PATH
,
tmpBuf
,
&
nameBit
);
if
(
result
)
{
int
len
;
/* nameBit is always shorter than the original filename */
strcpyW
(
fodInfos
->
filename
,
nameBit
);
*
nameBit
=
0x00
;
len
=
strlenW
(
tmpBuf
);
if
(
fodInfos
->
initdir
)
MemFree
(
fodInfos
->
initdir
);
fodInfos
->
initdir
=
MemAlloc
((
len
+
1
)
*
sizeof
(
WCHAR
));
strcpyW
(
fodInfos
->
initdir
,
tmpBuf
);
handledPath
=
TRUE
;
TRACE
(
"Value in Filename includes path, overriding initdir: %s, %s
\n
"
,
debugstr_w
(
fodInfos
->
filename
),
debugstr_w
(
fodInfos
->
initdir
));
}
SetDlgItemTextW
(
hwnd
,
IDC_FILENAME
,
fodInfos
->
filename
);
}
/* 4. win98+ and win2000+ if any files of specified filter types in
current directory, use it */
if
(
win98plus
&&
handledPath
==
FALSE
&&
fodInfos
->
filter
&&
*
fodInfos
->
filter
)
{
BOOL
searchMore
=
TRUE
;
LPCWSTR
lpstrPos
=
fodInfos
->
filter
;
WIN32_FIND_DATAW
FindFileData
;
HANDLE
hFind
;
while
(
searchMore
)
{
/* filter is a list... title\0ext\0......\0\0 */
/* Skip the title */
if
(
!
*
lpstrPos
)
break
;
/* end */
lpstrPos
+=
strlenW
(
lpstrPos
)
+
1
;
/* See if any files exist in the current dir with this extension */
if
(
!
*
lpstrPos
)
break
;
/* end */
hFind
=
FindFirstFileW
(
lpstrPos
,
&
FindFileData
);
if
(
hFind
==
INVALID_HANDLE_VALUE
)
{
/* None found - continue search */
lpstrPos
+=
strlenW
(
lpstrPos
)
+
1
;
}
else
{
searchMore
=
FALSE
;
if
(
fodInfos
->
initdir
)
MemFree
(
fodInfos
->
initdir
);
fodInfos
->
initdir
=
MemAlloc
(
MAX_PATH
*
sizeof
(
WCHAR
));
GetCurrentDirectoryW
(
MAX_PATH
,
fodInfos
->
initdir
);
handledPath
=
TRUE
;
TRACE
(
"No initial dir specified, but files of type %s found in current, so using it
\n
"
,
debugstr_w
(
lpstrPos
));
break
;
}
}
}
/* 5. Win2000+: FIXME: Next, Recently used? Not sure how windows does this */
/* 6. Win98+ and 2000+: Use personal files dir, others use current dir */
if
(
handledPath
==
FALSE
&&
(
win2000plus
||
win98plus
))
{
fodInfos
->
initdir
=
MemAlloc
(
MAX_PATH
*
sizeof
(
WCHAR
));
if
(
FAILED
(
COMDLG32_SHGetFolderPathW
(
hwnd
,
CSIDL_PERSONAL
,
0
,
0
,
fodInfos
->
initdir
)))
{
if
(
FAILED
(
COMDLG32_SHGetFolderPathW
(
hwnd
,
CSIDL_DESKTOPDIRECTORY
|
CSIDL_FLAG_CREATE
,
0
,
0
,
fodInfos
->
initdir
)))
{
/* last fallback */
GetCurrentDirectoryW
(
MAX_PATH
,
fodInfos
->
initdir
);
TRACE
(
"No personal or desktop dir, using cwd as failsafe: %s
\n
"
,
debugstr_w
(
fodInfos
->
initdir
));
}
else
{
TRACE
(
"No personal dir, using desktop instead: %s
\n
"
,
debugstr_w
(
fodInfos
->
initdir
));
}
}
else
{
TRACE
(
"No initial dir specified, using personal files dir of %s
\n
"
,
debugstr_w
(
fodInfos
->
initdir
));
}
handledPath
=
TRUE
;
}
else
if
(
handledPath
==
FALSE
)
{
fodInfos
->
initdir
=
MemAlloc
(
MAX_PATH
*
sizeof
(
WCHAR
));
GetCurrentDirectoryW
(
MAX_PATH
,
fodInfos
->
initdir
);
handledPath
=
TRUE
;
TRACE
(
"No initial dir specified, using current dir of %s
\n
"
,
debugstr_w
(
fodInfos
->
initdir
));
}
}
SetFocus
(
GetDlgItem
(
hwnd
,
IDC_FILENAME
));
TRACE
(
"After manipulation, file = %s, dir = %s
\n
"
,
debugstr_w
(
fodInfos
->
filename
),
debugstr_w
(
fodInfos
->
initdir
));
/* Must the open as read only check box be checked ?*/
if
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_READONLY
)
{
SendDlgItemMessageA
(
hwnd
,
IDC_OPENREADONLY
,
BM_SETCHECK
,(
WPARAM
)
TRUE
,
0
);
}
/* Must the open as read only check box be hidden? */
if
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_HIDEREADONLY
)
{
ShowWindow
(
GetDlgItem
(
hwnd
,
IDC_OPENREADONLY
),
SW_HIDE
);
EnableWindow
(
GetDlgItem
(
hwnd
,
IDC_OPENREADONLY
),
FALSE
);
}
/* Must the help button be hidden? */
if
(
!
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_SHOWHELP
))
{
ShowWindow
(
GetDlgItem
(
hwnd
,
pshHelp
),
SW_HIDE
);
EnableWindow
(
GetDlgItem
(
hwnd
,
pshHelp
),
FALSE
);
}
/* Resize the height, if open as read only checkbox ad help button
are hidden and we are not using a custom template nor a customDialog
*/
if
(
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_HIDEREADONLY
)
&&
(
!
(
fodInfos
->
ofnInfos
->
Flags
&
(
OFN_SHOWHELP
|
OFN_ENABLETEMPLATE
|
OFN_ENABLETEMPLATEHANDLE
)))
&&
(
!
fodInfos
->
DlgInfos
.
hwndCustomDlg
))
{
RECT
rectDlg
,
rectHelp
,
rectCancel
;
GetWindowRect
(
hwnd
,
&
rectDlg
);
GetWindowRect
(
GetDlgItem
(
hwnd
,
pshHelp
),
&
rectHelp
);
GetWindowRect
(
GetDlgItem
(
hwnd
,
IDCANCEL
),
&
rectCancel
);
/* subtract the height of the help button plus the space between
the help button and the cancel button to the height of the dialog */
SetWindowPos
(
hwnd
,
0
,
0
,
0
,
rectDlg
.
right
-
rectDlg
.
left
,
(
rectDlg
.
bottom
-
rectDlg
.
top
)
-
(
rectHelp
.
bottom
-
rectCancel
.
bottom
),
SWP_NOACTIVATE
|
SWP_NOMOVE
|
SWP_NOZORDER
);
}
/* change Open to Save FIXME: use resources */
if
(
fodInfos
->
DlgInfos
.
dwDlgProp
&
FODPROP_SAVEDLG
)
{
SetDlgItemTextA
(
hwnd
,
IDOK
,
"&Save"
);
SetDlgItemTextA
(
hwnd
,
IDC_LOOKINSTATIC
,
"Save &in"
);
}
return
0
;
}
/***********************************************************************
* FILEDLG95_FillControls
*
* WM_INITDIALOG message handler (after hook notification)
*/
static
LRESULT
FILEDLG95_FillControls
(
HWND
hwnd
,
WPARAM
wParam
,
LPARAM
lParam
)
{
LPITEMIDLIST
pidlItemId
=
NULL
;
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
lParam
;
TRACE
(
"dir=%s file=%s
\n
"
,
debugstr_w
(
fodInfos
->
initdir
),
debugstr_w
(
fodInfos
->
filename
));
/* Get the initial directory pidl */
if
(
!
(
pidlItemId
=
GetPidlFromName
(
fodInfos
->
Shell
.
FOIShellFolder
,
fodInfos
->
initdir
)))
{
WCHAR
path
[
MAX_PATH
];
GetCurrentDirectoryW
(
MAX_PATH
,
path
);
pidlItemId
=
GetPidlFromName
(
fodInfos
->
Shell
.
FOIShellFolder
,
path
);
}
/* Initialise shell objects */
FILEDLG95_SHELL_Init
(
hwnd
);
/* Initialize the Look In combo box */
FILEDLG95_LOOKIN_Init
(
fodInfos
->
DlgInfos
.
hwndLookInCB
);
/* Initialize the filter combo box */
FILEDLG95_FILETYPE_Init
(
hwnd
);
/* Browse to the initial directory */
IShellBrowser_BrowseObject
(
fodInfos
->
Shell
.
FOIShellBrowser
,
pidlItemId
,
SBSP_ABSOLUTE
);
/* Free pidlItem memory */
COMDLG32_SHFree
(
pidlItemId
);
return
TRUE
;
}
/***********************************************************************
* FILEDLG95_Clean
*
* Regroups all the cleaning functions of the filedlg
*/
void
FILEDLG95_Clean
(
HWND
hwnd
)
{
FILEDLG95_FILETYPE_Clean
(
hwnd
);
FILEDLG95_LOOKIN_Clean
(
hwnd
);
FILEDLG95_SHELL_Clean
(
hwnd
);
}
/***********************************************************************
* FILEDLG95_OnWMCommand
*
* WM_COMMAND message handler
*/
static
LRESULT
FILEDLG95_OnWMCommand
(
HWND
hwnd
,
WPARAM
wParam
,
LPARAM
lParam
)
{
WORD
wNotifyCode
=
HIWORD
(
wParam
);
/* notification code */
WORD
wID
=
LOWORD
(
wParam
);
/* item, control, or accelerator identifier */
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
switch
(
wID
)
{
/* OK button */
case
IDOK
:
FILEDLG95_OnOpen
(
hwnd
);
break
;
/* Cancel button */
case
IDCANCEL
:
FILEDLG95_Clean
(
hwnd
);
EndDialog
(
hwnd
,
FALSE
);
break
;
/* Filetype combo box */
case
IDC_FILETYPE
:
FILEDLG95_FILETYPE_OnCommand
(
hwnd
,
wNotifyCode
);
break
;
/* LookIn combo box */
case
IDC_LOOKIN
:
FILEDLG95_LOOKIN_OnCommand
(
hwnd
,
wNotifyCode
);
break
;
/* --- toolbar --- */
/* Up folder button */
case
FCIDM_TB_UPFOLDER
:
FILEDLG95_SHELL_UpFolder
(
hwnd
);
break
;
/* New folder button */
case
FCIDM_TB_NEWFOLDER
:
FILEDLG95_SHELL_ExecuteCommand
(
hwnd
,
CMDSTR_NEWFOLDERA
);
break
;
/* List option button */
case
FCIDM_TB_SMALLICON
:
FILEDLG95_SHELL_ExecuteCommand
(
hwnd
,
CMDSTR_VIEWLISTA
);
break
;
/* Details option button */
case
FCIDM_TB_REPORTVIEW
:
FILEDLG95_SHELL_ExecuteCommand
(
hwnd
,
CMDSTR_VIEWDETAILSA
);
break
;
/* Details option button */
case
FCIDM_TB_DESKTOP
:
FILEDLG95_SHELL_BrowseToDesktop
(
hwnd
);
break
;
case
IDC_FILENAME
:
break
;
}
/* Do not use the listview selection anymore */
fodInfos
->
DlgInfos
.
dwDlgProp
&=
~
FODPROP_USEVIEW
;
return
0
;
}
/***********************************************************************
* FILEDLG95_OnWMGetIShellBrowser
*
* WM_GETISHELLBROWSER message handler
*/
static
LRESULT
FILEDLG95_OnWMGetIShellBrowser
(
HWND
hwnd
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"
\n
"
);
SetWindowLongA
(
hwnd
,
DWL_MSGRESULT
,(
LONG
)
fodInfos
->
Shell
.
FOIShellBrowser
);
return
TRUE
;
}
/***********************************************************************
* FILEDLG95_SendFileOK
*
* Sends the CDN_FILEOK notification if required
*
* RETURNS
* TRUE if the dialog should close
* FALSE if the dialog should not be closed
*/
static
BOOL
FILEDLG95_SendFileOK
(
HWND
hwnd
,
FileOpenDlgInfos
*
fodInfos
)
{
/* ask the hook if we can close */
if
(
IsHooked
(
fodInfos
))
{
TRACE
(
"---
\n
"
);
/* First send CDN_FILEOK as MSDN doc says */
SendCustomDlgNotificationMessage
(
hwnd
,
CDN_FILEOK
);
/* fodInfos->ofnInfos points to an ASCII or UNICODE structure as appropriate */
CallWindowProcA
((
WNDPROC
)
fodInfos
->
ofnInfos
->
lpfnHook
,
fodInfos
->
DlgInfos
.
hwndCustomDlg
,
fodInfos
->
HookMsg
.
fileokstring
,
0
,
(
LPARAM
)
fodInfos
->
ofnInfos
);
if
(
GetWindowLongA
(
fodInfos
->
DlgInfos
.
hwndCustomDlg
,
DWL_MSGRESULT
))
{
TRACE
(
"canceled
\n
"
);
return
FALSE
;
}
}
return
TRUE
;
}
/***********************************************************************
* FILEDLG95_OnOpenMultipleFiles
*
* Handles the opening of multiple files.
*
* FIXME
* check destination buffer size
*/
BOOL
FILEDLG95_OnOpenMultipleFiles
(
HWND
hwnd
,
LPWSTR
lpstrFileList
,
UINT
nFileCount
,
UINT
sizeUsed
)
{
WCHAR
lpstrPathSpec
[
MAX_PATH
]
=
{
0
};
UINT
nCount
,
nSizePath
;
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"
\n
"
);
if
(
fodInfos
->
unicode
)
{
LPOPENFILENAMEW
ofn
=
(
LPOPENFILENAMEW
)
fodInfos
->
ofnInfos
;
ofn
->
lpstrFile
[
0
]
=
'\0'
;
}
else
{
LPOPENFILENAMEA
ofn
=
fodInfos
->
ofnInfos
;
ofn
->
lpstrFile
[
0
]
=
'\0'
;
}
SHGetPathFromIDListW
(
fodInfos
->
ShellInfos
.
pidlAbsCurrent
,
lpstrPathSpec
);
if
(
!
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_NOVALIDATE
)
&&
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_FILEMUSTEXIST
)
&&
!
(
fodInfos
->
DlgInfos
.
dwDlgProp
&
FODPROP_SAVEDLG
)
)
{
LPWSTR
lpstrTemp
=
lpstrFileList
;
for
(
nCount
=
0
;
nCount
<
nFileCount
;
nCount
++
)
{
LPITEMIDLIST
pidl
;
pidl
=
GetPidlFromName
(
fodInfos
->
Shell
.
FOIShellFolder
,
lpstrTemp
);
if
(
!
pidl
)
{
WCHAR
lpstrNotFound
[
100
];
WCHAR
lpstrMsg
[
100
];
WCHAR
tmp
[
400
];
WCHAR
nl
[]
=
{
'\n'
,
0
};
LoadStringW
(
COMDLG32_hInstance
,
IDS_FILENOTFOUND
,
lpstrNotFound
,
100
);
LoadStringW
(
COMDLG32_hInstance
,
IDS_VERIFYFILE
,
lpstrMsg
,
100
);
strcpyW
(
tmp
,
lpstrTemp
);
strcatW
(
tmp
,
nl
);
strcatW
(
tmp
,
lpstrNotFound
);
strcatW
(
tmp
,
nl
);
strcatW
(
tmp
,
lpstrMsg
);
MessageBoxW
(
hwnd
,
tmp
,
fodInfos
->
title
,
MB_OK
|
MB_ICONEXCLAMATION
);
return
FALSE
;
}
/* move to the next file in the list of files */
lpstrTemp
+=
strlenW
(
lpstrTemp
)
+
1
;
COMDLG32_SHFree
(
pidl
);
}
}
nSizePath
=
strlenW
(
lpstrPathSpec
)
+
1
;
if
(
!
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_EXPLORER
)
)
{
/* For "oldstyle" dialog the components have to
be spearated by blanks (not '\0'!) and short
filenames have to be used! */
FIXME
(
"Components have to be separated by blanks"
);
}
if
(
fodInfos
->
unicode
)
{
LPOPENFILENAMEW
ofn
=
(
LPOPENFILENAMEW
)
fodInfos
->
ofnInfos
;
strcpyW
(
ofn
->
lpstrFile
,
lpstrPathSpec
);
memcpy
(
ofn
->
lpstrFile
+
nSizePath
,
lpstrFileList
,
sizeUsed
*
sizeof
(
WCHAR
)
);
}
else
{
LPOPENFILENAMEA
ofn
=
fodInfos
->
ofnInfos
;
if
(
ofn
->
lpstrFile
!=
NULL
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
lpstrPathSpec
,
-
1
,
ofn
->
lpstrFile
,
ofn
->
nMaxFile
,
NULL
,
NULL
);
if
(
ofn
->
nMaxFile
>
nSizePath
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
lpstrFileList
,
sizeUsed
,
ofn
->
lpstrFile
+
nSizePath
,
ofn
->
nMaxFile
-
nSizePath
,
NULL
,
NULL
);
}
}
}
fodInfos
->
ofnInfos
->
nFileOffset
=
nSizePath
+
1
;
fodInfos
->
ofnInfos
->
nFileExtension
=
0
;
if
(
!
FILEDLG95_SendFileOK
(
hwnd
,
fodInfos
)
)
return
FALSE
;
/* clean and exit */
FILEDLG95_Clean
(
hwnd
);
return
EndDialog
(
hwnd
,
TRUE
);
}
/***********************************************************************
* FILEDLG95_OnOpen
*
* Ok button WM_COMMAND message handler
*
* If the function succeeds, the return value is nonzero.
*/
#define ONOPEN_BROWSE 1
#define ONOPEN_OPEN 2
#define ONOPEN_SEARCH 3
static
void
FILEDLG95_OnOpenMessage
(
HWND
hwnd
,
int
idCaption
,
int
idText
)
{
char
strMsgTitle
[
MAX_PATH
];
char
strMsgText
[
MAX_PATH
];
if
(
idCaption
)
LoadStringA
(
COMDLG32_hInstance
,
idCaption
,
strMsgTitle
,
sizeof
(
strMsgTitle
));
else
strMsgTitle
[
0
]
=
'\0'
;
LoadStringA
(
COMDLG32_hInstance
,
idText
,
strMsgText
,
sizeof
(
strMsgText
));
MessageBoxA
(
hwnd
,
strMsgText
,
strMsgTitle
,
MB_OK
|
MB_ICONHAND
);
}
BOOL
FILEDLG95_OnOpen
(
HWND
hwnd
)
{
LPWSTR
lpstrFileList
;
UINT
nFileCount
=
0
;
UINT
sizeUsed
=
0
;
BOOL
ret
=
TRUE
;
WCHAR
lpstrPathAndFile
[
MAX_PATH
];
WCHAR
lpstrTemp
[
MAX_PATH
];
LPSHELLFOLDER
lpsf
=
NULL
;
int
nOpenAction
;
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"hwnd=%p
\n
"
,
hwnd
);
/* get the files from the edit control */
nFileCount
=
FILEDLG95_FILENAME_GetFileNames
(
hwnd
,
&
lpstrFileList
,
&
sizeUsed
);
/* try if the user selected a folder in the shellview */
if
(
nFileCount
==
0
)
{
BrowseSelectedFolder
(
hwnd
);
return
FALSE
;
}
if
(
nFileCount
>
1
)
{
ret
=
FILEDLG95_OnOpenMultipleFiles
(
hwnd
,
lpstrFileList
,
nFileCount
,
sizeUsed
);
goto
ret
;
}
TRACE
(
"count=%u len=%u file=%s
\n
"
,
nFileCount
,
sizeUsed
,
debugstr_w
(
lpstrFileList
));
/*
Step 1: Build a complete path name from the current folder and
the filename or path in the edit box.
Special cases:
- the path in the edit box is a root path
(with or without drive letter)
- the edit box contains ".." (or a path with ".." in it)
*/
/* Get the current directory name */
if
(
!
SHGetPathFromIDListW
(
fodInfos
->
ShellInfos
.
pidlAbsCurrent
,
lpstrPathAndFile
))
{
/* we are in a special folder, default to desktop */
if
(
FAILED
(
COMDLG32_SHGetFolderPathW
(
hwnd
,
CSIDL_DESKTOPDIRECTORY
|
CSIDL_FLAG_CREATE
,
0
,
0
,
lpstrPathAndFile
)))
{
/* last fallback */
GetCurrentDirectoryW
(
MAX_PATH
,
lpstrPathAndFile
);
}
}
PathAddBackslashW
(
lpstrPathAndFile
);
TRACE
(
"current directory=%s
\n
"
,
debugstr_w
(
lpstrPathAndFile
));
/* if the user specifyed a fully qualified path use it */
if
(
PathIsRelativeW
(
lpstrFileList
))
{
strcatW
(
lpstrPathAndFile
,
lpstrFileList
);
}
else
{
/* does the path have a drive letter? */
if
(
PathGetDriveNumberW
(
lpstrFileList
)
==
-
1
)
strcpyW
(
lpstrPathAndFile
+
2
,
lpstrFileList
);
else
strcpyW
(
lpstrPathAndFile
,
lpstrFileList
);
}
/* resolve "." and ".." */
PathCanonicalizeW
(
lpstrTemp
,
lpstrPathAndFile
);
strcpyW
(
lpstrPathAndFile
,
lpstrTemp
);
TRACE
(
"canon=%s
\n
"
,
debugstr_w
(
lpstrPathAndFile
));
MemFree
(
lpstrFileList
);
/*
Step 2: here we have a cleaned up path
We have to parse the path step by step to see if we have to browse
to a folder if the path points to a directory or the last
valid element is a directory.
valid variables:
lpstrPathAndFile: cleaned up path
*/
nOpenAction
=
ONOPEN_BROWSE
;
/* dont apply any checks with OFN_NOVALIDATE */
{
LPWSTR
lpszTemp
,
lpszTemp1
;
LPITEMIDLIST
pidl
=
NULL
;
WCHAR
szwInvalid
[]
=
{
'/'
,
':'
,
'<'
,
'>'
,
'|'
,
0
};
/* check for invalid chars */
if
((
strpbrkW
(
lpstrPathAndFile
+
3
,
szwInvalid
)
!=
NULL
)
&&
!
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_NOVALIDATE
))
{
FILEDLG95_OnOpenMessage
(
hwnd
,
IDS_INVALID_FILENAME_TITLE
,
IDS_INVALID_FILENAME
);
ret
=
FALSE
;
goto
ret
;
}
if
(
FAILED
(
SHGetDesktopFolder
(
&
lpsf
)))
return
FALSE
;
lpszTemp1
=
lpszTemp
=
lpstrPathAndFile
;
while
(
lpszTemp1
)
{
LPSHELLFOLDER
lpsfChild
;
WCHAR
lpwstrTemp
[
MAX_PATH
];
DWORD
dwEaten
,
dwAttributes
;
LPWSTR
p
;
strcpyW
(
lpwstrTemp
,
lpszTemp
);
p
=
PathFindNextComponentW
(
lpwstrTemp
);
if
(
!
p
)
break
;
/* end of path */
*
p
=
0
;
lpszTemp
=
lpszTemp
+
strlenW
(
lpwstrTemp
);
if
(
*
lpszTemp
==
0
)
{
WCHAR
wszWild
[]
=
{
'*'
,
'?'
,
0
};
/* if the last element is a wildcard do a search */
if
(
strpbrkW
(
lpszTemp1
,
wszWild
)
!=
NULL
)
{
nOpenAction
=
ONOPEN_SEARCH
;
break
;
}
}
lpszTemp1
=
lpszTemp
;
TRACE
(
"parse now=%s next=%s sf=%p
\n
"
,
debugstr_w
(
lpwstrTemp
),
debugstr_w
(
lpszTemp
),
lpsf
);
if
(
lstrlenW
(
lpwstrTemp
)
==
2
)
PathAddBackslashW
(
lpwstrTemp
);
dwAttributes
=
SFGAO_FOLDER
;
if
(
SUCCEEDED
(
IShellFolder_ParseDisplayName
(
lpsf
,
hwnd
,
NULL
,
lpwstrTemp
,
&
dwEaten
,
&
pidl
,
&
dwAttributes
)))
{
/* the path component is valid, we have a pidl of the next path component */
TRACE
(
"parse OK attr=0x%08lx pidl=%p
\n
"
,
dwAttributes
,
pidl
);
if
(
dwAttributes
&
SFGAO_FOLDER
)
{
if
(
FAILED
(
IShellFolder_BindToObject
(
lpsf
,
pidl
,
0
,
&
IID_IShellFolder
,
(
LPVOID
*
)
&
lpsfChild
)))
{
ERR
(
"bind to failed
\n
"
);
/* should not fail */
break
;
}
IShellFolder_Release
(
lpsf
);
lpsf
=
lpsfChild
;
lpsfChild
=
NULL
;
}
else
{
TRACE
(
"value
\n
"
);
/* end dialog, return value */
nOpenAction
=
ONOPEN_OPEN
;
break
;
}
COMDLG32_SHFree
(
pidl
);
pidl
=
NULL
;
}
else
if
(
!
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_NOVALIDATE
))
{
if
(
*
lpszTemp
)
/* points to trailing null for last path element */
{
if
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_PATHMUSTEXIST
)
{
FILEDLG95_OnOpenMessage
(
hwnd
,
0
,
IDS_PATHNOTEXISTING
);
break
;
}
}
else
{
if
(
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_FILEMUSTEXIST
)
&&
!
(
fodInfos
->
DlgInfos
.
dwDlgProp
&
FODPROP_SAVEDLG
)
)
{
FILEDLG95_OnOpenMessage
(
hwnd
,
0
,
IDS_FILENOTEXISTING
);
break
;
}
}
/* change to the current folder */
nOpenAction
=
ONOPEN_OPEN
;
break
;
}
else
{
nOpenAction
=
ONOPEN_OPEN
;
break
;
}
}
if
(
pidl
)
COMDLG32_SHFree
(
pidl
);
}
/*
Step 3: here we have a cleaned up and validated path
valid variables:
lpsf: ShellFolder bound to the rightmost valid path component
lpstrPathAndFile: cleaned up path
nOpenAction: action to do
*/
TRACE
(
"end validate sf=%p
\n
"
,
lpsf
);
switch
(
nOpenAction
)
{
case
ONOPEN_SEARCH
:
/* set the current filter to the file mask and refresh */
TRACE
(
"ONOPEN_SEARCH %s
\n
"
,
debugstr_w
(
lpstrPathAndFile
));
{
int
iPos
;
LPWSTR
lpszTemp
=
PathFindFileNameW
(
lpstrPathAndFile
);
DWORD
len
;
/* replace the current filter */
if
(
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
)
MemFree
((
LPVOID
)
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
);
len
=
strlenW
(
lpszTemp
)
+
1
;
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
=
MemAlloc
(
len
*
sizeof
(
WCHAR
));
strcpyW
(
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
,
lpszTemp
);
/* set the filter cb to the extension when possible */
if
(
-
1
<
(
iPos
=
FILEDLG95_FILETYPE_SearchExt
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
,
lpszTemp
)))
CBSetCurSel
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
,
iPos
);
}
/* fall through */
case
ONOPEN_BROWSE
:
/* browse to the highest folder we could bind to */
TRACE
(
"ONOPEN_BROWSE
\n
"
);
{
IPersistFolder2
*
ppf2
;
if
(
SUCCEEDED
(
IShellFolder_QueryInterface
(
lpsf
,
&
IID_IPersistFolder2
,
(
LPVOID
*
)
&
ppf2
)))
{
LPITEMIDLIST
pidlCurrent
;
IPersistFolder2_GetCurFolder
(
ppf2
,
&
pidlCurrent
);
IPersistFolder2_Release
(
ppf2
);
if
(
!
COMDLG32_PIDL_ILIsEqual
(
pidlCurrent
,
fodInfos
->
ShellInfos
.
pidlAbsCurrent
))
{
IShellBrowser_BrowseObject
(
fodInfos
->
Shell
.
FOIShellBrowser
,
pidlCurrent
,
SBSP_ABSOLUTE
);
}
else
if
(
nOpenAction
==
ONOPEN_SEARCH
)
{
IShellView_Refresh
(
fodInfos
->
Shell
.
FOIShellView
);
}
COMDLG32_SHFree
(
pidlCurrent
);
}
}
ret
=
FALSE
;
break
;
case
ONOPEN_OPEN
:
/* fill in the return struct and close the dialog */
TRACE
(
"ONOPEN_OPEN %s
\n
"
,
debugstr_w
(
lpstrPathAndFile
));
{
/* add default extension */
if
(
fodInfos
->
defext
)
{
if
(
!
*
PathFindExtensionW
(
lpstrPathAndFile
))
{
/* only add "." in case a default extension does exist */
if
(
*
fodInfos
->
defext
!=
'\0'
)
{
const
WCHAR
szwDot
[]
=
{
'.'
,
0
};
int
PathLength
=
strlenW
(
lpstrPathAndFile
);
strcatW
(
lpstrPathAndFile
,
szwDot
);
strcatW
(
lpstrPathAndFile
,
fodInfos
->
defext
);
/* if file does not exist try without extension */
if
(
!
PathFileExistsW
(
lpstrPathAndFile
))
lpstrPathAndFile
[
PathLength
]
=
'\0'
;
}
}
}
/* Check that the size of the file does not exceed buffer size.
(Allow for extra \0 if OFN_MULTISELECT is set.) */
if
(
strlenW
(
lpstrPathAndFile
)
<
fodInfos
->
ofnInfos
->
nMaxFile
-
((
fodInfos
->
ofnInfos
->
Flags
&
OFN_ALLOWMULTISELECT
)
?
1
:
0
))
{
LPWSTR
lpszTemp
;
/* fill destination buffer */
if
(
fodInfos
->
ofnInfos
->
lpstrFile
)
{
if
(
fodInfos
->
unicode
)
{
LPOPENFILENAMEW
ofn
=
(
LPOPENFILENAMEW
)
fodInfos
->
ofnInfos
;
strncpyW
(
ofn
->
lpstrFile
,
lpstrPathAndFile
,
ofn
->
nMaxFile
);
if
(
ofn
->
Flags
&
OFN_ALLOWMULTISELECT
)
ofn
->
lpstrFile
[
lstrlenW
(
ofn
->
lpstrFile
)
+
1
]
=
'\0'
;
}
else
{
LPOPENFILENAMEA
ofn
=
fodInfos
->
ofnInfos
;
WideCharToMultiByte
(
CP_ACP
,
0
,
lpstrPathAndFile
,
-
1
,
ofn
->
lpstrFile
,
ofn
->
nMaxFile
,
NULL
,
NULL
);
if
(
ofn
->
Flags
&
OFN_ALLOWMULTISELECT
)
ofn
->
lpstrFile
[
lstrlenA
(
ofn
->
lpstrFile
)
+
1
]
=
'\0'
;
}
}
/* set filename offset */
lpszTemp
=
PathFindFileNameW
(
lpstrPathAndFile
);
fodInfos
->
ofnInfos
->
nFileOffset
=
(
lpszTemp
-
lpstrPathAndFile
);
/* set extension offset */
lpszTemp
=
PathFindExtensionW
(
lpstrPathAndFile
);
fodInfos
->
ofnInfos
->
nFileExtension
=
(
*
lpszTemp
)
?
(
lpszTemp
-
lpstrPathAndFile
)
+
1
:
0
;
/* set the lpstrFileTitle */
if
(
fodInfos
->
ofnInfos
->
lpstrFileTitle
)
{
LPWSTR
lpstrFileTitle
=
PathFindFileNameW
(
lpstrPathAndFile
);
if
(
fodInfos
->
unicode
)
{
LPOPENFILENAMEW
ofn
=
(
LPOPENFILENAMEW
)
fodInfos
->
ofnInfos
;
strncpyW
(
ofn
->
lpstrFileTitle
,
lpstrFileTitle
,
ofn
->
nMaxFileTitle
);
}
else
{
LPOPENFILENAMEA
ofn
=
fodInfos
->
ofnInfos
;
WideCharToMultiByte
(
CP_ACP
,
0
,
lpstrFileTitle
,
-
1
,
ofn
->
lpstrFileTitle
,
ofn
->
nMaxFileTitle
,
NULL
,
NULL
);
}
}
if
(
!
FILEDLG95_SendFileOK
(
hwnd
,
fodInfos
)
)
goto
ret
;
TRACE
(
"close
\n
"
);
FILEDLG95_Clean
(
hwnd
);
ret
=
EndDialog
(
hwnd
,
TRUE
);
}
else
{
/* FIXME set error FNERR_BUFFERTOSMALL */
FILEDLG95_Clean
(
hwnd
);
ret
=
EndDialog
(
hwnd
,
FALSE
);
}
goto
ret
;
}
break
;
}
ret:
if
(
lpsf
)
IShellFolder_Release
(
lpsf
);
return
ret
;
}
/***********************************************************************
* FILEDLG95_SHELL_Init
*
* Initialisation of the shell objects
*/
static
HRESULT
FILEDLG95_SHELL_Init
(
HWND
hwnd
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"
\n
"
);
/*
* Initialisation of the FileOpenDialogInfos structure
*/
/* Shell */
/*ShellInfos */
fodInfos
->
ShellInfos
.
hwndOwner
=
hwnd
;
/* Disable multi-select if flag not set */
if
(
!
(
fodInfos
->
ofnInfos
->
Flags
&
OFN_ALLOWMULTISELECT
))
{
fodInfos
->
ShellInfos
.
folderSettings
.
fFlags
|=
FWF_SINGLESEL
;
}
fodInfos
->
ShellInfos
.
folderSettings
.
fFlags
|=
FWF_AUTOARRANGE
|
FWF_ALIGNLEFT
;
fodInfos
->
ShellInfos
.
folderSettings
.
ViewMode
=
FVM_LIST
;
/* Construct the IShellBrowser interface */
fodInfos
->
Shell
.
FOIShellBrowser
=
IShellBrowserImpl_Construct
(
hwnd
);
return
NOERROR
;
}
/***********************************************************************
* FILEDLG95_SHELL_ExecuteCommand
*
* Change the folder option and refresh the view
* If the function succeeds, the return value is nonzero.
*/
static
BOOL
FILEDLG95_SHELL_ExecuteCommand
(
HWND
hwnd
,
LPCSTR
lpVerb
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
IContextMenu
*
pcm
;
TRACE
(
"(%p,%p)
\n
"
,
hwnd
,
lpVerb
);
if
(
SUCCEEDED
(
IShellView_GetItemObject
(
fodInfos
->
Shell
.
FOIShellView
,
SVGIO_BACKGROUND
,
&
IID_IContextMenu
,
(
LPVOID
*
)
&
pcm
)))
{
CMINVOKECOMMANDINFO
ci
;
ZeroMemory
(
&
ci
,
sizeof
(
CMINVOKECOMMANDINFO
));
ci
.
cbSize
=
sizeof
(
CMINVOKECOMMANDINFO
);
ci
.
lpVerb
=
lpVerb
;
ci
.
hwnd
=
hwnd
;
IContextMenu_InvokeCommand
(
pcm
,
&
ci
);
IContextMenu_Release
(
pcm
);
}
return
FALSE
;
}
/***********************************************************************
* FILEDLG95_SHELL_UpFolder
*
* Browse to the specified object
* If the function succeeds, the return value is nonzero.
*/
static
BOOL
FILEDLG95_SHELL_UpFolder
(
HWND
hwnd
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"
\n
"
);
if
(
SUCCEEDED
(
IShellBrowser_BrowseObject
(
fodInfos
->
Shell
.
FOIShellBrowser
,
NULL
,
SBSP_PARENT
)))
{
return
TRUE
;
}
return
FALSE
;
}
/***********************************************************************
* FILEDLG95_SHELL_BrowseToDesktop
*
* Browse to the Desktop
* If the function succeeds, the return value is nonzero.
*/
static
BOOL
FILEDLG95_SHELL_BrowseToDesktop
(
HWND
hwnd
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
LPITEMIDLIST
pidl
;
HRESULT
hres
;
TRACE
(
"
\n
"
);
SHGetSpecialFolderLocation
(
0
,
CSIDL_DESKTOP
,
&
pidl
);
hres
=
IShellBrowser_BrowseObject
(
fodInfos
->
Shell
.
FOIShellBrowser
,
pidl
,
SBSP_ABSOLUTE
);
COMDLG32_SHFree
(
pidl
);
return
SUCCEEDED
(
hres
);
}
/***********************************************************************
* FILEDLG95_SHELL_Clean
*
* Cleans the memory used by shell objects
*/
static
void
FILEDLG95_SHELL_Clean
(
HWND
hwnd
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"
\n
"
);
COMDLG32_SHFree
(
fodInfos
->
ShellInfos
.
pidlAbsCurrent
);
/* clean Shell interfaces */
IShellView_DestroyViewWindow
(
fodInfos
->
Shell
.
FOIShellView
);
IShellView_Release
(
fodInfos
->
Shell
.
FOIShellView
);
IShellFolder_Release
(
fodInfos
->
Shell
.
FOIShellFolder
);
IShellBrowser_Release
(
fodInfos
->
Shell
.
FOIShellBrowser
);
if
(
fodInfos
->
Shell
.
FOIDataObject
)
IDataObject_Release
(
fodInfos
->
Shell
.
FOIDataObject
);
}
/***********************************************************************
* FILEDLG95_FILETYPE_Init
*
* Initialisation of the file type combo box
*/
static
HRESULT
FILEDLG95_FILETYPE_Init
(
HWND
hwnd
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"
\n
"
);
if
(
fodInfos
->
filter
)
{
int
nFilters
=
0
;
/* number of filters */
LPWSTR
lpstrFilter
;
LPCWSTR
lpstrPos
=
fodInfos
->
filter
;
for
(;;)
{
/* filter is a list... title\0ext\0......\0\0
* Set the combo item text to the title and the item data
* to the ext
*/
LPCWSTR
lpstrDisplay
;
LPWSTR
lpstrExt
;
/* Get the title */
if
(
!
*
lpstrPos
)
break
;
/* end */
lpstrDisplay
=
lpstrPos
;
lpstrPos
+=
strlenW
(
lpstrPos
)
+
1
;
/* Copy the extensions */
if
(
!
*
lpstrPos
)
return
E_FAIL
;
/* malformed filter */
if
(
!
(
lpstrExt
=
MemAlloc
((
strlenW
(
lpstrPos
)
+
1
)
*
sizeof
(
WCHAR
))))
return
E_FAIL
;
strcpyW
(
lpstrExt
,
lpstrPos
);
lpstrPos
+=
strlenW
(
lpstrPos
)
+
1
;
/* Add the item at the end of the combo */
CBAddStringW
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
,
lpstrDisplay
);
CBSetItemDataPtr
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
,
nFilters
,
lpstrExt
);
nFilters
++
;
}
/*
* Set the current filter to the one specified
* in the initialisation structure
* FIXME: lpstrCustomFilter not handled at all
*/
/* set default filter index */
if
(
fodInfos
->
ofnInfos
->
nFilterIndex
==
0
&&
fodInfos
->
customfilter
==
NULL
)
fodInfos
->
ofnInfos
->
nFilterIndex
=
1
;
/* First, check to make sure our index isn't out of bounds. */
if
(
fodInfos
->
ofnInfos
->
nFilterIndex
>
nFilters
)
fodInfos
->
ofnInfos
->
nFilterIndex
=
nFilters
;
/* Set the current index selection. */
CBSetCurSel
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
,
fodInfos
->
ofnInfos
->
nFilterIndex
-
1
);
/* Get the corresponding text string from the combo box. */
lpstrFilter
=
(
LPWSTR
)
CBGetItemDataPtr
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
,
fodInfos
->
ofnInfos
->
nFilterIndex
-
1
);
if
((
INT
)
lpstrFilter
==
CB_ERR
)
/* control is empty */
lpstrFilter
=
NULL
;
if
(
lpstrFilter
)
{
DWORD
len
;
CharLowerW
(
lpstrFilter
);
/* lowercase */
len
=
strlenW
(
lpstrFilter
)
+
1
;
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
=
MemAlloc
(
len
*
sizeof
(
WCHAR
)
);
strcpyW
(
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
,
lpstrFilter
);
}
}
return
NOERROR
;
}
/***********************************************************************
* FILEDLG95_FILETYPE_OnCommand
*
* WM_COMMAND of the file type combo box
* If the function succeeds, the return value is nonzero.
*/
static
BOOL
FILEDLG95_FILETYPE_OnCommand
(
HWND
hwnd
,
WORD
wNotifyCode
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
switch
(
wNotifyCode
)
{
case
CBN_SELENDOK
:
{
LPWSTR
lpstrFilter
;
/* Get the current item of the filetype combo box */
int
iItem
=
CBGetCurSel
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
);
/* set the current filter index - indexed from 1 */
fodInfos
->
ofnInfos
->
nFilterIndex
=
iItem
+
1
;
/* Set the current filter with the current selection */
if
(
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
)
MemFree
((
LPVOID
)
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
);
lpstrFilter
=
(
LPWSTR
)
CBGetItemDataPtr
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
,
iItem
);
if
((
int
)
lpstrFilter
!=
CB_ERR
)
{
DWORD
len
;
CharLowerW
(
lpstrFilter
);
/* lowercase */
len
=
strlenW
(
lpstrFilter
)
+
1
;
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
=
MemAlloc
(
len
*
sizeof
(
WCHAR
)
);
strcpyW
(
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
,
lpstrFilter
);
SendCustomDlgNotificationMessage
(
hwnd
,
CDN_TYPECHANGE
);
}
/* Refresh the actual view to display the included items*/
IShellView_Refresh
(
fodInfos
->
Shell
.
FOIShellView
);
}
}
return
FALSE
;
}
/***********************************************************************
* FILEDLG95_FILETYPE_SearchExt
*
* searches for a extension in the filetype box
*/
static
int
FILEDLG95_FILETYPE_SearchExt
(
HWND
hwnd
,
LPCWSTR
lpstrExt
)
{
int
i
,
iCount
=
CBGetCount
(
hwnd
);
TRACE
(
"%s
\n
"
,
debugstr_w
(
lpstrExt
));
if
(
iCount
!=
CB_ERR
)
{
for
(
i
=
0
;
i
<
iCount
;
i
++
)
{
if
(
!
lstrcmpiW
(
lpstrExt
,(
LPWSTR
)
CBGetItemDataPtr
(
hwnd
,
i
)))
return
i
;
}
}
return
-
1
;
}
/***********************************************************************
* FILEDLG95_FILETYPE_Clean
*
* Clean the memory used by the filetype combo box
*/
static
void
FILEDLG95_FILETYPE_Clean
(
HWND
hwnd
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
int
iPos
;
int
iCount
=
CBGetCount
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
);
TRACE
(
"
\n
"
);
/* Delete each string of the combo and their associated data */
if
(
iCount
!=
CB_ERR
)
{
for
(
iPos
=
iCount
-
1
;
iPos
>=
0
;
iPos
--
)
{
MemFree
((
LPSTR
)
CBGetItemDataPtr
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
,
iPos
));
CBDeleteString
(
fodInfos
->
DlgInfos
.
hwndFileTypeCB
,
iPos
);
}
}
/* Current filter */
if
(
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
)
MemFree
(
fodInfos
->
ShellInfos
.
lpstrCurrentFilter
);
}
/***********************************************************************
* FILEDLG95_LOOKIN_Init
*
* Initialisation of the look in combo box
*/
static
HRESULT
FILEDLG95_LOOKIN_Init
(
HWND
hwndCombo
)
{
IShellFolder
*
psfRoot
,
*
psfDrives
;
IEnumIDList
*
lpeRoot
,
*
lpeDrives
;
LPITEMIDLIST
pidlDrives
,
pidlTmp
,
pidlTmp1
,
pidlAbsTmp
;
LookInInfos
*
liInfos
=
MemAlloc
(
sizeof
(
LookInInfos
));
TRACE
(
"
\n
"
);
liInfos
->
iMaxIndentation
=
0
;
SetPropA
(
hwndCombo
,
LookInInfosStr
,
(
HANDLE
)
liInfos
);
/* set item height for both text field and listbox */
CBSetItemHeight
(
hwndCombo
,
-
1
,
GetSystemMetrics
(
SM_CYSMICON
));
CBSetItemHeight
(
hwndCombo
,
0
,
GetSystemMetrics
(
SM_CYSMICON
));
/* Initialise data of Desktop folder */
SHGetSpecialFolderLocation
(
0
,
CSIDL_DESKTOP
,
&
pidlTmp
);
FILEDLG95_LOOKIN_AddItem
(
hwndCombo
,
pidlTmp
,
LISTEND
);
COMDLG32_SHFree
(
pidlTmp
);
SHGetSpecialFolderLocation
(
0
,
CSIDL_DRIVES
,
&
pidlDrives
);
SHGetDesktopFolder
(
&
psfRoot
);
if
(
psfRoot
)
{
/* enumerate the contents of the desktop */
if
(
SUCCEEDED
(
IShellFolder_EnumObjects
(
psfRoot
,
hwndCombo
,
SHCONTF_FOLDERS
,
&
lpeRoot
)))
{
while
(
S_OK
==
IEnumIDList_Next
(
lpeRoot
,
1
,
&
pidlTmp
,
NULL
))
{
FILEDLG95_LOOKIN_AddItem
(
hwndCombo
,
pidlTmp
,
LISTEND
);
/* special handling for CSIDL_DRIVES */
if
(
COMDLG32_PIDL_ILIsEqual
(
pidlTmp
,
pidlDrives
))
{
if
(
SUCCEEDED
(
IShellFolder_BindToObject
(
psfRoot
,
pidlTmp
,
NULL
,
&
IID_IShellFolder
,
(
LPVOID
*
)
&
psfDrives
)))
{
/* enumerate the drives */
if
(
SUCCEEDED
(
IShellFolder_EnumObjects
(
psfDrives
,
hwndCombo
,
SHCONTF_FOLDERS
,
&
lpeDrives
)))
{
while
(
S_OK
==
IEnumIDList_Next
(
lpeDrives
,
1
,
&
pidlTmp1
,
NULL
))
{
pidlAbsTmp
=
COMDLG32_PIDL_ILCombine
(
pidlTmp
,
pidlTmp1
);
FILEDLG95_LOOKIN_AddItem
(
hwndCombo
,
pidlAbsTmp
,
LISTEND
);
COMDLG32_SHFree
(
pidlAbsTmp
);
COMDLG32_SHFree
(
pidlTmp1
);
}
IEnumIDList_Release
(
lpeDrives
);
}
IShellFolder_Release
(
psfDrives
);
}
}
COMDLG32_SHFree
(
pidlTmp
);
}
IEnumIDList_Release
(
lpeRoot
);
}
}
IShellFolder_Release
(
psfRoot
);
COMDLG32_SHFree
(
pidlDrives
);
return
NOERROR
;
}
/***********************************************************************
* FILEDLG95_LOOKIN_DrawItem
*
* WM_DRAWITEM message handler
*/
static
LRESULT
FILEDLG95_LOOKIN_DrawItem
(
LPDRAWITEMSTRUCT
pDIStruct
)
{
COLORREF
crWin
=
GetSysColor
(
COLOR_WINDOW
);
COLORREF
crHighLight
=
GetSysColor
(
COLOR_HIGHLIGHT
);
COLORREF
crText
=
GetSysColor
(
COLOR_WINDOWTEXT
);
RECT
rectText
;
RECT
rectIcon
;
SHFILEINFOA
sfi
;
HIMAGELIST
ilItemImage
;
int
iIndentation
;
TEXTMETRICA
tm
;
LPSFOLDER
tmpFolder
;
LookInInfos
*
liInfos
=
(
LookInInfos
*
)
GetPropA
(
pDIStruct
->
hwndItem
,
LookInInfosStr
);
TRACE
(
"
\n
"
);
if
(
pDIStruct
->
itemID
==
-
1
)
return
0
;
if
(
!
(
tmpFolder
=
(
LPSFOLDER
)
CBGetItemDataPtr
(
pDIStruct
->
hwndItem
,
pDIStruct
->
itemID
)))
return
0
;
if
(
pDIStruct
->
itemID
==
liInfos
->
uSelectedItem
)
{
ilItemImage
=
(
HIMAGELIST
)
SHGetFileInfoA
((
LPCSTR
)
tmpFolder
->
pidlItem
,
0
,
&
sfi
,
sizeof
(
SHFILEINFOA
),
SHGFI_PIDL
|
SHGFI_SMALLICON
|
SHGFI_OPENICON
|
SHGFI_SYSICONINDEX
|
SHGFI_DISPLAYNAME
);
}
else
{
ilItemImage
=
(
HIMAGELIST
)
SHGetFileInfoA
((
LPCSTR
)
tmpFolder
->
pidlItem
,
0
,
&
sfi
,
sizeof
(
SHFILEINFOA
),
SHGFI_PIDL
|
SHGFI_SMALLICON
|
SHGFI_SYSICONINDEX
|
SHGFI_DISPLAYNAME
);
}
/* Is this item selected ? */
if
(
pDIStruct
->
itemState
&
ODS_SELECTED
)
{
SetTextColor
(
pDIStruct
->
hDC
,(
0x00FFFFFF
&
~
(
crText
)));
SetBkColor
(
pDIStruct
->
hDC
,
crHighLight
);
FillRect
(
pDIStruct
->
hDC
,
&
pDIStruct
->
rcItem
,
GetSysColorBrush
(
COLOR_HIGHLIGHT
));
}
else
{
SetTextColor
(
pDIStruct
->
hDC
,
crText
);
SetBkColor
(
pDIStruct
->
hDC
,
crWin
);
FillRect
(
pDIStruct
->
hDC
,
&
pDIStruct
->
rcItem
,
GetSysColorBrush
(
COLOR_WINDOW
));
}
/* Do not indent item if drawing in the edit of the combo */
if
(
pDIStruct
->
itemState
&
ODS_COMBOBOXEDIT
)
{
iIndentation
=
0
;
ilItemImage
=
(
HIMAGELIST
)
SHGetFileInfoA
((
LPCSTR
)
tmpFolder
->
pidlItem
,
0
,
&
sfi
,
sizeof
(
SHFILEINFOA
),
SHGFI_PIDL
|
SHGFI_SMALLICON
|
SHGFI_OPENICON
|
SHGFI_SYSICONINDEX
|
SHGFI_DISPLAYNAME
);
}
else
{
iIndentation
=
tmpFolder
->
m_iIndent
;
}
/* Draw text and icon */
/* Initialise the icon display area */
rectIcon
.
left
=
pDIStruct
->
rcItem
.
left
+
ICONWIDTH
/
2
*
iIndentation
;
rectIcon
.
top
=
pDIStruct
->
rcItem
.
top
;
rectIcon
.
right
=
rectIcon
.
left
+
ICONWIDTH
;
rectIcon
.
bottom
=
pDIStruct
->
rcItem
.
bottom
;
/* Initialise the text display area */
GetTextMetricsA
(
pDIStruct
->
hDC
,
&
tm
);
rectText
.
left
=
rectIcon
.
right
;
rectText
.
top
=
(
pDIStruct
->
rcItem
.
top
+
pDIStruct
->
rcItem
.
bottom
-
tm
.
tmHeight
)
/
2
;
rectText
.
right
=
pDIStruct
->
rcItem
.
right
+
XTEXTOFFSET
;
rectText
.
bottom
=
(
pDIStruct
->
rcItem
.
top
+
pDIStruct
->
rcItem
.
bottom
+
tm
.
tmHeight
)
/
2
;
/* Draw the icon from the image list */
ImageList_Draw
(
ilItemImage
,
sfi
.
iIcon
,
pDIStruct
->
hDC
,
rectIcon
.
left
,
rectIcon
.
top
,
ILD_TRANSPARENT
);
/* Draw the associated text */
if
(
sfi
.
szDisplayName
)
TextOutA
(
pDIStruct
->
hDC
,
rectText
.
left
,
rectText
.
top
,
sfi
.
szDisplayName
,
strlen
(
sfi
.
szDisplayName
));
return
NOERROR
;
}
/***********************************************************************
* FILEDLG95_LOOKIN_OnCommand
*
* LookIn combo box WM_COMMAND message handler
* If the function succeeds, the return value is nonzero.
*/
static
BOOL
FILEDLG95_LOOKIN_OnCommand
(
HWND
hwnd
,
WORD
wNotifyCode
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"%p
\n
"
,
fodInfos
);
switch
(
wNotifyCode
)
{
case
CBN_SELENDOK
:
{
LPSFOLDER
tmpFolder
;
int
iItem
;
iItem
=
CBGetCurSel
(
fodInfos
->
DlgInfos
.
hwndLookInCB
);
if
(
!
(
tmpFolder
=
(
LPSFOLDER
)
CBGetItemDataPtr
(
fodInfos
->
DlgInfos
.
hwndLookInCB
,
iItem
)))
return
FALSE
;
if
(
SUCCEEDED
(
IShellBrowser_BrowseObject
(
fodInfos
->
Shell
.
FOIShellBrowser
,
tmpFolder
->
pidlItem
,
SBSP_ABSOLUTE
)))
{
return
TRUE
;
}
break
;
}
}
return
FALSE
;
}
/***********************************************************************
* FILEDLG95_LOOKIN_AddItem
*
* Adds an absolute pidl item to the lookin combo box
* returns the index of the inserted item
*/
static
int
FILEDLG95_LOOKIN_AddItem
(
HWND
hwnd
,
LPITEMIDLIST
pidl
,
int
iInsertId
)
{
LPITEMIDLIST
pidlNext
;
SHFILEINFOA
sfi
;
SFOLDER
*
tmpFolder
;
LookInInfos
*
liInfos
;
TRACE
(
"%08x
\n
"
,
iInsertId
);
if
(
!
pidl
)
return
-
1
;
if
(
!
(
liInfos
=
(
LookInInfos
*
)
GetPropA
(
hwnd
,
LookInInfosStr
)))
return
-
1
;
tmpFolder
=
MemAlloc
(
sizeof
(
SFOLDER
));
tmpFolder
->
m_iIndent
=
0
;
/* Calculate the indentation of the item in the lookin*/
pidlNext
=
pidl
;
while
(
(
pidlNext
=
COMDLG32_PIDL_ILGetNext
(
pidlNext
))
)
{
tmpFolder
->
m_iIndent
++
;
}
tmpFolder
->
pidlItem
=
COMDLG32_PIDL_ILClone
(
pidl
);
if
(
tmpFolder
->
m_iIndent
>
liInfos
->
iMaxIndentation
)
liInfos
->
iMaxIndentation
=
tmpFolder
->
m_iIndent
;
sfi
.
dwAttributes
=
SFGAO_FILESYSANCESTOR
|
SFGAO_FILESYSTEM
;
SHGetFileInfoA
((
LPSTR
)
pidl
,
0
,
&
sfi
,
sizeof
(
sfi
),
SHGFI_DISPLAYNAME
|
SHGFI_SYSICONINDEX
|
SHGFI_PIDL
|
SHGFI_SMALLICON
|
SHGFI_ATTRIBUTES
|
SHGFI_ATTR_SPECIFIED
);
TRACE
(
"-- Add %s attr=%08lx
\n
"
,
sfi
.
szDisplayName
,
sfi
.
dwAttributes
);
if
((
sfi
.
dwAttributes
&
SFGAO_FILESYSANCESTOR
)
||
(
sfi
.
dwAttributes
&
SFGAO_FILESYSTEM
))
{
int
iItemID
;
TRACE
(
"-- Add %s at %u
\n
"
,
sfi
.
szDisplayName
,
tmpFolder
->
m_iIndent
);
/* Add the item at the end of the list */
if
(
iInsertId
<
0
)
{
iItemID
=
CBAddString
(
hwnd
,
sfi
.
szDisplayName
);
}
/* Insert the item at the iInsertId position*/
else
{
iItemID
=
CBInsertString
(
hwnd
,
sfi
.
szDisplayName
,
iInsertId
);
}
CBSetItemDataPtr
(
hwnd
,
iItemID
,
tmpFolder
);
return
iItemID
;
}
COMDLG32_SHFree
(
tmpFolder
->
pidlItem
);
MemFree
(
tmpFolder
);
return
-
1
;
}
/***********************************************************************
* FILEDLG95_LOOKIN_InsertItemAfterParent
*
* Insert an item below its parent
*/
static
int
FILEDLG95_LOOKIN_InsertItemAfterParent
(
HWND
hwnd
,
LPITEMIDLIST
pidl
)
{
LPITEMIDLIST
pidlParent
=
GetParentPidl
(
pidl
);
int
iParentPos
;
TRACE
(
"
\n
"
);
iParentPos
=
FILEDLG95_LOOKIN_SearchItem
(
hwnd
,(
WPARAM
)
pidlParent
,
SEARCH_PIDL
);
if
(
iParentPos
<
0
)
{
iParentPos
=
FILEDLG95_LOOKIN_InsertItemAfterParent
(
hwnd
,
pidlParent
);
}
/* Free pidlParent memory */
COMDLG32_SHFree
((
LPVOID
)
pidlParent
);
return
FILEDLG95_LOOKIN_AddItem
(
hwnd
,
pidl
,
iParentPos
+
1
);
}
/***********************************************************************
* FILEDLG95_LOOKIN_SelectItem
*
* Adds an absolute pidl item to the lookin combo box
* returns the index of the inserted item
*/
int
FILEDLG95_LOOKIN_SelectItem
(
HWND
hwnd
,
LPITEMIDLIST
pidl
)
{
int
iItemPos
;
LookInInfos
*
liInfos
;
TRACE
(
"
\n
"
);
iItemPos
=
FILEDLG95_LOOKIN_SearchItem
(
hwnd
,(
WPARAM
)
pidl
,
SEARCH_PIDL
);
liInfos
=
(
LookInInfos
*
)
GetPropA
(
hwnd
,
LookInInfosStr
);
if
(
iItemPos
<
0
)
{
while
(
FILEDLG95_LOOKIN_RemoveMostExpandedItem
(
hwnd
)
>
-
1
);
iItemPos
=
FILEDLG95_LOOKIN_InsertItemAfterParent
(
hwnd
,
pidl
);
}
else
{
SFOLDER
*
tmpFolder
=
(
LPSFOLDER
)
CBGetItemDataPtr
(
hwnd
,
iItemPos
);
while
(
liInfos
->
iMaxIndentation
>
tmpFolder
->
m_iIndent
)
{
int
iRemovedItem
;
if
(
-
1
==
(
iRemovedItem
=
FILEDLG95_LOOKIN_RemoveMostExpandedItem
(
hwnd
)))
break
;
if
(
iRemovedItem
<
iItemPos
)
iItemPos
--
;
}
}
CBSetCurSel
(
hwnd
,
iItemPos
);
liInfos
->
uSelectedItem
=
iItemPos
;
return
0
;
}
/***********************************************************************
* FILEDLG95_LOOKIN_RemoveMostExpandedItem
*
* Remove the item with an expansion level over iExpansionLevel
*/
static
int
FILEDLG95_LOOKIN_RemoveMostExpandedItem
(
HWND
hwnd
)
{
int
iItemPos
;
LookInInfos
*
liInfos
=
(
LookInInfos
*
)
GetPropA
(
hwnd
,
LookInInfosStr
);
TRACE
(
"
\n
"
);
if
(
liInfos
->
iMaxIndentation
<=
2
)
return
-
1
;
if
((
iItemPos
=
FILEDLG95_LOOKIN_SearchItem
(
hwnd
,(
WPARAM
)
liInfos
->
iMaxIndentation
,
SEARCH_EXP
))
>=
0
)
{
SFOLDER
*
tmpFolder
=
(
LPSFOLDER
)
CBGetItemDataPtr
(
hwnd
,
iItemPos
);
COMDLG32_SHFree
(
tmpFolder
->
pidlItem
);
MemFree
(
tmpFolder
);
CBDeleteString
(
hwnd
,
iItemPos
);
liInfos
->
iMaxIndentation
--
;
return
iItemPos
;
}
return
-
1
;
}
/***********************************************************************
* FILEDLG95_LOOKIN_SearchItem
*
* Search for pidl in the lookin combo box
* returns the index of the found item
*/
static
int
FILEDLG95_LOOKIN_SearchItem
(
HWND
hwnd
,
WPARAM
searchArg
,
int
iSearchMethod
)
{
int
i
=
0
;
int
iCount
=
CBGetCount
(
hwnd
);
TRACE
(
"0x%08x 0x%x
\n
"
,
searchArg
,
iSearchMethod
);
if
(
iCount
!=
CB_ERR
)
{
for
(;
i
<
iCount
;
i
++
)
{
LPSFOLDER
tmpFolder
=
(
LPSFOLDER
)
CBGetItemDataPtr
(
hwnd
,
i
);
if
(
iSearchMethod
==
SEARCH_PIDL
&&
COMDLG32_PIDL_ILIsEqual
((
LPITEMIDLIST
)
searchArg
,
tmpFolder
->
pidlItem
))
return
i
;
if
(
iSearchMethod
==
SEARCH_EXP
&&
tmpFolder
->
m_iIndent
==
(
int
)
searchArg
)
return
i
;
}
}
return
-
1
;
}
/***********************************************************************
* FILEDLG95_LOOKIN_Clean
*
* Clean the memory used by the lookin combo box
*/
static
void
FILEDLG95_LOOKIN_Clean
(
HWND
hwnd
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
int
iPos
;
int
iCount
=
CBGetCount
(
fodInfos
->
DlgInfos
.
hwndLookInCB
);
TRACE
(
"
\n
"
);
/* Delete each string of the combo and their associated data */
if
(
iCount
!=
CB_ERR
)
{
for
(
iPos
=
iCount
-
1
;
iPos
>=
0
;
iPos
--
)
{
SFOLDER
*
tmpFolder
=
(
LPSFOLDER
)
CBGetItemDataPtr
(
fodInfos
->
DlgInfos
.
hwndLookInCB
,
iPos
);
COMDLG32_SHFree
(
tmpFolder
->
pidlItem
);
MemFree
(
tmpFolder
);
CBDeleteString
(
fodInfos
->
DlgInfos
.
hwndLookInCB
,
iPos
);
}
}
/* LookInInfos structure */
RemovePropA
(
fodInfos
->
DlgInfos
.
hwndLookInCB
,
LookInInfosStr
);
}
/***********************************************************************
* FILEDLG95_FILENAME_FillFromSelection
*
* fills the edit box from the cached DataObject
*/
void
FILEDLG95_FILENAME_FillFromSelection
(
HWND
hwnd
)
{
FileOpenDlgInfos
*
fodInfos
;
LPITEMIDLIST
pidl
;
UINT
nFiles
=
0
,
nFileToOpen
,
nFileSelected
,
nLength
=
0
;
char
lpstrTemp
[
MAX_PATH
];
LPSTR
lpstrAllFile
=
NULL
,
lpstrCurrFile
=
NULL
;
TRACE
(
"
\n
"
);
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
/* Count how many files we have */
nFileSelected
=
GetNumSelected
(
fodInfos
->
Shell
.
FOIDataObject
);
/* calculate the string length, count files */
if
(
nFileSelected
>=
1
)
{
nLength
+=
3
;
/* first and last quotes, trailing \0 */
for
(
nFileToOpen
=
0
;
nFileToOpen
<
nFileSelected
;
nFileToOpen
++
)
{
pidl
=
GetPidlFromDataObject
(
fodInfos
->
Shell
.
FOIDataObject
,
nFileToOpen
+
1
);
if
(
pidl
)
{
/* get the total length of the selected file names */
lpstrTemp
[
0
]
=
'\0'
;
GetName
(
fodInfos
->
Shell
.
FOIShellFolder
,
pidl
,
SHGDN_INFOLDER
|
SHGDN_FORPARSING
,
lpstrTemp
);
if
(
!
IsPidlFolder
(
fodInfos
->
Shell
.
FOIShellFolder
,
pidl
)
)
/* Ignore folders */
{
nLength
+=
strlen
(
lpstrTemp
)
+
3
;
nFiles
++
;
}
COMDLG32_SHFree
(
pidl
);
}
}
}
/* allocate the buffer */
if
(
nFiles
<=
1
)
nLength
=
MAX_PATH
;
lpstrAllFile
=
(
LPSTR
)
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
nLength
);
lpstrAllFile
[
0
]
=
'\0'
;
/* Generate the string for the edit control */
if
(
nFiles
>=
1
)
{
lpstrCurrFile
=
lpstrAllFile
;
for
(
nFileToOpen
=
0
;
nFileToOpen
<
nFileSelected
;
nFileToOpen
++
)
{
pidl
=
GetPidlFromDataObject
(
fodInfos
->
Shell
.
FOIDataObject
,
nFileToOpen
+
1
);
if
(
pidl
)
{
/* get the file name */
lpstrTemp
[
0
]
=
'\0'
;
GetName
(
fodInfos
->
Shell
.
FOIShellFolder
,
pidl
,
SHGDN_INFOLDER
|
SHGDN_FORPARSING
,
lpstrTemp
);
if
(
!
IsPidlFolder
(
fodInfos
->
Shell
.
FOIShellFolder
,
pidl
))
/* Ignore folders */
{
if
(
nFiles
>
1
)
{
*
lpstrCurrFile
++
=
'\"'
;
strcpy
(
lpstrCurrFile
,
lpstrTemp
);
lpstrCurrFile
+=
strlen
(
lpstrTemp
);
strcpy
(
lpstrCurrFile
,
"
\"
"
);
lpstrCurrFile
+=
2
;
}
else
{
strcpy
(
lpstrAllFile
,
lpstrTemp
);
}
}
COMDLG32_SHFree
(
(
LPVOID
)
pidl
);
}
}
SetWindowTextA
(
fodInfos
->
DlgInfos
.
hwndFileName
,
lpstrAllFile
);
}
HeapFree
(
GetProcessHeap
(),
0
,
lpstrAllFile
);
}
/* copied from shell32 to avoid linking to it */
static
HRESULT
COMDLG32_StrRetToStrNA
(
LPVOID
dest
,
DWORD
len
,
LPSTRRET
src
,
LPITEMIDLIST
pidl
)
{
switch
(
src
->
uType
)
{
case
STRRET_WSTR
:
WideCharToMultiByte
(
CP_ACP
,
0
,
src
->
u
.
pOleStr
,
-
1
,
(
LPSTR
)
dest
,
len
,
NULL
,
NULL
);
COMDLG32_SHFree
(
src
->
u
.
pOleStr
);
break
;
case
STRRET_CSTR
:
lstrcpynA
((
LPSTR
)
dest
,
src
->
u
.
cStr
,
len
);
break
;
case
STRRET_OFFSET
:
lstrcpynA
((
LPSTR
)
dest
,
((
LPCSTR
)
&
pidl
->
mkid
)
+
src
->
u
.
uOffset
,
len
);
break
;
default:
FIXME
(
"unknown type!
\n
"
);
if
(
len
)
{
*
(
LPSTR
)
dest
=
'\0'
;
}
return
(
FALSE
);
}
return
S_OK
;
}
/***********************************************************************
* FILEDLG95_FILENAME_GetFileNames
*
* copies the filenames to a 0-delimited string list (A\0B\0C\0\0)
*/
int
FILEDLG95_FILENAME_GetFileNames
(
HWND
hwnd
,
LPWSTR
*
lpstrFileList
,
UINT
*
sizeUsed
)
{
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
UINT
nStrCharCount
=
0
;
/* index in src buffer */
UINT
nFileIndex
=
0
;
/* index in dest buffer */
UINT
nFileCount
=
0
;
/* number of files */
UINT
nStrLen
=
0
;
/* length of string in edit control */
LPWSTR
lpstrEdit
;
/* buffer for string from edit control */
TRACE
(
"
\n
"
);
/* get the filenames from the edit control */
nStrLen
=
SendMessageW
(
fodInfos
->
DlgInfos
.
hwndFileName
,
WM_GETTEXTLENGTH
,
0
,
0
);
lpstrEdit
=
MemAlloc
(
(
nStrLen
+
1
)
*
sizeof
(
WCHAR
)
);
GetDlgItemTextW
(
hwnd
,
IDC_FILENAME
,
lpstrEdit
,
nStrLen
+
1
);
TRACE
(
"nStrLen=%u str=%s
\n
"
,
nStrLen
,
debugstr_w
(
lpstrEdit
));
/* we might get single filename without any '"',
* so we need nStrLen + terminating \0 + end-of-list \0 */
*
lpstrFileList
=
MemAlloc
(
(
nStrLen
+
2
)
*
sizeof
(
WCHAR
)
);
*
sizeUsed
=
0
;
/* build 0-delimited file list from filenames */
while
(
nStrCharCount
<=
nStrLen
)
{
if
(
lpstrEdit
[
nStrCharCount
]
==
'"'
)
{
nStrCharCount
++
;
while
((
lpstrEdit
[
nStrCharCount
]
!=
'"'
)
&&
(
nStrCharCount
<=
nStrLen
))
{
(
*
lpstrFileList
)[
nFileIndex
++
]
=
lpstrEdit
[
nStrCharCount
];
(
*
sizeUsed
)
++
;
nStrCharCount
++
;
}
(
*
lpstrFileList
)[
nFileIndex
++
]
=
'\0'
;
(
*
sizeUsed
)
++
;
nFileCount
++
;
}
nStrCharCount
++
;
}
/* single, unquoted string */
if
((
nStrLen
>
0
)
&&
(
*
sizeUsed
==
0
)
)
{
strcpyW
(
*
lpstrFileList
,
lpstrEdit
);
nFileIndex
=
strlenW
(
lpstrEdit
)
+
1
;
(
*
sizeUsed
)
=
nFileIndex
;
nFileCount
=
1
;
}
/* trailing \0 */
(
*
lpstrFileList
)[
nFileIndex
]
=
'\0'
;
(
*
sizeUsed
)
++
;
MemFree
(
lpstrEdit
);
return
nFileCount
;
}
#define SETDefFormatEtc(fe,cf,med) \
{ \
(fe).cfFormat = cf;\
(fe).dwAspect = DVASPECT_CONTENT; \
(fe).ptd =NULL;\
(fe).tymed = med;\
(fe).lindex = -1;\
};
/*
* DATAOBJECT Helper functions
*/
/***********************************************************************
* COMCTL32_ReleaseStgMedium
*
* like ReleaseStgMedium from ole32
*/
static
void
COMCTL32_ReleaseStgMedium
(
STGMEDIUM
medium
)
{
if
(
medium
.
pUnkForRelease
)
{
IUnknown_Release
(
medium
.
pUnkForRelease
);
}
else
{
GlobalUnlock
(
medium
.
u
.
hGlobal
);
GlobalFree
(
medium
.
u
.
hGlobal
);
}
}
/***********************************************************************
* GetPidlFromDataObject
*
* Return pidl(s) by number from the cached DataObject
*
* nPidlIndex=0 gets the fully qualified root path
*/
LPITEMIDLIST
GetPidlFromDataObject
(
IDataObject
*
doSelected
,
UINT
nPidlIndex
)
{
STGMEDIUM
medium
;
FORMATETC
formatetc
;
LPITEMIDLIST
pidl
=
NULL
;
TRACE
(
"sv=%p index=%u
\n
"
,
doSelected
,
nPidlIndex
);
/* Set the FORMATETC structure*/
SETDefFormatEtc
(
formatetc
,
RegisterClipboardFormatA
(
CFSTR_SHELLIDLIST
),
TYMED_HGLOBAL
);
/* Get the pidls from IDataObject */
if
(
SUCCEEDED
(
IDataObject_GetData
(
doSelected
,
&
formatetc
,
&
medium
)))
{
LPIDA
cida
=
GlobalLock
(
medium
.
u
.
hGlobal
);
if
(
nPidlIndex
<=
cida
->
cidl
)
{
pidl
=
COMDLG32_PIDL_ILClone
((
LPITEMIDLIST
)(
&
((
LPBYTE
)
cida
)[
cida
->
aoffset
[
nPidlIndex
]]));
}
COMCTL32_ReleaseStgMedium
(
medium
);
}
return
pidl
;
}
/***********************************************************************
* GetNumSelected
*
* Return the number of selected items in the DataObject.
*
*/
UINT
GetNumSelected
(
IDataObject
*
doSelected
)
{
UINT
retVal
=
0
;
STGMEDIUM
medium
;
FORMATETC
formatetc
;
TRACE
(
"sv=%p
\n
"
,
doSelected
);
if
(
!
doSelected
)
return
0
;
/* Set the FORMATETC structure*/
SETDefFormatEtc
(
formatetc
,
RegisterClipboardFormatA
(
CFSTR_SHELLIDLIST
),
TYMED_HGLOBAL
);
/* Get the pidls from IDataObject */
if
(
SUCCEEDED
(
IDataObject_GetData
(
doSelected
,
&
formatetc
,
&
medium
)))
{
LPIDA
cida
=
GlobalLock
(
medium
.
u
.
hGlobal
);
retVal
=
cida
->
cidl
;
COMCTL32_ReleaseStgMedium
(
medium
);
return
retVal
;
}
return
0
;
}
/*
* TOOLS
*/
/***********************************************************************
* GetName
*
* Get the pidl's display name (relative to folder) and
* put it in lpstrFileName.
*
* Return NOERROR on success,
* E_FAIL otherwise
*/
HRESULT
GetName
(
LPSHELLFOLDER
lpsf
,
LPITEMIDLIST
pidl
,
DWORD
dwFlags
,
LPSTR
lpstrFileName
)
{
STRRET
str
;
HRESULT
hRes
;
TRACE
(
"sf=%p pidl=%p
\n
"
,
lpsf
,
pidl
);
if
(
!
lpsf
)
{
HRESULT
hRes
;
SHGetDesktopFolder
(
&
lpsf
);
hRes
=
GetName
(
lpsf
,
pidl
,
dwFlags
,
lpstrFileName
);
IShellFolder_Release
(
lpsf
);
return
hRes
;
}
/* Get the display name of the pidl relative to the folder */
if
(
SUCCEEDED
(
hRes
=
IShellFolder_GetDisplayNameOf
(
lpsf
,
pidl
,
dwFlags
,
&
str
)))
{
return
COMDLG32_StrRetToStrNA
(
lpstrFileName
,
MAX_PATH
,
&
str
,
pidl
);
}
return
E_FAIL
;
}
/***********************************************************************
* GetShellFolderFromPidl
*
* pidlRel is the item pidl relative
* Return the IShellFolder of the absolute pidl
*/
IShellFolder
*
GetShellFolderFromPidl
(
LPITEMIDLIST
pidlAbs
)
{
IShellFolder
*
psf
=
NULL
,
*
psfParent
;
TRACE
(
"%p
\n
"
,
pidlAbs
);
if
(
SUCCEEDED
(
SHGetDesktopFolder
(
&
psfParent
)))
{
psf
=
psfParent
;
if
(
pidlAbs
&&
pidlAbs
->
mkid
.
cb
)
{
if
(
SUCCEEDED
(
IShellFolder_BindToObject
(
psfParent
,
pidlAbs
,
NULL
,
&
IID_IShellFolder
,
(
LPVOID
*
)
&
psf
)))
{
IShellFolder_Release
(
psfParent
);
return
psf
;
}
}
/* return the desktop */
return
psfParent
;
}
return
NULL
;
}
/***********************************************************************
* GetParentPidl
*
* Return the LPITEMIDLIST to the parent of the pidl in the list
*/
LPITEMIDLIST
GetParentPidl
(
LPITEMIDLIST
pidl
)
{
LPITEMIDLIST
pidlParent
;
TRACE
(
"%p
\n
"
,
pidl
);
pidlParent
=
COMDLG32_PIDL_ILClone
(
pidl
);
COMDLG32_PIDL_ILRemoveLastID
(
pidlParent
);
return
pidlParent
;
}
/***********************************************************************
* GetPidlFromName
*
* returns the pidl of the file name relative to folder
* NULL if an error occurred
*/
LPITEMIDLIST
GetPidlFromName
(
IShellFolder
*
lpsf
,
LPWSTR
lpcstrFileName
)
{
LPITEMIDLIST
pidl
=
NULL
;
ULONG
ulEaten
;
TRACE
(
"sf=%p file=%s
\n
"
,
lpsf
,
debugstr_w
(
lpcstrFileName
));
if
(
!
lpcstrFileName
)
return
NULL
;
if
(
!*
lpcstrFileName
)
return
NULL
;
if
(
!
lpsf
)
{
if
(
SUCCEEDED
(
SHGetDesktopFolder
(
&
lpsf
)))
{
IShellFolder_ParseDisplayName
(
lpsf
,
0
,
NULL
,
lpcstrFileName
,
&
ulEaten
,
&
pidl
,
NULL
);
IShellFolder_Release
(
lpsf
);
}
}
else
{
IShellFolder_ParseDisplayName
(
lpsf
,
0
,
NULL
,
lpcstrFileName
,
&
ulEaten
,
&
pidl
,
NULL
);
}
return
pidl
;
}
/*
*/
BOOL
IsPidlFolder
(
LPSHELLFOLDER
psf
,
LPCITEMIDLIST
pidl
)
{
ULONG
uAttr
=
SFGAO_FOLDER
|
SFGAO_HASSUBFOLDER
;
HRESULT
ret
;
TRACE
(
"%p, %p
\n
"
,
psf
,
pidl
);
ret
=
IShellFolder_GetAttributesOf
(
psf
,
1
,
&
pidl
,
&
uAttr
);
TRACE
(
"-- 0x%08lx 0x%08lx
\n
"
,
uAttr
,
ret
);
/* see documentation shell 4.1*/
return
uAttr
&
(
SFGAO_FOLDER
|
SFGAO_HASSUBFOLDER
);
}
/***********************************************************************
* BrowseSelectedFolder
*/
static
BOOL
BrowseSelectedFolder
(
HWND
hwnd
)
{
BOOL
bBrowseSelFolder
=
FALSE
;
FileOpenDlgInfos
*
fodInfos
=
(
FileOpenDlgInfos
*
)
GetPropA
(
hwnd
,
FileOpenDlgInfosStr
);
TRACE
(
"
\n
"
);
if
(
GetNumSelected
(
fodInfos
->
Shell
.
FOIDataObject
)
==
1
)
{
LPITEMIDLIST
pidlSelection
;
/* get the file selected */
pidlSelection
=
GetPidlFromDataObject
(
fodInfos
->
Shell
.
FOIDataObject
,
1
);
if
(
IsPidlFolder
(
fodInfos
->
Shell
.
FOIShellFolder
,
pidlSelection
))
{
if
(
FAILED
(
IShellBrowser_BrowseObject
(
fodInfos
->
Shell
.
FOIShellBrowser
,
pidlSelection
,
SBSP_RELATIVE
)
)
)
{
WCHAR
notexist
[]
=
{
'P'
,
'a'
,
't'
,
'h'
,
' '
,
'd'
,
'o'
,
'e'
,
's'
,
' '
,
'n'
,
'o'
,
't'
,
' '
,
'e'
,
'x'
,
'i'
,
's'
,
't'
,
0
};
MessageBoxW
(
hwnd
,
notexist
,
fodInfos
->
title
,
MB_OK
|
MB_ICONEXCLAMATION
);
}
bBrowseSelFolder
=
TRUE
;
}
COMDLG32_SHFree
(
pidlSelection
);
}
return
bBrowseSelFolder
;
}
/*
* Memory allocation methods */
static
void
*
MemAlloc
(
UINT
size
)
{
return
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
size
);
}
static
void
MemFree
(
void
*
mem
)
{
if
(
mem
)
{
HeapFree
(
GetProcessHeap
(),
0
,
mem
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment