wined3d: Implement more GLSL instructions and a little cleanup.
[wine] / dlls / shell32 / regsvr.c
1 /*
2  *      self-registerable dll functions for shell32.dll
3 *
4  * Copyright (C) 2003 John K. Hohm
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <string.h>
23 #include <stdio.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winreg.h"
29 #include "winerror.h"
30
31 #include "ole2.h"
32 #include "shlguid.h"
33 #include "shell32_main.h"
34 #include "shresdef.h"
35 #include "initguid.h"
36 #include "shfldr.h"
37
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41
42 /*
43  * Near the bottom of this file are the exported DllRegisterServer and
44  * DllUnregisterServer, which make all this worthwhile.
45  */
46
47 /***********************************************************************
48  *              interface for self-registering
49  */
50 struct regsvr_interface
51 {
52     IID const *iid;             /* NULL for end of list */
53     LPCSTR name;                /* can be NULL to omit */
54     IID const *base_iid;        /* can be NULL to omit */
55     int num_methods;            /* can be <0 to omit */
56     CLSID const *ps_clsid;      /* can be NULL to omit */
57     CLSID const *ps_clsid32;    /* can be NULL to omit */
58 };
59
60 static HRESULT register_interfaces(struct regsvr_interface const *list);
61 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
62
63 struct regsvr_coclass
64 {
65     CLSID const *clsid;         /* NULL for end of list */
66     LPCSTR name;                /* can be NULL to omit */
67     UINT idName;                /* can be 0 to omit */
68     LPCSTR ips;                 /* can be NULL to omit */
69     LPCSTR ips32;               /* can be NULL to omit */
70     LPCSTR ips32_tmodel;        /* can be NULL to omit */
71     DWORD flags;
72     DWORD dwAttributes;
73     DWORD dwCallForAttributes;
74     LPCSTR clsid_str;           /* can be NULL to omit */
75     LPCSTR progid;              /* can be NULL to omit */
76 };
77
78 /* flags for regsvr_coclass.flags */
79 #define SHELLEX_MAYCHANGEDEFAULTMENU  0x00000001
80 #define SHELLFOLDER_WANTSFORPARSING   0x00000002
81 #define SHELLFOLDER_ATTRIBUTES        0x00000004
82 #define SHELLFOLDER_CALLFORATTRIBUTES 0x00000008
83
84 static HRESULT register_coclasses(struct regsvr_coclass const *list);
85 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
86
87 struct regsvr_namespace
88 {
89     CLSID const *clsid; /* CLSID of the namespace extension. NULL for end of list */
90     LPCWSTR parent;     /* Mount point (MyComputer, Desktop, ..). */
91     LPCWSTR value;      /* Display name of the extension. */
92 };
93
94 static HRESULT register_namespace_extensions(struct regsvr_namespace const *list);
95 static HRESULT unregister_namespace_extensions(struct regsvr_namespace const *list);
96
97 /***********************************************************************
98  *              static string constants
99  */
100 static WCHAR const interface_keyname[10] = {
101     'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
102 static WCHAR const base_ifa_keyname[14] = {
103     'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
104     'e', 0 };
105 static WCHAR const num_methods_keyname[11] = {
106     'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
107 static WCHAR const ps_clsid_keyname[15] = {
108     'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
109     'i', 'd', 0 };
110 static WCHAR const ps_clsid32_keyname[17] = {
111     'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
112     'i', 'd', '3', '2', 0 };
113 static WCHAR const clsid_keyname[6] = {
114     'C', 'L', 'S', 'I', 'D', 0 };
115 static WCHAR const ips_keyname[13] = {
116     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
117     0 };
118 static WCHAR const ips32_keyname[15] = {
119     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
120     '3', '2', 0 };
121 static WCHAR const progid_keyname[7] = {
122     'P', 'r', 'o', 'g', 'I', 'D', 0 };
123 static WCHAR const shellex_keyname[8] = {
124     's', 'h', 'e', 'l', 'l', 'e', 'x', 0 };
125 static WCHAR const shellfolder_keyname[12] = {
126     'S', 'h', 'e', 'l', 'l', 'F', 'o', 'l', 'd', 'e', 'r', 0 };
127 static WCHAR const mcdm_keyname[21] = {
128     'M', 'a', 'y', 'C', 'h', 'a', 'n', 'g', 'e', 'D', 'e', 'f',
129     'a', 'u', 'l', 't', 'M', 'e', 'n', 'u', 0 };
130 static char const tmodel_valuename[] = "ThreadingModel";
131 static char const wfparsing_valuename[] = "WantsFORPARSING";
132 static char const attributes_valuename[] = "Attributes";
133 static char const cfattributes_valuename[] = "CallForAttributes";
134 static char const localized_valuename[] = "LocalizedString";
135
136 /***********************************************************************
137  *              static helper functions
138  */
139 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
140 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
141                                    WCHAR const *value);
142 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
143                                    char const *value);
144 static LONG recursive_delete_key(HKEY key);
145 static LONG recursive_delete_keyA(HKEY base, char const *name);
146 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
147
148 /***********************************************************************
149  *              register_interfaces
150  */
151 static HRESULT register_interfaces(struct regsvr_interface const *list)
152 {
153     LONG res = ERROR_SUCCESS;
154     HKEY interface_key;
155
156     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
157                           KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
158     if (res != ERROR_SUCCESS) goto error_return;
159
160     for (; res == ERROR_SUCCESS && list->iid; ++list) {
161         WCHAR buf[39];
162         HKEY iid_key;
163
164         StringFromGUID2(list->iid, buf, 39);
165         res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
166                               KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
167         if (res != ERROR_SUCCESS) goto error_close_interface_key;
168
169         if (list->name) {
170             res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
171                                  (CONST BYTE*)(list->name),
172                                  strlen(list->name) + 1);
173             if (res != ERROR_SUCCESS) goto error_close_iid_key;
174         }
175
176         if (list->base_iid) {
177             res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
178             if (res != ERROR_SUCCESS) goto error_close_iid_key;
179         }
180
181         if (0 <= list->num_methods) {
182             static WCHAR const fmt[3] = { '%', 'd', 0 };
183             HKEY key;
184
185             res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
186                                   KEY_READ | KEY_WRITE, NULL, &key, NULL);
187             if (res != ERROR_SUCCESS) goto error_close_iid_key;
188
189             wsprintfW(buf, fmt, list->num_methods);
190             res = RegSetValueExW(key, NULL, 0, REG_SZ,
191                                  (CONST BYTE*)buf,
192                                  (lstrlenW(buf) + 1) * sizeof(WCHAR));
193             RegCloseKey(key);
194
195             if (res != ERROR_SUCCESS) goto error_close_iid_key;
196         }
197
198         if (list->ps_clsid) {
199             register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
200             if (res != ERROR_SUCCESS) goto error_close_iid_key;
201         }
202
203         if (list->ps_clsid32) {
204             register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
205             if (res != ERROR_SUCCESS) goto error_close_iid_key;
206         }
207
208     error_close_iid_key:
209         RegCloseKey(iid_key);
210     }
211
212 error_close_interface_key:
213     RegCloseKey(interface_key);
214 error_return:
215     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
216 }
217
218 /***********************************************************************
219  *              unregister_interfaces
220  */
221 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
222 {
223     LONG res = ERROR_SUCCESS;
224     HKEY interface_key;
225
226     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
227                         KEY_READ | KEY_WRITE, &interface_key);
228     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
229     if (res != ERROR_SUCCESS) goto error_return;
230
231     for (; res == ERROR_SUCCESS && list->iid; ++list) {
232         WCHAR buf[39];
233
234         StringFromGUID2(list->iid, buf, 39);
235         res = recursive_delete_keyW(interface_key, buf);
236     }
237
238     RegCloseKey(interface_key);
239 error_return:
240     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
241 }
242
243 /***********************************************************************
244  *              register_coclasses
245  */
246 static HRESULT register_coclasses(struct regsvr_coclass const *list)
247 {
248     LONG res = ERROR_SUCCESS;
249     HKEY coclass_key;
250
251     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
252                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
253     if (res != ERROR_SUCCESS) goto error_return;
254
255     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
256         WCHAR buf[39];
257         HKEY clsid_key;
258
259         StringFromGUID2(list->clsid, buf, 39);
260         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
261                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
262         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
263
264         if (list->name) {
265             res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
266                                  (CONST BYTE*)(list->name),
267                                  strlen(list->name) + 1);
268             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
269         }
270
271         if (list->idName) {
272             char buffer[64] = "@%SYSTEMROOT%\\system32\\shell32.dll,-";
273             sprintf(buffer+strlen(buffer), "%u", list->idName);
274             res = RegSetValueExA(clsid_key, localized_valuename, 0, REG_EXPAND_SZ,
275                                  (CONST BYTE*)(buffer), strlen(buffer)+1);
276             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
277         }
278
279         if (list->ips) {
280             res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
281             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
282         }
283
284         if (list->ips32) {
285             HKEY ips32_key;
286
287             res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
288                                   KEY_READ | KEY_WRITE, NULL,
289                                   &ips32_key, NULL);
290             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
291
292             res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
293                                  (CONST BYTE*)list->ips32,
294                                  lstrlenA(list->ips32) + 1);
295             if (res == ERROR_SUCCESS && list->ips32_tmodel)
296                 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
297                                      (CONST BYTE*)list->ips32_tmodel,
298                                      strlen(list->ips32_tmodel) + 1);
299             RegCloseKey(ips32_key);
300             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
301         }
302
303         if (list->flags & SHELLEX_MAYCHANGEDEFAULTMENU) {
304             HKEY shellex_key, mcdm_key;
305
306             res = RegCreateKeyExW(clsid_key, shellex_keyname, 0, NULL, 0,
307                                   KEY_READ | KEY_WRITE, NULL,
308                                   &shellex_key, NULL);
309             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
310             res = RegCreateKeyExW(shellex_key, mcdm_keyname, 0, NULL, 0,
311                                   KEY_READ | KEY_WRITE, NULL,
312                                   &mcdm_key, NULL);
313             RegCloseKey(shellex_key);
314             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
315             RegCloseKey(mcdm_key);
316         }
317
318         if (list->flags & 
319                 (SHELLFOLDER_WANTSFORPARSING|SHELLFOLDER_ATTRIBUTES|SHELLFOLDER_CALLFORATTRIBUTES))
320         {
321             HKEY shellfolder_key;
322
323             res = RegCreateKeyExW(clsid_key, shellfolder_keyname, 0, NULL, 0,
324                                   KEY_READ | KEY_WRITE, NULL,
325                                   &shellfolder_key, NULL);
326             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
327             if (list->flags & SHELLFOLDER_WANTSFORPARSING)
328                 res = RegSetValueExA(shellfolder_key, wfparsing_valuename, 0, REG_SZ, (LPBYTE)"", 1);
329             if (list->flags & SHELLFOLDER_ATTRIBUTES) 
330                 res = RegSetValueExA(shellfolder_key, attributes_valuename, 0, REG_DWORD, 
331                                      (LPBYTE)&list->dwAttributes, sizeof(DWORD));
332             if (list->flags & SHELLFOLDER_CALLFORATTRIBUTES) 
333                 res = RegSetValueExA(shellfolder_key, cfattributes_valuename, 0, REG_DWORD,
334                                      (LPBYTE)&list->dwCallForAttributes, sizeof(DWORD));
335             RegCloseKey(shellfolder_key);
336             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
337         }
338
339         if (list->clsid_str) {
340             res = register_key_defvalueA(clsid_key, clsid_keyname,
341                                          list->clsid_str);
342             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
343         }
344
345         if (list->progid) {
346             HKEY progid_key;
347
348             res = register_key_defvalueA(clsid_key, progid_keyname,
349                                          list->progid);
350             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
351
352             res = RegCreateKeyExA(HKEY_CLASSES_ROOT, list->progid, 0,
353                                   NULL, 0, KEY_READ | KEY_WRITE, NULL,
354                                   &progid_key, NULL);
355             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
356
357             res = register_key_defvalueW(progid_key, clsid_keyname, buf);
358             RegCloseKey(progid_key);
359             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
360         }
361
362     error_close_clsid_key:
363         RegCloseKey(clsid_key);
364     }
365
366 error_close_coclass_key:
367     RegCloseKey(coclass_key);
368 error_return:
369     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
370 }
371
372 /***********************************************************************
373  *              unregister_coclasses
374  */
375 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
376 {
377     LONG res = ERROR_SUCCESS;
378     HKEY coclass_key;
379
380     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
381                         KEY_READ | KEY_WRITE, &coclass_key);
382     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
383     if (res != ERROR_SUCCESS) goto error_return;
384
385     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
386         WCHAR buf[39];
387
388         StringFromGUID2(list->clsid, buf, 39);
389         res = recursive_delete_keyW(coclass_key, buf);
390         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
391
392         if (list->progid) {
393             res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
394             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
395         }
396     }
397
398 error_close_coclass_key:
399     RegCloseKey(coclass_key);
400 error_return:
401     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
402 }
403
404 /**********************************************************************
405  * register_namespace_extensions
406  */
407 static WCHAR *get_namespace_key(struct regsvr_namespace const *list) {
408     static const WCHAR wszExplorerKey[] = {
409         'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
410         'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
411         'E','x','p','l','o','r','e','r','\\',0 };
412     static const WCHAR wszNamespace[] = { '\\','N','a','m','e','s','p','a','c','e','\\',0 };
413     WCHAR *pwszKey, *pwszCLSID;
414
415     pwszKey = HeapAlloc(GetProcessHeap(), 0, sizeof(wszExplorerKey)+sizeof(wszNamespace)+
416                                              sizeof(WCHAR)*(lstrlenW(list->parent)+CHARS_IN_GUID));
417     if (!pwszKey)
418         return NULL;
419
420     lstrcpyW(pwszKey, wszExplorerKey);
421     lstrcatW(pwszKey, list->parent);
422     lstrcatW(pwszKey, wszNamespace);
423     if (FAILED(StringFromCLSID(list->clsid, &pwszCLSID))) {
424         HeapFree(GetProcessHeap(), 0, pwszKey);
425         return NULL;
426     }
427     lstrcatW(pwszKey, pwszCLSID);
428     CoTaskMemFree(pwszCLSID);
429
430     return pwszKey;
431 }
432
433 static HRESULT register_namespace_extensions(struct regsvr_namespace const *list) {
434     WCHAR *pwszKey;
435     HKEY hKey;
436     
437     for (; list->clsid; list++) {
438         pwszKey = get_namespace_key(list);
439             
440         /* Create the key and set the value. */
441         if (pwszKey && ERROR_SUCCESS == 
442             RegCreateKeyExW(HKEY_LOCAL_MACHINE, pwszKey, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL)) 
443         {
444             RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE)list->value, sizeof(WCHAR)*(lstrlenW(list->value)+1));
445             RegCloseKey(hKey);
446         }
447
448         HeapFree(GetProcessHeap(), 0, pwszKey);
449     }
450     return S_OK;
451 }
452
453 static HRESULT unregister_namespace_extensions(struct regsvr_namespace const *list) {
454     WCHAR *pwszKey;
455     
456     for (; list->clsid; list++) {
457         pwszKey = get_namespace_key(list);
458         RegDeleteKeyW(HKEY_LOCAL_MACHINE, pwszKey);
459         HeapFree(GetProcessHeap(), 0, pwszKey);
460     }
461     return S_OK;
462 }
463
464 /***********************************************************************
465  *              regsvr_key_guid
466  */
467 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
468 {
469     WCHAR buf[39];
470
471     StringFromGUID2(guid, buf, 39);
472     return register_key_defvalueW(base, name, buf);
473 }
474
475 /***********************************************************************
476  *              regsvr_key_defvalueW
477  */
478 static LONG register_key_defvalueW(
479     HKEY base,
480     WCHAR const *name,
481     WCHAR const *value)
482 {
483     LONG res;
484     HKEY key;
485
486     res = RegCreateKeyExW(base, name, 0, NULL, 0,
487                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
488     if (res != ERROR_SUCCESS) return res;
489     res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
490                          (lstrlenW(value) + 1) * sizeof(WCHAR));
491     RegCloseKey(key);
492     return res;
493 }
494
495 /***********************************************************************
496  *              regsvr_key_defvalueA
497  */
498 static LONG register_key_defvalueA(
499     HKEY base,
500     WCHAR const *name,
501     char const *value)
502 {
503     LONG res;
504     HKEY key;
505
506     res = RegCreateKeyExW(base, name, 0, NULL, 0,
507                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
508     if (res != ERROR_SUCCESS) return res;
509     res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
510                          lstrlenA(value) + 1);
511     RegCloseKey(key);
512     return res;
513 }
514
515 /***********************************************************************
516  *              recursive_delete_key
517  */
518 static LONG recursive_delete_key(HKEY key)
519 {
520     LONG res;
521     WCHAR subkey_name[MAX_PATH];
522     DWORD cName;
523     HKEY subkey;
524
525     for (;;) {
526         cName = sizeof(subkey_name) / sizeof(WCHAR);
527         res = RegEnumKeyExW(key, 0, subkey_name, &cName,
528                             NULL, NULL, NULL, NULL);
529         if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
530             res = ERROR_SUCCESS; /* presumably we're done enumerating */
531             break;
532         }
533         res = RegOpenKeyExW(key, subkey_name, 0,
534                             KEY_READ | KEY_WRITE, &subkey);
535         if (res == ERROR_FILE_NOT_FOUND) continue;
536         if (res != ERROR_SUCCESS) break;
537
538         res = recursive_delete_key(subkey);
539         RegCloseKey(subkey);
540         if (res != ERROR_SUCCESS) break;
541     }
542
543     if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
544     return res;
545 }
546
547 /***********************************************************************
548  *              recursive_delete_keyA
549  */
550 static LONG recursive_delete_keyA(HKEY base, char const *name)
551 {
552     LONG res;
553     HKEY key;
554
555     res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
556     if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
557     if (res != ERROR_SUCCESS) return res;
558     res = recursive_delete_key(key);
559     RegCloseKey(key);
560     return res;
561 }
562
563 /***********************************************************************
564  *              recursive_delete_keyW
565  */
566 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
567 {
568     LONG res;
569     HKEY key;
570
571     res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
572     if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
573     if (res != ERROR_SUCCESS) return res;
574     res = recursive_delete_key(key);
575     RegCloseKey(key);
576     return res;
577 }
578
579 /***********************************************************************
580  *              coclass list
581  */
582 static GUID const CLSID_Desktop = {
583     0x00021400, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
584
585 static GUID const CLSID_Shortcut = {
586     0x00021401, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
587
588 static struct regsvr_coclass const coclass_list[] = {
589     {   &CLSID_Desktop,
590         "Desktop",
591         IDS_DESKTOP,
592         NULL,
593         "shell32.dll",
594         "Apartment"
595     },
596     {   &CLSID_DragDropHelper,
597         "Shell Drag and Drop Helper",
598         0,
599         NULL,
600         "shell32.dll",
601         "Apartment"
602     },
603     {   &CLSID_MyComputer,
604         "My Computer",
605         IDS_MYCOMPUTER,
606         NULL,
607         "shell32.dll",
608         "Apartment"
609     },
610     {   &CLSID_Shortcut,
611         "Shortcut",
612         0,
613         NULL,
614         "shell32.dll",
615         "Apartment",
616         SHELLEX_MAYCHANGEDEFAULTMENU
617     },
618     {   &CLSID_AutoComplete,
619         "AutoComplete",
620         0,
621         NULL,
622         "shell32.dll",
623         "Apartment",
624     },
625     {   &CLSID_UnixFolder,
626         "/",
627         0,
628         NULL,
629         "shell32.dll",
630         "Apartment",
631         SHELLFOLDER_WANTSFORPARSING
632     },
633     {   &CLSID_UnixDosFolder,
634         "/",
635         0,
636         NULL,
637         "shell32.dll",
638         "Apartment",
639         SHELLFOLDER_WANTSFORPARSING|SHELLFOLDER_ATTRIBUTES|SHELLFOLDER_CALLFORATTRIBUTES,
640         SFGAO_FILESYSANCESTOR|SFGAO_FOLDER|SFGAO_HASSUBFOLDER,
641         SFGAO_FILESYSTEM
642     },
643     {   &CLSID_FolderShortcut,
644         "Foldershortcut",
645         0,
646         NULL,
647         "shell32.dll",
648         "Apartment",
649         SHELLFOLDER_ATTRIBUTES|SHELLFOLDER_CALLFORATTRIBUTES,
650         SFGAO_FILESYSTEM|SFGAO_FOLDER|SFGAO_LINK,
651         SFGAO_HASSUBFOLDER|SFGAO_FILESYSTEM|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR
652     },
653     {   &CLSID_MyDocuments,
654         "My Documents",
655         IDS_PERSONAL,
656         NULL,
657         "shell32.dll",
658         "Apartment",
659         SHELLFOLDER_WANTSFORPARSING|SHELLFOLDER_ATTRIBUTES|SHELLFOLDER_CALLFORATTRIBUTES,
660         SFGAO_FILESYSANCESTOR|SFGAO_FOLDER|SFGAO_HASSUBFOLDER,
661         SFGAO_FILESYSTEM
662     },
663     { NULL }                    /* list terminator */
664 };
665
666 /***********************************************************************
667  *              interface list
668  */
669
670 static struct regsvr_interface const interface_list[] = {
671     { NULL }                    /* list terminator */
672 };
673
674 /***********************************************************************
675  *              namespace extensions list
676  */
677 static const WCHAR wszDesktop[] = { 'D','e','s','k','t','o','p',0 };
678 static const WCHAR wszSlash[] = { '/', 0 };
679 static const WCHAR wszMyDocuments[] = { 'M','y',' ','D','o','c','u','m','e','n','t','s', 0 };
680
681 static struct regsvr_namespace const namespace_extensions_list[] = {
682     {   
683         &CLSID_UnixDosFolder,
684         wszDesktop,
685         wszSlash
686     },
687     {   
688         &CLSID_MyDocuments,
689         wszDesktop,
690         wszMyDocuments
691     },
692     { NULL }
693 };
694
695 /***********************************************************************
696  *              DllRegisterServer (SHELL32.@)
697  */
698 HRESULT WINAPI DllRegisterServer(void)
699 {
700     HRESULT hr;
701
702     TRACE("\n");
703
704     hr = register_coclasses(coclass_list);
705     if (SUCCEEDED(hr))
706         hr = register_interfaces(interface_list);
707     if (SUCCEEDED(hr))
708         hr = SHELL_RegisterShellFolders();
709     if (SUCCEEDED(hr))
710         hr = register_namespace_extensions(namespace_extensions_list);
711     return hr;
712 }
713
714 /***********************************************************************
715  *              DllUnregisterServer (SHELL32.@)
716  */
717 HRESULT WINAPI DllUnregisterServer(void)
718 {
719     HRESULT hr;
720
721     TRACE("\n");
722
723     hr = unregister_coclasses(coclass_list);
724     if (SUCCEEDED(hr))
725         hr = unregister_interfaces(interface_list);
726     if (SUCCEEDED(hr))
727         hr = unregister_namespace_extensions(namespace_extensions_list);
728     return hr;
729 }