1 /*
2 	vfdshutil.cpp
3 
4 	Virtual Floppy Drive for Windows
5 	Driver control library
6 	shell extension utility functions
7 
8 	Copyright (c) 2003-2005 Ken Kato
9 */
10 
11 #define WIN32_LEAN_AND_MEAN
12 #include <windows.h>
13 #include <objbase.h>
14 #include <stdio.h>
15 
16 #include "vfdtypes.h"
17 #include "vfdapi.h"
18 #include "vfdlib.h"
19 #include "vfdshcfact.h"
20 
21 //=====================================
22 // Initialize the GUID instance
23 //=====================================
24 
25 #if !defined(__REACTOS__) || defined(_MSC_VER)
26 #pragma data_seg(".text")
27 #endif
28 #define INITGUID
29 #include <initguid.h>
30 #include <shlguid.h>
31 #include "vfdshguid.h"
32 #if !defined(__REACTOS__) || defined(_MSC_VER)
33 #pragma data_seg()
34 #endif
35 
36 //
37 //	Registry path to the approved shell extensions key
38 //
39 #define REGKEY_APPROVED \
40 	"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"
41 
42 
43 //=====================================
44 //	Shell extension library requirements
45 //=====================================
46 
47 //
48 //	Creates a class factory instance
49 //
DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppvOut)50 STDAPI DllGetClassObject(
51 	REFCLSID		rclsid,
52 	REFIID			riid,
53 	LPVOID			*ppvOut)
54 {
55 	VFDTRACE(0,
56 		("DllGetClassObject\n"));
57 
58 	*ppvOut = NULL;
59 
60 	if (IsEqualIID(rclsid, CLSID_VfdShellExt)) {
61 		CVfdFactory *pFactory = new CVfdFactory;
62 
63 		if (!pFactory) {
64 			return E_OUTOFMEMORY;
65 		}
66 
67 		return pFactory->QueryInterface(riid, ppvOut);
68 	}
69 
70 	return CLASS_E_CLASSNOTAVAILABLE;
71 }
72 
73 //
74 //	DllCanUnloadNow
75 //
DllCanUnloadNow(void)76 STDAPI DllCanUnloadNow(void)
77 {
78 	VFDTRACE(0,
79 		("DllCanUnloadNow - %s\n", (g_cDllRefCnt ? "No" : "Yes")));
80 
81 	return (g_cDllRefCnt ? S_FALSE : S_OK);
82 }
83 
84 //=====================================
85 // Shell extension register functions
86 //=====================================
87 
MakeGuidString(LPTSTR str,const GUID & guid)88 static inline void MakeGuidString(LPTSTR str, const GUID &guid)
89 {
90 	sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
91 		guid.Data1, guid.Data2, guid.Data3,
92 		guid.Data4[0], guid.Data4[1],
93 		guid.Data4[2], guid.Data4[3], guid.Data4[4],
94 		guid.Data4[5], guid.Data4[6], guid.Data4[7]);
95 }
96 
97 //
98 //	Regster this dll as shell extention handlers
99 //
VfdRegisterHandlers()100 DWORD WINAPI VfdRegisterHandlers()
101 {
102 	TCHAR	buf[MAX_PATH];
103 	TCHAR	guid_str[40];
104 	HKEY	hKey;
105 	DWORD	temp;
106 	DWORD	ret;
107 
108 	MakeGuidString(guid_str, CLSID_VfdShellExt);
109 
110 	//
111 	//	Register the GUID in the CLSID subtree
112 	//
113 	sprintf(buf, "CLSID\\%s", guid_str);
114 
115 	VFDTRACE(0, ("HKCR\\%s\n", buf));
116 
117 	ret = RegCreateKeyEx(
118 		HKEY_CLASSES_ROOT, buf, 0, NULL,
119 		0, KEY_ALL_ACCESS, NULL, &hKey, &temp);
120 
121 	if (ret != ERROR_SUCCESS) {
122 		return ret;
123 	}
124 
125 	if (temp == REG_OPENED_EXISTING_KEY) {
126 		temp = sizeof(buf);
127 
128 		ret = RegQueryValueEx(
129 			hKey, NULL, NULL, NULL, (PBYTE)buf, &temp);
130 
131 		if (ret != ERROR_SUCCESS) {
132 			RegCloseKey(hKey);
133 			return ret;
134 		}
135 
136 		if (_stricmp(buf, VFDEXT_DESCRIPTION)) {
137 			RegCloseKey(hKey);
138 			return ERROR_FILE_EXISTS;
139 		}
140 	}
141 	else {
142 
143 		VFDTRACE(0, ("@=" VFDEXT_DESCRIPTION "\n"));
144 
145 		ret = RegSetValueEx(hKey, NULL, NULL, REG_SZ,
146 			(PBYTE)VFDEXT_DESCRIPTION, sizeof(VFDEXT_DESCRIPTION));
147 
148 		RegCloseKey(hKey);
149 
150 		if (ret != ERROR_SUCCESS) {
151 			return ret;
152 		}
153 	}
154 
155 	//
156 	//	Register the executable path
157 	//
158 	sprintf(buf, "CLSID\\%s\\InProcServer32", guid_str);
159 
160 	VFDTRACE(0, ("HKCR\\%s\n", buf));
161 
162 	ret = RegCreateKeyEx(
163 		HKEY_CLASSES_ROOT, buf, 0, NULL,
164 		0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
165 
166 	if (ret != ERROR_SUCCESS) {
167 		return ret;
168 	}
169 
170 	temp = GetModuleFileName(g_hDllModule, buf, sizeof(buf));
171 
172 	VFDTRACE(0, ("@=%s\n", buf));
173 
174 	ret = RegSetValueEx(
175 		hKey, NULL, NULL, REG_SZ, (PBYTE)buf, temp + 1);
176 
177 	if (ret != ERROR_SUCCESS) {
178 		RegCloseKey(hKey);
179 		return ret;
180 	}
181 
182 	VFDTRACE(0, ("ThreadingModel=Apartment\n"));
183 
184 	ret = RegSetValueEx(hKey, "ThreadingModel", NULL, REG_SZ,
185 		(PBYTE)"Apartment", sizeof("Apartment"));
186 
187 	RegCloseKey(hKey);
188 
189 	if (ret != ERROR_SUCCESS) {
190 		return ret;
191 	}
192 
193 	//
194 	//	Register context menu handler
195 	//
196 	VFDTRACE(0, ("HKCR\\" VFDEXT_MENU_REGKEY "\n"));
197 
198 	ret = RegCreateKeyEx(
199 		HKEY_CLASSES_ROOT, VFDEXT_MENU_REGKEY, 0, NULL,
200 		0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
201 
202 	if (ret != ERROR_SUCCESS) {
203 		return ret;
204 	}
205 
206 	VFDTRACE(0, ("@=%s\n", guid_str));
207 
208 	ret = RegSetValueEx(hKey, NULL, NULL, REG_SZ,
209 		(PBYTE)guid_str, strlen(guid_str) + 1);
210 
211 	RegCloseKey(hKey);
212 
213 	if (ret != ERROR_SUCCESS) {
214 		return ret;
215 	}
216 
217 	//
218 	//	Register Drag&Drop handler
219 	//
220 	if (!IS_WINDOWS_NT()) {
221 		//
222 		//	Windows NT does not support Drag&Drop handlers ???
223 		//
224 		VFDTRACE(0, ("HKCR\\" VFDEXT_DND_REGKEY "\n"));
225 
226 		ret = RegCreateKeyEx(
227 			HKEY_CLASSES_ROOT, VFDEXT_DND_REGKEY, 0, NULL,
228 			0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
229 
230 		if (ret != ERROR_SUCCESS) {
231 			return ret;
232 		}
233 
234 		VFDTRACE(0, ("@=%s\n", guid_str));
235 
236 		ret = RegSetValueEx(hKey, NULL, NULL, REG_SZ,
237 			(PBYTE)guid_str, strlen(guid_str) + 1);
238 
239 		RegCloseKey(hKey);
240 
241 		if (ret != ERROR_SUCCESS) {
242 			return ret;
243 		}
244 	}
245 
246 	//
247 	//	Register property sheet handler
248 	//
249 	VFDTRACE(0, ("HKCR\\" VFDEXT_PROP_REGKEY "\n"));
250 
251 	ret = RegCreateKeyEx(
252 		HKEY_CLASSES_ROOT, VFDEXT_PROP_REGKEY, 0, NULL,
253 		0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
254 
255 	if (ret != ERROR_SUCCESS) {
256 		return ret;
257 	}
258 
259 	VFDTRACE(0, ("@=%s\n", guid_str));
260 
261 	ret = RegSetValueEx(hKey, NULL, NULL, REG_SZ,
262 		(PBYTE)guid_str, strlen(guid_str) + 1);
263 
264 	RegCloseKey(hKey);
265 
266 	if (ret != ERROR_SUCCESS) {
267 		return ret;
268 	}
269 
270 	//
271 	//	Register approved extensions entry
272 	//
273 	VFDTRACE(0, ("HKLM\\" REGKEY_APPROVED "\n"));
274 
275 	ret = RegCreateKeyEx(
276 		HKEY_LOCAL_MACHINE, REGKEY_APPROVED,
277 		0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
278 
279 	if (ret != ERROR_SUCCESS) {
280 		return ret;
281 	}
282 
283 	VFDTRACE(0,
284 		("%s=" VFDEXT_DESCRIPTION "\n", guid_str));
285 
286 	ret = RegSetValueEx(hKey, guid_str, NULL, REG_SZ,
287 		(PBYTE)VFDEXT_DESCRIPTION, sizeof(VFDEXT_DESCRIPTION));
288 
289 	RegCloseKey(hKey);
290 
291 	return ret;
292 }
293 
294 //
295 //	Unregister context menu handler
296 //
VfdUnregisterHandlers()297 DWORD WINAPI VfdUnregisterHandlers()
298 {
299 	TCHAR	buf[MAX_PATH];
300 	TCHAR	guid_str[40];
301 	HKEY	hKey;
302 	DWORD	temp;
303 	DWORD	ret;
304 
305 	MakeGuidString(guid_str, CLSID_VfdShellExt);
306 
307 	sprintf(buf, "CLSID\\%s", guid_str);
308 
309 	VFDTRACE(0, ("HKCR\\%s\n", buf));
310 
311 	temp = sizeof(buf);
312 
313 	ret = RegQueryValue(HKEY_CLASSES_ROOT, buf, buf, (PLONG)&temp);
314 
315 	if (ret != ERROR_SUCCESS) {
316 		return ret;
317 	}
318 
319 	if (_stricmp(buf, VFDEXT_DESCRIPTION)) {
320 		return ERROR_PATH_NOT_FOUND;
321 	}
322 
323 	sprintf(buf, "CLSID\\%s\\InProcServer32", guid_str);
324 
325 	VFDTRACE(0, ("HKCR\\%s\n", buf));
326 
327 	ret = RegDeleteKey(HKEY_CLASSES_ROOT, buf);
328 
329 	if (ret != ERROR_SUCCESS) {
330 		return ret;
331 	}
332 
333 	sprintf(buf, "CLSID\\%s", guid_str);
334 
335 	VFDTRACE(0, ("HKCR\\%s\n", buf));
336 
337 	ret = RegDeleteKey(HKEY_CLASSES_ROOT, buf);
338 
339 	if (ret != ERROR_SUCCESS) {
340 		return ret;
341 	}
342 
343 	VFDTRACE(0, ("HKCR\\" VFDEXT_MENU_REGKEY "\n"));
344 
345 	ret = RegDeleteKey(HKEY_CLASSES_ROOT, VFDEXT_MENU_REGKEY);
346 
347 	if (ret != ERROR_SUCCESS) {
348 		return ret;
349 	}
350 
351 	if (!IS_WINDOWS_NT()) {
352 
353 		//	Windows NT doesn't support Drag & Drop handlers ???
354 
355 		VFDTRACE(0, ("HKCR\\" VFDEXT_DND_REGKEY "\n"));
356 
357 		ret = RegDeleteKey(HKEY_CLASSES_ROOT, VFDEXT_DND_REGKEY);
358 
359 		if (ret != ERROR_SUCCESS) {
360 			return ret;
361 		}
362 	}
363 
364 	VFDTRACE(0, ("HKCR\\" VFDEXT_PROP_REGKEY "\n"));
365 
366 	ret = RegDeleteKey(HKEY_CLASSES_ROOT, VFDEXT_PROP_REGKEY);
367 
368 	if (ret != ERROR_SUCCESS) {
369 		return ret;
370 	}
371 
372 	VFDTRACE(0, ("HKLM\\" REGKEY_APPROVED "\n"));
373 
374 	ret = RegCreateKeyEx(
375 		HKEY_LOCAL_MACHINE,
376 		REGKEY_APPROVED,
377 		0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
378 
379 	if (ret != ERROR_SUCCESS) {
380 		return ret;
381 	}
382 
383 	ret = RegDeleteValue(hKey, guid_str);
384 
385 	RegCloseKey(hKey);
386 
387 	return ret;
388 }
389 
390 //
391 //	Check if context menu handler is registered
392 //
VfdCheckHandlers()393 DWORD WINAPI VfdCheckHandlers()
394 {
395 	TCHAR	buf[MAX_PATH];
396 	TCHAR	guid_str[40];
397 	DWORD	temp;
398 	DWORD	ret;
399 
400 	MakeGuidString(guid_str, CLSID_VfdShellExt);
401 
402 	sprintf(buf, "CLSID\\%s", guid_str);
403 
404 	VFDTRACE(0, ("HKCR\\%s\n", buf));
405 
406 	temp = sizeof(buf);
407 
408 	ret = RegQueryValue(HKEY_CLASSES_ROOT, buf, buf, (PLONG)&temp);
409 
410 	if (ret != ERROR_SUCCESS) {
411 		return ret;
412 	}
413 
414 	if (_stricmp(buf, VFDEXT_DESCRIPTION)) {
415 		return ERROR_PATH_NOT_FOUND;
416 	}
417 
418 	return ERROR_SUCCESS;
419 }
420