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