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