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 #include <strsafe.h>
24 
25 const WCHAR g_szGeneralRegKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit";
26 DECLSPEC_IMPORT ULONG WINAPIV DbgPrint(PCCH Format,...);
27 
28 /*
29 VV,VV,VV,VV,WA,WA,WA,WA,WB,WB,WB,WB,R1,R1,R1,R1
30 R2,R2,R2,R2,R3,R3,R3,R3,R4,R4,R4,r4,LL,LL,LL,LL
31 TT,TT,TT,TT,RR,RR,RR,RR,BB,BB,BB,BB,SS,SS,SS,SS
32 NN,NN,NN,NN,KK,KK,KK,KK,DD,DD,DD,DD,SB,SB,SB,SB
33 
34 VV = Version or Sanity? WINDOWPLACEMENT? (2C?)
35 WA = (0=restored / 1=maximized)
36 WB = (1=restored / 3=maximized)
37 R1 = ???? \
38 R2 = ???? | either those are reserved unused or they will
39 R3 = ???? | have IP/INFO if connected to remote registry
40 R4 = ???? /
41 LL = Left position of window
42 TT = top position of window
43 RR = right position of window
44 BB = bottom position of window
45 SS = size of key tree view (splitter)
46 NN = size of 'name' column
47 KK = size of 'type' column (kind)
48 DD = size of 'data' coumn
49 SB = status bar (1=visible / 0=hidden)
50 */
51 
52 typedef struct
53 {
54     WINDOWPLACEMENT tPlacement;
55     int             TreeViewSize;
56     int             NameColumnSize;
57     int             TypeColumnSize;
58     int             DataColumnSize;
59     BOOL            StatusBarVisible;
60 } RegistryBinaryConfig;
61 
62 extern void LoadSettings(void)
63 {
64     HKEY hKey = NULL;
65     WCHAR szBuffer[MAX_PATH];
66 
67     if (RegOpenKeyW(HKEY_CURRENT_USER, g_szGeneralRegKey, &hKey) == ERROR_SUCCESS)
68     {
69         RegistryBinaryConfig tConfig;
70         DWORD iBufferSize = sizeof(tConfig);
71         BOOL bVisible = FALSE;
72 
73         if (RegQueryValueExW(hKey, L"View", NULL, NULL, (LPBYTE)&tConfig, &iBufferSize) == ERROR_SUCCESS)
74         {
75             if (iBufferSize == sizeof(tConfig))
76             {
77                 RECT rcTemp;
78 
79                 /* Update status bar settings */
80                 CheckMenuItem(GetSubMenu(hMenuFrame, ID_VIEW_MENU), ID_VIEW_STATUSBAR, MF_BYCOMMAND | (tConfig.StatusBarVisible ? MF_CHECKED : MF_UNCHECKED));
81                 ShowWindow(hStatusBar, (tConfig.StatusBarVisible ? SW_SHOW : SW_HIDE));
82 
83                 /* Update listview column width */
84                 (void)ListView_SetColumnWidth(g_pChildWnd->hListWnd, 0, tConfig.NameColumnSize);
85                 (void)ListView_SetColumnWidth(g_pChildWnd->hListWnd, 1, tConfig.TypeColumnSize);
86                 (void)ListView_SetColumnWidth(g_pChildWnd->hListWnd, 2, tConfig.DataColumnSize);
87 
88                 /* Update treeview (splitter) */
89                 GetClientRect(hFrameWnd, &rcTemp);
90                 g_pChildWnd->nSplitPos = tConfig.TreeViewSize;
91                 ResizeWnd(rcTemp.right, rcTemp.bottom);
92 
93                 /* Apply program window settings */
94                 tConfig.tPlacement.length = sizeof(WINDOWPLACEMENT);
95                 bVisible = SetWindowPlacement(hFrameWnd, &tConfig.tPlacement);
96             }
97         }
98 
99         /* In case we fail to restore the window, or open the key, show normal */
100         if (!bVisible)
101             ShowWindow(hFrameWnd, SW_SHOWNORMAL);
102 
103         /* Restore key position */
104         if (QueryStringValue(HKEY_CURRENT_USER, g_szGeneralRegKey, L"LastKey", szBuffer, COUNT_OF(szBuffer)) == ERROR_SUCCESS)
105         {
106             SelectNode(g_pChildWnd->hTreeWnd, szBuffer);
107         }
108 
109         RegCloseKey(hKey);
110     }
111     else
112     {
113         /* Failed to open key, show normal */
114         ShowWindow(hFrameWnd, SW_SHOWNORMAL);
115     }
116 }
117 
118 extern void SaveSettings(void)
119 {
120     HKEY hKey = NULL;
121 
122     if (RegCreateKeyW(HKEY_CURRENT_USER, g_szGeneralRegKey, &hKey) == ERROR_SUCCESS)
123     {
124         RegistryBinaryConfig tConfig;
125         DWORD iBufferSize = sizeof(tConfig);
126         WCHAR szBuffer[MAX_PATH]; /* FIXME: a complete registry path can be longer than that */
127         LPCWSTR keyPath, rootName;
128         HKEY hRootKey;
129 
130         /* Save key position */
131         keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
132         rootName = get_root_key_name(hRootKey);
133 
134         /* Load "My Computer" string and complete it */
135         if (LoadStringW(hInst, IDS_MY_COMPUTER, szBuffer, COUNT_OF(szBuffer)) &&
136             SUCCEEDED(StringCbCatW(szBuffer, sizeof(szBuffer), L"\\")) &&
137             SUCCEEDED(StringCbCatW(szBuffer, sizeof(szBuffer), rootName)) &&
138             SUCCEEDED(StringCbCatW(szBuffer, sizeof(szBuffer), L"\\")))
139         {
140             HRESULT hr = S_OK;
141             if (keyPath)
142                 hr = StringCbCatW(szBuffer, sizeof(szBuffer), keyPath);
143             if (SUCCEEDED(hr))
144                 RegSetValueExW(hKey, L"LastKey", 0, REG_SZ, (LPBYTE)szBuffer, (DWORD)wcslen(szBuffer) * sizeof(WCHAR));
145             else
146                 DbgPrint("err: (%s:%d): Buffer not big enough for '%S + %S'\n", __FILE__, __LINE__, rootName, keyPath);
147         }
148         else
149         {
150             DbgPrint("err: (%s:%d): Buffer not big enough for '%S'\n", __FILE__, __LINE__, rootName);
151         }
152 
153         /* Get statusbar settings */
154         tConfig.StatusBarVisible = ((GetMenuState(GetSubMenu(hMenuFrame, ID_VIEW_MENU), ID_VIEW_STATUSBAR, MF_BYCOMMAND) & MF_CHECKED) ? 1 : 0);
155 
156         /* Get splitter position */
157         tConfig.TreeViewSize = g_pChildWnd->nSplitPos;
158 
159         /* Get list view column width*/
160         tConfig.NameColumnSize = ListView_GetColumnWidth(g_pChildWnd->hListWnd, 0);
161         tConfig.TypeColumnSize = ListView_GetColumnWidth(g_pChildWnd->hListWnd, 1);
162         tConfig.DataColumnSize = ListView_GetColumnWidth(g_pChildWnd->hListWnd, 2);
163 
164         /* Get program window settings */
165         tConfig.tPlacement.length = sizeof(WINDOWPLACEMENT);
166         GetWindowPlacement(hFrameWnd, &tConfig.tPlacement);
167 
168         /* Save all the data */
169         RegSetValueExW(hKey, L"View", 0, REG_BINARY, (LPBYTE)&tConfig, iBufferSize);
170 
171         RegCloseKey(hKey);
172     }
173 }
174 /* EOF */
175