xref: /reactos/dll/win32/shell32/wine/classes.c (revision 8107ff86)
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 #ifdef __REACTOS__
38 #include <strsafe.h>
39 #endif
40 
41 #include "pidl.h"
42 #include "shell32_main.h"
43 #include "shresdef.h"
44 
45 WINE_DEFAULT_DEBUG_CHANNEL(shell);
46 
47 #define MAX_EXTENSION_LENGTH 20 // FIXME: The limit is 254?
48 
GetRegString(HKEY hKey,PCWSTR SubKey,PCWSTR Name,PWSTR Buffer,UINT cchBuf)49 static LONG GetRegString(HKEY hKey, PCWSTR SubKey, PCWSTR Name, PWSTR Buffer, UINT cchBuf)
50 {
51     DWORD cb = sizeof(*Buffer) * cchBuf;
52     return RegGetValueW(hKey, SubKey, Name, RRF_RT_REG_SZ, NULL, Buffer, &cb);
53 }
54 
HCR_GetProgIdKeyOfExtension(PCWSTR szExtension,PHKEY phKey,BOOL AllowFallback)55 HRESULT HCR_GetProgIdKeyOfExtension(PCWSTR szExtension, PHKEY phKey, BOOL AllowFallback)
56 {
57     LONG err;
58     WCHAR ext[max(1 + MAX_EXTENSION_LENGTH + 1, MAX_PATH)];
59     WCHAR progid[MAX_PATH];
60     if (szExtension[0] != '.')
61     {
62         ext[0] = '.';
63         lstrcpynW(ext + 1, szExtension, _countof(ext) - 1);
64         szExtension = ext;
65     }
66     err = GetRegString(HKEY_CLASSES_ROOT, szExtension, NULL, progid, _countof(progid));
67     if (!err && progid[0] != UNICODE_NULL)
68     {
69         err = RegOpenKeyExW(HKEY_CLASSES_ROOT, progid, 0, KEY_READ, phKey);
70         if (!err)
71             return err; /* A real ProgId key, return S_OK */
72     }
73     if (AllowFallback)
74     {
75         err = RegOpenKeyExW(HKEY_CLASSES_ROOT, szExtension, 0, KEY_READ, phKey);
76         if (!err)
77             return S_FALSE;
78     }
79     return HRESULT_FROM_WIN32(err);
80 }
81 
HCR_MapTypeToValueW(LPCWSTR szExtension,LPWSTR szFileType,LONG len,BOOL bPrependDot)82 BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL bPrependDot)
83 {
84 	HKEY	hkey;
85 	WCHAR	szTemp[MAX_EXTENSION_LENGTH + 2];
86 
87 	TRACE("%s %p\n", debugstr_w(szExtension), szFileType);
88 
89         /* added because we do not want to have double dots */
90         if (szExtension[0] == '.')
91           bPrependDot = FALSE;
92 
93 	if (bPrependDot)
94 	  szTemp[0] = '.';
95 
96 	lstrcpynW(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH);
97 
98 	if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szTemp, 0, KEY_READ, &hkey))
99 	{
100 	  return FALSE;
101 	}
102 
103 	if (RegQueryValueW(hkey, NULL, szFileType, &len))
104 	{
105 	  RegCloseKey(hkey);
106 	  return FALSE;
107 	}
108 
109 	RegCloseKey(hkey);
110 
111 	TRACE("--UE;\n} %s\n", debugstr_w(szFileType));
112 
113 	return TRUE;
114 }
115 
HCR_MapTypeToValueA(LPCSTR szExtension,LPSTR szFileType,LONG len,BOOL bPrependDot)116 BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, LONG len, BOOL bPrependDot)
117 {
118 	HKEY	hkey;
119 	char	szTemp[MAX_EXTENSION_LENGTH + 2];
120 
121 	TRACE("%s %p\n", szExtension, szFileType);
122 
123         /* added because we do not want to have double dots */
124         if (szExtension[0] == '.')
125           bPrependDot = FALSE;
126 
127 	if (bPrependDot)
128 	  szTemp[0] = '.';
129 
130 	lstrcpynA(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH);
131 
132 	if (RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, KEY_READ, &hkey))
133 	{
134 	  return FALSE;
135 	}
136 
137 	if (RegQueryValueA(hkey, NULL, szFileType, &len))
138 	{
139 	  RegCloseKey(hkey);
140 	  return FALSE;
141 	}
142 
143 	RegCloseKey(hkey);
144 
145 	TRACE("--UE;\n} %s\n", szFileType);
146 
147 	return TRUE;
148 }
149 
150 EXTERN_C HRESULT SHELL32_EnumDefaultVerbList(LPCWSTR List, UINT Index, LPWSTR Verb, SIZE_T cchMax);
151 
HCR_GetDefaultVerbW(HKEY hkeyClass,LPCWSTR szVerb,LPWSTR szDest,DWORD len)152 BOOL HCR_GetDefaultVerbW( HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len )
153 {
154         WCHAR sTemp[MAX_PATH], verbs[MAX_PATH];
155         LONG size;
156         HKEY hkey;
157 
158 	TRACE("%p %s %p\n", hkeyClass, debugstr_w(szVerb), szDest);
159 
160         if (szVerb && *szVerb)
161         {
162             lstrcpynW(szDest, szVerb, len);
163             return TRUE;
164         }
165 
166         /* MSDN says to first try the default verb */
167         size = _countof(verbs);
168         if (!RegQueryValueW(hkeyClass, L"shell", verbs, &size) && *verbs)
169         {
170             for (UINT i = 0;; ++i)
171             {
172                 if (FAILED(SHELL32_EnumDefaultVerbList(verbs, i, szDest, len)))
173                     break;
174                 if (FAILED(StringCchPrintfW(sTemp, _countof(sTemp), L"shell\\%s\\command", szDest)))
175                     break;
176                 if (!RegOpenKeyExW(hkeyClass, sTemp, 0, KEY_READ, &hkey))
177                 {
178                     RegCloseKey(hkey);
179                     TRACE("default verb=%s\n", debugstr_w(szDest));
180                     return TRUE;
181                 }
182             }
183         }
184         *szDest = UNICODE_NULL;
185 
186         /* then fallback to 'open' */
187         lstrcpyW(sTemp, L"shell\\open\\command");
188         if (!RegOpenKeyExW(hkeyClass, sTemp, 0, KEY_READ, &hkey))
189         {
190             RegCloseKey(hkey);
191             lstrcpynW(szDest, L"open", len);
192             TRACE("default verb=open\n");
193             return TRUE;
194         }
195 
196         /* and then just use the first verb on Windows >= 2000 */
197 #ifdef __REACTOS__
198         if (!RegOpenKeyExW(hkeyClass, L"shell", 0, KEY_READ, &hkey))
199         {
200             if (!RegEnumKeyW(hkey, 0, szDest, len) && *szDest)
201             {
202                 TRACE("default verb=first verb=%s\n", debugstr_w(szDest));
203                 RegCloseKey(hkey);
204                 return TRUE;
205             }
206             RegCloseKey(hkey);
207         }
208 #else
209         if (!RegEnumKeyW(hkeyClass, 0, szDest, len) && *szDest)
210         {
211             TRACE("default verb=first verb=%s\n", debugstr_w(szDest));
212             return TRUE;
213         }
214 #endif
215 
216         TRACE("no default verb!\n");
217 	return FALSE;
218 }
219 
HCR_GetExecuteCommandW(HKEY hkeyClass,LPCWSTR szClass,LPCWSTR szVerb,LPWSTR szDest,DWORD len)220 BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len )
221 {
222 	WCHAR sTempVerb[MAX_PATH];
223 	BOOL ret;
224 
225 	TRACE("%p %s %s %p\n", hkeyClass, debugstr_w(szClass), debugstr_w(szVerb), szDest);
226 
227 	if (szClass)
228             RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, KEY_READ, &hkeyClass);
229         if (!hkeyClass)
230             return FALSE;
231         ret = FALSE;
232 
233         if (HCR_GetDefaultVerbW(hkeyClass, szVerb, sTempVerb, sizeof(sTempVerb)/sizeof(sTempVerb[0])))
234         {
235             WCHAR sTemp[MAX_PATH];
236             lstrcpyW(sTemp, L"shell\\");
237             lstrcatW(sTemp, sTempVerb);
238             lstrcatW(sTemp, L"\\command");
239             ret = (ERROR_SUCCESS == SHGetValueW(hkeyClass, sTemp, NULL, NULL, szDest, &len));
240         }
241         if (szClass)
242             RegCloseKey(hkeyClass);
243 
244 	TRACE("-- %s\n", debugstr_w(szDest) );
245 	return ret;
246 }
247 
248 /***************************************************************************************
249 *	HCR_GetDefaultIcon	[internal]
250 *
251 * Gets the icon for a filetype
252 */
HCR_RegOpenClassIDKey(REFIID riid,HKEY * hkey)253 BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey)
254 {
255 	char	xriid[50];
256     sprintf( xriid, "CLSID\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
257                  riid->Data1, riid->Data2, riid->Data3,
258                  riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
259                  riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] );
260 
261  	TRACE("%s\n",xriid );
262 
263 	return !RegOpenKeyExA(HKEY_CLASSES_ROOT, xriid, 0, KEY_READ, hkey);
264 }
265 
HCR_RegGetIconW(HKEY hkey,LPWSTR szDest,LPCWSTR szName,DWORD len,int * picon_idx)266 static BOOL HCR_RegGetIconW(HKEY hkey, LPWSTR szDest, LPCWSTR szName, DWORD len, int* picon_idx)
267 {
268     DWORD dwType, size = len * sizeof(WCHAR);
269     WCHAR sTemp[MAX_PATH];
270     WCHAR sNum[5];
271 
272     if (!RegQueryValueExW(hkey, szName, 0, &dwType, (LPBYTE)szDest, &size))
273     {
274       if (dwType == REG_EXPAND_SZ)
275       {
276         ExpandEnvironmentStringsW(szDest, sTemp, MAX_PATH);
277         lstrcpynW(szDest, sTemp, len);
278       }
279         if (ParseFieldW (szDest, 2, sNum, _countof(sNum)))
280              *picon_idx = atoiW(sNum);
281           else
282              *picon_idx=0; /* sometimes the icon number is missing */
283       ParseFieldW (szDest, 1, szDest, len);
284           PathUnquoteSpacesW(szDest);
285       return TRUE;
286     }
287     return FALSE;
288 }
289 
HCR_RegGetIconA(HKEY hkey,LPSTR szDest,LPCSTR szName,DWORD len,int * picon_idx)290 static BOOL HCR_RegGetIconA(HKEY hkey, LPSTR szDest, LPCSTR szName, DWORD len, int* picon_idx)
291 {
292 	DWORD dwType;
293 	char sTemp[MAX_PATH];
294 	char  sNum[5];
295 
296 	if (!RegQueryValueExA(hkey, szName, 0, &dwType, (LPBYTE)szDest, &len))
297 	{
298           if (dwType == REG_EXPAND_SZ)
299 	  {
300 	    ExpandEnvironmentStringsA(szDest, sTemp, MAX_PATH);
301 	    lstrcpynA(szDest, sTemp, len);
302 	  }
303 	  if (ParseFieldA (szDest, 2, sNum, 5))
304              *picon_idx=atoi(sNum);
305           else
306              *picon_idx=0; /* sometimes the icon number is missing */
307 	  ParseFieldA (szDest, 1, szDest, len);
308           PathUnquoteSpacesA(szDest);
309 	  return TRUE;
310 	}
311 	return FALSE;
312 }
313 
HCR_GetIconW(LPCWSTR szClass,LPWSTR szDest,LPCWSTR szName,DWORD len,int * picon_idx)314 BOOL HCR_GetIconW(LPCWSTR szClass, LPWSTR szDest, LPCWSTR szName, DWORD len, int* picon_idx)
315 {
316 	HKEY	hkey;
317 	WCHAR	sTemp[MAX_PATH];
318 	BOOL	ret = FALSE;
319 
320 	TRACE("%s\n",debugstr_w(szClass) );
321 
322 	lstrcpynW(sTemp, szClass, MAX_PATH);
323 	lstrcatW(sTemp, L"\\DefaultIcon");
324 
325 	if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, sTemp, 0, KEY_READ, &hkey))
326 	{
327 	  ret = HCR_RegGetIconW(hkey, szDest, szName, len, picon_idx);
328 	  RegCloseKey(hkey);
329 	}
330 
331         if(ret)
332             TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx);
333         else
334             TRACE("-- not found\n");
335 
336 	return ret;
337 }
338 
HCR_GetIconA(LPCSTR szClass,LPSTR szDest,LPCSTR szName,DWORD len,int * picon_idx)339 BOOL HCR_GetIconA(LPCSTR szClass, LPSTR szDest, LPCSTR szName, DWORD len, int* picon_idx)
340 {
341 	HKEY	hkey;
342 	char	sTemp[MAX_PATH];
343 	BOOL	ret = FALSE;
344 
345 	TRACE("%s\n",szClass );
346 
347 	sprintf(sTemp, "%s\\DefaultIcon",szClass);
348 
349 	if (!RegOpenKeyExA(HKEY_CLASSES_ROOT, sTemp, 0, KEY_READ, &hkey))
350 	{
351 	  ret = HCR_RegGetIconA(hkey, szDest, szName, len, picon_idx);
352 	  RegCloseKey(hkey);
353 	}
354 
355     if (ret)
356         TRACE("-- %s %i\n", szDest, *picon_idx);
357     else
358         TRACE("-- not found\n");
359 
360 	return ret;
361 }
362 
363 #ifdef __REACTOS__
HCU_GetIconW(LPCWSTR szClass,LPWSTR szDest,LPCWSTR szName,DWORD len,int * picon_idx)364 BOOL HCU_GetIconW(LPCWSTR szClass, LPWSTR szDest, LPCWSTR szName, DWORD len, int* picon_idx)
365 {
366     HKEY hkey;
367     WCHAR sTemp[MAX_PATH];
368     BOOL ret = FALSE;
369 
370     TRACE("%s\n", debugstr_w(szClass));
371 
372     StringCchPrintfW(sTemp, _countof(sTemp), L"%s\\DefaultIcon", szClass);
373 
374     if (!RegOpenKeyExW(HKEY_CURRENT_USER, sTemp, 0, KEY_READ, &hkey))
375     {
376         ret = HCR_RegGetIconW(hkey, szDest, szName, len, picon_idx);
377         RegCloseKey(hkey);
378     }
379 
380     if (ret)
381         TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx);
382     else
383         TRACE("-- not found\n");
384 
385     return ret;
386 }
387 
HLM_GetIconW(int reg_idx,LPWSTR szDest,DWORD len,int * picon_idx)388 BOOL HLM_GetIconW(int reg_idx, LPWSTR szDest, DWORD len, int* picon_idx)
389 {
390     HKEY hkey;
391     WCHAR sTemp[5];
392     BOOL ret = FALSE;
393 
394     TRACE("%d\n", reg_idx);
395 
396     StringCchPrintfW(sTemp, _countof(sTemp), L"%d", reg_idx);
397 
398     if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE,
399                        L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons",
400                        0,
401                        KEY_READ,
402                        &hkey))
403     {
404         ret = HCR_RegGetIconW(hkey, szDest, sTemp, len, picon_idx);
405         RegCloseKey(hkey);
406     }
407 
408     if (ret)
409         TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx);
410     else
411         TRACE("-- not found\n");
412 
413     return ret;
414 }
415 #endif
416 
417 /***************************************************************************************
418 *	HCR_GetClassName	[internal]
419 *
420 * Gets the name of a registered class
421 */
HCR_GetClassNameW(REFIID riid,LPWSTR szDest,DWORD len)422 BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len)
423 {
424 	HKEY	hkey;
425 	BOOL ret = FALSE;
426 	DWORD buflen = len;
427 #ifdef __REACTOS__
428         WCHAR szName[100];
429         LPOLESTR pStr;
430 #endif
431 
432  	szDest[0] = 0;
433 
434 #ifdef __REACTOS__
435         if (StringFromCLSID(riid, &pStr) == S_OK)
436         {
437             DWORD dwLen = buflen * sizeof(WCHAR);
438             swprintf(szName, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", pStr);
439             if (!RegGetValueW(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, NULL, (PVOID)szDest, &dwLen))
440             {
441                 ret = TRUE;
442             }
443             CoTaskMemFree(pStr);
444         }
445         if (!ret && HCR_RegOpenClassIDKey(riid, &hkey))
446 #else
447 	if (HCR_RegOpenClassIDKey(riid, &hkey))
448 #endif
449 	{
450           if (!RegLoadMUIStringW(hkey, L"LocalizedString", szDest, len, NULL, 0, NULL) ||
451               !RegQueryValueExW(hkey, L"", 0, NULL, (LPBYTE)szDest, &len))
452           {
453 	    ret = TRUE;
454 	  }
455 	  RegCloseKey(hkey);
456 	}
457 
458 	if (!ret || !szDest[0])
459 	{
460 	  if(IsEqualIID(riid, &CLSID_ShellDesktop))
461 	  {
462 	    if (LoadStringW(shell32_hInstance, IDS_DESKTOP, szDest, buflen))
463 	      ret = TRUE;
464 	  }
465 	  else if (IsEqualIID(riid, &CLSID_MyComputer))
466 	  {
467 	    if(LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen))
468 	      ret = TRUE;
469 	  }
470 #ifdef __REACTOS__
471           else if (IsEqualIID(riid, &CLSID_MyDocuments))
472           {
473               if(LoadStringW(shell32_hInstance, IDS_PERSONAL, szDest, buflen))
474                   ret = TRUE;
475           }
476           else if (IsEqualIID(riid, &CLSID_RecycleBin))
477           {
478               if(LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_FOLDER_NAME, szDest, buflen))
479                   ret = TRUE;
480           }
481           else if (IsEqualIID(riid, &CLSID_ControlPanel))
482           {
483               if(LoadStringW(shell32_hInstance, IDS_CONTROLPANEL, szDest, buflen))
484                   ret = TRUE;
485           }
486           else if (IsEqualIID(riid, &CLSID_AdminFolderShortcut))
487           {
488               if(LoadStringW(shell32_hInstance, IDS_ADMINISTRATIVETOOLS, szDest, buflen))
489                   ret = TRUE;
490           }
491 #endif
492 	}
493 	TRACE("-- %s\n", debugstr_w(szDest));
494 	return ret;
495 }
496 
HCR_GetClassNameA(REFIID riid,LPSTR szDest,DWORD len)497 BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len)
498 {	HKEY	hkey;
499 	BOOL ret = FALSE;
500 	DWORD buflen = len;
501 #ifdef __REACTOS__
502         CHAR szName[100];
503         LPOLESTR pStr;
504 #endif
505 
506 	szDest[0] = 0;
507 
508 #ifdef __REACTOS__
509         if (StringFromCLSID(riid, &pStr) == S_OK)
510         {
511             DWORD dwLen = buflen * sizeof(CHAR);
512             sprintf(szName, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%S", pStr);
513             if (!RegGetValueA(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, NULL, (PVOID)szDest, &dwLen))
514             {
515                 ret = TRUE;
516             }
517             CoTaskMemFree(pStr);
518         }
519         if (!ret && HCR_RegOpenClassIDKey(riid, &hkey))
520 #else
521 	if (HCR_RegOpenClassIDKey(riid, &hkey))
522 #endif
523 	{
524           if (!RegLoadMUIStringA(hkey,"LocalizedString",szDest,len,NULL,0,NULL) ||
525               !RegQueryValueExA(hkey,"",0,NULL,(LPBYTE)szDest,&len))
526           {
527 	    ret = TRUE;
528 	  }
529 	  RegCloseKey(hkey);
530 	}
531 
532 	if (!ret || !szDest[0])
533 	{
534 	  if(IsEqualIID(riid, &CLSID_ShellDesktop))
535 	  {
536 	    if (LoadStringA(shell32_hInstance, IDS_DESKTOP, szDest, buflen))
537 	      ret = TRUE;
538 	  }
539 	  else if (IsEqualIID(riid, &CLSID_MyComputer))
540 	  {
541 	    if(LoadStringA(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen))
542 	      ret = TRUE;
543 	  }
544 #ifdef __REACTOS__
545           else if (IsEqualIID(riid, &CLSID_MyDocuments))
546           {
547               if(LoadStringA(shell32_hInstance, IDS_PERSONAL, szDest, buflen))
548                   ret = TRUE;
549           }
550           else if (IsEqualIID(riid, &CLSID_RecycleBin))
551           {
552               if(LoadStringA(shell32_hInstance, IDS_RECYCLEBIN_FOLDER_NAME, szDest, buflen))
553                   ret = TRUE;
554           }
555           else if (IsEqualIID(riid, &CLSID_ControlPanel))
556           {
557               if(LoadStringA(shell32_hInstance, IDS_CONTROLPANEL, szDest, buflen))
558                   ret = TRUE;
559           }
560           else if (IsEqualIID(riid, &CLSID_AdminFolderShortcut))
561           {
562               if(LoadStringA(shell32_hInstance, IDS_ADMINISTRATIVETOOLS, szDest, buflen))
563                   ret = TRUE;
564           }
565 #endif
566 	}
567 
568 	TRACE("-- (%s)\n", szDest);
569 
570 	return ret;
571 }
572 
573 /******************************************************************************
574  * HCR_GetFolderAttributes [Internal]
575  *
576  * Query the registry for a shell folders' attributes
577  *
578  * PARAMS
579  *  pidlFolder    [I]  A simple pidl of type PT_GUID.
580  *  pdwAttributes [IO] In: Attributes to be queried, OUT: Resulting attributes.
581  *
582  * RETURNS
583  *  TRUE:  Found information for the attributes in the registry
584  *  FALSE: No attribute information found
585  *
586  * NOTES
587  *  If queried for an attribute, which is set in the CallForAttributes registry
588  *  value, the function binds to the shellfolder objects and queries it.
589  */
HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder,LPDWORD pdwAttributes)590 BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD pdwAttributes)
591 {
592     HKEY hSFKey;
593     LPOLESTR pwszCLSID;
594     LONG lResult;
595     DWORD dwTemp, dwLen;
596     WCHAR wszShellFolderKey[] = L"CLSID\\{00021400-0000-0000-C000-000000000046}\\ShellFolder";
597 
598     TRACE("(pidlFolder=%p, pdwAttributes=%p)\n", pidlFolder, pdwAttributes);
599 
600     if (!_ILIsPidlSimple(pidlFolder)) {
601         static BOOL firstHit = TRUE;
602         if (firstHit) {
603             ERR("should be called for simple PIDL's only!\n");
604             firstHit = FALSE;
605         }
606         return FALSE;
607     }
608 
609     if (!_ILIsDesktop(pidlFolder)) {
610         if (FAILED(StringFromCLSID(_ILGetGUIDPointer(pidlFolder), &pwszCLSID))) return FALSE;
611         memcpy(&wszShellFolderKey[6], pwszCLSID, 38 * sizeof(WCHAR));
612         CoTaskMemFree(pwszCLSID);
613     }
614 
615     lResult = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszShellFolderKey, 0, KEY_READ, &hSFKey);
616 #ifdef __REACTOS__
617     if (lResult != ERROR_SUCCESS)
618     {
619         ERR("Cannot open key: %ls\n", wszShellFolderKey);
620         return FALSE;
621     }
622 #else
623     if (lResult != ERROR_SUCCESS) return FALSE;
624 #endif
625 
626     dwLen = sizeof(DWORD);
627     lResult = RegQueryValueExW(hSFKey, L"CallForAttributes", 0, NULL, (LPBYTE)&dwTemp, &dwLen);
628     if ((lResult == ERROR_SUCCESS) && (dwTemp & *pdwAttributes)) {
629         LPSHELLFOLDER psfDesktop, psfFolder;
630         HRESULT hr;
631 
632         RegCloseKey(hSFKey);
633         hr = SHGetDesktopFolder(&psfDesktop);
634         if (SUCCEEDED(hr)) {
635             hr = IShellFolder_BindToObject(psfDesktop, pidlFolder, NULL, &IID_IShellFolder,
636                                            (LPVOID*)&psfFolder);
637             if (SUCCEEDED(hr)) {
638                 hr = IShellFolder_GetAttributesOf(psfFolder, 0, NULL, pdwAttributes);
639                 IShellFolder_Release(psfFolder);
640             }
641             IShellFolder_Release(psfDesktop);
642         }
643         if (FAILED(hr)) return FALSE;
644     } else {
645         lResult = RegQueryValueExW(hSFKey, L"Attributes", 0, NULL, (LPBYTE)&dwTemp, &dwLen);
646         RegCloseKey(hSFKey);
647         if (lResult == ERROR_SUCCESS) {
648             *pdwAttributes &= dwTemp;
649         } else {
650             return FALSE;
651         }
652     }
653 
654     TRACE("-- *pdwAttributes == 0x%08x\n", *pdwAttributes);
655 
656     return TRUE;
657 }
658