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