Change the V86BASE macro to call DOSMEM_MemoryBase() instead of using
[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
18 #include "oleidl.h"
19 #include "shlguid.h"
20
21 #include "pidl.h"
22 #include "wine/obj_base.h"
23 #include "wine/obj_dragdrop.h"
24 #include "wine/obj_shellfolder.h"
25 #include "wine/undocshell.h"
26 #include "shell32_main.h"
27 #include "shresdef.h"
28 #include "shlwapi.h"
29
30 #define INITGUID
31 #include "initguid.h"
32 #include "shellfolder.h"
33
34
35 DEFAULT_DEBUG_CHANNEL(shell)
36
37
38 /***************************************************************************
39  * debughelper: print out the return adress
40  *  helps especially to track down unbalanced AddRef/Release
41  */
42 #define MEM_DEBUG 0
43
44 #if MEM_DEBUG
45 #define _CALL_TRACE TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 ));
46 #else
47 #define _CALL_TRACE
48 #endif
49
50 typedef struct
51 {
52         int     colnameid;
53         int     pcsFlags;
54         int     fmt;
55         int     cxChar;
56         
57 } shvheader;
58
59 /***************************************************************************
60  *  GetNextElement (internal function)
61  *
62  * gets a part of a string till the first backslash
63  *
64  * PARAMETERS
65  *  pszNext [IN] string to get the element from
66  *  pszOut  [IN] pointer to buffer whitch receives string
67  *  dwOut   [IN] length of pszOut
68  *
69  *  RETURNS
70  *    LPSTR pointer to first, not yet parsed char
71  */
72
73 static LPCWSTR GetNextElementW(LPCWSTR pszNext,LPWSTR pszOut,DWORD dwOut)
74 {       LPCWSTR   pszTail = pszNext;
75         DWORD dwCopy;
76         TRACE("(%s %p 0x%08lx)\n",debugstr_w(pszNext),pszOut,dwOut);
77
78         *pszOut=0x0000;
79         
80         if(!pszNext || !*pszNext)
81           return NULL;
82
83         while(*pszTail && (*pszTail != (WCHAR)'\\'))
84           pszTail++;
85
86         dwCopy = (WCHAR*)pszTail - (WCHAR*)pszNext + 1;
87         lstrcpynW(pszOut, pszNext, (dwOut<dwCopy)? dwOut : dwCopy);
88
89         if(*pszTail)
90            pszTail++;
91         else
92            pszTail = NULL;
93
94         TRACE("--(%s %s 0x%08lx %p)\n",debugstr_w(pszNext),debugstr_w(pszOut),dwOut,pszTail);
95         return pszTail;
96 }
97
98 static HRESULT SHELL32_ParseNextElement(
99         HWND hwndOwner,
100         IShellFolder2 * psf,
101         LPITEMIDLIST * pidlInOut,
102         LPOLESTR szNext,
103         DWORD *pEaten,
104         DWORD *pdwAttributes)
105 {
106         HRESULT         hr = E_OUTOFMEMORY;
107         LPITEMIDLIST    pidlOut, pidlTemp = NULL;
108         IShellFolder    *psfChild;
109         
110         TRACE("(%p, %p, %s)\n",psf, pidlInOut ? *pidlInOut : NULL, debugstr_w(szNext));
111
112
113         /* get the shellfolder for the child pidl and let it analyse further */
114         hr = IShellFolder_BindToObject(psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
115
116         if (psfChild)
117         {
118           hr = IShellFolder_ParseDisplayName(psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes);
119           IShellFolder_Release(psfChild);
120
121           pidlTemp = ILCombine(*pidlInOut, pidlOut);
122
123           if (pidlOut) 
124             ILFree(pidlOut);
125         }
126
127         ILFree(*pidlInOut);
128         *pidlInOut = pidlTemp;
129
130         TRACE("-- pidl=%p ret=0x%08lx\n", pidlInOut? *pidlInOut: NULL, hr);
131         return hr;      
132 }
133
134 /***********************************************************************
135  *      SHELL32_CoCreateInitSF
136  *
137  *      creates a initialized shell folder
138  */
139 static HRESULT SHELL32_CoCreateInitSF (
140         LPITEMIDLIST pidlRoot,
141         LPITEMIDLIST pidlChild,
142         REFCLSID clsid,
143         REFIID iid,
144         LPVOID * ppvOut)
145 {
146         HRESULT hr;
147         LPITEMIDLIST    absPidl;
148         IShellFolder2   *pShellFolder;
149         IPersistFolder  *pPersistFolder;
150
151         TRACE("%p %p\n", pidlRoot, pidlChild);
152
153         *ppvOut = NULL;
154         
155         /* we have to ask first for IPersistFolder, some special folders are expecting this */
156         hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IPersistFolder, (LPVOID*)&pPersistFolder);
157         if (SUCCEEDED(hr))
158         {
159           hr = IPersistFolder_QueryInterface(pPersistFolder, iid, (LPVOID*)&pShellFolder);
160           if (SUCCEEDED(hr))
161           {
162             absPidl = ILCombine (pidlRoot, pidlChild);
163             hr = IPersistFolder_Initialize(pPersistFolder, absPidl);
164             IPersistFolder_Release(pPersistFolder);
165             SHFree(absPidl);
166             *ppvOut = pShellFolder;
167           }
168         }
169
170         TRACE("-- ret=0x%08lx\n", hr);
171         return hr;
172 }
173
174 static HRESULT SHELL32_GetDisplayNameOfChild(
175         IShellFolder2 * psf,
176         LPCITEMIDLIST pidl,
177         DWORD dwFlags,
178         LPSTR szOut,
179         DWORD dwOutLen)
180 {
181         LPITEMIDLIST    pidlFirst, pidlNext;
182         IShellFolder2 * psfChild;
183         HRESULT         hr = E_OUTOFMEMORY;
184         STRRET strTemp;
185         
186         TRACE("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n",psf,pidl,dwFlags,szOut, dwOutLen);
187         pdump(pidl);
188         
189         if ((pidlFirst = ILCloneFirst(pidl)))
190         { 
191           hr = IShellFolder_BindToObject(psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
192           if (SUCCEEDED(hr))
193           {
194             pidlNext = ILGetNext(pidl);
195
196             hr = IShellFolder_GetDisplayNameOf(psfChild, pidlNext, dwFlags | SHGDN_INFOLDER, &strTemp);
197             if (SUCCEEDED(hr))
198             {
199               hr = StrRetToStrNA(szOut, dwOutLen, &strTemp, pidlNext);
200             }
201
202             IShellFolder_Release(psfChild);
203           }
204           ILFree(pidlFirst);
205         }
206
207         TRACE("-- ret=0x%08lx %s\n", hr, szOut);
208
209         return hr;
210 }
211
212 /***********************************************************************
213  *  SHELL32_GetItemAttributes
214  *
215  * NOTES
216  * observerd values:
217  *  folder:     0xE0000177      FILESYSTEM | HASSUBFOLDER | FOLDER
218  *  file:       0x40000177      FILESYSTEM
219  *  drive:      0xf0000144      FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR
220  *  mycomputer: 0xb0000154      HASSUBFOLDER | FOLDER | FILESYSANCESTOR
221  *  (seems to be default for shell extensions if no registry entry exists)
222  *
223  * This functions does not set flags!! It only resets flags when nessesary.
224  */
225 static HRESULT SHELL32_GetItemAttributes(
226         IShellFolder * psf,
227         LPITEMIDLIST pidl,
228         LPDWORD pdwAttributes)
229 {
230         GUID const * clsid;
231         DWORD dwAttributes;
232         
233         TRACE("0x%08lx\n", *pdwAttributes);
234
235         if (*pdwAttributes & (0xcff3fe88))
236           WARN("attribute 0x%08lx not implemented\n", *pdwAttributes);
237         *pdwAttributes &= ~SFGAO_LINK; /* FIXME: for native filedialogs */
238
239         if (_ILIsDrive(pidl))
240         {
241           *pdwAttributes &= 0xf0000144;
242         }
243         else if ((clsid=_ILGetGUIDPointer(pidl)))
244         {
245           if (HCR_GetFolderAttributes(clsid, &dwAttributes))
246           {
247             *pdwAttributes &= dwAttributes;
248           }
249           else
250           {
251             *pdwAttributes &= 0xb0000154;
252           }       
253         }
254         else if (_ILGetDataPointer(pidl))
255         {
256           dwAttributes = _ILGetFileAttributes(pidl, NULL, 0);
257           *pdwAttributes &= ~SFGAO_FILESYSANCESTOR;
258
259           if(( SFGAO_FOLDER & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
260               *pdwAttributes &= ~(SFGAO_FOLDER|SFGAO_HASSUBFOLDER);
261
262           if(( SFGAO_HIDDEN & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN))
263               *pdwAttributes &= ~SFGAO_HIDDEN;
264
265           if(( SFGAO_READONLY & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_READONLY))
266               *pdwAttributes &= ~SFGAO_READONLY;
267         }
268         else
269         {
270           *pdwAttributes &= 0xb0000154;
271         }
272         TRACE("-- 0x%08lx\n", *pdwAttributes);
273         return S_OK;
274 }
275
276 /***********************************************************************
277 *   IShellFolder implementation
278 */
279
280 typedef struct 
281 {
282         ICOM_VFIELD(IUnknown);
283         DWORD                           ref;
284         ICOM_VTABLE(IShellFolder2)*     lpvtblShellFolder;
285         ICOM_VTABLE(IPersistFolder2)*   lpvtblPersistFolder2;
286         ICOM_VTABLE(IDropTarget)*       lpvtblDropTarget;
287         ICOM_VTABLE(ISFHelper)*         lpvtblSFHelper;
288
289         IUnknown                        *pUnkOuter;     /* used for aggregation */
290
291         CLSID*                          pclsid;
292
293         LPSTR                           sMyPath;
294         LPITEMIDLIST                    absPidl;        /* complete pidl */
295
296         UINT            cfShellIDList;                  /* clipboardformat for IDropTarget */
297         BOOL            fAcceptFmt;                     /* flag for pending Drop */
298 } IGenericSFImpl;
299
300 static struct ICOM_VTABLE(IUnknown) unkvt;
301 static struct ICOM_VTABLE(IShellFolder2) sfvt;
302 static struct ICOM_VTABLE(IPersistFolder2) psfvt;
303 static struct ICOM_VTABLE(IDropTarget) dtvt;
304 static struct ICOM_VTABLE(ISFHelper) shvt;
305
306 static IShellFolder * ISF_MyComputer_Constructor(void);
307
308 #define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder))) 
309 #define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset); 
310         
311 #define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder2))) 
312 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset); 
313         
314 #define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget))) 
315 #define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset); 
316
317 #define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper))) 
318 #define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset); 
319 /*
320   converts This to a interface pointer
321 */
322 #define _IUnknown_(This)        (IUnknown*)&(This->lpVtbl)
323 #define _IShellFolder_(This)    (IShellFolder*)&(This->lpvtblShellFolder)
324 #define _IShellFolder2_(This)   (IShellFolder2*)&(This->lpvtblShellFolder)
325 #define _IPersist_(This)        (IPersist*)&(This->lpvtblPersistFolder2)
326 #define _IPersistFolder_(This)  (IPersistFolder*)&(This->lpvtblPersistFolder2)
327 #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder2)
328 #define _IDropTarget_(This)     (IDropTarget*)&(This->lpvtblDropTarget)
329 #define _ISFHelper_(This)       (ISFHelper*)&(This->lpvtblSFHelper)
330 /**************************************************************************
331 *       registers clipboardformat once
332 */
333 static void SF_RegisterClipFmt (IGenericSFImpl * This)
334 {
335         TRACE("(%p)\n", This);
336
337         if (!This->cfShellIDList)
338         {
339           This->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
340         }
341 }
342
343 /**************************************************************************
344 *       we need a seperate IUnknown to handle aggregation
345 *       (inner IUnknown)
346 */
347 static HRESULT WINAPI IUnknown_fnQueryInterface(
348         IUnknown * iface,
349         REFIID riid,
350         LPVOID *ppvObj)
351 {
352         ICOM_THIS(IGenericSFImpl, iface);
353
354         _CALL_TRACE
355         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
356
357         *ppvObj = NULL;
358
359         if(IsEqualIID(riid, &IID_IUnknown))             *ppvObj = _IUnknown_(This); 
360         else if(IsEqualIID(riid, &IID_IShellFolder))    *ppvObj = _IShellFolder_(This);
361         else if(IsEqualIID(riid, &IID_IShellFolder2))   *ppvObj = _IShellFolder_(This);
362         else if(IsEqualIID(riid, &IID_IPersist))        *ppvObj = _IPersist_(This);
363         else if(IsEqualIID(riid, &IID_IPersistFolder))  *ppvObj = _IPersistFolder_(This);
364         else if(IsEqualIID(riid, &IID_IPersistFolder2)) *ppvObj = _IPersistFolder2_(This);
365         else if(IsEqualIID(riid, &IID_ISFHelper))       *ppvObj = _ISFHelper_(This);
366         else if(IsEqualIID(riid, &IID_IDropTarget))
367         {
368           *ppvObj = _IDropTarget_(This);
369           SF_RegisterClipFmt(This);
370         }
371
372         if(*ppvObj)
373         {
374           IUnknown_AddRef((IUnknown*)(*ppvObj));
375           TRACE("-- Interface = %p\n", *ppvObj);
376           return S_OK;
377         }
378         TRACE("-- Interface: E_NOINTERFACE\n");
379         return E_NOINTERFACE;
380 }
381
382 static ULONG WINAPI IUnknown_fnAddRef(IUnknown * iface)
383 {
384         ICOM_THIS(IGenericSFImpl, iface);
385
386         _CALL_TRACE
387         TRACE("(%p)->(count=%lu)\n",This,This->ref);
388
389         shell32_ObjCount++;
390         return ++(This->ref);
391 }
392
393 static ULONG WINAPI IUnknown_fnRelease(IUnknown * iface) 
394 {
395         ICOM_THIS(IGenericSFImpl, iface);
396
397         _CALL_TRACE
398         TRACE("(%p)->(count=%lu)\n",This,This->ref);
399
400         shell32_ObjCount--;
401         if (!--(This->ref)) 
402         {
403           TRACE("-- destroying IShellFolder(%p)\n",This);
404
405           if (pdesktopfolder == _IShellFolder_(This))
406           {
407             pdesktopfolder=NULL;
408             TRACE("-- destroyed IShellFolder(%p) was Desktopfolder\n",This);
409           }
410           if(This->absPidl) SHFree(This->absPidl);
411           if(This->sMyPath) SHFree(This->sMyPath);
412           HeapFree(GetProcessHeap(),0,This);
413           return 0;
414         }
415         return This->ref;
416 }
417
418 static ICOM_VTABLE(IUnknown) unkvt = 
419 {       
420         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
421         IUnknown_fnQueryInterface,
422         IUnknown_fnAddRef,
423         IUnknown_fnRelease,
424 };
425
426 static shvheader GenericSFHeader [] =
427 {
428  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
429  { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
430  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
431  { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
432  { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
433 };
434 #define GENERICSHELLVIEWCOLUMNS 5
435
436 /**************************************************************************
437 *       IShellFolder_Constructor
438 *
439 * NOTES
440 *  creating undocumented ShellFS_Folder as part of an aggregation
441 *  {F3364BA0-65B9-11CE-A9BA-00AA004AE837}
442 *
443 * FIXME
444 *       when pUnkOuter = 0 then rrid = IID_IShellFolder is returned
445 */
446 HRESULT IFSFolder_Constructor(
447         IUnknown * pUnkOuter,
448         REFIID riid,
449         LPVOID * ppv)
450 {
451         IGenericSFImpl *        sf;
452         HRESULT hr = S_OK;
453
454         TRACE("unkOut=%p riid=%s\n",pUnkOuter, debugstr_guid(riid));
455
456         if(pUnkOuter && ! IsEqualIID(riid, &IID_IUnknown))
457         {
458           hr = CLASS_E_NOAGGREGATION;   /* forbidden by definition */
459         }
460         else
461         {
462           sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
463           if (sf)
464           {
465             sf->ref=1;
466             ICOM_VTBL(sf)=&unkvt;
467             sf->lpvtblShellFolder=&sfvt;
468             sf->lpvtblPersistFolder2=&psfvt;
469             sf->lpvtblDropTarget=&dtvt;
470             sf->lpvtblSFHelper=&shvt;
471             
472             sf->pclsid = (CLSID*)&CLSID_SFFile;
473             sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_(sf);
474             *ppv = _IUnknown_(sf);
475             hr = S_OK;
476             shell32_ObjCount++;
477           }
478           else
479           {
480             hr = E_OUTOFMEMORY;
481           }
482         }
483         return hr;
484 }
485 /**************************************************************************
486 *         IShellFolder_Constructor
487 *
488 * NOTES
489 *       THIS points to the parent folder
490 */
491
492 IShellFolder * IShellFolder_Constructor(
493         IShellFolder2 * iface,
494         LPITEMIDLIST pidl)
495 {
496         IGenericSFImpl *        sf;
497         DWORD                   dwSize=0;
498
499         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
500
501         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
502         sf->ref=1;
503
504         ICOM_VTBL(sf)=&unkvt;
505         sf->lpvtblShellFolder=&sfvt;
506         sf->lpvtblPersistFolder2=&psfvt;
507         sf->lpvtblDropTarget=&dtvt;
508         sf->lpvtblSFHelper=&shvt;
509
510         sf->pclsid = (CLSID*)&CLSID_SFFile;
511         sf->pUnkOuter = _IUnknown_(sf);
512
513         TRACE("(%p)->(parent=%p, pidl=%p)\n",sf,This, pidl);
514         pdump(pidl);
515                 
516         if(pidl && iface)                               /* do we have a pidl? */
517         {
518           int len;
519
520           sf->absPidl = ILCombine(This->absPidl, pidl); /* build a absolute pidl */
521
522           if (!_ILIsSpecialFolder(pidl))                                /* only file system paths */
523           {
524             if(This->sMyPath)                           /* get the size of the parents path */
525             {
526               dwSize += strlen(This->sMyPath) ;
527               TRACE("-- (%p)->(parent's path=%s)\n",sf, debugstr_a(This->sMyPath));
528             }   
529
530             dwSize += _ILSimpleGetText(pidl,NULL,0);            /* add the size of our name*/
531             sf->sMyPath = SHAlloc(dwSize + 2);                  /* '\0' and backslash */
532
533             if(!sf->sMyPath) return NULL;
534             *(sf->sMyPath)=0x00;
535
536             if(This->sMyPath)                           /* if the parent has a path, get it*/
537             {
538               strcpy(sf->sMyPath, This->sMyPath);
539               PathAddBackslashA (sf->sMyPath);
540             }
541
542             len = strlen(sf->sMyPath);
543             _ILSimpleGetText(pidl, sf->sMyPath + len, dwSize+2 - len);
544           }
545
546           TRACE("-- (%p)->(my pidl=%p, my path=%s)\n",sf, sf->absPidl,debugstr_a(sf->sMyPath));
547
548           pdump (sf->absPidl);
549         }
550
551         shell32_ObjCount++;
552         return _IShellFolder_(sf);
553 }
554
555 /**************************************************************************
556  *  IShellFolder_fnQueryInterface
557  *
558  * PARAMETERS
559  *  REFIID riid         [in ] Requested InterfaceID
560  *  LPVOID* ppvObject   [out] Interface* to hold the result
561  */
562 static HRESULT WINAPI IShellFolder_fnQueryInterface(
563         IShellFolder2 * iface,
564         REFIID riid,
565         LPVOID *ppvObj)
566 {
567         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
568
569         _CALL_TRACE
570         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
571
572         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
573 }
574
575 /**************************************************************************
576 *  IShellFolder_AddRef
577 */
578
579 static ULONG WINAPI IShellFolder_fnAddRef(IShellFolder2 * iface)
580 {
581         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
582
583         _CALL_TRACE
584         TRACE("(%p)->(count=%lu)\n",This,This->ref);
585
586         return IUnknown_AddRef(This->pUnkOuter);
587 }
588
589 /**************************************************************************
590  *  IShellFolder_fnRelease
591  */
592 static ULONG WINAPI IShellFolder_fnRelease(IShellFolder2 * iface) 
593 {
594         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
595
596         _CALL_TRACE
597         TRACE("(%p)->(count=%lu)\n",This,This->ref);
598
599         return IUnknown_Release(This->pUnkOuter);
600 }
601
602 /**************************************************************************
603 *               IShellFolder_fnParseDisplayName
604 * PARAMETERS
605 *  HWND          hwndOwner,      //[in ] Parent window for any message's
606 *  LPBC          pbc,            //[in ] reserved
607 *  LPOLESTR      lpszDisplayName,//[in ] "Unicode" displayname.
608 *  ULONG*        pchEaten,       //[out] (unicode) characters processed
609 *  LPITEMIDLIST* ppidl,          //[out] complex pidl to item
610 *  ULONG*        pdwAttributes   //[out] items attributes
611 *
612 * NOTES
613 *  every folder trys to parse only it's own (the leftmost) pidl and creates a 
614 *  subfolder to evaluate the remaining parts
615 *  now we can parse into namespaces implemented by shell extensions
616 *
617 *  behaviour on win98:  lpszDisplayName=NULL -> chrash
618 *                       lpszDisplayName="" -> returns mycoputer-pidl
619 *
620 * FIXME: 
621 *    pdwAttributes: not set
622 *    pchEaten: not set like in windows
623 */
624 static HRESULT WINAPI IShellFolder_fnParseDisplayName(
625         IShellFolder2 * iface,
626         HWND hwndOwner,
627         LPBC pbcReserved,
628         LPOLESTR lpszDisplayName,
629         DWORD *pchEaten,
630         LPITEMIDLIST *ppidl,
631         DWORD *pdwAttributes)
632 {
633         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
634
635         HRESULT         hr = E_OUTOFMEMORY;
636         LPCWSTR         szNext=NULL;
637         WCHAR           szElement[MAX_PATH];
638         CHAR            szTempA[MAX_PATH], szPath[MAX_PATH];
639         LPITEMIDLIST    pidlTemp=NULL;
640         
641         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
642         This,hwndOwner,pbcReserved,lpszDisplayName,
643         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
644
645         if (!lpszDisplayName || !ppidl) return E_INVALIDARG;
646
647         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
648         
649         if (*lpszDisplayName)
650         {       
651           /* get the next element */
652           szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
653
654           /* build the full pathname to the element */
655           lstrcpynWtoA(szTempA, szElement, lstrlenW(szElement) + 1);
656           strcpy(szPath, This->sMyPath);
657           PathAddBackslashA(szPath);
658           strcat(szPath, szTempA);
659
660           /* get the pidl */
661           pidlTemp = SHSimpleIDListFromPathA(szPath);
662
663           if (pidlTemp)
664           {
665             /* try to analyse the next element */
666             if (szNext && *szNext)
667             {
668               hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
669             }
670             else
671             {
672                if (pdwAttributes && *pdwAttributes)
673                {
674                  SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
675 /*               WIN32_FIND_DATAA fd;
676                  SHGetDataFromIDListA(_IShellFolder_(This), pidlTemp, SHGDFIL_FINDDATA, &fd, sizeof(fd));
677                  if (!(FILE_ATTRIBUTE_DIRECTORY & fd.dwFileAttributes))
678                    *pdwAttributes &= ~SFGAO_FOLDER;
679                  if (FILE_ATTRIBUTE_READONLY  & fd.dwFileAttributes)
680                    *pdwAttributes &= ~(SFGAO_CANDELETE|SFGAO_CANMOVE|SFGAO_CANRENAME );
681 */
682                }
683                hr = S_OK;
684             }
685           }
686         }
687
688         *ppidl = pidlTemp;
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         lstrcpynWtoA(szDest+len, lpName, MAX_PATH-len);
1186         
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
1496         TRACE("(%p)(%u %p)\n", This, cidl, apidl);
1497         
1498         for(i=0; i< cidl; i++)
1499         {
1500           strcpy(szPath, This->sMyPath);
1501           PathAddBackslashA(szPath);
1502           _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
1503
1504           if (_ILIsFolder(apidl[i]))
1505           {
1506             LPITEMIDLIST pidl;
1507
1508             MESSAGE("delete %s\n", szPath);
1509             if (! SHELL_DeleteDirectoryA(szPath, TRUE)) return E_FAIL;
1510             pidl = ILCombine(This->absPidl, apidl[i]);
1511             SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
1512             SHFree(pidl); 
1513           }
1514           else if (_ILIsValue(apidl[i]))
1515           {
1516             LPITEMIDLIST pidl;
1517
1518             MESSAGE("delete %s\n", szPath);
1519             if (! DeleteFileA(szPath)) return E_FAIL;
1520             pidl = ILCombine(This->absPidl, apidl[i]);
1521             SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1522             SHFree(pidl); 
1523           }
1524
1525         }
1526         return S_OK;
1527 }
1528
1529 /****************************************************************************
1530  * ISFHelper_fnCopyItems
1531  *
1532  * copys items to this folder
1533  */
1534 static HRESULT WINAPI ISFHelper_fnCopyItems(
1535         ISFHelper *iface,
1536         IShellFolder* pSFFrom,
1537         UINT cidl,
1538         LPCITEMIDLIST *apidl)
1539 {
1540         int i;
1541         IPersistFolder2 * ppf2=NULL;
1542         char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
1543         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1544
1545         TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1546
1547         IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
1548         if (ppf2)
1549         {
1550           LPITEMIDLIST pidl;
1551           if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
1552           {
1553             for (i=0; i<cidl; i++)
1554             {
1555               SHGetPathFromIDListA(pidl, szSrcPath);
1556               PathAddBackslashA(szSrcPath);
1557               _ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
1558
1559               strcpy(szDstPath, This->sMyPath);
1560               PathAddBackslashA(szDstPath);
1561               _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
1562               MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
1563             }
1564             SHFree(pidl);
1565           }
1566           IPersistFolder2_Release(ppf2);
1567         }
1568         return S_OK;
1569 }
1570
1571 static ICOM_VTABLE(ISFHelper) shvt = 
1572 {
1573         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1574         ISFHelper_fnQueryInterface,
1575         ISFHelper_fnAddRef,
1576         ISFHelper_fnRelease,
1577         ISFHelper_fnGetUniqueName,
1578         ISFHelper_fnAddFolder,
1579         ISFHelper_fnDeleteItems,
1580         ISFHelper_fnCopyItems,
1581 };
1582
1583 /***********************************************************************
1584 *       [Desktopfolder] IShellFolder implementation
1585 */
1586 static struct ICOM_VTABLE(IShellFolder2) sfdvt;
1587
1588 static shvheader DesktopSFHeader [] =
1589 {
1590  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
1591  { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1592  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1593  { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
1594  { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
1595 };
1596 #define DESKTOPSHELLVIEWCOLUMNS 5
1597
1598 /**************************************************************************
1599 *       ISF_Desktop_Constructor
1600 *
1601 */
1602 IShellFolder * ISF_Desktop_Constructor()
1603 {
1604         IGenericSFImpl *        sf;
1605
1606         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1607         sf->ref=1;
1608         ICOM_VTBL(sf)=&unkvt;
1609         sf->lpvtblShellFolder=&sfdvt;
1610         sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1611         sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
1612
1613         TRACE("(%p)\n",sf);
1614
1615         shell32_ObjCount++;
1616         return _IShellFolder_(sf);
1617 }
1618
1619 /**************************************************************************
1620  *      ISF_Desktop_fnQueryInterface
1621  *
1622  * NOTES supports not IPersist/IPersistFolder
1623  */
1624 static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1625         IShellFolder2 * iface,
1626         REFIID riid,
1627         LPVOID *ppvObj)
1628 {
1629         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1630
1631         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1632
1633         *ppvObj = NULL;
1634
1635         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
1636         {
1637           *ppvObj = _IUnknown_(This); 
1638         }
1639         else if(IsEqualIID(riid, &IID_IShellFolder))  /*IShellFolder*/
1640         {
1641           *ppvObj = _IShellFolder_(This);
1642         }   
1643         else if(IsEqualIID(riid, &IID_IShellFolder2))  /*IShellFolder2*/
1644         {
1645           *ppvObj = _IShellFolder_(This);
1646         }   
1647
1648         if(*ppvObj)
1649         {
1650           IUnknown_AddRef((IUnknown*)(*ppvObj));
1651           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1652           return S_OK;
1653         }
1654         TRACE("-- Interface: E_NOINTERFACE\n");
1655         return E_NOINTERFACE;
1656 }
1657
1658 /**************************************************************************
1659 *       ISF_Desktop_fnParseDisplayName
1660 *
1661 * NOTES
1662 *       "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1663 *       to MyComputer
1664 */
1665 static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1666         IShellFolder2 * iface,
1667         HWND hwndOwner,
1668         LPBC pbcReserved,
1669         LPOLESTR lpszDisplayName,
1670         DWORD *pchEaten,
1671         LPITEMIDLIST *ppidl,
1672         DWORD *pdwAttributes)
1673 {
1674         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1675
1676         LPCWSTR         szNext=NULL;
1677         LPITEMIDLIST    pidlTemp=NULL;
1678         HRESULT         hr=E_OUTOFMEMORY;
1679         
1680         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1681         This,hwndOwner,pbcReserved,lpszDisplayName,
1682         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1683
1684         *ppidl = 0;
1685         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
1686         
1687         /* fixme no real parsing implemented */
1688         pidlTemp = _ILCreateMyComputer();
1689         szNext = lpszDisplayName;
1690
1691         if (szNext && *szNext)
1692         {
1693           hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1694         }
1695         else
1696         {
1697           hr = S_OK;
1698
1699           if (pdwAttributes && *pdwAttributes)
1700           {
1701             SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
1702           }
1703         }
1704
1705         *ppidl = pidlTemp;
1706
1707         TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1708
1709         return hr;      
1710 }
1711
1712 /**************************************************************************
1713 *               ISF_Desktop_fnEnumObjects
1714 */
1715 static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1716         IShellFolder2 * iface,
1717         HWND hwndOwner,
1718         DWORD dwFlags,
1719         LPENUMIDLIST* ppEnumIDList)
1720 {
1721         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1722
1723         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1724
1725         *ppEnumIDList = NULL;
1726         *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1727
1728         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1729
1730         if(!*ppEnumIDList) return E_OUTOFMEMORY;
1731
1732         return S_OK;            
1733 }
1734
1735 /**************************************************************************
1736 *               ISF_Desktop_fnBindToObject
1737 */
1738 static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
1739                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1740 {
1741         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1742         GUID            const * clsid;
1743         IShellFolder    *pShellFolder, *pSubFolder;
1744         
1745         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
1746               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
1747
1748         *ppvOut = NULL;
1749
1750         if ((clsid=_ILGetGUIDPointer(pidl)))
1751         {
1752           if ( IsEqualIID(clsid, &CLSID_MyComputer))
1753           {
1754             pShellFolder = ISF_MyComputer_Constructor();
1755           }
1756           else 
1757           {
1758              /* shell extension */
1759              if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1760              {
1761                return E_INVALIDARG;
1762              }
1763           }
1764         } 
1765         else
1766         {
1767           /* file system folder on the desktop */
1768           LPITEMIDLIST deskpidl, firstpidl, completepidl;
1769           IPersistFolder * ppf;
1770
1771           /* combine pidls */
1772           SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
1773           firstpidl = ILCloneFirst(pidl);
1774           completepidl = ILCombine(deskpidl, firstpidl);
1775
1776           pShellFolder = IShellFolder_Constructor(NULL, NULL);
1777           if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf)))
1778           {
1779             IPersistFolder_Initialize(ppf, completepidl);
1780             IPersistFolder_Release(ppf);
1781           }
1782           ILFree(completepidl);
1783           ILFree(deskpidl);
1784           ILFree(firstpidl);
1785         }
1786         
1787         if (_ILIsPidlSimple(pidl))      /* no sub folders */
1788         {
1789           *ppvOut = pShellFolder;
1790         }
1791         else                            /* go deeper */
1792         {
1793           IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1794           IShellFolder_Release(pShellFolder);
1795           *ppvOut = pSubFolder;
1796         }
1797
1798         TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1799
1800         return S_OK;
1801 }
1802
1803 /**************************************************************************
1804 *       ISF_Desktop_fnCreateViewObject
1805 */
1806 static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
1807                  HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1808 {
1809         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1810
1811         LPSHELLVIEW     pShellView;
1812         HRESULT         hr = E_INVALIDARG;
1813
1814         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
1815         
1816         if(ppvOut)
1817         {
1818           *ppvOut = NULL;
1819
1820           if(IsEqualIID(riid, &IID_IDropTarget))
1821           {
1822             WARN("IDropTarget not implemented\n");
1823             hr = E_NOTIMPL;
1824           }
1825           else if(IsEqualIID(riid, &IID_IContextMenu))
1826           {
1827             WARN("IContextMenu not implemented\n");
1828             hr = E_NOTIMPL;
1829           }
1830           else if(IsEqualIID(riid, &IID_IShellView))
1831           {
1832             pShellView = IShellView_Constructor((IShellFolder*)iface);
1833             if(pShellView)
1834             {
1835               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1836               IShellView_Release(pShellView);
1837             }
1838           }
1839         }
1840         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1841         return hr; 
1842 }
1843
1844 /**************************************************************************
1845 *  ISF_Desktop_fnGetAttributesOf
1846 */
1847 static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
1848         IShellFolder2 * iface,
1849         UINT cidl,
1850         LPCITEMIDLIST *apidl,
1851         DWORD *rgfInOut)
1852 {
1853         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1854
1855         HRESULT         hr = S_OK;
1856
1857         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1858
1859         if ( (!cidl) || (!apidl) || (!rgfInOut))
1860           return E_INVALIDARG;
1861
1862         while (cidl > 0 && *apidl)
1863         {
1864           pdump (*apidl);
1865           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1866           apidl++;
1867           cidl--;
1868         }
1869
1870         TRACE("-- result=0x%08lx\n",*rgfInOut);
1871
1872         return hr;
1873 }
1874
1875 /**************************************************************************
1876 *       ISF_Desktop_fnGetDisplayNameOf
1877 *
1878 * NOTES
1879 *       special case: pidl = null gives desktop-name back
1880 */
1881 static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1882         IShellFolder2 * iface,
1883         LPCITEMIDLIST pidl,
1884         DWORD dwFlags,
1885         LPSTRRET strRet)
1886 {
1887         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1888
1889         CHAR            szPath[MAX_PATH]= "";
1890                 
1891         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1892         pdump(pidl);
1893         
1894         if(!strRet) return E_INVALIDARG;
1895         
1896         if(!pidl)
1897         {
1898           HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1899         }
1900         else if ( _ILIsPidlSimple(pidl) )
1901         {
1902           _ILSimpleGetText(pidl, szPath, MAX_PATH);
1903         }
1904         else
1905         { 
1906           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
1907             return E_OUTOFMEMORY;
1908         }
1909         strRet->uType = STRRET_CSTRA;
1910         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1911
1912
1913         TRACE("-- (%p)->(%s)\n", This, szPath);
1914         return S_OK;
1915 }
1916
1917 static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
1918         IShellFolder2 * iface,
1919         GUID *pguid)
1920 {
1921         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1922         FIXME("(%p)\n",This);
1923         return E_NOTIMPL;
1924 }       
1925 static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
1926         IShellFolder2 * iface,
1927         IEnumExtraSearch **ppenum)
1928 {
1929         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1930         FIXME("(%p)\n",This);
1931         return E_NOTIMPL;
1932 }       
1933 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
1934         IShellFolder2 * iface,
1935         DWORD dwRes,
1936         ULONG *pSort,
1937         ULONG *pDisplay)
1938 {
1939         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1940
1941         TRACE("(%p)\n",This);
1942
1943         if (pSort) *pSort = 0;
1944         if (pDisplay) *pDisplay = 0;
1945
1946         return S_OK;
1947 }       
1948 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
1949         IShellFolder2 * iface,
1950         UINT iColumn,
1951         DWORD *pcsFlags)
1952 {
1953         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1954         
1955         TRACE("(%p)\n",This);
1956
1957         if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1958
1959         *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
1960
1961         return S_OK;
1962 }       
1963 static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
1964         IShellFolder2 * iface,
1965         LPCITEMIDLIST pidl,
1966         const SHCOLUMNID *pscid,
1967         VARIANT *pv)
1968 {
1969         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1970         FIXME("(%p)\n",This);
1971
1972         return E_NOTIMPL;
1973 }       
1974 static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
1975         IShellFolder2 * iface,
1976         LPCITEMIDLIST pidl,
1977         UINT iColumn,
1978         SHELLDETAILS *psd)
1979 {
1980         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1981         HRESULT hr = E_FAIL;;
1982
1983         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1984
1985         if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1986         
1987         if (!pidl)
1988         {
1989           psd->fmt = DesktopSFHeader[iColumn].fmt;
1990           psd->cxChar = DesktopSFHeader[iColumn].cxChar;
1991           psd->str.uType = STRRET_CSTRA;
1992           LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
1993           return S_OK;
1994         }
1995         else
1996         {
1997           /* the data from the pidl */
1998           switch(iColumn)
1999           {
2000             case 0:     /* name */
2001               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2002               break;
2003             case 1:     /* size */
2004               _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
2005               break;
2006             case 2:     /* type */
2007               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2008               break;
2009             case 3:     /* date */
2010               _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
2011               break;
2012             case 4:     /* attributes */
2013               _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
2014               break;
2015           }
2016           hr = S_OK;
2017           psd->str.uType = STRRET_CSTRA;
2018         }
2019
2020         return hr;
2021 }       
2022 static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
2023         IShellFolder2 * iface,
2024         LPCWSTR pwszName,
2025         SHCOLUMNID *pscid)
2026 {
2027         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2028         FIXME("(%p)\n",This);
2029         return E_NOTIMPL;
2030 }       
2031
2032 static ICOM_VTABLE(IShellFolder2) sfdvt = 
2033 {       
2034         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2035         ISF_Desktop_fnQueryInterface,
2036         IShellFolder_fnAddRef,
2037         IShellFolder_fnRelease,
2038         ISF_Desktop_fnParseDisplayName,
2039         ISF_Desktop_fnEnumObjects,
2040         ISF_Desktop_fnBindToObject,
2041         IShellFolder_fnBindToStorage,
2042         IShellFolder_fnCompareIDs,
2043         ISF_Desktop_fnCreateViewObject,
2044         ISF_Desktop_fnGetAttributesOf,
2045         IShellFolder_fnGetUIObjectOf,
2046         ISF_Desktop_fnGetDisplayNameOf,
2047         IShellFolder_fnSetNameOf,
2048
2049         /* ShellFolder2 */
2050         ISF_Desktop_fnGetDefaultSearchGUID,
2051         ISF_Desktop_fnEnumSearches,
2052         ISF_Desktop_fnGetDefaultColumn,
2053         ISF_Desktop_fnGetDefaultColumnState,
2054         ISF_Desktop_fnGetDetailsEx,
2055         ISF_Desktop_fnGetDetailsOf,
2056         ISF_Desktop_fnMapNameToSCID
2057 };
2058
2059
2060 /***********************************************************************
2061 *   IShellFolder [MyComputer] implementation
2062 */
2063
2064 static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
2065
2066 static shvheader MyComputerSFHeader [] =
2067 {
2068  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
2069  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2070  { IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2071  { IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2072 };
2073 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
2074
2075 /**************************************************************************
2076 *       ISF_MyComputer_Constructor
2077 */
2078 static IShellFolder * ISF_MyComputer_Constructor(void)
2079 {
2080         IGenericSFImpl *        sf;
2081
2082         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
2083         sf->ref=1;
2084
2085         ICOM_VTBL(sf)=&unkvt;
2086         sf->lpvtblShellFolder=&sfmcvt;
2087         sf->lpvtblPersistFolder2 = &psfvt;
2088         sf->pclsid = (CLSID*)&CLSID_SFMyComp;
2089         sf->absPidl=_ILCreateMyComputer();      /* my qualified pidl */
2090         sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
2091
2092         TRACE("(%p)\n",sf);
2093
2094         shell32_ObjCount++;
2095         return _IShellFolder_(sf);
2096 }
2097
2098 /**************************************************************************
2099 *       ISF_MyComputer_fnParseDisplayName
2100 */
2101 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
2102         IShellFolder2 * iface,
2103         HWND hwndOwner,
2104         LPBC pbcReserved,
2105         LPOLESTR lpszDisplayName,
2106         DWORD *pchEaten,
2107         LPITEMIDLIST *ppidl,
2108         DWORD *pdwAttributes)
2109 {
2110         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2111
2112         HRESULT         hr = E_OUTOFMEMORY;
2113         LPCWSTR         szNext=NULL;
2114         WCHAR           szElement[MAX_PATH];
2115         CHAR            szTempA[MAX_PATH];
2116         LPITEMIDLIST    pidlTemp;
2117         
2118         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
2119         This,hwndOwner,pbcReserved,lpszDisplayName,
2120         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
2121
2122         *ppidl = 0;
2123         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
2124
2125         /* do we have an absolute path name ? */
2126         if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
2127             lpszDisplayName[2] == (WCHAR)'\\')
2128         {
2129           szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
2130           lstrcpynWtoA(szTempA, szElement, lstrlenW(szElement) + 1);
2131           pidlTemp = _ILCreateDrive(szTempA);
2132
2133           if (szNext && *szNext)
2134           {
2135             hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
2136           }
2137           else
2138           {
2139             if (pdwAttributes && *pdwAttributes)
2140             {
2141               SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
2142             }
2143             hr = S_OK;
2144           }
2145           *ppidl = pidlTemp;
2146         }
2147
2148         TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
2149
2150         return hr;      
2151 }
2152
2153 /**************************************************************************
2154 *               ISF_MyComputer_fnEnumObjects
2155 */
2156 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
2157         IShellFolder2 * iface,
2158         HWND hwndOwner,
2159         DWORD dwFlags,
2160         LPENUMIDLIST* ppEnumIDList)
2161 {
2162         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2163
2164         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
2165
2166         *ppEnumIDList = NULL;
2167         *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
2168
2169         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
2170
2171         if(!*ppEnumIDList) return E_OUTOFMEMORY;
2172
2173         return S_OK;            
2174 }
2175
2176 /**************************************************************************
2177 *               ISF_MyComputer_fnBindToObject
2178 */
2179 static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
2180                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
2181 {
2182         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2183         GUID            const * clsid;
2184         IShellFolder    *pShellFolder, *pSubFolder;
2185         LPITEMIDLIST    pidltemp;
2186         
2187         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
2188               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
2189
2190         if(!pidl || !ppvOut) return E_INVALIDARG;
2191
2192         *ppvOut = NULL;
2193
2194         if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
2195         {
2196            if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
2197            {
2198              return E_FAIL;
2199            }
2200         }
2201         else
2202         {
2203           if (!_ILIsDrive(pidl)) return E_INVALIDARG;
2204
2205           pidltemp = ILCloneFirst(pidl);
2206           pShellFolder = IShellFolder_Constructor(iface, pidltemp);
2207           ILFree(pidltemp);
2208         }
2209
2210         if (_ILIsPidlSimple(pidl))      /* no sub folders */
2211         {
2212           *ppvOut = pShellFolder;
2213         }
2214         else                            /* go deeper */
2215         {
2216           IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder);
2217           IShellFolder_Release(pShellFolder);
2218           *ppvOut = pSubFolder;
2219         }
2220
2221         TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
2222
2223         return S_OK;
2224 }
2225
2226 /**************************************************************************
2227 *       ISF_MyComputer_fnCreateViewObject
2228 */
2229 static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
2230                  HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
2231 {
2232         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2233
2234         LPSHELLVIEW     pShellView;
2235         HRESULT         hr = E_INVALIDARG;
2236
2237         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
2238         
2239         if(ppvOut)
2240         {
2241           *ppvOut = NULL;
2242
2243           if(IsEqualIID(riid, &IID_IDropTarget))
2244           {
2245             WARN("IDropTarget not implemented\n");
2246             hr = E_NOTIMPL;
2247           }
2248           else if(IsEqualIID(riid, &IID_IContextMenu))
2249           {
2250             WARN("IContextMenu not implemented\n");
2251             hr = E_NOTIMPL;
2252           }
2253           else if(IsEqualIID(riid, &IID_IShellView))
2254           {
2255             pShellView = IShellView_Constructor((IShellFolder*)iface);
2256             if(pShellView)
2257             {
2258               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
2259               IShellView_Release(pShellView);
2260             }
2261           }
2262         }
2263         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
2264         return hr; 
2265 }
2266
2267 /**************************************************************************
2268 *  ISF_MyComputer_fnGetAttributesOf
2269 */
2270 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
2271         IShellFolder2 * iface,
2272         UINT cidl,
2273         LPCITEMIDLIST *apidl,
2274         DWORD *rgfInOut)
2275 {
2276         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2277
2278         HRESULT         hr = S_OK;
2279
2280         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
2281
2282         if ( (!cidl) || (!apidl) || (!rgfInOut))
2283           return E_INVALIDARG;
2284
2285         while (cidl > 0 && *apidl)
2286         {
2287           pdump (*apidl);
2288           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
2289           apidl++;
2290           cidl--;
2291         }
2292
2293         TRACE("-- result=0x%08lx\n",*rgfInOut);
2294         return hr;
2295 }
2296
2297 /**************************************************************************
2298 *       ISF_MyComputer_fnGetDisplayNameOf
2299 *
2300 * NOTES
2301 *       The desktopfolder creates only complete paths (SHGDN_FORPARSING).
2302 *       SHGDN_INFOLDER makes no sense.
2303 */
2304 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
2305         IShellFolder2 * iface,
2306         LPCITEMIDLIST pidl,
2307         DWORD dwFlags,
2308         LPSTRRET strRet)
2309 {
2310         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2311
2312         char            szPath[MAX_PATH], szDrive[18];
2313         int             len = 0;
2314         BOOL            bSimplePidl;
2315                 
2316         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
2317         pdump(pidl);
2318         
2319         if(!strRet) return E_INVALIDARG;
2320         
2321         szPath[0]=0x00; szDrive[0]=0x00;
2322         
2323         
2324         bSimplePidl = _ILIsPidlSimple(pidl);
2325         
2326         if (_ILIsSpecialFolder(pidl))
2327         {
2328           /* take names of special folders only if its only this folder */
2329           if ( bSimplePidl )
2330           {
2331             _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2332           }
2333         }
2334         else
2335         {
2336           if (!_ILIsDrive(pidl))
2337           {
2338             ERR("Wrong pidl type\n");
2339             return E_INVALIDARG;
2340           }
2341
2342           _ILSimpleGetText(pidl, szPath, MAX_PATH);     /* append my own path */
2343
2344           /* long view "lw_name (C:)" */
2345           if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
2346           {
2347             DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
2348
2349             GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2350             strcat (szDrive," (");
2351             strncat (szDrive, szPath, 2);
2352             strcat (szDrive,")");
2353             strcpy (szPath, szDrive);
2354           }
2355         }
2356         
2357         if (!bSimplePidl)       /* go deeper if needed */
2358         { 
2359           PathAddBackslashA(szPath);
2360           len = strlen(szPath);
2361
2362           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
2363             return E_OUTOFMEMORY;
2364         }
2365         strRet->uType = STRRET_CSTRA;
2366         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
2367
2368
2369         TRACE("-- (%p)->(%s)\n", This, szPath);
2370         return S_OK;
2371 }
2372
2373 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
2374         IShellFolder2 * iface,
2375         GUID *pguid)
2376 {
2377         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2378         FIXME("(%p)\n",This);
2379         return E_NOTIMPL;
2380 }       
2381 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
2382         IShellFolder2 * iface,
2383         IEnumExtraSearch **ppenum)
2384 {
2385         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2386         FIXME("(%p)\n",This);
2387         return E_NOTIMPL;
2388 }       
2389 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
2390         IShellFolder2 * iface,
2391         DWORD dwRes,
2392         ULONG *pSort,
2393         ULONG *pDisplay)
2394 {
2395         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2396
2397         TRACE("(%p)\n",This);
2398
2399         if (pSort) *pSort = 0;
2400         if (pDisplay) *pDisplay = 0;
2401
2402         return S_OK;
2403 }       
2404 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
2405         IShellFolder2 * iface,
2406         UINT iColumn,
2407         DWORD *pcsFlags)
2408 {
2409         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2410         
2411         TRACE("(%p)\n",This);
2412
2413         if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2414
2415         *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
2416
2417         return S_OK;
2418 }       
2419 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
2420         IShellFolder2 * iface,
2421         LPCITEMIDLIST pidl,
2422         const SHCOLUMNID *pscid,
2423         VARIANT *pv)
2424 {
2425         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2426         FIXME("(%p)\n",This);
2427
2428         return E_NOTIMPL;
2429 }       
2430
2431 /* fixme: drive size >4GB is rolling over */
2432 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
2433         IShellFolder2 * iface,
2434         LPCITEMIDLIST pidl,
2435         UINT iColumn,
2436         SHELLDETAILS *psd)
2437 {
2438         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2439         HRESULT hr;
2440
2441         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2442
2443         if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2444         
2445         if (!pidl)
2446         {
2447           psd->fmt = MyComputerSFHeader[iColumn].fmt;
2448           psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
2449           psd->str.uType = STRRET_CSTRA;
2450           LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2451           return S_OK;
2452         }
2453         else
2454         {
2455           char szPath[MAX_PATH];
2456           ULARGE_INTEGER ulBytes;
2457
2458           psd->str.u.cStr[0] = 0x00;
2459           psd->str.uType = STRRET_CSTRA;
2460           switch(iColumn)
2461           {
2462             case 0:     /* name */
2463               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2464               break;
2465             case 1:     /* type */
2466               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2467               break;
2468             case 2:     /* total size */
2469               if (_ILIsDrive(pidl))
2470               {
2471                 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2472                 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
2473                 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2474               }
2475               break;
2476             case 3:     /* free size */
2477               if (_ILIsDrive(pidl))
2478               {
2479                 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2480                 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
2481                 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2482               }
2483               break;
2484           }
2485           hr = S_OK;
2486         }
2487
2488         return hr;
2489 }       
2490 static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
2491         IShellFolder2 * iface,
2492         LPCWSTR pwszName,
2493         SHCOLUMNID *pscid)
2494 {
2495         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2496         FIXME("(%p)\n",This);
2497         return E_NOTIMPL;
2498 }       
2499
2500 static ICOM_VTABLE(IShellFolder2) sfmcvt = 
2501 {       
2502         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2503         IShellFolder_fnQueryInterface,
2504         IShellFolder_fnAddRef,
2505         IShellFolder_fnRelease,
2506         ISF_MyComputer_fnParseDisplayName,
2507         ISF_MyComputer_fnEnumObjects,
2508         ISF_MyComputer_fnBindToObject,
2509         IShellFolder_fnBindToStorage,
2510         IShellFolder_fnCompareIDs,
2511         ISF_MyComputer_fnCreateViewObject,
2512         ISF_MyComputer_fnGetAttributesOf,
2513         IShellFolder_fnGetUIObjectOf,
2514         ISF_MyComputer_fnGetDisplayNameOf,
2515         IShellFolder_fnSetNameOf,
2516
2517         /* ShellFolder2 */
2518         ISF_MyComputer_fnGetDefaultSearchGUID,
2519         ISF_MyComputer_fnEnumSearches,
2520         ISF_MyComputer_fnGetDefaultColumn,
2521         ISF_MyComputer_fnGetDefaultColumnState,
2522         ISF_MyComputer_fnGetDetailsEx,
2523         ISF_MyComputer_fnGetDetailsOf,
2524         ISF_MyComputer_fnMapNameToSCID
2525 };
2526
2527
2528 /************************************************************************
2529  * ISFPersistFolder_QueryInterface (IUnknown)
2530  *
2531  */
2532 static HRESULT WINAPI ISFPersistFolder2_QueryInterface(
2533         IPersistFolder2 *       iface,
2534         REFIID                  iid,
2535         LPVOID*                 ppvObj)
2536 {
2537         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2538
2539         TRACE("(%p)\n", This);
2540
2541         return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
2542 }
2543
2544 /************************************************************************
2545  * ISFPersistFolder_AddRef (IUnknown)
2546  *
2547  */
2548 static ULONG WINAPI ISFPersistFolder2_AddRef(
2549         IPersistFolder2 *       iface)
2550 {
2551         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2552
2553         TRACE("(%p)\n", This);
2554
2555         return IUnknown_AddRef(This->pUnkOuter);
2556 }
2557
2558 /************************************************************************
2559  * ISFPersistFolder_Release (IUnknown)
2560  *
2561  */
2562 static ULONG WINAPI ISFPersistFolder2_Release(
2563         IPersistFolder2 *       iface)
2564 {
2565         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2566
2567         TRACE("(%p)\n", This);
2568
2569         return IUnknown_Release(This->pUnkOuter);
2570 }
2571
2572 /************************************************************************
2573  * ISFPersistFolder_GetClassID (IPersist)
2574  */
2575 static HRESULT WINAPI ISFPersistFolder2_GetClassID(
2576         IPersistFolder2 *       iface,
2577         CLSID *                 lpClassId)
2578 {
2579         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2580
2581         TRACE("(%p)\n", This);
2582
2583         if (!lpClassId) return E_POINTER;
2584         *lpClassId = *This->pclsid;
2585
2586         return S_OK;
2587 }
2588
2589 /************************************************************************
2590  * ISFPersistFolder_Initialize (IPersistFolder)
2591  *
2592  * NOTES
2593  *  sMyPath is not set. Don't know how to handle in a non rooted environment.
2594  */
2595 static HRESULT WINAPI ISFPersistFolder2_Initialize(
2596         IPersistFolder2 *       iface,
2597         LPCITEMIDLIST           pidl)
2598 {
2599         char sTemp[MAX_PATH];
2600         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2601
2602         TRACE("(%p)->(%p)\n", This, pidl);
2603
2604         /* free the old stuff */
2605         if(This->absPidl)
2606         {
2607           SHFree(This->absPidl);
2608           This->absPidl = NULL;
2609         }
2610         if(This->sMyPath)
2611         {
2612           SHFree(This->sMyPath);
2613           This->sMyPath = NULL;
2614         }
2615
2616         /* set my pidl */
2617         This->absPidl = ILClone(pidl);
2618
2619         /* set my path */
2620         if (SHGetPathFromIDListA(pidl, sTemp))
2621         {
2622           This->sMyPath = SHAlloc(strlen(sTemp)+1);
2623           strcpy(This->sMyPath, sTemp);
2624         }
2625
2626         TRACE("--(%p)->(%s)\n", This, This->sMyPath);
2627
2628         return S_OK;
2629 }
2630
2631 /**************************************************************************
2632 *  IPersistFolder2_fnGetCurFolder
2633 */
2634 static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder(
2635         IPersistFolder2 *       iface,
2636         LPITEMIDLIST * pidl)
2637 {
2638         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2639         
2640         TRACE("(%p)->(%p)\n",This, pidl);
2641
2642         if (!pidl) return E_POINTER;
2643
2644         *pidl = ILClone(This->absPidl);
2645
2646         return S_OK;
2647 }
2648
2649 static ICOM_VTABLE(IPersistFolder2) psfvt = 
2650 {
2651         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2652         ISFPersistFolder2_QueryInterface,
2653         ISFPersistFolder2_AddRef,
2654         ISFPersistFolder2_Release,
2655         ISFPersistFolder2_GetClassID,
2656         ISFPersistFolder2_Initialize,
2657         ISFPersistFolder2_fnGetCurFolder
2658 };
2659
2660 /****************************************************************************
2661  * ISFDropTarget implementation
2662  */
2663 static BOOL ISFDropTarget_QueryDrop(
2664         IDropTarget *iface,
2665         DWORD dwKeyState,
2666         LPDWORD pdwEffect)
2667 {
2668         DWORD dwEffect = *pdwEffect;
2669
2670         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2671         
2672         *pdwEffect = DROPEFFECT_NONE;
2673
2674         if (This->fAcceptFmt)
2675         { /* Does our interpretation of the keystate ... */
2676           *pdwEffect = KeyStateToDropEffect(dwKeyState);
2677           
2678           /* ... matches the desired effect ? */
2679           if (dwEffect & *pdwEffect)
2680           {
2681             return TRUE;
2682           }
2683         }
2684         return FALSE;
2685 }
2686
2687 static HRESULT WINAPI ISFDropTarget_QueryInterface(
2688         IDropTarget *iface,
2689         REFIID riid,
2690         LPVOID *ppvObj)
2691 {
2692         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2693
2694         TRACE("(%p)\n", This);
2695
2696         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
2697 }
2698
2699 static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
2700 {
2701         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2702
2703         TRACE("(%p)\n", This);
2704
2705         return IUnknown_AddRef(This->pUnkOuter);
2706 }
2707
2708 static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
2709 {
2710         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2711
2712         TRACE("(%p)\n", This);
2713
2714         return IUnknown_Release(This->pUnkOuter);
2715 }
2716
2717 static HRESULT WINAPI ISFDropTarget_DragEnter(
2718         IDropTarget     *iface,
2719         IDataObject     *pDataObject,
2720         DWORD           dwKeyState,
2721         POINTL          pt,
2722         DWORD           *pdwEffect)
2723 {       
2724         FORMATETC       fmt;
2725         
2726         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2727
2728         TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
2729
2730         InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
2731
2732         This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
2733
2734         ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2735
2736         return S_OK;
2737 }
2738
2739 static HRESULT WINAPI ISFDropTarget_DragOver(
2740         IDropTarget     *iface,
2741         DWORD           dwKeyState,
2742         POINTL          pt,
2743         DWORD           *pdwEffect)
2744 {
2745         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2746
2747         TRACE("(%p)\n",This);
2748         
2749         if(!pdwEffect) return E_INVALIDARG;
2750
2751         ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2752
2753         return S_OK;
2754 }
2755
2756 static HRESULT WINAPI ISFDropTarget_DragLeave(
2757         IDropTarget     *iface)
2758 {
2759         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2760
2761         TRACE("(%p)\n",This);
2762
2763         This->fAcceptFmt = FALSE;
2764         
2765         return S_OK;
2766 }
2767
2768 static HRESULT WINAPI ISFDropTarget_Drop(
2769         IDropTarget     *iface,
2770         IDataObject*    pDataObject,
2771         DWORD           dwKeyState,
2772         POINTL          pt,
2773         DWORD           *pdwEffect)
2774 {
2775         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2776
2777         FIXME("(%p) object dropped\n",This);
2778
2779         return E_NOTIMPL;
2780 }
2781
2782 static struct ICOM_VTABLE(IDropTarget) dtvt = 
2783 {
2784         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2785         ISFDropTarget_QueryInterface,
2786         ISFDropTarget_AddRef,
2787         ISFDropTarget_Release,
2788         ISFDropTarget_DragEnter,
2789         ISFDropTarget_DragOver,
2790         ISFDropTarget_DragLeave,
2791         ISFDropTarget_Drop
2792 };