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