1 /*
2  * Regedit settings
3  *
4  * Copyright (C) 2012 Edijs Kolesnikovics <terminedijs@yahoo.com>
5  * Copyright (C) 2012 Gr�gori Mac�rio Harbs <mysoft64bits at gmail dot com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "regedit.h"
23 
24 const WCHAR g_szGeneralRegKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit";
25 DECLSPEC_IMPORT ULONG WINAPIV DbgPrint(PCCH Format,...);
26 
27 /*
28 VV,VV,VV,VV,WA,WA,WA,WA,WB,WB,WB,WB,R1,R1,R1,R1
29 R2,R2,R2,R2,R3,R3,R3,R3,R4,R4,R4,r4,LL,LL,LL,LL
30 TT,TT,TT,TT,RR,RR,RR,RR,BB,BB,BB,BB,SS,SS,SS,SS
31 NN,NN,NN,NN,KK,KK,KK,KK,DD,DD,DD,DD,SB,SB,SB,SB
32 
33 VV = Version or Sanity? WINDOWPLACEMENT? (2C?)
34 WA = (0=restored / 1=maximized)
35 WB = (1=restored / 3=maximized)
36 R1 = ???? \
37 R2 = ???? | either those are reserved unused or they will
38 R3 = ???? | have IP/INFO if connected to remote registry
39 R4 = ???? /
40 LL = Left position of window
41 TT = top position of window
42 RR = right position of window
43 BB = bottom position of window
44 SS = size of key tree view (splitter)
45 NN = size of 'name' column
46 KK = size of 'type' column (kind)
47 DD = size of 'data' coumn
48 SB = status bar (1=visible / 0=hidden)
49 */
50 
51 typedef struct
52 {
53     WINDOWPLACEMENT tPlacement;
54     int             TreeViewSize;
55     int             NameColumnSize;
56     int             TypeColumnSize;
57     int             DataColumnSize;
58     BOOL            StatusBarVisible;
59 } RegistryBinaryConfig;
60 
61 extern void LoadSettings(void)
62 {
63     HKEY hKey = NULL;
64     WCHAR szBuffer[MAX_PATH];
65 
66     if (RegOpenKeyW(HKEY_CURRENT_USER, g_szGeneralRegKey, &hKey) == ERROR_SUCCESS)
67     {
68         RegistryBinaryConfig tConfig;
69         DWORD iBufferSize = sizeof(tConfig);
70         BOOL bVisible = FALSE;
71 
72         if (RegQueryValueExW(hKey, L"View", NULL, NULL, (LPBYTE)&tConfig, &iBufferSize) == ERROR_SUCCESS)
73         {
74             if (iBufferSize == sizeof(tConfig))
75             {
76                 RECT rcTemp;
77 
78                 /* Update status bar settings */
79                 CheckMenuItem(GetSubMenu(hMenuFrame, ID_VIEW_MENU), ID_VIEW_STATUSBAR, MF_BYCOMMAND | (tConfig.StatusBarVisible ? MF_CHECKED : MF_UNCHECKED));
80                 ShowWindow(hStatusBar, (tConfig.StatusBarVisible ? SW_SHOW : SW_HIDE));
81 
82                 /* Update listview column width */
83                 (void)ListView_SetColumnWidth(g_pChildWnd->hListWnd, 0, tConfig.NameColumnSize);
84                 (void)ListView_SetColumnWidth(g_pChildWnd->hListWnd, 1, tConfig.TypeColumnSize);
85                 (void)ListView_SetColumnWidth(g_pChildWnd->hListWnd, 2, tConfig.DataColumnSize);
86 
87                 /* Update treeview (splitter) */
88                 GetClientRect(hFrameWnd, &rcTemp);
89                 g_pChildWnd->nSplitPos = tConfig.TreeViewSize;
90                 ResizeWnd(rcTemp.right, rcTemp.bottom);
91 
92                 /* Apply program window settings */
93                 tConfig.tPlacement.length = sizeof(WINDOWPLACEMENT);
94                 bVisible = SetWindowPlacement(hFrameWnd, &tConfig.tPlacement);
95             }
96         }
97 
98         /* In case we fail to restore the window, or open the key, show normal */
99         if (!bVisible)
100             ShowWindow(hFrameWnd, SW_SHOWNORMAL);
101 
102         /* Restore key position */
103         if (QueryStringValue(HKEY_CURRENT_USER, g_szGeneralRegKey, L"LastKey", szBuffer, ARRAY_SIZE(szBuffer)) == ERROR_SUCCESS)
104         {
105             SelectNode(g_pChildWnd->hTreeWnd, szBuffer);
106         }
107 
108         RegCloseKey(hKey);
109     }
110     else
111     {
112         /* Failed to open key, show normal */
113         ShowWindow(hFrameWnd, SW_SHOWNORMAL);
114     }
115 }
116 
117 extern void SaveSettings(void)
118 {
119     HKEY hKey = NULL;
120 
121     if (RegCreateKeyW(HKEY_CURRENT_USER, g_szGeneralRegKey, &hKey) == ERROR_SUCCESS)
122     {
123         RegistryBinaryConfig tConfig;
124         DWORD iBufferSize = sizeof(tConfig);
125         WCHAR szBuffer[MAX_PATH]; /* FIXME: a complete registry path can be longer than that */
126         LPCWSTR keyPath, rootName;
127         HKEY hRootKey;
128 
129         /* Save key position */
130         keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
131         rootName = get_root_key_name(hRootKey);
132 
133         /* Load "My Computer" string and complete it */
134         if (LoadStringW(hInst, IDS_MY_COMPUTER, szBuffer, ARRAY_SIZE(szBuffer)) &&
135             SUCCEEDED(StringCbCatW(szBuffer, sizeof(szBuffer), L"\\")) &&
136             SUCCEEDED(StringCbCatW(szBuffer, sizeof(szBuffer), rootName)) &&
137             SUCCEEDED(StringCbCatW(szBuffer, sizeof(szBuffer), L"\\")))
138         {
139             HRESULT hr = S_OK;
140             if (keyPath)
141                 hr = StringCbCatW(szBuffer, sizeof(szBuffer), keyPath);
142             if (SUCCEEDED(hr))
143                 RegSetValueExW(hKey, L"LastKey", 0, REG_SZ, (LPBYTE)szBuffer, (DWORD)wcslen(szBuffer) * sizeof(WCHAR));
144             else
145                 DbgPrint("err: (%s:%d): Buffer not big enough for '%S + %S'\n", __FILE__, __LINE__, rootName, keyPath);
146         }
147         else
148         {
149             DbgPrint("err: (%s:%d): Buffer not big enough for '%S'\n", __FILE__, __LINE__, rootName);
150         }
151 
152         /* Get statusbar settings */
153         tConfig.StatusBarVisible = ((GetMenuState(GetSubMenu(hMenuFrame, ID_VIEW_MENU), ID_VIEW_STATUSBAR, MF_BYCOMMAND) & MF_CHECKED) ? 1 : 0);
154 
155         /* Get splitter position */
156         tConfig.TreeViewSize = g_pChildWnd->nSplitPos;
157 
158         /* Get list view column width*/
159         tConfig.NameColumnSize = ListView_GetColumnWidth(g_pChildWnd->hListWnd, 0);
160         tConfig.TypeColumnSize = ListView_GetColumnWidth(g_pChildWnd->hListWnd, 1);
161         tConfig.DataColumnSize = ListView_GetColumnWidth(g_pChildWnd->hListWnd, 2);
162 
163         /* Get program window settings */
164         tConfig.tPlacement.length = sizeof(WINDOWPLACEMENT);
165         GetWindowPlacement(hFrameWnd, &tConfig.tPlacement);
166 
167         /* Save all the data */
168         RegSetValueExW(hKey, L"View", 0, REG_BINARY, (LPBYTE)&tConfig, iBufferSize);
169 
170         RegCloseKey(hKey);
171     }
172 }
173 /* EOF */
174