Confirm file deletes. Make delete confirmation messages more
[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 "wine/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 seperate 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         *ppidl = pidlTemp;
686
687         TRACE("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl? *ppidl:0, hr);
688
689         return hr;      
690 }
691
692 /**************************************************************************
693 *               IShellFolder_fnEnumObjects
694 * PARAMETERS
695 *  HWND          hwndOwner,    //[in ] Parent Window
696 *  DWORD         grfFlags,     //[in ] SHCONTF enumeration mask
697 *  LPENUMIDLIST* ppenumIDList  //[out] IEnumIDList interface
698 */
699 static HRESULT WINAPI IShellFolder_fnEnumObjects(
700         IShellFolder2 * iface,
701         HWND hwndOwner,
702         DWORD dwFlags,
703         LPENUMIDLIST* ppEnumIDList)
704 {
705         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
706
707         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
708
709         *ppEnumIDList = NULL;
710         *ppEnumIDList = IEnumIDList_Constructor (This->sMyPath, dwFlags, EIDL_FILE);
711
712         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
713
714         if(!*ppEnumIDList) return E_OUTOFMEMORY;
715
716         return S_OK;            
717 }
718
719 /**************************************************************************
720 *               IShellFolder_fnBindToObject
721 * PARAMETERS
722 *  LPCITEMIDLIST pidl,       //[in ] relative pidl to open
723 *  LPBC          pbc,        //[in ] reserved
724 *  REFIID        riid,       //[in ] Initial Interface
725 *  LPVOID*       ppvObject   //[out] Interface*
726 */
727 static HRESULT WINAPI IShellFolder_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
728                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
729 {
730         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
731         GUID            const * iid;
732         IShellFolder    *pShellFolder, *pSubFolder;
733         IPersistFolder  *pPersistFolder;
734         LPITEMIDLIST    absPidl;
735         
736         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
737
738         if(!pidl || !ppvOut) return E_INVALIDARG;
739
740         *ppvOut = NULL;
741
742         if ((iid=_ILGetGUIDPointer(pidl)))
743         {
744           /* we have to create a alien folder */
745           if (  SUCCEEDED(SHCoCreateInstance(NULL, iid, NULL, riid, (LPVOID*)&pShellFolder))
746              && SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder)))
747             {
748               absPidl = ILCombine (This->absPidl, pidl);
749               IPersistFolder_Initialize(pPersistFolder, absPidl);
750               IPersistFolder_Release(pPersistFolder);
751               SHFree(absPidl);
752             }
753             else
754             {
755               return E_FAIL;
756             }
757         }
758         else if(_ILIsFolder(pidl))
759         {
760           LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
761           pShellFolder = IShellFolder_Constructor(iface, pidltemp);
762           ILFree(pidltemp);
763         }
764         else
765         {
766           ERR("can't bind to a file\n");
767           return E_FAIL;
768         }
769         
770         if (_ILIsPidlSimple(pidl))
771         {
772           *ppvOut = pShellFolder;
773         }
774         else
775         {
776           IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder);
777           IShellFolder_Release(pShellFolder);
778           *ppvOut = pSubFolder;
779         }
780
781         TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
782
783         return S_OK;
784 }
785
786 /**************************************************************************
787 *  IShellFolder_fnBindToStorage
788 * PARAMETERS
789 *  LPCITEMIDLIST pidl,       //[in ] complex pidl to store
790 *  LPBC          pbc,        //[in ] reserved
791 *  REFIID        riid,       //[in ] Initial storage interface 
792 *  LPVOID*       ppvObject   //[out] Interface* returned
793 */
794 static HRESULT WINAPI IShellFolder_fnBindToStorage(
795         IShellFolder2 * iface,
796         LPCITEMIDLIST pidl,
797         LPBC pbcReserved,
798         REFIID riid,
799         LPVOID *ppvOut)
800 {
801         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
802
803         FIXME("(%p)->(pidl=%p,%p,\n\tIID:%s,%p) stub\n",
804               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
805
806         *ppvOut = NULL;
807         return E_NOTIMPL;
808 }
809
810 /**************************************************************************
811 *  IShellFolder_fnCompareIDs
812 *
813 * PARMETERS
814 *  LPARAM        lParam, //[in ] Column?
815 *  LPCITEMIDLIST pidl1,  //[in ] simple pidl
816 *  LPCITEMIDLIST pidl2)  //[in ] simple pidl
817 *
818 * NOTES
819 *   Special case - If one of the items is a Path and the other is a File,
820 *   always make the Path come before the File.
821 *
822 * NOTES 
823 *  use SCODE_CODE() on the return value to get the result
824 */
825
826 static HRESULT WINAPI  IShellFolder_fnCompareIDs(
827         IShellFolder2 * iface,
828         LPARAM lParam,
829         LPCITEMIDLIST pidl1,
830         LPCITEMIDLIST pidl2)
831 {
832         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
833
834         CHAR szTemp1[MAX_PATH];
835         CHAR szTemp2[MAX_PATH];
836         int   nReturn;
837         IShellFolder * psf;
838         HRESULT hr = E_OUTOFMEMORY;
839         LPCITEMIDLIST  pidlTemp;
840         PIDLTYPE pt1, pt2;
841
842         TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
843         pdump (pidl1);
844         pdump (pidl2);
845         
846         if (!pidl1 && !pidl2)
847         {
848           hr = ResultFromShort(0);
849         }
850         else if (!pidl1)
851         {
852           hr = ResultFromShort(-1);
853         }
854         else if (!pidl2)
855         {
856           hr = ResultFromShort(1);
857         }
858         else
859         {
860           LPPIDLDATA pd1, pd2;
861           pd1 = _ILGetDataPointer(pidl1);
862           pd2 = _ILGetDataPointer(pidl2);
863         
864           /* compate the types. sort order is the PT_* constant */
865           pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
866           pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
867
868           if (pt1 != pt2)
869           {
870             hr = ResultFromShort(pt1-pt2);
871           }
872           else                                          /* same type of pidl */
873           {
874             _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
875             _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
876             nReturn = strcasecmp(szTemp1, szTemp2);
877         
878             if (nReturn == 0)                           /* first pidl different ? */
879             {
880               pidl1 = ILGetNext(pidl1);
881
882               if (pidl1 && pidl1->mkid.cb)              /* go deeper? */        
883               {
884                 pidlTemp = ILCloneFirst(pidl1);
885                 pidl2 = ILGetNext(pidl2);
886         
887                 hr = IShellFolder_BindToObject(iface, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
888                 if (SUCCEEDED(hr))
889                 { 
890                   nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
891                   IShellFolder_Release(psf);
892                   hr = ResultFromShort(nReturn);
893                 }
894                 ILFree(pidlTemp);
895               }
896               else
897               {
898                 hr = ResultFromShort(nReturn);          /* two equal simple pidls */
899               }
900             }
901             else
902             {
903               hr = ResultFromShort(nReturn);            /* two different simple pidls */
904             }
905           }
906         }
907         
908         TRACE("-- res=0x%08lx\n", hr);
909         return hr;
910 }
911
912 /**************************************************************************
913 *       IShellFolder_fnCreateViewObject
914 */
915 static HRESULT WINAPI IShellFolder_fnCreateViewObject(
916         IShellFolder2 * iface,
917         HWND hwndOwner,
918         REFIID riid,
919         LPVOID *ppvOut)
920 {
921         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
922
923         LPSHELLVIEW     pShellView;
924         HRESULT         hr = E_INVALIDARG;
925
926         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
927         
928         if(ppvOut)
929         {
930           *ppvOut = NULL;
931
932           if(IsEqualIID(riid, &IID_IDropTarget))
933           {
934             hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, ppvOut);
935           }
936           else if(IsEqualIID(riid, &IID_IContextMenu))
937           {
938             FIXME("IContextMenu not implemented\n");
939             hr = E_NOTIMPL;
940           }
941           else if(IsEqualIID(riid, &IID_IShellView))
942           {
943             pShellView = IShellView_Constructor((IShellFolder*)iface);
944             if(pShellView)
945             {
946               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
947               IShellView_Release(pShellView);
948             }
949           }
950         }
951         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
952         return hr; 
953 }
954
955 /**************************************************************************
956 *  IShellFolder_fnGetAttributesOf
957 *
958 * PARAMETERS
959 *  UINT            cidl,     //[in ] num elements in pidl array
960 *  LPCITEMIDLIST*  apidl,    //[in ] simple pidl array 
961 *  ULONG*          rgfInOut) //[out] result array  
962 *
963 */
964 static HRESULT WINAPI IShellFolder_fnGetAttributesOf(
965         IShellFolder2 * iface,
966         UINT cidl,
967         LPCITEMIDLIST *apidl,
968         DWORD *rgfInOut)
969 {
970         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
971
972         HRESULT hr = S_OK;
973
974         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
975
976         if ( (!cidl) || (!apidl) || (!rgfInOut))
977           return E_INVALIDARG;
978
979         while (cidl > 0 && *apidl)
980         {
981           pdump (*apidl);
982           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
983           apidl++;
984           cidl--;
985         } 
986
987         TRACE("-- result=0x%08lx\n",*rgfInOut);
988
989         return hr;
990 }
991 /**************************************************************************
992 *  IShellFolder_fnGetUIObjectOf
993 *
994 * PARAMETERS
995 *  HWND           hwndOwner, //[in ] Parent window for any output
996 *  UINT           cidl,      //[in ] array size
997 *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
998 *  REFIID         riid,      //[in ] Requested Interface
999 *  UINT*          prgfInOut, //[   ] reserved 
1000 *  LPVOID*        ppvObject) //[out] Resulting Interface
1001 *
1002 * NOTES
1003 *  This function gets asked to return "view objects" for one or more (multiple select)
1004 *  items:
1005 *  The viewobject typically is an COM object with one of the following interfaces:
1006 *  IExtractIcon,IDataObject,IContextMenu
1007 *  In order to support icon positions in the default Listview your DataObject
1008 *  must implement the SetData method (in addition to GetData :) - the shell passes
1009 *  a barely documented "Icon positions" structure to SetData when the drag starts,
1010 *  and GetData's it if the drop is in another explorer window that needs the positions.
1011 */
1012 static HRESULT WINAPI IShellFolder_fnGetUIObjectOf( 
1013         IShellFolder2 * iface,
1014         HWND            hwndOwner,
1015         UINT            cidl,
1016         LPCITEMIDLIST * apidl, 
1017         REFIID          riid, 
1018         UINT *          prgfInOut,
1019         LPVOID *        ppvOut)
1020 {       
1021         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1022
1023         LPITEMIDLIST    pidl;
1024         IUnknown*       pObj = NULL; 
1025         HRESULT         hr = E_INVALIDARG;
1026         
1027         TRACE("(%p)->(0x%04x,%u,apidl=%p,\n\tIID:%s,%p,%p)\n",
1028           This,hwndOwner,cidl,apidl,debugstr_guid(riid),prgfInOut,ppvOut);
1029
1030         if (ppvOut)
1031         {
1032           *ppvOut = NULL;
1033
1034           if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
1035           {
1036             pObj  = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl);
1037             hr = S_OK;
1038           }
1039           else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
1040           {
1041             pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
1042             hr = S_OK;
1043           }
1044           else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
1045           {
1046             pidl = ILCombine(This->absPidl,apidl[0]);
1047             pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
1048             SHFree(pidl);
1049             hr = S_OK;
1050           } 
1051           else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
1052           {
1053             hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pObj);
1054           }
1055           else
1056           { 
1057             hr = E_NOINTERFACE;
1058           }
1059
1060           if(!pObj)
1061             hr = E_OUTOFMEMORY;
1062
1063           *ppvOut = pObj;
1064         }
1065         TRACE("(%p)->hr=0x%08lx\n",This, hr);
1066         return hr;
1067 }
1068
1069 /**************************************************************************
1070 *  IShellFolder_fnGetDisplayNameOf
1071 *  Retrieves the display name for the specified file object or subfolder
1072 *
1073 * PARAMETERS
1074 *  LPCITEMIDLIST pidl,    //[in ] complex pidl to item
1075 *  DWORD         dwFlags, //[in ] SHGNO formatting flags
1076 *  LPSTRRET      lpName)  //[out] Returned display name
1077 *
1078 * FIXME
1079 *  if the name is in the pidl the ret value should be a STRRET_OFFSET
1080 */
1081 #define GET_SHGDN_FOR(dwFlags)         ((DWORD)dwFlags & (DWORD)0x0000FF00)
1082 #define GET_SHGDN_RELATION(dwFlags)    ((DWORD)dwFlags & (DWORD)0x000000FF)
1083
1084 static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
1085         IShellFolder2 * iface,
1086         LPCITEMIDLIST pidl,
1087         DWORD dwFlags,
1088         LPSTRRET strRet)
1089 {
1090         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1091
1092         CHAR            szPath[MAX_PATH]= "";
1093         int             len = 0;
1094         BOOL            bSimplePidl;
1095                 
1096         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1097         pdump(pidl);
1098         
1099         if(!pidl || !strRet) return E_INVALIDARG;
1100         
1101         bSimplePidl = _ILIsPidlSimple(pidl);
1102
1103         /* take names of special folders only if its only this folder */
1104         if (_ILIsSpecialFolder(pidl))
1105         {
1106           if ( bSimplePidl)
1107           {
1108             _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1109           }
1110         }
1111         else
1112         {
1113           if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
1114           {
1115             strcpy (szPath, This->sMyPath);                     /* get path to root*/
1116             PathAddBackslashA(szPath);
1117             len = strlen(szPath);
1118           }
1119           _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
1120         }
1121         
1122         if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl)      /* go deeper if needed */
1123         {
1124           PathAddBackslashA(szPath);
1125           len = strlen(szPath);
1126
1127           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath + len, MAX_PATH - len)))
1128             return E_OUTOFMEMORY;
1129         }
1130         strRet->uType = STRRET_CSTRA;
1131         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1132
1133         TRACE("-- (%p)->(%s)\n", This, szPath);
1134         return S_OK;
1135 }
1136
1137 /**************************************************************************
1138 *  IShellFolder_fnSetNameOf
1139 *  Changes the name of a file object or subfolder, possibly changing its item
1140 *  identifier in the process.
1141 *
1142 * PARAMETERS
1143 *  HWND          hwndOwner,  //[in ] Owner window for output
1144 *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
1145 *  LPCOLESTR     lpszName,   //[in ] the items new display name
1146 *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
1147 *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
1148 */
1149 static HRESULT WINAPI IShellFolder_fnSetNameOf(
1150         IShellFolder2 * iface,
1151         HWND hwndOwner, 
1152         LPCITEMIDLIST pidl, /*simple pidl*/
1153         LPCOLESTR lpName, 
1154         DWORD dwFlags, 
1155         LPITEMIDLIST *pPidlOut)
1156 {
1157         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1158         char szSrc[MAX_PATH], szDest[MAX_PATH];
1159         int len;
1160         BOOL bIsFolder = _ILIsFolder(ILFindLastID(pidl));
1161
1162         TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p)\n",
1163           This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut);
1164
1165         /* build source path */
1166         if (dwFlags & SHGDN_INFOLDER)
1167         {
1168           strcpy(szSrc, This->sMyPath);
1169           PathAddBackslashA(szSrc);
1170           len = strlen (szSrc);
1171           _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len);
1172         }
1173         else 
1174         {
1175           SHGetPathFromIDListA(pidl, szSrc);
1176         }
1177
1178         /* build destination path */
1179         strcpy(szDest, This->sMyPath);
1180         PathAddBackslashA(szDest);
1181         len = strlen (szDest);
1182         WideCharToMultiByte( CP_ACP, 0, lpName, -1, szDest+len, MAX_PATH-len, NULL, NULL );
1183         szDest[MAX_PATH-1] = 0;
1184         TRACE("src=%s dest=%s\n", szSrc, szDest);
1185         if ( MoveFileA(szSrc, szDest) )
1186         {
1187           if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest);
1188           SHChangeNotifyA( bIsFolder?SHCNE_RENAMEFOLDER:SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
1189           return S_OK;
1190         }
1191         return E_FAIL;
1192 }
1193
1194 static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(
1195         IShellFolder2 * iface,
1196         GUID *pguid)
1197 {
1198         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1199         FIXME("(%p)\n",This);
1200         return E_NOTIMPL;
1201 }       
1202 static HRESULT WINAPI IShellFolder_fnEnumSearches(
1203         IShellFolder2 * iface,
1204         IEnumExtraSearch **ppenum)
1205 {
1206         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1207         FIXME("(%p)\n",This);
1208         return E_NOTIMPL;
1209 }       
1210 static HRESULT WINAPI IShellFolder_fnGetDefaultColumn(
1211         IShellFolder2 * iface,
1212         DWORD dwRes,
1213         ULONG *pSort,
1214         ULONG *pDisplay)
1215 {
1216         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1217
1218         TRACE("(%p)\n",This);
1219
1220         if (pSort) *pSort = 0;
1221         if (pDisplay) *pDisplay = 0;
1222
1223         return S_OK;
1224 }       
1225 static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState(
1226         IShellFolder2 * iface,
1227         UINT iColumn,
1228         DWORD *pcsFlags)
1229 {
1230         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1231         
1232         TRACE("(%p)\n",This);
1233
1234         if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1235
1236         *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
1237
1238         return S_OK;
1239 }       
1240 static HRESULT WINAPI IShellFolder_fnGetDetailsEx(
1241         IShellFolder2 * iface,
1242         LPCITEMIDLIST pidl,
1243         const SHCOLUMNID *pscid,
1244         VARIANT *pv)
1245 {
1246         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1247         FIXME("(%p)\n",This);
1248
1249         return E_NOTIMPL;
1250 }       
1251 static HRESULT WINAPI IShellFolder_fnGetDetailsOf(
1252         IShellFolder2 * iface,
1253         LPCITEMIDLIST pidl,
1254         UINT iColumn,
1255         SHELLDETAILS *psd)
1256 {
1257         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1258         HRESULT hr = E_FAIL;
1259
1260         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1261
1262         if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1263         
1264         if (!pidl)
1265         {
1266           /* the header titles */
1267           psd->fmt = GenericSFHeader[iColumn].fmt;
1268           psd->cxChar = GenericSFHeader[iColumn].cxChar;
1269           psd->str.uType = STRRET_CSTRA;
1270           LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
1271           return S_OK;
1272         }
1273         else
1274         {
1275           /* the data from the pidl */
1276           switch(iColumn)
1277           {
1278             case 0:     /* name */
1279               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
1280               break;
1281             case 1:     /* size */
1282               _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
1283               break;
1284             case 2:     /* type */
1285               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
1286               break;
1287             case 3:     /* date */
1288               _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
1289               break;
1290             case 4:     /* attributes */
1291               _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
1292               break;
1293           }
1294           hr = S_OK;
1295           psd->str.uType = STRRET_CSTRA;
1296         }
1297
1298         return hr;
1299 }       
1300 static HRESULT WINAPI IShellFolder_fnMapNameToSCID(
1301         IShellFolder2 * iface,
1302         LPCWSTR pwszName,
1303         SHCOLUMNID *pscid)
1304 {
1305         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1306         FIXME("(%p)\n",This);
1307         return E_NOTIMPL;
1308 }       
1309
1310 static ICOM_VTABLE(IShellFolder2) sfvt = 
1311 {       
1312         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1313         IShellFolder_fnQueryInterface,
1314         IShellFolder_fnAddRef,
1315         IShellFolder_fnRelease,
1316         IShellFolder_fnParseDisplayName,
1317         IShellFolder_fnEnumObjects,
1318         IShellFolder_fnBindToObject,
1319         IShellFolder_fnBindToStorage,
1320         IShellFolder_fnCompareIDs,
1321         IShellFolder_fnCreateViewObject,
1322         IShellFolder_fnGetAttributesOf,
1323         IShellFolder_fnGetUIObjectOf,
1324         IShellFolder_fnGetDisplayNameOf,
1325         IShellFolder_fnSetNameOf,
1326
1327         /* ShellFolder2 */
1328         IShellFolder_fnGetDefaultSearchGUID,
1329         IShellFolder_fnEnumSearches,
1330         IShellFolder_fnGetDefaultColumn,
1331         IShellFolder_fnGetDefaultColumnState,
1332         IShellFolder_fnGetDetailsEx,
1333         IShellFolder_fnGetDetailsOf,
1334         IShellFolder_fnMapNameToSCID
1335 };
1336
1337 /****************************************************************************
1338  * ISFHelper for IShellFolder implementation
1339  */
1340
1341 static HRESULT WINAPI ISFHelper_fnQueryInterface(
1342         ISFHelper *iface,
1343         REFIID riid,
1344         LPVOID *ppvObj)
1345 {
1346         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1347
1348         TRACE("(%p)\n", This);
1349
1350         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
1351 }
1352
1353 static ULONG WINAPI ISFHelper_fnAddRef(
1354         ISFHelper *iface)
1355 {
1356         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1357
1358         TRACE("(%p)\n", This);
1359
1360         return IUnknown_AddRef(This->pUnkOuter);
1361 }
1362
1363 static ULONG WINAPI ISFHelper_fnRelease(
1364         ISFHelper *iface)
1365 {
1366         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1367
1368         TRACE("(%p)\n", This);
1369
1370         return IUnknown_Release(This->pUnkOuter);
1371 }
1372
1373
1374 /****************************************************************************
1375  * ISFHelper_fnAddFolder
1376  *
1377  * creates a unique folder name
1378  */
1379
1380 static HRESULT WINAPI ISFHelper_fnGetUniqueName(
1381         ISFHelper *iface,
1382         LPSTR lpName,
1383         UINT uLen)
1384 {
1385         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1386         IEnumIDList * penum;
1387         HRESULT hr;
1388         char szText[MAX_PATH];
1389         char * szNewFolder = "New Folder";
1390         
1391         TRACE("(%p)(%s %u)\n", This, lpName, uLen);
1392
1393         if (uLen < strlen(szNewFolder) + 4) return E_POINTER;
1394         
1395         strcpy(lpName, szNewFolder);
1396         
1397         hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
1398         if (penum)
1399         {
1400           LPITEMIDLIST pidl;
1401           DWORD dwFetched;
1402           int i=1;
1403           
1404 next:     IEnumIDList_Reset(penum);
1405           while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched)
1406           {
1407             _ILSimpleGetText(pidl, szText, MAX_PATH);
1408             if (0 == strcasecmp(szText, lpName))
1409             {
1410               sprintf(lpName, "%s %d", szNewFolder, i++);
1411               if (i > 99) 
1412               {
1413                 hr = E_FAIL;
1414                 break;
1415               }
1416               goto next;
1417             }
1418           }
1419
1420           IEnumIDList_Release(penum);
1421         }
1422         return hr;
1423 }
1424         
1425 /****************************************************************************
1426  * ISFHelper_fnAddFolder
1427  *
1428  * adds a new folder.
1429  */
1430
1431 static HRESULT WINAPI ISFHelper_fnAddFolder(
1432         ISFHelper *iface,
1433         HWND hwnd,
1434         LPCSTR lpName,
1435         LPITEMIDLIST* ppidlOut)
1436 {
1437         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1438         char lpstrNewDir[MAX_PATH];
1439         DWORD bRes;
1440         HRESULT hres = E_FAIL;
1441         
1442         TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut);
1443
1444         strcpy(lpstrNewDir, This->sMyPath);
1445         PathAddBackslashA(lpstrNewDir);
1446         strcat(lpstrNewDir, lpName);
1447
1448         bRes = CreateDirectoryA(lpstrNewDir, NULL);
1449
1450         if (bRes)
1451         {
1452           LPITEMIDLIST pidl, pidlitem;
1453
1454           pidlitem = SHSimpleIDListFromPathA(lpstrNewDir);
1455
1456           pidl = ILCombine(This->absPidl, pidlitem);
1457           SHChangeNotifyA(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
1458           SHFree(pidl); 
1459
1460           if (ppidlOut) *ppidlOut = pidlitem;
1461           hres = S_OK;
1462         }
1463         else
1464         {
1465           char lpstrText[128+MAX_PATH];
1466           char lpstrTempText[128];
1467           char lpstrCaption[256];
1468
1469           /* Cannot Create folder because of permissions */
1470           LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText));
1471           LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption));
1472           sprintf(lpstrText,lpstrTempText, lpstrNewDir);
1473           MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
1474         }
1475
1476         return hres;
1477 }
1478
1479 /****************************************************************************
1480  * ISFHelper_fnDeleteItems
1481  *
1482  * deletes items in folder
1483  */
1484 static HRESULT WINAPI ISFHelper_fnDeleteItems(
1485         ISFHelper *iface,
1486         UINT cidl,
1487         LPCITEMIDLIST* apidl)
1488 {
1489         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1490         int i;
1491         char szPath[MAX_PATH];
1492         BOOL bConfirm = TRUE;
1493
1494         TRACE("(%p)(%u %p)\n", This, cidl, apidl);
1495         
1496         /* deleting multiple items so give a slightly different warning */
1497         if(cidl != 1)
1498         {
1499           char tmp[8]; 
1500           snprintf(tmp, sizeof(tmp), "%d", cidl);
1501           if(!SHELL_WarnItemDelete(ASK_DELETE_MULTIPLE_ITEM, tmp))
1502             return E_FAIL;
1503           bConfirm = FALSE;
1504         }
1505
1506         for(i=0; i< cidl; i++)
1507         {
1508           strcpy(szPath, This->sMyPath);
1509           PathAddBackslashA(szPath);
1510           _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
1511
1512           if (_ILIsFolder(apidl[i]))
1513           {
1514             LPITEMIDLIST pidl;
1515             TRACE("delete %s\n", szPath);
1516             if (! SHELL_DeleteDirectoryA(szPath, bConfirm))
1517             {
1518               TRACE("delete %s failed, bConfirm=%d", szPath, bConfirm);
1519               return E_FAIL;
1520             }
1521             pidl = ILCombine(This->absPidl, apidl[i]);
1522             SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
1523             SHFree(pidl); 
1524           }
1525           else if (_ILIsValue(apidl[i]))
1526           {
1527             LPITEMIDLIST pidl;
1528
1529             TRACE("delete %s\n", szPath);
1530             if (! SHELL_DeleteFileA(szPath, bConfirm))
1531             {
1532               TRACE("delete %s failed, bConfirm=%d", szPath, bConfirm);
1533               return E_FAIL;
1534             }
1535             pidl = ILCombine(This->absPidl, apidl[i]);
1536             SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1537             SHFree(pidl); 
1538           }
1539
1540         }
1541         return S_OK;
1542 }
1543
1544 /****************************************************************************
1545  * ISFHelper_fnCopyItems
1546  *
1547  * copys items to this folder
1548  */
1549 static HRESULT WINAPI ISFHelper_fnCopyItems(
1550         ISFHelper *iface,
1551         IShellFolder* pSFFrom,
1552         UINT cidl,
1553         LPCITEMIDLIST *apidl)
1554 {
1555         int i;
1556         IPersistFolder2 * ppf2=NULL;
1557         char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
1558         _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1559
1560         TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1561
1562         IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
1563         if (ppf2)
1564         {
1565           LPITEMIDLIST pidl;
1566           if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
1567           {
1568             for (i=0; i<cidl; i++)
1569             {
1570               SHGetPathFromIDListA(pidl, szSrcPath);
1571               PathAddBackslashA(szSrcPath);
1572               _ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
1573
1574               strcpy(szDstPath, This->sMyPath);
1575               PathAddBackslashA(szDstPath);
1576               _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
1577               MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
1578             }
1579             SHFree(pidl);
1580           }
1581           IPersistFolder2_Release(ppf2);
1582         }
1583         return S_OK;
1584 }
1585
1586 static ICOM_VTABLE(ISFHelper) shvt = 
1587 {
1588         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1589         ISFHelper_fnQueryInterface,
1590         ISFHelper_fnAddRef,
1591         ISFHelper_fnRelease,
1592         ISFHelper_fnGetUniqueName,
1593         ISFHelper_fnAddFolder,
1594         ISFHelper_fnDeleteItems,
1595         ISFHelper_fnCopyItems,
1596 };
1597
1598 /***********************************************************************
1599 *       [Desktopfolder] IShellFolder implementation
1600 */
1601 static struct ICOM_VTABLE(IShellFolder2) sfdvt;
1602
1603 static shvheader DesktopSFHeader [] =
1604 {
1605  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
1606  { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1607  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1608  { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
1609  { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
1610 };
1611 #define DESKTOPSHELLVIEWCOLUMNS 5
1612
1613 /**************************************************************************
1614 *       ISF_Desktop_Constructor
1615 *
1616 */
1617 IShellFolder * ISF_Desktop_Constructor()
1618 {
1619         IGenericSFImpl *        sf;
1620
1621         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1622         sf->ref=1;
1623         ICOM_VTBL(sf)=&unkvt;
1624         sf->lpvtblShellFolder=&sfdvt;
1625         sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1626         sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
1627
1628         TRACE("(%p)\n",sf);
1629
1630         shell32_ObjCount++;
1631         return _IShellFolder_(sf);
1632 }
1633
1634 /**************************************************************************
1635  *      ISF_Desktop_fnQueryInterface
1636  *
1637  * NOTES supports not IPersist/IPersistFolder
1638  */
1639 static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1640         IShellFolder2 * iface,
1641         REFIID riid,
1642         LPVOID *ppvObj)
1643 {
1644         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1645
1646         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1647
1648         *ppvObj = NULL;
1649
1650         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
1651         {
1652           *ppvObj = _IUnknown_(This); 
1653         }
1654         else if(IsEqualIID(riid, &IID_IShellFolder))  /*IShellFolder*/
1655         {
1656           *ppvObj = _IShellFolder_(This);
1657         }   
1658         else if(IsEqualIID(riid, &IID_IShellFolder2))  /*IShellFolder2*/
1659         {
1660           *ppvObj = _IShellFolder_(This);
1661         }   
1662
1663         if(*ppvObj)
1664         {
1665           IUnknown_AddRef((IUnknown*)(*ppvObj));
1666           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1667           return S_OK;
1668         }
1669         TRACE("-- Interface: E_NOINTERFACE\n");
1670         return E_NOINTERFACE;
1671 }
1672
1673 /**************************************************************************
1674 *       ISF_Desktop_fnParseDisplayName
1675 *
1676 * NOTES
1677 *       "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1678 *       to MyComputer
1679 */
1680 static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1681         IShellFolder2 * iface,
1682         HWND hwndOwner,
1683         LPBC pbcReserved,
1684         LPOLESTR lpszDisplayName,
1685         DWORD *pchEaten,
1686         LPITEMIDLIST *ppidl,
1687         DWORD *pdwAttributes)
1688 {
1689         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1690
1691         LPCWSTR         szNext=NULL;
1692         LPITEMIDLIST    pidlTemp=NULL;
1693         HRESULT         hr=E_OUTOFMEMORY;
1694         
1695         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1696         This,hwndOwner,pbcReserved,lpszDisplayName,
1697         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1698
1699         *ppidl = 0;
1700         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
1701         
1702         /* fixme no real parsing implemented */
1703         pidlTemp = _ILCreateMyComputer();
1704         szNext = lpszDisplayName;
1705
1706         if (szNext && *szNext)
1707         {
1708           hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1709         }
1710         else
1711         {
1712           hr = S_OK;
1713
1714           if (pdwAttributes && *pdwAttributes)
1715           {
1716             SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
1717           }
1718         }
1719
1720         *ppidl = pidlTemp;
1721
1722         TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1723
1724         return hr;      
1725 }
1726
1727 /**************************************************************************
1728 *               ISF_Desktop_fnEnumObjects
1729 */
1730 static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1731         IShellFolder2 * iface,
1732         HWND hwndOwner,
1733         DWORD dwFlags,
1734         LPENUMIDLIST* ppEnumIDList)
1735 {
1736         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1737
1738         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1739
1740         *ppEnumIDList = NULL;
1741         *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1742
1743         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1744
1745         if(!*ppEnumIDList) return E_OUTOFMEMORY;
1746
1747         return S_OK;            
1748 }
1749
1750 /**************************************************************************
1751 *               ISF_Desktop_fnBindToObject
1752 */
1753 static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
1754                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1755 {
1756         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1757         GUID            const * clsid;
1758         IShellFolder    *pShellFolder, *pSubFolder;
1759         
1760         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
1761               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
1762
1763         *ppvOut = NULL;
1764
1765         if ((clsid=_ILGetGUIDPointer(pidl)))
1766         {
1767           if ( IsEqualIID(clsid, &CLSID_MyComputer))
1768           {
1769             pShellFolder = ISF_MyComputer_Constructor();
1770           }
1771           else 
1772           {
1773              /* shell extension */
1774              if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1775              {
1776                return E_INVALIDARG;
1777              }
1778           }
1779         } 
1780         else
1781         {
1782           /* file system folder on the desktop */
1783           LPITEMIDLIST deskpidl, firstpidl, completepidl;
1784           IPersistFolder * ppf;
1785
1786           /* combine pidls */
1787           SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
1788           firstpidl = ILCloneFirst(pidl);
1789           completepidl = ILCombine(deskpidl, firstpidl);
1790
1791           pShellFolder = IShellFolder_Constructor(NULL, NULL);
1792           if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf)))
1793           {
1794             IPersistFolder_Initialize(ppf, completepidl);
1795             IPersistFolder_Release(ppf);
1796           }
1797           ILFree(completepidl);
1798           ILFree(deskpidl);
1799           ILFree(firstpidl);
1800         }
1801         
1802         if (_ILIsPidlSimple(pidl))      /* no sub folders */
1803         {
1804           *ppvOut = pShellFolder;
1805         }
1806         else                            /* go deeper */
1807         {
1808           IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1809           IShellFolder_Release(pShellFolder);
1810           *ppvOut = pSubFolder;
1811         }
1812
1813         TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1814
1815         return S_OK;
1816 }
1817
1818 /**************************************************************************
1819 *       ISF_Desktop_fnCreateViewObject
1820 */
1821 static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
1822                  HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1823 {
1824         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1825
1826         LPSHELLVIEW     pShellView;
1827         HRESULT         hr = E_INVALIDARG;
1828
1829         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
1830         
1831         if(ppvOut)
1832         {
1833           *ppvOut = NULL;
1834
1835           if(IsEqualIID(riid, &IID_IDropTarget))
1836           {
1837             WARN("IDropTarget not implemented\n");
1838             hr = E_NOTIMPL;
1839           }
1840           else if(IsEqualIID(riid, &IID_IContextMenu))
1841           {
1842             WARN("IContextMenu not implemented\n");
1843             hr = E_NOTIMPL;
1844           }
1845           else if(IsEqualIID(riid, &IID_IShellView))
1846           {
1847             pShellView = IShellView_Constructor((IShellFolder*)iface);
1848             if(pShellView)
1849             {
1850               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1851               IShellView_Release(pShellView);
1852             }
1853           }
1854         }
1855         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1856         return hr; 
1857 }
1858
1859 /**************************************************************************
1860 *  ISF_Desktop_fnGetAttributesOf
1861 */
1862 static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
1863         IShellFolder2 * iface,
1864         UINT cidl,
1865         LPCITEMIDLIST *apidl,
1866         DWORD *rgfInOut)
1867 {
1868         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1869
1870         HRESULT         hr = S_OK;
1871
1872         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1873
1874         if ( (!cidl) || (!apidl) || (!rgfInOut))
1875           return E_INVALIDARG;
1876
1877         while (cidl > 0 && *apidl)
1878         {
1879           pdump (*apidl);
1880           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1881           apidl++;
1882           cidl--;
1883         }
1884
1885         TRACE("-- result=0x%08lx\n",*rgfInOut);
1886
1887         return hr;
1888 }
1889
1890 /**************************************************************************
1891 *       ISF_Desktop_fnGetDisplayNameOf
1892 *
1893 * NOTES
1894 *       special case: pidl = null gives desktop-name back
1895 */
1896 static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1897         IShellFolder2 * iface,
1898         LPCITEMIDLIST pidl,
1899         DWORD dwFlags,
1900         LPSTRRET strRet)
1901 {
1902         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1903
1904         CHAR            szPath[MAX_PATH]= "";
1905                 
1906         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1907         pdump(pidl);
1908         
1909         if(!strRet) return E_INVALIDARG;
1910         
1911         if(!pidl)
1912         {
1913           HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1914         }
1915         else if ( _ILIsPidlSimple(pidl) )
1916         {
1917           _ILSimpleGetText(pidl, szPath, MAX_PATH);
1918         }
1919         else
1920         { 
1921           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
1922             return E_OUTOFMEMORY;
1923         }
1924         strRet->uType = STRRET_CSTRA;
1925         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1926
1927
1928         TRACE("-- (%p)->(%s)\n", This, szPath);
1929         return S_OK;
1930 }
1931
1932 static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
1933         IShellFolder2 * iface,
1934         GUID *pguid)
1935 {
1936         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1937         FIXME("(%p)\n",This);
1938         return E_NOTIMPL;
1939 }       
1940 static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
1941         IShellFolder2 * iface,
1942         IEnumExtraSearch **ppenum)
1943 {
1944         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1945         FIXME("(%p)\n",This);
1946         return E_NOTIMPL;
1947 }       
1948 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
1949         IShellFolder2 * iface,
1950         DWORD dwRes,
1951         ULONG *pSort,
1952         ULONG *pDisplay)
1953 {
1954         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1955
1956         TRACE("(%p)\n",This);
1957
1958         if (pSort) *pSort = 0;
1959         if (pDisplay) *pDisplay = 0;
1960
1961         return S_OK;
1962 }       
1963 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
1964         IShellFolder2 * iface,
1965         UINT iColumn,
1966         DWORD *pcsFlags)
1967 {
1968         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1969         
1970         TRACE("(%p)\n",This);
1971
1972         if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1973
1974         *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
1975
1976         return S_OK;
1977 }       
1978 static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
1979         IShellFolder2 * iface,
1980         LPCITEMIDLIST pidl,
1981         const SHCOLUMNID *pscid,
1982         VARIANT *pv)
1983 {
1984         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1985         FIXME("(%p)\n",This);
1986
1987         return E_NOTIMPL;
1988 }       
1989 static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
1990         IShellFolder2 * iface,
1991         LPCITEMIDLIST pidl,
1992         UINT iColumn,
1993         SHELLDETAILS *psd)
1994 {
1995         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1996         HRESULT hr = E_FAIL;;
1997
1998         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1999
2000         if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2001         
2002         if (!pidl)
2003         {
2004           psd->fmt = DesktopSFHeader[iColumn].fmt;
2005           psd->cxChar = DesktopSFHeader[iColumn].cxChar;
2006           psd->str.uType = STRRET_CSTRA;
2007           LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2008           return S_OK;
2009         }
2010         else
2011         {
2012           /* the data from the pidl */
2013           switch(iColumn)
2014           {
2015             case 0:     /* name */
2016               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2017               break;
2018             case 1:     /* size */
2019               _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
2020               break;
2021             case 2:     /* type */
2022               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2023               break;
2024             case 3:     /* date */
2025               _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
2026               break;
2027             case 4:     /* attributes */
2028               _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
2029               break;
2030           }
2031           hr = S_OK;
2032           psd->str.uType = STRRET_CSTRA;
2033         }
2034
2035         return hr;
2036 }       
2037 static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
2038         IShellFolder2 * iface,
2039         LPCWSTR pwszName,
2040         SHCOLUMNID *pscid)
2041 {
2042         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2043         FIXME("(%p)\n",This);
2044         return E_NOTIMPL;
2045 }       
2046
2047 static ICOM_VTABLE(IShellFolder2) sfdvt = 
2048 {       
2049         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2050         ISF_Desktop_fnQueryInterface,
2051         IShellFolder_fnAddRef,
2052         IShellFolder_fnRelease,
2053         ISF_Desktop_fnParseDisplayName,
2054         ISF_Desktop_fnEnumObjects,
2055         ISF_Desktop_fnBindToObject,
2056         IShellFolder_fnBindToStorage,
2057         IShellFolder_fnCompareIDs,
2058         ISF_Desktop_fnCreateViewObject,
2059         ISF_Desktop_fnGetAttributesOf,
2060         IShellFolder_fnGetUIObjectOf,
2061         ISF_Desktop_fnGetDisplayNameOf,
2062         IShellFolder_fnSetNameOf,
2063
2064         /* ShellFolder2 */
2065         ISF_Desktop_fnGetDefaultSearchGUID,
2066         ISF_Desktop_fnEnumSearches,
2067         ISF_Desktop_fnGetDefaultColumn,
2068         ISF_Desktop_fnGetDefaultColumnState,
2069         ISF_Desktop_fnGetDetailsEx,
2070         ISF_Desktop_fnGetDetailsOf,
2071         ISF_Desktop_fnMapNameToSCID
2072 };
2073
2074
2075 /***********************************************************************
2076 *   IShellFolder [MyComputer] implementation
2077 */
2078
2079 static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
2080
2081 static shvheader MyComputerSFHeader [] =
2082 {
2083  { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
2084  { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2085  { IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2086  { IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2087 };
2088 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
2089
2090 /**************************************************************************
2091 *       ISF_MyComputer_Constructor
2092 */
2093 static IShellFolder * ISF_MyComputer_Constructor(void)
2094 {
2095         IGenericSFImpl *        sf;
2096
2097         sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
2098         sf->ref=1;
2099
2100         ICOM_VTBL(sf)=&unkvt;
2101         sf->lpvtblShellFolder=&sfmcvt;
2102         sf->lpvtblPersistFolder2 = &psfvt;
2103         sf->pclsid = (CLSID*)&CLSID_SFMyComp;
2104         sf->absPidl=_ILCreateMyComputer();      /* my qualified pidl */
2105         sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
2106
2107         TRACE("(%p)\n",sf);
2108
2109         shell32_ObjCount++;
2110         return _IShellFolder_(sf);
2111 }
2112
2113 /**************************************************************************
2114 *       ISF_MyComputer_fnParseDisplayName
2115 */
2116 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
2117         IShellFolder2 * iface,
2118         HWND hwndOwner,
2119         LPBC pbcReserved,
2120         LPOLESTR lpszDisplayName,
2121         DWORD *pchEaten,
2122         LPITEMIDLIST *ppidl,
2123         DWORD *pdwAttributes)
2124 {
2125         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2126
2127         HRESULT         hr = E_OUTOFMEMORY;
2128         LPCWSTR         szNext=NULL;
2129         WCHAR           szElement[MAX_PATH];
2130         CHAR            szTempA[MAX_PATH];
2131         LPITEMIDLIST    pidlTemp;
2132         
2133         TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
2134         This,hwndOwner,pbcReserved,lpszDisplayName,
2135         debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
2136
2137         *ppidl = 0;
2138         if (pchEaten) *pchEaten = 0;    /* strange but like the original */
2139
2140         /* do we have an absolute path name ? */
2141         if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
2142             lpszDisplayName[2] == (WCHAR)'\\')
2143         {
2144           szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
2145           WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
2146           pidlTemp = _ILCreateDrive(szTempA);
2147
2148           if (szNext && *szNext)
2149           {
2150             hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
2151           }
2152           else
2153           {
2154             if (pdwAttributes && *pdwAttributes)
2155             {
2156               SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
2157             }
2158             hr = S_OK;
2159           }
2160           *ppidl = pidlTemp;
2161         }
2162
2163         TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
2164
2165         return hr;      
2166 }
2167
2168 /**************************************************************************
2169 *               ISF_MyComputer_fnEnumObjects
2170 */
2171 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
2172         IShellFolder2 * iface,
2173         HWND hwndOwner,
2174         DWORD dwFlags,
2175         LPENUMIDLIST* ppEnumIDList)
2176 {
2177         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2178
2179         TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
2180
2181         *ppEnumIDList = NULL;
2182         *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
2183
2184         TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
2185
2186         if(!*ppEnumIDList) return E_OUTOFMEMORY;
2187
2188         return S_OK;            
2189 }
2190
2191 /**************************************************************************
2192 *               ISF_MyComputer_fnBindToObject
2193 */
2194 static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
2195                         LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
2196 {
2197         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2198         GUID            const * clsid;
2199         IShellFolder    *pShellFolder, *pSubFolder;
2200         LPITEMIDLIST    pidltemp;
2201         
2202         TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
2203               This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
2204
2205         if(!pidl || !ppvOut) return E_INVALIDARG;
2206
2207         *ppvOut = NULL;
2208
2209         if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
2210         {
2211            if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
2212            {
2213              return E_FAIL;
2214            }
2215         }
2216         else
2217         {
2218           if (!_ILIsDrive(pidl)) return E_INVALIDARG;
2219
2220           pidltemp = ILCloneFirst(pidl);
2221           pShellFolder = IShellFolder_Constructor(iface, pidltemp);
2222           ILFree(pidltemp);
2223         }
2224
2225         if (_ILIsPidlSimple(pidl))      /* no sub folders */
2226         {
2227           *ppvOut = pShellFolder;
2228         }
2229         else                            /* go deeper */
2230         {
2231           IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder);
2232           IShellFolder_Release(pShellFolder);
2233           *ppvOut = pSubFolder;
2234         }
2235
2236         TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
2237
2238         return S_OK;
2239 }
2240
2241 /**************************************************************************
2242 *       ISF_MyComputer_fnCreateViewObject
2243 */
2244 static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
2245                  HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
2246 {
2247         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2248
2249         LPSHELLVIEW     pShellView;
2250         HRESULT         hr = E_INVALIDARG;
2251
2252         TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
2253         
2254         if(ppvOut)
2255         {
2256           *ppvOut = NULL;
2257
2258           if(IsEqualIID(riid, &IID_IDropTarget))
2259           {
2260             WARN("IDropTarget not implemented\n");
2261             hr = E_NOTIMPL;
2262           }
2263           else if(IsEqualIID(riid, &IID_IContextMenu))
2264           {
2265             WARN("IContextMenu not implemented\n");
2266             hr = E_NOTIMPL;
2267           }
2268           else if(IsEqualIID(riid, &IID_IShellView))
2269           {
2270             pShellView = IShellView_Constructor((IShellFolder*)iface);
2271             if(pShellView)
2272             {
2273               hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
2274               IShellView_Release(pShellView);
2275             }
2276           }
2277         }
2278         TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
2279         return hr; 
2280 }
2281
2282 /**************************************************************************
2283 *  ISF_MyComputer_fnGetAttributesOf
2284 */
2285 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
2286         IShellFolder2 * iface,
2287         UINT cidl,
2288         LPCITEMIDLIST *apidl,
2289         DWORD *rgfInOut)
2290 {
2291         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2292
2293         HRESULT         hr = S_OK;
2294
2295         TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
2296
2297         if ( (!cidl) || (!apidl) || (!rgfInOut))
2298           return E_INVALIDARG;
2299
2300         while (cidl > 0 && *apidl)
2301         {
2302           pdump (*apidl);
2303           SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
2304           apidl++;
2305           cidl--;
2306         }
2307
2308         TRACE("-- result=0x%08lx\n",*rgfInOut);
2309         return hr;
2310 }
2311
2312 /**************************************************************************
2313 *       ISF_MyComputer_fnGetDisplayNameOf
2314 *
2315 * NOTES
2316 *       The desktopfolder creates only complete paths (SHGDN_FORPARSING).
2317 *       SHGDN_INFOLDER makes no sense.
2318 */
2319 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
2320         IShellFolder2 * iface,
2321         LPCITEMIDLIST pidl,
2322         DWORD dwFlags,
2323         LPSTRRET strRet)
2324 {
2325         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2326
2327         char            szPath[MAX_PATH], szDrive[18];
2328         int             len = 0;
2329         BOOL            bSimplePidl;
2330                 
2331         TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
2332         pdump(pidl);
2333         
2334         if(!strRet) return E_INVALIDARG;
2335         
2336         szPath[0]=0x00; szDrive[0]=0x00;
2337         
2338         
2339         bSimplePidl = _ILIsPidlSimple(pidl);
2340         
2341         if (_ILIsSpecialFolder(pidl))
2342         {
2343           /* take names of special folders only if its only this folder */
2344           if ( bSimplePidl )
2345           {
2346             _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2347           }
2348         }
2349         else
2350         {
2351           if (!_ILIsDrive(pidl))
2352           {
2353             ERR("Wrong pidl type\n");
2354             return E_INVALIDARG;
2355           }
2356
2357           _ILSimpleGetText(pidl, szPath, MAX_PATH);     /* append my own path */
2358
2359           /* long view "lw_name (C:)" */
2360           if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
2361           {
2362             DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
2363
2364             GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2365             strcat (szDrive," (");
2366             strncat (szDrive, szPath, 2);
2367             strcat (szDrive,")");
2368             strcpy (szPath, szDrive);
2369           }
2370         }
2371         
2372         if (!bSimplePidl)       /* go deeper if needed */
2373         { 
2374           PathAddBackslashA(szPath);
2375           len = strlen(szPath);
2376
2377           if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
2378             return E_OUTOFMEMORY;
2379         }
2380         strRet->uType = STRRET_CSTRA;
2381         lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
2382
2383
2384         TRACE("-- (%p)->(%s)\n", This, szPath);
2385         return S_OK;
2386 }
2387
2388 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
2389         IShellFolder2 * iface,
2390         GUID *pguid)
2391 {
2392         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2393         FIXME("(%p)\n",This);
2394         return E_NOTIMPL;
2395 }       
2396 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
2397         IShellFolder2 * iface,
2398         IEnumExtraSearch **ppenum)
2399 {
2400         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2401         FIXME("(%p)\n",This);
2402         return E_NOTIMPL;
2403 }       
2404 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
2405         IShellFolder2 * iface,
2406         DWORD dwRes,
2407         ULONG *pSort,
2408         ULONG *pDisplay)
2409 {
2410         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2411
2412         TRACE("(%p)\n",This);
2413
2414         if (pSort) *pSort = 0;
2415         if (pDisplay) *pDisplay = 0;
2416
2417         return S_OK;
2418 }       
2419 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
2420         IShellFolder2 * iface,
2421         UINT iColumn,
2422         DWORD *pcsFlags)
2423 {
2424         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2425         
2426         TRACE("(%p)\n",This);
2427
2428         if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2429
2430         *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
2431
2432         return S_OK;
2433 }       
2434 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
2435         IShellFolder2 * iface,
2436         LPCITEMIDLIST pidl,
2437         const SHCOLUMNID *pscid,
2438         VARIANT *pv)
2439 {
2440         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2441         FIXME("(%p)\n",This);
2442
2443         return E_NOTIMPL;
2444 }       
2445
2446 /* fixme: drive size >4GB is rolling over */
2447 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
2448         IShellFolder2 * iface,
2449         LPCITEMIDLIST pidl,
2450         UINT iColumn,
2451         SHELLDETAILS *psd)
2452 {
2453         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2454         HRESULT hr;
2455
2456         TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2457
2458         if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2459         
2460         if (!pidl)
2461         {
2462           psd->fmt = MyComputerSFHeader[iColumn].fmt;
2463           psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
2464           psd->str.uType = STRRET_CSTRA;
2465           LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2466           return S_OK;
2467         }
2468         else
2469         {
2470           char szPath[MAX_PATH];
2471           ULARGE_INTEGER ulBytes;
2472
2473           psd->str.u.cStr[0] = 0x00;
2474           psd->str.uType = STRRET_CSTRA;
2475           switch(iColumn)
2476           {
2477             case 0:     /* name */
2478               hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2479               break;
2480             case 1:     /* type */
2481               _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2482               break;
2483             case 2:     /* total size */
2484               if (_ILIsDrive(pidl))
2485               {
2486                 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2487                 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
2488                 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2489               }
2490               break;
2491             case 3:     /* free size */
2492               if (_ILIsDrive(pidl))
2493               {
2494                 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2495                 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
2496                 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2497               }
2498               break;
2499           }
2500           hr = S_OK;
2501         }
2502
2503         return hr;
2504 }       
2505 static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
2506         IShellFolder2 * iface,
2507         LPCWSTR pwszName,
2508         SHCOLUMNID *pscid)
2509 {
2510         _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2511         FIXME("(%p)\n",This);
2512         return E_NOTIMPL;
2513 }       
2514
2515 static ICOM_VTABLE(IShellFolder2) sfmcvt = 
2516 {       
2517         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2518         IShellFolder_fnQueryInterface,
2519         IShellFolder_fnAddRef,
2520         IShellFolder_fnRelease,
2521         ISF_MyComputer_fnParseDisplayName,
2522         ISF_MyComputer_fnEnumObjects,
2523         ISF_MyComputer_fnBindToObject,
2524         IShellFolder_fnBindToStorage,
2525         IShellFolder_fnCompareIDs,
2526         ISF_MyComputer_fnCreateViewObject,
2527         ISF_MyComputer_fnGetAttributesOf,
2528         IShellFolder_fnGetUIObjectOf,
2529         ISF_MyComputer_fnGetDisplayNameOf,
2530         IShellFolder_fnSetNameOf,
2531
2532         /* ShellFolder2 */
2533         ISF_MyComputer_fnGetDefaultSearchGUID,
2534         ISF_MyComputer_fnEnumSearches,
2535         ISF_MyComputer_fnGetDefaultColumn,
2536         ISF_MyComputer_fnGetDefaultColumnState,
2537         ISF_MyComputer_fnGetDetailsEx,
2538         ISF_MyComputer_fnGetDetailsOf,
2539         ISF_MyComputer_fnMapNameToSCID
2540 };
2541
2542
2543 /************************************************************************
2544  * ISFPersistFolder_QueryInterface (IUnknown)
2545  *
2546  */
2547 static HRESULT WINAPI ISFPersistFolder2_QueryInterface(
2548         IPersistFolder2 *       iface,
2549         REFIID                  iid,
2550         LPVOID*                 ppvObj)
2551 {
2552         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2553
2554         TRACE("(%p)\n", This);
2555
2556         return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
2557 }
2558
2559 /************************************************************************
2560  * ISFPersistFolder_AddRef (IUnknown)
2561  *
2562  */
2563 static ULONG WINAPI ISFPersistFolder2_AddRef(
2564         IPersistFolder2 *       iface)
2565 {
2566         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2567
2568         TRACE("(%p)\n", This);
2569
2570         return IUnknown_AddRef(This->pUnkOuter);
2571 }
2572
2573 /************************************************************************
2574  * ISFPersistFolder_Release (IUnknown)
2575  *
2576  */
2577 static ULONG WINAPI ISFPersistFolder2_Release(
2578         IPersistFolder2 *       iface)
2579 {
2580         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2581
2582         TRACE("(%p)\n", This);
2583
2584         return IUnknown_Release(This->pUnkOuter);
2585 }
2586
2587 /************************************************************************
2588  * ISFPersistFolder_GetClassID (IPersist)
2589  */
2590 static HRESULT WINAPI ISFPersistFolder2_GetClassID(
2591         IPersistFolder2 *       iface,
2592         CLSID *                 lpClassId)
2593 {
2594         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2595
2596         TRACE("(%p)\n", This);
2597
2598         if (!lpClassId) return E_POINTER;
2599         *lpClassId = *This->pclsid;
2600
2601         return S_OK;
2602 }
2603
2604 /************************************************************************
2605  * ISFPersistFolder_Initialize (IPersistFolder)
2606  *
2607  * NOTES
2608  *  sMyPath is not set. Don't know how to handle in a non rooted environment.
2609  */
2610 static HRESULT WINAPI ISFPersistFolder2_Initialize(
2611         IPersistFolder2 *       iface,
2612         LPCITEMIDLIST           pidl)
2613 {
2614         char sTemp[MAX_PATH];
2615         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2616
2617         TRACE("(%p)->(%p)\n", This, pidl);
2618
2619         /* free the old stuff */
2620         if(This->absPidl)
2621         {
2622           SHFree(This->absPidl);
2623           This->absPidl = NULL;
2624         }
2625         if(This->sMyPath)
2626         {
2627           SHFree(This->sMyPath);
2628           This->sMyPath = NULL;
2629         }
2630
2631         /* set my pidl */
2632         This->absPidl = ILClone(pidl);
2633
2634         /* set my path */
2635         if (SHGetPathFromIDListA(pidl, sTemp))
2636         {
2637           This->sMyPath = SHAlloc(strlen(sTemp)+1);
2638           strcpy(This->sMyPath, sTemp);
2639         }
2640
2641         TRACE("--(%p)->(%s)\n", This, This->sMyPath);
2642
2643         return S_OK;
2644 }
2645
2646 /**************************************************************************
2647 *  IPersistFolder2_fnGetCurFolder
2648 */
2649 static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder(
2650         IPersistFolder2 *       iface,
2651         LPITEMIDLIST * pidl)
2652 {
2653         _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2654         
2655         TRACE("(%p)->(%p)\n",This, pidl);
2656
2657         if (!pidl) return E_POINTER;
2658
2659         *pidl = ILClone(This->absPidl);
2660
2661         return S_OK;
2662 }
2663
2664 static ICOM_VTABLE(IPersistFolder2) psfvt = 
2665 {
2666         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2667         ISFPersistFolder2_QueryInterface,
2668         ISFPersistFolder2_AddRef,
2669         ISFPersistFolder2_Release,
2670         ISFPersistFolder2_GetClassID,
2671         ISFPersistFolder2_Initialize,
2672         ISFPersistFolder2_fnGetCurFolder
2673 };
2674
2675 /****************************************************************************
2676  * ISFDropTarget implementation
2677  */
2678 static BOOL ISFDropTarget_QueryDrop(
2679         IDropTarget *iface,
2680         DWORD dwKeyState,
2681         LPDWORD pdwEffect)
2682 {
2683         DWORD dwEffect = *pdwEffect;
2684
2685         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2686         
2687         *pdwEffect = DROPEFFECT_NONE;
2688
2689         if (This->fAcceptFmt)
2690         { /* Does our interpretation of the keystate ... */
2691           *pdwEffect = KeyStateToDropEffect(dwKeyState);
2692           
2693           /* ... matches the desired effect ? */
2694           if (dwEffect & *pdwEffect)
2695           {
2696             return TRUE;
2697           }
2698         }
2699         return FALSE;
2700 }
2701
2702 static HRESULT WINAPI ISFDropTarget_QueryInterface(
2703         IDropTarget *iface,
2704         REFIID riid,
2705         LPVOID *ppvObj)
2706 {
2707         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2708
2709         TRACE("(%p)\n", This);
2710
2711         return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
2712 }
2713
2714 static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
2715 {
2716         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2717
2718         TRACE("(%p)\n", This);
2719
2720         return IUnknown_AddRef(This->pUnkOuter);
2721 }
2722
2723 static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
2724 {
2725         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2726
2727         TRACE("(%p)\n", This);
2728
2729         return IUnknown_Release(This->pUnkOuter);
2730 }
2731
2732 static HRESULT WINAPI ISFDropTarget_DragEnter(
2733         IDropTarget     *iface,
2734         IDataObject     *pDataObject,
2735         DWORD           dwKeyState,
2736         POINTL          pt,
2737         DWORD           *pdwEffect)
2738 {       
2739         FORMATETC       fmt;
2740         
2741         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2742
2743         TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
2744
2745         InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
2746
2747         This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
2748
2749         ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2750
2751         return S_OK;
2752 }
2753
2754 static HRESULT WINAPI ISFDropTarget_DragOver(
2755         IDropTarget     *iface,
2756         DWORD           dwKeyState,
2757         POINTL          pt,
2758         DWORD           *pdwEffect)
2759 {
2760         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2761
2762         TRACE("(%p)\n",This);
2763         
2764         if(!pdwEffect) return E_INVALIDARG;
2765
2766         ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2767
2768         return S_OK;
2769 }
2770
2771 static HRESULT WINAPI ISFDropTarget_DragLeave(
2772         IDropTarget     *iface)
2773 {
2774         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2775
2776         TRACE("(%p)\n",This);
2777
2778         This->fAcceptFmt = FALSE;
2779         
2780         return S_OK;
2781 }
2782
2783 static HRESULT WINAPI ISFDropTarget_Drop(
2784         IDropTarget     *iface,
2785         IDataObject*    pDataObject,
2786         DWORD           dwKeyState,
2787         POINTL          pt,
2788         DWORD           *pdwEffect)
2789 {
2790         _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2791
2792         FIXME("(%p) object dropped\n",This);
2793
2794         return E_NOTIMPL;
2795 }
2796
2797 static struct ICOM_VTABLE(IDropTarget) dtvt = 
2798 {
2799         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2800         ISFDropTarget_QueryInterface,
2801         ISFDropTarget_AddRef,
2802         ISFDropTarget_Release,
2803         ISFDropTarget_DragEnter,
2804         ISFDropTarget_DragOver,
2805         ISFDropTarget_DragLeave,
2806         ISFDropTarget_Drop
2807 };