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