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