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
24 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
26 #define MAX_EXTENSION_LENGTH 20
28 BOOL
HCR_MapTypeToValueW(LPCWSTR szExtension
, LPWSTR szFileType
, LONG len
, BOOL bPrependDot
)
31 WCHAR szTemp
[MAX_EXTENSION_LENGTH
+ 2];
33 TRACE("%s %p\n", debugstr_w(szExtension
), debugstr_w(szFileType
));
35 /* added because we do not want to have double dots */
36 if (szExtension
[0] == '.')
42 lstrcpynW(szTemp
+ (bPrependDot
? 1 : 0), szExtension
, MAX_EXTENSION_LENGTH
);
44 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szTemp
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
47 if (RegQueryValueW(hkey
, NULL
, szFileType
, &len
) != ERROR_SUCCESS
)
55 TRACE("--UE;\n} %s\n", debugstr_w(szFileType
));
60 BOOL
HCR_MapTypeToValueA(LPCSTR szExtension
, LPSTR szFileType
, LONG len
, BOOL bPrependDot
)
63 char szTemp
[MAX_EXTENSION_LENGTH
+ 2];
65 TRACE("%s %p\n", szExtension
, szFileType
);
67 /* added because we do not want to have double dots */
68 if (szExtension
[0] == '.')
74 lstrcpynA(szTemp
+ (bPrependDot
? 1 : 0), szExtension
, MAX_EXTENSION_LENGTH
);
76 if (RegOpenKeyExA(HKEY_CLASSES_ROOT
, szTemp
, 0, KEY_READ
, &hkey
))
81 if (RegLoadMUIStringA(hkey
, "FriendlyTypeName", szFileType
, len
, NULL
, 0, NULL
) == ERROR_SUCCESS
)
87 if (RegQueryValueA(hkey
, NULL
, szFileType
, &len
))
95 TRACE("--UE;\n} %s\n", szFileType
);
100 static const WCHAR swShell
[] = L
"shell\\";
101 static const WCHAR swOpen
[] = L
"open";
102 static const WCHAR swCommand
[] = L
"\\command";
104 BOOL
HCR_GetDefaultVerbW(HKEY hkeyClass
, LPCWSTR szVerb
, LPWSTR szDest
, DWORD len
)
106 WCHAR sTemp
[MAX_PATH
];
110 TRACE("%p %s %p\n", hkeyClass
, debugstr_w(szVerb
), szDest
);
114 lstrcpynW(szDest
, szVerb
, len
);
120 if (RegQueryValueW(hkeyClass
, L
"shell", szDest
, &size
) == ERROR_SUCCESS
&& *szDest
)
122 /* The MSDN says to first try the default verb */
123 wcscpy(sTemp
, swShell
);
124 wcscat(sTemp
, szDest
);
125 wcscat(sTemp
, swCommand
);
126 if (RegOpenKeyExW(hkeyClass
, sTemp
, 0, KEY_READ
, &hkey
) == ERROR_SUCCESS
)
129 TRACE("default verb=%s\n", debugstr_w(szDest
));
134 /* then fallback to 'open' */
135 wcscpy(sTemp
, swShell
);
136 wcscat(sTemp
, swOpen
);
137 wcscat(sTemp
, swCommand
);
138 if (RegOpenKeyExW(hkeyClass
, sTemp
, 0, KEY_READ
, &hkey
) == ERROR_SUCCESS
)
141 lstrcpynW(szDest
, swOpen
, len
);
142 TRACE("default verb=open\n");
146 /* and then just use the first verb on Windows >= 2000 */
147 if (RegOpenKeyExW(hkeyClass
, L
"shell", 0, KEY_READ
, &hkey
) == ERROR_SUCCESS
)
149 if (RegEnumKeyW(hkey
, 0, szDest
, len
) == ERROR_SUCCESS
&& *szDest
)
151 TRACE("default verb=first verb=%s\n", debugstr_w(szDest
));
159 TRACE("no default verb!\n");
163 BOOL
HCR_GetExecuteCommandW(HKEY hkeyClass
, LPCWSTR szClass
, LPCWSTR szVerb
, LPWSTR szDest
, DWORD len
)
165 WCHAR sTempVerb
[MAX_PATH
];
168 TRACE("%p %s %s %p\n", hkeyClass
, debugstr_w(szClass
), debugstr_w(szVerb
), szDest
);
171 RegOpenKeyExW(HKEY_CLASSES_ROOT
, szClass
, 0, KEY_READ
, &hkeyClass
);
176 if (HCR_GetDefaultVerbW(hkeyClass
, szVerb
, sTempVerb
, sizeof(sTempVerb
)))
178 WCHAR sTemp
[MAX_PATH
];
179 wcscpy(sTemp
, swShell
);
180 wcscat(sTemp
, sTempVerb
);
181 wcscat(sTemp
, swCommand
);
182 ret
= (ERROR_SUCCESS
== SHGetValueW(hkeyClass
, sTemp
, NULL
, NULL
, szDest
, &len
));
185 RegCloseKey(hkeyClass
);
187 TRACE("-- %s\n", debugstr_w(szDest
));
191 /***************************************************************************************
192 * HCR_GetDefaultIcon [internal]
194 * Gets the icon for a filetype
196 static BOOL
HCR_RegOpenClassIDKey(REFIID riid
, HKEY
*hkey
)
199 swprintf(xriid
, L
"CLSID\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
200 riid
.Data1
, riid
.Data2
, riid
.Data3
,
201 riid
.Data4
[0], riid
.Data4
[1], riid
.Data4
[2], riid
.Data4
[3],
202 riid
.Data4
[4], riid
.Data4
[5], riid
.Data4
[6], riid
.Data4
[7] );
204 TRACE("%S\n", xriid
);
206 return (RegOpenKeyExW(HKEY_CLASSES_ROOT
, xriid
, 0, KEY_READ
, hkey
) == ERROR_SUCCESS
);
209 static BOOL
HCR_RegGetDefaultIconW(HKEY hkey
, LPWSTR szDest
, DWORD len
, int* picon_idx
)
212 WCHAR sTemp
[MAX_PATH
];
215 if (!RegQueryValueExW(hkey
, NULL
, 0, &dwType
, (LPBYTE
)szDest
, &len
))
217 if (dwType
== REG_EXPAND_SZ
)
219 ExpandEnvironmentStringsW(szDest
, sTemp
, MAX_PATH
);
220 lstrcpynW(szDest
, sTemp
, len
);
222 if (ParseFieldW (szDest
, 2, sNum
, _countof(sNum
)))
223 *picon_idx
= atoiW(sNum
);
225 *picon_idx
= 0; /* sometimes the icon number is missing */
226 ParseFieldW (szDest
, 1, szDest
, len
);
227 PathUnquoteSpacesW(szDest
);
233 static BOOL
HCR_RegGetDefaultIconA(HKEY hkey
, LPSTR szDest
, DWORD len
, int* picon_idx
)
236 char sTemp
[MAX_PATH
];
239 if (!RegQueryValueExA(hkey
, NULL
, 0, &dwType
, (LPBYTE
)szDest
, &len
))
241 if (dwType
== REG_EXPAND_SZ
)
243 ExpandEnvironmentStringsA(szDest
, sTemp
, MAX_PATH
);
244 lstrcpynA(szDest
, sTemp
, len
);
246 if (ParseFieldA (szDest
, 2, sNum
, 5))
247 *picon_idx
= atoi(sNum
);
249 *picon_idx
= 0; /* sometimes the icon number is missing */
250 ParseFieldA (szDest
, 1, szDest
, len
);
251 PathUnquoteSpacesA(szDest
);
257 BOOL
HCR_GetDefaultIconW(LPCWSTR szClass
, LPWSTR szDest
, DWORD len
, int* picon_idx
)
259 static const WCHAR swDefaultIcon
[] = L
"\\DefaultIcon";
261 WCHAR sTemp
[MAX_PATH
];
264 TRACE("%s\n", debugstr_w(szClass
) );
266 lstrcpynW(sTemp
, szClass
, MAX_PATH
);
267 wcscat(sTemp
, swDefaultIcon
);
269 if (!RegOpenKeyExW(HKEY_CLASSES_ROOT
, sTemp
, 0, KEY_READ
, &hKey
))
271 ret
= HCR_RegGetDefaultIconW(hKey
, szDest
, len
, picon_idx
);
276 TRACE("-- %s %i\n", debugstr_w(szDest
), *picon_idx
);
278 TRACE("-- not found\n");
283 BOOL
HCR_GetDefaultIconA(LPCSTR szClass
, LPSTR szDest
, DWORD len
, int* picon_idx
)
286 char sTemp
[MAX_PATH
];
289 TRACE("%s\n", szClass
);
291 sprintf(sTemp
, "%s\\DefaultIcon", szClass
);
293 if (!RegOpenKeyExA(HKEY_CLASSES_ROOT
, sTemp
, 0, KEY_READ
, &hKey
))
295 ret
= HCR_RegGetDefaultIconA(hKey
, szDest
, len
, picon_idx
);
298 TRACE("-- %s %i\n", szDest
, *picon_idx
);
302 BOOL
HCR_GetDefaultIconFromGUIDW(REFIID riid
, LPWSTR szDest
, DWORD len
, int* picon_idx
)
307 if (HCR_RegOpenClassIDKey(riid
, &hKey
))
309 ret
= HCR_RegGetDefaultIconW(hKey
, szDest
, len
, picon_idx
);
312 TRACE("-- %s %i\n", debugstr_w(szDest
), *picon_idx
);
316 /***************************************************************************************
317 * HCR_GetClassName [internal]
319 * Gets the name of a registered class
321 static const WCHAR swEmpty
[] = {0};
323 BOOL
HCR_GetClassNameW(REFIID riid
, LPWSTR szDest
, DWORD len
)
333 if (StringFromCLSID(riid
, &pStr
) == S_OK
)
335 DWORD dwLen
= buflen
* sizeof(WCHAR
);
336 swprintf(szName
, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", pStr
);
337 if (RegGetValueW(HKEY_CURRENT_USER
, szName
, NULL
, RRF_RT_REG_SZ
, NULL
, (PVOID
)szDest
, &dwLen
) == ERROR_SUCCESS
)
343 if (!ret
&& HCR_RegOpenClassIDKey(riid
, &hKey
))
345 static const WCHAR wszLocalizedString
[] = L
"LocalizedString";
347 if (RegLoadMUIStringW(hKey
, wszLocalizedString
, szDest
, len
, NULL
, 0, NULL
) == ERROR_SUCCESS
||
348 RegQueryValueExW(hKey
, swEmpty
, 0, NULL
, (LPBYTE
)szDest
, &len
) == ERROR_SUCCESS
)
355 if (!ret
|| !szDest
[0])
357 if(IsEqualIID(riid
, CLSID_ShellDesktop
))
359 if (LoadStringW(shell32_hInstance
, IDS_DESKTOP
, szDest
, buflen
))
362 else if (IsEqualIID(riid
, CLSID_MyComputer
))
364 if(LoadStringW(shell32_hInstance
, IDS_MYCOMPUTER
, szDest
, buflen
))
367 else if (IsEqualIID(riid
, CLSID_MyDocuments
))
369 if(LoadStringW(shell32_hInstance
, IDS_PERSONAL
, szDest
, buflen
))
372 else if (IsEqualIID(riid
, CLSID_RecycleBin
))
374 if(LoadStringW(shell32_hInstance
, IDS_RECYCLEBIN_FOLDER_NAME
, szDest
, buflen
))
377 else if (IsEqualIID(riid
, CLSID_ControlPanel
))
379 if(LoadStringW(shell32_hInstance
, IDS_CONTROLPANEL
, szDest
, buflen
))
382 else if (IsEqualIID(riid
, CLSID_AdminFolderShortcut
))
384 if(LoadStringW(shell32_hInstance
, IDS_ADMINISTRATIVETOOLS
, szDest
, buflen
))
389 TRACE("-- %s\n", debugstr_w(szDest
));
393 BOOL
HCR_GetClassNameA(REFIID riid
, LPSTR szDest
, DWORD len
)
399 if (HCR_RegOpenClassIDKey(riid
, &hKey
))
401 if (!RegLoadMUIStringA(hKey
, "LocalizedString", szDest
, len
, NULL
, 0, NULL
) ||
402 !RegQueryValueExA(hKey
, "", 0, NULL
, (LPBYTE
)szDest
, &len
))
409 if (!ret
|| !szDest
[0])
411 if(IsEqualIID(riid
, CLSID_ShellDesktop
))
413 if (LoadStringA(shell32_hInstance
, IDS_DESKTOP
, szDest
, buflen
))
416 else if (IsEqualIID(riid
, CLSID_MyComputer
))
418 if(LoadStringA(shell32_hInstance
, IDS_MYCOMPUTER
, szDest
, buflen
))
423 TRACE("-- %s\n", szDest
);
428 /******************************************************************************
429 * HCR_GetFolderAttributes [Internal]
431 * Query the registry for a shell folders' attributes
434 * pidlFolder [I] A simple pidl of type PT_GUID.
435 * pdwAttributes [IO] In: Attributes to be queried, OUT: Resulting attributes.
438 * TRUE: Found information for the attributes in the registry
439 * FALSE: No attribute information found
442 * If queried for an attribute, which is set in the CallForAttributes registry
443 * value, the function binds to the shellfolder objects and queries it.
445 BOOL
HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder
, LPDWORD pdwAttributes
)
451 static const WCHAR wszAttributes
[] = L
"Attributes";
452 static const WCHAR wszCallForAttributes
[] = L
"CallForAttributes";
453 WCHAR wszShellFolderKey
[] = L
"CLSID\\{00021400-0000-0000-C000-000000000046}\\ShellFolder";
455 TRACE("(pidlFolder=%p, pdwAttributes=%p)\n", pidlFolder
, pdwAttributes
);
457 if (!_ILIsPidlSimple(pidlFolder
))
459 ERR("should be called for simple PIDL's only!\n");
463 if (!_ILIsDesktop(pidlFolder
))
465 if (FAILED(StringFromCLSID(*_ILGetGUIDPointer(pidlFolder
), &pwszCLSID
)))
467 memcpy(&wszShellFolderKey
[6], pwszCLSID
, 38 * sizeof(WCHAR
));
468 CoTaskMemFree(pwszCLSID
);
471 lResult
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszShellFolderKey
, 0, KEY_READ
, &hSFKey
);
472 if (lResult
!= ERROR_SUCCESS
)
474 ERR("Cannot open key: %ls\n", wszShellFolderKey
);
478 dwLen
= sizeof(DWORD
);
479 lResult
= RegQueryValueExW(hSFKey
, wszCallForAttributes
, 0, NULL
, (LPBYTE
)&dwTemp
, &dwLen
);
480 if ((lResult
== ERROR_SUCCESS
) && (dwTemp
& *pdwAttributes
))
482 CComPtr
<IShellFolder
> psfDesktop
;
483 CComPtr
<IShellFolder
> psfFolder
;
487 hr
= SHGetDesktopFolder(&psfDesktop
);
490 hr
= psfDesktop
->BindToObject(pidlFolder
, NULL
, IID_PPV_ARG(IShellFolder
,&psfFolder
));
492 hr
= psfFolder
->GetAttributesOf(0, NULL
, pdwAttributes
);
499 lResult
= RegQueryValueExW(hSFKey
, wszAttributes
, 0, NULL
, (LPBYTE
)&dwTemp
, &dwLen
);
501 if (lResult
== ERROR_SUCCESS
)
502 *pdwAttributes
&= dwTemp
;
507 TRACE("-- *pdwAttributes == 0x%08x\n", *pdwAttributes
);