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

Last change on this file since 1330 was 1215, checked in by sandervl, 26 years ago

Added $Id$

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