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

Last change on this file since 1036 was 918, checked in by phaller, 26 years ago

Fix: updated to current wine 19990913

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) dt2vt;
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=&dt2vt;
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 hr = S_OK;
837 }
838 else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
839 {
840 pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
841 hr = S_OK;
842 }
843 else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
844 {
845 pidl = ILCombine(This->absPidl,apidl[0]);
846 pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
847 SHFree(pidl);
848 hr = S_OK;
849 }
850 else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
851 {
852 hr = IShellFolder_QueryInterface((IShellFolder*)This, &IID_IDropTarget, (LPVOID*)&pObj);
853 }
854 else
855 {
856 hr = E_NOINTERFACE;
857 }
858
859 if(!pObj)
860 hr = E_OUTOFMEMORY;
861
862 *ppvOut = pObj;
863 }
864 TRACE("(%p)->hr=0x%08lx\n",This, hr);
865 return hr;
866}
867
868/**************************************************************************
869* IShellFolder_fnGetDisplayNameOf
870* Retrieves the display name for the specified file object or subfolder
871*
872* PARAMETERS
873* LPCITEMIDLIST pidl, //[in ] complex pidl to item
874* DWORD dwFlags, //[in ] SHGNO formatting flags
875* LPSTRRET lpName) //[out] Returned display name
876*
877* FIXME
878* if the name is in the pidl the ret value should be a STRRET_OFFSET
879*/
880#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
881#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
882
883static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
884 IShellFolder * iface,
885 LPCITEMIDLIST pidl,
886 DWORD dwFlags,
887 LPSTRRET strRet)
888{
889 ICOM_THIS(IGenericSFImpl, iface);
890
891 CHAR szPath[MAX_PATH]= "";
892 int len = 0;
893 BOOL bSimplePidl;
894
895 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
896 pdump(pidl);
897
898 if(!pidl || !strRet) return E_INVALIDARG;
899
900 bSimplePidl = _ILIsPidlSimple(pidl);
901
902 /* take names of special folders only if its only this folder */
903 if (_ILIsSpecialFolder(pidl))
904 {
905 if ( bSimplePidl)
906 {
907 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
908 }
909 }
910 else
911 {
912 if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
913 {
914 strcpy (szPath, This->sMyPath); /* get path to root*/
915 PathAddBackslashA(szPath);
916 len = strlen(szPath);
917 }
918 _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
919 }
920
921 if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl) /* go deeper if needed */
922 {
923 PathAddBackslashA(szPath);
924 len = strlen(szPath);
925
926 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild((IShellFolder*)This, pidl, dwFlags, szPath + len, MAX_PATH - len)))
927 return E_OUTOFMEMORY;
928 }
929 strRet->uType = STRRET_CSTRA;
930 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
931
932 TRACE("-- (%p)->(%s)\n", This, szPath);
933 return S_OK;
934}
935
936/**************************************************************************
937* IShellFolder_fnSetNameOf
938* Changes the name of a file object or subfolder, possibly changing its item
939* identifier in the process.
940*
941* PARAMETERS
942* HWND hwndOwner, //[in ] Owner window for output
943* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
944* LPCOLESTR lpszName, //[in ] the items new display name
945* DWORD dwFlags, //[in ] SHGNO formatting flags
946* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
947*/
948static HRESULT WINAPI IShellFolder_fnSetNameOf(
949 IShellFolder * iface,
950 HWND hwndOwner,
951 LPCITEMIDLIST pidl, /*simple pidl*/
952 LPCOLESTR lpName,
953 DWORD dw,
954 LPITEMIDLIST *pPidlOut)
955{
956 ICOM_THIS(IGenericSFImpl, iface);
957
958 FIXME("(%p)->(%u,pidl=%p,%s,%lu,%p),stub!\n",
959 This,hwndOwner,pidl,debugstr_w(lpName),dw,pPidlOut);
960
961 return E_NOTIMPL;
962}
963
964/**************************************************************************
965* IShellFolder_fnGetFolderPath
966*/
967static HRESULT WINAPI IShellFolder_fnGetFolderPath(IShellFolder * iface, LPSTR lpszOut, DWORD dwOutSize)
968{
969 ICOM_THIS(IGenericSFImpl, iface);
970
971 TRACE("(%p)->(%p %lu)\n",This, lpszOut, dwOutSize);
972
973 if (!lpszOut) return FALSE;
974
975 *lpszOut=0;
976
977 if (! This->sMyPath) return FALSE;
978
979 lstrcpynA(lpszOut, This->sMyPath, dwOutSize);
980
981 TRACE("-- (%p)->(return=%s)\n",This, lpszOut);
982 return TRUE;
983}
984
985ICOM_VTABLE(IShellFolder) sfvt =
986{
987 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
988 IShellFolder_fnQueryInterface,
989 IShellFolder_fnAddRef,
990 IShellFolder_fnRelease,
991 IShellFolder_fnParseDisplayName,
992 IShellFolder_fnEnumObjects,
993 IShellFolder_fnBindToObject,
994 IShellFolder_fnBindToStorage,
995 IShellFolder_fnCompareIDs,
996 IShellFolder_fnCreateViewObject,
997 IShellFolder_fnGetAttributesOf,
998 IShellFolder_fnGetUIObjectOf,
999 IShellFolder_fnGetDisplayNameOf,
1000 IShellFolder_fnSetNameOf,
1001 IShellFolder_fnGetFolderPath
1002};
1003
1004/***********************************************************************
1005* [Desktopfolder] IShellFolder implementation
1006*/
1007extern struct ICOM_VTABLE(IShellFolder) sfdvt;
1008
1009/**************************************************************************
1010* ISF_Desktop_Constructor
1011*
1012*/
1013IShellFolder * ISF_Desktop_Constructor()
1014{
1015 IGenericSFImpl * sf;
1016
1017 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1018 sf->ref=1;
1019 sf->lpvtbl=&sfdvt;
1020 sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1021
1022 TRACE("(%p)\n",sf);
1023
1024 shell32_ObjCount++;
1025 return (IShellFolder *)sf;
1026}
1027
1028/**************************************************************************
1029 * ISF_Desktop_fnQueryInterface
1030 *
1031 * NOTES supports not IPersist/IPersistFolder
1032 */
1033static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1034 IShellFolder * iface,
1035 REFIID riid,
1036 LPVOID *ppvObj)
1037{
1038 ICOM_THIS(IGenericSFImpl, iface);
1039
1040 char xriid[50];
1041 WINE_StringFromCLSID((LPCLSID)riid,xriid);
1042 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
1043
1044 *ppvObj = NULL;
1045
1046 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
1047 { *ppvObj = This;
1048 }
1049 else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
1050 { *ppvObj = (IShellFolder*)This;
1051 }
1052
1053 if(*ppvObj)
1054 {
1055 IUnknown_AddRef((IUnknown*)(*ppvObj));
1056 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1057 return S_OK;
1058 }
1059 TRACE("-- Interface: E_NOINTERFACE\n");
1060 return E_NOINTERFACE;
1061}
1062
1063/**************************************************************************
1064* ISF_Desktop_fnParseDisplayName
1065*
1066* NOTES
1067* "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1068* to MyComputer
1069*/
1070static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1071 IShellFolder * iface,
1072 HWND hwndOwner,
1073 LPBC pbcReserved,
1074 LPOLESTR lpszDisplayName,
1075 DWORD *pchEaten,
1076 LPITEMIDLIST *ppidl,
1077 DWORD *pdwAttributes)
1078{
1079 ICOM_THIS(IGenericSFImpl, iface);
1080
1081 LPCWSTR szNext=NULL;
1082 LPITEMIDLIST pidlTemp=NULL;
1083 HRESULT hr=E_OUTOFMEMORY;
1084
1085 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1086 This,hwndOwner,pbcReserved,lpszDisplayName,
1087 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1088
1089 *ppidl = 0;
1090 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1091
1092 /* fixme no real parsing implemented */
1093 pidlTemp = _ILCreateMyComputer();
1094 szNext = lpszDisplayName;
1095
1096 if (szNext && *szNext)
1097 {
1098 hr = SHELL32_ParseNextElement(hwndOwner, (IShellFolder*)This, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1099 }
1100 else
1101 {
1102 hr = S_OK;
1103 }
1104
1105 *ppidl = pidlTemp;
1106
1107 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1108
1109 return hr;
1110}
1111
1112/**************************************************************************
1113* ISF_Desktop_fnEnumObjects
1114*/
1115static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1116 IShellFolder * iface,
1117 HWND hwndOwner,
1118 DWORD dwFlags,
1119 LPENUMIDLIST* ppEnumIDList)
1120{
1121 ICOM_THIS(IGenericSFImpl, iface);
1122
1123 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1124
1125 *ppEnumIDList = NULL;
1126 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1127
1128 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1129
1130 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1131
1132 return S_OK;
1133}
1134
1135/**************************************************************************
1136* ISF_Desktop_fnBindToObject
1137*/
1138static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder * iface, LPCITEMIDLIST pidl,
1139 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1140{
1141 ICOM_THIS(IGenericSFImpl, iface);
1142 GUID const * clsid;
1143 char xriid[50];
1144 IShellFolder *pShellFolder, *pSubFolder;
1145
1146 WINE_StringFromCLSID(riid,xriid);
1147
1148 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,xriid,ppvOut);
1149
1150 *ppvOut = NULL;
1151
1152 if ((clsid=_ILGetGUIDPointer(pidl)))
1153 {
1154 if ( IsEqualIID(clsid, &IID_MyComputer))
1155 {
1156 pShellFolder = ISF_MyComputer_Constructor();
1157 }
1158 else
1159 {
1160 /* shell extension */
1161 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1162 {
1163 return E_INVALIDARG;
1164 }
1165 }
1166 }
1167 else
1168 {
1169 /* file system folder on the desktop */
1170 LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
1171 pShellFolder = IShellFolder_Constructor((IShellFolder*)This, pidltemp);
1172 ILFree(pidltemp);
1173 }
1174
1175 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1176 {
1177 *ppvOut = pShellFolder;
1178 }
1179 else /* go deeper */
1180 {
1181 IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID*)&pSubFolder);
1182 IShellFolder_Release(pShellFolder);
1183 *ppvOut = pSubFolder;
1184 }
1185
1186 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1187
1188 return S_OK;
1189}
1190
1191/**************************************************************************
1192* ISF_Desktop_fnCreateViewObject
1193*/
1194static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder * iface,
1195 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1196{
1197 ICOM_THIS(IGenericSFImpl, iface);
1198
1199 LPSHELLVIEW pShellView;
1200 char xriid[50];
1201 HRESULT hr = E_INVALIDARG;
1202
1203 WINE_StringFromCLSID(riid,xriid);
1204 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,xriid,ppvOut);
1205
1206 if(ppvOut)
1207 {
1208 *ppvOut = NULL;
1209
1210 if(IsEqualIID(riid, &IID_IDropTarget))
1211 {
1212 FIXME("IDropTarget not implemented\n");
1213 hr = E_NOTIMPL;
1214 }
1215 else if(IsEqualIID(riid, &IID_IContextMenu))
1216 {
1217 FIXME("IContextMenu not implemented\n");
1218 hr = E_NOTIMPL;
1219 }
1220 else if(IsEqualIID(riid, &IID_IShellView))
1221 {
1222 pShellView = IShellView_Constructor((IShellFolder *) This);
1223 if(pShellView)
1224 {
1225 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1226 IShellView_Release(pShellView);
1227 }
1228 }
1229 }
1230 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1231 return hr;
1232}
1233
1234/**************************************************************************
1235* ISF_Desktop_fnGetAttributesOf
1236*/
1237static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(IShellFolder * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut)
1238{
1239 ICOM_THIS(IGenericSFImpl, iface);
1240
1241 GUID const * clsid;
1242 DWORD attributes;
1243 HRESULT hr = S_OK;
1244
1245 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1246
1247 if ( (!cidl) || (!apidl) || (!rgfInOut))
1248 return E_INVALIDARG;
1249
1250 while (cidl > 0 && *apidl)
1251 {
1252 pdump (*apidl);
1253
1254 if ((clsid=_ILGetGUIDPointer(*apidl)))
1255 {
1256 if (IsEqualIID(clsid, &IID_MyComputer))
1257 {
1258 *rgfInOut &= 0xb0000154;
1259 goto next;
1260 }
1261 else if (HCR_GetFolderAttributes(clsid, &attributes))
1262 {
1263 *rgfInOut &= attributes;
1264 goto next;
1265 }
1266 else
1267 { /* some shell-extension */
1268 *rgfInOut &= 0xb0000154;
1269 }
1270 }
1271 else if (_ILIsFolder( *apidl))
1272 {
1273 *rgfInOut &= 0xe0000177;
1274 goto next;
1275 }
1276 else if (_ILIsValue( *apidl))
1277 {
1278 *rgfInOut &= 0x40000177;
1279 goto next;
1280 }
1281 hr = E_INVALIDARG;
1282
1283next: apidl++;
1284 cidl--;
1285 }
1286
1287 TRACE("-- result=0x%08lx\n",*rgfInOut);
1288
1289 return hr;
1290}
1291
1292/**************************************************************************
1293* ISF_Desktop_fnGetDisplayNameOf
1294*
1295* NOTES
1296* special case: pidl = null gives desktop-name back
1297*/
1298static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1299 IShellFolder * iface,
1300 LPCITEMIDLIST pidl,
1301 DWORD dwFlags,
1302 LPSTRRET strRet)
1303{
1304 ICOM_THIS(IGenericSFImpl, iface);
1305
1306 CHAR szPath[MAX_PATH]= "";
1307
1308 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1309 pdump(pidl);
1310
1311 if(!strRet) return E_INVALIDARG;
1312
1313 if(!pidl)
1314 {
1315 HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1316 }
1317 else if ( _ILIsPidlSimple(pidl) )
1318 {
1319 _ILSimpleGetText(pidl, szPath, MAX_PATH);
1320 }
1321 else
1322 {
1323 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild((IShellFolder*)This, pidl, dwFlags, szPath, MAX_PATH)))
1324 return E_OUTOFMEMORY;
1325 }
1326 strRet->uType = STRRET_CSTRA;
1327 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1328
1329
1330 TRACE("-- (%p)->(%s)\n", This, szPath);
1331 return S_OK;
1332}
1333
1334ICOM_VTABLE(IShellFolder) sfdvt =
1335{
1336 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1337 ISF_Desktop_fnQueryInterface,
1338 IShellFolder_fnAddRef,
1339 IShellFolder_fnRelease,
1340 ISF_Desktop_fnParseDisplayName,
1341 ISF_Desktop_fnEnumObjects,
1342 ISF_Desktop_fnBindToObject,
1343 IShellFolder_fnBindToStorage,
1344 IShellFolder_fnCompareIDs,
1345 ISF_Desktop_fnCreateViewObject,
1346 ISF_Desktop_fnGetAttributesOf,
1347 IShellFolder_fnGetUIObjectOf,
1348 ISF_Desktop_fnGetDisplayNameOf,
1349 IShellFolder_fnSetNameOf,
1350 IShellFolder_fnGetFolderPath
1351};
1352
1353
1354/***********************************************************************
1355* IShellFolder [MyComputer] implementation
1356*/
1357
1358extern struct ICOM_VTABLE(IShellFolder) sfmcvt;
1359
1360/**************************************************************************
1361* ISF_MyComputer_Constructor
1362*/
1363static IShellFolder * ISF_MyComputer_Constructor(void)
1364{
1365 IGenericSFImpl * sf;
1366
1367 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1368 sf->ref=1;
1369
1370 sf->lpvtbl = &sfmcvt;
1371 sf->lpvtblPersistFolder = &psfvt;
1372 sf->pclsid = (CLSID*)&CLSID_SFMyComp;
1373 sf->absPidl=_ILCreateMyComputer(); /* my qualified pidl */
1374
1375 TRACE("(%p)\n",sf);
1376
1377 shell32_ObjCount++;
1378 return (IShellFolder *)sf;
1379}
1380
1381/**************************************************************************
1382* ISF_MyComputer_fnParseDisplayName
1383*/
1384static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
1385 IShellFolder * iface,
1386 HWND hwndOwner,
1387 LPBC pbcReserved,
1388 LPOLESTR lpszDisplayName,
1389 DWORD *pchEaten,
1390 LPITEMIDLIST *ppidl,
1391 DWORD *pdwAttributes)
1392{
1393 ICOM_THIS(IGenericSFImpl, iface);
1394
1395 HRESULT hr = E_OUTOFMEMORY;
1396 LPCWSTR szNext=NULL;
1397 WCHAR szElement[MAX_PATH];
1398 CHAR szTempA[MAX_PATH];
1399 LPITEMIDLIST pidlTemp;
1400
1401 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1402 This,hwndOwner,pbcReserved,lpszDisplayName,
1403 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1404
1405 *ppidl = 0;
1406 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1407
1408 if (PathIsRootW(lpszDisplayName))
1409 {
1410 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
1411 WideCharToLocal(szTempA, szElement, lstrlenW(szElement) + 1);
1412 pidlTemp = _ILCreateDrive(szTempA);
1413
1414 if (szNext && *szNext)
1415 {
1416 hr = SHELL32_ParseNextElement(hwndOwner, (IShellFolder*)This, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1417 }
1418 else
1419 {
1420 hr = S_OK;
1421 }
1422 *ppidl = pidlTemp;
1423 }
1424
1425 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1426
1427 return hr;
1428}
1429
1430/**************************************************************************
1431* ISF_MyComputer_fnEnumObjects
1432*/
1433static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
1434 IShellFolder * iface,
1435 HWND hwndOwner,
1436 DWORD dwFlags,
1437 LPENUMIDLIST* ppEnumIDList)
1438{
1439 ICOM_THIS(IGenericSFImpl, iface);
1440
1441 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1442
1443 *ppEnumIDList = NULL;
1444 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
1445
1446 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1447
1448 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1449
1450 return S_OK;
1451}
1452
1453/**************************************************************************
1454* ISF_MyComputer_fnBindToObject
1455*/
1456static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder * iface, LPCITEMIDLIST pidl,
1457 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1458{
1459 ICOM_THIS(IGenericSFImpl, iface);
1460 GUID const * clsid;
1461 char xriid[50];
1462 IShellFolder *pShellFolder, *pSubFolder;
1463 LPITEMIDLIST pidltemp;
1464
1465 WINE_StringFromCLSID(riid,xriid);
1466
1467 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,xriid,ppvOut);
1468
1469 *ppvOut = NULL;
1470
1471 if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &IID_MyComputer))
1472 {
1473 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1474 {
1475 return E_FAIL;
1476 }
1477 }
1478 else
1479 {
1480 if (!_ILIsDrive(pidl)) return E_INVALIDARG;
1481
1482 pidltemp = ILCloneFirst(pidl);
1483 pShellFolder = IShellFolder_Constructor((IShellFolder*)This, pidltemp);
1484 ILFree(pidltemp);
1485 }
1486
1487 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1488 {
1489 *ppvOut = pShellFolder;
1490 }
1491 else /* go deeper */
1492 {
1493 IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID*)&pSubFolder);
1494 IShellFolder_Release(pShellFolder);
1495 *ppvOut = pSubFolder;
1496 }
1497
1498 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1499
1500 return S_OK;
1501}
1502
1503/**************************************************************************
1504* ISF_MyComputer_fnCreateViewObject
1505*/
1506static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder * iface,
1507 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1508{
1509 ICOM_THIS(IGenericSFImpl, iface);
1510
1511 LPSHELLVIEW pShellView;
1512 char xriid[50];
1513 HRESULT hr = E_INVALIDARG;
1514
1515 WINE_StringFromCLSID(riid,xriid);
1516 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,xriid,ppvOut);
1517
1518 if(ppvOut)
1519 {
1520 *ppvOut = NULL;
1521
1522 if(IsEqualIID(riid, &IID_IDropTarget))
1523 {
1524 FIXME("IDropTarget not implemented\n");
1525 hr = E_NOTIMPL;
1526 }
1527 else if(IsEqualIID(riid, &IID_IContextMenu))
1528 {
1529 FIXME("IContextMenu not implemented\n");
1530 hr = E_NOTIMPL;
1531 }
1532 else if(IsEqualIID(riid, &IID_IShellView))
1533 {
1534 pShellView = IShellView_Constructor((IShellFolder *) This);
1535 if(pShellView)
1536 {
1537 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1538 IShellView_Release(pShellView);
1539 }
1540 }
1541 }
1542 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1543 return hr;
1544}
1545
1546/**************************************************************************
1547* ISF_MyComputer_fnGetAttributesOf
1548*/
1549static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(IShellFolder * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut)
1550{
1551 ICOM_THIS(IGenericSFImpl, iface);
1552
1553 GUID const * clsid;
1554 DWORD attributes;
1555 HRESULT hr = S_OK;
1556
1557 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
1558
1559 if ( (!cidl) || (!apidl) || (!rgfInOut))
1560 return E_INVALIDARG;
1561
1562 *rgfInOut = 0xffffffff;
1563
1564 while (cidl > 0 && *apidl)
1565 {
1566 pdump (*apidl);
1567
1568 if (_ILIsDrive(*apidl))
1569 {
1570 *rgfInOut &= 0xf0000144;
1571 goto next;
1572 }
1573 else if ((clsid=_ILGetGUIDPointer(*apidl)))
1574 {
1575 if (HCR_GetFolderAttributes(clsid, &attributes))
1576 {
1577 *rgfInOut &= attributes;
1578 goto next;
1579 }
1580 }
1581 hr = E_INVALIDARG;
1582
1583next: apidl++;
1584 cidl--;
1585 }
1586
1587 TRACE("-- result=0x%08lx\n",*rgfInOut);
1588 return hr;
1589}
1590
1591/**************************************************************************
1592* ISF_MyComputer_fnGetDisplayNameOf
1593*
1594* NOTES
1595* The desktopfolder creates only complete paths (SHGDN_FORPARSING).
1596* SHGDN_INFOLDER makes no sense.
1597*/
1598static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
1599 IShellFolder * iface,
1600 LPCITEMIDLIST pidl,
1601 DWORD dwFlags,
1602 LPSTRRET strRet)
1603{
1604 ICOM_THIS(IGenericSFImpl, iface);
1605
1606 char szPath[MAX_PATH], szDrive[18];
1607 int len = 0;
1608 BOOL bSimplePidl;
1609
1610 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1611 pdump(pidl);
1612
1613 if(!strRet) return E_INVALIDARG;
1614
1615 szPath[0]=0x00; szDrive[0]=0x00;
1616
1617
1618 bSimplePidl = _ILIsPidlSimple(pidl);
1619
1620 if (_ILIsSpecialFolder(pidl))
1621 {
1622 /* take names of special folders only if its only this folder */
1623 if ( bSimplePidl )
1624 {
1625 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1626 }
1627 }
1628 else
1629 {
1630 if (!_ILIsDrive(pidl))
1631 {
1632 ERR("Wrong pidl type\n");
1633 return E_INVALIDARG;
1634 }
1635
1636 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1637
1638 /* long view "lw_name (C:)" */
1639 if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
1640 {
1641 DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
1642
1643 GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
1644 strcat (szDrive," (");
1645 strncat (szDrive, szPath, 2);
1646 strcat (szDrive,")");
1647 strcpy (szPath, szDrive);
1648 }
1649 }
1650
1651 if (!bSimplePidl) /* go deeper if needed */
1652 {
1653 PathAddBackslashA(szPath);
1654 len = strlen(szPath);
1655
1656 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild((IShellFolder*)This, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
1657 return E_OUTOFMEMORY;
1658 }
1659 strRet->uType = STRRET_CSTRA;
1660 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1661
1662
1663 TRACE("-- (%p)->(%s)\n", This, szPath);
1664 return S_OK;
1665}
1666
1667ICOM_VTABLE(IShellFolder) sfmcvt =
1668{
1669 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1670 IShellFolder_fnQueryInterface,
1671 IShellFolder_fnAddRef,
1672 IShellFolder_fnRelease,
1673 ISF_MyComputer_fnParseDisplayName,
1674 ISF_MyComputer_fnEnumObjects,
1675 ISF_MyComputer_fnBindToObject,
1676 IShellFolder_fnBindToStorage,
1677 IShellFolder_fnCompareIDs,
1678 ISF_MyComputer_fnCreateViewObject,
1679 ISF_MyComputer_fnGetAttributesOf,
1680 IShellFolder_fnGetUIObjectOf,
1681 ISF_MyComputer_fnGetDisplayNameOf,
1682 IShellFolder_fnSetNameOf,
1683 IShellFolder_fnGetFolderPath
1684};
1685
1686
1687/************************************************************************
1688 * ISFPersistFolder_QueryInterface (IUnknown)
1689 *
1690 */
1691static HRESULT WINAPI ISFPersistFolder_QueryInterface(
1692 IPersistFolder * iface,
1693 REFIID iid,
1694 LPVOID* ppvObj)
1695{
1696 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1697
1698 TRACE("(%p)\n", This);
1699
1700 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
1701}
1702
1703/************************************************************************
1704 * ISFPersistFolder_AddRef (IUnknown)
1705 *
1706 */
1707static ULONG WINAPI ISFPersistFolder_AddRef(
1708 IPersistFolder * iface)
1709{
1710 _ICOM_THIS_From_IPersistFolder(IShellFolder, iface);
1711
1712 TRACE("(%p)\n", This);
1713
1714 return IShellFolder_AddRef((IShellFolder*)This);
1715}
1716
1717/************************************************************************
1718 * ISFPersistFolder_Release (IUnknown)
1719 *
1720 */
1721static ULONG WINAPI ISFPersistFolder_Release(
1722 IPersistFolder * iface)
1723{
1724 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1725
1726 TRACE("(%p)\n", This);
1727
1728 return IShellFolder_Release((IShellFolder*)This);
1729}
1730
1731/************************************************************************
1732 * ISFPersistFolder_GetClassID (IPersist)
1733 */
1734static HRESULT WINAPI ISFPersistFolder_GetClassID(
1735 IPersistFolder * iface,
1736 CLSID * lpClassId)
1737{
1738 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1739
1740 TRACE("(%p)\n", This);
1741
1742 if (!lpClassId) return E_POINTER;
1743 *lpClassId = *This->pclsid;
1744
1745 return S_OK;
1746}
1747
1748/************************************************************************
1749 * ISFPersistFolder_Initialize (IPersistFolder)
1750 *
1751 * NOTES
1752 * sMyPath is not set. Don't know how to handle in a non rooted environment.
1753 */
1754static HRESULT WINAPI ISFPersistFolder_Initialize(
1755 IPersistFolder * iface,
1756 LPCITEMIDLIST pidl)
1757{
1758 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1759
1760 TRACE("(%p)\n", This);
1761
1762 if(This->absPidl)
1763 {
1764 SHFree(This->absPidl);
1765 This->absPidl = NULL;
1766 }
1767 This->absPidl = ILClone(pidl);
1768 return S_OK;
1769}
1770
1771ICOM_VTABLE(IPersistFolder) psfvt =
1772{
1773 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1774 ISFPersistFolder_QueryInterface,
1775 ISFPersistFolder_AddRef,
1776 ISFPersistFolder_Release,
1777 ISFPersistFolder_GetClassID,
1778 ISFPersistFolder_Initialize
1779};
1780
1781/****************************************************************************
1782 * ISFDropTarget implementation
1783 */
1784static BOOL ISFDropTarget_QueryDrop(
1785 IDropTarget *iface,
1786 DWORD dwKeyState,
1787 LPDWORD pdwEffect)
1788{
1789 DWORD dwEffect = *pdwEffect;
1790
1791 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1792
1793 *pdwEffect = DROPEFFECT_NONE;
1794
1795 if (This->fAcceptFmt)
1796 { /* Does our interpretation of the keystate ... */
1797 *pdwEffect = KeyStateToDropEffect(dwKeyState);
1798
1799 /* ... matches the desired effect ? */
1800 if (dwEffect & *pdwEffect)
1801 {
1802 return TRUE;
1803 }
1804 }
1805 return FALSE;
1806}
1807
1808static HRESULT WINAPI ISFDropTarget_QueryInterface(
1809 IDropTarget *iface,
1810 REFIID riid,
1811 LPVOID *ppvObj)
1812{
1813 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1814
1815 TRACE("(%p)\n", This);
1816
1817 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
1818}
1819
1820static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
1821{
1822 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1823
1824 TRACE("(%p)\n", This);
1825
1826 return IShellFolder_AddRef((IShellFolder*)This);
1827}
1828
1829static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
1830{
1831 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1832
1833 TRACE("(%p)\n", This);
1834
1835 return IShellFolder_Release((IShellFolder*)This);
1836}
1837
1838static HRESULT WINAPI ISFDropTarget_DragEnter(
1839 IDropTarget *iface,
1840 IDataObject *pDataObject,
1841 DWORD dwKeyState,
1842 POINTL pt,
1843 DWORD *pdwEffect)
1844{
1845 FORMATETC fmt;
1846
1847 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1848
1849 TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
1850
1851 InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
1852
1853 This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
1854
1855 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
1856
1857 return S_OK;
1858}
1859
1860static HRESULT WINAPI ISFDropTarget_DragOver(
1861 IDropTarget *iface,
1862 DWORD dwKeyState,
1863 POINTL pt,
1864 DWORD *pdwEffect)
1865{
1866 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1867
1868 TRACE("(%p)\n",This);
1869
1870 if(!pdwEffect) return E_INVALIDARG;
1871
1872 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
1873
1874 return S_OK;
1875}
1876
1877static HRESULT WINAPI ISFDropTarget_DragLeave(
1878 IDropTarget *iface)
1879{
1880 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1881
1882 TRACE("(%p)\n",This);
1883
1884 This->fAcceptFmt = FALSE;
1885
1886 return S_OK;
1887}
1888
1889static HRESULT WINAPI ISFDropTarget_Drop(
1890 IDropTarget *iface,
1891 IDataObject* pDataObject,
1892 DWORD dwKeyState,
1893 POINTL pt,
1894 DWORD *pdwEffect)
1895{
1896 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
1897
1898 FIXME("(%p) object dropped\n",This);
1899
1900 return E_NOTIMPL;
1901}
1902
1903struct ICOM_VTABLE(IDropTarget) dt2vt =
1904{
1905 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1906 ISFDropTarget_QueryInterface,
1907 ISFDropTarget_AddRef,
1908 ISFDropTarget_Release,
1909 ISFDropTarget_DragEnter,
1910 ISFDropTarget_DragOver,
1911 ISFDropTarget_DragLeave,
1912 ISFDropTarget_Drop
1913};
1914
Note: See TracBrowser for help on using the repository browser.