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