1370b324cSopenharmony_ci// Windows/CommonDialog.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../Common/MyBuffer.h" 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#ifdef UNDER_CE 8370b324cSopenharmony_ci#include <commdlg.h> 9370b324cSopenharmony_ci#endif 10370b324cSopenharmony_ci 11370b324cSopenharmony_ci#ifndef _UNICODE 12370b324cSopenharmony_ci#include "../Common/StringConvert.h" 13370b324cSopenharmony_ci#endif 14370b324cSopenharmony_ci 15370b324cSopenharmony_ci#include "CommonDialog.h" 16370b324cSopenharmony_ci#include "Defs.h" 17370b324cSopenharmony_ci// #include "FileDir.h" 18370b324cSopenharmony_ci 19370b324cSopenharmony_ci#ifndef _UNICODE 20370b324cSopenharmony_ciextern bool g_IsNT; 21370b324cSopenharmony_ci#endif 22370b324cSopenharmony_ci 23370b324cSopenharmony_cinamespace NWindows { 24370b324cSopenharmony_ci 25370b324cSopenharmony_ci/* 26370b324cSopenharmony_ci GetSaveFileName() 27370b324cSopenharmony_ci GetOpenFileName() 28370b324cSopenharmony_ci OPENFILENAME 29370b324cSopenharmony_ci 30370b324cSopenharmony_ci(lpstrInitialDir) : the initial directory. 31370b324cSopenharmony_ciDOCs: the algorithm for selecting the initial directory varies on different platforms: 32370b324cSopenharmony_ci{ 33370b324cSopenharmony_ci Win2000/XP/Vista: 34370b324cSopenharmony_ci 1. If lpstrFile contains a path, that path is the initial directory. 35370b324cSopenharmony_ci 2. Otherwise, lpstrInitialDir specifies the initial directory. 36370b324cSopenharmony_ci 37370b324cSopenharmony_ci Win7: 38370b324cSopenharmony_ci If lpstrInitialDir has the same value as was passed the first time 39370b324cSopenharmony_ci the application used an Open or Save As dialog box, the path 40370b324cSopenharmony_ci most recently selected by the user is used as the initial directory. 41370b324cSopenharmony_ci} 42370b324cSopenharmony_ci 43370b324cSopenharmony_ciWin10: 44370b324cSopenharmony_ci in: 45370b324cSopenharmony_ci function supports (lpstrInitialDir) path with super prefix "\\\\?\\" 46370b324cSopenharmony_ci function supports (lpstrInitialDir) path with long path 47370b324cSopenharmony_ci function doesn't support absolute (lpstrFile) path with super prefix "\\\\?\\" 48370b324cSopenharmony_ci function doesn't support absolute (lpstrFile) path with long path 49370b324cSopenharmony_ci out: the path with super prefix "\\\\?\\" will be returned, if selected path is long 50370b324cSopenharmony_ci 51370b324cSopenharmony_ciWinXP-64 and Win10: if no filters, the system shows all files. 52370b324cSopenharmony_ci but DOCs say: If all three members are zero or NULL, 53370b324cSopenharmony_ci the system does not use any filters and does not 54370b324cSopenharmony_ci show any files in the file list control of the dialog box. 55370b324cSopenharmony_ci 56370b324cSopenharmony_ciin Win7+: GetOpenFileName() and GetSaveFileName() 57370b324cSopenharmony_ci do not support pstrCustomFilter feature anymore 58370b324cSopenharmony_ci*/ 59370b324cSopenharmony_ci 60370b324cSopenharmony_ci#ifdef UNDER_CE 61370b324cSopenharmony_ci#define MY_OFN_PROJECT 0x00400000 62370b324cSopenharmony_ci#define MY_OFN_SHOW_ALL 0x01000000 63370b324cSopenharmony_ci#endif 64370b324cSopenharmony_ci 65370b324cSopenharmony_ci 66370b324cSopenharmony_ci/* 67370b324cSopenharmony_cistructures 68370b324cSopenharmony_ci OPENFILENAMEW 69370b324cSopenharmony_ci OPENFILENAMEA 70370b324cSopenharmony_cicontain additional members: 71370b324cSopenharmony_ci#if (_WIN32_WINNT >= 0x0500) 72370b324cSopenharmony_ci void *pvReserved; 73370b324cSopenharmony_ci DWORD dwReserved; 74370b324cSopenharmony_ci DWORD FlagsEx; 75370b324cSopenharmony_ci#endif 76370b324cSopenharmony_ci 77370b324cSopenharmony_ciIf we compile the source code with (_WIN32_WINNT >= 0x0500), some functions 78370b324cSopenharmony_ciwill not work at NT 4.0, if we use sizeof(OPENFILENAME). 79370b324cSopenharmony_ciWe try to use reduced structure OPENFILENAME_NT4. 80370b324cSopenharmony_ci*/ 81370b324cSopenharmony_ci 82370b324cSopenharmony_ci// #if defined(_WIN64) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500) 83370b324cSopenharmony_ci#if defined(__GNUC__) && (__GNUC__ <= 9) || defined(Z7_OLD_WIN_SDK) 84370b324cSopenharmony_ci #ifndef _UNICODE 85370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEA OPENFILENAMEA 86370b324cSopenharmony_ci #endif 87370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEW OPENFILENAMEW 88370b324cSopenharmony_ci 89370b324cSopenharmony_ci // MinGW doesn't support some required macros. So we define them here: 90370b324cSopenharmony_ci #ifndef CDSIZEOF_STRUCT 91370b324cSopenharmony_ci #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) 92370b324cSopenharmony_ci #endif 93370b324cSopenharmony_ci #ifndef _UNICODE 94370b324cSopenharmony_ci #ifndef OPENFILENAME_SIZE_VERSION_400A 95370b324cSopenharmony_ci #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName) 96370b324cSopenharmony_ci #endif 97370b324cSopenharmony_ci #endif 98370b324cSopenharmony_ci #ifndef OPENFILENAME_SIZE_VERSION_400W 99370b324cSopenharmony_ci #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName) 100370b324cSopenharmony_ci #endif 101370b324cSopenharmony_ci 102370b324cSopenharmony_ci #ifndef _UNICODE 103370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A 104370b324cSopenharmony_ci #endif 105370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W 106370b324cSopenharmony_ci#else 107370b324cSopenharmony_ci #ifndef _UNICODE 108370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEA OPENFILENAME_NT4A 109370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEA_size sizeof(my_compatib_OPENFILENAMEA) 110370b324cSopenharmony_ci #endif 111370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEW OPENFILENAME_NT4W 112370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEW_size sizeof(my_compatib_OPENFILENAMEW) 113370b324cSopenharmony_ci#endif 114370b324cSopenharmony_ci/* 115370b324cSopenharmony_ci#elif defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500) 116370b324cSopenharmony_ci// || !defined(WINVER) 117370b324cSopenharmony_ci #ifndef _UNICODE 118370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEA OPENFILENAMEA 119370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA) 120370b324cSopenharmony_ci #endif 121370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEW OPENFILENAMEW 122370b324cSopenharmony_ci #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW) 123370b324cSopenharmony_ci#else 124370b324cSopenharmony_ci 125370b324cSopenharmony_ci#endif 126370b324cSopenharmony_ci*/ 127370b324cSopenharmony_ci 128370b324cSopenharmony_ci#ifndef _UNICODE 129370b324cSopenharmony_ci#define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; } 130370b324cSopenharmony_ci#endif 131370b324cSopenharmony_ci 132370b324cSopenharmony_cibool CCommonDialogInfo::CommonDlg_BrowseForFile(LPCWSTR lpstrInitialDir, const UStringVector &filters) 133370b324cSopenharmony_ci{ 134370b324cSopenharmony_ci /* GetSaveFileName() and GetOpenFileName() could change current dir, 135370b324cSopenharmony_ci if OFN_NOCHANGEDIR is not used. 136370b324cSopenharmony_ci We can restore current dir manually, if it's required. 137370b324cSopenharmony_ci 22.02: we use OFN_NOCHANGEDIR. So we don't need to restore current dir manually. */ 138370b324cSopenharmony_ci // NFile::NDir::CCurrentDirRestorer curDirRestorer; 139370b324cSopenharmony_ci 140370b324cSopenharmony_ci#ifndef _UNICODE 141370b324cSopenharmony_ci if (!g_IsNT) 142370b324cSopenharmony_ci { 143370b324cSopenharmony_ci AString tempPath; 144370b324cSopenharmony_ci AStringVector f; 145370b324cSopenharmony_ci unsigned i; 146370b324cSopenharmony_ci for (i = 0; i < filters.Size(); i++) 147370b324cSopenharmony_ci f.Add(GetSystemString(filters[i])); 148370b324cSopenharmony_ci unsigned size = f.Size() + 1; 149370b324cSopenharmony_ci for (i = 0; i < f.Size(); i++) 150370b324cSopenharmony_ci size += f[i].Len(); 151370b324cSopenharmony_ci CObjArray<char> filterBuf(size); 152370b324cSopenharmony_ci // memset(filterBuf, 0, size * sizeof(char)); 153370b324cSopenharmony_ci { 154370b324cSopenharmony_ci char *dest = filterBuf; 155370b324cSopenharmony_ci for (i = 0; i < f.Size(); i++) 156370b324cSopenharmony_ci { 157370b324cSopenharmony_ci const AString &s = f[i]; 158370b324cSopenharmony_ci MyStringCopy(dest, s); 159370b324cSopenharmony_ci dest += s.Len() + 1; 160370b324cSopenharmony_ci } 161370b324cSopenharmony_ci *dest = 0; 162370b324cSopenharmony_ci } 163370b324cSopenharmony_ci my_compatib_OPENFILENAMEA p; 164370b324cSopenharmony_ci memset(&p, 0, sizeof(p)); 165370b324cSopenharmony_ci p.lStructSize = my_compatib_OPENFILENAMEA_size; 166370b324cSopenharmony_ci p.hwndOwner = hwndOwner; 167370b324cSopenharmony_ci if (size > 1) 168370b324cSopenharmony_ci { 169370b324cSopenharmony_ci p.lpstrFilter = filterBuf; 170370b324cSopenharmony_ci p.nFilterIndex = (DWORD)(FilterIndex + 1); 171370b324cSopenharmony_ci } 172370b324cSopenharmony_ci 173370b324cSopenharmony_ci CONV_U_To_A(p.lpstrInitialDir, lpstrInitialDir, initialDir_a) 174370b324cSopenharmony_ci CONV_U_To_A(p.lpstrTitle, lpstrTitle, title_a) 175370b324cSopenharmony_ci 176370b324cSopenharmony_ci const AString filePath_a = GetSystemString(FilePath); 177370b324cSopenharmony_ci const unsigned bufSize = MAX_PATH * 8 178370b324cSopenharmony_ci + filePath_a.Len() 179370b324cSopenharmony_ci + initialDir_a.Len(); 180370b324cSopenharmony_ci p.nMaxFile = bufSize; 181370b324cSopenharmony_ci p.lpstrFile = tempPath.GetBuf(bufSize); 182370b324cSopenharmony_ci MyStringCopy(p.lpstrFile, filePath_a); 183370b324cSopenharmony_ci p.Flags = 184370b324cSopenharmony_ci OFN_EXPLORER 185370b324cSopenharmony_ci | OFN_HIDEREADONLY 186370b324cSopenharmony_ci | OFN_NOCHANGEDIR; 187370b324cSopenharmony_ci const BOOL b = SaveMode ? 188370b324cSopenharmony_ci ::GetSaveFileNameA((LPOPENFILENAMEA)(void *)&p) : 189370b324cSopenharmony_ci ::GetOpenFileNameA((LPOPENFILENAMEA)(void *)&p); 190370b324cSopenharmony_ci if (!b) 191370b324cSopenharmony_ci return false; 192370b324cSopenharmony_ci { 193370b324cSopenharmony_ci tempPath.ReleaseBuf_CalcLen(bufSize); 194370b324cSopenharmony_ci FilePath = GetUnicodeString(tempPath); 195370b324cSopenharmony_ci FilterIndex = (int)p.nFilterIndex - 1; 196370b324cSopenharmony_ci return true; 197370b324cSopenharmony_ci } 198370b324cSopenharmony_ci } 199370b324cSopenharmony_ci else 200370b324cSopenharmony_ci#endif 201370b324cSopenharmony_ci { 202370b324cSopenharmony_ci UString tempPath; 203370b324cSopenharmony_ci unsigned size = filters.Size() + 1; 204370b324cSopenharmony_ci unsigned i; 205370b324cSopenharmony_ci for (i = 0; i < filters.Size(); i++) 206370b324cSopenharmony_ci size += filters[i].Len(); 207370b324cSopenharmony_ci CObjArray<wchar_t> filterBuf(size); 208370b324cSopenharmony_ci // memset(filterBuf, 0, size * sizeof(wchar_t)); 209370b324cSopenharmony_ci { 210370b324cSopenharmony_ci wchar_t *dest = filterBuf; 211370b324cSopenharmony_ci for (i = 0; i < filters.Size(); i++) 212370b324cSopenharmony_ci { 213370b324cSopenharmony_ci const UString &s = filters[i]; 214370b324cSopenharmony_ci MyStringCopy(dest, s); 215370b324cSopenharmony_ci dest += s.Len() + 1; 216370b324cSopenharmony_ci } 217370b324cSopenharmony_ci *dest = 0; 218370b324cSopenharmony_ci // if ((unsigned)(dest + 1 - filterBuf) != size) return false; 219370b324cSopenharmony_ci } 220370b324cSopenharmony_ci my_compatib_OPENFILENAMEW p; 221370b324cSopenharmony_ci memset(&p, 0, sizeof(p)); 222370b324cSopenharmony_ci p.lStructSize = my_compatib_OPENFILENAMEW_size; 223370b324cSopenharmony_ci p.hwndOwner = hwndOwner; 224370b324cSopenharmony_ci if (size > 1) 225370b324cSopenharmony_ci { 226370b324cSopenharmony_ci p.lpstrFilter = filterBuf; 227370b324cSopenharmony_ci p.nFilterIndex = (DWORD)(FilterIndex + 1); 228370b324cSopenharmony_ci } 229370b324cSopenharmony_ci unsigned bufSize = MAX_PATH * 8 + FilePath.Len(); 230370b324cSopenharmony_ci if (lpstrInitialDir) 231370b324cSopenharmony_ci { 232370b324cSopenharmony_ci p.lpstrInitialDir = lpstrInitialDir; 233370b324cSopenharmony_ci bufSize += MyStringLen(lpstrInitialDir); 234370b324cSopenharmony_ci } 235370b324cSopenharmony_ci p.nMaxFile = bufSize; 236370b324cSopenharmony_ci p.lpstrFile = tempPath.GetBuf(bufSize); 237370b324cSopenharmony_ci MyStringCopy(p.lpstrFile, FilePath); 238370b324cSopenharmony_ci p.lpstrTitle = lpstrTitle; 239370b324cSopenharmony_ci p.Flags = 240370b324cSopenharmony_ci OFN_EXPLORER 241370b324cSopenharmony_ci | OFN_HIDEREADONLY 242370b324cSopenharmony_ci | OFN_NOCHANGEDIR 243370b324cSopenharmony_ci // | OFN_FORCESHOWHIDDEN // Win10 shows hidden items even without this flag 244370b324cSopenharmony_ci // | OFN_PATHMUSTEXIST 245370b324cSopenharmony_ci #ifdef UNDER_CE 246370b324cSopenharmony_ci | (OpenFolderMode ? (MY_OFN_PROJECT | MY_OFN_SHOW_ALL) : 0) 247370b324cSopenharmony_ci #endif 248370b324cSopenharmony_ci ; 249370b324cSopenharmony_ci const BOOL b = SaveMode ? 250370b324cSopenharmony_ci ::GetSaveFileNameW((LPOPENFILENAMEW)(void *)&p) : 251370b324cSopenharmony_ci ::GetOpenFileNameW((LPOPENFILENAMEW)(void *)&p); 252370b324cSopenharmony_ci /* DOCs: lpstrFile : 253370b324cSopenharmony_ci if the buffer is too small, then: 254370b324cSopenharmony_ci - the function returns FALSE 255370b324cSopenharmony_ci - the CommDlgExtendedError() returns FNERR_BUFFERTOOSMALL 256370b324cSopenharmony_ci - the first two bytes of the lpstrFile buffer contain the 257370b324cSopenharmony_ci required size, in bytes or characters. */ 258370b324cSopenharmony_ci if (!b) 259370b324cSopenharmony_ci return false; 260370b324cSopenharmony_ci { 261370b324cSopenharmony_ci tempPath.ReleaseBuf_CalcLen(bufSize); 262370b324cSopenharmony_ci FilePath = tempPath; 263370b324cSopenharmony_ci FilterIndex = (int)p.nFilterIndex - 1; 264370b324cSopenharmony_ci return true; 265370b324cSopenharmony_ci } 266370b324cSopenharmony_ci } 267370b324cSopenharmony_ci} 268370b324cSopenharmony_ci 269370b324cSopenharmony_ci} 270