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