source: trunk/src/shell32/shlfolder.cpp@ 1570

Last change on this file since 1570 was 1558, checked in by phaller, 26 years ago

Add: update to wine/shell32 1999/11/02 #4

File size: 49.8 KB
Line 
1/* $Id: shlfolder.cpp,v 1.3 1999-11-02 20:38:47 phaller Exp $ */
2/*
3 * Shell Folder stuff
4 *
5 * Copyright 1997 Marcus Meissner
6 * Copyright 1998, 1999 Juergen Schmied
7 *
8 * IShellFolder with IDropTarget, IPersistFolder
9 *
10 */
11
12#include <stdlib.h>
13#include <string.h>
14#include <odin.h>
15
16#define ICOM_CINTERFACE 1
17#define CINTERFACE 1
18
19#include "debugtools.h"
20#include "winerror.h"
21
22#include "oleidl.h"
23#include "shlguid.h"
24
25#include "pidl.h"
26#include "wine/obj_base.h"
27#include "wine/obj_dragdrop.h"
28#include "wine/obj_shellfolder.h"
29#include "wine/undocshell.h"
30#include "shell32_main.h"
31
32#include <heapstring.h>
33#include <misc.h>
34
35DEFAULT_DEBUG_CHANNEL(shell)
36
37#define MEM_DEBUG 1
38
39/***************************************************************************
40 * GetNextElement (internal function)
41 *
42 * gets a part of a string till the first backslash
43 *
44 * PARAMETERS
45 * pszNext [IN] string to get the element from
46 * pszOut [IN] pointer to buffer whitch receives string
47 * dwOut [IN] length of pszOut
48 *
49 * RETURNS
50 * LPSTR pointer to first, not yet parsed char
51 */
52
53static LPCWSTR GetNextElementW(LPCWSTR pszNext,LPWSTR pszOut,DWORD dwOut)
54{ LPCWSTR pszTail = pszNext;
55 DWORD dwCopy;
56 TRACE("(%s %p 0x%08lx)\n",debugstr_w(pszNext),pszOut,dwOut);
57
58 *pszOut=0x0000;
59
60 if(!pszNext || !*pszNext)
61 return NULL;
62
63 while(*pszTail && (*pszTail != (WCHAR)'\\'))
64 pszTail++;
65
66 dwCopy = (WCHAR*)pszTail - (WCHAR*)pszNext + 1;
67 lstrcpynW(pszOut, pszNext, (dwOut<dwCopy)? dwOut : dwCopy);
68
69 if(*pszTail)
70 pszTail++;
71 else
72 pszTail = NULL;
73
74 TRACE("--(%s %s 0x%08lx %p)\n",debugstr_w(pszNext),debugstr_w(pszOut),dwOut,pszTail);
75 return pszTail;
76}
77
78static HRESULT SHELL32_ParseNextElement(
79 HWND hwndOwner,
80 IShellFolder * psf,
81 LPITEMIDLIST * pidlInOut,
82 LPOLESTR szNext,
83 DWORD *pEaten,
84 DWORD *pdwAttributes)
85{
86 HRESULT hr = E_OUTOFMEMORY;
87 LPITEMIDLIST pidlOut, pidlTemp = NULL;
88 IShellFolder *psfChild;
89
90 TRACE("(%p %p %s)\n",psf, pidlInOut? *pidlInOut: NULL, debugstr_w(szNext));
91
92
93 /* get the shellfolder for the child pidl and let it analyse further */
94 hr = IShellFolder_BindToObject(psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
95
96 if (psfChild)
97 {
98 hr = IShellFolder_ParseDisplayName(psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes);
99 IShellFolder_Release(psfChild);
100
101 pidlTemp = ILCombine(*pidlInOut, pidlOut);
102
103 if (pidlOut)
104 ILFree(pidlOut);
105 }
106
107 ILFree(*pidlInOut);
108 *pidlInOut = pidlTemp;
109
110 TRACE("-- pidl=%p ret=0x%08lx\n", pidlInOut? *pidlInOut: NULL, hr);
111 return hr;
112}
113
114/***********************************************************************
115 * SHELL32_CoCreateInitSF
116 *
117 * creates a initialized shell folder
118 */
119static HRESULT SHELL32_CoCreateInitSF (
120 LPITEMIDLIST pidlRoot,
121 LPITEMIDLIST pidlChild,
122 REFCLSID clsid,
123 REFIID iid,
124 LPVOID * ppvOut)
125{
126 HRESULT hr;
127 LPITEMIDLIST absPidl;
128 IShellFolder *pShellFolder;
129 IPersistFolder *pPersistFolder;
130
131 TRACE("%p %p\n", pidlRoot, pidlChild);
132
133 *ppvOut = NULL;
134
135 /* we have to ask first for IPersistFolder, some special folders are expecting this */
136 hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IPersistFolder, (LPVOID*)&pPersistFolder);
137 if (SUCCEEDED(hr))
138 {
139 hr = IPersistFolder_QueryInterface(pPersistFolder, iid, (LPVOID*)&pShellFolder);
140 if (SUCCEEDED(hr))
141 {
142 absPidl = ILCombine (pidlRoot, pidlChild);
143 hr = IPersistFolder_Initialize(pPersistFolder, absPidl);
144 IPersistFolder_Release(pPersistFolder);
145 SHFree(absPidl);
146 *ppvOut = pShellFolder;
147 }
148 }
149
150 TRACE("-- ret=0x%08lx\n", hr);
151 return hr;
152}
153
154static HRESULT SHELL32_GetDisplayNameOfChild(
155 IShellFolder * psf,
156 LPCITEMIDLIST pidl,
157 DWORD dwFlags,
158 LPSTR szOut,
159 DWORD dwOutLen)
160{
161 LPITEMIDLIST pidlFirst, pidlNext;
162 IShellFolder * psfChild;
163 HRESULT hr = E_OUTOFMEMORY;
164 STRRET strTemp;
165
166 TRACE("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n",psf,pidl,dwFlags,szOut, dwOutLen);
167 pdump(pidl);
168
169 if ((pidlFirst = ILCloneFirst(pidl)))
170 {
171 hr = IShellFolder_BindToObject(psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
172 if (SUCCEEDED(hr))
173 {
174 pidlNext = ILGetNext(pidl);
175
176 hr = IShellFolder_GetDisplayNameOf(psfChild, pidlNext, dwFlags | SHGDN_INFOLDER, &strTemp);
177 if (SUCCEEDED(hr))
178 {
179 hr = StrRetToStrNA(szOut, dwOutLen, &strTemp, pidlNext);
180 }
181
182 IShellFolder_Release(psfChild);
183 }
184 ILFree(pidlFirst);
185 }
186
187 TRACE("-- ret=0x%08lx %s\n", hr, szOut);
188
189 return hr;
190}
191
192/***********************************************************************
193* IShellFolder implementation
194*/
195
196typedef struct
197{
198 ICOM_VTABLE(IShellFolder)* lpvtbl;
199 DWORD ref;
200
201 ICOM_VTABLE(IPersistFolder)* lpvtblPersistFolder;
202 ICOM_VTABLE(IDropTarget)* lpvtblDropTarget;
203
204 CLSID* pclsid;
205
206 LPSTR sMyPath;
207 LPITEMIDLIST absPidl; /* complete pidl */
208
209 UINT cfShellIDList; /* clipboardformat for IDropTarget */
210 BOOL fAcceptFmt; /* flag for pending Drop */
211} IGenericSFImpl;
212
213extern struct ICOM_VTABLE(IShellFolder) sfvt;
214extern struct ICOM_VTABLE(IPersistFolder) psfvt;
215extern struct ICOM_VTABLE(IDropTarget) dt2vt;
216
217static IShellFolder * ISF_MyComputer_Constructor(void);
218
219#define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder)))
220#define _ICOM_THIS_From_IPersistFolder(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset);
221
222#define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget)))
223#define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset);
224
225/**************************************************************************
226* registers clipboardformat once
227*/
228static void SF_RegisterClipFmt (IShellFolder * iface)
229{
230 ICOM_THIS(IGenericSFImpl, iface);
231
232 TRACE("(%p)\n", This);
233
234 if (!This->cfShellIDList)
235 {
236 This->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
237 }
238}
239
240/**************************************************************************
241* IShellFolder_Constructor
242*
243*/
244
245static IShellFolder * IShellFolder_Constructor(
246 IShellFolder * psf,
247 LPITEMIDLIST pidl)
248{
249 IGenericSFImpl * sf;
250 IGenericSFImpl * sfParent = (IGenericSFImpl*) psf;
251 DWORD dwSize=0;
252
253 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
254 sf->ref=1;
255
256 sf->lpvtbl=&sfvt;
257 sf->lpvtblPersistFolder=&psfvt;
258 sf->lpvtblDropTarget=&dt2vt;
259 sf->pclsid = (CLSID*)&CLSID_SFFile;
260 sf->cfShellIDList=0;
261 sf->fAcceptFmt=FALSE;
262
263 TRACE("(%p)->(parent=%p, pidl=%p)\n",sf,sfParent, pidl);
264 pdump(pidl);
265
266 if(pidl) /* do we have a pidl? */
267 {
268 int len;
269
270 sf->absPidl = ILCombine(sfParent->absPidl, pidl); /* build a absolute pidl */
271
272 if (!_ILIsSpecialFolder(pidl)) /* only file system paths */
273 {
274 if(sfParent->sMyPath) /* get the size of the parents path */
275 {
276 dwSize += strlen(sfParent->sMyPath) ;
277 TRACE("-- (%p)->(parent's path=%s)\n",sf, debugstr_a(sfParent->sMyPath));
278 }
279
280 dwSize += _ILSimpleGetText(pidl,NULL,0); /* add the size of our name*/
281 sf->sMyPath = (char*)SHAlloc(dwSize + 2); /* '\0' and backslash */
282
283 if(!sf->sMyPath) return NULL;
284 *(sf->sMyPath)=0x00;
285
286 if(sfParent->sMyPath) /* if the parent has a path, get it*/
287 {
288 strcpy(sf->sMyPath, sfParent->sMyPath);
289 PathAddBackslashA (sf->sMyPath);
290 }
291
292 len = strlen(sf->sMyPath);
293 _ILSimpleGetText(pidl, sf->sMyPath + len, dwSize - len + 1);
294 }
295
296 TRACE("-- (%p)->(my pidl=%p, my path=%s)\n",sf, sf->absPidl,debugstr_a(sf->sMyPath));
297
298 pdump (sf->absPidl);
299 }
300
301 shell32_ObjCount++;
302 return (IShellFolder *)sf;
303}
304/**************************************************************************
305 * IShellFolder_fnQueryInterface
306 *
307 * PARAMETERS
308 * REFIID riid [in ] Requested InterfaceID
309 * LPVOID* ppvObject [out] Interface* to hold the result
310 */
311static HRESULT WINAPI IShellFolder_fnQueryInterface(
312 IShellFolder * iface,
313 REFIID riid,
314 LPVOID *ppvObj)
315{
316 ICOM_THIS(IGenericSFImpl, iface);
317
318 char xriid[50];
319 WINE_StringFromCLSID((LPCLSID)riid,xriid);
320 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
321
322 *ppvObj = NULL;
323
324 if(IsEqualIID(riid, &IID_IUnknown))
325 { *ppvObj = This;
326 }
327 else if(IsEqualIID(riid, &IID_IShellFolder))
328 {
329 *ppvObj = (IShellFolder*)This;
330 }
331 else if(IsEqualIID(riid, &IID_IPersist))
332 {
333 *ppvObj = (IPersistFolder*)&(This->lpvtblPersistFolder);
334 }
335 else if(IsEqualIID(riid, &IID_IPersistFolder))
336 {
337 *ppvObj = (IPersistFolder*)&(This->lpvtblPersistFolder);
338 }
339 else if(IsEqualIID(riid, &IID_IDropTarget))
340 {
341 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
342 SF_RegisterClipFmt((IShellFolder*)This);
343 }
344
345 if(*ppvObj)
346 {
347 IUnknown_AddRef((IUnknown*)(*ppvObj));
348 TRACE("-- Interface = %p\n", *ppvObj);
349 return S_OK;
350 }
351 TRACE("-- Interface: E_NOINTERFACE\n");
352 return E_NOINTERFACE;
353}
354
355/**************************************************************************
356* IShellFolder_AddRef
357*/
358
359static ULONG WINAPI IShellFolder_fnAddRef(IShellFolder * iface)
360{
361 ICOM_THIS(IGenericSFImpl, iface);
362
363#ifdef MEM_DEBUG
364 TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 ));
365#endif
366 TRACE("(%p)->(count=%lu)\n",This,This->ref);
367
368 shell32_ObjCount++;
369 return ++(This->ref);
370}
371
372/**************************************************************************
373 * IShellFolder_fnRelease
374 */
375static ULONG WINAPI IShellFolder_fnRelease(IShellFolder * iface)
376{
377 ICOM_THIS(IGenericSFImpl, iface);
378
379#ifdef MEM_DEBUG
380 TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 ));
381#endif
382 TRACE("(%p)->(count=%lu)\n",This,This->ref);
383
384 shell32_ObjCount--;
385 if (!--(This->ref))
386 { TRACE("-- destroying IShellFolder(%p)\n",This);
387
388 if (pdesktopfolder == iface)
389 { pdesktopfolder=NULL;
390 TRACE("-- destroyed IShellFolder(%p) was Desktopfolder\n",This);
391 }
392 if(This->absPidl)
393 { SHFree(This->absPidl);
394 }
395 if(This->sMyPath)
396 { SHFree(This->sMyPath);
397 }
398
399 HeapFree(GetProcessHeap(),0,This);
400
401 return 0;
402 }
403 return This->ref;
404}
405/**************************************************************************
406* IShellFolder_fnParseDisplayName
407* PARAMETERS
408* HWND hwndOwner, //[in ] Parent window for any message's
409* LPBC pbc, //[in ] reserved
410* LPOLESTR lpszDisplayName,//[in ] "Unicode" displayname.
411* ULONG* pchEaten, //[out] (unicode) characters processed
412* LPITEMIDLIST* ppidl, //[out] complex pidl to item
413* ULONG* pdwAttributes //[out] items attributes
414*
415* NOTES
416* every folder trys to parse only it's own (the leftmost) pidl and creates a
417* subfolder to evaluate the remaining parts
418* now we can parse into namespaces implemented by shell extensions
419*
420* behaviour on win98: lpszDisplayName=NULL -> chrash
421* lpszDisplayName="" -> returns mycoputer-pidl
422*
423* FIXME:
424* pdwAttributes: not set
425* pchEaten: not set like in windows
426*/
427static HRESULT WINAPI IShellFolder_fnParseDisplayName(
428 IShellFolder * iface,
429 HWND hwndOwner,
430 LPBC pbcReserved,
431 LPOLESTR lpszDisplayName,
432 DWORD *pchEaten,
433 LPITEMIDLIST *ppidl,
434 DWORD *pdwAttributes)
435{
436 ICOM_THIS(IGenericSFImpl, iface);
437
438 HRESULT hr = E_OUTOFMEMORY;
439 LPCWSTR szNext=NULL;
440 WCHAR szElement[MAX_PATH];
441 CHAR szTempA[MAX_PATH], szPath[MAX_PATH];
442 LPITEMIDLIST pidlTemp=NULL;
443
444 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
445 This,hwndOwner,pbcReserved,lpszDisplayName,
446 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
447
448 if (!lpszDisplayName || !ppidl) return E_INVALIDARG;
449
450 if (pchEaten) *pchEaten = 0; /* strange but like the original */
451
452 if (*lpszDisplayName)
453 {
454 /* get the next element */
455 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
456
457 /* build the full pathname to the element */
458 WideCharToLocal(szTempA, szElement, lstrlenW(szElement) + 1);
459 strcpy(szPath, This->sMyPath);
460 PathAddBackslashA(szPath);
461 strcat(szPath, szTempA);
462
463 /* get the pidl */
464 pidlTemp = SHSimpleIDListFromPathA(szPath);
465
466 if (pidlTemp)
467 {
468 /* try to analyse the next element */
469 if (szNext && *szNext)
470 {
471 hr = SHELL32_ParseNextElement(hwndOwner, (IShellFolder*)This, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
472 }
473 else
474 {
475 hr = S_OK;
476 }
477 }
478 }
479
480 *ppidl = pidlTemp;
481
482 TRACE("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl? *ppidl:0, hr);
483
484 return hr;
485}
486
487/**************************************************************************
488* IShellFolder_fnEnumObjects
489* PARAMETERS
490* HWND hwndOwner, //[in ] Parent Window
491* DWORD grfFlags, //[in ] SHCONTF enumeration mask
492* LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
493*/
494static HRESULT WINAPI IShellFolder_fnEnumObjects(
495 IShellFolder * iface,
496 HWND hwndOwner,
497 DWORD dwFlags,
498 LPENUMIDLIST* ppEnumIDList)
499{
500 ICOM_THIS(IGenericSFImpl, iface);
501
502 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
503
504 *ppEnumIDList = NULL;
505 *ppEnumIDList = IEnumIDList_Constructor (This->sMyPath, dwFlags, EIDL_FILE);
506
507 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
508
509 if(!*ppEnumIDList) return E_OUTOFMEMORY;
510
511 return S_OK;
512}
513
514/**************************************************************************
515* IShellFolder_fnBindToObject
516* PARAMETERS
517* LPCITEMIDLIST pidl, //[in ] relative pidl to open
518* LPBC pbc, //[in ] reserved
519* REFIID riid, //[in ] Initial Interface
520* LPVOID* ppvObject //[out] Interface*
521*/
522static HRESULT WINAPI IShellFolder_fnBindToObject( IShellFolder * iface, LPCITEMIDLIST pidl,
523 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
524{
525 ICOM_THIS(IGenericSFImpl, iface);
526 GUID const * iid;
527 char xriid[50];
528 IShellFolder *pShellFolder, *pSubFolder;
529 IPersistFolder *pPersistFolder;
530 LPITEMIDLIST absPidl;
531
532 WINE_StringFromCLSID(riid,xriid);
533
534 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,xriid,ppvOut);
535
536 if(!pidl || !ppvOut) return E_INVALIDARG;
537
538 *ppvOut = NULL;
539
540 if ((iid=_ILGetGUIDPointer(pidl)))
541 {
542 /* we have to create a alien folder */
543 if ( SUCCEEDED(SHCoCreateInstance(NULL, iid, NULL, riid, (LPVOID*)&pShellFolder))
544 && SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder)))
545 {
546 absPidl = ILCombine (This->absPidl, pidl);
547 IPersistFolder_Initialize(pPersistFolder, absPidl);
548 IPersistFolder_Release(pPersistFolder);
549 SHFree(absPidl);
550 }
551 else
552 {
553 return E_FAIL;
554 }
555 }
556 else
557 {
558 LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
559 pShellFolder = IShellFolder_Constructor((IShellFolder*)This, pidltemp);
560 ILFree(pidltemp);
561 }
562
563 if (_ILIsPidlSimple(pidl))
564 {
565 *ppvOut = pShellFolder;
566 }
567 else
568 {
569 IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID*)&pSubFolder);
570 IShellFolder_Release(pShellFolder);
571 *ppvOut = pSubFolder;
572 }
573
574 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
575
576 return S_OK;
577}
578
579/**************************************************************************
580* IShellFolder_fnBindToStorage
581* PARAMETERS
582* LPCITEMIDLIST pidl, //[in ] complex pidl to store
583* LPBC pbc, //[in ] reserved
584* REFIID riid, //[in ] Initial storage interface
585* LPVOID* ppvObject //[out] Interface* returned
586*/
587static HRESULT WINAPI IShellFolder_fnBindToStorage(
588 IShellFolder * iface,
589 LPCITEMIDLIST pidl,
590 LPBC pbcReserved,
591 REFIID riid,
592 LPVOID *ppvOut)
593{
594 ICOM_THIS(IGenericSFImpl, iface);
595
596 char xriid[50];
597 WINE_StringFromCLSID(riid,xriid);
598
599 FIXME("(%p)->(pidl=%p,%p,\n\tIID:%s,%p) stub\n",This,pidl,pbcReserved,xriid,ppvOut);
600
601 *ppvOut = NULL;
602 return E_NOTIMPL;
603}
604
605/**************************************************************************
606* IShellFolder_fnCompareIDs
607*
608* PARMETERS
609* LPARAM lParam, //[in ] Column?
610* LPCITEMIDLIST pidl1, //[in ] simple pidl
611* LPCITEMIDLIST pidl2) //[in ] simple pidl
612*
613* NOTES
614* Special case - If one of the items is a Path and the other is a File,
615* always make the Path come before the File.
616*
617* NOTES
618* use SCODE_CODE() on the return value to get the result
619*/
620
621static HRESULT WINAPI IShellFolder_fnCompareIDs(
622 IShellFolder * iface,
623 LPARAM lParam,
624 LPCITEMIDLIST pidl1,
625 LPCITEMIDLIST pidl2)
626{
627 ICOM_THIS(IGenericSFImpl, iface);
628
629 CHAR szTemp1[MAX_PATH];
630 CHAR szTemp2[MAX_PATH];
631 int nReturn;
632 IShellFolder * psf;
633 HRESULT hr = E_OUTOFMEMORY;
634 LPCITEMIDLIST pidlTemp;
635 PIDLTYPE pt1, pt2;
636
637 TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
638 pdump (pidl1);
639 pdump (pidl2);
640
641 if (!pidl1 && !pidl2)
642 {
643 hr = ResultFromShort(0);
644 }
645 else if (!pidl1)
646 {
647 hr = ResultFromShort(-1);
648 }
649 else if (!pidl2)
650 {
651 hr = ResultFromShort(1);
652 }
653 else
654 {
655 LPPIDLDATA pd1, pd2;
656 pd1 = _ILGetDataPointer(pidl1);
657 pd2 = _ILGetDataPointer(pidl2);
658
659 /* compate the types. sort order is the PT_* constant */
660 pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
661 pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
662
663 if (pt1 != pt2)
664 {
665 hr = ResultFromShort(pt1-pt2);
666 }
667 else /* same type of pidl */
668 {
669 _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
670 _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
671 nReturn = strcmp(szTemp1, szTemp2);
672
673 if (nReturn == 0) /* first pidl different ? */
674 {
675 pidl1 = ILGetNext(pidl1);
676
677 if (pidl1 && pidl1->mkid.cb) /* go deeper? */
678 {
679 pidlTemp = ILCloneFirst(pidl1);
680 pidl2 = ILGetNext(pidl2);
681
682 hr = IShellFolder_BindToObject((IShellFolder*)This, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
683 if (SUCCEEDED(hr))
684 {
685 nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
686 IShellFolder_Release(psf);
687 hr = ResultFromShort(nReturn);
688 }
689 ILFree(pidlTemp);
690 }
691 else
692 {
693 hr = ResultFromShort(nReturn); /* two equal simple pidls */
694 }
695 }
696 else
697 {
698 hr = ResultFromShort(nReturn); /* two different simple pidls */
699 }
700 }
701 }
702
703 TRACE("-- res=0x%08lx\n", hr);
704 return hr;
705}
706
707/**************************************************************************
708* IShellFolder_fnCreateViewObject
709*/
710static HRESULT WINAPI IShellFolder_fnCreateViewObject( IShellFolder * iface,
711 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
712{
713 ICOM_THIS(IGenericSFImpl, iface);
714
715 LPSHELLVIEW pShellView;
716 char xriid[50];
717 HRESULT hr = E_INVALIDARG;
718
719 WINE_StringFromCLSID(riid,xriid);
720 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,xriid,ppvOut);
721
722 if(ppvOut)
723 {
724 *ppvOut = NULL;
725
726 if(IsEqualIID(riid, &IID_IDropTarget))
727 {
728 hr = IShellFolder_QueryInterface((IShellFolder*)This, &IID_IDropTarget, ppvOut);
729 }
730 else if(IsEqualIID(riid, &IID_IContextMenu))
731 {
732 FIXME("IContextMenu not implemented\n");
733 hr = E_NOTIMPL;
734 }
735 else if(IsEqualIID(riid, &IID_IShellView))
736 {
737 pShellView = IShellView_Constructor((IShellFolder *) This);
738 if(pShellView)
739 {
740 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
741 IShellView_Release(pShellView);
742 }
743 }
744 }
745 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
746 return hr;
747}
748
749/**************************************************************************
750* IShellFolder_fnGetAttributesOf
751*
752* PARAMETERS
753* UINT cidl, //[in ] num elements in pidl array
754* LPCITEMIDLIST* apidl, //[in ] simple pidl array
755* ULONG* rgfInOut) //[out] result array
756*
757*/
758static HRESULT WINAPI IShellFolder_fnGetAttributesOf(IShellFolder * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut)
759{
760 ICOM_THIS(IGenericSFImpl, iface);
761
762 HRESULT hr = S_OK;
763
764 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
765
766 if ( (!cidl) || (!apidl) || (!rgfInOut))
767 return E_INVALIDARG;
768
769 while (cidl > 0 && *apidl)
770 {
771 pdump (*apidl);
772 if (_ILIsFolder( *apidl))
773 {
774 *rgfInOut &= 0xe0000177;
775 goto next;
776 }
777 else if (_ILIsValue( *apidl))
778 {
779 *rgfInOut &= 0x40000177;
780 goto next;
781 }
782 hr = E_INVALIDARG;
783
784next: apidl++;
785 cidl--;
786 }
787
788 TRACE("-- result=0x%08lx\n",*rgfInOut);
789
790 return hr;
791}
792/**************************************************************************
793* IShellFolder_fnGetUIObjectOf
794*
795* PARAMETERS
796* HWND hwndOwner, //[in ] Parent window for any output
797* UINT cidl, //[in ] array size
798* LPCITEMIDLIST* apidl, //[in ] simple pidl array
799* REFIID riid, //[in ] Requested Interface
800* UINT* prgfInOut, //[ ] reserved
801* LPVOID* ppvObject) //[out] Resulting Interface
802*
803* NOTES
804* This function gets asked to return "view objects" for one or more (multiple select)
805* items:
806* The viewobject typically is an COM object with one of the following interfaces:
807* IExtractIcon,IDataObject,IContextMenu
808* In order to support icon positions in the default Listview your DataObject
809* must implement the SetData method (in addition to GetData :) - the shell passes
810* a barely documented "Icon positions" structure to SetData when the drag starts,
811* and GetData's it if the drop is in another explorer window that needs the positions.
812*/
813static HRESULT WINAPI IShellFolder_fnGetUIObjectOf(
814 IShellFolder * iface,
815 HWND hwndOwner,
816 UINT cidl,
817 LPCITEMIDLIST * apidl,
818 REFIID riid,
819 UINT * prgfInOut,
820 LPVOID * ppvOut)
821{
822 ICOM_THIS(IGenericSFImpl, iface);
823
824 char xclsid[50];
825 LPITEMIDLIST pidl;
826 IUnknown* pObj = NULL;
827 HRESULT hr = E_INVALIDARG;
828
829 WINE_StringFromCLSID(riid,xclsid);
830
831 TRACE("(%p)->(%u,%u,apidl=%p,\n\tIID:%s,%p,%p)\n",
832 This,hwndOwner,cidl,apidl,xclsid,prgfInOut,ppvOut);
833
834 if (ppvOut)
835 {
836 *ppvOut = NULL;
837
838 if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
839 {
840 pObj = (LPUNKNOWN)IContextMenu_Constructor((IShellFolder *)This, This->absPidl, apidl, cidl);
841 hr = S_OK;
842 }
843 else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
844 {
845 pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
846 hr = S_OK;
847 }
848 else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
849 {
850 pidl = ILCombine(This->absPidl,apidl[0]);
851 pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
852 SHFree(pidl);
853 hr = S_OK;
854 }
855 else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
856 {
857 hr = IShellFolder_QueryInterface((IShellFolder*)This, &IID_IDropTarget, (LPVOID*)&pObj);
858 }
859 else
860 {
861 hr = E_NOINTERFACE;
862 }
863
864 if(!pObj)
865 hr = E_OUTOFMEMORY;
866
867 *ppvOut = pObj;
868 }
869 TRACE("(%p)->hr=0x%08lx\n",This, hr);
870 return hr;
871}
872
873/**************************************************************************
874* IShellFolder_fnGetDisplayNameOf
875* Retrieves the display name for the specified file object or subfolder
876*
877* PARAMETERS
878* LPCITEMIDLIST pidl, //[in ] complex pidl to item
879* DWORD dwFlags, //[in ] SHGNO formatting flags
880* LPSTRRET lpName) //[out] Returned display name
881*
882* FIXME
883* if the name is in the pidl the ret value should be a STRRET_OFFSET
884*/
885#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
886#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
887
888static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
889 IShellFolder * iface,
890 LPCITEMIDLIST pidl,
891 DWORD dwFlags,
892 LPSTRRET strRet)
893{
894 ICOM_THIS(IGenericSFImpl, iface);
895
896 CHAR szPath[MAX_PATH]= "";
897 int len = 0;
898 BOOL bSimplePidl;
899
900 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
901 pdump(pidl);
902
903 if(!pidl || !strRet) return E_INVALIDARG;
904
905 bSimplePidl = _ILIsPidlSimple(pidl);
906
907 /* take names of special folders only if its only this folder */
908 if (_ILIsSpecialFolder(pidl))
909 {
910 if ( bSimplePidl)
911 {
912 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
913 }
914 }
915 else
916 {
917 if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
918 {
919 strcpy (szPath, This->sMyPath); /* get path to root*/
920 PathAddBackslashA(szPath);
921 len = strlen(szPath);
922 }
923 _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
924 }
925
926 if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl) /* go deeper if needed */
927 {
928 PathAddBackslashA(szPath);
929 len = strlen(szPath);
930
931 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild((IShellFolder*)This, pidl, dwFlags, szPath + len, MAX_PATH - len)))
932 return E_OUTOFMEMORY;
933 }
934 strRet->uType = STRRET_CSTRA;
935 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
936
937 TRACE("-- (%p)->(%s)\n", This, szPath);
938 return S_OK;
939}
940
941/**************************************************************************
942* IShellFolder_fnSetNameOf
943* Changes the name of a file object or subfolder, possibly changing its item
944* identifier in the process.
945*
946* PARAMETERS
947* HWND hwndOwner, //[in ] Owner window for output
948* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
949* LPCOLESTR lpszName, //[in ] the items new display name
950* DWORD dwFlags, //[in ] SHGNO formatting flags
951* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
952*/
953static HRESULT WINAPI IShellFolder_fnSetNameOf(
954 IShellFolder * iface,
955 HWND hwndOwner,
956 LPCITEMIDLIST pidl, /*simple pidl*/
957 LPCOLESTR lpName,
958 DWORD dw,
959 LPITEMIDLIST *pPidlOut)
960{
961 ICOM_THIS(IGenericSFImpl, iface);
962
963 FIXME("(%p)->(%u,pidl=%p,%s,%lu,%p),stub!\n",
964 This,hwndOwner,pidl,debugstr_w(lpName),dw,pPidlOut);
965
966 return E_NOTIMPL;
967}
968
969/**************************************************************************
970* IShellFolder_fnGetFolderPath
971*/
972static HRESULT WINAPI IShellFolder_fnGetFolderPath(IShellFolder * iface, LPSTR lpszOut, DWORD dwOutSize)
973{
974 ICOM_THIS(IGenericSFImpl, iface);
975
976 TRACE("(%p)->(%p %lu)\n",This, lpszOut, dwOutSize);
977
978 if (!lpszOut) return FALSE;
979
980 *lpszOut=0;
981
982 if (! This->sMyPath) return FALSE;
983
984 lstrcpynA(lpszOut, This->sMyPath, dwOutSize);
985
986 TRACE("-- (%p)->(return=%s)\n",This, lpszOut);
987 return TRUE;
988}
989
990ICOM_VTABLE(IShellFolder) sfvt =
991{
992 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
993 IShellFolder_fnQueryInterface,
994 IShellFolder_fnAddRef,
995 IShellFolder_fnRelease,
996 IShellFolder_fnParseDisplayName,
997 IShellFolder_fnEnumObjects,
998 IShellFolder_fnBindToObject,
999 IShellFolder_fnBindToStorage,
1000 IShellFolder_fnCompareIDs,
1001 IShellFolder_fnCreateViewObject,
1002 IShellFolder_fnGetAttributesOf,
1003 IShellFolder_fnGetUIObjectOf,
1004 IShellFolder_fnGetDisplayNameOf,
1005 IShellFolder_fnSetNameOf,
1006 IShellFolder_fnGetFolderPath
1007};
1008
1009/***********************************************************************
1010* [Desktopfolder] IShellFolder implementation
1011*/
1012extern struct ICOM_VTABLE(IShellFolder) sfdvt;
1013
1014/**************************************************************************
1015* ISF_Desktop_Constructor
1016*
1017*/
1018IShellFolder * ISF_Desktop_Constructor()
1019{
1020 IGenericSFImpl * sf;
1021
1022 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1023 sf->ref=1;
1024 sf->lpvtbl=&sfdvt;
1025 sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1026
1027 TRACE("(%p)\n",sf);
1028
1029 shell32_ObjCount++;
1030 return (IShellFolder *)sf;
1031}
1032
1033/**************************************************************************
1034 * ISF_Desktop_fnQueryInterface
1035 *
1036 * NOTES supports not IPersist/IPersistFolder
1037 */
1038static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1039 IShellFolder * iface,
1040 REFIID riid,
1041 LPVOID *ppvObj)
1042{
1043 ICOM_THIS(IGenericSFImpl, iface);
1044
1045 char xriid[50];
1046 WINE_StringFromCLSID((LPCLSID)riid,xriid);
1047 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
1048
1049 *ppvObj = NULL;
1050
1051 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
1052 { *ppvObj = This;
1053 }
1054 else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
1055 { *ppvObj = (IShellFolder*)This;
1056 }
1057
1058 if(*ppvObj)
1059 {
1060 IUnknown_AddRef((IUnknown*)(*ppvObj));
1061 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1062 return S_OK;
1063 }
1064 TRACE("-- Interface: E_NOINTERFACE\n");
1065 return E_NOINTERFACE;
1066}
1067
1068/**************************************************************************
1069* ISF_Desktop_fnParseDisplayName
1070*
1071* NOTES
1072* "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1073* to MyComputer
1074*/
1075static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1076 IShellFolder * iface,
1077 HWND hwndOwner,
1078 LPBC pbcReserved,
1079 LPOLESTR lpszDisplayName,
1080 DWORD *pchEaten,
1081 LPITEMIDLIST *ppidl,
1082 DWORD *pdwAttributes)
1083{
1084 ICOM_THIS(IGenericSFImpl, iface);
1085
1086 LPCWSTR szNext=NULL;
1087 LPITEMIDLIST pidlTemp=NULL;
1088 HRESULT hr=E_OUTOFMEMORY;
1089
1090 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1091 This,hwndOwner,pbcReserved,lpszDisplayName,
1092 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1093
1094 *ppidl = 0;
1095 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1096
1097 /* fixme no real parsing implemented */
1098 pidlTemp = _ILCreateMyComputer();
1099 szNext = lpszDisplayName;
1100
1101 if (szNext && *szNext)
1102 {
1103 hr = SHELL32_ParseNextElement(hwndOwner, (IShellFolder*)This, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1104 }
1105 else
1106 {
1107 hr = S_OK;
1108 }
1109
1110 *ppidl = pidlTemp;
1111
1112 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1113
1114 return hr;
1115}
1116
1117/**************************************************************************
1118* ISF_Desktop_fnEnumObjects
1119*/
1120static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1121 IShellFolder * iface,
1122 HWND hwndOwner,
1123 DWORD dwFlags,
1124 LPENUMIDLIST* ppEnumIDList)
1125{
1126 ICOM_THIS(IGenericSFImpl, iface);
1127
1128 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1129
1130 *ppEnumIDList = NULL;
1131 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1132
1133 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1134
1135 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1136
1137 return S_OK;
1138}
1139
1140/**************************************************************************
1141* ISF_Desktop_fnBindToObject
1142*/
1143static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder * iface, LPCITEMIDLIST pidl,
1144 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1145{
1146 ICOM_THIS(IGenericSFImpl, iface);
1147 GUID const * clsid;
1148 char xriid[50];
1149 IShellFolder *pShellFolder, *pSubFolder;
1150
1151 WINE_StringFromCLSID(riid,xriid);
1152
1153 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,xriid,ppvOut);
1154
1155 *ppvOut = NULL;
1156
1157 if ((clsid=_ILGetGUIDPointer(pidl)))
1158 {
1159 if ( IsEqualIID(clsid, &IID_MyComputer))
1160 {
1161 pShellFolder = ISF_MyComputer_Constructor();
1162 }
1163 else
1164 {
1165 /* shell extension */
1166 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1167 {
1168 return E_INVALIDARG;
1169 }
1170 }
1171 }
1172 else
1173 {
1174 /* file system folder on the desktop */
1175 LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
1176 pShellFolder = IShellFolder_Constructor((IShellFolder*)This, pidltemp);
1177 ILFree(pidltemp);
1178 }
1179
1180 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1181 {
1182 *ppvOut = pShellFolder;
1183 }
1184 else /* go deeper */
1185 {
1186 IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID*)&pSubFolder);
1187 IShellFolder_Release(pShellFolder);
1188 *ppvOut = pSubFolder;
1189 }
1190
1191 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1192
1193 return S_OK;
1194}
1195
1196/**************************************************************************
1197* ISF_Desktop_fnCreateViewObject
1198*/
1199static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder * iface,
1200 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1201{
1202 ICOM_THIS(IGenericSFImpl, iface);
1203
1204 LPSHELLVIEW pShellView;
1205 char xriid[50];
1206 HRESULT hr = E_INVALIDARG;
1207
1208 WINE_StringFromCLSID(riid,xriid);
1209 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,xriid,ppvOut);
1210
1211 if(ppvOut)
1212 {
1213 *ppvOut = NULL;
1214
1215 if(IsEqualIID(riid, &IID_IDropTarget))
1216 {
1217 FIXME("IDropTarget not implemented\n");
1218 hr = E_NOTIMPL;
1219 }
1220 else if(IsEqualIID(riid, &IID_IContextMenu))
1221 {
1222 FIXME("IContextMenu not implemented\n");
1223 hr = E_NOTIMPL;
1224 }
1225 else if(IsEqualIID(riid, &IID_IShellView))
1226 {
1227 pShellView = IShellView_Constructor((IShellFolder *) This);
1228 if(pShellView)
1229 {
1230 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1231 IShellView_Release(pShellView);
1232 }
1233 }
1234 }
1235 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1236 return hr;
1237}
1238
1239/**************************************************************************
1240* ISF_Desktop_fnGetAttributesOf
1241*/
1242static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(IShellFolder * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut)
1243{
1244 ICOM_THIS(IGenericSFImpl, iface);
1245
1246 GUID const * clsid;
1247 DWORD attributes;
1248 HRESULT hr = S_OK;
1249
1250 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1251
1252 if ( (!cidl) || (!apidl) || (!rgfInOut))
1253 return E_INVALIDARG;
1254
1255 while (cidl > 0 && *apidl)
1256 {
1257 pdump (*apidl);
1258
1259 if ((clsid=_ILGetGUIDPointer(*apidl)))
1260 {
1261 if (IsEqualIID(clsid, &IID_MyComputer))
1262 {
1263 *rgfInOut &= 0xb0000154;
1264 goto next;
1265 }
1266 else if (HCR_GetFolderAttributes(clsid, &attributes))
1267 {
1268 *rgfInOut &= attributes;
1269 goto next;
1270 }
1271 else
1272 { /* some shell-extension */
1273 *rgfInOut &= 0xb0000154;
1274 }
1275 }
1276 else if (_ILIsFolder( *apidl))
1277 {
1278 *rgfInOut &= 0xe0000177;
1279 goto next;
1280 }
1281 else if (_ILIsValue( *apidl))
1282 {
1283 *rgfInOut &= 0x40000177;
1284 goto next;
1285 }
1286 hr = E_INVALIDARG;
1287
1288next: apidl++;
1289 cidl--;
1290 }
1291
1292 TRACE("-- result=0x%08lx\n",*rgfInOut);
1293
1294 return hr;
1295}
1296
1297/**************************************************************************
1298* ISF_Desktop_fnGetDisplayNameOf
1299*
1300* NOTES
1301* special case: pidl = null gives desktop-name back
1302*/
1303static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1304 IShellFolder * iface,
1305 LPCITEMIDLIST pidl,
1306 DWORD dwFlags,
1307 LPSTRRET strRet)
1308{
1309 ICOM_THIS(IGenericSFImpl, iface);
1310
1311 CHAR szPath[MAX_PATH]= "";
1312
1313 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1314 pdump(pidl);
1315
1316 if(!strRet) return E_INVALIDARG;
1317
1318 if(!pidl)
1319 {
1320 HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1321 }
1322 else if ( _ILIsPidlSimple(pidl) )
1323 {
1324 _ILSimpleGetText(pidl, szPath, MAX_PATH);
1325 }
1326 else
1327 {
1328 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild((IShellFolder*)This, pidl, dwFlags, szPath, MAX_PATH)))
1329 return E_OUTOFMEMORY;
1330 }
1331 strRet->uType = STRRET_CSTRA;
1332 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1333
1334
1335 TRACE("-- (%p)->(%s)\n", This, szPath);
1336 return S_OK;
1337}
1338
1339ICOM_VTABLE(IShellFolder) sfdvt =
1340{
1341 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1342 ISF_Desktop_fnQueryInterface,
1343 IShellFolder_fnAddRef,
1344 IShellFolder_fnRelease,
1345 ISF_Desktop_fnParseDisplayName,
1346 ISF_Desktop_fnEnumObjects,
1347 ISF_Desktop_fnBindToObject,
1348 IShellFolder_fnBindToStorage,
1349 IShellFolder_fnCompareIDs,
1350 ISF_Desktop_fnCreateViewObject,
1351 ISF_Desktop_fnGetAttributesOf,
1352 IShellFolder_fnGetUIObjectOf,
1353 ISF_Desktop_fnGetDisplayNameOf,
1354 IShellFolder_fnSetNameOf,
1355 IShellFolder_fnGetFolderPath
1356};
1357
1358
1359/***********************************************************************
1360* IShellFolder [MyComputer] implementation
1361*/
1362
1363extern struct ICOM_VTABLE(IShellFolder) sfmcvt;
1364
1365/**************************************************************************
1366* ISF_MyComputer_Constructor
1367*/
1368static IShellFolder * ISF_MyComputer_Constructor(void)
1369{
1370 IGenericSFImpl * sf;
1371
1372 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1373 sf->ref=1;
1374
1375 sf->lpvtbl = &sfmcvt;
1376 sf->lpvtblPersistFolder = &psfvt;
1377 sf->pclsid = (CLSID*)&CLSID_SFMyComp;
1378 sf->absPidl=_ILCreateMyComputer(); /* my qualified pidl */
1379
1380 TRACE("(%p)\n",sf);
1381
1382 shell32_ObjCount++;
1383 return (IShellFolder *)sf;
1384}
1385
1386/**************************************************************************
1387* ISF_MyComputer_fnParseDisplayName
1388*/
1389static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
1390 IShellFolder * iface,
1391 HWND hwndOwner,
1392 LPBC pbcReserved,
1393 LPOLESTR lpszDisplayName,
1394 DWORD *pchEaten,
1395 LPITEMIDLIST *ppidl,
1396 DWORD *pdwAttributes)
1397{
1398 ICOM_THIS(IGenericSFImpl, iface);
1399
1400 HRESULT hr = E_OUTOFMEMORY;
1401 LPCWSTR szNext=NULL;
1402 WCHAR szElement[MAX_PATH];
1403 CHAR szTempA[MAX_PATH];
1404 LPITEMIDLIST pidlTemp;
1405
1406 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1407 This,hwndOwner,pbcReserved,lpszDisplayName,
1408 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1409
1410 *ppidl = 0;
1411 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1412
1413 if (PathIsRootW(lpszDisplayName))
1414 {
1415 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
1416 WideCharToLocal(szTempA, szElement, lstrlenW(szElement) + 1);
1417 pidlTemp = _ILCreateDrive(szTempA);
1418
1419 if (szNext && *szNext)
1420 {
1421 hr = SHELL32_ParseNextElement(hwndOwner, (IShellFolder*)This, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1422 }
1423 else
1424 {
1425 hr = S_OK;
1426 }
1427 *ppidl = pidlTemp;
1428 }
1429
1430 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1431
1432 return hr;
1433}
1434
1435/**************************************************************************
1436* ISF_MyComputer_fnEnumObjects
1437*/
1438static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
1439 IShellFolder * iface,
1440 HWND hwndOwner,
1441 DWORD dwFlags,
1442 LPENUMIDLIST* ppEnumIDList)
1443{
1444 ICOM_THIS(IGenericSFImpl, iface);
1445
1446 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1447
1448 *ppEnumIDList = NULL;
1449 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
1450
1451 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1452
1453 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1454
1455 return S_OK;
1456}
1457
1458/**************************************************************************
1459* ISF_MyComputer_fnBindToObject
1460*/
1461static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder * iface, LPCITEMIDLIST pidl,
1462 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1463{
1464 ICOM_THIS(IGenericSFImpl, iface);
1465 GUID const * clsid;
1466 char xriid[50];
1467 IShellFolder *pShellFolder, *pSubFolder;
1468 LPITEMIDLIST pidltemp;
1469
1470 WINE_StringFromCLSID(riid,xriid);
1471
1472 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,xriid,ppvOut);
1473
1474 if(!pidl || !ppvOut) return E_INVALIDARG;
1475
1476 *ppvOut = NULL;
1477
1478 if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &IID_MyComputer))
1479 {
1480 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1481 {
1482 return E_FAIL;
1483 }
1484 }
1485 else
1486 {
1487 if (!_ILIsDrive(pidl)) return E_INVALIDARG;
1488
1489 pidltemp = ILCloneFirst(pidl);
1490 pShellFolder = IShellFolder_Constructor((IShellFolder*)This, pidltemp);
1491 ILFree(pidltemp);
1492 }
1493
1494 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1495 {
1496 *ppvOut = pShellFolder;
1497 }
1498 else /* go deeper */
1499 {
1500 IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID*)&pSubFolder);
1501 IShellFolder_Release(pShellFolder);
1502 *ppvOut = pSubFolder;
1503 }
1504
1505 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1506
1507 return S_OK;
1508}
1509
1510/**************************************************************************
1511* ISF_MyComputer_fnCreateViewObject
1512*/
1513static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder * iface,
1514 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1515{
1516 ICOM_THIS(IGenericSFImpl, iface);
1517
1518 LPSHELLVIEW pShellView;
1519 char xriid[50];
1520 HRESULT hr = E_INVALIDARG;
1521
1522 WINE_StringFromCLSID(riid,xriid);
1523 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,xriid,ppvOut);
1524
1525 if(ppvOut)
1526 {
1527 *ppvOut = NULL;
1528
1529 if(IsEqualIID(riid, &IID_IDropTarget))
1530 {
1531 FIXME("IDropTarget not implemented\n");
1532 hr = E_NOTIMPL;
1533 }
1534 else if(IsEqualIID(riid, &IID_IContextMenu))
1535 {
1536 FIXME("IContextMenu not implemented\n");
1537 hr = E_NOTIMPL;
1538 }
1539 else if(IsEqualIID(riid, &IID_IShellView))
1540 {
1541 pShellView = IShellView_Constructor((IShellFolder *) This);
1542 if(pShellView)
1543 {
1544 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1545 IShellView_Release(pShellView);
1546 }
1547 }
1548 }
1549 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1550 return hr;
1551}
1552
1553/**************************************************************************
1554* ISF_MyComputer_fnGetAttributesOf
1555*/
1556static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(IShellFolder * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut)
1557{
1558 ICOM_THIS(IGenericSFImpl, iface);
1559
1560 GUID const * clsid;
1561 DWORD attributes;
1562 HRESULT hr = S_OK;
1563
1564 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
1565
1566 if ( (!cidl) || (!apidl) || (!rgfInOut))
1567 return E_INVALIDARG;
1568
1569 *rgfInOut = 0xffffffff;
1570
1571 while (cidl > 0 && *apidl)
1572 {
1573 pdump (*apidl);
1574
1575 if (_ILIsDrive(*apidl))
1576 {
1577 *rgfInOut &= 0xf0000144;
1578 goto next;
1579 }
1580 else if ((clsid=_ILGetGUIDPointer(*apidl)))
1581 {
1582 if (HCR_GetFolderAttributes(clsid, &attributes))
1583 {
1584 *rgfInOut &= attributes;
1585 goto next;
1586 }
1587 }
1588 hr = E_INVALIDARG;
1589
1590next: apidl++;
1591 cidl--;
1592 }
1593
1594 TRACE("-- result=0x%08lx\n",*rgfInOut);
1595 return hr;
1596}
1597
1598/**************************************************************************
1599* ISF_MyComputer_fnGetDisplayNameOf
1600*
1601* NOTES
1602* The desktopfolder creates only complete paths (SHGDN_FORPARSING).
1603* SHGDN_INFOLDER makes no sense.
1604*/
1605static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
1606 IShellFolder * iface,
1607 LPCITEMIDLIST pidl,
1608 DWORD dwFlags,
1609 LPSTRRET strRet)
1610{
1611 ICOM_THIS(IGenericSFImpl, iface);
1612
1613 char szPath[MAX_PATH], szDrive[18];
1614 int len = 0;
1615 BOOL bSimplePidl;
1616
1617 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1618 pdump(pidl);
1619
1620 if(!strRet) return E_INVALIDARG;
1621
1622 szPath[0]=0x00; szDrive[0]=0x00;
1623
1624
1625 bSimplePidl = _ILIsPidlSimple(pidl);
1626
1627 if (_ILIsSpecialFolder(pidl))
1628 {
1629 /* take names of special folders only if its only this folder */
1630 if ( bSimplePidl )
1631 {
1632 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1633 }
1634 }
1635 else
1636 {
1637 if (!_ILIsDrive(pidl))
1638 {
1639 ERR("Wrong pidl type\n");
1640 return E_INVALIDARG;
1641 }
1642
1643 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1644
1645 /* long view "lw_name (C:)" */
1646 if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
1647 {
1648 DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
1649
1650 GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
1651 strcat (szDrive," (");
1652 strncat (szDrive, szPath, 2);
1653 strcat (szDrive,")");
1654 strcpy (szPath, szDrive);
1655 }
1656 }
1657
1658 if (!bSimplePidl) /* go deeper if needed */
1659 {
1660 PathAddBackslashA(szPath);
1661 len = strlen(szPath);
1662
1663 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild((IShellFolder*)This, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
1664 return E_OUTOFMEMORY;
1665 }
1666 strRet->uType = STRRET_CSTRA;
1667 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1668
1669
1670 TRACE("-- (%p)->(%s)\n", This, szPath);
1671 return S_OK;
1672}
1673
1674ICOM_VTABLE(IShellFolder) sfmcvt =
1675{
1676 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1677 IShellFolder_fnQueryInterface,
1678 IShellFolder_fnAddRef,
1679 IShellFolder_fnRelease,
1680 ISF_MyComputer_fnParseDisplayName,
1681 ISF_MyComputer_fnEnumObjects,
1682 ISF_MyComputer_fnBindToObject,
1683 IShellFolder_fnBindToStorage,
1684 IShellFolder_fnCompareIDs,
1685 ISF_MyComputer_fnCreateViewObject,
1686 ISF_MyComputer_fnGetAttributesOf,
1687 IShellFolder_fnGetUIObjectOf,
1688 ISF_MyComputer_fnGetDisplayNameOf,
1689 IShellFolder_fnSetNameOf,
1690 IShellFolder_fnGetFolderPath
1691};
1692
1693
1694/************************************************************************
1695 * ISFPersistFolder_QueryInterface (IUnknown)
1696 *
1697 */
1698static HRESULT WINAPI ISFPersistFolder_QueryInterface(
1699 IPersistFolder * iface,
1700 REFIID iid,
1701 LPVOID* ppvObj)
1702{
1703 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1704
1705 TRACE("(%p)\n", This);
1706
1707 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
1708}
1709
1710/************************************************************************
1711 * ISFPersistFolder_AddRef (IUnknown)
1712 *
1713 */
1714static ULONG WINAPI ISFPersistFolder_AddRef(
1715 IPersistFolder * iface)
1716{
1717 _ICOM_THIS_From_IPersistFolder(IShellFolder, iface);
1718
1719 TRACE("(%p)\n", This);
1720
1721 return IShellFolder_AddRef((IShellFolder*)This);
1722}
1723
1724/************************************************************************
1725 * ISFPersistFolder_Release (IUnknown)
1726 *
1727 */
1728static ULONG WINAPI ISFPersistFolder_Release(
1729 IPersistFolder * iface)
1730{
1731 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1732
1733 TRACE("(%p)\n", This);
1734
1735 return IShellFolder_Release((IShellFolder*)This);
1736}
1737
1738/************************************************************************
1739 * ISFPersistFolder_GetClassID (IPersist)
1740 */
1741static HRESULT WINAPI ISFPersistFolder_GetClassID(
1742 IPersistFolder * iface,
1743 CLSID * lpClassId)
1744{
1745 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1746
1747 TRACE("(%p)\n", This);
1748
1749 if (!lpClassId) return E_POINTER;
1750 *lpClassId = *This->pclsid;
1751
1752 return S_OK;
1753}
1754
1755/************************************************************************
1756 * ISFPersistFolder_Initialize (IPersistFolder)
1757 *
1758 * NOTES
1759 * sMyPath is not set. Don't know how to handle in a non rooted environment.
1760 */
1761static HRESULT WINAPI ISFPersistFolder_Initialize(
1762 IPersistFolder * iface,
1763 LPCITEMIDLIST pidl)
1764{
1765 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1766
1767 TRACE("(%p)\n", This);
1768
1769 if(This->absPidl)
1770 {
1771 SHFree(This->absPidl);
1772 This->absPidl = NULL;
1773 }
1774 This->absPidl = ILClone(pidl);
1775 return S_OK;
1776}
1777
1778ICOM_VTABLE(IPersistFolder) psfvt =
1779{
1780 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1781 ISFPersistFolder_QueryInterface,
1782 ISFPersistFolder_AddRef,
1783 ISFPersistFolder_Release,
1784 ISFPersistFolder_GetClassID,
1785 ISFPersistFolder_Initialize
1786};
1787
1788/****************************************************************************
1789 * ISFDropTarget implementation
1790 */
1791static BOOL ISFDropTarget_QueryDrop(
1792 IDropTarget *iface,
1793 DWORD dwKeyState,
1794 LPDWORD pdwEffect)
1795{
1796 DWORD dwEffect = *pdwEffect;
1797
1798 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1799
1800 *pdwEffect = DROPEFFECT_NONE;
1801
1802 if (This->fAcceptFmt)
1803 { /* Does our interpretation of the keystate ... */
1804 *pdwEffect = KeyStateToDropEffect(dwKeyState);
1805
1806 /* ... matches the desired effect ? */
1807 if (dwEffect & *pdwEffect)
1808 {
1809 return TRUE;
1810 }
1811 }
1812 return FALSE;
1813}
1814
1815static HRESULT WINAPI ISFDropTarget_QueryInterface(
1816 IDropTarget *iface,
1817 REFIID riid,
1818 LPVOID *ppvObj)
1819{
1820 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1821
1822 TRACE("(%p)\n", This);
1823
1824 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
1825}
1826
1827static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
1828{
1829 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1830
1831 TRACE("(%p)\n", This);
1832
1833 return IShellFolder_AddRef((IShellFolder*)This);
1834}
1835
1836static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
1837{
1838 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1839
1840 TRACE("(%p)\n", This);
1841
1842 return IShellFolder_Release((IShellFolder*)This);
1843}
1844
1845static HRESULT WINAPI ISFDropTarget_DragEnter(
1846 IDropTarget *iface,
1847 IDataObject *pDataObject,
1848 DWORD dwKeyState,
1849 POINTL pt,
1850 DWORD *pdwEffect)
1851{
1852 FORMATETC fmt;
1853
1854 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1855
1856 TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
1857
1858 InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
1859
1860 This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
1861
1862 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
1863
1864 return S_OK;
1865}
1866
1867static HRESULT WINAPI ISFDropTarget_DragOver(
1868 IDropTarget *iface,
1869 DWORD dwKeyState,
1870 POINTL pt,
1871 DWORD *pdwEffect)
1872{
1873 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1874
1875 TRACE("(%p)\n",This);
1876
1877 if(!pdwEffect) return E_INVALIDARG;
1878
1879 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
1880
1881 return S_OK;
1882}
1883
1884static HRESULT WINAPI ISFDropTarget_DragLeave(
1885 IDropTarget *iface)
1886{
1887 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1888
1889 TRACE("(%p)\n",This);
1890
1891 This->fAcceptFmt = FALSE;
1892
1893 return S_OK;
1894}
1895
1896static HRESULT WINAPI ISFDropTarget_Drop(
1897 IDropTarget *iface,
1898 IDataObject* pDataObject,
1899 DWORD dwKeyState,
1900 POINTL pt,
1901 DWORD *pdwEffect)
1902{
1903 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1904
1905 FIXME("(%p) object dropped\n",This);
1906
1907 return E_NOTIMPL;
1908}
1909
1910struct ICOM_VTABLE(IDropTarget) dt2vt =
1911{
1912 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1913 ISFDropTarget_QueryInterface,
1914 ISFDropTarget_AddRef,
1915 ISFDropTarget_Release,
1916 ISFDropTarget_DragEnter,
1917 ISFDropTarget_DragOver,
1918 ISFDropTarget_DragLeave,
1919 ISFDropTarget_Drop
1920};
1921
Note: See TracBrowser for help on using the repository browser.