2 * self-registerable dll functions for shell32.dll
4 * Copyright (C) 2003 John K. Hohm
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.
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.
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
34 #include "shell32_main.h"
39 #include "wine/debug.h"
40 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
45 * Near the bottom of this file are the exported DllRegisterServer and
46 * DllUnregisterServer, which make all this worthwhile.
49 /***********************************************************************
50 * interface for self-registering
52 struct regsvr_interface
54 IID
const *iid
; /* NULL for end of list */
55 LPCSTR name
; /* can be NULL to omit */
56 IID
const *base_iid
; /* can be NULL to omit */
57 int num_methods
; /* can be <0 to omit */
58 CLSID
const *ps_clsid
; /* can be NULL to omit */
59 CLSID
const *ps_clsid32
; /* can be NULL to omit */
62 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
63 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
67 CLSID
const *clsid
; /* NULL for end of list */
68 LPCSTR name
; /* can be NULL to omit */
69 UINT idName
; /* can be 0 to omit */
70 LPCSTR ips
; /* can be NULL to omit */
71 LPCSTR ips32
; /* can be NULL to omit */
72 LPCSTR ips32_tmodel
; /* can be NULL to omit */
75 DWORD dwCallForAttributes
;
76 LPCSTR clsid_str
; /* can be NULL to omit */
77 LPCSTR progid
; /* can be NULL to omit */
78 LPCSTR viprogid
; /* can be NULL to omit */
79 LPCSTR progid_extra
; /* can be NULL to omit */
80 UINT idDefaultIcon
; /* can be 0 to omit */
83 /* flags for regsvr_coclass.flags */
84 #define SHELLEX_MAYCHANGEDEFAULTMENU 0x00000001
85 #define SHELLFOLDER_WANTSFORPARSING 0x00000002
86 #define SHELLFOLDER_WANTSFORDISPLAY 0x00000004
87 #define SHELLFOLDER_ATTRIBUTES 0x00000008
88 #define SHELLFOLDER_CALLFORATTRIBUTES 0x00000010
89 #define SHELLFOLDER_HIDEASDELETE 0x00000020
91 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
92 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
94 struct regsvr_namespace
96 CLSID
const *clsid
; /* CLSID of the namespace extension. NULL for end of list */
97 LPCWSTR parent
; /* Mount point (MyComputer, Desktop, ..). */
98 LPCWSTR value
; /* Display name of the extension. */
101 static HRESULT
register_namespace_extensions(struct regsvr_namespace
const *list
);
102 static HRESULT
unregister_namespace_extensions(struct regsvr_namespace
const *list
);
104 /***********************************************************************
105 * static string constants
107 static WCHAR
const interface_keyname
[10] = {
108 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
109 static WCHAR
const base_ifa_keyname
[14] = {
110 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
112 static WCHAR
const num_methods_keyname
[11] = {
113 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
114 static WCHAR
const ps_clsid_keyname
[15] = {
115 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
117 static WCHAR
const ps_clsid32_keyname
[17] = {
118 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
119 'i', 'd', '3', '2', 0 };
120 static WCHAR
const clsid_keyname
[6] = {
121 'C', 'L', 'S', 'I', 'D', 0 };
122 static WCHAR
const curver_keyname
[7] = {
123 'C', 'u', 'r', 'V', 'e', 'r', 0 };
124 static WCHAR
const ips_keyname
[13] = {
125 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
127 static WCHAR
const ips32_keyname
[15] = {
128 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
130 static WCHAR
const progid_keyname
[7] = {
131 'P', 'r', 'o', 'g', 'I', 'D', 0 };
132 static WCHAR
const viprogid_keyname
[25] = {
133 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
134 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
136 static WCHAR
const shellex_keyname
[8] = {
137 's', 'h', 'e', 'l', 'l', 'e', 'x', 0 };
138 static WCHAR
const shellfolder_keyname
[12] = {
139 'S', 'h', 'e', 'l', 'l', 'F', 'o', 'l', 'd', 'e', 'r', 0 };
140 static WCHAR
const mcdm_keyname
[21] = {
141 'M', 'a', 'y', 'C', 'h', 'a', 'n', 'g', 'e', 'D', 'e', 'f',
142 'a', 'u', 'l', 't', 'M', 'e', 'n', 'u', 0 };
143 static WCHAR
const defaulticon_keyname
[] = {
144 'D','e','f','a','u','l','t','I','c','o','n',0};
145 static char const tmodel_valuename
[] = "ThreadingModel";
146 static char const wfparsing_valuename
[] = "WantsFORPARSING";
147 static char const wfdisplay_valuename
[] = "WantsFORDISPLAY";
148 static char const attributes_valuename
[] = "Attributes";
149 static char const cfattributes_valuename
[] = "CallForAttributes";
150 static char const localized_valuename
[] = "LocalizedString";
151 static char const hideasdelete_valuename
[] = "HideAsDeletePerUser";
153 /***********************************************************************
154 * static helper functions
156 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
157 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
159 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
161 static LONG
register_progid(WCHAR
const *clsid
,
162 char const *progid
, char const *curver_progid
,
163 char const *name
, char const *extra
);
165 /***********************************************************************
166 * register_interfaces
168 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
170 LONG res
= ERROR_SUCCESS
;
173 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
174 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
175 if (res
!= ERROR_SUCCESS
) goto error_return
;
177 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
181 StringFromGUID2(list
->iid
, buf
, 39);
182 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
183 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
184 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
187 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
188 (CONST BYTE
*)(list
->name
),
189 strlen(list
->name
) + 1);
190 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
193 if (list
->base_iid
) {
194 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
195 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
198 if (0 <= list
->num_methods
) {
199 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
202 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
203 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
204 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
206 sprintfW(buf
, fmt
, list
->num_methods
);
207 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
209 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
212 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
215 if (list
->ps_clsid
) {
216 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
217 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
220 if (list
->ps_clsid32
) {
221 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
222 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
226 RegCloseKey(iid_key
);
229 error_close_interface_key
:
230 RegCloseKey(interface_key
);
232 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
235 /***********************************************************************
236 * unregister_interfaces
238 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
240 LONG res
= ERROR_SUCCESS
;
243 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
244 KEY_READ
| KEY_WRITE
, &interface_key
);
245 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
246 if (res
!= ERROR_SUCCESS
) goto error_return
;
248 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
251 StringFromGUID2(list
->iid
, buf
, 39);
252 res
= RegDeleteTreeW(interface_key
, buf
);
253 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
256 RegCloseKey(interface_key
);
258 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
261 /***********************************************************************
264 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
266 LONG res
= ERROR_SUCCESS
;
269 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
270 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
271 if (res
!= ERROR_SUCCESS
) goto error_return
;
273 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
277 StringFromGUID2(list
->clsid
, buf
, 39);
278 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
279 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
280 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
283 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
284 (CONST BYTE
*)(list
->name
),
285 strlen(list
->name
) + 1);
286 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
291 sprintf(buffer
, "@shell32.dll,-%u", list
->idName
);
292 res
= RegSetValueExA(clsid_key
, localized_valuename
, 0, REG_SZ
,
293 (CONST BYTE
*)(buffer
), strlen(buffer
)+1);
294 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
297 if (list
->idDefaultIcon
) {
301 res
= RegCreateKeyExW(clsid_key
, defaulticon_keyname
, 0, NULL
, 0,
302 KEY_READ
| KEY_WRITE
, NULL
, &icon_key
, NULL
);
303 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
305 sprintf(buffer
, "shell32.dll,-%u", list
->idDefaultIcon
);
306 res
= RegSetValueExA(icon_key
, NULL
, 0, REG_SZ
,
307 (CONST BYTE
*)(buffer
), strlen(buffer
)+1);
308 RegCloseKey(icon_key
);
309 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
313 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
314 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
320 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
321 KEY_READ
| KEY_WRITE
, NULL
,
323 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
325 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
326 (CONST BYTE
*)list
->ips32
,
327 lstrlenA(list
->ips32
) + 1);
328 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
329 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
330 (CONST BYTE
*)list
->ips32_tmodel
,
331 strlen(list
->ips32_tmodel
) + 1);
332 RegCloseKey(ips32_key
);
333 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
336 if (list
->flags
& SHELLEX_MAYCHANGEDEFAULTMENU
) {
337 HKEY shellex_key
, mcdm_key
;
339 res
= RegCreateKeyExW(clsid_key
, shellex_keyname
, 0, NULL
, 0,
340 KEY_READ
| KEY_WRITE
, NULL
,
342 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
343 res
= RegCreateKeyExW(shellex_key
, mcdm_keyname
, 0, NULL
, 0,
344 KEY_READ
| KEY_WRITE
, NULL
,
346 RegCloseKey(shellex_key
);
347 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
348 RegCloseKey(mcdm_key
);
352 (SHELLFOLDER_WANTSFORPARSING
|SHELLFOLDER_WANTSFORDISPLAY
|SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_CALLFORATTRIBUTES
|SHELLFOLDER_HIDEASDELETE
))
354 HKEY shellfolder_key
;
356 res
= RegCreateKeyExW(clsid_key
, shellfolder_keyname
, 0, NULL
, 0,
357 KEY_READ
| KEY_WRITE
, NULL
,
358 &shellfolder_key
, NULL
);
359 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
360 if (list
->flags
& SHELLFOLDER_WANTSFORPARSING
)
361 res
= RegSetValueExA(shellfolder_key
, wfparsing_valuename
, 0, REG_SZ
, (const BYTE
*)"", 1);
362 if (list
->flags
& SHELLFOLDER_WANTSFORDISPLAY
)
363 res
= RegSetValueExA(shellfolder_key
, wfdisplay_valuename
, 0, REG_SZ
, (const BYTE
*)"", 1);
364 if (list
->flags
& SHELLFOLDER_HIDEASDELETE
)
365 res
= RegSetValueExA(shellfolder_key
, hideasdelete_valuename
, 0, REG_SZ
, (const BYTE
*)"", 1);
366 if (list
->flags
& SHELLFOLDER_ATTRIBUTES
)
367 res
= RegSetValueExA(shellfolder_key
, attributes_valuename
, 0, REG_DWORD
,
368 (const BYTE
*)&list
->dwAttributes
, sizeof(DWORD
));
369 if (list
->flags
& SHELLFOLDER_CALLFORATTRIBUTES
)
370 res
= RegSetValueExA(shellfolder_key
, cfattributes_valuename
, 0, REG_DWORD
,
371 (const BYTE
*)&list
->dwCallForAttributes
, sizeof(DWORD
));
372 RegCloseKey(shellfolder_key
);
373 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
376 if (list
->clsid_str
) {
377 res
= register_key_defvalueA(clsid_key
, clsid_keyname
,
379 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
385 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
387 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
389 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, list
->progid
, 0,
390 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
392 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
394 res
= register_key_defvalueW(progid_key
, clsid_keyname
, buf
);
395 RegCloseKey(progid_key
);
396 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
399 if (list
->viprogid
) {
400 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
402 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
404 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
405 list
->name
, list
->progid_extra
);
406 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
409 error_close_clsid_key
:
410 RegCloseKey(clsid_key
);
413 error_close_coclass_key
:
414 RegCloseKey(coclass_key
);
416 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
419 /***********************************************************************
420 * unregister_coclasses
422 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
424 LONG res
= ERROR_SUCCESS
;
427 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
428 KEY_READ
| KEY_WRITE
, &coclass_key
);
429 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
430 if (res
!= ERROR_SUCCESS
) goto error_return
;
432 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
435 StringFromGUID2(list
->clsid
, buf
, 39);
436 res
= RegDeleteTreeW(coclass_key
, buf
);
437 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
438 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
441 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
442 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
443 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
446 if (list
->viprogid
) {
447 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
448 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
449 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
453 error_close_coclass_key
:
454 RegCloseKey(coclass_key
);
456 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
459 /**********************************************************************
460 * register_namespace_extensions
462 static WCHAR
*get_namespace_key(struct regsvr_namespace
const *list
) {
463 static const WCHAR wszExplorerKey
[] = {
464 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
465 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
466 'E','x','p','l','o','r','e','r','\\',0 };
467 static const WCHAR wszNamespace
[] = { '\\','N','a','m','e','s','p','a','c','e','\\',0 };
468 WCHAR
*pwszKey
, *pwszCLSID
;
470 pwszKey
= HeapAlloc(GetProcessHeap(), 0, sizeof(wszExplorerKey
)+sizeof(wszNamespace
)+
471 sizeof(WCHAR
)*(lstrlenW(list
->parent
)+CHARS_IN_GUID
));
475 lstrcpyW(pwszKey
, wszExplorerKey
);
476 lstrcatW(pwszKey
, list
->parent
);
477 lstrcatW(pwszKey
, wszNamespace
);
478 if (FAILED(StringFromCLSID(list
->clsid
, &pwszCLSID
))) {
479 HeapFree(GetProcessHeap(), 0, pwszKey
);
482 lstrcatW(pwszKey
, pwszCLSID
);
483 CoTaskMemFree(pwszCLSID
);
488 static HRESULT
register_namespace_extensions(struct regsvr_namespace
const *list
) {
492 for (; list
->clsid
; list
++) {
493 pwszKey
= get_namespace_key(list
);
495 /* Create the key and set the value. */
496 if (pwszKey
&& ERROR_SUCCESS
==
497 RegCreateKeyExW(HKEY_LOCAL_MACHINE
, pwszKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
))
499 RegSetValueExW(hKey
, NULL
, 0, REG_SZ
, (const BYTE
*)list
->value
, sizeof(WCHAR
)*(lstrlenW(list
->value
)+1));
503 HeapFree(GetProcessHeap(), 0, pwszKey
);
508 static HRESULT
unregister_namespace_extensions(struct regsvr_namespace
const *list
) {
511 for (; list
->clsid
; list
++) {
512 pwszKey
= get_namespace_key(list
);
513 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, pwszKey
);
514 HeapFree(GetProcessHeap(), 0, pwszKey
);
519 /***********************************************************************
522 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
526 StringFromGUID2(guid
, buf
, 39);
527 return register_key_defvalueW(base
, name
, buf
);
530 /***********************************************************************
531 * regsvr_key_defvalueW
533 static LONG
register_key_defvalueW(
541 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
542 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
543 if (res
!= ERROR_SUCCESS
) return res
;
544 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
545 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
550 /***********************************************************************
551 * regsvr_key_defvalueA
553 static LONG
register_key_defvalueA(
561 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
562 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
563 if (res
!= ERROR_SUCCESS
) return res
;
564 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
565 lstrlenA(value
) + 1);
570 /***********************************************************************
573 static LONG
register_progid(
576 char const *curver_progid
,
582 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
583 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
585 if (res
!= ERROR_SUCCESS
) return res
;
588 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
589 (CONST BYTE
*)name
, strlen(name
) + 1);
590 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
594 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
595 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
599 res
= register_key_defvalueA(progid_key
, curver_keyname
,
601 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
607 res
= RegCreateKeyExA(progid_key
, extra
, 0,
608 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
610 if (res
== ERROR_SUCCESS
)
611 RegCloseKey(extra_key
);
614 error_close_progid_key
:
615 RegCloseKey(progid_key
);
619 /***********************************************************************
622 static GUID
const CLSID_Desktop
= {
623 0x00021400, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
625 static GUID
const CLSID_Shortcut
= {
626 0x00021401, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
628 static struct regsvr_coclass
const coclass_list
[] = {
636 { &CLSID_DragDropHelper
,
637 "Shell Drag and Drop Helper",
650 { &CLSID_NetworkPlaces
,
663 SHELLEX_MAYCHANGEDEFAULTMENU
665 { &CLSID_AutoComplete
,
678 SHELLFOLDER_WANTSFORPARSING
680 { &CLSID_UnixDosFolder
,
686 SHELLFOLDER_WANTSFORPARSING
|SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_CALLFORATTRIBUTES
,
687 SFGAO_FILESYSANCESTOR
|SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
,
690 { &CLSID_FolderShortcut
,
696 SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_CALLFORATTRIBUTES
,
697 SFGAO_FILESYSTEM
|SFGAO_FOLDER
|SFGAO_LINK
,
698 SFGAO_HASSUBFOLDER
|SFGAO_FILESYSTEM
|SFGAO_FOLDER
|SFGAO_FILESYSANCESTOR
700 { &CLSID_MyDocuments
,
706 SHELLFOLDER_WANTSFORPARSING
|SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_CALLFORATTRIBUTES
,
707 SFGAO_FILESYSANCESTOR
|SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
,
712 IDS_RECYCLEBIN_FOLDER_NAME
,
716 SHELLFOLDER_ATTRIBUTES
,
717 SFGAO_FOLDER
|SFGAO_DROPTARGET
|SFGAO_HASPROPSHEET
,
723 IDI_SHELL_FULL_RECYCLE_BIN
725 { &CLSID_ShellFSFolder
,
726 "Shell File System Folder",
732 { &CLSID_ShellFolderViewOC
,
733 "Microsoft Shell Folder View Router",
739 { &CLSID_QueryAssociations
,
740 "Query file associations",
746 { &CLSID_ControlPanel
,
752 SHELLFOLDER_WANTSFORDISPLAY
|SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_HIDEASDELETE
,
753 SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
,
756 "Printers and Faxes",
762 { &CLSID_ExplorerBrowser
,
769 { &CLSID_KnownFolderManager
,
770 "Known Folder Manager",
777 "Shell Automation Service",
786 "Shell.Application.1",
789 { NULL
} /* list terminator */
792 /***********************************************************************
796 static struct regsvr_interface
const interface_list
[] = {
797 { NULL
} /* list terminator */
800 /***********************************************************************
801 * namespace extensions list
803 static const WCHAR wszDesktop
[] = { 'D','e','s','k','t','o','p',0 };
804 static const WCHAR wszSlash
[] = { '/', 0 };
805 static const WCHAR wszMyDocuments
[] = { 'M','y',' ','D','o','c','u','m','e','n','t','s', 0 };
806 static const WCHAR wszRecycleBin
[] = { 'T','r','a','s','h', 0 };
807 static const WCHAR wszMyComputer
[] = { 'M','y','C','o','m','p','u','t','e','r', 0 };
808 static const WCHAR wszControlPanel
[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l', 0 };
810 static struct regsvr_namespace
const namespace_extensions_list
[] = {
812 &CLSID_UnixDosFolder
,
834 /***********************************************************************
835 * DllRegisterServer (SHELL32.@)
837 HRESULT WINAPI
DllRegisterServer(void)
843 hr
= register_coclasses(coclass_list
);
845 hr
= register_interfaces(interface_list
);
847 hr
= SHELL_RegisterShellFolders();
849 hr
= register_namespace_extensions(namespace_extensions_list
);
853 /***********************************************************************
854 * DllUnregisterServer (SHELL32.@)
856 HRESULT WINAPI
DllUnregisterServer(void)
862 hr
= unregister_coclasses(coclass_list
);
864 hr
= unregister_interfaces(interface_list
);
866 hr
= unregister_namespace_extensions(namespace_extensions_list
);