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