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