1 /*
2  * ReactOS Explorer
3  *
4  * Copyright 2009 Andrew Hill <ash77 at domain reactos.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 #include "precomp.h"
22 
23 #define DEFBROWSERSTREAM L"Settings"
24 #define DEFAULT_VID GUID_NULL // We don't support WebView
25 #define CURRENT_VERSION ( DEFFOLDERSETTINGS::VER_XP )
26 
27 template<class S, class D> static void CopyTo(const S &Src, D &Dst)
28 {
29     Dst.FolderSettings = Src.FolderSettings;
30 }
31 
32 static void EnsureValid(FOLDERSETTINGS &fs)
33 {
34     if ((int)fs.ViewMode < FVM_AUTO || (int)fs.ViewMode > FVM_LAST)
35         fs.ViewMode = SBFOLDERSETTINGS::DEF_FVM;
36 
37     fs.fFlags &= ~(FWF_OWNERDATA | FWF_DESKTOP | FWF_TRANSPARENT | FWF_NOCLIENTEDGE |
38                    FWF_NOSUBFOLDERS | FWF_NOSCROLL | FWF_NOENUMREFRESH | FWF_NOVISIBLE);
39 }
40 
41 static void EnsureValid(DEFFOLDERSETTINGS &dfs)
42 {
43     EnsureValid(dfs.FolderSettings);
44 }
45 
46 static void InitializeDefaults(DEFFOLDERSETTINGS &dfs)
47 {
48     C_ASSERT(FIELD_OFFSET(DEFFOLDERSETTINGS, FolderSettings) == 4);
49     C_ASSERT(FIELD_OFFSET(DEFFOLDERSETTINGS, ViewPriority) == DEFFOLDERSETTINGS::SIZE_IE4);
50     C_ASSERT(sizeof(DEFFOLDERSETTINGS) == DEFFOLDERSETTINGS::SIZE_XP);
51 
52     *(UINT*)&dfs = FALSE; // Set all unknown flags to FALSE
53     dfs.Statusbar = TRUE;
54     dfs.FolderSettings.ViewMode = SBFOLDERSETTINGS::DEF_FVM;
55     dfs.FolderSettings.fFlags = SBFOLDERSETTINGS::DEF_FWF;
56     dfs.vid = DEFAULT_VID;
57     dfs.Version = CURRENT_VERSION;
58     dfs.Counter = 0;
59     dfs.ViewPriority = VIEW_PRIORITY_CACHEMISS;
60 }
61 
62 void SBFOLDERSETTINGS::Load()
63 {
64     DEFFOLDERSETTINGS dfs;
65     CGlobalFolderSettings::Load(dfs);
66     CopyTo(dfs, *this);
67 }
68 
69 CGlobalFolderSettings::CGlobalFolderSettings()
70 {
71 }
72 
73 CGlobalFolderSettings::~CGlobalFolderSettings()
74 {
75 }
76 
77 HRESULT CGlobalFolderSettings::ResetBrowserSettings()
78 {
79     return Save(NULL);
80 }
81 
82 HRESULT CGlobalFolderSettings::SaveBrowserSettings(const SBFOLDERSETTINGS &sbfs)
83 {
84     DEFFOLDERSETTINGS dfs;
85     InitializeDefaults(dfs);
86     CopyTo(sbfs, dfs);
87     return Save(&dfs);
88 }
89 
90 HRESULT CGlobalFolderSettings::Load(DEFFOLDERSETTINGS &dfs)
91 {
92     HKEY hStreamsKey = SHGetShellKey(SHKEY_Key_Explorer, L"Streams", FALSE);
93     if (hStreamsKey)
94     {
95         DWORD cb = sizeof(DEFFOLDERSETTINGS);
96         DWORD err = SHRegGetValueW(hStreamsKey, NULL, DEFBROWSERSTREAM,
97                                    SRRF_RT_REG_BINARY, NULL, &dfs, &cb);
98         RegCloseKey(hStreamsKey);
99         if (!err && cb >= DEFFOLDERSETTINGS::SIZE_NT4)
100         {
101             if (cb < FIELD_OFFSET(DEFFOLDERSETTINGS, vid))
102             {
103                 dfs.FolderSettings.fFlags = SBFOLDERSETTINGS::DEF_FWF;
104             }
105             if (cb < FIELD_OFFSET(DEFFOLDERSETTINGS, Version))
106             {
107                 dfs.vid = DEFAULT_VID;
108             }
109             if (cb <= FIELD_OFFSET(DEFFOLDERSETTINGS, ViewPriority))
110             {
111                 dfs.Version = CURRENT_VERSION;
112             }
113             dfs.ViewPriority = VIEW_PRIORITY_STALECACHEHIT;
114             EnsureValid(dfs);
115             return S_OK;
116         }
117     }
118     InitializeDefaults(dfs);
119     return S_FALSE;
120 }
121 
122 HRESULT CGlobalFolderSettings::Save(const DEFFOLDERSETTINGS *pFDS)
123 {
124     HKEY hStreamsKey = SHGetShellKey(SHKEY_Key_Explorer, L"Streams", TRUE);
125     if (!hStreamsKey)
126         return E_FAIL;
127 
128     HRESULT hr = E_INVALIDARG;
129     if (!pFDS)
130     {
131         DWORD err = SHDeleteValueW(hStreamsKey, NULL, DEFBROWSERSTREAM);
132         hr = (!err || err == ERROR_FILE_NOT_FOUND) ? S_OK : HResultFromWin32(err);
133     }
134     else
135     {
136         DWORD cb = sizeof(DEFFOLDERSETTINGS);
137         hr = HResultFromWin32(SHSetValueW(hStreamsKey, NULL, DEFBROWSERSTREAM, REG_BINARY, pFDS, cb));
138     }
139     RegCloseKey(hStreamsKey);
140     return hr;
141 }
142 
143 HRESULT STDMETHODCALLTYPE CGlobalFolderSettings::Get(struct DEFFOLDERSETTINGS *pFDS, UINT cb)
144 {
145     if (cb != sizeof(DEFFOLDERSETTINGS) || !pFDS)
146         return E_INVALIDARG;
147     return Load(*pFDS);
148 }
149 
150 HRESULT STDMETHODCALLTYPE CGlobalFolderSettings::Set(const struct DEFFOLDERSETTINGS *pFDS, UINT cb, UINT unknown)
151 {
152     // NULL pFDS means reset
153     if (cb != sizeof(DEFFOLDERSETTINGS) && pFDS)
154         return E_INVALIDARG;
155     return Save(pFDS);
156 }
157