source: trunk/src/shell32/new/shlfolder.cpp@ 815

Last change on this file since 815 was 815, checked in by achimha, 26 years ago

shell32/new compilation fixes

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