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