Added winebuild support for generating a .dbg.c file containing the
[wine] / dlls / shell32 / shlfolder.c
1 /*
2  *      Shell Folder stuff
3  *
4  *      Copyright 1997  Marcus Meissner
5  *      Copyright 1998, 1999    Juergen Schmied
6  *      
7  *      IShellFolder2 and related interfaces
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27
28 #include "winerror.h"
29 #include "winbase.h"
30 #include "winreg.h"
31
32 #include "oleidl.h"
33 #include "shlguid.h"
34
35 #include "pidl.h"
36 #include "wine/obj_base.h"
37 #include "wine/obj_dragdrop.h"
38 #include "wine/obj_shellfolder.h"
39 #include "undocshell.h"
40 #include "shell32_main.h"
41 #include "shresdef.h"
42 #include "shlwapi.h"
43 #include "shellfolder.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(shell);
47
48
49 /***************************************************************************
50  * debughelper: print out the return adress
51  *  helps especially to track down unbalanced AddRef/Release
52  */
53 #define MEM_DEBUG 0
54
55 #if MEM_DEBUG
56 #define _CALL_TRACE TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 ));
57 #else
58 #define _CALL_TRACE
59 #endif
60
61 typedef struct
62 {
63         int     colnameid;
64         int     pcsFlags;
65         int     fmt;
66         int     cxChar;
67         
68 } shvheader;
69
70 /***************************************************************************
71  *  GetNextElement (internal function)
72  *
73  * gets a part of a string till the first backslash
74  *
75  * PARAMETERS
76  *  pszNext [IN] string to get the element from
77  *  pszOut  [IN] pointer to buffer whitch receives string
78  *  dwOut   [IN] length of pszOut
79  *
80  *  RETURNS
81  *    LPSTR pointer to first, not yet parsed char
82  */
83
84 static LPCWSTR GetNextElementW(LPCWSTR pszNext,LPWSTR pszOut,DWORD dwOut)
85 {       LPCWSTR   pszTail = pszNext;
86         DWORD dwCopy;
87         TRACE("(%s %p 0x%08lx)\n",debugstr_w(pszNext),pszOut,dwOut);
88
89         *pszOut=0x0000;
90         
91         if(!pszNext || !*pszNext)
92           return NULL;
93
94         while(*pszTail && (*pszTail != (WCHAR)'\\'))
95           pszTail++;
96
97         dwCopy = (WCHAR*)pszTail - (WCHAR*)pszNext + 1;
98         lstrcpynW(pszOut, pszNext, (dwOut<dwCopy)? dwOut : dwCopy);
99
100         if(*pszTail)
101            pszTail++;
102         else
103            pszTail = NULL;
104
105         TRACE("--(%s %s 0x%08lx %p)\n",debugstr_w(pszNext),debugstr_w(pszOut),dwOut,pszTail);
106         return pszTail;
107 }
108
109 static HRESULT SHELL32_ParseNextElement(
110         HWND hwndOwner,
111         IShellFolder2 * psf,
112         LPITEMIDLIST * pidlInOut,
113         LPOLESTR szNext,
114         DWORD *pEaten,
115         DWORD *pdwAttributes)
116 {
117         HRESULT         hr = E_OUTOFMEMORY;
118         LPITEMIDLIST    pidlOut, pidlTemp = NULL;
119         IShellFolder    *psfChild;
120         
121         TRACE("(%p, %p, %s)\n",psf, pidlInOut ? *pidlInOut : NULL, debugstr_w(szNext));
122
123
124         /* get the shellfolder for the child pidl and let it analyse further */
125         hr = IShellFolder_BindToObject(psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
126
127         if (psfChild)
128         {
129           hr = IShellFolder_ParseDisplayName(psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes);
130           IShellFolder_Release(psfChild);
131
132           pidlTemp = ILCombine(*pidlInOut, pidlOut);
133
134           if (pidlOut) 
135             ILFree(pidlOut);
136         }
137
138         ILFree(*pidlInOut);
139         *pidlInOut = pidlTemp;
140
141         TRACE("-- pidl=%p ret=0x%08lx\n", pidlInOut? *pidlInOut: NULL, hr);
142         return hr;      
143 }
144
145 /***********************************************************************
146  *      SHELL32_CoCreateInitSF
147  *
148  *      creates a initialized shell folder
149  */
150 static HRESULT SHELL32_CoCreateInitSF (
151         LPITEMIDLIST pidlRoot,
152         LPITEMIDLIST pidlChild,
153         REFCLSID clsid,
154         REFIID iid,
155         LPVOID * ppvOut)
156 {
157         HRESULT hr;
158         LPITEMIDLIST    absPidl;
159         IShellFolder2   *pShellFolder;
160         IPersistFolder  *pPersistFolder;
161
162         TRACE("%p %p\n", pidlRoot, pidlChild);
163
164         *ppvOut = NULL;
165         
166         /* we have to ask first for IPersistFolder, some special folders are expecting this */
167         hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IPersistFolder, (LPVOID*)&pPersistFolder);
168         if (SUCCEEDED(hr))
169         {
170           hr = IPersistFolder_QueryInterface(pPersistFolder, iid, (LPVOID*)&pShellFolder);
171           if (SUCCEEDED(hr))
172           {
173             absPidl = ILCombine (pidlRoot, pidlChild);
174             hr = IPersistFolder_Initialize(pPersistFolder, absPidl);
175             IPersistFolder_Release(pPersistFolder);
176             SHFree(absPidl);
177             *ppvOut = pShellFolder;
178           }
179         }
180
181         TRACE("-- ret=0x%08lx\n", hr);
182         return hr;
183 }
184
185 static HRESULT SHELL32_GetDisplayNameOfChild(
186         IShellFolder2 * psf,
187         LPCITEMIDLIST pidl,
188         DWORD dwFlags,
189         LPSTR szOut,
190         DWORD dwOutLen)
191 {
192         LPITEMIDLIST    pidlFirst, pidlNext;
193         IShellFolder2 * psfChild;
194         HRESULT         hr = E_OUTOFMEMORY;
195         STRRET strTemp;
196         
197         TRACE("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n",psf,pidl,dwFlags,szOut, dwOutLen);
198         pdump(pidl);
199         
200         if ((pidlFirst = ILCloneFirst(pidl)))
201         { 
202           hr = IShellFolder_BindToObject(psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
203           if (SUCCEEDED(hr))
204           {
205             pidlNext = ILGetNext(pidl);
206
207             hr = IShellFolder_GetDisplayNameOf(psfChild, pidlNext, dwFlags | SHGDN_INFOLDER, &strTemp);
208             if (SUCCEEDED(hr))
209             {
210               hr = StrRetToStrNA(szOut, dwOutLen, &strTemp, pidlNext);
211             }
212
213             IShellFolder_Release(psfChild);
214           }
215           ILFree(pidlFirst);
216         }
217
218         TRACE("-- ret=0x%08lx %s\n", hr, szOut);
219
220         return hr;
221 }
222
223 /***********************************************************************
224  *  SHELL32_GetItemAttributes
225  *
226  * NOTES
227  * observerd values:
228  *  folder:     0xE0000177      FILESYSTEM | HASSUBFOLDER | FOLDER
229  *  file:       0x40000177      FILESYSTEM
230  *  drive:      0xf0000144      FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR
231  *  mycomputer: 0xb0000154      HASSUBFOLDER | FOLDER | FILESYSANCESTOR
232  *  (seems to be default for shell extensions if no registry entry exists)
233  *
234  * This functions does not set flags!! It only resets flags when nessesary.
235  */
236 static HRESULT SHELL32_GetItemAttributes(
237         IShellFolder * psf,
238         LPITEMIDLIST pidl,
239         LPDWORD pdwAttributes)
240 {
241         GUID const * clsid;
242         DWORD dwAttributes;
243         
244         TRACE("0x%08lx\n", *pdwAttributes);
245
246         if (*pdwAttributes & (0xcff3fe88))
247           WARN("attribute 0x%08lx not implemented\n", *pdwAttributes);
248         *pdwAttributes &= ~SFGAO_LINK; /* FIXME: for native filedialogs */
249
250         if (_ILIsDrive(pidl))
251         {
252           *pdwAttributes &= 0xf0000144;
253         }
254         else if ((clsid=_ILGetGUIDPointer(pidl)))
255         {
256           if (HCR_GetFolderAttributes(clsid, &dwAttributes))
257           {
258             *pdwAttributes &= dwAttributes;
259           }
260           else
261           {
262             *pdwAttributes &= 0xb0000154;
263           }       
264         }
265         else if (_ILGetDataPointer(pidl))
266         {
267           dwAttributes = _ILGetFileAttributes(pidl, NULL, 0);
268           *pdwAttributes &= ~SFGAO_FILESYSANCESTOR;
269
270           if(( SFGAO_FOLDER & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
271               *pdwAttributes &= ~(SFGAO_FOLDER|SFGAO_HASSUBFOLDER);
272
273           if(( SFGAO_HIDDEN & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN))
274               *pdwAttributes &= ~SFGAO_HIDDEN;
275
276           if(( SFGAO_READONLY & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_READONLY))
277               *pdwAttributes &= ~SFGAO_READONLY;
278         }
279         else
280         {
281           *pdwAttributes &= 0xb0000154;
282         }
283         TRACE("-- 0x%08lx\n", *pdwAttributes);
284         return S_OK;
285 }
286
287 /***********************************************************************
288 *   IShellFolder implementation
289 */
290
291 typedef struct 
292 {
293         ICOM_VFIELD(IUnknown);
294         DWORD                           ref;
295         ICOM_VTABLE(IShellFolder2)*     lpvtblShellFolder;
296         ICOM_VTABLE(IPersistFolder2)*   lpvtblPersistFolder2;
297         ICOM_VTABLE(IDropTarget)*       lpvtblDropTarget;
298         ICOM_VTABLE(ISFHelper)*         lpvtblSFHelper;
299
300         IUnknown                        *pUnkOuter;     /* used for aggregation */
301
302         CLSID*                          pclsid;
303
304         LPSTR                           sMyPath;
305         LPITEMIDLIST                    absPidl;        /* complete pidl */
306
307         UINT            cfShellIDList;                  /* clipboardformat for IDropTarget */
308         BOOL            fAcceptFmt;                     /* flag for pending Drop */
309 } IGenericSFImpl;
310
311 static struct ICOM_VTABLE(IUnknown) unkvt;
312 static struct ICOM_VTABLE(IShellFolder2) sfvt;
313 static struct ICOM_VTABLE(IPersistFolder2) psfvt;
314 static struct ICOM_VTABLE(IDropTarget) dtvt;
315 static struct ICOM_VTABLE(ISFHelper) shvt;
316
317 static IShellFolder * ISF_MyComputer_Constructor(void);
318
319 #define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder))) 
320 #define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset); 
321         
322 #define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder2))) 
323 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset); 
324         
325 #define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget))) 
326 #define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset); 
327
328 #define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper))) 
329 #define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset); 
330 /*
331   converts This to a interface pointer
332 */
333 #define _IUnknown_(This)        (IUnknown*)&(This->lpVtbl)
334 #define _IShellFolder_(This)    (IShellFolder*)&(This->lpvtblShellFolder)
335 #define _IShellFolder2_(This)   (IShellFolder2*)&(This->lpvtblShellFolder)
336 #define _IPersist_(This)        (IPersist*)&(This->lpvtblPersistFolder2)
337 #define _IPersistFolder_(This)  (IPersistFolder*)&(This->lpvtblPersistFolder2)
338 #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder2)
339 #define _IDropTarget_(This)     (IDropTarget*)&(This->lpvtblDropTarget)
340 #define _ISFHelper_(This)       (ISFHelper*)&(This->lpvtblSFHelper)
341 /**************************************************************************
342 *       registers clipboardformat once
343 */
344 static void SF_RegisterClipFmt (IGenericSFImpl * This)
345 {
346         TRACE("(%p)\n", This);
347
348         if (!This->cfShellIDList)
349         {
350           This->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
351         }
352 }
353
354 /**************************************************************************
355 *       we need a separate IUnknown to handle aggregation
356 *       (inner IUnknown)
357 */
358 static HRESULT WINAPI IUnknown_fnQueryInterface(
359         IUnknown * iface,
360         REFIID riid,
361         LPVOID *ppvObj)
362 {
363         ICOM_THIS(IGenericSFImpl, iface);
364
365         _CALL_TRACE
366         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
367
368         *ppvObj = NULL;
369
370         if(IsEqualIID(riid, &IID_IUnknown))             *ppvObj = _IUnknown_(This); 
371         else if(IsEqualIID(riid, &IID_IShellFolder))    *ppvObj = _IShellFolder_(This);
372         else if(IsEqualIID(riid, &IID_IShellFolder2))   *ppvObj = _IShellFolder_(This);
373         else if(IsEqualIID(riid, &IID_IPersist))        *ppvObj = _IPersist_(This);
374         else if(IsEqualIID(riid, &IID_IPersistFolder))  *ppvObj = _IPersistFolder_(This);
375         else if(IsEqualIID(riid, &IID_IPersistFolder2)) *ppvObj = _IPersistFolder2_(This);
376         else if(IsEqualIID(riid, &IID_ISFHelper))       *ppvObj = _ISFHelper_(This);
377         else if(IsEqualIID(riid, &IID_IDropTarget))
378         {
379           *ppvObj = _IDropTarget_(This);
380           SF_RegisterClipFmt(This);
381         }
382
383         if(*ppvObj)
384         {
385           IUnknown_AddRef((IUnknown*)(*ppvObj));
386           TRACE("-- Interface = %p\n", *ppvObj);
387           return S_OK;
388         }
389         TRACE("-- Interface: E_NOINTERFACE\n");
390         return E_NOINTERFACE;
391 }
392
393 static ULONG WINAPI IUnknown_fnAddRef(IUnknown * iface)
394 {
395         ICOM_THIS(IGenericSFImpl, iface);
396
397         _CALL_TRACE
398         TRACE("(%p)->(count=%lu)\n",This,This->ref);
399
400         shell32_ObjCount++;
401         return ++(This->ref);
402 }
403
404 static ULONG WINAPI IUnknown_fnRelease(IUnknown * iface) 
405 {
406         ICOM_THIS(IGenericSFImpl, iface);
407
408         _CALL_TRACE
409         TRACE("(%p)->(count=%lu)\n",This,This->ref);
410
411         shell32_ObjCount--;
412         if (!--(This->ref)) 
413         {
414           TRACE("-- destroying IShellFolder(%p)\n",This);
415
416           if (pdesktopfolder == _IShellFolder_(This))
417           {
418             pdesktopfolder=NULL;
419             TRACE("-- destroyed IShellFolder(%p) was Desktopfolder\n",This);
420           }
421           if(This->absPidl) SHFree(This->absPidl);
422           if(This->sMyPath) SHFree(This->sMyPath);
423           HeapFree(GetProcessHeap(),0,This);
424           return 0;
425         }
426         return This->ref;
427 }
428
429 static ICOM_VTABLE(IUnknown) unkvt = 
430 {       
431         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
432         IUnknown_fnQueryInterface,
433         IUnknown_fnAddRef,
434         IUnknown_fnRelease,
435 };
436
437 static shvheader GenericSFHeader [] =
438 {
439  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
440  { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
441  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
442  { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
443  { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
444 };
445 #define GENERICSHELLVIEWCOLUMNS 5
446
447 /**************************************************************************
448 *       IShellFolder_Constructor
449 *
450 * NOTES
451 *  creating undocumented ShellFS_Folder as part of an aggregation
452 *  {F3364BA0-65B9-11CE-A9BA-00AA004AE837}
453 *
454 * FIXME
455 *       when pUnkOuter = 0 then rrid = IID_IShellFolder is returned
456 */
457 HRESULT IFSFolder_Constructor(
458         IUnknown * pUnkOuter,
459         REFIID riid,
460         LPVOID * ppv)
461 {
462         IGenericSFImpl *        sf;
463         HRESULT hr = S_OK;
464
465         TRACE("unkOut=%p riid=%s\n",pUnkOuter, debugstr_guid(riid));
466
467         if(pUnkOuter && ! IsEqualIID(riid, &IID_IUnknown))
468         {
469           hr = CLASS_E_NOAGGREGATION;   /* forbidden by definition */
470         }
471         else
472         {
473           sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
474           if (sf)
475           {
476             sf->ref=1;
477             ICOM_VTBL(sf)=&unkvt;
478             sf->lpvtblShellFolder=&sfvt;
479             sf->lpvtblPersistFolder2=&psfvt;
480             sf->lpvtblDropTarget=&dtvt;
481             sf->lpvtblSFHelper=&shvt;
482             
483             sf->pclsid = (CLSID*)&CLSID_SFFile;
484             sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_(sf);
485             *ppv = _IUnknown_(sf);
486             hr = S_OK;
487             shell32_ObjCount++;
488           }
489           else
490           {
491             hr = E_OUTOFMEMORY;
492           }
493         }
494         return hr;
495 }
496 /**************************************************************************
497 *         IShellFolder_Constructor
498 *
499 * NOTES
500 *       THIS points to the parent folder
501 */
502
503 IShellFolder * IShellFolder_Constructor(
504         IShellFolder2 * iface,
505         LPITEMIDLIST pidl)
506 {
507         IGenericSFImpl *        sf;
508         DWORD                   dwSize=0;
509
510         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
511
512         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
513         sf->ref=1;
514
515         ICOM_VTBL(sf)=&unkvt;
516         sf->lpvtblShellFolder=&sfvt;
517         sf->lpvtblPersistFolder2=&psfvt;
518         sf->lpvtblDropTarget=&dtvt;
519         sf->lpvtblSFHelper=&shvt;
520
521         sf->pclsid = (CLSID*)&CLSID_SFFile;
522         sf->pUnkOuter = _IUnknown_(sf);
523
524         TRACE("(%p)->(parent=%p, pidl=%p)\n",sf,This, pidl);
525         pdump(pidl);
526                 
527         if(pidl && iface)                               /* do we have a pidl? */
528         {
529           int len;
530
531           sf->absPidl = ILCombine(This->absPidl, pidl); /* build a absolute pidl */
532
533           if (!_ILIsSpecialFolder(pidl))                                /* only file system paths */
534           {
535             if(This->sMyPath)                           /* get the size of the parents path */
536             {
537               dwSize += strlen(This->sMyPath) ;
538               TRACE("-- (%p)->(parent's path=%s)\n",sf, debugstr_a(This->sMyPath));
539             }   
540
541             dwSize += _ILSimpleGetText(pidl,NULL,0);            /* add the size of our name*/
542             sf->sMyPath = SHAlloc(dwSize + 2);                  /* '\0' and backslash */
543
544             if(!sf->sMyPath) return NULL;
545             *(sf->sMyPath)=0x00;
546
547             if(This->sMyPath)                           /* if the parent has a path, get it*/
548             {
549               strcpy(sf->sMyPath, This->sMyPath);
550               PathAddBackslashA (sf->sMyPath);
551             }
552
553             len = strlen(sf->sMyPath);
554             _ILSimpleGetText(pidl, sf->sMyPath + len, dwSize+2 - len);
555           }
556
557           TRACE("-- (%p)->(my pidl=%p, my path=%s)\n",sf, sf->absPidl,debugstr_a(sf->sMyPath));
558
559           pdump (sf->absPidl);
560         }
561
562         shell32_ObjCount++;
563         return _IShellFolder_(sf);
564 }
565
566 /**************************************************************************
567  *  IShellFolder_fnQueryInterface
568  *
569  * PARAMETERS
570  *  REFIID riid         [in ] Requested InterfaceID
571  *  LPVOID* ppvObject   [out] Interface* to hold the result
572  */
573 static HRESULT WINAPI IShellFolder_fnQueryInterface(
574         IShellFolder2 * iface,
575         REFIID riid,
576         LPVOID *ppvObj)
577 {
578         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
579
580         _CALL_TRACE
581         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
582
583         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
584 }
585
586 /**************************************************************************
587 *  IShellFolder_AddRef
588 */
589
590 static ULONG WINAPI IShellFolder_fnAddRef(IShellFolder2 * iface)
591 {
592         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
593
594         _CALL_TRACE
595         TRACE("(%p)->(count=%lu)\n",This,This->ref);
596
597         return IUnknown_AddRef(This->pUnkOuter);
598 }
599
600 /**************************************************************************
601  *  IShellFolder_fnRelease
602  */
603 static ULONG WINAPI IShellFolder_fnRelease(IShellFolder2 * iface) 
604 {
605         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
606
607         _CALL_TRACE
608         TRACE("(%p)->(count=%lu)\n",This,This->ref);
609
610         return IUnknown_Release(This->pUnkOuter);
611 }
612
613 /**************************************************************************
614 *               IShellFolder_fnParseDisplayName
615 * PARAMETERS
616 *  HWND          hwndOwner,      //[in ] Parent window for any message's
617 *  LPBC          pbc,            //[in ] reserved
618 *  LPOLESTR      lpszDisplayName,//[in ] "Unicode" displayname.
619 *  ULONG*        pchEaten,       //[out] (unicode) characters processed
620 *  LPITEMIDLIST* ppidl,          //[out] complex pidl to item
621 *  ULONG*        pdwAttributes   //[out] items attributes
622 *
623 * NOTES
624 *  every folder tries to parse only its own (the leftmost) pidl and creates a 
625 *  subfolder to evaluate the remaining parts
626 *  now we can parse into namespaces implemented by shell extensions
627 *
628 *  behaviour on win98:  lpszDisplayName=NULL -> chrash
629 *                       lpszDisplayName="" -> returns mycoputer-pidl
630 *
631 * FIXME: 
632 *    pdwAttributes: not set
633 *    pchEaten: not set like in windows
634 */
635 static HRESULT WINAPI IShellFolder_fnParseDisplayName(
636         IShellFolder2 * iface,
637         HWND hwndOwner,
638         LPBC pbcReserved,
639         LPOLESTR lpszDisplayName,
640         DWORD *pchEaten,
641         LPITEMIDLIST *ppidl,
642         DWORD *pdwAttributes)
643 {
644         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
645
646         HRESULT         hr = E_OUTOFMEMORY;
647         LPCWSTR         szNext=NULL;
648         WCHAR           szElement[MAX_PATH];
649         CHAR            szTempA[MAX_PATH], szPath[MAX_PATH];
650         LPITEMIDLIST    pidlTemp=NULL;
651         
652         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
653         This,hwndOwner,pbcReserved,lpszDisplayName,
654         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
655
656         if (!lpszDisplayName || !ppidl) return E_INVALIDARG;
657
658         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
659         
660         if (*lpszDisplayName)
661         {       
662           /* get the next element */
663           szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
664
665           /* build the full pathname to the element */
666           WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
667           strcpy(szPath, This->sMyPath);
668           PathAddBackslashA(szPath);
669           strcat(szPath, szTempA);
670
671           /* get the pidl */
672           pidlTemp = SHSimpleIDListFromPathA(szPath);
673
674           if (pidlTemp)
675           {
676             /* try to analyse the next element */
677             if (szNext && *szNext)
678             {
679               hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
680             }
681             else
682             {
683                if (pdwAttributes && *pdwAttributes)
684                {
685                  SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
686 /*               WIN32_FIND_DATAA fd;
687                  SHGetDataFromIDListA(_IShellFolder_(This), pidlTemp, SHGDFIL_FINDDATA, &fd, sizeof(fd));
688                  if (!(FILE_ATTRIBUTE_DIRECTORY & fd.dwFileAttributes))
689                    *pdwAttributes &= ~SFGAO_FOLDER;
690                  if (FILE_ATTRIBUTE_READONLY  & fd.dwFileAttributes)
691                    *pdwAttributes &= ~(SFGAO_CANDELETE|SFGAO_CANMOVE|SFGAO_CANRENAME );
692 */
693                }
694                hr = S_OK;
695             }
696           }
697         }
698
699         if (!hr)
700           *ppidl = pidlTemp;
701         else
702           *ppidl = NULL;
703
704         TRACE("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl? *ppidl:0, hr);
705
706         return hr;      
707 }
708
709 /**************************************************************************
710 *               IShellFolder_fnEnumObjects
711 * PARAMETERS
712 *  HWND          hwndOwner,    //[in ] Parent Window
713 *  DWORD         grfFlags,     //[in ] SHCONTF enumeration mask
714 *  LPENUMIDLIST* ppenumIDList  //[out] IEnumIDList interface
715 */
716 static HRESULT WINAPI IShellFolder_fnEnumObjects(
717         IShellFolder2 * iface,
718         HWND hwndOwner,
719         DWORD dwFlags,
720         LPENUMIDLIST* ppEnumIDList)
721 {
722         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
723
724         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
725
726         *ppEnumIDList = NULL;
727         *ppEnumIDList = IEnumIDList_Constructor (This->sMyPath, dwFlags, EIDL_FILE);
728
729         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
730
731         if(!*ppEnumIDList) return E_OUTOFMEMORY;
732
733         return S_OK;            
734 }
735
736 /**************************************************************************
737 *               IShellFolder_fnBindToObject
738 * PARAMETERS
739 *  LPCITEMIDLIST pidl,       //[in ] relative pidl to open
740 *  LPBC          pbc,        //[in ] reserved
741 *  REFIID        riid,       //[in ] Initial Interface
742 *  LPVOID*       ppvObject   //[out] Interface*
743 */
744 static HRESULT WINAPI IShellFolder_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
745                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
746 {
747         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
748         GUID            const * iid;
749         IShellFolder    *pShellFolder, *pSubFolder;
750         IPersistFolder  *pPersistFolder;
751         LPITEMIDLIST    absPidl;
752         HRESULT         hr;
753         
754         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
755
756         if(!pidl || !ppvOut) return E_INVALIDARG;
757
758         *ppvOut = NULL;
759
760         if ((iid=_ILGetGUIDPointer(pidl)))
761         {
762           /* we have to create a alien folder */
763           if (  SUCCEEDED(SHCoCreateInstance(NULL, iid, NULL, riid, (LPVOID*)&pShellFolder))
764              && SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder)))
765             {
766               absPidl = ILCombine (This->absPidl, pidl);
767               IPersistFolder_Initialize(pPersistFolder, absPidl);
768               IPersistFolder_Release(pPersistFolder);
769               SHFree(absPidl);
770             }
771             else
772             {
773               return E_FAIL;
774             }
775         }
776         else
777         {
778           LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
779           pShellFolder = IShellFolder_Constructor(iface, pidltemp);
780           ILFree(pidltemp);
781         }
782
783         if (_ILIsPidlSimple(pidl))
784         {
785           if(IsEqualIID(riid, &IID_IShellFolder))
786           {
787             *ppvOut = pShellFolder;
788             hr = S_OK;
789           }
790           else
791           {
792             hr = IShellFolder_QueryInterface(pShellFolder, riid, ppvOut);
793             IShellFolder_Release(pShellFolder);
794           }
795         }
796         else
797         {
798           hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL,
799                                          riid, (LPVOID)&pSubFolder);
800           IShellFolder_Release(pShellFolder);
801           *ppvOut = pSubFolder;
802         }
803
804         TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
805
806         return hr;
807 }
808
809 /**************************************************************************
810 *  IShellFolder_fnBindToStorage
811 * PARAMETERS
812 *  LPCITEMIDLIST pidl,       //[in ] complex pidl to store
813 *  LPBC          pbc,        //[in ] reserved
814 *  REFIID        riid,       //[in ] Initial storage interface 
815 *  LPVOID*       ppvObject   //[out] Interface* returned
816 */
817 static HRESULT WINAPI IShellFolder_fnBindToStorage(
818         IShellFolder2 * iface,
819         LPCITEMIDLIST pidl,
820         LPBC pbcReserved,
821         REFIID riid,
822         LPVOID *ppvOut)
823 {
824         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
825
826         FIXME("(%p)->(pidl=%p,%p,\n\tIID:%s,%p) stub\n",
827               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
828
829         *ppvOut = NULL;
830         return E_NOTIMPL;
831 }
832
833 /**************************************************************************
834 *  IShellFolder_fnCompareIDs
835 *
836 * PARMETERS
837 *  LPARAM        lParam, //[in ] Column?
838 *  LPCITEMIDLIST pidl1,  //[in ] simple pidl
839 *  LPCITEMIDLIST pidl2)  //[in ] simple pidl
840 *
841 * NOTES
842 *   Special case - If one of the items is a Path and the other is a File,
843 *   always make the Path come before the File.
844 *
845 * NOTES 
846 *  use SCODE_CODE() on the return value to get the result
847 */
848
849 static HRESULT WINAPI  IShellFolder_fnCompareIDs(
850         IShellFolder2 * iface,
851         LPARAM lParam,
852         LPCITEMIDLIST pidl1,
853         LPCITEMIDLIST pidl2)
854 {
855         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
856
857         CHAR szTemp1[MAX_PATH];
858         CHAR szTemp2[MAX_PATH];
859         int   nReturn;
860         IShellFolder * psf;
861         HRESULT hr = E_OUTOFMEMORY;
862         LPCITEMIDLIST  pidlTemp;
863         PIDLTYPE pt1, pt2;
864
865         if (TRACE_ON(shell)) {
866             TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
867             pdump (pidl1);
868             pdump (pidl2);
869         }
870         
871         if (!pidl1 && !pidl2)
872         {
873           hr = ResultFromShort(0);
874         }
875         else if (!pidl1)
876         {
877           hr = ResultFromShort(-1);
878         }
879         else if (!pidl2)
880         {
881           hr = ResultFromShort(1);
882         }
883         else
884         {
885           LPPIDLDATA pd1, pd2;
886           pd1 = _ILGetDataPointer(pidl1);
887           pd2 = _ILGetDataPointer(pidl2);
888         
889           /* compate the types. sort order is the PT_* constant */
890           pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
891           pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
892
893           if (pt1 != pt2)
894           {
895             hr = ResultFromShort(pt1-pt2);
896           }
897           else                                          /* same type of pidl */
898           {
899             _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
900             _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
901             nReturn = strcasecmp(szTemp1, szTemp2);
902         
903             if (nReturn == 0)                           /* first pidl different ? */
904             {
905               pidl1 = ILGetNext(pidl1);
906
907               if (pidl1 && pidl1->mkid.cb)              /* go deeper? */        
908               {
909                 pidlTemp = ILCloneFirst(pidl1);
910                 pidl2 = ILGetNext(pidl2);
911         
912                 hr = IShellFolder_BindToObject(iface, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
913                 if (SUCCEEDED(hr))
914                 { 
915                   nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
916                   IShellFolder_Release(psf);
917                   hr = ResultFromShort(nReturn);
918                 }
919                 ILFree(pidlTemp);
920               }
921               else                                      /* no deeper on #1  */
922               {
923                 pidl2 = ILGetNext(pidl2);
924                 if (pidl2 && pidl2->mkid.cb)            /* go deeper on #2 ? */
925                     hr = ResultFromShort(-1);           /* two different */
926                 else
927                     hr = ResultFromShort(nReturn);      /* two equal simple pidls */
928               }
929             }
930             else
931             {
932               hr = ResultFromShort(nReturn);            /* two different simple pidls */
933             }
934           }
935         }
936         
937         TRACE("-- res=0x%08lx\n", hr);
938         return hr;
939 }
940
941 /**************************************************************************
942 *       IShellFolder_fnCreateViewObject
943 */
944 static HRESULT WINAPI IShellFolder_fnCreateViewObject(
945         IShellFolder2 * iface,
946         HWND hwndOwner,
947         REFIID riid,
948         LPVOID *ppvOut)
949 {
950         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
951
952         LPSHELLVIEW     pShellView;
953         HRESULT         hr = E_INVALIDARG;
954
955         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
956         
957         if(ppvOut)
958         {
959           *ppvOut = NULL;
960
961           if(IsEqualIID(riid, &IID_IDropTarget))
962           {
963             hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, ppvOut);
964           }
965           else if(IsEqualIID(riid, &IID_IContextMenu))
966           {
967             FIXME("IContextMenu not implemented\n");
968             hr = E_NOTIMPL;
969           }
970           else if(IsEqualIID(riid, &IID_IShellView))
971           {
972             pShellView = IShellView_Constructor((IShellFolder*)iface);
973             if(pShellView)
974             {
975               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
976               IShellView_Release(pShellView);
977             }
978           }
979         }
980         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
981         return hr; 
982 }
983
984 /**************************************************************************
985 *  IShellFolder_fnGetAttributesOf
986 *
987 * PARAMETERS
988 *  UINT            cidl,     //[in ] num elements in pidl array
989 *  LPCITEMIDLIST*  apidl,    //[in ] simple pidl array 
990 *  ULONG*          rgfInOut) //[out] result array  
991 *
992 */
993 static HRESULT WINAPI IShellFolder_fnGetAttributesOf(
994         IShellFolder2 * iface,
995         UINT cidl,
996         LPCITEMIDLIST *apidl,
997         DWORD *rgfInOut)
998 {
999         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1000
1001         HRESULT hr = S_OK;
1002
1003         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
1004
1005         if ( (!cidl) || (!apidl) || (!rgfInOut))
1006           return E_INVALIDARG;
1007
1008         while (cidl > 0 && *apidl)
1009         {
1010           pdump (*apidl);
1011           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1012           apidl++;
1013           cidl--;
1014         } 
1015
1016         TRACE("-- result=0x%08lx\n",*rgfInOut);
1017
1018         return hr;
1019 }
1020 /**************************************************************************
1021 *  IShellFolder_fnGetUIObjectOf
1022 *
1023 * PARAMETERS
1024 *  HWND           hwndOwner, //[in ] Parent window for any output
1025 *  UINT           cidl,      //[in ] array size
1026 *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
1027 *  REFIID         riid,      //[in ] Requested Interface
1028 *  UINT*          prgfInOut, //[   ] reserved 
1029 *  LPVOID*        ppvObject) //[out] Resulting Interface
1030 *
1031 * NOTES
1032 *  This function gets asked to return "view objects" for one or more (multiple select)
1033 *  items:
1034 *  The viewobject typically is an COM object with one of the following interfaces:
1035 *  IExtractIcon,IDataObject,IContextMenu
1036 *  In order to support icon positions in the default Listview your DataObject
1037 *  must implement the SetData method (in addition to GetData :) - the shell passes
1038 *  a barely documented "Icon positions" structure to SetData when the drag starts,
1039 *  and GetData's it if the drop is in another explorer window that needs the positions.
1040 */
1041 static HRESULT WINAPI IShellFolder_fnGetUIObjectOf( 
1042         IShellFolder2 * iface,
1043         HWND            hwndOwner,
1044         UINT            cidl,
1045         LPCITEMIDLIST * apidl, 
1046         REFIID          riid, 
1047         UINT *          prgfInOut,
1048         LPVOID *        ppvOut)
1049 {       
1050         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1051
1052         LPITEMIDLIST    pidl;
1053         IUnknown*       pObj = NULL; 
1054         HRESULT         hr = E_INVALIDARG;
1055         
1056         TRACE("(%p)->(0x%04x,%u,apidl=%p,\n\tIID:%s,%p,%p)\n",
1057           This,hwndOwner,cidl,apidl,debugstr_guid(riid),prgfInOut,ppvOut);
1058
1059         if (ppvOut)
1060         {
1061           *ppvOut = NULL;
1062
1063           if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
1064           {
1065             pObj  = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl);
1066             hr = S_OK;
1067           }
1068           else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
1069           {
1070             pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
1071             hr = S_OK;
1072           }
1073           else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
1074           {
1075             pidl = ILCombine(This->absPidl,apidl[0]);
1076             pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
1077             SHFree(pidl);
1078             hr = S_OK;
1079           } 
1080           else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
1081           {
1082             hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pObj);
1083           }
1084           else
1085           { 
1086             hr = E_NOINTERFACE;
1087           }
1088
1089           if(!pObj)
1090             hr = E_OUTOFMEMORY;
1091
1092           *ppvOut = pObj;
1093         }
1094         TRACE("(%p)->hr=0x%08lx\n",This, hr);
1095         return hr;
1096 }
1097
1098 /**************************************************************************
1099 *  IShellFolder_fnGetDisplayNameOf
1100 *  Retrieves the display name for the specified file object or subfolder
1101 *
1102 * PARAMETERS
1103 *  LPCITEMIDLIST pidl,    //[in ] complex pidl to item
1104 *  DWORD         dwFlags, //[in ] SHGNO formatting flags
1105 *  LPSTRRET      lpName)  //[out] Returned display name
1106 *
1107 * FIXME
1108 *  if the name is in the pidl the ret value should be a STRRET_OFFSET
1109 */
1110 #define GET_SHGDN_FOR(dwFlags)         ((DWORD)dwFlags & (DWORD)0x0000FF00)
1111 #define GET_SHGDN_RELATION(dwFlags)    ((DWORD)dwFlags & (DWORD)0x000000FF)
1112
1113 static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
1114         IShellFolder2 * iface,
1115         LPCITEMIDLIST pidl,
1116         DWORD dwFlags,
1117         LPSTRRET strRet)
1118 {
1119         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1120
1121         CHAR            szPath[MAX_PATH]= "";
1122         int             len = 0;
1123         BOOL            bSimplePidl;
1124                 
1125         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1126         pdump(pidl);
1127         
1128         if(!pidl || !strRet) return E_INVALIDARG;
1129         
1130         bSimplePidl = _ILIsPidlSimple(pidl);
1131
1132         /* take names of special folders only if its only this folder */
1133         if (_ILIsSpecialFolder(pidl))
1134         {
1135           if ( bSimplePidl)
1136           {
1137             _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1138           }
1139         }
1140         else
1141         {
1142           if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
1143           {
1144             strcpy (szPath, This->sMyPath);                     /* get path to root*/
1145             PathAddBackslashA(szPath);
1146             len = strlen(szPath);
1147           }
1148           _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
1149
1150           /* MSDN also mentions SHGDN_FOREDITING, which isn't defined in wine */
1151           if(!_ILIsFolder(pidl) && !(dwFlags & SHGDN_FORPARSING) &&
1152              ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL)))
1153           {
1154               HKEY hKey;
1155               DWORD dwData;
1156               DWORD dwDataSize = sizeof(DWORD);
1157               BOOL  doHide = 0; /* The default value is FALSE (win98 at least) */
1158
1159               /* XXX should it do this only for known file types? -- that would make it even slower! */
1160                           /* XXX That's what the prompt says!! */
1161               if(!RegCreateKeyExA(HKEY_CURRENT_USER,
1162                                   "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
1163                                   0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0))
1164               {
1165                   if(!RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize))
1166                       doHide = dwData;
1167                   RegCloseKey(hKey);
1168               }
1169               if(doHide && szPath[0]!='.') PathRemoveExtensionA(szPath);
1170           }
1171         }
1172         
1173         if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl)      /* go deeper if needed */
1174         {
1175           PathAddBackslashA(szPath);
1176           len = strlen(szPath);
1177
1178           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath + len, MAX_PATH - len)))
1179             return E_OUTOFMEMORY;
1180         }
1181         strRet->uType = STRRET_CSTRA;
1182         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1183
1184         TRACE("-- (%p)->(%s)\n", This, szPath);
1185         return S_OK;
1186 }
1187
1188 /**************************************************************************
1189 *  IShellFolder_fnSetNameOf
1190 *  Changes the name of a file object or subfolder, possibly changing its item
1191 *  identifier in the process.
1192 *
1193 * PARAMETERS
1194 *  HWND          hwndOwner,  //[in ] Owner window for output
1195 *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
1196 *  LPCOLESTR     lpszName,   //[in ] the items new display name
1197 *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
1198 *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
1199 */
1200 static HRESULT WINAPI IShellFolder_fnSetNameOf(
1201         IShellFolder2 * iface,
1202         HWND hwndOwner, 
1203         LPCITEMIDLIST pidl, /*simple pidl*/
1204         LPCOLESTR lpName, 
1205         DWORD dwFlags, 
1206         LPITEMIDLIST *pPidlOut)
1207 {
1208         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1209         char szSrc[MAX_PATH], szDest[MAX_PATH];
1210         int len;
1211         BOOL bIsFolder = _ILIsFolder(ILFindLastID(pidl));
1212
1213         TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p)\n",
1214           This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut);
1215
1216         /* build source path */
1217         if (dwFlags & SHGDN_INFOLDER)
1218         {
1219           strcpy(szSrc, This->sMyPath);
1220           PathAddBackslashA(szSrc);
1221           len = strlen (szSrc);
1222           _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len);
1223         }
1224         else 
1225         {
1226           SHGetPathFromIDListA(pidl, szSrc);
1227         }
1228
1229         /* build destination path */
1230         strcpy(szDest, This->sMyPath);
1231         PathAddBackslashA(szDest);
1232         len = strlen (szDest);
1233         WideCharToMultiByte( CP_ACP, 0, lpName, -1, szDest+len, MAX_PATH-len, NULL, NULL );
1234         szDest[MAX_PATH-1] = 0;
1235         TRACE("src=%s dest=%s\n", szSrc, szDest);
1236         if ( MoveFileA(szSrc, szDest) )
1237         {
1238           if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest);
1239           SHChangeNotifyA( bIsFolder?SHCNE_RENAMEFOLDER:SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
1240           return S_OK;
1241         }
1242         return E_FAIL;
1243 }
1244
1245 static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(
1246         IShellFolder2 * iface,
1247         GUID *pguid)
1248 {
1249         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1250         FIXME("(%p)\n",This);
1251         return E_NOTIMPL;
1252 }       
1253 static HRESULT WINAPI IShellFolder_fnEnumSearches(
1254         IShellFolder2 * iface,
1255         IEnumExtraSearch **ppenum)
1256 {
1257         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1258         FIXME("(%p)\n",This);
1259         return E_NOTIMPL;
1260 }       
1261 static HRESULT WINAPI IShellFolder_fnGetDefaultColumn(
1262         IShellFolder2 * iface,
1263         DWORD dwRes,
1264         ULONG *pSort,
1265         ULONG *pDisplay)
1266 {
1267         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1268
1269         TRACE("(%p)\n",This);
1270
1271         if (pSort) *pSort = 0;
1272         if (pDisplay) *pDisplay = 0;
1273
1274         return S_OK;
1275 }       
1276 static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState(
1277         IShellFolder2 * iface,
1278         UINT iColumn,
1279         DWORD *pcsFlags)
1280 {
1281         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1282         
1283         TRACE("(%p)\n",This);
1284
1285         if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1286
1287         *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
1288
1289         return S_OK;
1290 }       
1291 static HRESULT WINAPI IShellFolder_fnGetDetailsEx(
1292         IShellFolder2 * iface,
1293         LPCITEMIDLIST pidl,
1294         const SHCOLUMNID *pscid,
1295         VARIANT *pv)
1296 {
1297         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1298         FIXME("(%p)\n",This);
1299
1300         return E_NOTIMPL;
1301 }       
1302 static HRESULT WINAPI IShellFolder_fnGetDetailsOf(
1303         IShellFolder2 * iface,
1304         LPCITEMIDLIST pidl,
1305         UINT iColumn,
1306         SHELLDETAILS *psd)
1307 {
1308         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1309         HRESULT hr = E_FAIL;
1310
1311         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1312
1313         if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1314         
1315         if (!pidl)
1316         {
1317           /* the header titles */
1318           psd->fmt = GenericSFHeader[iColumn].fmt;
1319           psd->cxChar = GenericSFHeader[iColumn].cxChar;
1320           psd->str.uType = STRRET_CSTRA;
1321           LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
1322           return S_OK;
1323         }
1324         else
1325         {
1326           /* the data from the pidl */
1327           switch(iColumn)
1328           {
1329             case 0:     /* name */
1330               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
1331               break;
1332             case 1:     /* size */
1333               _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
1334               break;
1335             case 2:     /* type */
1336               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
1337               break;
1338             case 3:     /* date */
1339               _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
1340               break;
1341             case 4:     /* attributes */
1342               _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
1343               break;
1344           }
1345           hr = S_OK;
1346           psd->str.uType = STRRET_CSTRA;
1347         }
1348
1349         return hr;
1350 }       
1351 static HRESULT WINAPI IShellFolder_fnMapNameToSCID(
1352         IShellFolder2 * iface,
1353         LPCWSTR pwszName,
1354         SHCOLUMNID *pscid)
1355 {
1356         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1357         FIXME("(%p)\n",This);
1358         return E_NOTIMPL;
1359 }       
1360
1361 static ICOM_VTABLE(IShellFolder2) sfvt = 
1362 {       
1363         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1364         IShellFolder_fnQueryInterface,
1365         IShellFolder_fnAddRef,
1366         IShellFolder_fnRelease,
1367         IShellFolder_fnParseDisplayName,
1368         IShellFolder_fnEnumObjects,
1369         IShellFolder_fnBindToObject,
1370         IShellFolder_fnBindToStorage,
1371         IShellFolder_fnCompareIDs,
1372         IShellFolder_fnCreateViewObject,
1373         IShellFolder_fnGetAttributesOf,
1374         IShellFolder_fnGetUIObjectOf,
1375         IShellFolder_fnGetDisplayNameOf,
1376         IShellFolder_fnSetNameOf,
1377
1378         /* ShellFolder2 */
1379         IShellFolder_fnGetDefaultSearchGUID,
1380         IShellFolder_fnEnumSearches,
1381         IShellFolder_fnGetDefaultColumn,
1382         IShellFolder_fnGetDefaultColumnState,
1383         IShellFolder_fnGetDetailsEx,
1384         IShellFolder_fnGetDetailsOf,
1385         IShellFolder_fnMapNameToSCID
1386 };
1387
1388 /****************************************************************************
1389  * ISFHelper for IShellFolder implementation
1390  */
1391
1392 static HRESULT WINAPI ISFHelper_fnQueryInterface(
1393         ISFHelper *iface,
1394         REFIID riid,
1395         LPVOID *ppvObj)
1396 {
1397         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1398
1399         TRACE("(%p)\n", This);
1400
1401         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
1402 }
1403
1404 static ULONG WINAPI ISFHelper_fnAddRef(
1405         ISFHelper *iface)
1406 {
1407         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1408
1409         TRACE("(%p)\n", This);
1410
1411         return IUnknown_AddRef(This->pUnkOuter);
1412 }
1413
1414 static ULONG WINAPI ISFHelper_fnRelease(
1415         ISFHelper *iface)
1416 {
1417         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1418
1419         TRACE("(%p)\n", This);
1420
1421         return IUnknown_Release(This->pUnkOuter);
1422 }
1423
1424
1425 /****************************************************************************
1426  * ISFHelper_fnAddFolder
1427  *
1428  * creates a unique folder name
1429  */
1430
1431 static HRESULT WINAPI ISFHelper_fnGetUniqueName(
1432         ISFHelper *iface,
1433         LPSTR lpName,
1434         UINT uLen)
1435 {
1436         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1437         IEnumIDList * penum;
1438         HRESULT hr;
1439         char szText[MAX_PATH];
1440         char * szNewFolder = "New Folder";
1441         
1442         TRACE("(%p)(%s %u)\n", This, lpName, uLen);
1443
1444         if (uLen < strlen(szNewFolder) + 4) return E_POINTER;
1445         
1446         strcpy(lpName, szNewFolder);
1447         
1448         hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
1449         if (penum)
1450         {
1451           LPITEMIDLIST pidl;
1452           DWORD dwFetched;
1453           int i=1;
1454           
1455 next:     IEnumIDList_Reset(penum);
1456           while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched)
1457           {
1458             _ILSimpleGetText(pidl, szText, MAX_PATH);
1459             if (0 == strcasecmp(szText, lpName))
1460             {
1461               sprintf(lpName, "%s %d", szNewFolder, i++);
1462               if (i > 99) 
1463               {
1464                 hr = E_FAIL;
1465                 break;
1466               }
1467               goto next;
1468             }
1469           }
1470
1471           IEnumIDList_Release(penum);
1472         }
1473         return hr;
1474 }
1475         
1476 /****************************************************************************
1477  * ISFHelper_fnAddFolder
1478  *
1479  * adds a new folder.
1480  */
1481
1482 static HRESULT WINAPI ISFHelper_fnAddFolder(
1483         ISFHelper *iface,
1484         HWND hwnd,
1485         LPCSTR lpName,
1486         LPITEMIDLIST* ppidlOut)
1487 {
1488         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1489         char lpstrNewDir[MAX_PATH];
1490         DWORD bRes;
1491         HRESULT hres = E_FAIL;
1492         
1493         TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut);
1494
1495         strcpy(lpstrNewDir, This->sMyPath);
1496         PathAddBackslashA(lpstrNewDir);
1497         strcat(lpstrNewDir, lpName);
1498
1499         bRes = CreateDirectoryA(lpstrNewDir, NULL);
1500
1501         if (bRes)
1502         {
1503           LPITEMIDLIST pidl, pidlitem;
1504
1505           pidlitem = SHSimpleIDListFromPathA(lpstrNewDir);
1506
1507           pidl = ILCombine(This->absPidl, pidlitem);
1508           SHChangeNotifyA(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
1509           SHFree(pidl); 
1510
1511           if (ppidlOut) *ppidlOut = pidlitem;
1512           hres = S_OK;
1513         }
1514         else
1515         {
1516           char lpstrText[128+MAX_PATH];
1517           char lpstrTempText[128];
1518           char lpstrCaption[256];
1519
1520           /* Cannot Create folder because of permissions */
1521           LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText));
1522           LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption));
1523           sprintf(lpstrText,lpstrTempText, lpstrNewDir);
1524           MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
1525         }
1526
1527         return hres;
1528 }
1529
1530 /****************************************************************************
1531  * ISFHelper_fnDeleteItems
1532  *
1533  * deletes items in folder
1534  */
1535 static HRESULT WINAPI ISFHelper_fnDeleteItems(
1536         ISFHelper *iface,
1537         UINT cidl,
1538         LPCITEMIDLIST* apidl)
1539 {
1540         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1541         int i;
1542         char szPath[MAX_PATH];
1543         BOOL bConfirm = TRUE;
1544
1545         TRACE("(%p)(%u %p)\n", This, cidl, apidl);
1546         
1547         /* deleting multiple items so give a slightly different warning */
1548         if(cidl != 1)
1549         {
1550           char tmp[8]; 
1551           snprintf(tmp, sizeof(tmp), "%d", cidl);
1552           if(!SHELL_WarnItemDelete(ASK_DELETE_MULTIPLE_ITEM, tmp))
1553             return E_FAIL;
1554           bConfirm = FALSE;
1555         }
1556
1557         for(i=0; i< cidl; i++)
1558         {
1559           strcpy(szPath, This->sMyPath);
1560           PathAddBackslashA(szPath);
1561           _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
1562
1563           if (_ILIsFolder(apidl[i]))
1564           {
1565             LPITEMIDLIST pidl;
1566             TRACE("delete %s\n", szPath);
1567             if (! SHELL_DeleteDirectoryA(szPath, bConfirm))
1568             {
1569               TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1570               return E_FAIL;
1571             }
1572             pidl = ILCombine(This->absPidl, apidl[i]);
1573             SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
1574             SHFree(pidl); 
1575           }
1576           else if (_ILIsValue(apidl[i]))
1577           {
1578             LPITEMIDLIST pidl;
1579
1580             TRACE("delete %s\n", szPath);
1581             if (! SHELL_DeleteFileA(szPath, bConfirm))
1582             {
1583               TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1584               return E_FAIL;
1585             }
1586             pidl = ILCombine(This->absPidl, apidl[i]);
1587             SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1588             SHFree(pidl); 
1589           }
1590
1591         }
1592         return S_OK;
1593 }
1594
1595 /****************************************************************************
1596  * ISFHelper_fnCopyItems
1597  *
1598  * copies items to this folder
1599  */
1600 static HRESULT WINAPI ISFHelper_fnCopyItems(
1601         ISFHelper *iface,
1602         IShellFolder* pSFFrom,
1603         UINT cidl,
1604         LPCITEMIDLIST *apidl)
1605 {
1606         int i;
1607         IPersistFolder2 * ppf2=NULL;
1608         char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
1609         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1610
1611         TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1612
1613         IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
1614         if (ppf2)
1615         {
1616           LPITEMIDLIST pidl;
1617           if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
1618           {
1619             for (i=0; i<cidl; i++)
1620             {
1621               SHGetPathFromIDListA(pidl, szSrcPath);
1622               PathAddBackslashA(szSrcPath);
1623               _ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
1624
1625               strcpy(szDstPath, This->sMyPath);
1626               PathAddBackslashA(szDstPath);
1627               _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
1628               MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
1629             }
1630             SHFree(pidl);
1631           }
1632           IPersistFolder2_Release(ppf2);
1633         }
1634         return S_OK;
1635 }
1636
1637 static ICOM_VTABLE(ISFHelper) shvt = 
1638 {
1639         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1640         ISFHelper_fnQueryInterface,
1641         ISFHelper_fnAddRef,
1642         ISFHelper_fnRelease,
1643         ISFHelper_fnGetUniqueName,
1644         ISFHelper_fnAddFolder,
1645         ISFHelper_fnDeleteItems,
1646         ISFHelper_fnCopyItems,
1647 };
1648
1649 /***********************************************************************
1650 *       [Desktopfolder] IShellFolder implementation
1651 */
1652 static struct ICOM_VTABLE(IShellFolder2) sfdvt;
1653
1654 static shvheader DesktopSFHeader [] =
1655 {
1656  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
1657  { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1658  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1659  { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
1660  { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
1661 };
1662 #define DESKTOPSHELLVIEWCOLUMNS 5
1663
1664 /**************************************************************************
1665 *       ISF_Desktop_Constructor
1666 *
1667 */
1668 IShellFolder * ISF_Desktop_Constructor()
1669 {
1670         IGenericSFImpl *        sf;
1671
1672         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1673         sf->ref=1;
1674         ICOM_VTBL(sf)=&unkvt;
1675         sf->lpvtblShellFolder=&sfdvt;
1676         sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1677         sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
1678
1679         TRACE("(%p)\n",sf);
1680
1681         shell32_ObjCount++;
1682         return _IShellFolder_(sf);
1683 }
1684
1685 /**************************************************************************
1686  *      ISF_Desktop_fnQueryInterface
1687  *
1688  * NOTES supports not IPersist/IPersistFolder
1689  */
1690 static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1691         IShellFolder2 * iface,
1692         REFIID riid,
1693         LPVOID *ppvObj)
1694 {
1695         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1696
1697         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1698
1699         *ppvObj = NULL;
1700
1701         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
1702         {
1703           *ppvObj = _IUnknown_(This); 
1704         }
1705         else if(IsEqualIID(riid, &IID_IShellFolder))  /*IShellFolder*/
1706         {
1707           *ppvObj = _IShellFolder_(This);
1708         }   
1709         else if(IsEqualIID(riid, &IID_IShellFolder2))  /*IShellFolder2*/
1710         {
1711           *ppvObj = _IShellFolder_(This);
1712         }   
1713
1714         if(*ppvObj)
1715         {
1716           IUnknown_AddRef((IUnknown*)(*ppvObj));
1717           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1718           return S_OK;
1719         }
1720         TRACE("-- Interface: E_NOINTERFACE\n");
1721         return E_NOINTERFACE;
1722 }
1723
1724 /**************************************************************************
1725 *       ISF_Desktop_fnParseDisplayName
1726 *
1727 * NOTES
1728 *       "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1729 *       to MyComputer
1730 */
1731 static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1732         IShellFolder2 * iface,
1733         HWND hwndOwner,
1734         LPBC pbcReserved,
1735         LPOLESTR lpszDisplayName,
1736         DWORD *pchEaten,
1737         LPITEMIDLIST *ppidl,
1738         DWORD *pdwAttributes)
1739 {
1740         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1741
1742         LPCWSTR         szNext=NULL;
1743         LPITEMIDLIST    pidlTemp=NULL;
1744         HRESULT         hr=E_OUTOFMEMORY;
1745         
1746         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1747         This,hwndOwner,pbcReserved,lpszDisplayName,
1748         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1749
1750         *ppidl = 0;
1751         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
1752         
1753         /* FIXME no real parsing implemented */
1754         pidlTemp = _ILCreateMyComputer();
1755         szNext = lpszDisplayName;
1756
1757         if (szNext && *szNext)
1758         {
1759           hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1760         }
1761         else
1762         {
1763           hr = S_OK;
1764
1765           if (pdwAttributes && *pdwAttributes)
1766           {
1767             SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
1768           }
1769         }
1770
1771         *ppidl = pidlTemp;
1772
1773         TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1774
1775         return hr;      
1776 }
1777
1778 /**************************************************************************
1779 *               ISF_Desktop_fnEnumObjects
1780 */
1781 static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1782         IShellFolder2 * iface,
1783         HWND hwndOwner,
1784         DWORD dwFlags,
1785         LPENUMIDLIST* ppEnumIDList)
1786 {
1787         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1788
1789         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1790
1791         *ppEnumIDList = NULL;
1792         *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1793
1794         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1795
1796         if(!*ppEnumIDList) return E_OUTOFMEMORY;
1797
1798         return S_OK;            
1799 }
1800
1801 /**************************************************************************
1802 *               ISF_Desktop_fnBindToObject
1803 */
1804 static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
1805                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1806 {
1807         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1808         GUID            const * clsid;
1809         IShellFolder    *pShellFolder, *pSubFolder;
1810         HRESULT         hr;
1811
1812         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
1813               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
1814
1815         *ppvOut = NULL;
1816
1817         if ((clsid=_ILGetGUIDPointer(pidl)))
1818         {
1819           if ( IsEqualIID(clsid, &CLSID_MyComputer))
1820           {
1821             pShellFolder = ISF_MyComputer_Constructor();
1822           }
1823           else 
1824           {
1825              /* shell extension */
1826              if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1827              {
1828                return E_INVALIDARG;
1829              }
1830           }
1831         } 
1832         else
1833         {
1834           /* file system folder on the desktop */
1835           LPITEMIDLIST deskpidl, firstpidl, completepidl;
1836           IPersistFolder * ppf;
1837
1838           /* combine pidls */
1839           SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
1840           firstpidl = ILCloneFirst(pidl);
1841           completepidl = ILCombine(deskpidl, firstpidl);
1842
1843           pShellFolder = IShellFolder_Constructor(NULL, NULL);
1844           if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf)))
1845           {
1846             IPersistFolder_Initialize(ppf, completepidl);
1847             IPersistFolder_Release(ppf);
1848           }
1849           ILFree(completepidl);
1850           ILFree(deskpidl);
1851           ILFree(firstpidl);
1852         }
1853         
1854         if (_ILIsPidlSimple(pidl))      /* no sub folders */
1855         {
1856           *ppvOut = pShellFolder;
1857           hr = S_OK;
1858         }
1859         else                            /* go deeper */
1860         {
1861           hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1862           IShellFolder_Release(pShellFolder);
1863           *ppvOut = pSubFolder;
1864         }
1865
1866         TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
1867
1868         return hr;
1869 }
1870
1871 /**************************************************************************
1872 *       ISF_Desktop_fnCreateViewObject
1873 */
1874 static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
1875                  HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1876 {
1877         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1878
1879         LPSHELLVIEW     pShellView;
1880         HRESULT         hr = E_INVALIDARG;
1881
1882         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
1883         
1884         if(ppvOut)
1885         {
1886           *ppvOut = NULL;
1887
1888           if(IsEqualIID(riid, &IID_IDropTarget))
1889           {
1890             WARN("IDropTarget not implemented\n");
1891             hr = E_NOTIMPL;
1892           }
1893           else if(IsEqualIID(riid, &IID_IContextMenu))
1894           {
1895             WARN("IContextMenu not implemented\n");
1896             hr = E_NOTIMPL;
1897           }
1898           else if(IsEqualIID(riid, &IID_IShellView))
1899           {
1900             pShellView = IShellView_Constructor((IShellFolder*)iface);
1901             if(pShellView)
1902             {
1903               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1904               IShellView_Release(pShellView);
1905             }
1906           }
1907         }
1908         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1909         return hr; 
1910 }
1911
1912 /**************************************************************************
1913 *  ISF_Desktop_fnGetAttributesOf
1914 */
1915 static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
1916         IShellFolder2 * iface,
1917         UINT cidl,
1918         LPCITEMIDLIST *apidl,
1919         DWORD *rgfInOut)
1920 {
1921         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1922
1923         HRESULT         hr = S_OK;
1924
1925         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1926
1927         if ( (!cidl) || (!apidl) || (!rgfInOut))
1928           return E_INVALIDARG;
1929
1930         while (cidl > 0 && *apidl)
1931         {
1932           pdump (*apidl);
1933           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1934           apidl++;
1935           cidl--;
1936         }
1937
1938         TRACE("-- result=0x%08lx\n",*rgfInOut);
1939
1940         return hr;
1941 }
1942
1943 /**************************************************************************
1944 *       ISF_Desktop_fnGetDisplayNameOf
1945 *
1946 * NOTES
1947 *       special case: pidl = null gives desktop-name back
1948 */
1949 static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1950         IShellFolder2 * iface,
1951         LPCITEMIDLIST pidl,
1952         DWORD dwFlags,
1953         LPSTRRET strRet)
1954 {
1955         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1956
1957         CHAR            szPath[MAX_PATH]= "";
1958                 
1959         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1960         pdump(pidl);
1961         
1962         if(!strRet) return E_INVALIDARG;
1963         
1964         if(!pidl)
1965         {
1966           HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1967         }
1968         else if ( _ILIsPidlSimple(pidl) )
1969         {
1970           _ILSimpleGetText(pidl, szPath, MAX_PATH);
1971         }
1972         else
1973         { 
1974           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
1975             return E_OUTOFMEMORY;
1976         }
1977         strRet->uType = STRRET_CSTRA;
1978         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1979
1980
1981         TRACE("-- (%p)->(%s)\n", This, szPath);
1982         return S_OK;
1983 }
1984
1985 static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
1986         IShellFolder2 * iface,
1987         GUID *pguid)
1988 {
1989         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1990         FIXME("(%p)\n",This);
1991         return E_NOTIMPL;
1992 }       
1993 static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
1994         IShellFolder2 * iface,
1995         IEnumExtraSearch **ppenum)
1996 {
1997         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1998         FIXME("(%p)\n",This);
1999         return E_NOTIMPL;
2000 }       
2001 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
2002         IShellFolder2 * iface,
2003         DWORD dwRes,
2004         ULONG *pSort,
2005         ULONG *pDisplay)
2006 {
2007         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2008
2009         TRACE("(%p)\n",This);
2010
2011         if (pSort) *pSort = 0;
2012         if (pDisplay) *pDisplay = 0;
2013
2014         return S_OK;
2015 }       
2016 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
2017         IShellFolder2 * iface,
2018         UINT iColumn,
2019         DWORD *pcsFlags)
2020 {
2021         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2022         
2023         TRACE("(%p)\n",This);
2024
2025         if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2026
2027         *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
2028
2029         return S_OK;
2030 }       
2031 static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
2032         IShellFolder2 * iface,
2033         LPCITEMIDLIST pidl,
2034         const SHCOLUMNID *pscid,
2035         VARIANT *pv)
2036 {
2037         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2038         FIXME("(%p)\n",This);
2039
2040         return E_NOTIMPL;
2041 }       
2042 static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
2043         IShellFolder2 * iface,
2044         LPCITEMIDLIST pidl,
2045         UINT iColumn,
2046         SHELLDETAILS *psd)
2047 {
2048         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2049         HRESULT hr = E_FAIL;;
2050
2051         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2052
2053         if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2054         
2055         if (!pidl)
2056         {
2057           psd->fmt = DesktopSFHeader[iColumn].fmt;
2058           psd->cxChar = DesktopSFHeader[iColumn].cxChar;
2059           psd->str.uType = STRRET_CSTRA;
2060           LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2061           return S_OK;
2062         }
2063         else
2064         {
2065           /* the data from the pidl */
2066           switch(iColumn)
2067           {
2068             case 0:     /* name */
2069               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2070               break;
2071             case 1:     /* size */
2072               _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
2073               break;
2074             case 2:     /* type */
2075               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2076               break;
2077             case 3:     /* date */
2078               _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
2079               break;
2080             case 4:     /* attributes */
2081               _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
2082               break;
2083           }
2084           hr = S_OK;
2085           psd->str.uType = STRRET_CSTRA;
2086         }
2087
2088         return hr;
2089 }       
2090 static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
2091         IShellFolder2 * iface,
2092         LPCWSTR pwszName,
2093         SHCOLUMNID *pscid)
2094 {
2095         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2096         FIXME("(%p)\n",This);
2097         return E_NOTIMPL;
2098 }       
2099
2100 static ICOM_VTABLE(IShellFolder2) sfdvt = 
2101 {       
2102         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2103         ISF_Desktop_fnQueryInterface,
2104         IShellFolder_fnAddRef,
2105         IShellFolder_fnRelease,
2106         ISF_Desktop_fnParseDisplayName,
2107         ISF_Desktop_fnEnumObjects,
2108         ISF_Desktop_fnBindToObject,
2109         IShellFolder_fnBindToStorage,
2110         IShellFolder_fnCompareIDs,
2111         ISF_Desktop_fnCreateViewObject,
2112         ISF_Desktop_fnGetAttributesOf,
2113         IShellFolder_fnGetUIObjectOf,
2114         ISF_Desktop_fnGetDisplayNameOf,
2115         IShellFolder_fnSetNameOf,
2116
2117         /* ShellFolder2 */
2118         ISF_Desktop_fnGetDefaultSearchGUID,
2119         ISF_Desktop_fnEnumSearches,
2120         ISF_Desktop_fnGetDefaultColumn,
2121         ISF_Desktop_fnGetDefaultColumnState,
2122         ISF_Desktop_fnGetDetailsEx,
2123         ISF_Desktop_fnGetDetailsOf,
2124         ISF_Desktop_fnMapNameToSCID
2125 };
2126
2127
2128 /***********************************************************************
2129 *   IShellFolder [MyComputer] implementation
2130 */
2131
2132 static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
2133
2134 static shvheader MyComputerSFHeader [] =
2135 {
2136  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
2137  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2138  { IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2139  { IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2140 };
2141 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
2142
2143 /**************************************************************************
2144 *       ISF_MyComputer_Constructor
2145 */
2146 static IShellFolder * ISF_MyComputer_Constructor(void)
2147 {
2148         IGenericSFImpl *        sf;
2149
2150         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
2151         sf->ref=1;
2152
2153         ICOM_VTBL(sf)=&unkvt;
2154         sf->lpvtblShellFolder=&sfmcvt;
2155         sf->lpvtblPersistFolder2 = &psfvt;
2156         sf->pclsid = (CLSID*)&CLSID_SFMyComp;
2157         sf->absPidl=_ILCreateMyComputer();      /* my qualified pidl */
2158         sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
2159
2160         TRACE("(%p)\n",sf);
2161
2162         shell32_ObjCount++;
2163         return _IShellFolder_(sf);
2164 }
2165
2166 /**************************************************************************
2167 *       ISF_MyComputer_fnParseDisplayName
2168 */
2169 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
2170         IShellFolder2 * iface,
2171         HWND hwndOwner,
2172         LPBC pbcReserved,
2173         LPOLESTR lpszDisplayName,
2174         DWORD *pchEaten,
2175         LPITEMIDLIST *ppidl,
2176         DWORD *pdwAttributes)
2177 {
2178         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2179
2180         HRESULT         hr = E_OUTOFMEMORY;
2181         LPCWSTR         szNext=NULL;
2182         WCHAR           szElement[MAX_PATH];
2183         CHAR            szTempA[MAX_PATH];
2184         LPITEMIDLIST    pidlTemp;
2185         
2186         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
2187         This,hwndOwner,pbcReserved,lpszDisplayName,
2188         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
2189
2190         *ppidl = 0;
2191         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
2192
2193         /* do we have an absolute path name ? */
2194         if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
2195             lpszDisplayName[2] == (WCHAR)'\\')
2196         {
2197           szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
2198           WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
2199           pidlTemp = _ILCreateDrive(szTempA);
2200
2201           if (szNext && *szNext)
2202           {
2203             hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
2204           }
2205           else
2206           {
2207             if (pdwAttributes && *pdwAttributes)
2208             {
2209               SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
2210             }
2211             hr = S_OK;
2212           }
2213           *ppidl = pidlTemp;
2214         }
2215
2216         TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
2217
2218         return hr;      
2219 }
2220
2221 /**************************************************************************
2222 *               ISF_MyComputer_fnEnumObjects
2223 */
2224 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
2225         IShellFolder2 * iface,
2226         HWND hwndOwner,
2227         DWORD dwFlags,
2228         LPENUMIDLIST* ppEnumIDList)
2229 {
2230         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2231
2232         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
2233
2234         *ppEnumIDList = NULL;
2235         *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
2236
2237         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
2238
2239         if(!*ppEnumIDList) return E_OUTOFMEMORY;
2240
2241         return S_OK;            
2242 }
2243
2244 /**************************************************************************
2245 *               ISF_MyComputer_fnBindToObject
2246 */
2247 static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
2248                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
2249 {
2250         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2251         GUID            const * clsid;
2252         IShellFolder    *pShellFolder, *pSubFolder;
2253         LPITEMIDLIST    pidltemp;
2254         HRESULT         hr;
2255
2256         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
2257               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
2258
2259         if(!pidl || !ppvOut) return E_INVALIDARG;
2260
2261         *ppvOut = NULL;
2262
2263         if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
2264         {
2265            if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
2266            {
2267              return E_FAIL;
2268            }
2269         }
2270         else
2271         {
2272           if (!_ILIsDrive(pidl)) return E_INVALIDARG;
2273
2274           pidltemp = ILCloneFirst(pidl);
2275           pShellFolder = IShellFolder_Constructor(iface, pidltemp);
2276           ILFree(pidltemp);
2277         }
2278
2279         if (_ILIsPidlSimple(pidl))      /* no sub folders */
2280         {
2281           *ppvOut = pShellFolder;
2282           hr = S_OK;
2283         }
2284         else                            /* go deeper */
2285         {
2286           hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL,
2287                                          riid, (LPVOID)&pSubFolder);
2288           IShellFolder_Release(pShellFolder);
2289           *ppvOut = pSubFolder;
2290         }
2291
2292         TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
2293
2294         return hr;
2295 }
2296
2297 /**************************************************************************
2298 *       ISF_MyComputer_fnCreateViewObject
2299 */
2300 static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
2301                  HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
2302 {
2303         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2304
2305         LPSHELLVIEW     pShellView;
2306         HRESULT         hr = E_INVALIDARG;
2307
2308         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
2309         
2310         if(ppvOut)
2311         {
2312           *ppvOut = NULL;
2313
2314           if(IsEqualIID(riid, &IID_IDropTarget))
2315           {
2316             WARN("IDropTarget not implemented\n");
2317             hr = E_NOTIMPL;
2318           }
2319           else if(IsEqualIID(riid, &IID_IContextMenu))
2320           {
2321             WARN("IContextMenu not implemented\n");
2322             hr = E_NOTIMPL;
2323           }
2324           else if(IsEqualIID(riid, &IID_IShellView))
2325           {
2326             pShellView = IShellView_Constructor((IShellFolder*)iface);
2327             if(pShellView)
2328             {
2329               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
2330               IShellView_Release(pShellView);
2331             }
2332           }
2333         }
2334         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
2335         return hr; 
2336 }
2337
2338 /**************************************************************************
2339 *  ISF_MyComputer_fnGetAttributesOf
2340 */
2341 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
2342         IShellFolder2 * iface,
2343         UINT cidl,
2344         LPCITEMIDLIST *apidl,
2345         DWORD *rgfInOut)
2346 {
2347         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2348
2349         HRESULT         hr = S_OK;
2350
2351         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
2352
2353         if ( (!cidl) || (!apidl) || (!rgfInOut))
2354           return E_INVALIDARG;
2355
2356         while (cidl > 0 && *apidl)
2357         {
2358           pdump (*apidl);
2359           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
2360           apidl++;
2361           cidl--;
2362         }
2363
2364         TRACE("-- result=0x%08lx\n",*rgfInOut);
2365         return hr;
2366 }
2367
2368 /**************************************************************************
2369 *       ISF_MyComputer_fnGetDisplayNameOf
2370 *
2371 * NOTES
2372 *       The desktopfolder creates only complete paths (SHGDN_FORPARSING).
2373 *       SHGDN_INFOLDER makes no sense.
2374 */
2375 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
2376         IShellFolder2 * iface,
2377         LPCITEMIDLIST pidl,
2378         DWORD dwFlags,
2379         LPSTRRET strRet)
2380 {
2381         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2382
2383         char            szPath[MAX_PATH], szDrive[18];
2384         int             len = 0;
2385         BOOL            bSimplePidl;
2386                 
2387         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
2388         pdump(pidl);
2389         
2390         if(!strRet) return E_INVALIDARG;
2391         
2392         szPath[0]=0x00; szDrive[0]=0x00;
2393         
2394         
2395         bSimplePidl = _ILIsPidlSimple(pidl);
2396         
2397         if (_ILIsSpecialFolder(pidl))
2398         {
2399           /* take names of special folders only if its only this folder */
2400           if ( bSimplePidl )
2401           {
2402             _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2403           }
2404         }
2405         else
2406         {
2407           if (!_ILIsDrive(pidl))
2408           {
2409             ERR("Wrong pidl type\n");
2410             return E_INVALIDARG;
2411           }
2412
2413           _ILSimpleGetText(pidl, szPath, MAX_PATH);     /* append my own path */
2414
2415           /* long view "lw_name (C:)" */
2416           if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
2417           {
2418             DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
2419
2420             GetVolumeInformationA(szPath,szDrive,sizeof(szDrive)-6,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2421             strcat (szDrive," (");
2422             strncat (szDrive, szPath, 2);
2423             strcat (szDrive,")");
2424             strcpy (szPath, szDrive);
2425           }
2426         }
2427         
2428         if (!bSimplePidl)       /* go deeper if needed */
2429         { 
2430           PathAddBackslashA(szPath);
2431           len = strlen(szPath);
2432
2433           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
2434             return E_OUTOFMEMORY;
2435         }
2436         strRet->uType = STRRET_CSTRA;
2437         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
2438
2439
2440         TRACE("-- (%p)->(%s)\n", This, szPath);
2441         return S_OK;
2442 }
2443
2444 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
2445         IShellFolder2 * iface,
2446         GUID *pguid)
2447 {
2448         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2449         FIXME("(%p)\n",This);
2450         return E_NOTIMPL;
2451 }       
2452 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
2453         IShellFolder2 * iface,
2454         IEnumExtraSearch **ppenum)
2455 {
2456         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2457         FIXME("(%p)\n",This);
2458         return E_NOTIMPL;
2459 }       
2460 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
2461         IShellFolder2 * iface,
2462         DWORD dwRes,
2463         ULONG *pSort,
2464         ULONG *pDisplay)
2465 {
2466         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2467
2468         TRACE("(%p)\n",This);
2469
2470         if (pSort) *pSort = 0;
2471         if (pDisplay) *pDisplay = 0;
2472
2473         return S_OK;
2474 }       
2475 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
2476         IShellFolder2 * iface,
2477         UINT iColumn,
2478         DWORD *pcsFlags)
2479 {
2480         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2481         
2482         TRACE("(%p)\n",This);
2483
2484         if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2485
2486         *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
2487
2488         return S_OK;
2489 }       
2490 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
2491         IShellFolder2 * iface,
2492         LPCITEMIDLIST pidl,
2493         const SHCOLUMNID *pscid,
2494         VARIANT *pv)
2495 {
2496         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2497         FIXME("(%p)\n",This);
2498
2499         return E_NOTIMPL;
2500 }       
2501
2502 /* FIXME: drive size >4GB is rolling over */
2503 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
2504         IShellFolder2 * iface,
2505         LPCITEMIDLIST pidl,
2506         UINT iColumn,
2507         SHELLDETAILS *psd)
2508 {
2509         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2510         HRESULT hr;
2511
2512         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2513
2514         if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2515         
2516         if (!pidl)
2517         {
2518           psd->fmt = MyComputerSFHeader[iColumn].fmt;
2519           psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
2520           psd->str.uType = STRRET_CSTRA;
2521           LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2522           return S_OK;
2523         }
2524         else
2525         {
2526           char szPath[MAX_PATH];
2527           ULARGE_INTEGER ulBytes;
2528
2529           psd->str.u.cStr[0] = 0x00;
2530           psd->str.uType = STRRET_CSTRA;
2531           switch(iColumn)
2532           {
2533             case 0:     /* name */
2534               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2535               break;
2536             case 1:     /* type */
2537               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2538               break;
2539             case 2:     /* total size */
2540               if (_ILIsDrive(pidl))
2541               {
2542                 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2543                 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
2544                 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2545               }
2546               break;
2547             case 3:     /* free size */
2548               if (_ILIsDrive(pidl))
2549               {
2550                 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2551                 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
2552                 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2553               }
2554               break;
2555           }
2556           hr = S_OK;
2557         }
2558
2559         return hr;
2560 }       
2561 static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
2562         IShellFolder2 * iface,
2563         LPCWSTR pwszName,
2564         SHCOLUMNID *pscid)
2565 {
2566         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2567         FIXME("(%p)\n",This);
2568         return E_NOTIMPL;
2569 }       
2570
2571 static ICOM_VTABLE(IShellFolder2) sfmcvt = 
2572 {       
2573         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2574         IShellFolder_fnQueryInterface,
2575         IShellFolder_fnAddRef,
2576         IShellFolder_fnRelease,
2577         ISF_MyComputer_fnParseDisplayName,
2578         ISF_MyComputer_fnEnumObjects,
2579         ISF_MyComputer_fnBindToObject,
2580         IShellFolder_fnBindToStorage,
2581         IShellFolder_fnCompareIDs,
2582         ISF_MyComputer_fnCreateViewObject,
2583         ISF_MyComputer_fnGetAttributesOf,
2584         IShellFolder_fnGetUIObjectOf,
2585         ISF_MyComputer_fnGetDisplayNameOf,
2586         IShellFolder_fnSetNameOf,
2587
2588         /* ShellFolder2 */
2589         ISF_MyComputer_fnGetDefaultSearchGUID,
2590         ISF_MyComputer_fnEnumSearches,
2591         ISF_MyComputer_fnGetDefaultColumn,
2592         ISF_MyComputer_fnGetDefaultColumnState,
2593         ISF_MyComputer_fnGetDetailsEx,
2594         ISF_MyComputer_fnGetDetailsOf,
2595         ISF_MyComputer_fnMapNameToSCID
2596 };
2597
2598
2599 /************************************************************************
2600  * ISFPersistFolder_QueryInterface (IUnknown)
2601  *
2602  */
2603 static HRESULT WINAPI ISFPersistFolder2_QueryInterface(
2604         IPersistFolder2 *       iface,
2605         REFIID                  iid,
2606         LPVOID*                 ppvObj)
2607 {
2608         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2609
2610         TRACE("(%p)\n", This);
2611
2612         return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
2613 }
2614
2615 /************************************************************************
2616  * ISFPersistFolder_AddRef (IUnknown)
2617  *
2618  */
2619 static ULONG WINAPI ISFPersistFolder2_AddRef(
2620         IPersistFolder2 *       iface)
2621 {
2622         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2623
2624         TRACE("(%p)\n", This);
2625
2626         return IUnknown_AddRef(This->pUnkOuter);
2627 }
2628
2629 /************************************************************************
2630  * ISFPersistFolder_Release (IUnknown)
2631  *
2632  */
2633 static ULONG WINAPI ISFPersistFolder2_Release(
2634         IPersistFolder2 *       iface)
2635 {
2636         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2637
2638         TRACE("(%p)\n", This);
2639
2640         return IUnknown_Release(This->pUnkOuter);
2641 }
2642
2643 /************************************************************************
2644  * ISFPersistFolder_GetClassID (IPersist)
2645  */
2646 static HRESULT WINAPI ISFPersistFolder2_GetClassID(
2647         IPersistFolder2 *       iface,
2648         CLSID *                 lpClassId)
2649 {
2650         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2651
2652         TRACE("(%p)\n", This);
2653
2654         if (!lpClassId) return E_POINTER;
2655         *lpClassId = *This->pclsid;
2656
2657         return S_OK;
2658 }
2659
2660 /************************************************************************
2661  * ISFPersistFolder_Initialize (IPersistFolder)
2662  *
2663  * NOTES
2664  *  sMyPath is not set. Don't know how to handle in a non rooted environment.
2665  */
2666 static HRESULT WINAPI ISFPersistFolder2_Initialize(
2667         IPersistFolder2 *       iface,
2668         LPCITEMIDLIST           pidl)
2669 {
2670         char sTemp[MAX_PATH];
2671         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2672
2673         TRACE("(%p)->(%p)\n", This, pidl);
2674
2675         /* free the old stuff */
2676         if(This->absPidl)
2677         {
2678           SHFree(This->absPidl);
2679           This->absPidl = NULL;
2680         }
2681         if(This->sMyPath)
2682         {
2683           SHFree(This->sMyPath);
2684           This->sMyPath = NULL;
2685         }
2686
2687         /* set my pidl */
2688         This->absPidl = ILClone(pidl);
2689
2690         /* set my path */
2691         if (SHGetPathFromIDListA(pidl, sTemp))
2692         {
2693           This->sMyPath = SHAlloc(strlen(sTemp)+1);
2694           strcpy(This->sMyPath, sTemp);
2695         }
2696
2697         TRACE("--(%p)->(%s)\n", This, This->sMyPath);
2698
2699         return S_OK;
2700 }
2701
2702 /**************************************************************************
2703 *  IPersistFolder2_fnGetCurFolder
2704 */
2705 static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder(
2706         IPersistFolder2 *       iface,
2707         LPITEMIDLIST * pidl)
2708 {
2709         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2710         
2711         TRACE("(%p)->(%p)\n",This, pidl);
2712
2713         if (!pidl) return E_POINTER;
2714
2715         *pidl = ILClone(This->absPidl);
2716
2717         return S_OK;
2718 }
2719
2720 static ICOM_VTABLE(IPersistFolder2) psfvt = 
2721 {
2722         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2723         ISFPersistFolder2_QueryInterface,
2724         ISFPersistFolder2_AddRef,
2725         ISFPersistFolder2_Release,
2726         ISFPersistFolder2_GetClassID,
2727         ISFPersistFolder2_Initialize,
2728         ISFPersistFolder2_fnGetCurFolder
2729 };
2730
2731 /****************************************************************************
2732  * ISFDropTarget implementation
2733  */
2734 static BOOL ISFDropTarget_QueryDrop(
2735         IDropTarget *iface,
2736         DWORD dwKeyState,
2737         LPDWORD pdwEffect)
2738 {
2739         DWORD dwEffect = *pdwEffect;
2740
2741         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2742         
2743         *pdwEffect = DROPEFFECT_NONE;
2744
2745         if (This->fAcceptFmt)
2746         { /* Does our interpretation of the keystate ... */
2747           *pdwEffect = KeyStateToDropEffect(dwKeyState);
2748           
2749           /* ... matches the desired effect ? */
2750           if (dwEffect & *pdwEffect)
2751           {
2752             return TRUE;
2753           }
2754         }
2755         return FALSE;
2756 }
2757
2758 static HRESULT WINAPI ISFDropTarget_QueryInterface(
2759         IDropTarget *iface,
2760         REFIID riid,
2761         LPVOID *ppvObj)
2762 {
2763         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2764
2765         TRACE("(%p)\n", This);
2766
2767         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
2768 }
2769
2770 static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
2771 {
2772         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2773
2774         TRACE("(%p)\n", This);
2775
2776         return IUnknown_AddRef(This->pUnkOuter);
2777 }
2778
2779 static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
2780 {
2781         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2782
2783         TRACE("(%p)\n", This);
2784
2785         return IUnknown_Release(This->pUnkOuter);
2786 }
2787
2788 static HRESULT WINAPI ISFDropTarget_DragEnter(
2789         IDropTarget     *iface,
2790         IDataObject     *pDataObject,
2791         DWORD           dwKeyState,
2792         POINTL          pt,
2793         DWORD           *pdwEffect)
2794 {       
2795         FORMATETC       fmt;
2796         
2797         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2798
2799         TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
2800
2801         InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
2802
2803         This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
2804
2805         ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2806
2807         return S_OK;
2808 }
2809
2810 static HRESULT WINAPI ISFDropTarget_DragOver(
2811         IDropTarget     *iface,
2812         DWORD           dwKeyState,
2813         POINTL          pt,
2814         DWORD           *pdwEffect)
2815 {
2816         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2817
2818         TRACE("(%p)\n",This);
2819         
2820         if(!pdwEffect) return E_INVALIDARG;
2821
2822         ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2823
2824         return S_OK;
2825 }
2826
2827 static HRESULT WINAPI ISFDropTarget_DragLeave(
2828         IDropTarget     *iface)
2829 {
2830         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2831
2832         TRACE("(%p)\n",This);
2833
2834         This->fAcceptFmt = FALSE;
2835         
2836         return S_OK;
2837 }
2838
2839 static HRESULT WINAPI ISFDropTarget_Drop(
2840         IDropTarget     *iface,
2841         IDataObject*    pDataObject,
2842         DWORD           dwKeyState,
2843         POINTL          pt,
2844         DWORD           *pdwEffect)
2845 {
2846         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2847
2848         FIXME("(%p) object dropped\n",This);
2849
2850         return E_NOTIMPL;
2851 }
2852
2853 static struct ICOM_VTABLE(IDropTarget) dtvt = 
2854 {
2855         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2856         ISFDropTarget_QueryInterface,
2857         ISFDropTarget_AddRef,
2858         ISFDropTarget_Release,
2859         ISFDropTarget_DragEnter,
2860         ISFDropTarget_DragOver,
2861         ISFDropTarget_DragLeave,
2862         ISFDropTarget_Drop
2863 };