3 * (HKEY_CLASSES_ROOT - Stuff)
5 * Copyright 1998, 1999, 2000 Juergen Schmied
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <wine/config.h>
26 #define WIN32_NO_STATUS
33 #include <shlguid_undoc.h>
35 #include <wine/debug.h>
36 #include <wine/unicode.h>
39 #include "shell32_main.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
44 #define MAX_EXTENSION_LENGTH 20
46 BOOL
HCR_MapTypeToValueW(LPCWSTR szExtension
, LPWSTR szFileType
, LONG len
, BOOL bPrependDot
)
49 WCHAR szTemp
[MAX_EXTENSION_LENGTH
+ 2];
51 TRACE("%s %p\n", debugstr_w(szExtension
), debugstr_w(szFileType
));
53 /* added because we do not want to have double dots */
54 if (szExtension
[0] == '.')
60 lstrcpynW(szTemp
+ (bPrependDot
?1:0), szExtension
, MAX_EXTENSION_LENGTH
);
62 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szTemp
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
65 if (RegQueryValueW(hkey
, NULL
, szFileType
, &len
) != ERROR_SUCCESS
)
73 TRACE("--UE;\n} %s\n", debugstr_w(szFileType
));
78 BOOL
HCR_MapTypeToValueA(LPCSTR szExtension
, LPSTR szFileType
, LONG len
, BOOL bPrependDot
)
81 char szTemp
[MAX_EXTENSION_LENGTH
+ 2];
83 TRACE("%s %p\n", szExtension
, szFileType
);
85 /* added because we do not want to have double dots */
86 if (szExtension
[0] == '.')
92 lstrcpynA(szTemp
+ (bPrependDot
?1:0), szExtension
, MAX_EXTENSION_LENGTH
);
94 if (RegOpenKeyExA(HKEY_CLASSES_ROOT
, szTemp
, 0, KEY_READ
, &hkey
))
99 if (RegLoadMUIStringA(hkey
, "FriendlyTypeName", szFileType
, len
, NULL
, 0, NULL
) == ERROR_SUCCESS
)
105 if (RegQueryValueA(hkey
, NULL
, szFileType
, &len
))
113 TRACE("--UE;\n} %s\n", szFileType
);
118 static const WCHAR swShell
[] = L
"shell\\";
119 static const WCHAR swOpen
[] = L
"open";
120 static const WCHAR swCommand
[] = L
"\\command";
122 BOOL
HCR_GetDefaultVerbW( HKEY hkeyClass
, LPCWSTR szVerb
, LPWSTR szDest
, DWORD len
)
124 WCHAR sTemp
[MAX_PATH
];
128 TRACE("%p %s %p\n", hkeyClass
, debugstr_w(szVerb
), szDest
);
130 if (szVerb
&& *szVerb
)
132 lstrcpynW(szDest
, szVerb
, len
);
138 if (RegQueryValueW(hkeyClass
, L
"shell", szDest
, &size
) == ERROR_SUCCESS
&& *szDest
)
140 /* The MSDN says to first try the default verb */
141 wcscpy(sTemp
, swShell
);
142 wcscat(sTemp
, szDest
);
143 wcscat(sTemp
, swCommand
);
144 if (RegOpenKeyExW(hkeyClass
, sTemp
, 0, KEY_READ
, &hkey
) == ERROR_SUCCESS
)
147 TRACE("default verb=%s\n", debugstr_w(szDest
));
152 /* then fallback to 'open' */
153 wcscpy(sTemp
, swShell
);
154 wcscat(sTemp
, swOpen
);
155 wcscat(sTemp
, swCommand
);
156 if (RegOpenKeyExW(hkeyClass
, sTemp
, 0, KEY_READ
, &hkey
) == ERROR_SUCCESS
)
159 lstrcpynW(szDest
, swOpen
, len
);
160 TRACE("default verb=open\n");
164 /* and then just use the first verb on Windows >= 2000 */
165 if (RegOpenKeyExW(hkeyClass
, L
"shell", 0, KEY_READ
, &hkey
) == ERROR_SUCCESS
)
167 if (RegEnumKeyW(hkey
, 0, szDest
, len
) == ERROR_SUCCESS
&& *szDest
)
169 TRACE("default verb=first verb=%s\n", debugstr_w(szDest
));
177 TRACE("no default verb!\n");
181 BOOL
HCR_GetExecuteCommandW( HKEY hkeyClass
, LPCWSTR szClass
, LPCWSTR szVerb
, LPWSTR szDest
, DWORD len
)
183 WCHAR sTempVerb
[MAX_PATH
];
186 TRACE("%p %s %s %p\n", hkeyClass
, debugstr_w(szClass
), debugstr_w(szVerb
), szDest
);
189 RegOpenKeyExW(HKEY_CLASSES_ROOT
, szClass
, 0, KEY_READ
, &hkeyClass
);
194 if (HCR_GetDefaultVerbW(hkeyClass
, szVerb
, sTempVerb
, sizeof(sTempVerb
)/sizeof(sTempVerb
[0])))
196 WCHAR sTemp
[MAX_PATH
];
197 wcscpy(sTemp
, swShell
);
198 wcscat(sTemp
, sTempVerb
);
199 wcscat(sTemp
, swCommand
);
200 ret
= (ERROR_SUCCESS
== SHGetValueW(hkeyClass
, sTemp
, NULL
, NULL
, szDest
, &len
));
203 RegCloseKey(hkeyClass
);
205 TRACE("-- %s\n", debugstr_w(szDest
) );
209 /***************************************************************************************
210 * HCR_GetDefaultIcon [internal]
212 * Gets the icon for a filetype
214 static BOOL
HCR_RegOpenClassIDKey(REFIID riid
, HKEY
*hkey
)
217 sprintf( xriid
, "CLSID\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
218 riid
->Data1
, riid
->Data2
, riid
->Data3
,
219 riid
->Data4
[0], riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3],
220 riid
->Data4
[4], riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7] );
222 TRACE("%s\n",xriid
);
224 return (RegOpenKeyExA(HKEY_CLASSES_ROOT
, xriid
, 0, KEY_READ
, hkey
) == ERROR_SUCCESS
);
227 static BOOL
HCR_RegGetIconW(HKEY hkey
, LPWSTR szDest
, LPCWSTR szName
, DWORD len
, int* picon_idx
)
230 WCHAR sTemp
[MAX_PATH
];
233 if (!RegQueryValueExW(hkey
, szName
, 0, &dwType
, (LPBYTE
)szDest
, &len
))
235 if (dwType
== REG_EXPAND_SZ
)
237 ExpandEnvironmentStringsW(szDest
, sTemp
, MAX_PATH
);
238 lstrcpynW(szDest
, sTemp
, len
);
240 if (ParseFieldW (szDest
, 2, sNum
, _countof(sNum
)))
241 *picon_idx
= atoiW(sNum
);
243 *picon_idx
=0; /* sometimes the icon number is missing */
244 ParseFieldW (szDest
, 1, szDest
, len
);
245 PathUnquoteSpacesW(szDest
);
251 static BOOL
HCR_RegGetIconA(HKEY hkey
, LPSTR szDest
, LPCSTR szName
, DWORD len
, int* picon_idx
)
254 char sTemp
[MAX_PATH
];
257 if (!RegQueryValueExA(hkey
, szName
, 0, &dwType
, (LPBYTE
)szDest
, &len
))
259 if (dwType
== REG_EXPAND_SZ
)
261 ExpandEnvironmentStringsA(szDest
, sTemp
, MAX_PATH
);
262 lstrcpynA(szDest
, sTemp
, len
);
264 if (ParseFieldA (szDest
, 2, sNum
, 5))
265 *picon_idx
=atoi(sNum
);
267 *picon_idx
=0; /* sometimes the icon number is missing */
268 ParseFieldA (szDest
, 1, szDest
, len
);
269 PathUnquoteSpacesA(szDest
);
275 BOOL
HCR_GetIconW(LPCWSTR szClass
, LPWSTR szDest
, LPCWSTR szName
, DWORD len
, int* picon_idx
)
277 static const WCHAR swDefaultIcon
[] = L
"\\DefaultIcon";
279 WCHAR sTemp
[MAX_PATH
];
282 TRACE("%s\n",debugstr_w(szClass
) );
284 lstrcpynW(sTemp
, szClass
, MAX_PATH
);
285 wcscat(sTemp
, swDefaultIcon
);
287 if (!RegOpenKeyExW(HKEY_CLASSES_ROOT
, sTemp
, 0, KEY_READ
, &hKey
))
289 ret
= HCR_RegGetIconW(hKey
, szDest
, szName
, len
, picon_idx
);
294 TRACE("-- %s %i\n", debugstr_w(szDest
), *picon_idx
);
296 TRACE("-- not found\n");
301 BOOL
HCR_GetIconA(LPCSTR szClass
, LPSTR szDest
, LPCSTR szName
, DWORD len
, int* picon_idx
)
304 char sTemp
[MAX_PATH
];
307 TRACE("%s\n",szClass
);
309 sprintf(sTemp
, "%s\\DefaultIcon",szClass
);
311 if (!RegOpenKeyExA(HKEY_CLASSES_ROOT
, sTemp
, 0, KEY_READ
, &hKey
))
313 ret
= HCR_RegGetIconA(hKey
, szDest
, szName
, len
, picon_idx
);
316 TRACE("-- %s %i\n", szDest
, *picon_idx
);
320 BOOL
HCR_GetIconFromGUIDW(REFIID riid
, LPWSTR szDest
, LPWSTR szName
, DWORD len
, int* picon_idx
)
325 if (HCR_RegOpenClassIDKey(riid
, &hKey
))
327 ret
= HCR_RegGetIconW(hKey
, szDest
, szName
, len
, picon_idx
);
330 TRACE("-- %s %i\n", debugstr_w(szDest
), *picon_idx
);
334 /***************************************************************************************
335 * HCR_GetClassName [internal]
337 * Gets the name of a registered class
339 static const WCHAR swEmpty
[] = {0};
341 BOOL
HCR_GetClassNameW(REFIID riid
, LPWSTR szDest
, DWORD len
)
351 if (StringFromCLSID(riid
, &pStr
) == S_OK
)
353 DWORD dwLen
= buflen
* sizeof(WCHAR
);
354 swprintf(szName
, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", pStr
);
355 if (RegGetValueW(HKEY_CURRENT_USER
, szName
, NULL
, RRF_RT_REG_SZ
, NULL
, (PVOID
)szDest
, &dwLen
) == ERROR_SUCCESS
)
361 if (!ret
&& HCR_RegOpenClassIDKey(riid
, &hKey
))
363 static const WCHAR wszLocalizedString
[] = L
"LocalizedString";
365 if (RegLoadMUIStringW(hKey
, wszLocalizedString
, szDest
, len
, NULL
, 0, NULL
) == ERROR_SUCCESS
||
366 RegQueryValueExW(hKey
, swEmpty
, 0, NULL
, (LPBYTE
)szDest
, &len
) == ERROR_SUCCESS
)
373 if (!ret
|| !szDest
[0])
375 if(IsEqualIID(riid
, &CLSID_ShellDesktop
))
377 if (LoadStringW(shell32_hInstance
, IDS_DESKTOP
, szDest
, buflen
))
380 else if (IsEqualIID(riid
, &CLSID_MyComputer
))
382 if(LoadStringW(shell32_hInstance
, IDS_MYCOMPUTER
, szDest
, buflen
))
385 else if (IsEqualIID(riid
, &CLSID_MyDocuments
))
387 if(LoadStringW(shell32_hInstance
, IDS_PERSONAL
, szDest
, buflen
))
390 else if (IsEqualIID(riid
, &CLSID_RecycleBin
))
392 if(LoadStringW(shell32_hInstance
, IDS_RECYCLEBIN_FOLDER_NAME
, szDest
, buflen
))
395 else if (IsEqualIID(riid
, &CLSID_ControlPanel
))
397 if(LoadStringW(shell32_hInstance
, IDS_CONTROLPANEL
, szDest
, buflen
))
400 else if (IsEqualIID(riid
, &CLSID_AdminFolderShortcut
))
402 if(LoadStringW(shell32_hInstance
, IDS_ADMINISTRATIVETOOLS
, szDest
, buflen
))
407 TRACE("-- %s\n", debugstr_w(szDest
));
411 BOOL
HCR_GetClassNameA(REFIID riid
, LPSTR szDest
, DWORD len
)
417 if (HCR_RegOpenClassIDKey(riid
, &hKey
))
419 if (!RegLoadMUIStringA(hKey
, "LocalizedString", szDest
, len
, NULL
, 0, NULL
) ||
420 !RegQueryValueExA(hKey
, "", 0, NULL
, (LPBYTE
)szDest
, &len
))
427 if (!ret
|| !szDest
[0])
429 if(IsEqualIID(riid
, &CLSID_ShellDesktop
))
431 if (LoadStringA(shell32_hInstance
, IDS_DESKTOP
, szDest
, buflen
))
434 else if (IsEqualIID(riid
, &CLSID_MyComputer
))
436 if(LoadStringA(shell32_hInstance
, IDS_MYCOMPUTER
, szDest
, buflen
))
441 TRACE("-- (%s)\n", szDest
);
446 /******************************************************************************
447 * HCR_GetFolderAttributes [Internal]
449 * Query the registry for a shell folders' attributes
452 * pidlFolder [I] A simple pidl of type PT_GUID.
453 * pdwAttributes [IO] In: Attributes to be queried, OUT: Resulting attributes.
456 * TRUE: Found information for the attributes in the registry
457 * FALSE: No attribute information found
460 * If queried for an attribute, which is set in the CallForAttributes registry
461 * value, the function binds to the shellfolder objects and queries it.
463 BOOL
HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder
, LPDWORD pdwAttributes
)
469 static const WCHAR wszAttributes
[] = { 'A','t','t','r','i','b','u','t','e','s',0 };
470 static const WCHAR wszCallForAttributes
[] = {
471 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 };
472 WCHAR wszShellFolderKey
[] = { 'C','L','S','I','D','\\','{','0','0','0','2','1','4','0','0','-',
473 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0','0',
474 '0','0','0','4','6','}','\\','S','h','e','l','l','F','o','l','d','e','r',0 };
476 TRACE("(pidlFolder=%p, pdwAttributes=%p)\n", pidlFolder
, pdwAttributes
);
478 if (!_ILIsPidlSimple(pidlFolder
)) {
479 ERR("should be called for simple PIDL's only!\n");
483 if (!_ILIsDesktop(pidlFolder
)) {
484 if (FAILED(StringFromCLSID(_ILGetGUIDPointer(pidlFolder
), &pwszCLSID
))) return FALSE
;
485 memcpy(&wszShellFolderKey
[6], pwszCLSID
, 38 * sizeof(WCHAR
));
486 CoTaskMemFree(pwszCLSID
);
489 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszShellFolderKey
, 0, KEY_READ
, &hSFKey
);
490 if (lResult
!= ERROR_SUCCESS
)
492 ERR("Cannot open key: %ls\n", wszShellFolderKey
);
496 dwLen
= sizeof(DWORD
);
497 lResult
= RegQueryValueExW(hSFKey
, wszCallForAttributes
, 0, NULL
, (LPBYTE
)&dwTemp
, &dwLen
);
498 if ((lResult
== ERROR_SUCCESS
) && (dwTemp
& *pdwAttributes
)) {
499 IShellFolder
*psfDesktop
;
500 IShellFolder
*psfFolder
;
504 hr
= SHGetDesktopFolder(&psfDesktop
);
506 hr
= IShellFolder_BindToObject(psfDesktop
, pidlFolder
, NULL
, &IID_IShellFolder
,
507 (LPVOID
*)&psfFolder
);
509 hr
= IShellFolder_GetAttributesOf(psfFolder
, 0, NULL
, pdwAttributes
);
511 if (FAILED(hr
)) return FALSE
;
513 lResult
= RegQueryValueExW(hSFKey
, wszAttributes
, 0, NULL
, (LPBYTE
)&dwTemp
, &dwLen
);
515 if (lResult
== ERROR_SUCCESS
) {
516 *pdwAttributes
&= dwTemp
;
522 TRACE("-- *pdwAttributes == 0x%08x\n", *pdwAttributes
);