1 /* 2 * PROJECT: ReactOS Applications Manager 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Functions to load / save settings from reg. 5 * COPYRIGHT: Copyright 2020 He Yang (1160386205@qq.com) 6 */ 7 8 #include "rapps.h" 9 #include "settings.h" 10 11 #define SETTINGSSUBKEY L"Software\\ReactOS\\" RAPPS_NAME 12 13 class SettingsField 14 { 15 public: 16 virtual ~SettingsField() 17 { 18 ; 19 } 20 virtual BOOL 21 Save(CRegKey &key) = 0; 22 virtual BOOL 23 Load(CRegKey &key) = 0; 24 }; 25 26 class SettingsFieldBool : public SettingsField 27 { 28 public: 29 SettingsFieldBool(BOOL *pValue, LPCWSTR szRegName) : m_pValueStore(pValue), m_RegName(szRegName) 30 { 31 } 32 33 virtual BOOL 34 Save(CRegKey &key) override 35 { 36 return key.SetDWORDValue(m_RegName, (DWORD)(*m_pValueStore)) == ERROR_SUCCESS; 37 } 38 virtual BOOL 39 Load(CRegKey &key) override 40 { 41 DWORD dwField; 42 LONG lResult = key.QueryDWORDValue(m_RegName, dwField); 43 if (lResult != ERROR_SUCCESS) 44 { 45 return FALSE; 46 } 47 *m_pValueStore = (BOOL)dwField; 48 return TRUE; 49 } 50 51 private: 52 BOOL *m_pValueStore; // where to read/store the value 53 LPCWSTR m_RegName; // key name in registery 54 }; 55 56 class SettingsFieldInt : public SettingsField 57 { 58 public: 59 SettingsFieldInt(INT *pValue, LPCWSTR szRegName) : m_pValueStore(pValue), m_RegName(szRegName) 60 { 61 } 62 63 virtual BOOL 64 Save(CRegKey &key) override 65 { 66 return key.SetDWORDValue(m_RegName, (DWORD)(*m_pValueStore)) == ERROR_SUCCESS; 67 } 68 virtual BOOL 69 Load(CRegKey &key) override 70 { 71 DWORD dwField; 72 LONG lResult = key.QueryDWORDValue(m_RegName, dwField); 73 if (lResult != ERROR_SUCCESS) 74 { 75 return FALSE; 76 } 77 *m_pValueStore = (INT)dwField; 78 return TRUE; 79 } 80 81 private: 82 INT *m_pValueStore; // where to read/store the value 83 LPCWSTR m_RegName; // key name in registery 84 }; 85 86 class SettingsFieldString : public SettingsField 87 { 88 public: 89 SettingsFieldString(WCHAR *pString, ULONG cchLen, LPCWSTR szRegName) 90 : m_pStringStore(pString), m_StringLen(cchLen), m_RegName(szRegName) 91 { 92 } 93 94 virtual BOOL 95 Save(CRegKey &key) override 96 { 97 return key.SetStringValue(m_RegName, m_pStringStore) == ERROR_SUCCESS; 98 } 99 virtual BOOL 100 Load(CRegKey &key) override 101 { 102 ULONG nChar = m_StringLen - 1; // make sure the terminating L'\0' 103 LONG lResult = key.QueryStringValue(m_RegName, m_pStringStore, &nChar); 104 return lResult == ERROR_SUCCESS; 105 } 106 107 private: 108 WCHAR *m_pStringStore; // where to read/store the value 109 ULONG m_StringLen; // string length, in chars 110 LPCWSTR m_RegName; // key name in registery 111 }; 112 113 static void 114 AddInfoFields(ATL::CAtlList<SettingsField *> &infoFields, SETTINGS_INFO &settings) 115 { 116 infoFields.AddTail(new SettingsFieldBool(&(settings.bSaveWndPos), L"bSaveWndPos")); 117 infoFields.AddTail(new SettingsFieldBool(&(settings.bUpdateAtStart), L"bUpdateAtStart")); 118 infoFields.AddTail(new SettingsFieldBool(&(settings.bLogEnabled), L"bLogEnabled")); 119 infoFields.AddTail(new SettingsFieldString(settings.szDownloadDir, MAX_PATH, L"szDownloadDir")); 120 infoFields.AddTail(new SettingsFieldBool(&(settings.bDelInstaller), L"bDelInstaller")); 121 infoFields.AddTail(new SettingsFieldBool(&(settings.Maximized), L"WindowPosMaximized")); 122 infoFields.AddTail(new SettingsFieldInt(&(settings.Left), L"WindowPosLeft")); 123 infoFields.AddTail(new SettingsFieldInt(&(settings.Top), L"WindowPosTop")); 124 infoFields.AddTail(new SettingsFieldInt(&(settings.Width), L"WindowPosWidth")); 125 infoFields.AddTail(new SettingsFieldInt(&(settings.Height), L"WindowPosHeight")); 126 infoFields.AddTail(new SettingsFieldInt(&(settings.Proxy), L"ProxyMode")); 127 infoFields.AddTail(new SettingsFieldString((settings.szProxyServer), MAX_PATH, L"ProxyServer")); 128 infoFields.AddTail(new SettingsFieldString((settings.szNoProxyFor), MAX_PATH, L"NoProxyFor")); 129 infoFields.AddTail(new SettingsFieldBool(&(settings.bUseSource), L"bUseSource")); 130 infoFields.AddTail(new SettingsFieldString((settings.szSourceURL), INTERNET_MAX_URL_LENGTH, L"SourceURL")); 131 } 132 133 static BOOL 134 SaveAllSettings(CRegKey &key, SETTINGS_INFO &settings) 135 { 136 BOOL bAllSuccess = TRUE; 137 ATL::CAtlList<SettingsField *> infoFields; 138 139 AddInfoFields(infoFields, settings); 140 141 POSITION InfoListPosition = infoFields.GetHeadPosition(); 142 while (InfoListPosition) 143 { 144 SettingsField *Info = infoFields.GetNext(InfoListPosition); 145 if (!Info->Save(key)) 146 { 147 bAllSuccess = FALSE; 148 // TODO: error log 149 } 150 delete Info; 151 } 152 return bAllSuccess; 153 } 154 155 static BOOL 156 LoadAllSettings(CRegKey &key, SETTINGS_INFO &settings) 157 { 158 BOOL bLoadedAny = FALSE; 159 ATL::CAtlList<SettingsField *> infoFields; 160 161 AddInfoFields(infoFields, settings); 162 163 POSITION InfoListPosition = infoFields.GetHeadPosition(); 164 while (InfoListPosition) 165 { 166 SettingsField *Info = infoFields.GetNext(InfoListPosition); 167 if (Info->Load(key)) 168 bLoadedAny = TRUE; 169 //else 170 // TODO: error log 171 delete Info; 172 } 173 return bLoadedAny; 174 } 175 176 static void 177 GetDefaultDownloadDirectory(CStringW &szDownloadDir) 178 { 179 if (FAILED(SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, szDownloadDir.GetBuffer(MAX_PATH)))) 180 { 181 szDownloadDir.ReleaseBuffer(); 182 if (!szDownloadDir.GetEnvironmentVariableW(L"SystemDrive")) 183 { 184 szDownloadDir = L"C:"; 185 } 186 } 187 else 188 { 189 szDownloadDir.ReleaseBuffer(); 190 } 191 192 PathAppendW(szDownloadDir.GetBuffer(MAX_PATH), L"\\RAPPS Downloads"); 193 szDownloadDir.ReleaseBuffer(); 194 } 195 196 static VOID 197 ValidateStringSettings(PSETTINGS_INFO pSettingsInfo) 198 { 199 if (!pSettingsInfo->szDownloadDir[0]) 200 { 201 CStringW szDownloadDir; 202 GetDefaultDownloadDirectory(szDownloadDir); 203 204 CStringW::CopyChars(pSettingsInfo->szDownloadDir, _countof(pSettingsInfo->szDownloadDir), 205 szDownloadDir.GetString(), szDownloadDir.GetLength() + 1); 206 } 207 } 208 209 VOID 210 FillDefaultSettings(PSETTINGS_INFO pSettingsInfo) 211 { 212 ZeroMemory(pSettingsInfo, sizeof(*pSettingsInfo)); 213 214 pSettingsInfo->bSaveWndPos = TRUE; 215 pSettingsInfo->bUpdateAtStart = FALSE; 216 pSettingsInfo->bLogEnabled = TRUE; 217 pSettingsInfo->bUseSource = FALSE; 218 pSettingsInfo->bDelInstaller = FALSE; 219 pSettingsInfo->Maximized = FALSE; 220 pSettingsInfo->Left = CW_USEDEFAULT; 221 pSettingsInfo->Top = CW_USEDEFAULT; 222 pSettingsInfo->Width = 680; 223 pSettingsInfo->Height = 450; 224 225 ValidateStringSettings(pSettingsInfo); 226 } 227 228 BOOL 229 LoadSettings(PSETTINGS_INFO pSettingsInfo) 230 { 231 BOOL bLoadedAny = FALSE; 232 233 FillDefaultSettings(pSettingsInfo); 234 235 ATL::CRegKey RegKey; 236 if (RegKey.Open(HKEY_CURRENT_USER, SETTINGSSUBKEY, KEY_READ) == ERROR_SUCCESS) 237 { 238 bLoadedAny = LoadAllSettings(RegKey, *pSettingsInfo); 239 } 240 241 ValidateStringSettings(pSettingsInfo); // Handles the case where a REG_SZ is present but empty 242 243 if (!bLoadedAny) 244 { 245 // This the first launch, write at least one item so ParseCmdAndExecute() does not 246 // trigger another DB update in another process instance between now and SaveSettings(). 247 ATL::CRegKey RegKey; 248 if (RegKey.Create(HKEY_CURRENT_USER, SETTINGSSUBKEY, NULL, REG_OPTION_NON_VOLATILE, 249 KEY_WRITE, NULL, NULL) == ERROR_SUCCESS) 250 { 251 SettingsFieldBool field(&(pSettingsInfo->bUpdateAtStart), L"bUpdateAtStart"); 252 field.Save(RegKey); 253 } 254 } 255 return bLoadedAny; 256 } 257 258 BOOL 259 SaveSettings(HWND hwnd, PSETTINGS_INFO pSettingsInfo) 260 { 261 WINDOWPLACEMENT wp; 262 ATL::CRegKey RegKey; 263 264 if (pSettingsInfo->bSaveWndPos) 265 { 266 wp.length = sizeof(wp); 267 GetWindowPlacement(hwnd, &wp); 268 269 pSettingsInfo->Left = wp.rcNormalPosition.left; 270 pSettingsInfo->Top = wp.rcNormalPosition.top; 271 pSettingsInfo->Width = wp.rcNormalPosition.right - wp.rcNormalPosition.left; 272 pSettingsInfo->Height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; 273 pSettingsInfo->Maximized = 274 (wp.showCmd == SW_MAXIMIZE || (wp.showCmd == SW_SHOWMINIMIZED && (wp.flags & WPF_RESTORETOMAXIMIZED))); 275 } 276 277 if (RegKey.Create(HKEY_CURRENT_USER, SETTINGSSUBKEY, NULL, REG_OPTION_NON_VOLATILE, 278 KEY_WRITE, NULL, NULL) != ERROR_SUCCESS) 279 { 280 return FALSE; 281 } 282 283 return SaveAllSettings(RegKey, *pSettingsInfo); 284 } 285