OSDN Git Service

Fix crash when registry is set to an unexpected value
authorTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sun, 8 Aug 2021 05:32:00 +0000 (14:32 +0900)
committerTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sun, 8 Aug 2021 05:32:00 +0000 (14:32 +0900)
15 files changed:
Src/7zCommon.cpp
Src/Common/OptionsMgr.cpp
Src/Common/OptionsMgr.h
Src/DirScan.cpp
Src/DirView.cpp
Src/ImgMergeFrm.cpp
Src/OptionsDef.h
Src/OptionsDiffOptions.cpp
Src/OptionsFont.cpp
Src/OptionsInit.cpp
Src/PropArchive.cpp
Testing/GoogleTest/GUITests/GUITestUtils.cpp
Testing/GoogleTest/GUITests/GUITestUtils.h
Testing/GoogleTest/GUITests/GUITests.vcxproj
Testing/GoogleTest/GUITests/GUITests.vcxproj.filters

index a9eb99a..b5923c2 100644 (file)
@@ -145,7 +145,7 @@ bool IsArchiveFile(const String& pszFile)
  */\r
 Merge7z::Format *ArchiveGuessFormat(const String& path)\r
 {\r
-       if (GetOptionsMgr()->GetInt(OPT_ARCHIVE_ENABLE) == 0)\r
+       if (!GetOptionsMgr()->GetBool(OPT_ARCHIVE_ENABLE))\r
                return nullptr;\r
        if (paths::IsDirectory(path))\r
                return nullptr;\r
@@ -271,7 +271,7 @@ interface Merge7z *Merge7z::Proxy::operator->()
        {\r
                // Merge7z has not yet been loaded\r
 \r
-               if (GetOptionsMgr()->GetInt(OPT_ARCHIVE_ENABLE) == 0)\r
+               if (!GetOptionsMgr()->GetBool(OPT_ARCHIVE_ENABLE))\r
                        throw new CResourceException();\r
                if (DWORD ver = VersionOf7z())\r
                {\r
index af033f9..67f1899 100644 (file)
@@ -377,6 +377,18 @@ int COptionsMgr::AddOption(const String& name, const varprop::VariantValue& defa
        return retVal;
 }
 
+int COptionsMgr::InitOption(const String& name, int defaultValue, int minValue, int maxValue, bool serializable)
+{
+       int retVal = InitOption(name, defaultValue, serializable);
+       if (retVal == COption::OPT_OK)
+       {
+               int ival = GetInt(name);
+               if (ival < minValue || ival > maxValue)
+                       Reset(name);
+       }
+       return retVal;
+}
+
 /**
  * @brief Get option value from list by name.
  * @param [in] name Name of the option to get.
index 1d04713..1618711 100644 (file)
@@ -134,6 +134,7 @@ public:
        virtual int InitOption(const String& name, const String& defaultValue) = 0;
        virtual int InitOption(const String& name, const TCHAR *defaultValue) = 0;
        virtual int InitOption(const String& name, int defaultValue, bool serializable = true) = 0;
+       virtual int InitOption(const String& name, int defaultValue, int minValue, int maxValue, bool serializable = true);
        virtual int InitOption(const String& name, bool defaultValue) = 0;
 
        virtual int SaveOption(const String& name) = 0;
index 4f45623..0a41852 100644 (file)
@@ -480,11 +480,8 @@ int DirScan_CompareItems(DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos)
        {
                nworkers = GetOptionsMgr()->GetInt(OPT_CMP_COMPARE_THREADS);
                if (nworkers <= 0)
-               {
                        nworkers += Environment::processorCount();
-                       if (nworkers <= 0)
-                               nworkers = 1;
-               }
+               nworkers = std::clamp(nworkers, 1, static_cast<int>(Environment::processorCount()));
        }
 
        ThreadPool threadPool(nworkers, nworkers);
index 01fa6b4..ae3026e 100644 (file)
@@ -1104,7 +1104,7 @@ void CDirView::OnColumnClick(NMHDR *pNMHDR, LRESULT *pResult)
 void CDirView::SortColumnsAppropriately()
 {
        int sortCol = GetOptionsMgr()->GetInt((GetDocument()->m_nDirs < 3) ? OPT_DIRVIEW_SORT_COLUMN : OPT_DIRVIEW_SORT_COLUMN3);
-       if (sortCol == -1 || sortCol >= m_pColItems->GetColCount())
+       if (sortCol < 0 || sortCol >= m_pColItems->GetColCount())
                return;
 
        bool bSortAscending = GetOptionsMgr()->GetBool(OPT_DIRVIEW_SORT_ASCENDING);
index bf7149d..6219510 100644 (file)
@@ -602,7 +602,7 @@ BOOL CImgMergeFrame::DestroyWindow()
 void CImgMergeFrame::LoadOptions()
 {
        m_pImgMergeWindow->SetShowDifferences(GetOptionsMgr()->GetBool(OPT_CMP_IMG_SHOWDIFFERENCES));
-       m_pImgMergeWindow->SetOverlayMode(static_cast<IImgMergeWindow::OVERLAY_MODE>(GetOptionsMgr()->GetInt(OPT_CMP_IMG_OVERLAYMOVE)));
+       m_pImgMergeWindow->SetOverlayMode(static_cast<IImgMergeWindow::OVERLAY_MODE>(GetOptionsMgr()->GetInt(OPT_CMP_IMG_OVERLAYMODE)));
        m_pImgMergeWindow->SetOverlayAlpha(GetOptionsMgr()->GetInt(OPT_CMP_IMG_OVERLAYALPHA) / 100.0);
        m_pImgMergeWindow->SetDraggingMode(static_cast<IImgMergeWindow::DRAGGING_MODE>(GetOptionsMgr()->GetInt(OPT_CMP_IMG_DRAGGING_MODE)));
        m_pImgMergeWindow->SetZoom(GetOptionsMgr()->GetInt(OPT_CMP_IMG_ZOOM) / 1000.0);
@@ -620,7 +620,7 @@ void CImgMergeFrame::LoadOptions()
 void CImgMergeFrame::SaveOptions()
 {
        GetOptionsMgr()->SaveOption(OPT_CMP_IMG_SHOWDIFFERENCES, m_pImgMergeWindow->GetShowDifferences());
-       GetOptionsMgr()->SaveOption(OPT_CMP_IMG_OVERLAYMOVE, m_pImgMergeWindow->GetOverlayMode());
+       GetOptionsMgr()->SaveOption(OPT_CMP_IMG_OVERLAYMODE, m_pImgMergeWindow->GetOverlayMode());
        GetOptionsMgr()->SaveOption(OPT_CMP_IMG_OVERLAYALPHA, static_cast<int>(m_pImgMergeWindow->GetOverlayAlpha() * 100));
        GetOptionsMgr()->SaveOption(OPT_CMP_IMG_DRAGGING_MODE, static_cast<int>(m_pImgMergeWindow->GetDraggingMode()));
        GetOptionsMgr()->SaveOption(OPT_CMP_IMG_ZOOM, static_cast<int>(m_pImgMergeWindow->GetZoom() * 1000));
index b8dde2b..3353fc8 100644 (file)
@@ -218,7 +218,7 @@ extern const String OPT_CMP_COMPLETELY_BLANK_OUT_IGNORED_CHANGES OP("Settings/Co
 // Image Compare options
 extern const String OPT_CMP_IMG_FILEPATTERNS OP("Settings/ImageFilePatterns");
 extern const String OPT_CMP_IMG_SHOWDIFFERENCES OP("Settings/ImageShowDifferences");
-extern const String OPT_CMP_IMG_OVERLAYMOVE OP("Settings/ImageOverlayMode");
+extern const String OPT_CMP_IMG_OVERLAYMODE OP("Settings/ImageOverlayMode");
 extern const String OPT_CMP_IMG_OVERLAYALPHA OP("Settings/ImageOverlayAlpha");
 extern const String OPT_CMP_IMG_DRAGGING_MODE OP("Settings/ImageDraggingMode");
 extern const String OPT_CMP_IMG_ZOOM OP("Settings/ImageZoom");
index 522f807..0500625 100644 (file)
@@ -16,12 +16,12 @@ namespace Options { namespace DiffOptions {
  */
 void SetDefaults(COptionsMgr *pOptionsMgr)
 {
-       pOptionsMgr->InitOption(OPT_CMP_IGNORE_WHITESPACE, (int)0);
+       pOptionsMgr->InitOption(OPT_CMP_IGNORE_WHITESPACE, (int)0, 0, 2);
        pOptionsMgr->InitOption(OPT_CMP_IGNORE_BLANKLINES, false);
        pOptionsMgr->InitOption(OPT_CMP_FILTER_COMMENTLINES, false);
        pOptionsMgr->InitOption(OPT_CMP_IGNORE_CASE, false);
        pOptionsMgr->InitOption(OPT_CMP_IGNORE_EOL, false);
-       pOptionsMgr->InitOption(OPT_CMP_DIFF_ALGORITHM, (int)0);
+       pOptionsMgr->InitOption(OPT_CMP_DIFF_ALGORITHM, (int)0, 0, 3);
        pOptionsMgr->InitOption(OPT_CMP_INDENT_HEURISTIC, true);
        pOptionsMgr->InitOption(OPT_CMP_COMPLETELY_BLANK_OUT_IGNORED_CHANGES, false);
 }
index c2c93b7..15f1b63 100644 (file)
@@ -96,7 +96,7 @@ void SetDefaults(COptionsMgr *pOptionsMgr)
                String name = (i == 0 ? OPT_FONT_FILECMP : OPT_FONT_DIRCMP);
 
                pOptionsMgr->InitOption(name + OPT_FONT_USECUSTOM, false);
-               pOptionsMgr->InitOption(name + OPT_FONT_POINTSIZE, ::MulDiv(abs(thisFont.lfHeight), 72, logPixelsY));
+               pOptionsMgr->InitOption(name + OPT_FONT_POINTSIZE, ::MulDiv(abs(thisFont.lfHeight), 72, logPixelsY), 1, 72);
                pOptionsMgr->InitOption(name + OPT_FONT_HEIGHT, thisFont.lfHeight);
                pOptionsMgr->InitOption(name + OPT_FONT_ESCAPEMENT, thisFont.lfEscapement);
                pOptionsMgr->InitOption(name + OPT_FONT_ORIENTATION, thisFont.lfOrientation);
index 18d31cd..e809973 100644 (file)
@@ -65,7 +65,7 @@ void Init(COptionsMgr *pOptions)
        pOptions->InitOption(OPT_SHOW_TOOLBAR, true);
        pOptions->InitOption(OPT_SHOW_STATUSBAR, true);
        pOptions->InitOption(OPT_SHOW_TABBAR, true);
-       pOptions->InitOption(OPT_TOOLBAR_SIZE, 0);
+       pOptions->InitOption(OPT_TOOLBAR_SIZE, 0, 0, 2);
        pOptions->InitOption(OPT_RESIZE_PANES, false);
 
        pOptions->InitOption(OPT_SYNTAX_HIGHLIGHT, true);
@@ -76,12 +76,12 @@ void Init(COptionsMgr *pOptions)
        pOptions->InitOption(OPT_SCROLL_TO_FIRST, false);
        pOptions->InitOption(OPT_SCROLL_TO_FIRST_INLINE_DIFF, false);
        pOptions->InitOption(OPT_VERIFY_OPEN_PATHS, true);
-       pOptions->InitOption(OPT_AUTO_COMPLETE_SOURCE, (int)1);
+       pOptions->InitOption(OPT_AUTO_COMPLETE_SOURCE, (int)1, 0, 2);
        pOptions->InitOption(OPT_VIEW_FILEMARGIN, false);
        pOptions->InitOption(OPT_DIFF_CONTEXT, (int)-1);
        pOptions->InitOption(OPT_INVERT_DIFF_CONTEXT, false);
        pOptions->InitOption(OPT_SPLIT_HORIZONTALLY, false);
-       pOptions->InitOption(OPT_RENDERING_MODE, -1);
+       pOptions->InitOption(OPT_RENDERING_MODE, -1, 0, 6);
        pOptions->InitOption(OPT_FILE_SIZE_THRESHOLD, 64*1024*1024);
 
        pOptions->InitOption(OPT_WORDDIFF_HIGHLIGHT, true);
@@ -89,13 +89,13 @@ void Init(COptionsMgr *pOptions)
 
        pOptions->InitOption(OPT_BACKUP_FOLDERCMP, false);
        pOptions->InitOption(OPT_BACKUP_FILECMP, true);
-       pOptions->InitOption(OPT_BACKUP_LOCATION, (int)0);
+       pOptions->InitOption(OPT_BACKUP_LOCATION, (int)0, 0, 1);
        pOptions->InitOption(OPT_BACKUP_GLOBALFOLDER, _T(""));
        pOptions->InitOption(OPT_BACKUP_ADD_BAK, true);
        pOptions->InitOption(OPT_BACKUP_ADD_TIME, false);
 
-       pOptions->InitOption(OPT_DIRVIEW_SORT_COLUMN, (int)-1);
-       pOptions->InitOption(OPT_DIRVIEW_SORT_COLUMN3, (int)-1);
+       pOptions->InitOption(OPT_DIRVIEW_SORT_COLUMN, (int)-1, -1, 128);
+       pOptions->InitOption(OPT_DIRVIEW_SORT_COLUMN3, (int)-1, -1, 128);
        pOptions->InitOption(OPT_DIRVIEW_SORT_ASCENDING, true);
        pOptions->InitOption(OPT_SHOW_SELECT_FILES_AT_STARTUP, false);
        pOptions->InitOption(OPT_DIRVIEW_EXPAND_SUBDIRS, false);
@@ -104,38 +104,38 @@ void Init(COptionsMgr *pOptions)
        pOptions->InitOption(OPT_DIRVIEW3_COLUMN_ORDERS, _T(""));
        pOptions->InitOption(OPT_DIRVIEW3_COLUMN_WIDTHS, _T(""));
 
-       pOptions->InitOption(OPT_REPORTFILES_REPORTTYPE, 0);
+       pOptions->InitOption(OPT_REPORTFILES_REPORTTYPE, 0, 0, 3);
        pOptions->InitOption(OPT_REPORTFILES_COPYTOCLIPBOARD, false);
        pOptions->InitOption(OPT_REPORTFILES_INCLUDEFILECMPREPORT, false);
 
        pOptions->InitOption(OPT_AUTOMATIC_RESCAN, false);
        pOptions->InitOption(OPT_ALLOW_MIXED_EOL, false);
        pOptions->InitOption(OPT_COPY_FULL_LINE, false);
-       pOptions->InitOption(OPT_TAB_SIZE, (int)4);
-       pOptions->InitOption(OPT_TAB_TYPE, (int)0);     // 0 means tabs inserted
+       pOptions->InitOption(OPT_TAB_SIZE, (int)4, 0, 64);
+       pOptions->InitOption(OPT_TAB_TYPE, (int)0, 0, 1);       // 0 means tabs inserted
 
        pOptions->InitOption(OPT_EXT_EDITOR_CMD, _T("%windir%\\NOTEPAD.EXE"));
        pOptions->InitOption(OPT_USE_RECYCLE_BIN, true);
-       pOptions->InitOption(OPT_SINGLE_INSTANCE, 0);
+       pOptions->InitOption(OPT_SINGLE_INSTANCE, 0, 0, 2);
        pOptions->InitOption(OPT_MERGE_MODE, false);
        // OPT_WORDDIFF_HIGHLIGHT is initialized above
        pOptions->InitOption(OPT_BREAK_ON_WORDS, false);
-       pOptions->InitOption(OPT_BREAK_TYPE, 1);
+       pOptions->InitOption(OPT_BREAK_TYPE, 1, 0, 1);
 
-       pOptions->InitOption(OPT_CLOSE_WITH_ESC, 1);
+       pOptions->InitOption(OPT_CLOSE_WITH_ESC, 1, 0, 2);
        pOptions->InitOption(OPT_CLOSE_WITH_OK, false);
        pOptions->InitOption(OPT_IGNORE_SMALL_FILETIME, false);
        pOptions->InitOption(OPT_ASK_MULTIWINDOW_CLOSE, false);
        pOptions->InitOption(OPT_PRESERVE_FILETIMES, false);
        pOptions->InitOption(OPT_TREE_MODE, true);
 
-       pOptions->InitOption(OPT_CMP_METHOD, (int)CMP_CONTENT);
+       pOptions->InitOption(OPT_CMP_METHOD, (int)CMP_CONTENT, 0, CMP_SIZE);
        pOptions->InitOption(OPT_CMP_MOVED_BLOCKS, false);
        pOptions->InitOption(OPT_CMP_MATCH_SIMILAR_LINES, false);
        pOptions->InitOption(OPT_CMP_STOP_AFTER_FIRST, false);
        pOptions->InitOption(OPT_CMP_QUICK_LIMIT, 4 * 1024 * 1024); // 4 Megs
        pOptions->InitOption(OPT_CMP_BINARY_LIMIT, 64 * 1024 * 1024); // 64 Megs
-       pOptions->InitOption(OPT_CMP_COMPARE_THREADS, -1);
+       pOptions->InitOption(OPT_CMP_COMPARE_THREADS, -1, -128, 128);
        pOptions->InitOption(OPT_CMP_WALK_UNIQUE_DIRS, true);
        pOptions->InitOption(OPT_CMP_IGNORE_REPARSE_POINTS, false);
        pOptions->InitOption(OPT_CMP_IGNORE_CODEPAGE, false);
@@ -153,18 +153,18 @@ void Init(COptionsMgr *pOptions)
 
        pOptions->InitOption(OPT_CMP_IMG_FILEPATTERNS, _T("*.bmp;*.cut;*.dds;*.exr;*.g3;*.gif;*.hdr;*.ico;*.iff;*.lbm;*.j2k;*.j2c;*.jng;*.jp2;*.jpg;*.jif;*.jpeg;*.jpe;*.jxr;*.wdp;*.hdp;*.koa;*.mng;*.pcd;*.pcx;*.pfm;*.pct;*.pict;*.pic;*.png;*.pbm;*.pgm;*.ppm;*.psd;*.ras;*.sgi;*.rgb;*.rgba;*.bw;*.tga;*.targa;*.tif;*.tiff;*.wap;*.wbmp;*.wbm;*.webp;*.xbm;*.xpm"));
        pOptions->InitOption(OPT_CMP_IMG_SHOWDIFFERENCES, true);
-       pOptions->InitOption(OPT_CMP_IMG_OVERLAYMOVE, 0);
-       pOptions->InitOption(OPT_CMP_IMG_OVERLAYALPHA, 30);
-       pOptions->InitOption(OPT_CMP_IMG_DRAGGING_MODE, 1);
-       pOptions->InitOption(OPT_CMP_IMG_ZOOM, 1000);
+       pOptions->InitOption(OPT_CMP_IMG_OVERLAYMODE, 0, 0, 3);
+       pOptions->InitOption(OPT_CMP_IMG_OVERLAYALPHA, 30, 0, 100);
+       pOptions->InitOption(OPT_CMP_IMG_DRAGGING_MODE, 1, 0, 5);
+       pOptions->InitOption(OPT_CMP_IMG_ZOOM, 1000, 1, 8000);
        pOptions->InitOption(OPT_CMP_IMG_USEBACKCOLOR, true);
        pOptions->InitOption(OPT_CMP_IMG_BACKCOLOR, 0xFFFFFF);
-       pOptions->InitOption(OPT_CMP_IMG_DIFFBLOCKSIZE, 8);
-       pOptions->InitOption(OPT_CMP_IMG_DIFFCOLORALPHA, 70);
-       pOptions->InitOption(OPT_CMP_IMG_THRESHOLD, 0);
-       pOptions->InitOption(OPT_CMP_IMG_INSERTIONDELETIONDETECTION_MODE, 0);
-       pOptions->InitOption(OPT_CMP_IMG_VECTOR_IMAGE_ZOOM_RATIO, 1000);
-       pOptions->InitOption(OPT_CMP_IMG_OCR_RESULT_TYPE, 0);
+       pOptions->InitOption(OPT_CMP_IMG_DIFFBLOCKSIZE, 8, 0, 64);
+       pOptions->InitOption(OPT_CMP_IMG_DIFFCOLORALPHA, 70, 0, 100);
+       pOptions->InitOption(OPT_CMP_IMG_THRESHOLD, 0, 0, 442);
+       pOptions->InitOption(OPT_CMP_IMG_INSERTIONDELETIONDETECTION_MODE, 0, 0, 2);
+       pOptions->InitOption(OPT_CMP_IMG_VECTOR_IMAGE_ZOOM_RATIO, 1000, 1, 8000);
+       pOptions->InitOption(OPT_CMP_IMG_OCR_RESULT_TYPE, 0, 0, 2);
 
        pOptions->InitOption(OPT_PROJECTS_PATH, _T(""));
        pOptions->InitOption(OPT_USE_SYSTEM_TEMP_PATH, true);
@@ -194,7 +194,7 @@ void Init(COptionsMgr *pOptions)
        else
                pOptions->InitOption(OPT_CP_DETECT, (int)(50001 << 16) | 1);
 
-       pOptions->InitOption(OPT_ARCHIVE_ENABLE, 1); // Enable by default
+       pOptions->InitOption(OPT_ARCHIVE_ENABLE, true); // Enable by default
        pOptions->InitOption(OPT_ARCHIVE_PROBETYPE, false);
        pOptions->InitOption(OPT_ARCHIVE_FILTER_INDEX, 1);
 
@@ -205,20 +205,20 @@ void Init(COptionsMgr *pOptions)
        pOptions->InitOption(OPT_PLUGINS_UNPACK_DONT_CHECK_EXTENSION, true);
        pOptions->InitOption(OPT_PLUGINS_OPEN_IN_SAME_FRAME_TYPE, false);
 
-       pOptions->InitOption(OPT_PATCHCREATOR_PATCH_STYLE, 0);
+       pOptions->InitOption(OPT_PATCHCREATOR_PATCH_STYLE, 0, 0, 3);
        pOptions->InitOption(OPT_PATCHCREATOR_CONTEXT_LINES, 0);
        pOptions->InitOption(OPT_PATCHCREATOR_CASE_SENSITIVE, true);
        pOptions->InitOption(OPT_PATCHCREATOR_EOL_SENSITIVE, true);
        pOptions->InitOption(OPT_PATCHCREATOR_IGNORE_BLANK_LINES, false);
-       pOptions->InitOption(OPT_PATCHCREATOR_WHITESPACE, WHITESPACE_COMPARE_ALL);
+       pOptions->InitOption(OPT_PATCHCREATOR_WHITESPACE, WHITESPACE_COMPARE_ALL, WHITESPACE_COMPARE_ALL, WHITESPACE_IGNORE_ALL);
        pOptions->InitOption(OPT_PATCHCREATOR_OPEN_TO_EDITOR, false);
        pOptions->InitOption(OPT_PATCHCREATOR_INCLUDE_CMD_LINE, false);
 
        pOptions->InitOption(OPT_TABBAR_AUTO_MAXWIDTH, true);
        pOptions->InitOption(OPT_ACTIVE_FRAME_MAX, true);
-       pOptions->InitOption(OPT_ACTIVE_PANE, 0);
+       pOptions->InitOption(OPT_ACTIVE_PANE, 0, 0, 2);
 
-       pOptions->InitOption(OPT_MRU_MAX, 9);
+       pOptions->InitOption(OPT_MRU_MAX, 9, 0, 128);
 
        pOptions->InitOption(OPT_COLOR_SCHEME, _T("Default"));
 
index 9f7145a..2269ee9 100644 (file)
@@ -44,7 +44,7 @@ END_MESSAGE_MAP()
  */
 void PropArchive::ReadOptions()
 {
-       int enable = GetOptionsMgr()->GetInt(OPT_ARCHIVE_ENABLE);
+       int enable = GetOptionsMgr()->GetBool(OPT_ARCHIVE_ENABLE);
        m_bEnableSupport = enable > 0;
        m_bProbeType = GetOptionsMgr()->GetBool(OPT_ARCHIVE_PROBETYPE);
 }
@@ -54,7 +54,7 @@ void PropArchive::ReadOptions()
  */
 void PropArchive::WriteOptions()
 {
-       GetOptionsMgr()->SaveOption(OPT_ARCHIVE_ENABLE, (int)(m_bEnableSupport ? 1 : 0));
+       GetOptionsMgr()->SaveOption(OPT_ARCHIVE_ENABLE, m_bEnableSupport);
        GetOptionsMgr()->SaveOption(OPT_ARCHIVE_PROBETYPE, m_bProbeType);
 }
 
index 7f3c416..d0178d8 100644 (file)
@@ -333,5 +333,118 @@ const char* languageIdToName(int id)
        return "";\r
 }\r
 \r
+static std::pair<std::wstring, std::wstring> splitOptionName(const std::wstring& name)\r
+{\r
+       std::wstring key = L"Software\\Thingamahoochie\\WinMerge";\r
+       key += L"\\" + name.substr(0, name.find('/'));\r
+       std::wstring name2 = name.substr(name.find('/') + 1);\r
+       return { key, name2 };\r
+}\r
+\r
+std::optional<bool> regReadBool(const std::wstring& name)\r
+{\r
+       std::optional<bool> value;\r
+       HKEY hKey = nullptr;\r
+       auto [keyname, valuename] = splitOptionName(name);\r
+       if (ERROR_SUCCESS == RegOpenKeyW(HKEY_CURRENT_USER, keyname.c_str(), &hKey))\r
+       {\r
+               DWORD type = REG_DWORD, data = 0, size = 4;\r
+               if (ERROR_SUCCESS == RegQueryValueExW(hKey, valuename.c_str(), nullptr, &type, reinterpret_cast<BYTE*>(&data), &size))\r
+                       value = data != 0;\r
+               RegCloseKey(hKey);\r
+       }\r
+       return value;\r
+}\r
+\r
+std::optional<int> regReadInt(const std::wstring& name)\r
+{\r
+       std::optional<int> value;\r
+       HKEY hKey = nullptr;\r
+       auto [keyname, valuename] = splitOptionName(name);\r
+       if (ERROR_SUCCESS == RegOpenKeyW(HKEY_CURRENT_USER, keyname.c_str(), &hKey))\r
+       {\r
+               DWORD type = REG_DWORD, data = 0, size = 4;\r
+               if (ERROR_SUCCESS == RegQueryValueExW(hKey, valuename.c_str(), nullptr, &type, reinterpret_cast<BYTE*>(&data), &size))\r
+                       value = static_cast<int>(data);\r
+               RegCloseKey(hKey);\r
+       }\r
+       return value;\r
+}\r
+\r
+std::optional<std::wstring> regReadString(const std::wstring& name)\r
+{\r
+       std::optional<std::wstring> value;\r
+       HKEY hKey = nullptr;\r
+       auto [keyname, valuename] = splitOptionName(name);\r
+       if (ERROR_SUCCESS == RegOpenKeyW(HKEY_CURRENT_USER, keyname.c_str(), &hKey))\r
+       {\r
+               std::vector<wchar_t> data(65536);\r
+               DWORD type = REG_SZ, size = static_cast<DWORD>(data.size());\r
+               if (ERROR_SUCCESS == RegQueryValueExW(hKey, valuename.c_str(), nullptr, &type, reinterpret_cast<BYTE*>(data.data()), &size))\r
+                       value = data.data();\r
+               RegCloseKey(hKey);\r
+       }\r
+       return value;\r
+}\r
+\r
+bool regWrite(const std::wstring& name, bool value)\r
+{\r
+       bool result = false;\r
+       HKEY hKey = nullptr;\r
+       auto [keyname, valuename] = splitOptionName(name);\r
+       if (ERROR_SUCCESS == RegCreateKeyW(HKEY_CURRENT_USER, keyname.c_str(), &hKey))\r
+       {\r
+               DWORD data = value;\r
+               if (ERROR_SUCCESS == RegSetValueExW(hKey, valuename.c_str(), 0, REG_DWORD, reinterpret_cast<BYTE*>(&data), sizeof(DWORD)))\r
+                       result = true;\r
+               RegCloseKey(hKey);\r
+       }\r
+       return result;\r
+}\r
+\r
+bool regWrite(const std::wstring& name, int value)\r
+{\r
+       bool result = false;\r
+       HKEY hKey = nullptr;\r
+       auto [keyname, valuename] = splitOptionName(name);\r
+       if (ERROR_SUCCESS == RegCreateKeyW(HKEY_CURRENT_USER, keyname.c_str(), &hKey))\r
+       {\r
+               DWORD data = value;\r
+               if (ERROR_SUCCESS == RegSetValueExW(hKey, valuename.c_str(), 0, REG_DWORD, reinterpret_cast<BYTE*>(&data), sizeof(DWORD)))\r
+                       result = true;\r
+               RegCloseKey(hKey);\r
+       }\r
+       return result;\r
+}\r
+\r
+bool regWrite(const std::wstring& name, const std::wstring& value)\r
+{\r
+       bool result = false;\r
+       HKEY hKey = nullptr;\r
+       auto [keyname, valuename] = splitOptionName(name);\r
+       if (ERROR_SUCCESS == RegCreateKeyW(HKEY_CURRENT_USER, keyname.c_str(), &hKey))\r
+       {\r
+               if (ERROR_SUCCESS == RegSetValueExW(hKey, valuename.c_str(), 0, REG_SZ, reinterpret_cast<const BYTE*>(value.c_str()),\r
+                       static_cast<DWORD>((value.length() + 1) * sizeof(wchar_t))))\r
+                       result = true;\r
+               RegCloseKey(hKey);\r
+       }\r
+       return result;\r
+}\r
+\r
+bool regDelete(const std::wstring& name)\r
+{\r
+       bool result = false;\r
+       HKEY hKey = nullptr;\r
+       auto [keyname, valuename] = splitOptionName(name);\r
+       if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CURRENT_USER, keyname.c_str(), 0, KEY_ALL_ACCESS, &hKey))\r
+       {\r
+               if (ERROR_SUCCESS == RegDeleteValueW(hKey, valuename.c_str()))\r
+                       result = true;\r
+               RegCloseKey(hKey);\r
+       }\r
+       return result;\r
+}\r
+\r
 }\r
 \r
