https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d55e33d0f3cf7ca8a1b08…
commit d55e33d0f3cf7ca8a1b087a677ef5726834130aa
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Mon Sep 4 21:11:24 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Mon Sep 4 21:11:24 2023 +0900
[COMDLG32] GetOpen/GetSaveFileName: Improve extension handling (#5640)
- Improve GetOpenFileName and GetSaveFileName
functions.
- Add FILEDLG95_GetFallbackExtension and
FILEDLG95_AddDotExtIfNeeded helper functions.
- Modify FILEDLG95_ValidatePathAction and
FILEDLG95_OnOpen functions.
CORE-19148, CORE-15020
---
dll/win32/comdlg32/cdlg.h | 6 ++
dll/win32/comdlg32/filedlg.c | 202 +++++++++++++++++++-----------------
dll/win32/comdlg32/filedlgbrowser.h | 5 +-
3 files changed, 118 insertions(+), 95 deletions(-)
diff --git a/dll/win32/comdlg32/cdlg.h b/dll/win32/comdlg32/cdlg.h
index 7570acebb9e..4c8be081e84 100644
--- a/dll/win32/comdlg32/cdlg.h
+++ b/dll/win32/comdlg32/cdlg.h
@@ -199,8 +199,14 @@ HRESULT FileSaveDialog_Constructor(IUnknown *pUnkOuter, REFIID riid,
void **ppv)
/* Shared helper functions */
void COMDLG32_GetCanonicalPath(PCIDLIST_ABSOLUTE pidlAbsCurrent, LPWSTR lpstrFile, LPWSTR
lpstrPathAndFile) DECLSPEC_HIDDEN;
+#ifdef __REACTOS__
+struct FileOpenDlgInfos;
+int FILEDLG95_ValidatePathAction(struct FileOpenDlgInfos *fodInfos, LPWSTR
lpstrPathAndFile, IShellFolder **ppsf,
+ HWND hwnd, DWORD flags, BOOL isSaveDlg, int defAction)
DECLSPEC_HIDDEN;
+#else
int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
HWND hwnd, DWORD flags, BOOL isSaveDlg, int defAction)
DECLSPEC_HIDDEN;
+#endif
int COMDLG32_SplitFileNames(LPWSTR lpstrEdit, UINT nStrLen, LPWSTR *lpstrFileList, UINT
*sizeUsed) DECLSPEC_HIDDEN;
void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText) DECLSPEC_HIDDEN;
diff --git a/dll/win32/comdlg32/filedlg.c b/dll/win32/comdlg32/filedlg.c
index 54bbc544aab..8aa8eae3987 100644
--- a/dll/win32/comdlg32/filedlg.c
+++ b/dll/win32/comdlg32/filedlg.c
@@ -2826,8 +2826,98 @@ void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText)
MessageBoxW(hwnd,strMsgText, strMsgTitle, MB_OK | MB_ICONHAND);
}
+#ifdef __REACTOS__
+/* The return value needs LocalFree */
+static LPWSTR FILEDLG95_GetFallbackExtension(FileOpenDlgInfos *fodInfos, LPWSTR
lpstrPathAndFile)
+{
+ LPWSTR lpstrFilter, the_ext = NULL, pchDot = NULL;
+
+ /* Without lpstrDefExt, append no extension */
+ if (!fodInfos->defext)
+ return NULL;
+
+ /* Get filter extensions */
+ lpstrFilter = (LPWSTR)CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
+ fodInfos->ofnInfos->nFilterIndex - 1);
+ if (lpstrFilter != (LPWSTR)CB_ERR && lpstrFilter && *lpstrFilter)
+ {
+ LPWSTR pchSemicolon = wcschr(lpstrFilter, L';');
+
+ if (pchSemicolon)
+ *pchSemicolon = UNICODE_NULL;
+
+ pchDot = wcschr(lpstrFilter, L'.');
+
+ if (pchDot && pchDot[1] && !wcschr(pchDot, L'*')
&& !wcschr(pchDot, L'?'))
+ the_ext = StrDupW(pchDot + 1);
+
+ if (pchSemicolon)
+ *pchSemicolon = L';';
+ }
+
+ if (!the_ext && (!pchDot || pchDot[1]))
+ {
+ /* use default extension if no extension in filter */
+ the_ext = StrDupW(fodInfos->defext);
+ }
+
+ return the_ext;
+}
+
+static BOOL
+FILEDLG95_AddDotExtIfNeeded(FileOpenDlgInfos *fodInfos, LPWSTR lpstrPathAndFile)
+{
+ BOOL ret = FALSE;
+ LPWSTR ext = PathFindExtensionW(lpstrPathAndFile);
+ int PathLength = lstrlenW(lpstrPathAndFile);
+ LPWSTR the_ext = FILEDLG95_GetFallbackExtension(fodInfos, lpstrPathAndFile);
+
+ if (the_ext && *the_ext &&
+ (*ext == UNICODE_NULL || lstrcmpiW(ext + 1, the_ext) != 0))
+ {
+ if (strlenW(lpstrPathAndFile) + 1 + strlenW(the_ext) + 1 <=
+ fodInfos->ofnInfos->nMaxFile)
+ {
+ /* Make the extension lowercase */
+ CharLowerW(the_ext);
+ /* Append it (with dot) to the file */
+ lstrcatW(lpstrPathAndFile, L".");
+ lstrcatW(lpstrPathAndFile, the_ext);
+ /* update ext */
+ ext = PathFindExtensionW(lpstrPathAndFile);
+ ret = TRUE;
+ }
+ }
+
+ LocalFree(the_ext);
+
+ /* In Open dialog: if file does not exist try without extension */
+ if (!(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) &&
!PathFileExistsW(lpstrPathAndFile))
+ {
+ lpstrPathAndFile[PathLength] = UNICODE_NULL;
+ ret = FALSE;
+ }
+
+ /* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
+ if (*ext)
+ ext++;
+ if (!lstrcmpiW(fodInfos->defext, ext))
+ fodInfos->ofnInfos->Flags &= ~OFN_EXTENSIONDIFFERENT;
+ else
+ fodInfos->ofnInfos->Flags |= OFN_EXTENSIONDIFFERENT;
+
+ return ret;
+}
+#endif
+
+#ifdef __REACTOS__
+int FILEDLG95_ValidatePathAction(struct FileOpenDlgInfos *fodInfos, LPWSTR
lpstrPathAndFile,
+ IShellFolder **ppsf, HWND hwnd, DWORD flags, BOOL
isSaveDlg,
+ int defAction)
+#else
int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
HWND hwnd, DWORD flags, BOOL isSaveDlg, int defAction)
+#endif
{
int nOpenAction = defAction;
LPWSTR lpszTemp, lpszTemp1;
@@ -2924,8 +3014,17 @@ int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile,
IShellFolder **ppsf,
{
if( (flags & OFN_FILEMUSTEXIST) && !isSaveDlg )
{
+#ifdef __REACTOS__
+ FILEDLG95_AddDotExtIfNeeded(fodInfos, lpstrPathAndFile);
+ if (!PathFileExistsW(lpstrPathAndFile))
+ {
+ FILEDLG95_OnOpenMessage(hwnd, 0, IDS_FILENOTEXISTING);
+ break;
+ }
+#else
FILEDLG95_OnOpenMessage(hwnd, 0, IDS_FILENOTEXISTING);
break;
+#endif
}
}
/* change to the current folder */
@@ -3011,7 +3110,11 @@ BOOL FILEDLG95_OnOpen(HWND hwnd)
else
nOpenAction = ONOPEN_BROWSE;
+#ifdef __REACTOS__
+ nOpenAction = FILEDLG95_ValidatePathAction(fodInfos, lpstrPathAndFile, &lpsf,
hwnd,
+#else
nOpenAction = FILEDLG95_ValidatePathAction(lpstrPathAndFile, &lpsf, hwnd,
+#endif
fodInfos->ofnInfos->Flags,
fodInfos->DlgInfos.dwDlgProp &
FODPROP_SAVEDLG,
nOpenAction);
@@ -3088,7 +3191,9 @@ BOOL FILEDLG95_OnOpen(HWND hwnd)
case ONOPEN_OPEN: /* fill in the return struct and close the dialog */
TRACE("ONOPEN_OPEN %s\n", debugstr_w(lpstrPathAndFile));
{
+#ifndef __REACTOS__
WCHAR *ext = NULL;
+#endif
/* update READONLY check box flag */
if ((SendMessageW(GetDlgItem(hwnd,IDC_OPENREADONLY),BM_GETCHECK,0,0) & 0x03) ==
BST_CHECKED)
@@ -3097,104 +3202,13 @@ BOOL FILEDLG95_OnOpen(HWND hwnd)
fodInfos->ofnInfos->Flags &= ~OFN_READONLY;
/* Attach the file extension with file name*/
- ext = PathFindExtensionW(lpstrPathAndFile);
#ifdef __REACTOS__
- if (*ext == UNICODE_NULL && fodInfos->defext)
- {
- LPWSTR filterExt = NULL, lpstrFilter = NULL, pch, pchNext;
- LPCWSTR the_ext = NULL;
- static const WCHAR szwDot[] = {'.',0};
- int PathLength = lstrlenW(lpstrPathAndFile);
-
- /* get filter extensions */
- lpstrFilter = (LPWSTR)
CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
-
fodInfos->ofnInfos->nFilterIndex - 1);
- if (lpstrFilter != (LPWSTR)CB_ERR) /* control is not empty */
- {
- LPWSTR filterSearchIndex, pchFirst = NULL;
- filterExt = heap_alloc((lstrlenW(lpstrFilter) + 1) * sizeof(WCHAR));
- if (filterExt)
- {
- strcpyW(filterExt, lpstrFilter);
-
- if (ext && *ext)
- {
- /* find ext in filter */
- for (pch = filterExt; pch && *pch; pch = pchNext)
- {
- filterSearchIndex = strchrW(pch, ';');
- if (filterSearchIndex)
- {
- filterSearchIndex[0] = 0;
- pchNext = filterSearchIndex + 1;
- }
- else
- {
- pchNext = NULL;
- }
-
- while (*pch == '*' || *pch == '.' || *pch ==
'?')
- {
- ++pch;
- }
-
- if (!pchFirst)
- pchFirst = pch;
-
- if (lstrcmpiW(pch, &ext[1]) == 0)
- {
- the_ext = pch;
- break;
- }
- }
-
- /* use first one if not found */
- if (!the_ext && pchFirst && *pchFirst)
- {
- the_ext = pchFirst;
- }
- }
- }
- }
-
- if (!the_ext)
- {
- /* use default extension if no extension in filter */
- the_ext = fodInfos->defext;
- }
-
- if (the_ext && *the_ext && lstrcmpiW(&ext[1], the_ext) !=
0)
- {
- if (strlenW(lpstrPathAndFile) + 1 + strlenW(the_ext) + 1 <=
- fodInfos->ofnInfos->nMaxFile)
- {
- /* append the dot */
- lstrcatW(lpstrPathAndFile, szwDot);
- /* append the extension */
- lstrcatW(lpstrPathAndFile, the_ext);
- /* update ext */
- ext = PathFindExtensionW(lpstrPathAndFile);
- }
- }
-
- heap_free(filterExt);
-
- /* In Open dialog: if file does not exist try without extension */
- if (!(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) &&
!PathFileExistsW(lpstrPathAndFile))
- lpstrPathAndFile[PathLength] = 0;
-
- /* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
- if (*ext)
- ext++;
- if (!lstrcmpiW(fodInfos->defext, ext))
- fodInfos->ofnInfos->Flags &= ~OFN_EXTENSIONDIFFERENT;
- else
- fodInfos->ofnInfos->Flags |= OFN_EXTENSIONDIFFERENT;
- }
-
+ /* Add extension if necessary */
+ FILEDLG95_AddDotExtIfNeeded(fodInfos, lpstrPathAndFile);
/* update dialog data */
SetWindowTextW(fodInfos->DlgInfos.hwndFileName,
PathFindFileNameW(lpstrPathAndFile));
#else /* __REACTOS__ */
+ ext = PathFindExtensionW(lpstrPathAndFile);
if (! *ext && fodInfos->defext)
{
/* if no extension is specified with file name, then */
diff --git a/dll/win32/comdlg32/filedlgbrowser.h b/dll/win32/comdlg32/filedlgbrowser.h
index 67c07a8793c..ee7fbdc79d8 100644
--- a/dll/win32/comdlg32/filedlgbrowser.h
+++ b/dll/win32/comdlg32/filedlgbrowser.h
@@ -47,8 +47,11 @@
* Data structure
*/
-
+#ifdef __REACTOS__
+typedef struct FileOpenDlgInfos
+#else
typedef struct
+#endif
{
LPOPENFILENAMEW ofnInfos;
BOOL unicode;