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