index f769c34..f266371 100644 (file)
@@ -1,6 +1,7 @@
 #include <Windows.h>\r
 #include <filesystem>\r
 #include <set>\r
+#include <optional>\r
 \r
 namespace GUITestUtils\r
 {\r
@@ -26,6 +27,13 @@ namespace GUITestUtils
        HWND execInstaller(const std::string& args = "");\r
        const std::set<int> languages();\r
        const char * languageIdToName(int id);\r
+       std::optional<bool> regReadBool(const std::wstring& name);\r
+       std::optional<int> regReadInt(const std::wstring& name);\r
+       std::optional<std::wstring> regReadString(const std::wstring& name);\r
+       bool regWrite(const std::wstring& name, bool value);\r
+       bool regWrite(const std::wstring& name, int value);\r
+       bool regWrite(const std::wstring& name, const std::wstring& value);\r
+       bool regDelete(const std::wstring& name);\r
 }\r
 \r
 #define selectMenuAndSaveWindowImage(id) selectMenuAndSaveWindowImageHelper(id, #id)\r
index ee1f652..c220198 100644 (file)
     </Manifest>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="ConfigTest.cpp" />
     <ClCompile Include="DirFrameTest.cpp" />
     <ClCompile Include="FileTest.cpp" />
     <ClCompile Include="GUITestUtils.cpp" />
index 33a4bee..ba87416 100644 (file)
@@ -39,6 +39,9 @@
     <ClCompile Include="FileTest.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="ConfigTest.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="GUITestUtils.h">