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