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
36 #include "shell32_main.h"
41 #include "wine/debug.h"
42 #include "wine/unicode.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
47 * Near the bottom of this file are the exported DllRegisterServer and
48 * DllUnregisterServer, which make all this worthwhile.
51 /***********************************************************************
52 * interface for self-registering
54 struct regsvr_interface
56 IID
const *iid
; /* NULL for end of list */
57 LPCSTR name
; /* can be NULL to omit */
58 IID
const *base_iid
; /* can be NULL to omit */
59 int num_methods
; /* can be <0 to omit */
60 CLSID
const *ps_clsid
; /* can be NULL to omit */
61 CLSID
const *ps_clsid32
; /* can be NULL to omit */
64 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
65 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
69 CLSID
const *clsid
; /* NULL for end of list */
70 LPCSTR name
; /* can be NULL to omit */
71 UINT idName
; /* can be 0 to omit */
72 LPCSTR ips
; /* can be NULL to omit */
73 LPCSTR ips32
; /* can be NULL to omit */
74 LPCSTR ips32_tmodel
; /* can be NULL to omit */
77 DWORD dwCallForAttributes
;
78 LPCSTR clsid_str
; /* can be NULL to omit */
79 LPCSTR progid
; /* can be NULL to omit */
80 LPCSTR viprogid
; /* can be NULL to omit */
81 LPCSTR progid_extra
; /* can be NULL to omit */
82 UINT idDefaultIcon
; /* can be 0 to omit */
85 /* flags for regsvr_coclass.flags */
86 #define SHELLEX_MAYCHANGEDEFAULTMENU 0x00000001
87 #define SHELLFOLDER_WANTSFORPARSING 0x00000002
88 #define SHELLFOLDER_WANTSFORDISPLAY 0x00000004
89 #define SHELLFOLDER_ATTRIBUTES 0x00000008
90 #define SHELLFOLDER_CALLFORATTRIBUTES 0x00000010
91 #define SHELLFOLDER_HIDEASDELETE 0x00000020
93 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
94 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
96 struct regsvr_namespace
98 CLSID
const *clsid
; /* CLSID of the namespace extension. NULL for end of list */
99 LPCWSTR parent
; /* Mount point (MyComputer, Desktop, ..). */
100 LPCWSTR value
; /* Display name of the extension. */
103 static HRESULT
register_namespace_extensions(struct regsvr_namespace
const *list
);
104 static HRESULT
unregister_namespace_extensions(struct regsvr_namespace
const *list
);
106 /***********************************************************************
107 * static string constants
109 static WCHAR
const interface_keyname
[10] = {
110 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
111 static WCHAR
const base_ifa_keyname
[14] = {
112 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
114 static WCHAR
const num_methods_keyname
[11] = {
115 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
116 static WCHAR
const ps_clsid_keyname
[15] = {
117 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
119 static WCHAR
const ps_clsid32_keyname
[17] = {
120 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
121 'i', 'd', '3', '2', 0 };
122 static WCHAR
const clsid_keyname
[6] = {
123 'C', 'L', 'S', 'I', 'D', 0 };
124 static WCHAR
const curver_keyname
[7] = {
125 'C', 'u', 'r', 'V', 'e', 'r', 0 };
126 static WCHAR
const ips_keyname
[13] = {
127 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
129 static WCHAR
const ips32_keyname
[15] = {
130 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
132 static WCHAR
const progid_keyname
[7] = {
133 'P', 'r', 'o', 'g', 'I', 'D', 0 };
134 static WCHAR
const viprogid_keyname
[25] = {
135 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
136 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
138 static WCHAR
const shellex_keyname
[8] = {
139 's', 'h', 'e', 'l', 'l', 'e', 'x', 0 };
140 static WCHAR
const shellfolder_keyname
[12] = {
141 'S', 'h', 'e', 'l', 'l', 'F', 'o', 'l', 'd', 'e', 'r', 0 };
142 static WCHAR
const mcdm_keyname
[21] = {
143 'M', 'a', 'y', 'C', 'h', 'a', 'n', 'g', 'e', 'D', 'e', 'f',
144 'a', 'u', 'l', 't', 'M', 'e', 'n', 'u', 0 };
145 static WCHAR
const defaulticon_keyname
[] = {
146 'D','e','f','a','u','l','t','I','c','o','n',0};
147 static char const tmodel_valuename
[] = "ThreadingModel";
148 static char const wfparsing_valuename
[] = "WantsFORPARSING";
149 static char const wfdisplay_valuename
[] = "WantsFORDISPLAY";
150 static char const attributes_valuename
[] = "Attributes";
151 static char const cfattributes_valuename
[] = "CallForAttributes";
152 static char const localized_valuename
[] = "LocalizedString";
153 static char const hideasdelete_valuename
[] = "HideAsDeletePerUser";
155 /***********************************************************************
156 * static helper functions
158 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
159 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
161 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
163 static LONG
register_progid(WCHAR
const *clsid
,
164 char const *progid
, char const *curver_progid
,
165 char const *name
, char const *extra
);
167 /***********************************************************************
168 * register_interfaces
170 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
172 LONG res
= ERROR_SUCCESS
;
175 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
176 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
177 if (res
!= ERROR_SUCCESS
) goto error_return
;
179 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
183 StringFromGUID2(list
->iid
, buf
, 39);
184 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
185 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
186 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
189 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
190 (CONST BYTE
*)(list
->name
),
191 strlen(list
->name
) + 1);
192 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
195 if (list
->base_iid
) {
196 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
197 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
200 if (0 <= list
->num_methods
) {
201 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
204 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
205 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
206 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
208 sprintfW(buf
, fmt
, list
->num_methods
);
209 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
211 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
214 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
217 if (list
->ps_clsid
) {
218 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
219 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
222 if (list
->ps_clsid32
) {
223 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
224 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
228 RegCloseKey(iid_key
);
231 error_close_interface_key
:
232 RegCloseKey(interface_key
);
234 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
237 /***********************************************************************
238 * unregister_interfaces
240 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
242 LONG res
= ERROR_SUCCESS
;
245 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
246 KEY_READ
| KEY_WRITE
, &interface_key
);
247 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
248 if (res
!= ERROR_SUCCESS
) goto error_return
;
250 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
253 StringFromGUID2(list
->iid
, buf
, 39);
254 res
= RegDeleteTreeW(interface_key
, buf
);
255 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
258 RegCloseKey(interface_key
);
260 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
263 /***********************************************************************
266 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
268 LONG res
= ERROR_SUCCESS
;
271 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
272 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
273 if (res
!= ERROR_SUCCESS
) goto error_return
;
275 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
279 StringFromGUID2(list
->clsid
, buf
, 39);
280 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
281 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
282 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
285 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
286 (CONST BYTE
*)(list
->name
),
287 strlen(list
->name
) + 1);
288 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
293 sprintf(buffer
, "@shell32.dll,-%u", list
->idName
);
294 res
= RegSetValueExA(clsid_key
, localized_valuename
, 0, REG_SZ
,
295 (CONST BYTE
*)(buffer
), strlen(buffer
)+1);
296 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
299 if (list
->idDefaultIcon
) {
303 res
= RegCreateKeyExW(clsid_key
, defaulticon_keyname
, 0, NULL
, 0,
304 KEY_READ
| KEY_WRITE
, NULL
, &icon_key
, NULL
);
305 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
307 sprintf(buffer
, "shell32.dll,-%u", list
->idDefaultIcon
);
308 res
= RegSetValueExA(icon_key
, NULL
, 0, REG_SZ
,
309 (CONST BYTE
*)(buffer
), strlen(buffer
)+1);
310 RegCloseKey(icon_key
);
311 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
315 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
316 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
322 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
323 KEY_READ
| KEY_WRITE
, NULL
,
325 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
327 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
328 (CONST BYTE
*)list
->ips32
,
329 lstrlenA(list
->ips32
) + 1);
330 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
331 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
332 (CONST BYTE
*)list
->ips32_tmodel
,
333 strlen(list
->ips32_tmodel
) + 1);
334 RegCloseKey(ips32_key
);
335 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
338 if (list
->flags
& SHELLEX_MAYCHANGEDEFAULTMENU
) {
339 HKEY shellex_key
, mcdm_key
;
341 res
= RegCreateKeyExW(clsid_key
, shellex_keyname
, 0, NULL
, 0,
342 KEY_READ
| KEY_WRITE
, NULL
,
344 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
345 res
= RegCreateKeyExW(shellex_key
, mcdm_keyname
, 0, NULL
, 0,
346 KEY_READ
| KEY_WRITE
, NULL
,
348 RegCloseKey(shellex_key
);
349 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
350 RegCloseKey(mcdm_key
);
354 (SHELLFOLDER_WANTSFORPARSING
|SHELLFOLDER_WANTSFORDISPLAY
|SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_CALLFORATTRIBUTES
|SHELLFOLDER_HIDEASDELETE
))
356 HKEY shellfolder_key
;
358 res
= RegCreateKeyExW(clsid_key
, shellfolder_keyname
, 0, NULL
, 0,
359 KEY_READ
| KEY_WRITE
, NULL
,
360 &shellfolder_key
, NULL
);
361 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
362 if (list
->flags
& SHELLFOLDER_WANTSFORPARSING
)
363 res
= RegSetValueExA(shellfolder_key
, wfparsing_valuename
, 0, REG_SZ
, (const BYTE
*)"", 1);
364 if (list
->flags
& SHELLFOLDER_WANTSFORDISPLAY
)
365 res
= RegSetValueExA(shellfolder_key
, wfdisplay_valuename
, 0, REG_SZ
, (const BYTE
*)"", 1);
366 if (list
->flags
& SHELLFOLDER_HIDEASDELETE
)
367 res
= RegSetValueExA(shellfolder_key
, hideasdelete_valuename
, 0, REG_SZ
, (const BYTE
*)"", 1);
368 if (list
->flags
& SHELLFOLDER_ATTRIBUTES
)
369 res
= RegSetValueExA(shellfolder_key
, attributes_valuename
, 0, REG_DWORD
,
370 (const BYTE
*)&list
->dwAttributes
, sizeof(DWORD
));
371 if (list
->flags
& SHELLFOLDER_CALLFORATTRIBUTES
)
372 res
= RegSetValueExA(shellfolder_key
, cfattributes_valuename
, 0, REG_DWORD
,
373 (const BYTE
*)&list
->dwCallForAttributes
, sizeof(DWORD
));
374 RegCloseKey(shellfolder_key
);
375 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
378 if (list
->clsid_str
) {
379 res
= register_key_defvalueA(clsid_key
, clsid_keyname
,
381 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
387 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
389 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
391 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, list
->progid
, 0,
392 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
394 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
396 res
= register_key_defvalueW(progid_key
, clsid_keyname
, buf
);
397 RegCloseKey(progid_key
);
398 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
401 if (list
->viprogid
) {
402 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
404 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
406 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
407 list
->name
, list
->progid_extra
);
408 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
411 error_close_clsid_key
:
412 RegCloseKey(clsid_key
);
415 error_close_coclass_key
:
416 RegCloseKey(coclass_key
);
418 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
421 /***********************************************************************
422 * unregister_coclasses
424 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
426 LONG res
= ERROR_SUCCESS
;
429 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
430 KEY_READ
| KEY_WRITE
, &coclass_key
);
431 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
432 if (res
!= ERROR_SUCCESS
) goto error_return
;
434 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
437 StringFromGUID2(list
->clsid
, buf
, 39);
438 res
= RegDeleteTreeW(coclass_key
, buf
);
439 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
440 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
443 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
444 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
445 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
448 if (list
->viprogid
) {
449 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
450 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
451 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
455 error_close_coclass_key
:
456 RegCloseKey(coclass_key
);
458 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
461 /**********************************************************************
462 * register_namespace_extensions
464 static WCHAR
*get_namespace_key(struct regsvr_namespace
const *list
) {
465 static const WCHAR wszExplorerKey
[] = {
466 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
467 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
468 'E','x','p','l','o','r','e','r','\\',0 };
469 static const WCHAR wszNamespace
[] = { '\\','N','a','m','e','s','p','a','c','e','\\',0 };
470 WCHAR
*pwszKey
, *pwszCLSID
;
472 pwszKey
= HeapAlloc(GetProcessHeap(), 0, sizeof(wszExplorerKey
)+sizeof(wszNamespace
)+
473 sizeof(WCHAR
)*(lstrlenW(list
->parent
)+CHARS_IN_GUID
));
477 lstrcpyW(pwszKey
, wszExplorerKey
);
478 lstrcatW(pwszKey
, list
->parent
);
479 lstrcatW(pwszKey
, wszNamespace
);
480 if (FAILED(StringFromCLSID(list
->clsid
, &pwszCLSID
))) {
481 HeapFree(GetProcessHeap(), 0, pwszKey
);
484 lstrcatW(pwszKey
, pwszCLSID
);
485 CoTaskMemFree(pwszCLSID
);
490 static HRESULT
register_namespace_extensions(struct regsvr_namespace
const *list
) {
494 for (; list
->clsid
; list
++) {
495 pwszKey
= get_namespace_key(list
);
497 /* Create the key and set the value. */
498 if (pwszKey
&& ERROR_SUCCESS
==
499 RegCreateKeyExW(HKEY_LOCAL_MACHINE
, pwszKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
))
501 RegSetValueExW(hKey
, NULL
, 0, REG_SZ
, (const BYTE
*)list
->value
, sizeof(WCHAR
)*(lstrlenW(list
->value
)+1));
505 HeapFree(GetProcessHeap(), 0, pwszKey
);
510 static HRESULT
unregister_namespace_extensions(struct regsvr_namespace
const *list
) {
513 for (; list
->clsid
; list
++) {
514 pwszKey
= get_namespace_key(list
);
515 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, pwszKey
);
516 HeapFree(GetProcessHeap(), 0, pwszKey
);
521 /***********************************************************************
524 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
528 StringFromGUID2(guid
, buf
, 39);
529 return register_key_defvalueW(base
, name
, buf
);
532 /***********************************************************************
533 * regsvr_key_defvalueW
535 static LONG
register_key_defvalueW(
543 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
544 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
545 if (res
!= ERROR_SUCCESS
) return res
;
546 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
547 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
552 /***********************************************************************
553 * regsvr_key_defvalueA
555 static LONG
register_key_defvalueA(
563 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
564 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
565 if (res
!= ERROR_SUCCESS
) return res
;
566 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
567 lstrlenA(value
) + 1);
572 /***********************************************************************
575 static LONG
register_progid(
578 char const *curver_progid
,
584 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
585 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
587 if (res
!= ERROR_SUCCESS
) return res
;
590 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
591 (CONST BYTE
*)name
, strlen(name
) + 1);
592 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
596 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
597 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
601 res
= register_key_defvalueA(progid_key
, curver_keyname
,
603 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
609 res
= RegCreateKeyExA(progid_key
, extra
, 0,
610 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
612 if (res
== ERROR_SUCCESS
)
613 RegCloseKey(extra_key
);
616 error_close_progid_key
:
617 RegCloseKey(progid_key
);
621 /***********************************************************************
624 static GUID
const CLSID_Desktop
= {
625 0x00021400, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
627 static GUID
const CLSID_Shortcut
= {
628 0x00021401, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
630 static struct regsvr_coclass
const coclass_list
[] = {
638 { &CLSID_DragDropHelper
,
639 "Shell Drag and Drop Helper",
652 { &CLSID_NetworkPlaces
,
665 SHELLEX_MAYCHANGEDEFAULTMENU
667 { &CLSID_AutoComplete
,
680 SHELLFOLDER_WANTSFORPARSING
682 { &CLSID_UnixDosFolder
,
688 SHELLFOLDER_WANTSFORPARSING
|SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_CALLFORATTRIBUTES
,
689 SFGAO_FILESYSANCESTOR
|SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
,
692 { &CLSID_FolderShortcut
,
698 SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_CALLFORATTRIBUTES
,
699 SFGAO_FILESYSTEM
|SFGAO_FOLDER
|SFGAO_LINK
,
700 SFGAO_HASSUBFOLDER
|SFGAO_FILESYSTEM
|SFGAO_FOLDER
|SFGAO_FILESYSANCESTOR
702 { &CLSID_MyDocuments
,
708 SHELLFOLDER_WANTSFORPARSING
|SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_CALLFORATTRIBUTES
,
709 SFGAO_FILESYSANCESTOR
|SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
,
714 IDS_RECYCLEBIN_FOLDER_NAME
,
718 SHELLFOLDER_ATTRIBUTES
,
719 SFGAO_FOLDER
|SFGAO_DROPTARGET
|SFGAO_HASPROPSHEET
,
725 IDI_SHELL_FULL_RECYCLE_BIN
727 { &CLSID_ShellFSFolder
,
728 "Shell File System Folder",
734 { &CLSID_ShellFolderViewOC
,
735 "Microsoft Shell Folder View Router",
741 { &CLSID_QueryAssociations
,
742 "Query file associations",
748 { &CLSID_ControlPanel
,
754 SHELLFOLDER_WANTSFORDISPLAY
|SHELLFOLDER_ATTRIBUTES
|SHELLFOLDER_HIDEASDELETE
,
755 SFGAO_FOLDER
|SFGAO_HASSUBFOLDER
,
758 "Printers and Faxes",
764 { &CLSID_ExplorerBrowser
,
771 { &CLSID_KnownFolderManager
,
772 "Known Folder Manager",
779 "Shell Automation Service",
788 "Shell.Application.1",
791 { NULL
} /* list terminator */
794 /***********************************************************************
798 static struct regsvr_interface
const interface_list
[] = {
799 { NULL
} /* list terminator */
802 /***********************************************************************
803 * namespace extensions list
805 static const WCHAR wszDesktop
[] = { 'D','e','s','k','t','o','p',0 };
806 static const WCHAR wszSlash
[] = { '/', 0 };
807 static const WCHAR wszMyDocuments
[] = { 'M','y',' ','D','o','c','u','m','e','n','t','s', 0 };
808 static const WCHAR wszRecycleBin
[] = { 'T','r','a','s','h', 0 };
809 static const WCHAR wszMyComputer
[] = { 'M','y','C','o','m','p','u','t','e','r', 0 };
810 static const WCHAR wszControlPanel
[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l', 0 };
812 static struct regsvr_namespace
const namespace_extensions_list
[] = {
814 &CLSID_UnixDosFolder
,
836 /***********************************************************************
837 * DllRegisterServer (SHELL32.@)
839 HRESULT WINAPI
DllRegisterServer(void)
843 static const WCHAR wszShell32
[] = { 's','h','e','l','l','3','2','.','d','l','l', 0 };
847 hr
= register_coclasses(coclass_list
);
849 hr
= register_interfaces(interface_list
);
851 hr
= SHELL_RegisterShellFolders();
853 hr
= register_namespace_extensions(namespace_extensions_list
);
856 hr
= LoadTypeLibEx(wszShell32
, REGKIND_REGISTER
, &tl
);
858 ITypeLib_Release(tl
);
863 /***********************************************************************
864 * DllUnregisterServer (SHELL32.@)
866 HRESULT WINAPI
DllUnregisterServer(void)
872 hr
= unregister_coclasses(coclass_list
);
874 hr
= unregister_interfaces(interface_list
);
876 hr
= unregister_namespace_extensions(namespace_extensions_list
);
878 hr
= UnRegisterTypeLib(&LIBID_Shell32
, 1, 0, LOCALE_SYSTEM_DEFAULT
,