1 /*
2 * Copyright 2004 Martin Fuchs
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19
20 //
21 // Explorer clone
22 //
23 // ntobjfs.cpp
24 //
25 // Martin Fuchs, 31.01.2004
26 //
27
28
29 #include <precomp.h>
30
31 #include "regfs.h"
32
33
read_directory(int scan_flags)34 void RegDirectory::read_directory(int scan_flags)
35 {
36 CONTEXT("RegDirectory::read_directory()");
37
38 Entry* first_entry = NULL;
39 int level = _level + 1;
40
41 TCHAR buffer[MAX_PATH];
42
43 _tcscpy(buffer, (LPCTSTR)_path);
44 LPTSTR pname = buffer + _tcslen(buffer);
45 int plen = MAX_PATH - _tcslen(buffer);
46
47 HKEY hkey;
48
49 if (!RegOpenKeyEx(_hKeyRoot, *buffer=='\\'?buffer+1:buffer, 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &hkey)) {
50 if (pname[-1] != '\\')
51 *pname++ = '\\', plen--;
52
53 TCHAR name[MAX_PATH], class_name[MAX_PATH];
54 WIN32_FIND_DATA w32fd;
55 Entry* last = NULL;
56 RegEntry* entry;
57
58 for(int idx=0; ; ++idx) {
59 memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
60
61 DWORD name_len = MAX_PATH;
62 DWORD class_len = MAX_PATH;
63
64 if (RegEnumKeyEx(hkey, idx, name, &name_len, 0, class_name, &class_len, &w32fd.ftLastWriteTime))
65 break;
66
67 w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
68 _tcsncpy(w32fd.cFileName, name, name_len);
69
70 _tcscpy_s(pname, plen, name);
71 entry = new RegDirectory(this, buffer, _hKeyRoot);
72
73 memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
74
75 if (class_len)
76 entry->_type_name = _tcsdup(String(class_name, class_len));
77
78 if (!first_entry)
79 first_entry = entry;
80
81 if (last)
82 last->_next = entry;
83
84 entry->_level = level;
85
86 last = entry;
87 }
88 /*
89 TCHAR value[MAX_PATH];
90 LONG value_len = sizeof(value);
91
92 if (!RegQueryValue(hkey, NULL, value, &value_len) && value_len>1) {
93 memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
94
95 lstrcpy(w32fd.cFileName, TEXT("(Default)"));
96
97 entry = new RegEntry(this);
98
99 memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
100
101 entry->_content = _tcsdup(value);
102
103 if (!first_entry)
104 first_entry = entry;
105
106 if (last)
107 last->_next = entry;
108
109 entry->_level = level;
110
111 last = entry;
112 }
113 */
114 DWORD type;
115 for(int idx=0; ; ++idx) {
116 DWORD name_len = MAX_PATH;
117
118 if (RegEnumValue(hkey, idx, name, &name_len, 0, &type, NULL, NULL))
119 break;
120
121 memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
122
123 if (name[0])
124 lstrcpy(w32fd.cFileName, name);
125 else
126 lstrcpy(w32fd.cFileName, TEXT("(Default)"));
127
128 entry = new RegEntry(this);
129
130 memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
131
132 switch(type) {
133 case REG_NONE: entry->_type_name = _tcsdup(TEXT("REG_NONE")); break;
134 case REG_SZ: entry->_type_name = _tcsdup(TEXT("REG_SZ")); break;
135 case REG_EXPAND_SZ: entry->_type_name = _tcsdup(TEXT("REG_EXPAND_SZ")); break;
136 case REG_BINARY: entry->_type_name = _tcsdup(TEXT("REG_BINARY")); break;
137 case REG_DWORD: entry->_type_name = _tcsdup(TEXT("REG_DWORD")); break;
138 case REG_DWORD_BIG_ENDIAN: entry->_type_name = _tcsdup(TEXT("REG_DWORD_BIG_ENDIAN")); break;
139 case REG_LINK: entry->_type_name = _tcsdup(TEXT("REG_LINK")); break;
140 case REG_MULTI_SZ: entry->_type_name = _tcsdup(TEXT("REG_MULTI_SZ")); break;
141 case REG_RESOURCE_LIST: entry->_type_name = _tcsdup(TEXT("REG_RESOURCE_LIST")); break;
142 case REG_FULL_RESOURCE_DESCRIPTOR: entry->_type_name = _tcsdup(TEXT("REG_FULL_RESOURCE_DESCRIPTOR")); break;
143 case REG_RESOURCE_REQUIREMENTS_LIST: entry->_type_name = _tcsdup(TEXT("REG_RESOURCE_REQUIREMENTS_LIST"));break;
144 case REG_QWORD: entry->_type_name = _tcsdup(TEXT("REG_QWORD")); break;
145 }
146
147 ///@todo This can also be done in the RegEnumValue() call if we dynamically adjust the return buffer size.
148 TCHAR value[MAX_PATH];
149 DWORD value_len = sizeof(value);
150
151 if (!RegQueryValueEx(hkey, name, NULL, NULL, (LPBYTE)value, &value_len)) {
152 if (type==REG_SZ || type==REG_EXPAND_SZ || type==REG_LINK)
153 entry->_content = _tcsdup(value);
154 else if (type == REG_DWORD) {
155 TCHAR b[32];
156 _stprintf(b, TEXT("%ld"), *(DWORD*)&value);
157 entry->_content = _tcsdup(b);
158 }
159 }
160
161 if (!first_entry)
162 first_entry = entry;
163
164 if (last)
165 last->_next = entry;
166
167 entry->_level = level;
168
169 last = entry;
170 }
171
172 if (last)
173 last->_next = NULL;
174
175 RegCloseKey(hkey);
176 }
177
178 _down = first_entry;
179 _scanned = true;
180 }
181
182
get_next_path_component(const void * p) const183 const void* RegDirectory::get_next_path_component(const void* p) const
184 {
185 LPCTSTR s = (LPCTSTR) p;
186
187 while(*s && *s!=TEXT('\\'))
188 ++s;
189
190 while(*s==TEXT('\\'))
191 ++s;
192
193 if (!*s)
194 return NULL;
195
196 return s;
197 }
198
199
find_entry(const void * p)200 Entry* RegDirectory::find_entry(const void* p)
201 {
202 LPCTSTR name = (LPCTSTR)p;
203
204 for(Entry*entry=_down; entry; entry=entry->_next) {
205 LPCTSTR p = name;
206 LPCTSTR q = entry->_data.cFileName;
207
208 do {
209 if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
210 return entry;
211 } while(tolower(*p++) == tolower(*q++));
212
213 p = name;
214 q = entry->_data.cAlternateFileName;
215
216 do {
217 if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
218 return entry;
219 } while(tolower(*p++) == tolower(*q++));
220 }
221
222 return NULL;
223 }
224
225
226 // get full path of specified registry entry
get_path(PTSTR path,size_t path_count) const227 bool RegEntry::get_path(PTSTR path, size_t path_count) const
228 {
229 return get_path_base ( path, path_count, ET_REGISTRY );
230 }
231
launch_entry(HWND hwnd,UINT nCmdShow)232 BOOL RegEntry::launch_entry(HWND hwnd, UINT nCmdShow)
233 {
234 return FALSE;
235 }
236
237
RegDirectory(Entry * parent,LPCTSTR path,HKEY hKeyRoot)238 RegDirectory::RegDirectory(Entry* parent, LPCTSTR path, HKEY hKeyRoot)
239 : RegEntry(parent),
240 _hKeyRoot(hKeyRoot)
241 {
242 _path = _tcsdup(path);
243
244 memset(&_data, 0, sizeof(WIN32_FIND_DATA));
245 _data.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
246 }
247
248
read_directory(int scan_flags)249 void RegistryRoot::read_directory(int scan_flags)
250 {
251 Entry *entry, *last, *first_entry;
252 int level = _level + 1;
253
254 _data.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
255
256 entry = new RegDirectory(this, TEXT("\\"), HKEY_CURRENT_USER);
257 _tcscpy(entry->_data.cFileName, TEXT("HKEY_CURRENT_USER"));
258 entry->_level = level;
259
260 first_entry = entry;
261 last = entry;
262
263 entry = new RegDirectory(this, TEXT("\\"), HKEY_LOCAL_MACHINE);
264 _tcscpy(entry->_data.cFileName, TEXT("HKEY_LOCAL_MACHINE"));
265 entry->_level = level;
266
267 last->_next = entry;
268 last = entry;
269
270 entry = new RegDirectory(this, TEXT("\\"), HKEY_CLASSES_ROOT);
271 _tcscpy(entry->_data.cFileName, TEXT("HKEY_CLASSES_ROOT"));
272 entry->_level = level;
273
274 last->_next = entry;
275 last = entry;
276
277 entry = new RegDirectory(this, TEXT("\\"), HKEY_USERS);
278 _tcscpy(entry->_data.cFileName, TEXT("HKEY_USERS"));
279 entry->_level = level;
280
281 last->_next = entry;
282 last = entry;
283 /*
284 entry = new RegDirectory(this, TEXT("\\"), HKEY_PERFORMANCE_DATA);
285 _tcscpy(entry->_data.cFileName, TEXT("HKEY_PERFORMANCE_DATA"));
286 entry->_level = level;
287
288 last->_next = entry;
289 last = entry;
290 */
291 entry = new RegDirectory(this, TEXT("\\"), HKEY_CURRENT_CONFIG);
292 _tcscpy(entry->_data.cFileName, TEXT("HKEY_CURRENT_CONFIG"));
293 entry->_level = level;
294
295 last->_next = entry;
296 last = entry;
297 /*
298 entry = new RegDirectory(this, TEXT("\\"), HKEY_DYN_DATA);
299 _tcscpy(entry->_data.cFileName, TEXT("HKEY_DYN_DATA"));
300 entry->_level = level;
301
302 last->_next = entry;
303 last = entry;
304 */
305 last->_next = NULL;
306
307 _down = first_entry;
308 _scanned = true;
309 }
310