- Define rest of URL_ESCAPE... and other flags.
[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         
740         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
741
742         if(!pidl || !ppvOut) return E_INVALIDARG;
743
744         *ppvOut = NULL;
745
746         if ((iid=_ILGetGUIDPointer(pidl)))
747         {
748           /* we have to create a alien folder */
749           if (  SUCCEEDED(SHCoCreateInstance(NULL, iid, NULL, riid, (LPVOID*)&pShellFolder))
750              && SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder)))
751             {
752               absPidl = ILCombine (This->absPidl, pidl);
753               IPersistFolder_Initialize(pPersistFolder, absPidl);
754               IPersistFolder_Release(pPersistFolder);
755               SHFree(absPidl);
756             }
757             else
758             {
759               return E_FAIL;
760             }
761         }
762         else if(_ILIsFolder(pidl))
763         {
764           LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
765           pShellFolder = IShellFolder_Constructor(iface, pidltemp);
766           ILFree(pidltemp);
767         }
768         else
769         {
770           ERR("can't bind to a file\n");
771           return E_FAIL;
772         }
773         
774         if (_ILIsPidlSimple(pidl))
775         {
776           *ppvOut = pShellFolder;
777         }
778         else
779         {
780           IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder);
781           IShellFolder_Release(pShellFolder);
782           *ppvOut = pSubFolder;
783         }
784
785         TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
786
787         return S_OK;
788 }
789
790 /**************************************************************************
791 *  IShellFolder_fnBindToStorage
792 * PARAMETERS
793 *  LPCITEMIDLIST pidl,       //[in ] complex pidl to store
794 *  LPBC          pbc,        //[in ] reserved
795 *  REFIID        riid,       //[in ] Initial storage interface 
796 *  LPVOID*       ppvObject   //[out] Interface* returned
797 */
798 static HRESULT WINAPI IShellFolder_fnBindToStorage(
799         IShellFolder2 * iface,
800         LPCITEMIDLIST pidl,
801         LPBC pbcReserved,
802         REFIID riid,
803         LPVOID *ppvOut)
804 {
805         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
806
807         FIXME("(%p)->(pidl=%p,%p,\n\tIID:%s,%p) stub\n",
808               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
809
810         *ppvOut = NULL;
811         return E_NOTIMPL;
812 }
813
814 /**************************************************************************
815 *  IShellFolder_fnCompareIDs
816 *
817 * PARMETERS
818 *  LPARAM        lParam, //[in ] Column?
819 *  LPCITEMIDLIST pidl1,  //[in ] simple pidl
820 *  LPCITEMIDLIST pidl2)  //[in ] simple pidl
821 *
822 * NOTES
823 *   Special case - If one of the items is a Path and the other is a File,
824 *   always make the Path come before the File.
825 *
826 * NOTES 
827 *  use SCODE_CODE() on the return value to get the result
828 */
829
830 static HRESULT WINAPI  IShellFolder_fnCompareIDs(
831         IShellFolder2 * iface,
832         LPARAM lParam,
833         LPCITEMIDLIST pidl1,
834         LPCITEMIDLIST pidl2)
835 {
836         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
837
838         CHAR szTemp1[MAX_PATH];
839         CHAR szTemp2[MAX_PATH];
840         int   nReturn;
841         IShellFolder * psf;
842         HRESULT hr = E_OUTOFMEMORY;
843         LPCITEMIDLIST  pidlTemp;
844         PIDLTYPE pt1, pt2;
845
846         TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
847         pdump (pidl1);
848         pdump (pidl2);
849         
850         if (!pidl1 && !pidl2)
851         {
852           hr = ResultFromShort(0);
853         }
854         else if (!pidl1)
855         {
856           hr = ResultFromShort(-1);
857         }
858         else if (!pidl2)
859         {
860           hr = ResultFromShort(1);
861         }
862         else
863         {
864           LPPIDLDATA pd1, pd2;
865           pd1 = _ILGetDataPointer(pidl1);
866           pd2 = _ILGetDataPointer(pidl2);
867         
868           /* compate the types. sort order is the PT_* constant */
869           pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
870           pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
871
872           if (pt1 != pt2)
873           {
874             hr = ResultFromShort(pt1-pt2);
875           }
876           else                                          /* same type of pidl */
877           {
878             _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
879             _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
880             nReturn = strcasecmp(szTemp1, szTemp2);
881         
882             if (nReturn == 0)                           /* first pidl different ? */
883             {
884               pidl1 = ILGetNext(pidl1);
885
886               if (pidl1 && pidl1->mkid.cb)              /* go deeper? */        
887               {
888                 pidlTemp = ILCloneFirst(pidl1);
889                 pidl2 = ILGetNext(pidl2);
890         
891                 hr = IShellFolder_BindToObject(iface, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
892                 if (SUCCEEDED(hr))
893                 { 
894                   nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
895                   IShellFolder_Release(psf);
896                   hr = ResultFromShort(nReturn);
897                 }
898                 ILFree(pidlTemp);
899               }
900               else                                      /* no deeper on #1  */
901               {
902                 pidl2 = ILGetNext(pidl2);
903                 if (pidl2 && pidl2->mkid.cb)            /* go deeper on #2 ? */
904                     hr = ResultFromShort(-1);           /* two different */
905                 else
906                     hr = ResultFromShort(nReturn);      /* two equal simple pidls */
907               }
908             }
909             else
910             {
911               hr = ResultFromShort(nReturn);            /* two different simple pidls */
912             }
913           }
914         }
915         
916         TRACE("-- res=0x%08lx\n", hr);
917         return hr;
918 }
919
920 /**************************************************************************
921 *       IShellFolder_fnCreateViewObject
922 */
923 static HRESULT WINAPI IShellFolder_fnCreateViewObject(
924         IShellFolder2 * iface,
925         HWND hwndOwner,
926         REFIID riid,
927         LPVOID *ppvOut)
928 {
929         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
930
931         LPSHELLVIEW     pShellView;
932         HRESULT         hr = E_INVALIDARG;
933
934         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
935         
936         if(ppvOut)
937         {
938           *ppvOut = NULL;
939
940           if(IsEqualIID(riid, &IID_IDropTarget))
941           {
942             hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, ppvOut);
943           }
944           else if(IsEqualIID(riid, &IID_IContextMenu))
945           {
946             FIXME("IContextMenu not implemented\n");
947             hr = E_NOTIMPL;
948           }
949           else if(IsEqualIID(riid, &IID_IShellView))
950           {
951             pShellView = IShellView_Constructor((IShellFolder*)iface);
952             if(pShellView)
953             {
954               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
955               IShellView_Release(pShellView);
956             }
957           }
958         }
959         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
960         return hr; 
961 }
962
963 /**************************************************************************
964 *  IShellFolder_fnGetAttributesOf
965 *
966 * PARAMETERS
967 *  UINT            cidl,     //[in ] num elements in pidl array
968 *  LPCITEMIDLIST*  apidl,    //[in ] simple pidl array 
969 *  ULONG*          rgfInOut) //[out] result array  
970 *
971 */
972 static HRESULT WINAPI IShellFolder_fnGetAttributesOf(
973         IShellFolder2 * iface,
974         UINT cidl,
975         LPCITEMIDLIST *apidl,
976         DWORD *rgfInOut)
977 {
978         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
979
980         HRESULT hr = S_OK;
981
982         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
983
984         if ( (!cidl) || (!apidl) || (!rgfInOut))
985           return E_INVALIDARG;
986
987         while (cidl > 0 && *apidl)
988         {
989           pdump (*apidl);
990           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
991           apidl++;
992           cidl--;
993         } 
994
995         TRACE("-- result=0x%08lx\n",*rgfInOut);
996
997         return hr;
998 }
999 /**************************************************************************
1000 *  IShellFolder_fnGetUIObjectOf
1001 *
1002 * PARAMETERS
1003 *  HWND           hwndOwner, //[in ] Parent window for any output
1004 *  UINT           cidl,      //[in ] array size
1005 *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
1006 *  REFIID         riid,      //[in ] Requested Interface
1007 *  UINT*          prgfInOut, //[   ] reserved 
1008 *  LPVOID*        ppvObject) //[out] Resulting Interface
1009 *
1010 * NOTES
1011 *  This function gets asked to return "view objects" for one or more (multiple select)
1012 *  items:
1013 *  The viewobject typically is an COM object with one of the following interfaces:
1014 *  IExtractIcon,IDataObject,IContextMenu
1015 *  In order to support icon positions in the default Listview your DataObject
1016 *  must implement the SetData method (in addition to GetData :) - the shell passes
1017 *  a barely documented "Icon positions" structure to SetData when the drag starts,
1018 *  and GetData's it if the drop is in another explorer window that needs the positions.
1019 */
1020 static HRESULT WINAPI IShellFolder_fnGetUIObjectOf( 
1021         IShellFolder2 * iface,
1022         HWND            hwndOwner,
1023         UINT            cidl,
1024         LPCITEMIDLIST * apidl, 
1025         REFIID          riid, 
1026         UINT *          prgfInOut,
1027         LPVOID *        ppvOut)
1028 {       
1029         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1030
1031         LPITEMIDLIST    pidl;
1032         IUnknown*       pObj = NULL; 
1033         HRESULT         hr = E_INVALIDARG;
1034         
1035         TRACE("(%p)->(0x%04x,%u,apidl=%p,\n\tIID:%s,%p,%p)\n",
1036           This,hwndOwner,cidl,apidl,debugstr_guid(riid),prgfInOut,ppvOut);
1037
1038         if (ppvOut)
1039         {
1040           *ppvOut = NULL;
1041
1042           if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
1043           {
1044             pObj  = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl);
1045             hr = S_OK;
1046           }
1047           else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
1048           {
1049             pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
1050             hr = S_OK;
1051           }
1052           else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
1053           {
1054             pidl = ILCombine(This->absPidl,apidl[0]);
1055             pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
1056             SHFree(pidl);
1057             hr = S_OK;
1058           } 
1059           else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
1060           {
1061             hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pObj);
1062           }
1063           else
1064           { 
1065             hr = E_NOINTERFACE;
1066           }
1067
1068           if(!pObj)
1069             hr = E_OUTOFMEMORY;
1070
1071           *ppvOut = pObj;
1072         }
1073         TRACE("(%p)->hr=0x%08lx\n",This, hr);
1074         return hr;
1075 }
1076
1077 /**************************************************************************
1078 *  IShellFolder_fnGetDisplayNameOf
1079 *  Retrieves the display name for the specified file object or subfolder
1080 *
1081 * PARAMETERS
1082 *  LPCITEMIDLIST pidl,    //[in ] complex pidl to item
1083 *  DWORD         dwFlags, //[in ] SHGNO formatting flags
1084 *  LPSTRRET      lpName)  //[out] Returned display name
1085 *
1086 * FIXME
1087 *  if the name is in the pidl the ret value should be a STRRET_OFFSET
1088 */
1089 #define GET_SHGDN_FOR(dwFlags)         ((DWORD)dwFlags & (DWORD)0x0000FF00)
1090 #define GET_SHGDN_RELATION(dwFlags)    ((DWORD)dwFlags & (DWORD)0x000000FF)
1091
1092 static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
1093         IShellFolder2 * iface,
1094         LPCITEMIDLIST pidl,
1095         DWORD dwFlags,
1096         LPSTRRET strRet)
1097 {
1098         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1099
1100         CHAR            szPath[MAX_PATH]= "";
1101         int             len = 0;
1102         BOOL            bSimplePidl;
1103                 
1104         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1105         pdump(pidl);
1106         
1107         if(!pidl || !strRet) return E_INVALIDARG;
1108         
1109         bSimplePidl = _ILIsPidlSimple(pidl);
1110
1111         /* take names of special folders only if its only this folder */
1112         if (_ILIsSpecialFolder(pidl))
1113         {
1114           if ( bSimplePidl)
1115           {
1116             _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1117           }
1118         }
1119         else
1120         {
1121           if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
1122           {
1123             strcpy (szPath, This->sMyPath);                     /* get path to root*/
1124             PathAddBackslashA(szPath);
1125             len = strlen(szPath);
1126           }
1127           _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
1128         }
1129         
1130         if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl)      /* go deeper if needed */
1131         {
1132           PathAddBackslashA(szPath);
1133           len = strlen(szPath);
1134
1135           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath + len, MAX_PATH - len)))
1136             return E_OUTOFMEMORY;
1137         }
1138         strRet->uType = STRRET_CSTRA;
1139         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1140
1141         TRACE("-- (%p)->(%s)\n", This, szPath);
1142         return S_OK;
1143 }
1144
1145 /**************************************************************************
1146 *  IShellFolder_fnSetNameOf
1147 *  Changes the name of a file object or subfolder, possibly changing its item
1148 *  identifier in the process.
1149 *
1150 * PARAMETERS
1151 *  HWND          hwndOwner,  //[in ] Owner window for output
1152 *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
1153 *  LPCOLESTR     lpszName,   //[in ] the items new display name
1154 *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
1155 *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
1156 */
1157 static HRESULT WINAPI IShellFolder_fnSetNameOf(
1158         IShellFolder2 * iface,
1159         HWND hwndOwner, 
1160         LPCITEMIDLIST pidl, /*simple pidl*/
1161         LPCOLESTR lpName, 
1162         DWORD dwFlags, 
1163         LPITEMIDLIST *pPidlOut)
1164 {
1165         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1166         char szSrc[MAX_PATH], szDest[MAX_PATH];
1167         int len;
1168         BOOL bIsFolder = _ILIsFolder(ILFindLastID(pidl));
1169
1170         TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p)\n",
1171           This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut);
1172
1173         /* build source path */
1174         if (dwFlags & SHGDN_INFOLDER)
1175         {
1176           strcpy(szSrc, This->sMyPath);
1177           PathAddBackslashA(szSrc);
1178           len = strlen (szSrc);
1179           _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len);
1180         }
1181         else 
1182         {
1183           SHGetPathFromIDListA(pidl, szSrc);
1184         }
1185
1186         /* build destination path */
1187         strcpy(szDest, This->sMyPath);
1188         PathAddBackslashA(szDest);
1189         len = strlen (szDest);
1190         WideCharToMultiByte( CP_ACP, 0, lpName, -1, szDest+len, MAX_PATH-len, NULL, NULL );
1191         szDest[MAX_PATH-1] = 0;
1192         TRACE("src=%s dest=%s\n", szSrc, szDest);
1193         if ( MoveFileA(szSrc, szDest) )
1194         {
1195           if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest);
1196           SHChangeNotifyA( bIsFolder?SHCNE_RENAMEFOLDER:SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
1197           return S_OK;
1198         }
1199         return E_FAIL;
1200 }
1201
1202 static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(
1203         IShellFolder2 * iface,
1204         GUID *pguid)
1205 {
1206         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1207         FIXME("(%p)\n",This);
1208         return E_NOTIMPL;
1209 }       
1210 static HRESULT WINAPI IShellFolder_fnEnumSearches(
1211         IShellFolder2 * iface,
1212         IEnumExtraSearch **ppenum)
1213 {
1214         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1215         FIXME("(%p)\n",This);
1216         return E_NOTIMPL;
1217 }       
1218 static HRESULT WINAPI IShellFolder_fnGetDefaultColumn(
1219         IShellFolder2 * iface,
1220         DWORD dwRes,
1221         ULONG *pSort,
1222         ULONG *pDisplay)
1223 {
1224         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1225
1226         TRACE("(%p)\n",This);
1227
1228         if (pSort) *pSort = 0;
1229         if (pDisplay) *pDisplay = 0;
1230
1231         return S_OK;
1232 }       
1233 static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState(
1234         IShellFolder2 * iface,
1235         UINT iColumn,
1236         DWORD *pcsFlags)
1237 {
1238         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1239         
1240         TRACE("(%p)\n",This);
1241
1242         if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1243
1244         *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
1245
1246         return S_OK;
1247 }       
1248 static HRESULT WINAPI IShellFolder_fnGetDetailsEx(
1249         IShellFolder2 * iface,
1250         LPCITEMIDLIST pidl,
1251         const SHCOLUMNID *pscid,
1252         VARIANT *pv)
1253 {
1254         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1255         FIXME("(%p)\n",This);
1256
1257         return E_NOTIMPL;
1258 }       
1259 static HRESULT WINAPI IShellFolder_fnGetDetailsOf(
1260         IShellFolder2 * iface,
1261         LPCITEMIDLIST pidl,
1262         UINT iColumn,
1263         SHELLDETAILS *psd)
1264 {
1265         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1266         HRESULT hr = E_FAIL;
1267
1268         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1269
1270         if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1271         
1272         if (!pidl)
1273         {
1274           /* the header titles */
1275           psd->fmt = GenericSFHeader[iColumn].fmt;
1276           psd->cxChar = GenericSFHeader[iColumn].cxChar;
1277           psd->str.uType = STRRET_CSTRA;
1278           LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
1279           return S_OK;
1280         }
1281         else
1282         {
1283           /* the data from the pidl */
1284           switch(iColumn)
1285           {
1286             case 0:     /* name */
1287               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
1288               break;
1289             case 1:     /* size */
1290               _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
1291               break;
1292             case 2:     /* type */
1293               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
1294               break;
1295             case 3:     /* date */
1296               _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
1297               break;
1298             case 4:     /* attributes */
1299               _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
1300               break;
1301           }
1302           hr = S_OK;
1303           psd->str.uType = STRRET_CSTRA;
1304         }
1305
1306         return hr;
1307 }       
1308 static HRESULT WINAPI IShellFolder_fnMapNameToSCID(
1309         IShellFolder2 * iface,
1310         LPCWSTR pwszName,
1311         SHCOLUMNID *pscid)
1312 {
1313         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1314         FIXME("(%p)\n",This);
1315         return E_NOTIMPL;
1316 }       
1317
1318 static ICOM_VTABLE(IShellFolder2) sfvt = 
1319 {       
1320         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1321         IShellFolder_fnQueryInterface,
1322         IShellFolder_fnAddRef,
1323         IShellFolder_fnRelease,
1324         IShellFolder_fnParseDisplayName,
1325         IShellFolder_fnEnumObjects,
1326         IShellFolder_fnBindToObject,
1327         IShellFolder_fnBindToStorage,
1328         IShellFolder_fnCompareIDs,
1329         IShellFolder_fnCreateViewObject,
1330         IShellFolder_fnGetAttributesOf,
1331         IShellFolder_fnGetUIObjectOf,
1332         IShellFolder_fnGetDisplayNameOf,
1333         IShellFolder_fnSetNameOf,
1334
1335         /* ShellFolder2 */
1336         IShellFolder_fnGetDefaultSearchGUID,
1337         IShellFolder_fnEnumSearches,
1338         IShellFolder_fnGetDefaultColumn,
1339         IShellFolder_fnGetDefaultColumnState,
1340         IShellFolder_fnGetDetailsEx,
1341         IShellFolder_fnGetDetailsOf,
1342         IShellFolder_fnMapNameToSCID
1343 };
1344
1345 /****************************************************************************
1346  * ISFHelper for IShellFolder implementation
1347  */
1348
1349 static HRESULT WINAPI ISFHelper_fnQueryInterface(
1350         ISFHelper *iface,
1351         REFIID riid,
1352         LPVOID *ppvObj)
1353 {
1354         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1355
1356         TRACE("(%p)\n", This);
1357
1358         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
1359 }
1360
1361 static ULONG WINAPI ISFHelper_fnAddRef(
1362         ISFHelper *iface)
1363 {
1364         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1365
1366         TRACE("(%p)\n", This);
1367
1368         return IUnknown_AddRef(This->pUnkOuter);
1369 }
1370
1371 static ULONG WINAPI ISFHelper_fnRelease(
1372         ISFHelper *iface)
1373 {
1374         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1375
1376         TRACE("(%p)\n", This);
1377
1378         return IUnknown_Release(This->pUnkOuter);
1379 }
1380
1381
1382 /****************************************************************************
1383  * ISFHelper_fnAddFolder
1384  *
1385  * creates a unique folder name
1386  */
1387
1388 static HRESULT WINAPI ISFHelper_fnGetUniqueName(
1389         ISFHelper *iface,
1390         LPSTR lpName,
1391         UINT uLen)
1392 {
1393         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1394         IEnumIDList * penum;
1395         HRESULT hr;
1396         char szText[MAX_PATH];
1397         char * szNewFolder = "New Folder";
1398         
1399         TRACE("(%p)(%s %u)\n", This, lpName, uLen);
1400
1401         if (uLen < strlen(szNewFolder) + 4) return E_POINTER;
1402         
1403         strcpy(lpName, szNewFolder);
1404         
1405         hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
1406         if (penum)
1407         {
1408           LPITEMIDLIST pidl;
1409           DWORD dwFetched;
1410           int i=1;
1411           
1412 next:     IEnumIDList_Reset(penum);
1413           while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched)
1414           {
1415             _ILSimpleGetText(pidl, szText, MAX_PATH);
1416             if (0 == strcasecmp(szText, lpName))
1417             {
1418               sprintf(lpName, "%s %d", szNewFolder, i++);
1419               if (i > 99) 
1420               {
1421                 hr = E_FAIL;
1422                 break;
1423               }
1424               goto next;
1425             }
1426           }
1427
1428           IEnumIDList_Release(penum);
1429         }
1430         return hr;
1431 }
1432         
1433 /****************************************************************************
1434  * ISFHelper_fnAddFolder
1435  *
1436  * adds a new folder.
1437  */
1438
1439 static HRESULT WINAPI ISFHelper_fnAddFolder(
1440         ISFHelper *iface,
1441         HWND hwnd,
1442         LPCSTR lpName,
1443         LPITEMIDLIST* ppidlOut)
1444 {
1445         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1446         char lpstrNewDir[MAX_PATH];
1447         DWORD bRes;
1448         HRESULT hres = E_FAIL;
1449         
1450         TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut);
1451
1452         strcpy(lpstrNewDir, This->sMyPath);
1453         PathAddBackslashA(lpstrNewDir);
1454         strcat(lpstrNewDir, lpName);
1455
1456         bRes = CreateDirectoryA(lpstrNewDir, NULL);
1457
1458         if (bRes)
1459         {
1460           LPITEMIDLIST pidl, pidlitem;
1461
1462           pidlitem = SHSimpleIDListFromPathA(lpstrNewDir);
1463
1464           pidl = ILCombine(This->absPidl, pidlitem);
1465           SHChangeNotifyA(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
1466           SHFree(pidl); 
1467
1468           if (ppidlOut) *ppidlOut = pidlitem;
1469           hres = S_OK;
1470         }
1471         else
1472         {
1473           char lpstrText[128+MAX_PATH];
1474           char lpstrTempText[128];
1475           char lpstrCaption[256];
1476
1477           /* Cannot Create folder because of permissions */
1478           LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText));
1479           LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption));
1480           sprintf(lpstrText,lpstrTempText, lpstrNewDir);
1481           MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
1482         }
1483
1484         return hres;
1485 }
1486
1487 /****************************************************************************
1488  * ISFHelper_fnDeleteItems
1489  *
1490  * deletes items in folder
1491  */
1492 static HRESULT WINAPI ISFHelper_fnDeleteItems(
1493         ISFHelper *iface,
1494         UINT cidl,
1495         LPCITEMIDLIST* apidl)
1496 {
1497         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1498         int i;
1499         char szPath[MAX_PATH];
1500         BOOL bConfirm = TRUE;
1501
1502         TRACE("(%p)(%u %p)\n", This, cidl, apidl);
1503         
1504         /* deleting multiple items so give a slightly different warning */
1505         if(cidl != 1)
1506         {
1507           char tmp[8]; 
1508           snprintf(tmp, sizeof(tmp), "%d", cidl);
1509           if(!SHELL_WarnItemDelete(ASK_DELETE_MULTIPLE_ITEM, tmp))
1510             return E_FAIL;
1511           bConfirm = FALSE;
1512         }
1513
1514         for(i=0; i< cidl; i++)
1515         {
1516           strcpy(szPath, This->sMyPath);
1517           PathAddBackslashA(szPath);
1518           _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
1519
1520           if (_ILIsFolder(apidl[i]))
1521           {
1522             LPITEMIDLIST pidl;
1523             TRACE("delete %s\n", szPath);
1524             if (! SHELL_DeleteDirectoryA(szPath, bConfirm))
1525             {
1526               TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1527               return E_FAIL;
1528             }
1529             pidl = ILCombine(This->absPidl, apidl[i]);
1530             SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
1531             SHFree(pidl); 
1532           }
1533           else if (_ILIsValue(apidl[i]))
1534           {
1535             LPITEMIDLIST pidl;
1536
1537             TRACE("delete %s\n", szPath);
1538             if (! SHELL_DeleteFileA(szPath, bConfirm))
1539             {
1540               TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1541               return E_FAIL;
1542             }
1543             pidl = ILCombine(This->absPidl, apidl[i]);
1544             SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1545             SHFree(pidl); 
1546           }
1547
1548         }
1549         return S_OK;
1550 }
1551
1552 /****************************************************************************
1553  * ISFHelper_fnCopyItems
1554  *
1555  * copies items to this folder
1556  */
1557 static HRESULT WINAPI ISFHelper_fnCopyItems(
1558         ISFHelper *iface,
1559         IShellFolder* pSFFrom,
1560         UINT cidl,
1561         LPCITEMIDLIST *apidl)
1562 {
1563         int i;
1564         IPersistFolder2 * ppf2=NULL;
1565         char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
1566         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1567
1568         TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1569
1570         IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
1571         if (ppf2)
1572         {
1573           LPITEMIDLIST pidl;
1574           if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
1575           {
1576             for (i=0; i<cidl; i++)
1577             {
1578               SHGetPathFromIDListA(pidl, szSrcPath);
1579               PathAddBackslashA(szSrcPath);
1580               _ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
1581
1582               strcpy(szDstPath, This->sMyPath);
1583               PathAddBackslashA(szDstPath);
1584               _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
1585               MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
1586             }
1587             SHFree(pidl);
1588           }
1589           IPersistFolder2_Release(ppf2);
1590         }
1591         return S_OK;
1592 }
1593
1594 static ICOM_VTABLE(ISFHelper) shvt = 
1595 {
1596         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1597         ISFHelper_fnQueryInterface,
1598         ISFHelper_fnAddRef,
1599         ISFHelper_fnRelease,
1600         ISFHelper_fnGetUniqueName,
1601         ISFHelper_fnAddFolder,
1602         ISFHelper_fnDeleteItems,
1603         ISFHelper_fnCopyItems,
1604 };
1605
1606 /***********************************************************************
1607 *       [Desktopfolder] IShellFolder implementation
1608 */
1609 static struct ICOM_VTABLE(IShellFolder2) sfdvt;
1610
1611 static shvheader DesktopSFHeader [] =
1612 {
1613  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
1614  { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1615  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1616  { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
1617  { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
1618 };
1619 #define DESKTOPSHELLVIEWCOLUMNS 5
1620
1621 /**************************************************************************
1622 *       ISF_Desktop_Constructor
1623 *
1624 */
1625 IShellFolder * ISF_Desktop_Constructor()
1626 {
1627         IGenericSFImpl *        sf;
1628
1629         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1630         sf->ref=1;
1631         ICOM_VTBL(sf)=&unkvt;
1632         sf->lpvtblShellFolder=&sfdvt;
1633         sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1634         sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
1635
1636         TRACE("(%p)\n",sf);
1637
1638         shell32_ObjCount++;
1639         return _IShellFolder_(sf);
1640 }
1641
1642 /**************************************************************************
1643  *      ISF_Desktop_fnQueryInterface
1644  *
1645  * NOTES supports not IPersist/IPersistFolder
1646  */
1647 static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1648         IShellFolder2 * iface,
1649         REFIID riid,
1650         LPVOID *ppvObj)
1651 {
1652         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1653
1654         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1655
1656         *ppvObj = NULL;
1657
1658         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
1659         {
1660           *ppvObj = _IUnknown_(This); 
1661         }
1662         else if(IsEqualIID(riid, &IID_IShellFolder))  /*IShellFolder*/
1663         {
1664           *ppvObj = _IShellFolder_(This);
1665         }   
1666         else if(IsEqualIID(riid, &IID_IShellFolder2))  /*IShellFolder2*/
1667         {
1668           *ppvObj = _IShellFolder_(This);
1669         }   
1670
1671         if(*ppvObj)
1672         {
1673           IUnknown_AddRef((IUnknown*)(*ppvObj));
1674           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1675           return S_OK;
1676         }
1677         TRACE("-- Interface: E_NOINTERFACE\n");
1678         return E_NOINTERFACE;
1679 }
1680
1681 /**************************************************************************
1682 *       ISF_Desktop_fnParseDisplayName
1683 *
1684 * NOTES
1685 *       "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1686 *       to MyComputer
1687 */
1688 static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1689         IShellFolder2 * iface,
1690         HWND hwndOwner,
1691         LPBC pbcReserved,
1692         LPOLESTR lpszDisplayName,
1693         DWORD *pchEaten,
1694         LPITEMIDLIST *ppidl,
1695         DWORD *pdwAttributes)
1696 {
1697         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1698
1699         LPCWSTR         szNext=NULL;
1700         LPITEMIDLIST    pidlTemp=NULL;
1701         HRESULT         hr=E_OUTOFMEMORY;
1702         
1703         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1704         This,hwndOwner,pbcReserved,lpszDisplayName,
1705         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1706
1707         *ppidl = 0;
1708         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
1709         
1710         /* fixme no real parsing implemented */
1711         pidlTemp = _ILCreateMyComputer();
1712         szNext = lpszDisplayName;
1713
1714         if (szNext && *szNext)
1715         {
1716           hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1717         }
1718         else
1719         {
1720           hr = S_OK;
1721
1722           if (pdwAttributes && *pdwAttributes)
1723           {
1724             SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
1725           }
1726         }
1727
1728         *ppidl = pidlTemp;
1729
1730         TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1731
1732         return hr;      
1733 }
1734
1735 /**************************************************************************
1736 *               ISF_Desktop_fnEnumObjects
1737 */
1738 static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1739         IShellFolder2 * iface,
1740         HWND hwndOwner,
1741         DWORD dwFlags,
1742         LPENUMIDLIST* ppEnumIDList)
1743 {
1744         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1745
1746         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1747
1748         *ppEnumIDList = NULL;
1749         *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1750
1751         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1752
1753         if(!*ppEnumIDList) return E_OUTOFMEMORY;
1754
1755         return S_OK;            
1756 }
1757
1758 /**************************************************************************
1759 *               ISF_Desktop_fnBindToObject
1760 */
1761 static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
1762                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1763 {
1764         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1765         GUID            const * clsid;
1766         IShellFolder    *pShellFolder, *pSubFolder;
1767         
1768         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
1769               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
1770
1771         *ppvOut = NULL;
1772
1773         if ((clsid=_ILGetGUIDPointer(pidl)))
1774         {
1775           if ( IsEqualIID(clsid, &CLSID_MyComputer))
1776           {
1777             pShellFolder = ISF_MyComputer_Constructor();
1778           }
1779           else 
1780           {
1781              /* shell extension */
1782              if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1783              {
1784                return E_INVALIDARG;
1785              }
1786           }
1787         } 
1788         else
1789         {
1790           /* file system folder on the desktop */
1791           LPITEMIDLIST deskpidl, firstpidl, completepidl;
1792           IPersistFolder * ppf;
1793
1794           /* combine pidls */
1795           SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
1796           firstpidl = ILCloneFirst(pidl);
1797           completepidl = ILCombine(deskpidl, firstpidl);
1798
1799           pShellFolder = IShellFolder_Constructor(NULL, NULL);
1800           if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf)))
1801           {
1802             IPersistFolder_Initialize(ppf, completepidl);
1803             IPersistFolder_Release(ppf);
1804           }
1805           ILFree(completepidl);
1806           ILFree(deskpidl);
1807           ILFree(firstpidl);
1808         }
1809         
1810         if (_ILIsPidlSimple(pidl))      /* no sub folders */
1811         {
1812           *ppvOut = pShellFolder;
1813         }
1814         else                            /* go deeper */
1815         {
1816           IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1817           IShellFolder_Release(pShellFolder);
1818           *ppvOut = pSubFolder;
1819         }
1820
1821         TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1822
1823         return S_OK;
1824 }
1825
1826 /**************************************************************************
1827 *       ISF_Desktop_fnCreateViewObject
1828 */
1829 static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
1830                  HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1831 {
1832         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1833
1834         LPSHELLVIEW     pShellView;
1835         HRESULT         hr = E_INVALIDARG;
1836
1837         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
1838         
1839         if(ppvOut)
1840         {
1841           *ppvOut = NULL;
1842
1843           if(IsEqualIID(riid, &IID_IDropTarget))
1844           {
1845             WARN("IDropTarget not implemented\n");
1846             hr = E_NOTIMPL;
1847           }
1848           else if(IsEqualIID(riid, &IID_IContextMenu))
1849           {
1850             WARN("IContextMenu not implemented\n");
1851             hr = E_NOTIMPL;
1852           }
1853           else if(IsEqualIID(riid, &IID_IShellView))
1854           {
1855             pShellView = IShellView_Constructor((IShellFolder*)iface);
1856             if(pShellView)
1857             {
1858               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1859               IShellView_Release(pShellView);
1860             }
1861           }
1862         }
1863         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1864         return hr; 
1865 }
1866
1867 /**************************************************************************
1868 *  ISF_Desktop_fnGetAttributesOf
1869 */
1870 static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
1871         IShellFolder2 * iface,
1872         UINT cidl,
1873         LPCITEMIDLIST *apidl,
1874         DWORD *rgfInOut)
1875 {
1876         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1877
1878         HRESULT         hr = S_OK;
1879
1880         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1881
1882         if ( (!cidl) || (!apidl) || (!rgfInOut))
1883           return E_INVALIDARG;
1884
1885         while (cidl > 0 && *apidl)
1886         {
1887           pdump (*apidl);
1888           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1889           apidl++;
1890           cidl--;
1891         }
1892
1893         TRACE("-- result=0x%08lx\n",*rgfInOut);
1894
1895         return hr;
1896 }
1897
1898 /**************************************************************************
1899 *       ISF_Desktop_fnGetDisplayNameOf
1900 *
1901 * NOTES
1902 *       special case: pidl = null gives desktop-name back
1903 */
1904 static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1905         IShellFolder2 * iface,
1906         LPCITEMIDLIST pidl,
1907         DWORD dwFlags,
1908         LPSTRRET strRet)
1909 {
1910         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1911
1912         CHAR            szPath[MAX_PATH]= "";
1913                 
1914         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1915         pdump(pidl);
1916         
1917         if(!strRet) return E_INVALIDARG;
1918         
1919         if(!pidl)
1920         {
1921           HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1922         }
1923         else if ( _ILIsPidlSimple(pidl) )
1924         {
1925           _ILSimpleGetText(pidl, szPath, MAX_PATH);
1926         }
1927         else
1928         { 
1929           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
1930             return E_OUTOFMEMORY;
1931         }
1932         strRet->uType = STRRET_CSTRA;
1933         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1934
1935
1936         TRACE("-- (%p)->(%s)\n", This, szPath);
1937         return S_OK;
1938 }
1939
1940 static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
1941         IShellFolder2 * iface,
1942         GUID *pguid)
1943 {
1944         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1945         FIXME("(%p)\n",This);
1946         return E_NOTIMPL;
1947 }       
1948 static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
1949         IShellFolder2 * iface,
1950         IEnumExtraSearch **ppenum)
1951 {
1952         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1953         FIXME("(%p)\n",This);
1954         return E_NOTIMPL;
1955 }       
1956 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
1957         IShellFolder2 * iface,
1958         DWORD dwRes,
1959         ULONG *pSort,
1960         ULONG *pDisplay)
1961 {
1962         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1963
1964         TRACE("(%p)\n",This);
1965
1966         if (pSort) *pSort = 0;
1967         if (pDisplay) *pDisplay = 0;
1968
1969         return S_OK;
1970 }       
1971 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
1972         IShellFolder2 * iface,
1973         UINT iColumn,
1974         DWORD *pcsFlags)
1975 {
1976         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1977         
1978         TRACE("(%p)\n",This);
1979
1980         if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1981
1982         *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
1983
1984         return S_OK;
1985 }       
1986 static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
1987         IShellFolder2 * iface,
1988         LPCITEMIDLIST pidl,
1989         const SHCOLUMNID *pscid,
1990         VARIANT *pv)
1991 {
1992         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1993         FIXME("(%p)\n",This);
1994
1995         return E_NOTIMPL;
1996 }       
1997 static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
1998         IShellFolder2 * iface,
1999         LPCITEMIDLIST pidl,
2000         UINT iColumn,
2001         SHELLDETAILS *psd)
2002 {
2003         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2004         HRESULT hr = E_FAIL;;
2005
2006         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2007
2008         if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2009         
2010         if (!pidl)
2011         {
2012           psd->fmt = DesktopSFHeader[iColumn].fmt;
2013           psd->cxChar = DesktopSFHeader[iColumn].cxChar;
2014           psd->str.uType = STRRET_CSTRA;
2015           LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2016           return S_OK;
2017         }
2018         else
2019         {
2020           /* the data from the pidl */
2021           switch(iColumn)
2022           {
2023             case 0:     /* name */
2024               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2025               break;
2026             case 1:     /* size */
2027               _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
2028               break;
2029             case 2:     /* type */
2030               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2031               break;
2032             case 3:     /* date */
2033               _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
2034               break;
2035             case 4:     /* attributes */
2036               _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
2037               break;
2038           }
2039           hr = S_OK;
2040           psd->str.uType = STRRET_CSTRA;
2041         }
2042
2043         return hr;
2044 }       
2045 static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
2046         IShellFolder2 * iface,
2047         LPCWSTR pwszName,
2048         SHCOLUMNID *pscid)
2049 {
2050         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2051         FIXME("(%p)\n",This);
2052         return E_NOTIMPL;
2053 }       
2054
2055 static ICOM_VTABLE(IShellFolder2) sfdvt = 
2056 {       
2057         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2058         ISF_Desktop_fnQueryInterface,
2059         IShellFolder_fnAddRef,
2060         IShellFolder_fnRelease,
2061         ISF_Desktop_fnParseDisplayName,
2062         ISF_Desktop_fnEnumObjects,
2063         ISF_Desktop_fnBindToObject,
2064         IShellFolder_fnBindToStorage,
2065         IShellFolder_fnCompareIDs,
2066         ISF_Desktop_fnCreateViewObject,
2067         ISF_Desktop_fnGetAttributesOf,
2068         IShellFolder_fnGetUIObjectOf,
2069         ISF_Desktop_fnGetDisplayNameOf,
2070         IShellFolder_fnSetNameOf,
2071
2072         /* ShellFolder2 */
2073         ISF_Desktop_fnGetDefaultSearchGUID,
2074         ISF_Desktop_fnEnumSearches,
2075         ISF_Desktop_fnGetDefaultColumn,
2076         ISF_Desktop_fnGetDefaultColumnState,
2077         ISF_Desktop_fnGetDetailsEx,
2078         ISF_Desktop_fnGetDetailsOf,
2079         ISF_Desktop_fnMapNameToSCID
2080 };
2081
2082
2083 /***********************************************************************
2084 *   IShellFolder [MyComputer] implementation
2085 */
2086
2087 static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
2088
2089 static shvheader MyComputerSFHeader [] =
2090 {
2091  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
2092  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2093  { IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2094  { IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2095 };
2096 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
2097
2098 /**************************************************************************
2099 *       ISF_MyComputer_Constructor
2100 */
2101 static IShellFolder * ISF_MyComputer_Constructor(void)
2102 {
2103         IGenericSFImpl *        sf;
2104
2105         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
2106         sf->ref=1;
2107
2108         ICOM_VTBL(sf)=&unkvt;
2109         sf->lpvtblShellFolder=&sfmcvt;
2110         sf->lpvtblPersistFolder2 = &psfvt;
2111         sf->pclsid = (CLSID*)&CLSID_SFMyComp;
2112         sf->absPidl=_ILCreateMyComputer();      /* my qualified pidl */
2113         sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
2114
2115         TRACE("(%p)\n",sf);
2116
2117         shell32_ObjCount++;
2118         return _IShellFolder_(sf);
2119 }
2120
2121 /**************************************************************************
2122 *       ISF_MyComputer_fnParseDisplayName
2123 */
2124 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
2125         IShellFolder2 * iface,
2126         HWND hwndOwner,
2127         LPBC pbcReserved,
2128         LPOLESTR lpszDisplayName,
2129         DWORD *pchEaten,
2130         LPITEMIDLIST *ppidl,
2131         DWORD *pdwAttributes)
2132 {
2133         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2134
2135         HRESULT         hr = E_OUTOFMEMORY;
2136         LPCWSTR         szNext=NULL;
2137         WCHAR           szElement[MAX_PATH];
2138         CHAR            szTempA[MAX_PATH];
2139         LPITEMIDLIST    pidlTemp;
2140         
2141         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
2142         This,hwndOwner,pbcReserved,lpszDisplayName,
2143         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
2144
2145         *ppidl = 0;
2146         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
2147
2148         /* do we have an absolute path name ? */
2149         if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
2150             lpszDisplayName[2] == (WCHAR)'\\')
2151         {
2152           szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
2153           WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
2154           pidlTemp = _ILCreateDrive(szTempA);
2155
2156           if (szNext && *szNext)
2157           {
2158             hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
2159           }
2160           else
2161           {
2162             if (pdwAttributes && *pdwAttributes)
2163             {
2164               SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
2165             }
2166             hr = S_OK;
2167           }
2168           *ppidl = pidlTemp;
2169         }
2170
2171         TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
2172
2173         return hr;      
2174 }
2175
2176 /**************************************************************************
2177 *               ISF_MyComputer_fnEnumObjects
2178 */
2179 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
2180         IShellFolder2 * iface,
2181         HWND hwndOwner,
2182         DWORD dwFlags,
2183         LPENUMIDLIST* ppEnumIDList)
2184 {
2185         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2186
2187         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
2188
2189         *ppEnumIDList = NULL;
2190         *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
2191
2192         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
2193
2194         if(!*ppEnumIDList) return E_OUTOFMEMORY;
2195
2196         return S_OK;            
2197 }
2198
2199 /**************************************************************************
2200 *               ISF_MyComputer_fnBindToObject
2201 */
2202 static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
2203                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
2204 {
2205         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2206         GUID            const * clsid;
2207         IShellFolder    *pShellFolder, *pSubFolder;
2208         LPITEMIDLIST    pidltemp;
2209         
2210         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
2211               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
2212
2213         if(!pidl || !ppvOut) return E_INVALIDARG;
2214
2215         *ppvOut = NULL;
2216
2217         if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
2218         {
2219            if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
2220            {
2221              return E_FAIL;
2222            }
2223         }
2224         else
2225         {
2226           if (!_ILIsDrive(pidl)) return E_INVALIDARG;
2227
2228           pidltemp = ILCloneFirst(pidl);
2229           pShellFolder = IShellFolder_Constructor(iface, pidltemp);
2230           ILFree(pidltemp);
2231         }
2232
2233         if (_ILIsPidlSimple(pidl))      /* no sub folders */
2234         {
2235           *ppvOut = pShellFolder;
2236         }
2237         else                            /* go deeper */
2238         {
2239           IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder);
2240           IShellFolder_Release(pShellFolder);
2241           *ppvOut = pSubFolder;
2242         }
2243
2244         TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
2245
2246         return S_OK;
2247 }
2248
2249 /**************************************************************************
2250 *       ISF_MyComputer_fnCreateViewObject
2251 */
2252 static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
2253                  HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
2254 {
2255         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2256
2257         LPSHELLVIEW     pShellView;
2258         HRESULT         hr = E_INVALIDARG;
2259
2260         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
2261         
2262         if(ppvOut)
2263         {
2264           *ppvOut = NULL;
2265
2266           if(IsEqualIID(riid, &IID_IDropTarget))
2267           {
2268             WARN("IDropTarget not implemented\n");
2269             hr = E_NOTIMPL;
2270           }
2271           else if(IsEqualIID(riid, &IID_IContextMenu))
2272           {
2273             WARN("IContextMenu not implemented\n");
2274             hr = E_NOTIMPL;
2275           }
2276           else if(IsEqualIID(riid, &IID_IShellView))
2277           {
2278             pShellView = IShellView_Constructor((IShellFolder*)iface);
2279             if(pShellView)
2280             {
2281               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
2282               IShellView_Release(pShellView);
2283             }
2284           }
2285         }
2286         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
2287         return hr; 
2288 }
2289
2290 /**************************************************************************
2291 *  ISF_MyComputer_fnGetAttributesOf
2292 */
2293 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
2294         IShellFolder2 * iface,
2295         UINT cidl,
2296         LPCITEMIDLIST *apidl,
2297         DWORD *rgfInOut)
2298 {
2299         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2300
2301         HRESULT         hr = S_OK;
2302
2303         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
2304
2305         if ( (!cidl) || (!apidl) || (!rgfInOut))
2306           return E_INVALIDARG;
2307
2308         while (cidl > 0 && *apidl)
2309         {
2310           pdump (*apidl);
2311           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
2312           apidl++;
2313           cidl--;
2314         }
2315
2316         TRACE("-- result=0x%08lx\n",*rgfInOut);
2317         return hr;
2318 }
2319
2320 /**************************************************************************
2321 *       ISF_MyComputer_fnGetDisplayNameOf
2322 *
2323 * NOTES
2324 *       The desktopfolder creates only complete paths (SHGDN_FORPARSING).
2325 *       SHGDN_INFOLDER makes no sense.
2326 */
2327 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
2328         IShellFolder2 * iface,
2329         LPCITEMIDLIST pidl,
2330         DWORD dwFlags,
2331         LPSTRRET strRet)
2332 {
2333         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2334
2335         char            szPath[MAX_PATH], szDrive[18];
2336         int             len = 0;
2337         BOOL            bSimplePidl;
2338                 
2339         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
2340         pdump(pidl);
2341         
2342         if(!strRet) return E_INVALIDARG;
2343         
2344         szPath[0]=0x00; szDrive[0]=0x00;
2345         
2346         
2347         bSimplePidl = _ILIsPidlSimple(pidl);
2348         
2349         if (_ILIsSpecialFolder(pidl))
2350         {
2351           /* take names of special folders only if its only this folder */
2352           if ( bSimplePidl )
2353           {
2354             _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2355           }
2356         }
2357         else
2358         {
2359           if (!_ILIsDrive(pidl))
2360           {
2361             ERR("Wrong pidl type\n");
2362             return E_INVALIDARG;
2363           }
2364
2365           _ILSimpleGetText(pidl, szPath, MAX_PATH);     /* append my own path */
2366
2367           /* long view "lw_name (C:)" */
2368           if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
2369           {
2370             DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
2371
2372             GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2373             strcat (szDrive," (");
2374             strncat (szDrive, szPath, 2);
2375             strcat (szDrive,")");
2376             strcpy (szPath, szDrive);
2377           }
2378         }
2379         
2380         if (!bSimplePidl)       /* go deeper if needed */
2381         { 
2382           PathAddBackslashA(szPath);
2383           len = strlen(szPath);
2384
2385           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
2386             return E_OUTOFMEMORY;
2387         }
2388         strRet->uType = STRRET_CSTRA;
2389         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
2390
2391
2392         TRACE("-- (%p)->(%s)\n", This, szPath);
2393         return S_OK;
2394 }
2395
2396 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
2397         IShellFolder2 * iface,
2398         GUID *pguid)
2399 {
2400         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2401         FIXME("(%p)\n",This);
2402         return E_NOTIMPL;
2403 }       
2404 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
2405         IShellFolder2 * iface,
2406         IEnumExtraSearch **ppenum)
2407 {
2408         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2409         FIXME("(%p)\n",This);
2410         return E_NOTIMPL;
2411 }       
2412 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
2413         IShellFolder2 * iface,
2414         DWORD dwRes,
2415         ULONG *pSort,
2416         ULONG *pDisplay)
2417 {
2418         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2419
2420         TRACE("(%p)\n",This);
2421
2422         if (pSort) *pSort = 0;
2423         if (pDisplay) *pDisplay = 0;
2424
2425         return S_OK;
2426 }       
2427 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
2428         IShellFolder2 * iface,
2429         UINT iColumn,
2430         DWORD *pcsFlags)
2431 {
2432         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2433         
2434         TRACE("(%p)\n",This);
2435
2436         if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2437
2438         *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
2439
2440         return S_OK;
2441 }       
2442 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
2443         IShellFolder2 * iface,
2444         LPCITEMIDLIST pidl,
2445         const SHCOLUMNID *pscid,
2446         VARIANT *pv)
2447 {
2448         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2449         FIXME("(%p)\n",This);
2450
2451         return E_NOTIMPL;
2452 }       
2453
2454 /* fixme: drive size >4GB is rolling over */
2455 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
2456         IShellFolder2 * iface,
2457         LPCITEMIDLIST pidl,
2458         UINT iColumn,
2459         SHELLDETAILS *psd)
2460 {
2461         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2462         HRESULT hr;
2463
2464         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2465
2466         if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2467         
2468         if (!pidl)
2469         {
2470           psd->fmt = MyComputerSFHeader[iColumn].fmt;
2471           psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
2472           psd->str.uType = STRRET_CSTRA;
2473           LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2474           return S_OK;
2475         }
2476         else
2477         {
2478           char szPath[MAX_PATH];
2479           ULARGE_INTEGER ulBytes;
2480
2481           psd->str.u.cStr[0] = 0x00;
2482           psd->str.uType = STRRET_CSTRA;
2483           switch(iColumn)
2484           {
2485             case 0:     /* name */
2486               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2487               break;
2488             case 1:     /* type */
2489               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2490               break;
2491             case 2:     /* total size */
2492               if (_ILIsDrive(pidl))
2493               {
2494                 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2495                 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
2496                 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2497               }
2498               break;
2499             case 3:     /* free size */
2500               if (_ILIsDrive(pidl))
2501               {
2502                 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2503                 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
2504                 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2505               }
2506               break;
2507           }
2508           hr = S_OK;
2509         }
2510
2511         return hr;
2512 }       
2513 static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
2514         IShellFolder2 * iface,
2515         LPCWSTR pwszName,
2516         SHCOLUMNID *pscid)
2517 {
2518         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2519         FIXME("(%p)\n",This);
2520         return E_NOTIMPL;
2521 }       
2522
2523 static ICOM_VTABLE(IShellFolder2) sfmcvt = 
2524 {       
2525         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2526         IShellFolder_fnQueryInterface,
2527         IShellFolder_fnAddRef,
2528         IShellFolder_fnRelease,
2529         ISF_MyComputer_fnParseDisplayName,
2530         ISF_MyComputer_fnEnumObjects,
2531         ISF_MyComputer_fnBindToObject,
2532         IShellFolder_fnBindToStorage,
2533         IShellFolder_fnCompareIDs,
2534         ISF_MyComputer_fnCreateViewObject,
2535         ISF_MyComputer_fnGetAttributesOf,
2536         IShellFolder_fnGetUIObjectOf,
2537         ISF_MyComputer_fnGetDisplayNameOf,
2538         IShellFolder_fnSetNameOf,
2539
2540         /* ShellFolder2 */
2541         ISF_MyComputer_fnGetDefaultSearchGUID,
2542         ISF_MyComputer_fnEnumSearches,
2543         ISF_MyComputer_fnGetDefaultColumn,
2544         ISF_MyComputer_fnGetDefaultColumnState,
2545         ISF_MyComputer_fnGetDetailsEx,
2546         ISF_MyComputer_fnGetDetailsOf,
2547         ISF_MyComputer_fnMapNameToSCID
2548 };
2549
2550
2551 /************************************************************************
2552  * ISFPersistFolder_QueryInterface (IUnknown)
2553  *
2554  */
2555 static HRESULT WINAPI ISFPersistFolder2_QueryInterface(
2556         IPersistFolder2 *       iface,
2557         REFIID                  iid,
2558         LPVOID*                 ppvObj)
2559 {
2560         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2561
2562         TRACE("(%p)\n", This);
2563
2564         return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
2565 }
2566
2567 /************************************************************************
2568  * ISFPersistFolder_AddRef (IUnknown)
2569  *
2570  */
2571 static ULONG WINAPI ISFPersistFolder2_AddRef(
2572         IPersistFolder2 *       iface)
2573 {
2574         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2575
2576         TRACE("(%p)\n", This);
2577
2578         return IUnknown_AddRef(This->pUnkOuter);
2579 }
2580
2581 /************************************************************************
2582  * ISFPersistFolder_Release (IUnknown)
2583  *
2584  */
2585 static ULONG WINAPI ISFPersistFolder2_Release(
2586         IPersistFolder2 *       iface)
2587 {
2588         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2589
2590         TRACE("(%p)\n", This);
2591
2592         return IUnknown_Release(This->pUnkOuter);
2593 }
2594
2595 /************************************************************************
2596  * ISFPersistFolder_GetClassID (IPersist)
2597  */
2598 static HRESULT WINAPI ISFPersistFolder2_GetClassID(
2599         IPersistFolder2 *       iface,
2600         CLSID *                 lpClassId)
2601 {
2602         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2603
2604         TRACE("(%p)\n", This);
2605
2606         if (!lpClassId) return E_POINTER;
2607         *lpClassId = *This->pclsid;
2608
2609         return S_OK;
2610 }
2611
2612 /************************************************************************
2613  * ISFPersistFolder_Initialize (IPersistFolder)
2614  *
2615  * NOTES
2616  *  sMyPath is not set. Don't know how to handle in a non rooted environment.
2617  */
2618 static HRESULT WINAPI ISFPersistFolder2_Initialize(
2619         IPersistFolder2 *       iface,
2620         LPCITEMIDLIST           pidl)
2621 {
2622         char sTemp[MAX_PATH];
2623         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2624
2625         TRACE("(%p)->(%p)\n", This, pidl);
2626
2627         /* free the old stuff */
2628         if(This->absPidl)
2629         {
2630           SHFree(This->absPidl);
2631           This->absPidl = NULL;
2632         }
2633         if(This->sMyPath)
2634         {
2635           SHFree(This->sMyPath);
2636           This->sMyPath = NULL;
2637         }
2638
2639         /* set my pidl */
2640         This->absPidl = ILClone(pidl);
2641
2642         /* set my path */
2643         if (SHGetPathFromIDListA(pidl, sTemp))
2644         {
2645           This->sMyPath = SHAlloc(strlen(sTemp)+1);
2646           strcpy(This->sMyPath, sTemp);
2647         }
2648
2649         TRACE("--(%p)->(%s)\n", This, This->sMyPath);
2650
2651         return S_OK;
2652 }
2653
2654 /**************************************************************************
2655 *  IPersistFolder2_fnGetCurFolder
2656 */
2657 static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder(
2658         IPersistFolder2 *       iface,
2659         LPITEMIDLIST * pidl)
2660 {
2661         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2662         
2663         TRACE("(%p)->(%p)\n",This, pidl);
2664
2665         if (!pidl) return E_POINTER;
2666
2667         *pidl = ILClone(This->absPidl);
2668
2669         return S_OK;
2670 }
2671
2672 static ICOM_VTABLE(IPersistFolder2) psfvt = 
2673 {
2674         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2675         ISFPersistFolder2_QueryInterface,
2676         ISFPersistFolder2_AddRef,
2677         ISFPersistFolder2_Release,
2678         ISFPersistFolder2_GetClassID,
2679         ISFPersistFolder2_Initialize,
2680         ISFPersistFolder2_fnGetCurFolder
2681 };
2682
2683 /****************************************************************************
2684  * ISFDropTarget implementation
2685  */
2686 static BOOL ISFDropTarget_QueryDrop(
2687         IDropTarget *iface,
2688         DWORD dwKeyState,
2689         LPDWORD pdwEffect)
2690 {
2691         DWORD dwEffect = *pdwEffect;
2692
2693         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2694         
2695         *pdwEffect = DROPEFFECT_NONE;
2696
2697         if (This->fAcceptFmt)
2698         { /* Does our interpretation of the keystate ... */
2699           *pdwEffect = KeyStateToDropEffect(dwKeyState);
2700           
2701           /* ... matches the desired effect ? */
2702           if (dwEffect & *pdwEffect)
2703           {
2704             return TRUE;
2705           }
2706         }
2707         return FALSE;
2708 }
2709
2710 static HRESULT WINAPI ISFDropTarget_QueryInterface(
2711         IDropTarget *iface,
2712         REFIID riid,
2713         LPVOID *ppvObj)
2714 {
2715         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2716
2717         TRACE("(%p)\n", This);
2718
2719         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
2720 }
2721
2722 static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
2723 {
2724         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2725
2726         TRACE("(%p)\n", This);
2727
2728         return IUnknown_AddRef(This->pUnkOuter);
2729 }
2730
2731 static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
2732 {
2733         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2734
2735         TRACE("(%p)\n", This);
2736
2737         return IUnknown_Release(This->pUnkOuter);
2738 }
2739
2740 static HRESULT WINAPI ISFDropTarget_DragEnter(
2741         IDropTarget     *iface,
2742         IDataObject     *pDataObject,
2743         DWORD           dwKeyState,
2744         POINTL          pt,
2745         DWORD           *pdwEffect)
2746 {       
2747         FORMATETC       fmt;
2748         
2749         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2750
2751         TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
2752
2753         InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
2754
2755         This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
2756
2757         ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2758
2759         return S_OK;
2760 }
2761
2762 static HRESULT WINAPI ISFDropTarget_DragOver(
2763         IDropTarget     *iface,
2764         DWORD           dwKeyState,
2765         POINTL          pt,
2766         DWORD           *pdwEffect)
2767 {
2768         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2769
2770         TRACE("(%p)\n",This);
2771         
2772         if(!pdwEffect) return E_INVALIDARG;
2773
2774         ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2775
2776         return S_OK;
2777 }
2778
2779 static HRESULT WINAPI ISFDropTarget_DragLeave(
2780         IDropTarget     *iface)
2781 {
2782         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2783
2784         TRACE("(%p)\n",This);
2785
2786         This->fAcceptFmt = FALSE;
2787         
2788         return S_OK;
2789 }
2790
2791 static HRESULT WINAPI ISFDropTarget_Drop(
2792         IDropTarget     *iface,
2793         IDataObject*    pDataObject,
2794         DWORD           dwKeyState,
2795         POINTL          pt,
2796         DWORD           *pdwEffect)
2797 {
2798         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2799
2800         FIXME("(%p) object dropped\n",This);
2801
2802         return E_NOTIMPL;
2803 }
2804
2805 static struct ICOM_VTABLE(IDropTarget) dtvt = 
2806 {
2807         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2808         ISFDropTarget_QueryInterface,
2809         ISFDropTarget_AddRef,
2810         ISFDropTarget_Release,
2811         ISFDropTarget_DragEnter,
2812         ISFDropTarget_DragOver,
2813         ISFDropTarget_DragLeave,
2814         ISFDropTarget_Drop
2815 };