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