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