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