[SHELL32]
[reactos.git] / dll / win32 / shell32 / wine / classes.c
1 /*
2 * file type mapping
3 * (HKEY_CLASSES_ROOT - Stuff)
4 *
5 * Copyright 1998, 1999, 2000 Juergen Schmied
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include <wine/config.h>
23
24 #include <stdio.h>
25
26 #define WIN32_NO_STATUS
27 #define _INC_WINDOWS
28 #define COBJMACROS
29
30 #include <windef.h>
31 #include <winbase.h>
32 #include <shlobj.h>
33 #include <shlguid_undoc.h>
34 #include <shlwapi.h>
35 #include <wine/debug.h>
36 #include <wine/unicode.h>
37
38 #include "pidl.h"
39 #include "shell32_main.h"
40 #include "shresdef.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(shell);
43
44 #define MAX_EXTENSION_LENGTH 20
45
46 BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL bPrependDot)
47 {
48 HKEY hkey;
49 WCHAR szTemp[MAX_EXTENSION_LENGTH + 2];
50
51 TRACE("%s %p\n", debugstr_w(szExtension), debugstr_w(szFileType));
52
53 /* added because we do not want to have double dots */
54 if (szExtension[0] == '.')
55 bPrependDot = FALSE;
56
57 if (bPrependDot)
58 szTemp[0] = '.';
59
60 lstrcpynW(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH);
61
62 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szTemp, 0, KEY_READ, &hkey) != ERROR_SUCCESS)
63 return FALSE;
64
65 if (RegQueryValueW(hkey, NULL, szFileType, &len) != ERROR_SUCCESS)
66 {
67 RegCloseKey(hkey);
68 return FALSE;
69 }
70
71 RegCloseKey(hkey);
72
73 TRACE("--UE;\n} %s\n", debugstr_w(szFileType));
74
75 return TRUE;
76 }
77
78 BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, LONG len, BOOL bPrependDot)
79 {
80 HKEY hkey;
81 char szTemp[MAX_EXTENSION_LENGTH + 2];
82
83 TRACE("%s %p\n", szExtension, szFileType);
84
85 /* added because we do not want to have double dots */
86 if (szExtension[0] == '.')
87 bPrependDot = FALSE;
88
89 if (bPrependDot)
90 szTemp[0] = '.';
91
92 lstrcpynA(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH);
93
94 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, KEY_READ, &hkey))
95 {
96 return FALSE;
97 }
98
99 if (RegLoadMUIStringA(hkey, "FriendlyTypeName", szFileType, len, NULL, 0, NULL) == ERROR_SUCCESS)
100 {
101 RegCloseKey(hkey);
102 return TRUE;
103 }
104
105 if (RegQueryValueA(hkey, NULL, szFileType, &len))
106 {
107 RegCloseKey(hkey);
108 return FALSE;
109 }
110
111 RegCloseKey(hkey);
112
113 TRACE("--UE;\n} %s\n", szFileType);
114
115 return TRUE;
116 }
117
118 static const WCHAR swShell[] = L"shell\\";
119 static const WCHAR swOpen[] = L"open";
120 static const WCHAR swCommand[] = L"\\command";
121
122 BOOL HCR_GetDefaultVerbW( HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len )
123 {
124 WCHAR sTemp[MAX_PATH];
125 LONG size;
126 HKEY hkey;
127
128 TRACE("%p %s %p\n", hkeyClass, debugstr_w(szVerb), szDest);
129
130 if (szVerb && *szVerb)
131 {
132 lstrcpynW(szDest, szVerb, len);
133 return TRUE;
134 }
135
136 size=len;
137 *szDest='\0';
138 if (RegQueryValueW(hkeyClass, L"shell", szDest, &size) == ERROR_SUCCESS && *szDest)
139 {
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)
145 {
146 RegCloseKey(hkey);
147 TRACE("default verb=%s\n", debugstr_w(szDest));
148 return TRUE;
149 }
150 }
151
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)
157 {
158 RegCloseKey(hkey);
159 lstrcpynW(szDest, swOpen, len);
160 TRACE("default verb=open\n");
161 return TRUE;
162 }
163
164 /* and then just use the first verb on Windows >= 2000 */
165 if (RegOpenKeyExW(hkeyClass, L"shell", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
166 {
167 if (RegEnumKeyW(hkey, 0, szDest, len) == ERROR_SUCCESS && *szDest)
168 {
169 TRACE("default verb=first verb=%s\n", debugstr_w(szDest));
170 RegCloseKey(hkey);
171 return TRUE;
172 }
173 RegCloseKey(hkey);
174 }
175
176
177 TRACE("no default verb!\n");
178 return FALSE;
179 }
180
181 BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len )
182 {
183 WCHAR sTempVerb[MAX_PATH];
184 BOOL ret;
185
186 TRACE("%p %s %s %p\n", hkeyClass, debugstr_w(szClass), debugstr_w(szVerb), szDest);
187
188 if (szClass)
189 RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, KEY_READ, &hkeyClass);
190 if (!hkeyClass)
191 return FALSE;
192 ret = FALSE;
193
194 if (HCR_GetDefaultVerbW(hkeyClass, szVerb, sTempVerb, sizeof(sTempVerb)/sizeof(sTempVerb[0])))
195 {
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));
201 }
202 if (szClass)
203 RegCloseKey(hkeyClass);
204
205 TRACE("-- %s\n", debugstr_w(szDest) );
206 return ret;
207 }
208
209 /***************************************************************************************
210 * HCR_GetDefaultIcon [internal]
211 *
212 * Gets the icon for a filetype
213 */
214 static BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey)
215 {
216 char xriid[50];
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] );
221
222 TRACE("%s\n",xriid );
223
224 return (RegOpenKeyExA(HKEY_CLASSES_ROOT, xriid, 0, KEY_READ, hkey) == ERROR_SUCCESS);
225 }
226
227 static BOOL HCR_RegGetIconW(HKEY hkey, LPWSTR szDest, LPCWSTR szName, DWORD len, int* picon_idx)
228 {
229 DWORD dwType;
230 WCHAR sTemp[MAX_PATH];
231 WCHAR sNum[7];
232
233 if (!RegQueryValueExW(hkey, szName, 0, &dwType, (LPBYTE)szDest, &len))
234 {
235 if (dwType == REG_EXPAND_SZ)
236 {
237 ExpandEnvironmentStringsW(szDest, sTemp, MAX_PATH);
238 lstrcpynW(szDest, sTemp, len);
239 }
240 if (ParseFieldW (szDest, 2, sNum, _countof(sNum)))
241 *picon_idx = atoiW(sNum);
242 else
243 *picon_idx=0; /* sometimes the icon number is missing */
244 ParseFieldW (szDest, 1, szDest, len);
245 PathUnquoteSpacesW(szDest);
246 return TRUE;
247 }
248 return FALSE;
249 }
250
251 static BOOL HCR_RegGetIconA(HKEY hkey, LPSTR szDest, LPCSTR szName, DWORD len, int* picon_idx)
252 {
253 DWORD dwType;
254 char sTemp[MAX_PATH];
255 char sNum[5];
256
257 if (!RegQueryValueExA(hkey, szName, 0, &dwType, (LPBYTE)szDest, &len))
258 {
259 if (dwType == REG_EXPAND_SZ)
260 {
261 ExpandEnvironmentStringsA(szDest, sTemp, MAX_PATH);
262 lstrcpynA(szDest, sTemp, len);
263 }
264 if (ParseFieldA (szDest, 2, sNum, 5))
265 *picon_idx=atoi(sNum);
266 else
267 *picon_idx=0; /* sometimes the icon number is missing */
268 ParseFieldA (szDest, 1, szDest, len);
269 PathUnquoteSpacesA(szDest);
270 return TRUE;
271 }
272 return FALSE;
273 }
274
275 BOOL HCR_GetIconW(LPCWSTR szClass, LPWSTR szDest, LPCWSTR szName, DWORD len, int* picon_idx)
276 {
277 static const WCHAR swDefaultIcon[] = L"\\DefaultIcon";
278 HKEY hKey;
279 WCHAR sTemp[MAX_PATH];
280 BOOL ret = FALSE;
281
282 TRACE("%s\n",debugstr_w(szClass) );
283
284 lstrcpynW(sTemp, szClass, MAX_PATH);
285 wcscat(sTemp, swDefaultIcon);
286
287 if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, sTemp, 0, KEY_READ, &hKey))
288 {
289 ret = HCR_RegGetIconW(hKey, szDest, szName, len, picon_idx);
290 RegCloseKey(hKey);
291 }
292
293 if(ret)
294 TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx);
295 else
296 TRACE("-- not found\n");
297
298 return ret;
299 }
300
301 BOOL HCR_GetIconA(LPCSTR szClass, LPSTR szDest, LPCSTR szName, DWORD len, int* picon_idx)
302 {
303 HKEY hKey;
304 char sTemp[MAX_PATH];
305 BOOL ret = FALSE;
306
307 TRACE("%s\n",szClass );
308
309 sprintf(sTemp, "%s\\DefaultIcon",szClass);
310
311 if (!RegOpenKeyExA(HKEY_CLASSES_ROOT, sTemp, 0, KEY_READ, &hKey))
312 {
313 ret = HCR_RegGetIconA(hKey, szDest, szName, len, picon_idx);
314 RegCloseKey(hKey);
315 }
316 TRACE("-- %s %i\n", szDest, *picon_idx);
317 return ret;
318 }
319
320 BOOL HCR_GetIconFromGUIDW(REFIID riid, LPWSTR szDest, LPWSTR szName, DWORD len, int* picon_idx)
321 {
322 HKEY hKey;
323 BOOL ret = FALSE;
324
325 if (HCR_RegOpenClassIDKey(riid, &hKey))
326 {
327 ret = HCR_RegGetIconW(hKey, szDest, szName, len, picon_idx);
328 RegCloseKey(hKey);
329 }
330 TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx);
331 return ret;
332 }
333
334 /***************************************************************************************
335 * HCR_GetClassName [internal]
336 *
337 * Gets the name of a registered class
338 */
339 static const WCHAR swEmpty[] = {0};
340
341 BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len)
342 {
343 HKEY hKey;
344 BOOL ret = FALSE;
345 DWORD buflen = len;
346 WCHAR szName[100];
347 LPOLESTR pStr;
348
349 szDest[0] = 0;
350
351 if (StringFromCLSID(riid, &pStr) == S_OK)
352 {
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)
356 {
357 ret = TRUE;
358 }
359 CoTaskMemFree(pStr);
360 }
361 if (!ret && HCR_RegOpenClassIDKey(riid, &hKey))
362 {
363 static const WCHAR wszLocalizedString[] = L"LocalizedString";
364
365 if (RegLoadMUIStringW(hKey, wszLocalizedString, szDest, len, NULL, 0, NULL) == ERROR_SUCCESS ||
366 RegQueryValueExW(hKey, swEmpty, 0, NULL, (LPBYTE)szDest, &len) == ERROR_SUCCESS)
367 {
368 ret = TRUE;
369 }
370 RegCloseKey(hKey);
371 }
372
373 if (!ret || !szDest[0])
374 {
375 if(IsEqualIID(riid, &CLSID_ShellDesktop))
376 {
377 if (LoadStringW(shell32_hInstance, IDS_DESKTOP, szDest, buflen))
378 ret = TRUE;
379 }
380 else if (IsEqualIID(riid, &CLSID_MyComputer))
381 {
382 if(LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen))
383 ret = TRUE;
384 }
385 else if (IsEqualIID(riid, &CLSID_MyDocuments))
386 {
387 if(LoadStringW(shell32_hInstance, IDS_PERSONAL, szDest, buflen))
388 ret = TRUE;
389 }
390 else if (IsEqualIID(riid, &CLSID_RecycleBin))
391 {
392 if(LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_FOLDER_NAME, szDest, buflen))
393 ret = TRUE;
394 }
395 else if (IsEqualIID(riid, &CLSID_ControlPanel))
396 {
397 if(LoadStringW(shell32_hInstance, IDS_CONTROLPANEL, szDest, buflen))
398 ret = TRUE;
399 }
400 else if (IsEqualIID(riid, &CLSID_AdminFolderShortcut))
401 {
402 if(LoadStringW(shell32_hInstance, IDS_ADMINISTRATIVETOOLS, szDest, buflen))
403 ret = TRUE;
404 }
405 }
406
407 TRACE("-- %s\n", debugstr_w(szDest));
408 return ret;
409 }
410
411 BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len)
412 { HKEY hKey;
413 BOOL ret = FALSE;
414 DWORD buflen = len;
415
416 szDest[0] = 0;
417 if (HCR_RegOpenClassIDKey(riid, &hKey))
418 {
419 if (!RegLoadMUIStringA(hKey, "LocalizedString", szDest, len, NULL, 0, NULL) ||
420 !RegQueryValueExA(hKey, "", 0, NULL, (LPBYTE)szDest, &len))
421 {
422 ret = TRUE;
423 }
424 RegCloseKey(hKey);
425 }
426
427 if (!ret || !szDest[0])
428 {
429 if(IsEqualIID(riid, &CLSID_ShellDesktop))
430 {
431 if (LoadStringA(shell32_hInstance, IDS_DESKTOP, szDest, buflen))
432 ret = TRUE;
433 }
434 else if (IsEqualIID(riid, &CLSID_MyComputer))
435 {
436 if(LoadStringA(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen))
437 ret = TRUE;
438 }
439 }
440
441 TRACE("-- (%s)\n", szDest);
442
443 return ret;
444 }
445
446 /******************************************************************************
447 * HCR_GetFolderAttributes [Internal]
448 *
449 * Query the registry for a shell folders' attributes
450 *
451 * PARAMS
452 * pidlFolder [I] A simple pidl of type PT_GUID.
453 * pdwAttributes [IO] In: Attributes to be queried, OUT: Resulting attributes.
454 *
455 * RETURNS
456 * TRUE: Found information for the attributes in the registry
457 * FALSE: No attribute information found
458 *
459 * NOTES
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.
462 */
463 BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD pdwAttributes)
464 {
465 HKEY hSFKey;
466 LPOLESTR pwszCLSID;
467 LONG lResult;
468 DWORD dwTemp, dwLen;
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 };
475
476 TRACE("(pidlFolder=%p, pdwAttributes=%p)\n", pidlFolder, pdwAttributes);
477
478 if (!_ILIsPidlSimple(pidlFolder)) {
479 ERR("should be called for simple PIDL's only!\n");
480 return FALSE;
481 }
482
483 if (!_ILIsDesktop(pidlFolder)) {
484 if (FAILED(StringFromCLSID(_ILGetGUIDPointer(pidlFolder), &pwszCLSID))) return FALSE;
485 memcpy(&wszShellFolderKey[6], pwszCLSID, 38 * sizeof(WCHAR));
486 CoTaskMemFree(pwszCLSID);
487 }
488
489 lResult = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszShellFolderKey, 0, KEY_READ, &hSFKey);
490 if (lResult != ERROR_SUCCESS)
491 {
492 ERR("Cannot open key: %ls\n", wszShellFolderKey);
493 return FALSE;
494 }
495
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;
501 HRESULT hr;
502
503 RegCloseKey(hSFKey);
504 hr = SHGetDesktopFolder(&psfDesktop);
505 if (SUCCEEDED(hr)) {
506 hr = IShellFolder_BindToObject(psfDesktop, pidlFolder, NULL, &IID_IShellFolder,
507 (LPVOID*)&psfFolder);
508 if (SUCCEEDED(hr))
509 hr = IShellFolder_GetAttributesOf(psfFolder, 0, NULL, pdwAttributes);
510 }
511 if (FAILED(hr)) return FALSE;
512 } else {
513 lResult = RegQueryValueExW(hSFKey, wszAttributes, 0, NULL, (LPBYTE)&dwTemp, &dwLen);
514 RegCloseKey(hSFKey);
515 if (lResult == ERROR_SUCCESS) {
516 *pdwAttributes &= dwTemp;
517 } else {
518 return FALSE;
519 }
520 }
521
522 TRACE("-- *pdwAttributes == 0x%08x\n", *pdwAttributes);
523
524 return TRUE;
525 }