https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d55e33d0f3cf7ca8a1b087a677ef5726834130aa
commit d55e33d0f3cf7ca8a1b087a677ef5726834130aa Author: Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com> AuthorDate: Mon Sep 4 21:11:24 2023 +0900 Commit: GitHub <nore...@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;