- Clear bits in structure passed to IOleCommandTarget_QueryStatus to
[wine] / dlls / shell32 / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include "wine/debug.h"
29 #include "winerror.h"
30 #include "winreg.h"
31
32 #include "shlobj.h"
33 #include "shell32_main.h"
34 #include "shlguid.h"
35 #include "shresdef.h"
36 #include "shlwapi.h"
37 #include "wine/unicode.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(shell);
40
41 #define MAX_EXTENSION_LENGTH 20
42
43 BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, DWORD len, BOOL bPrependDot)
44 {       
45         HKEY    hkey;
46         WCHAR   szTemp[MAX_EXTENSION_LENGTH + 2];
47
48         TRACE("%s %p\n", debugstr_w(szExtension), debugstr_w(szFileType));
49
50     /* added because we do not want to have double dots */
51     if (szExtension[0] == '.')
52         bPrependDot = 0;
53
54         if (bPrependDot)
55           szTemp[0] = '.';
56
57         lstrcpynW(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH);
58
59         if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szTemp, 0, 0x02000000, &hkey))
60         { 
61           return FALSE;
62         }
63
64         if (RegQueryValueW(hkey, NULL, szFileType, &len))
65         { 
66           RegCloseKey(hkey);
67           return FALSE;
68         }
69
70         RegCloseKey(hkey);
71
72         TRACE("--UE;\n} %s\n", debugstr_w(szFileType));
73
74         return TRUE;
75 }
76
77 BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, DWORD len, BOOL bPrependDot)
78 {
79         HKEY    hkey;
80         char    szTemp[MAX_EXTENSION_LENGTH + 2];
81
82         TRACE("%s %p\n", szExtension, szFileType);
83
84     /* added because we do not want to have double dots */
85     if (szExtension[0] == '.')
86         bPrependDot = 0;
87
88         if (bPrependDot)
89           szTemp[0] = '.';
90
91         lstrcpynA(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH);
92
93         if (RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, 0x02000000, &hkey))
94         { 
95           return FALSE;
96         }
97
98         if (RegQueryValueA(hkey, NULL, szFileType, &len))
99         { 
100           RegCloseKey(hkey);
101           return FALSE;
102         }
103
104         RegCloseKey(hkey);
105
106         TRACE("--UE;\n} %s\n", szFileType);
107
108         return TRUE;
109 }
110
111
112 BOOL HCR_GetExecuteCommandW(LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len)
113 {
114         static const WCHAR swShell[] = {'\\','s','h','e','l','l','\\',0};
115         static const WCHAR swCommand[] = {'\\','c','o','m','m','a','n','d',0};
116         WCHAR   sTemp[MAX_PATH];
117
118         TRACE("%s %s %p\n",debugstr_w(szClass), debugstr_w(szVerb), szDest);
119
120         lstrcpyW(sTemp, szClass);
121         lstrcatW(sTemp, swShell);
122         lstrcatW(sTemp, szVerb);
123         lstrcatW(sTemp, swCommand);
124
125         if (ERROR_SUCCESS == SHGetValueW(HKEY_CLASSES_ROOT, sTemp, NULL, NULL, szDest, &len)) {
126             TRACE("-- %s\n", debugstr_w(szDest) );
127             return TRUE;
128         }
129         return FALSE;
130 }
131
132 BOOL HCR_GetExecuteCommandA(LPCSTR szClass, LPCSTR szVerb, LPSTR szDest, DWORD len)
133 {
134         char    sTemp[MAX_PATH];
135
136         TRACE("%s %s\n",szClass, szVerb );
137
138         snprintf(sTemp, MAX_PATH, "%s\\shell\\%s\\command",szClass, szVerb);
139
140         if (ERROR_SUCCESS == SHGetValueA(HKEY_CLASSES_ROOT, sTemp, NULL, NULL, szDest, &len)) {
141             TRACE("-- %s\n", debugstr_a(szDest) );
142             return TRUE;
143         }
144         return FALSE;
145 }
146
147 /***************************************************************************************
148 *       HCR_GetDefaultIcon      [internal]
149 *
150 * Gets the icon for a filetype
151 */
152 static BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey)
153 {
154         char    xriid[50];
155     sprintf( xriid, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
156                  riid->Data1, riid->Data2, riid->Data3,
157                  riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
158                  riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] );
159
160         TRACE("%s\n",xriid );
161
162         return !RegOpenKeyExA(HKEY_CLASSES_ROOT, xriid, 0, KEY_READ, hkey);
163 }
164
165 static BOOL HCR_RegGetDefaultIconW(HKEY hkey, LPWSTR szDest, DWORD len, LPDWORD dwNr)
166 {
167         DWORD dwType;
168         WCHAR sTemp[MAX_PATH];
169         WCHAR sNum[5];
170
171         if (!RegQueryValueExW(hkey, NULL, 0, &dwType, (LPBYTE)szDest, &len))
172         {
173       if (dwType == REG_EXPAND_SZ)
174           {
175             ExpandEnvironmentStringsW(szDest, sTemp, MAX_PATH);
176             lstrcpynW(szDest, sTemp, len);
177           }
178           if (ParseFieldW (szDest, 2, sNum, 5))
179              *dwNr = atoiW(sNum);
180           else
181              *dwNr=0; /* sometimes the icon number is missing */
182           ParseFieldW (szDest, 1, szDest, len);
183           return TRUE;
184         }
185         return FALSE;
186 }
187
188 static BOOL HCR_RegGetDefaultIconA(HKEY hkey, LPSTR szDest, DWORD len, LPDWORD dwNr)
189 {
190         DWORD dwType;
191         char sTemp[MAX_PATH];
192         char  sNum[5];
193
194         if (!RegQueryValueExA(hkey, NULL, 0, &dwType, szDest, &len))
195         {
196       if (dwType == REG_EXPAND_SZ)
197           {
198             ExpandEnvironmentStringsA(szDest, sTemp, MAX_PATH);
199             lstrcpynA(szDest, sTemp, len);
200           }
201           if (ParseFieldA (szDest, 2, sNum, 5))
202              *dwNr=atoi(sNum);
203           else
204              *dwNr=0; /* sometimes the icon number is missing */
205           ParseFieldA (szDest, 1, szDest, len);
206           return TRUE;
207         }
208         return FALSE;
209 }
210
211 BOOL HCR_GetDefaultIconW(LPCWSTR szClass, LPWSTR szDest, DWORD len, LPDWORD dwNr)
212 {
213         static const WCHAR swDefaultIcon[] = {'\\','D','e','f','a','u','l','t','I','c','o','n',0};
214         HKEY    hkey;
215         WCHAR   sTemp[MAX_PATH];
216         BOOL    ret = FALSE;
217
218         TRACE("%s\n",debugstr_w(szClass) );
219
220         lstrcpynW(sTemp, szClass, MAX_PATH);
221         lstrcatW(sTemp, swDefaultIcon);
222
223         if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, sTemp, 0, 0x02000000, &hkey))
224         {
225           ret = HCR_RegGetDefaultIconW(hkey, szDest, len, dwNr);
226           RegCloseKey(hkey);
227         }
228         TRACE("-- %s %li\n", debugstr_w(szDest), *dwNr );
229         return ret;
230 }
231
232 BOOL HCR_GetDefaultIconA(LPCSTR szClass, LPSTR szDest, DWORD len, LPDWORD dwNr)
233 {
234         HKEY    hkey;
235         char    sTemp[MAX_PATH];
236         BOOL    ret = FALSE;
237
238         TRACE("%s\n",szClass );
239
240         sprintf(sTemp, "%s\\DefaultIcon",szClass);
241
242         if (!RegOpenKeyExA(HKEY_CLASSES_ROOT, sTemp, 0, 0x02000000, &hkey))
243         {
244           ret = HCR_RegGetDefaultIconA(hkey, szDest, len, dwNr);
245           RegCloseKey(hkey);
246         }
247         TRACE("-- %s %li\n", szDest, *dwNr );
248         return ret;
249 }
250
251 BOOL HCR_GetDefaultIconFromGUIDW(REFIID riid, LPWSTR szDest, DWORD len, LPDWORD dwNr)
252 {
253         HKEY    hkey;
254         BOOL    ret = FALSE;
255
256         if (HCR_RegOpenClassIDKey(riid, &hkey))
257         {
258           ret = HCR_RegGetDefaultIconW(hkey, szDest, len, dwNr);
259           RegCloseKey(hkey);
260         }
261         TRACE("-- %s %li\n", debugstr_w(szDest), *dwNr );
262         return ret;
263 }
264
265 /***************************************************************************************
266 *       HCR_GetClassName        [internal]
267 *
268 * Gets the name of a registred class
269 */
270 static WCHAR swEmpty[] = {0};
271
272 BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len)
273 {       
274         HKEY    hkey;
275         BOOL ret = FALSE;
276         DWORD buflen = len;
277
278         szDest[0] = 0;
279         if (HCR_RegOpenClassIDKey(riid, &hkey))
280         {
281           if (!RegQueryValueExW(hkey, swEmpty, 0, NULL, (LPBYTE)szDest, &len))
282           {
283             ret = TRUE;
284           }
285           RegCloseKey(hkey);
286         }
287
288         if (!ret || !szDest[0])
289         {
290           if(IsEqualIID(riid, &CLSID_ShellDesktop))
291           {
292             if (LoadStringW(shell32_hInstance, IDS_DESKTOP, szDest, buflen))
293               ret = TRUE;
294           }
295           else if (IsEqualIID(riid, &CLSID_MyComputer))
296           {
297             if(LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen))
298               ret = TRUE;
299           }
300         }
301         TRACE("-- %s\n", debugstr_w(szDest));
302         return ret;
303 }
304
305 BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len)
306 {       HKEY    hkey;
307         BOOL ret = FALSE;
308         DWORD buflen = len;
309
310         szDest[0] = 0;
311         if (HCR_RegOpenClassIDKey(riid, &hkey))
312         {
313           if (!RegQueryValueExA(hkey,"",0,NULL,szDest,&len))
314           {
315             ret = TRUE;
316           }
317           RegCloseKey(hkey);
318         }
319
320         if (!ret || !szDest[0])
321         {
322           if(IsEqualIID(riid, &CLSID_ShellDesktop))
323           {
324             if (LoadStringA(shell32_hInstance, IDS_DESKTOP, szDest, buflen))
325               ret = TRUE;
326           }
327           else if (IsEqualIID(riid, &CLSID_MyComputer))
328           {
329             if(LoadStringA(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen))
330               ret = TRUE;
331           }
332         }
333
334         TRACE("-- %s\n", szDest);
335
336         return ret;
337 }
338
339 /***************************************************************************************
340 *       HCR_GetFolderAttributes [internal]
341 *
342 * gets the folder attributes of a class
343 *
344 * FIXME
345 *       verify the defaultvalue for *szDest
346 */
347 BOOL HCR_GetFolderAttributes (REFIID riid, LPDWORD szDest)
348 {       HKEY    hkey;
349         char    xriid[60];
350         DWORD   attributes;
351         DWORD   len = 4;
352
353         sprintf( xriid, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
354                  riid->Data1, riid->Data2, riid->Data3,
355                  riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
356                  riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] );
357         TRACE("%s\n",xriid );
358
359         if (!szDest) return FALSE;
360         *szDest = SFGAO_FOLDER|SFGAO_FILESYSTEM;
361
362         strcat (xriid, "\\ShellFolder");
363
364         if (RegOpenKeyExA(HKEY_CLASSES_ROOT,xriid,0,KEY_READ,&hkey))
365         {
366           return FALSE;
367         }
368
369         if (RegQueryValueExA(hkey,"Attributes",0,NULL,(LPBYTE)&attributes,&len))
370         {
371           RegCloseKey(hkey);
372           return FALSE;
373         }
374
375         RegCloseKey(hkey);
376
377         TRACE("-- 0x%08lx\n", attributes);
378
379         *szDest = attributes;
380
381         return TRUE;
382 }
383
384 typedef struct
385 {       ICOM_VFIELD(IQueryAssociations);
386         DWORD   ref;
387 } IQueryAssociationsImpl;
388
389 static struct ICOM_VTABLE(IQueryAssociations) qavt;
390
391 /**************************************************************************
392 *  IQueryAssociations_Constructor
393 */
394 IQueryAssociations* IQueryAssociations_Constructor(void)
395 {
396         IQueryAssociationsImpl* ei;
397
398         ei=(IQueryAssociationsImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IQueryAssociationsImpl));
399         ei->ref=1;
400         ICOM_VTBL(ei) = &qavt;
401
402         TRACE("(%p)\n",ei);
403         return (IQueryAssociations *)ei;
404 }
405 /**************************************************************************
406  *  IQueryAssociations_QueryInterface
407  */
408 static HRESULT WINAPI IQueryAssociations_fnQueryInterface(
409         IQueryAssociations * iface,
410         REFIID riid,
411         LPVOID *ppvObj)
412 {
413         ICOM_THIS(IQueryAssociationsImpl,iface);
414
415          TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
416
417         *ppvObj = NULL;
418
419         if(IsEqualIID(riid, &IID_IUnknown))             /*IUnknown*/
420         {
421           *ppvObj = This;
422         }
423         else if(IsEqualIID(riid, &IID_IQueryAssociations))      /*IExtractIcon*/
424         {
425           *ppvObj = (IQueryAssociations*)This;
426         }
427
428         if(*ppvObj)
429         {
430           IQueryAssociations_AddRef((IQueryAssociations*) *ppvObj);
431           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
432           return S_OK;
433         }
434         TRACE("-- Interface: E_NOINTERFACE\n");
435         return E_NOINTERFACE;
436 }
437
438 /**************************************************************************
439 *  IQueryAssociations_AddRef
440 */
441 static ULONG WINAPI IQueryAssociations_fnAddRef(IQueryAssociations * iface)
442 {
443         ICOM_THIS(IQueryAssociationsImpl,iface);
444
445         TRACE("(%p)->(count=%lu)\n",This, This->ref );
446
447         return ++(This->ref);
448 }
449 /**************************************************************************
450 *  IQueryAssociations_Release
451 */
452 static ULONG WINAPI IQueryAssociations_fnRelease(IQueryAssociations * iface)
453 {
454         ICOM_THIS(IQueryAssociationsImpl,iface);
455
456         TRACE("(%p)->()\n",This);
457
458         if (!--(This->ref))
459         {
460           TRACE(" destroying IExtractIcon(%p)\n",This);
461           HeapFree(GetProcessHeap(),0,This);
462           return 0;
463         }
464         return This->ref;
465 }
466
467 static HRESULT WINAPI IQueryAssociations_fnInit(
468         IQueryAssociations * iface,
469         ASSOCF flags,
470         LPCWSTR pszAssoc,
471         HKEY hkProgid,
472         HWND hwnd)
473 {
474         return E_NOTIMPL;
475 }
476
477 static HRESULT WINAPI IQueryAssociations_fnGetString(
478         IQueryAssociations * iface,
479         ASSOCF flags,
480         ASSOCSTR str,
481         LPCWSTR pszExtra,
482         LPWSTR pszOut,
483         DWORD *pcchOut)
484 {
485         return E_NOTIMPL;
486 }
487
488 static HRESULT WINAPI IQueryAssociations_fnGetKey(
489         IQueryAssociations * iface,
490         ASSOCF flags,
491         ASSOCKEY key,
492         LPCWSTR pszExtra,
493         HKEY *phkeyOut)
494 {
495         return E_NOTIMPL;
496 }
497
498 static HRESULT WINAPI IQueryAssociations_fnGetData(
499         IQueryAssociations * iface,
500         ASSOCF flags,
501         ASSOCDATA data,
502         LPCWSTR pszExtra,
503         LPVOID pvOut,
504         DWORD *pcbOut)
505 {
506         return E_NOTIMPL;
507 }
508 static HRESULT WINAPI IQueryAssociations_fnGetEnum(
509         IQueryAssociations * iface,
510         ASSOCF flags,
511         ASSOCENUM assocenum,
512         LPCWSTR pszExtra,
513         REFIID riid,
514         LPVOID *ppvOut)
515 {
516         return E_NOTIMPL;
517 }
518
519 static struct ICOM_VTABLE(IQueryAssociations) qavt =
520 {
521         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
522         IQueryAssociations_fnQueryInterface,
523         IQueryAssociations_fnAddRef,
524         IQueryAssociations_fnRelease,
525         IQueryAssociations_fnInit,
526         IQueryAssociations_fnGetString,
527         IQueryAssociations_fnGetKey,
528         IQueryAssociations_fnGetData,
529         IQueryAssociations_fnGetEnum
530 };