source: trunk/src/shell32/shlfolder.c@ 8266

Last change on this file since 8266 was 8048, checked in by sandervl, 23 years ago

PH: Wine resync + OS2 integration

File size: 72.0 KB
Line 
1/*
2 * Shell Folder stuff
3 *
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999 Juergen Schmied
6 *
7 * IShellFolder2 and related interfaces
8 *
9 */
10
11/****************************************************************************
12 * includes
13 ****************************************************************************/
14
15#include <odin.h>
16#include <os2sel.h>
17#include <odinwrap.h>
18
19ODINDEBUGCHANNEL(SHELL32-SHLFOLDER)
20
21
22
23#ifdef __WIN32OS2__
24#define snprintf(a,b,c,d) sprintf(a,c,d)
25#endif
26#include <stdlib.h>
27#include <string.h>
28#include <stdio.h>
29
30#include "debugtools.h"
31#include "winerror.h"
32#include "winbase.h"
33
34#include "oleidl.h"
35#include "shlguid.h"
36
37#include "pidl.h"
38#include "wine/obj_base.h"
39#include "wine/obj_dragdrop.h"
40#include "wine/obj_shellfolder.h"
41#include "wine/undocshell.h"
42#include "shell32_main.h"
43#include "shresdef.h"
44#include "shlwapi.h"
45#include "shellfolder.h"
46
47DEFAULT_DEBUG_CHANNEL(shell);
48
49
50/***************************************************************************
51 * debughelper: print out the return adress
52 * helps especially to track down unbalanced AddRef/Release
53 */
54#define MEM_DEBUG 0
55
56#if MEM_DEBUG
57#define _CALL_TRACE TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 ));
58#else
59#define _CALL_TRACE
60#endif
61
62typedef struct
63{
64 int colnameid;
65 int pcsFlags;
66 int fmt;
67 int cxChar;
68
69} shvheader;
70
71/***************************************************************************
72 * GetNextElement (internal function)
73 *
74 * gets a part of a string till the first backslash
75 *
76 * PARAMETERS
77 * pszNext [IN] string to get the element from
78 * pszOut [IN] pointer to buffer whitch receives string
79 * dwOut [IN] length of pszOut
80 *
81 * RETURNS
82 * LPSTR pointer to first, not yet parsed char
83 */
84
85static LPCWSTR GetNextElementW(LPCWSTR pszNext,LPWSTR pszOut,DWORD dwOut)
86{ LPCWSTR pszTail = pszNext;
87 DWORD dwCopy;
88 TRACE("(%s %p 0x%08lx)\n",debugstr_w(pszNext),pszOut,dwOut);
89
90 *pszOut=0x0000;
91
92 if(!pszNext || !*pszNext)
93 return NULL;
94
95 while(*pszTail && (*pszTail != (WCHAR)'\\'))
96 pszTail++;
97
98 dwCopy = (WCHAR*)pszTail - (WCHAR*)pszNext + 1;
99 lstrcpynW(pszOut, pszNext, (dwOut<dwCopy)? dwOut : dwCopy);
100
101 if(*pszTail)
102 pszTail++;
103 else
104 pszTail = NULL;
105
106 TRACE("--(%s %s 0x%08lx %p)\n",debugstr_w(pszNext),debugstr_w(pszOut),dwOut,pszTail);
107 return pszTail;
108}
109
110static HRESULT SHELL32_ParseNextElement(
111 HWND hwndOwner,
112 IShellFolder2 * psf,
113 LPITEMIDLIST * pidlInOut,
114 LPOLESTR szNext,
115 DWORD *pEaten,
116 DWORD *pdwAttributes)
117{
118 HRESULT hr = E_OUTOFMEMORY;
119 LPITEMIDLIST pidlOut, pidlTemp = NULL;
120 IShellFolder *psfChild;
121
122 TRACE("(%p, %p, %s)\n",psf, pidlInOut ? *pidlInOut : NULL, debugstr_w(szNext));
123
124
125 /* get the shellfolder for the child pidl and let it analyse further */
126 hr = IShellFolder_BindToObject(psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
127
128 if (psfChild)
129 {
130 hr = IShellFolder_ParseDisplayName(psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes);
131 IShellFolder_Release(psfChild);
132
133 pidlTemp = ILCombine(*pidlInOut, pidlOut);
134
135 if (pidlOut)
136 ILFree(pidlOut);
137 }
138
139 ILFree(*pidlInOut);
140 *pidlInOut = pidlTemp;
141
142 TRACE("-- pidl=%p ret=0x%08lx\n", pidlInOut? *pidlInOut: NULL, hr);
143 return hr;
144}
145
146/***********************************************************************
147 * SHELL32_CoCreateInitSF
148 *
149 * creates a initialized shell folder
150 */
151static HRESULT SHELL32_CoCreateInitSF (
152 LPITEMIDLIST pidlRoot,
153 LPITEMIDLIST pidlChild,
154 REFCLSID clsid,
155 REFIID iid,
156 LPVOID * ppvOut)
157{
158 HRESULT hr;
159 LPITEMIDLIST absPidl;
160 IShellFolder2 *pShellFolder;
161 IPersistFolder *pPersistFolder;
162
163 TRACE("%p %p\n", pidlRoot, pidlChild);
164
165 *ppvOut = NULL;
166
167 /* we have to ask first for IPersistFolder, some special folders are expecting this */
168 hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IPersistFolder, (LPVOID*)&pPersistFolder);
169 if (SUCCEEDED(hr))
170 {
171 hr = IPersistFolder_QueryInterface(pPersistFolder, iid, (LPVOID*)&pShellFolder);
172 if (SUCCEEDED(hr))
173 {
174 absPidl = ILCombine (pidlRoot, pidlChild);
175 hr = IPersistFolder_Initialize(pPersistFolder, absPidl);
176 IPersistFolder_Release(pPersistFolder);
177 SHFree(absPidl);
178 *ppvOut = pShellFolder;
179 }
180 }
181
182 TRACE("-- ret=0x%08lx\n", hr);
183 return hr;
184}
185
186static HRESULT SHELL32_GetDisplayNameOfChild(
187 IShellFolder2 * psf,
188 LPCITEMIDLIST pidl,
189 DWORD dwFlags,
190 LPSTR szOut,
191 DWORD dwOutLen)
192{
193 LPITEMIDLIST pidlFirst, pidlNext;
194 IShellFolder2 * psfChild;
195 HRESULT hr = E_OUTOFMEMORY;
196 STRRET strTemp;
197
198 TRACE("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n",psf,pidl,dwFlags,szOut, dwOutLen);
199 pdump(pidl);
200
201 if ((pidlFirst = ILCloneFirst(pidl)))
202 {
203 hr = IShellFolder_BindToObject(psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
204 if (SUCCEEDED(hr))
205 {
206 pidlNext = ILGetNext(pidl);
207
208 hr = IShellFolder_GetDisplayNameOf(psfChild, pidlNext, dwFlags | SHGDN_INFOLDER, &strTemp);
209 if (SUCCEEDED(hr))
210 {
211 hr = StrRetToStrNA(szOut, dwOutLen, &strTemp, pidlNext);
212 }
213
214 IShellFolder_Release(psfChild);
215 }
216 ILFree(pidlFirst);
217 }
218
219 TRACE("-- ret=0x%08lx %s\n", hr, szOut);
220
221 return hr;
222}
223
224/***********************************************************************
225 * SHELL32_GetItemAttributes
226 *
227 * NOTES
228 * observerd values:
229 * folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER
230 * file: 0x40000177 FILESYSTEM
231 * drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR
232 * mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR
233 * (seems to be default for shell extensions if no registry entry exists)
234 *
235 * This functions does not set flags!! It only resets flags when nessesary.
236 */
237static HRESULT SHELL32_GetItemAttributes(
238 IShellFolder * psf,
239 LPITEMIDLIST pidl,
240 LPDWORD pdwAttributes)
241{
242 GUID const * clsid;
243 DWORD dwAttributes;
244
245 TRACE("0x%08lx\n", *pdwAttributes);
246
247 if (*pdwAttributes & (0xcff3fe88))
248 WARN("attribute 0x%08lx not implemented\n", *pdwAttributes);
249 *pdwAttributes &= ~SFGAO_LINK; /* FIXME: for native filedialogs */
250
251 if (_ILIsDrive(pidl))
252 {
253 *pdwAttributes &= 0xf0000144;
254 }
255 else if ((clsid=_ILGetGUIDPointer(pidl)))
256 {
257 if (HCR_GetFolderAttributes(clsid, &dwAttributes))
258 {
259 *pdwAttributes &= dwAttributes;
260 }
261 else
262 {
263 *pdwAttributes &= 0xb0000154;
264 }
265 }
266 else if (_ILGetDataPointer(pidl))
267 {
268 dwAttributes = _ILGetFileAttributes(pidl, NULL, 0);
269 *pdwAttributes &= ~SFGAO_FILESYSANCESTOR;
270
271 if(( SFGAO_FOLDER & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
272 *pdwAttributes &= ~(SFGAO_FOLDER|SFGAO_HASSUBFOLDER);
273
274 if(( SFGAO_HIDDEN & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN))
275 *pdwAttributes &= ~SFGAO_HIDDEN;
276
277 if(( SFGAO_READONLY & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_READONLY))
278 *pdwAttributes &= ~SFGAO_READONLY;
279 }
280 else
281 {
282 *pdwAttributes &= 0xb0000154;
283 }
284 TRACE("-- 0x%08lx\n", *pdwAttributes);
285 return S_OK;
286}
287
288/***********************************************************************
289* IShellFolder implementation
290*/
291
292typedef struct
293{
294 ICOM_VFIELD(IUnknown);
295 DWORD ref;
296 ICOM_VTABLE(IShellFolder2)* lpvtblShellFolder;
297 ICOM_VTABLE(IPersistFolder2)* lpvtblPersistFolder2;
298 ICOM_VTABLE(IDropTarget)* lpvtblDropTarget;
299 ICOM_VTABLE(ISFHelper)* lpvtblSFHelper;
300
301 IUnknown *pUnkOuter; /* used for aggregation */
302
303 CLSID* pclsid;
304
305 LPSTR sMyPath;
306 LPITEMIDLIST absPidl; /* complete pidl */
307
308 UINT cfShellIDList; /* clipboardformat for IDropTarget */
309 BOOL fAcceptFmt; /* flag for pending Drop */
310} IGenericSFImpl;
311
312static struct ICOM_VTABLE(IUnknown) unkvt;
313static struct ICOM_VTABLE(IShellFolder2) sfvt;
314static struct ICOM_VTABLE(IPersistFolder2) psfvt;
315static struct ICOM_VTABLE(IDropTarget) dtvt;
316static struct ICOM_VTABLE(ISFHelper) shvt;
317
318static IShellFolder * ISF_MyComputer_Constructor(void);
319
320#define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder)))
321#define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset);
322
323#define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder2)))
324#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset);
325
326#define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget)))
327#define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset);
328
329#define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper)))
330#define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset);
331/*
332 converts This to a interface pointer
333*/
334#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl)
335#define _IShellFolder_(This) (IShellFolder*)&(This->lpvtblShellFolder)
336#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpvtblShellFolder)
337#define _IPersist_(This) (IPersist*)&(This->lpvtblPersistFolder2)
338#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder2)
339#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder2)
340#define _IDropTarget_(This) (IDropTarget*)&(This->lpvtblDropTarget)
341#define _ISFHelper_(This) (ISFHelper*)&(This->lpvtblSFHelper)
342/**************************************************************************
343* registers clipboardformat once
344*/
345static void SF_RegisterClipFmt (IGenericSFImpl * This)
346{
347 TRACE("(%p)\n", This);
348
349 if (!This->cfShellIDList)
350 {
351 This->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
352 }
353}
354
355/**************************************************************************
356* we need a separate IUnknown to handle aggregation
357* (inner IUnknown)
358*/
359static HRESULT WINAPI IUnknown_fnQueryInterface(
360 IUnknown * iface,
361 REFIID riid,
362 LPVOID *ppvObj)
363{
364 ICOM_THIS(IGenericSFImpl, iface);
365
366 _CALL_TRACE
367 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
368
369 *ppvObj = NULL;
370
371 if(IsEqualIID(riid, &IID_IUnknown)) *ppvObj = _IUnknown_(This);
372 else if(IsEqualIID(riid, &IID_IShellFolder)) *ppvObj = _IShellFolder_(This);
373 else if(IsEqualIID(riid, &IID_IShellFolder2)) *ppvObj = _IShellFolder_(This);
374 else if(IsEqualIID(riid, &IID_IPersist)) *ppvObj = _IPersist_(This);
375 else if(IsEqualIID(riid, &IID_IPersistFolder)) *ppvObj = _IPersistFolder_(This);
376 else if(IsEqualIID(riid, &IID_IPersistFolder2)) *ppvObj = _IPersistFolder2_(This);
377 else if(IsEqualIID(riid, &IID_ISFHelper)) *ppvObj = _ISFHelper_(This);
378 else if(IsEqualIID(riid, &IID_IDropTarget))
379 {
380 *ppvObj = _IDropTarget_(This);
381 SF_RegisterClipFmt(This);
382 }
383
384 if(*ppvObj)
385 {
386 IUnknown_AddRef((IUnknown*)(*ppvObj));
387 TRACE("-- Interface = %p\n", *ppvObj);
388 return S_OK;
389 }
390 TRACE("-- Interface: E_NOINTERFACE\n");
391 return E_NOINTERFACE;
392}
393
394static ULONG WINAPI IUnknown_fnAddRef(IUnknown * iface)
395{
396 ICOM_THIS(IGenericSFImpl, iface);
397
398 _CALL_TRACE
399 TRACE("(%p)->(count=%lu)\n",This,This->ref);
400
401 shell32_ObjCount++;
402 return ++(This->ref);
403}
404
405static ULONG WINAPI IUnknown_fnRelease(IUnknown * iface)
406{
407 ICOM_THIS(IGenericSFImpl, iface);
408
409 _CALL_TRACE
410 TRACE("(%p)->(count=%lu)\n",This,This->ref);
411
412 shell32_ObjCount--;
413 if (!--(This->ref))
414 {
415 TRACE("-- destroying IShellFolder(%p)\n",This);
416
417 if (pdesktopfolder == _IShellFolder_(This))
418 {
419 pdesktopfolder=NULL;
420 TRACE("-- destroyed IShellFolder(%p) was Desktopfolder\n",This);
421 }
422 if(This->absPidl) SHFree(This->absPidl);
423 if(This->sMyPath) SHFree(This->sMyPath);
424 HeapFree(GetProcessHeap(),0,This);
425 return 0;
426 }
427 return This->ref;
428}
429
430static ICOM_VTABLE(IUnknown) unkvt =
431{
432 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
433 IUnknown_fnQueryInterface,
434 IUnknown_fnAddRef,
435 IUnknown_fnRelease,
436};
437
438static shvheader GenericSFHeader [] =
439{
440 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
441 { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
442 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
443 { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
444 { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
445};
446#define GENERICSHELLVIEWCOLUMNS 5
447
448/**************************************************************************
449* IShellFolder_Constructor
450*
451* NOTES
452* creating undocumented ShellFS_Folder as part of an aggregation
453* {F3364BA0-65B9-11CE-A9BA-00AA004AE837}
454*
455* FIXME
456* when pUnkOuter = 0 then rrid = IID_IShellFolder is returned
457*/
458HRESULT IFSFolder_Constructor(
459 IUnknown * pUnkOuter,
460 REFIID riid,
461 LPVOID * ppv)
462{
463 IGenericSFImpl * sf;
464 HRESULT hr = S_OK;
465
466 TRACE("unkOut=%p riid=%s\n",pUnkOuter, debugstr_guid(riid));
467
468 if(pUnkOuter && ! IsEqualIID(riid, &IID_IUnknown))
469 {
470 hr = CLASS_E_NOAGGREGATION; /* forbidden by definition */
471 }
472 else
473 {
474 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
475 if (sf)
476 {
477 sf->ref=1;
478 ICOM_VTBL(sf)=&unkvt;
479 sf->lpvtblShellFolder=&sfvt;
480 sf->lpvtblPersistFolder2=&psfvt;
481 sf->lpvtblDropTarget=&dtvt;
482 sf->lpvtblSFHelper=&shvt;
483
484 sf->pclsid = (CLSID*)&CLSID_SFFile;
485 sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_(sf);
486 *ppv = _IUnknown_(sf);
487 hr = S_OK;
488 shell32_ObjCount++;
489 }
490 else
491 {
492 hr = E_OUTOFMEMORY;
493 }
494 }
495 return hr;
496}
497/**************************************************************************
498* IShellFolder_Constructor
499*
500* NOTES
501* THIS points to the parent folder
502*/
503
504IShellFolder * IShellFolder_Constructor(
505 IShellFolder2 * iface,
506 LPITEMIDLIST pidl)
507{
508 IGenericSFImpl * sf;
509 DWORD dwSize=0;
510
511 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
512
513 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
514 sf->ref=1;
515
516 ICOM_VTBL(sf)=&unkvt;
517 sf->lpvtblShellFolder=&sfvt;
518 sf->lpvtblPersistFolder2=&psfvt;
519 sf->lpvtblDropTarget=&dtvt;
520 sf->lpvtblSFHelper=&shvt;
521
522 sf->pclsid = (CLSID*)&CLSID_SFFile;
523 sf->pUnkOuter = _IUnknown_(sf);
524
525 TRACE("(%p)->(parent=%p, pidl=%p)\n",sf,This, pidl);
526 pdump(pidl);
527
528 if(pidl && iface) /* do we have a pidl? */
529 {
530 int len;
531
532 sf->absPidl = ILCombine(This->absPidl, pidl); /* build a absolute pidl */
533
534 if (!_ILIsSpecialFolder(pidl)) /* only file system paths */
535 {
536 if(This->sMyPath) /* get the size of the parents path */
537 {
538 dwSize += strlen(This->sMyPath) ;
539 TRACE("-- (%p)->(parent's path=%s)\n",sf, debugstr_a(This->sMyPath));
540 }
541
542 dwSize += _ILSimpleGetText(pidl,NULL,0); /* add the size of our name*/
543 sf->sMyPath = SHAlloc(dwSize + 2); /* '\0' and backslash */
544
545 if(!sf->sMyPath) return NULL;
546 *(sf->sMyPath)=0x00;
547
548 if(This->sMyPath) /* if the parent has a path, get it*/
549 {
550 strcpy(sf->sMyPath, This->sMyPath);
551 PathAddBackslashA (sf->sMyPath);
552 }
553
554 len = strlen(sf->sMyPath);
555 _ILSimpleGetText(pidl, sf->sMyPath + len, dwSize+2 - len);
556 }
557
558 TRACE("-- (%p)->(my pidl=%p, my path=%s)\n",sf, sf->absPidl,debugstr_a(sf->sMyPath));
559
560 pdump (sf->absPidl);
561 }
562
563 shell32_ObjCount++;
564 return _IShellFolder_(sf);
565}
566
567/**************************************************************************
568 * IShellFolder_fnQueryInterface
569 *
570 * PARAMETERS
571 * REFIID riid [in ] Requested InterfaceID
572 * LPVOID* ppvObject [out] Interface* to hold the result
573 */
574static HRESULT WINAPI IShellFolder_fnQueryInterface(
575 IShellFolder2 * iface,
576 REFIID riid,
577 LPVOID *ppvObj)
578{
579 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
580
581 _CALL_TRACE
582 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
583
584 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
585}
586
587/**************************************************************************
588* IShellFolder_AddRef
589*/
590
591static ULONG WINAPI IShellFolder_fnAddRef(IShellFolder2 * iface)
592{
593 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
594
595 _CALL_TRACE
596 TRACE("(%p)->(count=%lu)\n",This,This->ref);
597
598 return IUnknown_AddRef(This->pUnkOuter);
599}
600
601/**************************************************************************
602 * IShellFolder_fnRelease
603 */
604static ULONG WINAPI IShellFolder_fnRelease(IShellFolder2 * iface)
605{
606 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
607
608 _CALL_TRACE
609 TRACE("(%p)->(count=%lu)\n",This,This->ref);
610
611 return IUnknown_Release(This->pUnkOuter);
612}
613
614/**************************************************************************
615* IShellFolder_fnParseDisplayName
616* PARAMETERS
617* HWND hwndOwner, //[in ] Parent window for any message's
618* LPBC pbc, //[in ] reserved
619* LPOLESTR lpszDisplayName,//[in ] "Unicode" displayname.
620* ULONG* pchEaten, //[out] (unicode) characters processed
621* LPITEMIDLIST* ppidl, //[out] complex pidl to item
622* ULONG* pdwAttributes //[out] items attributes
623*
624* NOTES
625* every folder tries to parse only its own (the leftmost) pidl and creates a
626* subfolder to evaluate the remaining parts
627* now we can parse into namespaces implemented by shell extensions
628*
629* behaviour on win98: lpszDisplayName=NULL -> chrash
630* lpszDisplayName="" -> returns mycoputer-pidl
631*
632* FIXME:
633* pdwAttributes: not set
634* pchEaten: not set like in windows
635*/
636static HRESULT WINAPI IShellFolder_fnParseDisplayName(
637 IShellFolder2 * iface,
638 HWND hwndOwner,
639 LPBC pbcReserved,
640 LPOLESTR lpszDisplayName,
641 DWORD *pchEaten,
642 LPITEMIDLIST *ppidl,
643 DWORD *pdwAttributes)
644{
645 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
646
647 HRESULT hr = E_OUTOFMEMORY;
648 LPCWSTR szNext=NULL;
649 WCHAR szElement[MAX_PATH];
650 CHAR szTempA[MAX_PATH], szPath[MAX_PATH];
651 LPITEMIDLIST pidlTemp=NULL;
652
653 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
654 This,hwndOwner,pbcReserved,lpszDisplayName,
655 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
656
657 if (!lpszDisplayName || !ppidl) return E_INVALIDARG;
658
659 if (pchEaten) *pchEaten = 0; /* strange but like the original */
660
661 if (*lpszDisplayName)
662 {
663 /* get the next element */
664 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
665
666 /* build the full pathname to the element */
667 WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
668 strcpy(szPath, This->sMyPath);
669 PathAddBackslashA(szPath);
670 strcat(szPath, szTempA);
671
672 /* get the pidl */
673 pidlTemp = SHSimpleIDListFromPathA(szPath);
674
675 if (pidlTemp)
676 {
677 /* try to analyse the next element */
678 if (szNext && *szNext)
679 {
680 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
681 }
682 else
683 {
684 if (pdwAttributes && *pdwAttributes)
685 {
686 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
687/* WIN32_FIND_DATAA fd;
688 SHGetDataFromIDListA(_IShellFolder_(This), pidlTemp, SHGDFIL_FINDDATA, &fd, sizeof(fd));
689 if (!(FILE_ATTRIBUTE_DIRECTORY & fd.dwFileAttributes))
690 *pdwAttributes &= ~SFGAO_FOLDER;
691 if (FILE_ATTRIBUTE_READONLY & fd.dwFileAttributes)
692 *pdwAttributes &= ~(SFGAO_CANDELETE|SFGAO_CANMOVE|SFGAO_CANRENAME );
693*/
694 }
695 hr = S_OK;
696 }
697 }
698 }
699
700 if (!hr)
701 *ppidl = pidlTemp;
702 else
703 *ppidl = NULL;
704
705 TRACE("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl? *ppidl:0, hr);
706
707 return hr;
708}
709
710/**************************************************************************
711* IShellFolder_fnEnumObjects
712* PARAMETERS
713* HWND hwndOwner, //[in ] Parent Window
714* DWORD grfFlags, //[in ] SHCONTF enumeration mask
715* LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
716*/
717static HRESULT WINAPI IShellFolder_fnEnumObjects(
718 IShellFolder2 * iface,
719 HWND hwndOwner,
720 DWORD dwFlags,
721 LPENUMIDLIST* ppEnumIDList)
722{
723 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
724
725 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
726
727 *ppEnumIDList = NULL;
728 *ppEnumIDList = IEnumIDList_Constructor (This->sMyPath, dwFlags, EIDL_FILE);
729
730 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
731
732 if(!*ppEnumIDList) return E_OUTOFMEMORY;
733
734 return S_OK;
735}
736
737/**************************************************************************
738* IShellFolder_fnBindToObject
739* PARAMETERS
740* LPCITEMIDLIST pidl, //[in ] relative pidl to open
741* LPBC pbc, //[in ] reserved
742* REFIID riid, //[in ] Initial Interface
743* LPVOID* ppvObject //[out] Interface*
744*/
745static HRESULT WINAPI IShellFolder_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
746 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
747{
748 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
749 GUID const * iid;
750 IShellFolder *pShellFolder, *pSubFolder;
751 IPersistFolder *pPersistFolder;
752 LPITEMIDLIST absPidl;
753
754 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
755
756 if(!pidl || !ppvOut) return E_INVALIDARG;
757
758 *ppvOut = NULL;
759
760 if ((iid=_ILGetGUIDPointer(pidl)))
761 {
762 /* we have to create a alien folder */
763 if ( SUCCEEDED(SHCoCreateInstance(NULL, iid, NULL, riid, (LPVOID*)&pShellFolder))
764 && SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder)))
765 {
766 absPidl = ILCombine (This->absPidl, pidl);
767 IPersistFolder_Initialize(pPersistFolder, absPidl);
768 IPersistFolder_Release(pPersistFolder);
769 SHFree(absPidl);
770 }
771 else
772 {
773 return E_FAIL;
774 }
775 }
776 else if(_ILIsFolder(pidl))
777 {
778 LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
779 pShellFolder = IShellFolder_Constructor(iface, pidltemp);
780 ILFree(pidltemp);
781 }
782 else
783 {
784 ERR("can't bind to a file\n");
785 return E_FAIL;
786 }
787
788 if (_ILIsPidlSimple(pidl))
789 {
790 *ppvOut = pShellFolder;
791 }
792 else
793 {
794 IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder);
795 IShellFolder_Release(pShellFolder);
796 *ppvOut = pSubFolder;
797 }
798
799 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
800
801 return S_OK;
802}
803
804/**************************************************************************
805* IShellFolder_fnBindToStorage
806* PARAMETERS
807* LPCITEMIDLIST pidl, //[in ] complex pidl to store
808* LPBC pbc, //[in ] reserved
809* REFIID riid, //[in ] Initial storage interface
810* LPVOID* ppvObject //[out] Interface* returned
811*/
812static HRESULT WINAPI IShellFolder_fnBindToStorage(
813 IShellFolder2 * iface,
814 LPCITEMIDLIST pidl,
815 LPBC pbcReserved,
816 REFIID riid,
817 LPVOID *ppvOut)
818{
819 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
820
821 FIXME("(%p)->(pidl=%p,%p,\n\tIID:%s,%p) stub\n",
822 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
823
824 *ppvOut = NULL;
825 return E_NOTIMPL;
826}
827
828/**************************************************************************
829* IShellFolder_fnCompareIDs
830*
831* PARMETERS
832* LPARAM lParam, //[in ] Column?
833* LPCITEMIDLIST pidl1, //[in ] simple pidl
834* LPCITEMIDLIST pidl2) //[in ] simple pidl
835*
836* NOTES
837* Special case - If one of the items is a Path and the other is a File,
838* always make the Path come before the File.
839*
840* NOTES
841* use SCODE_CODE() on the return value to get the result
842*/
843
844static ODINFUNCTION4(HRESULT, IShellFolder_fnCompareIDs,
845 IShellFolder2 *, iface,
846 LPARAM, lParam,
847 LPCITEMIDLIST, pidl1,
848 LPCITEMIDLIST, pidl2)
849{
850 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
851
852 int nReturn;
853 IShellFolder * psf;
854 HRESULT hr = E_OUTOFMEMORY;
855 LPCITEMIDLIST pidlTemp;
856 PIDLTYPE pt1, pt2;
857
858// TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
859// pdump (pidl1);
860// pdump (pidl2);
861
862 if (!pidl1 && !pidl2)
863 {
864 hr = ResultFromShort(0);
865 }
866 else if (!pidl1)
867 {
868 hr = ResultFromShort(-1);
869 }
870 else if (!pidl2)
871 {
872 hr = ResultFromShort(1);
873 }
874 else
875 {
876 LPPIDLDATA pd1, pd2;
877 pd1 = _ILGetDataPointer(pidl1);
878 pd2 = _ILGetDataPointer(pidl2);
879
880 /* compate the types. sort order is the PT_* constant */
881 pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
882 pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
883
884 if (pt1 != pt2)
885 {
886 hr = ResultFromShort(pt1-pt2);
887 }
888 else /* same type of pidl */
889 {
890// _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
891// _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
892// nReturn = strcasecmp(szTemp1, szTemp2);
893 nReturn = _ILSimpleCompareText( pidl1, pidl2 );
894
895 if (nReturn == 0) /* first pidl different ? */
896 {
897 pidl1 = ILGetNext(pidl1);
898
899 if (pidl1 && pidl1->mkid.cb) /* go deeper? */
900 {
901 pidlTemp = ILCloneFirst(pidl1);
902 pidl2 = ILGetNext(pidl2);
903
904 hr = IShellFolder_BindToObject(iface, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
905 if (SUCCEEDED(hr))
906 {
907 nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
908 IShellFolder_Release(psf);
909 hr = ResultFromShort(nReturn);
910 }
911 ILFree(pidlTemp);
912 }
913 else
914 {
915 pidl2 = ILGetNext(pidl2);
916 if (pidl2 && pidl2->mkid.cb) /* go deeper on #2 ? */
917 hr = ResultFromShort(-1); /* two different */
918 else
919 hr = ResultFromShort(nReturn); /* two equal simple pidls */
920 }
921 }
922 else
923 {
924 hr = ResultFromShort(nReturn); /* two different simple pidls */
925 }
926 }
927 }
928
929 TRACE("-- res=0x%08lx\n", hr);
930 return hr;
931}
932
933/**************************************************************************
934* IShellFolder_fnCreateViewObject
935*/
936static HRESULT WINAPI IShellFolder_fnCreateViewObject(
937 IShellFolder2 * iface,
938 HWND hwndOwner,
939 REFIID riid,
940 LPVOID *ppvOut)
941{
942 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
943
944 LPSHELLVIEW pShellView;
945 HRESULT hr = E_INVALIDARG;
946
947 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
948
949 if(ppvOut)
950 {
951 *ppvOut = NULL;
952
953 if(IsEqualIID(riid, &IID_IDropTarget))
954 {
955 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, ppvOut);
956 }
957 else if(IsEqualIID(riid, &IID_IContextMenu))
958 {
959 FIXME("IContextMenu not implemented\n");
960 hr = E_NOTIMPL;
961 }
962 else if(IsEqualIID(riid, &IID_IShellView))
963 {
964 pShellView = IShellView_Constructor((IShellFolder*)iface);
965 if(pShellView)
966 {
967 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
968 IShellView_Release(pShellView);
969 }
970 }
971 }
972 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
973 return hr;
974}
975
976/**************************************************************************
977* IShellFolder_fnGetAttributesOf
978*
979* PARAMETERS
980* UINT cidl, //[in ] num elements in pidl array
981* LPCITEMIDLIST* apidl, //[in ] simple pidl array
982* ULONG* rgfInOut) //[out] result array
983*
984*/
985static HRESULT WINAPI IShellFolder_fnGetAttributesOf(
986 IShellFolder2 * iface,
987 UINT cidl,
988 LPCITEMIDLIST *apidl,
989 DWORD *rgfInOut)
990{
991 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
992
993 HRESULT hr = S_OK;
994
995 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
996
997 if ( (!cidl) || (!apidl) || (!rgfInOut))
998 return E_INVALIDARG;
999
1000 while (cidl > 0 && *apidl)
1001 {
1002 pdump (*apidl);
1003 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1004 apidl++;
1005 cidl--;
1006 }
1007
1008 TRACE("-- result=0x%08lx\n",*rgfInOut);
1009
1010 return hr;
1011}
1012/**************************************************************************
1013* IShellFolder_fnGetUIObjectOf
1014*
1015* PARAMETERS
1016* HWND hwndOwner, //[in ] Parent window for any output
1017* UINT cidl, //[in ] array size
1018* LPCITEMIDLIST* apidl, //[in ] simple pidl array
1019* REFIID riid, //[in ] Requested Interface
1020* UINT* prgfInOut, //[ ] reserved
1021* LPVOID* ppvObject) //[out] Resulting Interface
1022*
1023* NOTES
1024* This function gets asked to return "view objects" for one or more (multiple select)
1025* items:
1026* The viewobject typically is an COM object with one of the following interfaces:
1027* IExtractIcon,IDataObject,IContextMenu
1028* In order to support icon positions in the default Listview your DataObject
1029* must implement the SetData method (in addition to GetData :) - the shell passes
1030* a barely documented "Icon positions" structure to SetData when the drag starts,
1031* and GetData's it if the drop is in another explorer window that needs the positions.
1032*/
1033static HRESULT WINAPI IShellFolder_fnGetUIObjectOf(
1034 IShellFolder2 * iface,
1035 HWND hwndOwner,
1036 UINT cidl,
1037 LPCITEMIDLIST * apidl,
1038 REFIID riid,
1039 UINT * prgfInOut,
1040 LPVOID * ppvOut)
1041{
1042 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1043
1044 LPITEMIDLIST pidl;
1045 IUnknown* pObj = NULL;
1046 HRESULT hr = E_INVALIDARG;
1047
1048 TRACE("(%p)->(0x%04x,%u,apidl=%p,\n\tIID:%s,%p,%p)\n",
1049 This,hwndOwner,cidl,apidl,debugstr_guid(riid),prgfInOut,ppvOut);
1050
1051 if (ppvOut)
1052 {
1053 *ppvOut = NULL;
1054
1055 if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
1056 {
1057 pObj = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl);
1058 hr = S_OK;
1059 }
1060 else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
1061 {
1062 pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
1063 hr = S_OK;
1064 }
1065 else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
1066 {
1067 pidl = ILCombine(This->absPidl,apidl[0]);
1068 pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
1069 SHFree(pidl);
1070 hr = S_OK;
1071 }
1072 else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
1073 {
1074 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pObj);
1075 }
1076 else
1077 {
1078 hr = E_NOINTERFACE;
1079 }
1080
1081 if(!pObj)
1082 hr = E_OUTOFMEMORY;
1083
1084 *ppvOut = pObj;
1085 }
1086 TRACE("(%p)->hr=0x%08lx\n",This, hr);
1087 return hr;
1088}
1089
1090/**************************************************************************
1091* IShellFolder_fnGetDisplayNameOf
1092* Retrieves the display name for the specified file object or subfolder
1093*
1094* PARAMETERS
1095* LPCITEMIDLIST pidl, //[in ] complex pidl to item
1096* DWORD dwFlags, //[in ] SHGNO formatting flags
1097* LPSTRRET lpName) //[out] Returned display name
1098*
1099* FIXME
1100* if the name is in the pidl the ret value should be a STRRET_OFFSET
1101*/
1102#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
1103#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
1104
1105static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
1106 IShellFolder2 * iface,
1107 LPCITEMIDLIST pidl,
1108 DWORD dwFlags,
1109 LPSTRRET strRet)
1110{
1111 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1112
1113 CHAR szPath[MAX_PATH]= "";
1114 int len = 0;
1115 BOOL bSimplePidl;
1116
1117 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1118 pdump(pidl);
1119
1120 if(!pidl || !strRet) return E_INVALIDARG;
1121
1122 bSimplePidl = _ILIsPidlSimple(pidl);
1123
1124 /* take names of special folders only if its only this folder */
1125 if (_ILIsSpecialFolder(pidl))
1126 {
1127 if ( bSimplePidl)
1128 {
1129 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1130 }
1131 }
1132 else
1133 {
1134 if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
1135 {
1136 strcpy (szPath, This->sMyPath); /* get path to root*/
1137 PathAddBackslashA(szPath);
1138 len = strlen(szPath);
1139 }
1140 _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
1141 }
1142
1143 if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl) /* go deeper if needed */
1144 {
1145 PathAddBackslashA(szPath);
1146 len = strlen(szPath);
1147
1148 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath + len, MAX_PATH - len)))
1149 return E_OUTOFMEMORY;
1150 }
1151 strRet->uType = STRRET_CSTRA;
1152 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1153
1154 TRACE("-- (%p)->(%s)\n", This, szPath);
1155 return S_OK;
1156}
1157
1158/**************************************************************************
1159* IShellFolder_fnSetNameOf
1160* Changes the name of a file object or subfolder, possibly changing its item
1161* identifier in the process.
1162*
1163* PARAMETERS
1164* HWND hwndOwner, //[in ] Owner window for output
1165* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
1166* LPCOLESTR lpszName, //[in ] the items new display name
1167* DWORD dwFlags, //[in ] SHGNO formatting flags
1168* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
1169*/
1170static HRESULT WINAPI IShellFolder_fnSetNameOf(
1171 IShellFolder2 * iface,
1172 HWND hwndOwner,
1173 LPCITEMIDLIST pidl, /*simple pidl*/
1174 LPCOLESTR lpName,
1175 DWORD dwFlags,
1176 LPITEMIDLIST *pPidlOut)
1177{
1178 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1179 char szSrc[MAX_PATH], szDest[MAX_PATH];
1180 int len;
1181 BOOL bIsFolder = _ILIsFolder(ILFindLastID(pidl));
1182
1183 TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p)\n",
1184 This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut);
1185
1186 /* build source path */
1187 if (dwFlags & SHGDN_INFOLDER)
1188 {
1189 strcpy(szSrc, This->sMyPath);
1190 PathAddBackslashA(szSrc);
1191 len = strlen (szSrc);
1192 _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len);
1193 }
1194 else
1195 {
1196 SHGetPathFromIDListA(pidl, szSrc);
1197 }
1198
1199 /* build destination path */
1200 strcpy(szDest, This->sMyPath);
1201 PathAddBackslashA(szDest);
1202 len = strlen (szDest);
1203 WideCharToMultiByte( CP_ACP, 0, lpName, -1, szDest+len, MAX_PATH-len, NULL, NULL );
1204 szDest[MAX_PATH-1] = 0;
1205 TRACE("src=%s dest=%s\n", szSrc, szDest);
1206 if ( MoveFileA(szSrc, szDest) )
1207 {
1208 if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest);
1209 SHChangeNotifyA( bIsFolder?SHCNE_RENAMEFOLDER:SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
1210 return S_OK;
1211 }
1212 return E_FAIL;
1213}
1214
1215static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(
1216 IShellFolder2 * iface,
1217 GUID *pguid)
1218{
1219 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1220 FIXME("(%p)\n",This);
1221 return E_NOTIMPL;
1222}
1223static HRESULT WINAPI IShellFolder_fnEnumSearches(
1224 IShellFolder2 * iface,
1225 IEnumExtraSearch **ppenum)
1226{
1227 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1228 FIXME("(%p)\n",This);
1229 return E_NOTIMPL;
1230}
1231static HRESULT WINAPI IShellFolder_fnGetDefaultColumn(
1232 IShellFolder2 * iface,
1233 DWORD dwRes,
1234 ULONG *pSort,
1235 ULONG *pDisplay)
1236{
1237 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1238
1239 TRACE("(%p)\n",This);
1240
1241 if (pSort) *pSort = 0;
1242 if (pDisplay) *pDisplay = 0;
1243
1244 return S_OK;
1245}
1246static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState(
1247 IShellFolder2 * iface,
1248 UINT iColumn,
1249 DWORD *pcsFlags)
1250{
1251 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1252
1253 TRACE("(%p)\n",This);
1254
1255 if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1256
1257 *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
1258
1259 return S_OK;
1260}
1261static HRESULT WINAPI IShellFolder_fnGetDetailsEx(
1262 IShellFolder2 * iface,
1263 LPCITEMIDLIST pidl,
1264 const SHCOLUMNID *pscid,
1265 VARIANT *pv)
1266{
1267 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1268 FIXME("(%p)\n",This);
1269
1270 return E_NOTIMPL;
1271}
1272static HRESULT WINAPI IShellFolder_fnGetDetailsOf(
1273 IShellFolder2 * iface,
1274 LPCITEMIDLIST pidl,
1275 UINT iColumn,
1276 SHELLDETAILS *psd)
1277{
1278 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1279 HRESULT hr = E_FAIL;
1280
1281 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1282
1283 if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1284
1285 if (!pidl)
1286 {
1287 /* the header titles */
1288 psd->fmt = GenericSFHeader[iColumn].fmt;
1289 psd->cxChar = GenericSFHeader[iColumn].cxChar;
1290 psd->str.uType = STRRET_CSTRA;
1291 LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
1292 return S_OK;
1293 }
1294 else
1295 {
1296 /* the data from the pidl */
1297 switch(iColumn)
1298 {
1299 case 0: /* name */
1300 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
1301 break;
1302 case 1: /* size */
1303 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
1304 break;
1305 case 2: /* type */
1306 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
1307 break;
1308 case 3: /* date */
1309 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
1310 break;
1311 case 4: /* attributes */
1312 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
1313 break;
1314 }
1315 hr = S_OK;
1316 psd->str.uType = STRRET_CSTRA;
1317 }
1318
1319 return hr;
1320}
1321static HRESULT WINAPI IShellFolder_fnMapNameToSCID(
1322 IShellFolder2 * iface,
1323 LPCWSTR pwszName,
1324 SHCOLUMNID *pscid)
1325{
1326 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1327 FIXME("(%p)\n",This);
1328 return E_NOTIMPL;
1329}
1330
1331static ICOM_VTABLE(IShellFolder2) sfvt =
1332{
1333 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1334 IShellFolder_fnQueryInterface,
1335 IShellFolder_fnAddRef,
1336 IShellFolder_fnRelease,
1337 IShellFolder_fnParseDisplayName,
1338 IShellFolder_fnEnumObjects,
1339 IShellFolder_fnBindToObject,
1340 IShellFolder_fnBindToStorage,
1341 IShellFolder_fnCompareIDs,
1342 IShellFolder_fnCreateViewObject,
1343 IShellFolder_fnGetAttributesOf,
1344 IShellFolder_fnGetUIObjectOf,
1345 IShellFolder_fnGetDisplayNameOf,
1346 IShellFolder_fnSetNameOf,
1347
1348 /* ShellFolder2 */
1349 IShellFolder_fnGetDefaultSearchGUID,
1350 IShellFolder_fnEnumSearches,
1351 IShellFolder_fnGetDefaultColumn,
1352 IShellFolder_fnGetDefaultColumnState,
1353 IShellFolder_fnGetDetailsEx,
1354 IShellFolder_fnGetDetailsOf,
1355 IShellFolder_fnMapNameToSCID
1356};
1357
1358/****************************************************************************
1359 * ISFHelper for IShellFolder implementation
1360 */
1361
1362static HRESULT WINAPI ISFHelper_fnQueryInterface(
1363 ISFHelper *iface,
1364 REFIID riid,
1365 LPVOID *ppvObj)
1366{
1367 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1368
1369 TRACE("(%p)\n", This);
1370
1371 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
1372}
1373
1374static ULONG WINAPI ISFHelper_fnAddRef(
1375 ISFHelper *iface)
1376{
1377 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1378
1379 TRACE("(%p)\n", This);
1380
1381 return IUnknown_AddRef(This->pUnkOuter);
1382}
1383
1384static ULONG WINAPI ISFHelper_fnRelease(
1385 ISFHelper *iface)
1386{
1387 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1388
1389 TRACE("(%p)\n", This);
1390
1391 return IUnknown_Release(This->pUnkOuter);
1392}
1393
1394
1395/****************************************************************************
1396 * ISFHelper_fnAddFolder
1397 *
1398 * creates a unique folder name
1399 */
1400
1401static HRESULT WINAPI ISFHelper_fnGetUniqueName(
1402 ISFHelper *iface,
1403 LPSTR lpName,
1404 UINT uLen)
1405{
1406 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1407 IEnumIDList * penum;
1408 HRESULT hr;
1409 char szText[MAX_PATH];
1410 char * szNewFolder = "New Folder";
1411
1412 TRACE("(%p)(%s %u)\n", This, lpName, uLen);
1413
1414 if (uLen < strlen(szNewFolder) + 4) return E_POINTER;
1415
1416 strcpy(lpName, szNewFolder);
1417
1418 hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
1419 if (penum)
1420 {
1421 LPITEMIDLIST pidl;
1422 DWORD dwFetched;
1423 int i=1;
1424
1425next: IEnumIDList_Reset(penum);
1426 while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched)
1427 {
1428 _ILSimpleGetText(pidl, szText, MAX_PATH);
1429 if (0 == strcasecmp(szText, lpName))
1430 {
1431 sprintf(lpName, "%s %d", szNewFolder, i++);
1432 if (i > 99)
1433 {
1434 hr = E_FAIL;
1435 break;
1436 }
1437 goto next;
1438 }
1439 }
1440
1441 IEnumIDList_Release(penum);
1442 }
1443 return hr;
1444}
1445
1446/****************************************************************************
1447 * ISFHelper_fnAddFolder
1448 *
1449 * adds a new folder.
1450 */
1451
1452static HRESULT WINAPI ISFHelper_fnAddFolder(
1453 ISFHelper *iface,
1454 HWND hwnd,
1455 LPCSTR lpName,
1456 LPITEMIDLIST* ppidlOut)
1457{
1458 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1459 char lpstrNewDir[MAX_PATH];
1460 DWORD bRes;
1461 HRESULT hres = E_FAIL;
1462
1463 TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut);
1464
1465 strcpy(lpstrNewDir, This->sMyPath);
1466 PathAddBackslashA(lpstrNewDir);
1467 strcat(lpstrNewDir, lpName);
1468
1469 bRes = CreateDirectoryA(lpstrNewDir, NULL);
1470
1471 if (bRes)
1472 {
1473 LPITEMIDLIST pidl, pidlitem;
1474
1475 pidlitem = SHSimpleIDListFromPathA(lpstrNewDir);
1476
1477 pidl = ILCombine(This->absPidl, pidlitem);
1478 SHChangeNotifyA(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
1479 SHFree(pidl);
1480
1481 if (ppidlOut) *ppidlOut = pidlitem;
1482 hres = S_OK;
1483 }
1484 else
1485 {
1486 char lpstrText[128+MAX_PATH];
1487 char lpstrTempText[128];
1488 char lpstrCaption[256];
1489
1490 /* Cannot Create folder because of permissions */
1491 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText));
1492 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption));
1493 sprintf(lpstrText,lpstrTempText, lpstrNewDir);
1494 MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
1495 }
1496
1497 return hres;
1498}
1499
1500/****************************************************************************
1501 * ISFHelper_fnDeleteItems
1502 *
1503 * deletes items in folder
1504 */
1505static HRESULT WINAPI ISFHelper_fnDeleteItems(
1506 ISFHelper *iface,
1507 UINT cidl,
1508 LPCITEMIDLIST* apidl)
1509{
1510 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1511 int i;
1512 char szPath[MAX_PATH];
1513 BOOL bConfirm = TRUE;
1514
1515 TRACE("(%p)(%u %p)\n", This, cidl, apidl);
1516
1517 /* deleting multiple items so give a slightly different warning */
1518 if(cidl != 1)
1519 {
1520 char tmp[8];
1521 snprintf(tmp, sizeof(tmp), "%d", cidl);
1522 if(!SHELL_WarnItemDelete(ASK_DELETE_MULTIPLE_ITEM, tmp))
1523 return E_FAIL;
1524 bConfirm = FALSE;
1525 }
1526
1527 for(i=0; i< cidl; i++)
1528 {
1529 strcpy(szPath, This->sMyPath);
1530 PathAddBackslashA(szPath);
1531 _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
1532
1533 if (_ILIsFolder(apidl[i]))
1534 {
1535 LPITEMIDLIST pidl;
1536 TRACE("delete %s\n", szPath);
1537 if (! SHELL_DeleteDirectoryA(szPath, bConfirm))
1538 {
1539 TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1540 return E_FAIL;
1541 }
1542 pidl = ILCombine(This->absPidl, apidl[i]);
1543 SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
1544 SHFree(pidl);
1545 }
1546 else if (_ILIsValue(apidl[i]))
1547 {
1548 LPITEMIDLIST pidl;
1549
1550 TRACE("delete %s\n", szPath);
1551 if (! SHELL_DeleteFileA(szPath, bConfirm))
1552 {
1553 TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1554 return E_FAIL;
1555 }
1556 pidl = ILCombine(This->absPidl, apidl[i]);
1557 SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1558 SHFree(pidl);
1559 }
1560
1561 }
1562 return S_OK;
1563}
1564
1565/****************************************************************************
1566 * ISFHelper_fnCopyItems
1567 *
1568 * copies items to this folder
1569 */
1570static HRESULT WINAPI ISFHelper_fnCopyItems(
1571 ISFHelper *iface,
1572 IShellFolder* pSFFrom,
1573 UINT cidl,
1574 LPCITEMIDLIST *apidl)
1575{
1576 int i;
1577 IPersistFolder2 * ppf2=NULL;
1578 char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
1579 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1580
1581 TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1582
1583 IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
1584 if (ppf2)
1585 {
1586 LPITEMIDLIST pidl;
1587 if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
1588 {
1589 for (i=0; i<cidl; i++)
1590 {
1591 SHGetPathFromIDListA(pidl, szSrcPath);
1592 PathAddBackslashA(szSrcPath);
1593 _ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
1594
1595 strcpy(szDstPath, This->sMyPath);
1596 PathAddBackslashA(szDstPath);
1597 _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
1598 MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
1599 }
1600 SHFree(pidl);
1601 }
1602 IPersistFolder2_Release(ppf2);
1603 }
1604 return S_OK;
1605}
1606
1607static ICOM_VTABLE(ISFHelper) shvt =
1608{
1609 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1610 ISFHelper_fnQueryInterface,
1611 ISFHelper_fnAddRef,
1612 ISFHelper_fnRelease,
1613 ISFHelper_fnGetUniqueName,
1614 ISFHelper_fnAddFolder,
1615 ISFHelper_fnDeleteItems,
1616 ISFHelper_fnCopyItems,
1617};
1618
1619/***********************************************************************
1620* [Desktopfolder] IShellFolder implementation
1621*/
1622static struct ICOM_VTABLE(IShellFolder2) sfdvt;
1623
1624static shvheader DesktopSFHeader [] =
1625{
1626 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
1627 { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1628 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1629 { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
1630 { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
1631};
1632#define DESKTOPSHELLVIEWCOLUMNS 5
1633
1634/**************************************************************************
1635* ISF_Desktop_Constructor
1636*
1637*/
1638IShellFolder * ISF_Desktop_Constructor()
1639{
1640 IGenericSFImpl * sf;
1641
1642 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1643 sf->ref=1;
1644 ICOM_VTBL(sf)=&unkvt;
1645 sf->lpvtblShellFolder=&sfdvt;
1646 sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1647 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
1648
1649 TRACE("(%p)\n",sf);
1650
1651 shell32_ObjCount++;
1652 return _IShellFolder_(sf);
1653}
1654
1655/**************************************************************************
1656 * ISF_Desktop_fnQueryInterface
1657 *
1658 * NOTES supports not IPersist/IPersistFolder
1659 */
1660static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1661 IShellFolder2 * iface,
1662 REFIID riid,
1663 LPVOID *ppvObj)
1664{
1665 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1666
1667 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1668
1669 *ppvObj = NULL;
1670
1671 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
1672 {
1673 *ppvObj = _IUnknown_(This);
1674 }
1675 else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
1676 {
1677 *ppvObj = _IShellFolder_(This);
1678 }
1679 else if(IsEqualIID(riid, &IID_IShellFolder2)) /*IShellFolder2*/
1680 {
1681 *ppvObj = _IShellFolder_(This);
1682 }
1683
1684 if(*ppvObj)
1685 {
1686 IUnknown_AddRef((IUnknown*)(*ppvObj));
1687 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1688 return S_OK;
1689 }
1690 TRACE("-- Interface: E_NOINTERFACE\n");
1691 return E_NOINTERFACE;
1692}
1693
1694/**************************************************************************
1695* ISF_Desktop_fnParseDisplayName
1696*
1697* NOTES
1698* "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1699* to MyComputer
1700*/
1701static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1702 IShellFolder2 * iface,
1703 HWND hwndOwner,
1704 LPBC pbcReserved,
1705 LPOLESTR lpszDisplayName,
1706 DWORD *pchEaten,
1707 LPITEMIDLIST *ppidl,
1708 DWORD *pdwAttributes)
1709{
1710 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1711
1712 LPCWSTR szNext=NULL;
1713 LPITEMIDLIST pidlTemp=NULL;
1714 HRESULT hr=E_OUTOFMEMORY;
1715
1716 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1717 This,hwndOwner,pbcReserved,lpszDisplayName,
1718 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1719
1720 *ppidl = 0;
1721 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1722
1723 /* FIXME no real parsing implemented */
1724 pidlTemp = _ILCreateMyComputer();
1725 szNext = lpszDisplayName;
1726
1727 if (szNext && *szNext)
1728 {
1729 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1730 }
1731 else
1732 {
1733 hr = S_OK;
1734
1735 if (pdwAttributes && *pdwAttributes)
1736 {
1737 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
1738 }
1739 }
1740
1741 *ppidl = pidlTemp;
1742
1743 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1744
1745 return hr;
1746}
1747
1748/**************************************************************************
1749* ISF_Desktop_fnEnumObjects
1750*/
1751static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1752 IShellFolder2 * iface,
1753 HWND hwndOwner,
1754 DWORD dwFlags,
1755 LPENUMIDLIST* ppEnumIDList)
1756{
1757 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1758
1759 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1760
1761 *ppEnumIDList = NULL;
1762 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1763
1764 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1765
1766 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1767
1768 return S_OK;
1769}
1770
1771/**************************************************************************
1772* ISF_Desktop_fnBindToObject
1773*/
1774static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
1775 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1776{
1777 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1778 GUID const * clsid;
1779 IShellFolder *pShellFolder, *pSubFolder;
1780 HRESULT hr;
1781
1782 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
1783 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
1784
1785 *ppvOut = NULL;
1786
1787 if ((clsid=_ILGetGUIDPointer(pidl)))
1788 {
1789 if ( IsEqualIID(clsid, &CLSID_MyComputer))
1790 {
1791 pShellFolder = ISF_MyComputer_Constructor();
1792 }
1793 else
1794 {
1795 /* shell extension */
1796 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1797 {
1798 return E_INVALIDARG;
1799 }
1800 }
1801 }
1802 else
1803 {
1804 /* file system folder on the desktop */
1805 LPITEMIDLIST deskpidl, firstpidl, completepidl;
1806 IPersistFolder * ppf;
1807
1808 /* combine pidls */
1809 SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
1810 firstpidl = ILCloneFirst(pidl);
1811 completepidl = ILCombine(deskpidl, firstpidl);
1812
1813 pShellFolder = IShellFolder_Constructor(NULL, NULL);
1814 if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf)))
1815 {
1816 IPersistFolder_Initialize(ppf, completepidl);
1817 IPersistFolder_Release(ppf);
1818 }
1819 ILFree(completepidl);
1820 ILFree(deskpidl);
1821 ILFree(firstpidl);
1822 }
1823
1824 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1825 {
1826 *ppvOut = pShellFolder;
1827 hr = S_OK;
1828 }
1829 else /* go deeper */
1830 {
1831 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1832 IShellFolder_Release(pShellFolder);
1833 *ppvOut = pSubFolder;
1834 }
1835
1836 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
1837
1838 return hr;
1839}
1840
1841/**************************************************************************
1842* ISF_Desktop_fnCreateViewObject
1843*/
1844static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
1845 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1846{
1847 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1848
1849 LPSHELLVIEW pShellView;
1850 HRESULT hr = E_INVALIDARG;
1851
1852 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
1853
1854 if(ppvOut)
1855 {
1856 *ppvOut = NULL;
1857
1858 if(IsEqualIID(riid, &IID_IDropTarget))
1859 {
1860 WARN("IDropTarget not implemented\n");
1861 hr = E_NOTIMPL;
1862 }
1863 else if(IsEqualIID(riid, &IID_IContextMenu))
1864 {
1865 WARN("IContextMenu not implemented\n");
1866 hr = E_NOTIMPL;
1867 }
1868 else if(IsEqualIID(riid, &IID_IShellView))
1869 {
1870 pShellView = IShellView_Constructor((IShellFolder*)iface);
1871 if(pShellView)
1872 {
1873 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1874 IShellView_Release(pShellView);
1875 }
1876 }
1877 }
1878 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1879 return hr;
1880}
1881
1882/**************************************************************************
1883* ISF_Desktop_fnGetAttributesOf
1884*/
1885static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
1886 IShellFolder2 * iface,
1887 UINT cidl,
1888 LPCITEMIDLIST *apidl,
1889 DWORD *rgfInOut)
1890{
1891 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1892
1893 HRESULT hr = S_OK;
1894
1895 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1896
1897 if ( (!cidl) || (!apidl) || (!rgfInOut))
1898 return E_INVALIDARG;
1899
1900 while (cidl > 0 && *apidl)
1901 {
1902 pdump (*apidl);
1903 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1904 apidl++;
1905 cidl--;
1906 }
1907
1908 TRACE("-- result=0x%08lx\n",*rgfInOut);
1909
1910 return hr;
1911}
1912
1913/**************************************************************************
1914* ISF_Desktop_fnGetDisplayNameOf
1915*
1916* NOTES
1917* special case: pidl = null gives desktop-name back
1918*/
1919static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1920 IShellFolder2 * iface,
1921 LPCITEMIDLIST pidl,
1922 DWORD dwFlags,
1923 LPSTRRET strRet)
1924{
1925 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1926
1927 CHAR szPath[MAX_PATH]= "";
1928
1929 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1930 pdump(pidl);
1931
1932 if(!strRet) return E_INVALIDARG;
1933
1934 if(!pidl)
1935 {
1936 HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1937 }
1938 else if ( _ILIsPidlSimple(pidl) )
1939 {
1940 _ILSimpleGetText(pidl, szPath, MAX_PATH);
1941 }
1942 else
1943 {
1944 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
1945 return E_OUTOFMEMORY;
1946 }
1947 strRet->uType = STRRET_CSTRA;
1948 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1949
1950
1951 TRACE("-- (%p)->(%s)\n", This, szPath);
1952 return S_OK;
1953}
1954
1955static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
1956 IShellFolder2 * iface,
1957 GUID *pguid)
1958{
1959 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1960 FIXME("(%p)\n",This);
1961 return E_NOTIMPL;
1962}
1963static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
1964 IShellFolder2 * iface,
1965 IEnumExtraSearch **ppenum)
1966{
1967 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1968 FIXME("(%p)\n",This);
1969 return E_NOTIMPL;
1970}
1971static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
1972 IShellFolder2 * iface,
1973 DWORD dwRes,
1974 ULONG *pSort,
1975 ULONG *pDisplay)
1976{
1977 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1978
1979 TRACE("(%p)\n",This);
1980
1981 if (pSort) *pSort = 0;
1982 if (pDisplay) *pDisplay = 0;
1983
1984 return S_OK;
1985}
1986static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
1987 IShellFolder2 * iface,
1988 UINT iColumn,
1989 DWORD *pcsFlags)
1990{
1991 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1992
1993 TRACE("(%p)\n",This);
1994
1995 if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1996
1997 *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
1998
1999 return S_OK;
2000}
2001static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
2002 IShellFolder2 * iface,
2003 LPCITEMIDLIST pidl,
2004 const SHCOLUMNID *pscid,
2005 VARIANT *pv)
2006{
2007 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2008 FIXME("(%p)\n",This);
2009
2010 return E_NOTIMPL;
2011}
2012static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
2013 IShellFolder2 * iface,
2014 LPCITEMIDLIST pidl,
2015 UINT iColumn,
2016 SHELLDETAILS *psd)
2017{
2018 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2019 HRESULT hr = E_FAIL;;
2020
2021 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2022
2023 if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2024
2025 if (!pidl)
2026 {
2027 psd->fmt = DesktopSFHeader[iColumn].fmt;
2028 psd->cxChar = DesktopSFHeader[iColumn].cxChar;
2029 psd->str.uType = STRRET_CSTRA;
2030 LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2031 return S_OK;
2032 }
2033 else
2034 {
2035 /* the data from the pidl */
2036 switch(iColumn)
2037 {
2038 case 0: /* name */
2039 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2040 break;
2041 case 1: /* size */
2042 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
2043 break;
2044 case 2: /* type */
2045 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2046 break;
2047 case 3: /* date */
2048 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
2049 break;
2050 case 4: /* attributes */
2051 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
2052 break;
2053 }
2054 hr = S_OK;
2055 psd->str.uType = STRRET_CSTRA;
2056 }
2057
2058 return hr;
2059}
2060static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
2061 IShellFolder2 * iface,
2062 LPCWSTR pwszName,
2063 SHCOLUMNID *pscid)
2064{
2065 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2066 FIXME("(%p)\n",This);
2067 return E_NOTIMPL;
2068}
2069
2070static ICOM_VTABLE(IShellFolder2) sfdvt =
2071{
2072 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2073 ISF_Desktop_fnQueryInterface,
2074 IShellFolder_fnAddRef,
2075 IShellFolder_fnRelease,
2076 ISF_Desktop_fnParseDisplayName,
2077 ISF_Desktop_fnEnumObjects,
2078 ISF_Desktop_fnBindToObject,
2079 IShellFolder_fnBindToStorage,
2080 IShellFolder_fnCompareIDs,
2081 ISF_Desktop_fnCreateViewObject,
2082 ISF_Desktop_fnGetAttributesOf,
2083 IShellFolder_fnGetUIObjectOf,
2084 ISF_Desktop_fnGetDisplayNameOf,
2085 IShellFolder_fnSetNameOf,
2086
2087 /* ShellFolder2 */
2088 ISF_Desktop_fnGetDefaultSearchGUID,
2089 ISF_Desktop_fnEnumSearches,
2090 ISF_Desktop_fnGetDefaultColumn,
2091 ISF_Desktop_fnGetDefaultColumnState,
2092 ISF_Desktop_fnGetDetailsEx,
2093 ISF_Desktop_fnGetDetailsOf,
2094 ISF_Desktop_fnMapNameToSCID
2095};
2096
2097
2098/***********************************************************************
2099* IShellFolder [MyComputer] implementation
2100*/
2101
2102static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
2103
2104static shvheader MyComputerSFHeader [] =
2105{
2106 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
2107 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2108 { IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2109 { IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2110};
2111#define MYCOMPUTERSHELLVIEWCOLUMNS 4
2112
2113/**************************************************************************
2114* ISF_MyComputer_Constructor
2115*/
2116static IShellFolder * ISF_MyComputer_Constructor(void)
2117{
2118 IGenericSFImpl * sf;
2119
2120 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
2121 sf->ref=1;
2122
2123 ICOM_VTBL(sf)=&unkvt;
2124 sf->lpvtblShellFolder=&sfmcvt;
2125 sf->lpvtblPersistFolder2 = &psfvt;
2126 sf->pclsid = (CLSID*)&CLSID_SFMyComp;
2127 sf->absPidl=_ILCreateMyComputer(); /* my qualified pidl */
2128 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
2129
2130 TRACE("(%p)\n",sf);
2131
2132 shell32_ObjCount++;
2133 return _IShellFolder_(sf);
2134}
2135
2136/**************************************************************************
2137* ISF_MyComputer_fnParseDisplayName
2138*/
2139static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
2140 IShellFolder2 * iface,
2141 HWND hwndOwner,
2142 LPBC pbcReserved,
2143 LPOLESTR lpszDisplayName,
2144 DWORD *pchEaten,
2145 LPITEMIDLIST *ppidl,
2146 DWORD *pdwAttributes)
2147{
2148 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2149
2150 HRESULT hr = E_OUTOFMEMORY;
2151 LPCWSTR szNext=NULL;
2152 WCHAR szElement[MAX_PATH];
2153 CHAR szTempA[MAX_PATH];
2154 LPITEMIDLIST pidlTemp;
2155
2156 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
2157 This,hwndOwner,pbcReserved,lpszDisplayName,
2158 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
2159
2160 *ppidl = 0;
2161 if (pchEaten) *pchEaten = 0; /* strange but like the original */
2162
2163 /* do we have an absolute path name ? */
2164 if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
2165 lpszDisplayName[2] == (WCHAR)'\\')
2166 {
2167 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
2168 WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
2169 pidlTemp = _ILCreateDrive(szTempA);
2170
2171 if (szNext && *szNext)
2172 {
2173 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
2174 }
2175 else
2176 {
2177 if (pdwAttributes && *pdwAttributes)
2178 {
2179 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
2180 }
2181 hr = S_OK;
2182 }
2183 *ppidl = pidlTemp;
2184 }
2185
2186 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
2187
2188 return hr;
2189}
2190
2191/**************************************************************************
2192* ISF_MyComputer_fnEnumObjects
2193*/
2194static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
2195 IShellFolder2 * iface,
2196 HWND hwndOwner,
2197 DWORD dwFlags,
2198 LPENUMIDLIST* ppEnumIDList)
2199{
2200 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2201
2202 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
2203
2204 *ppEnumIDList = NULL;
2205 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
2206
2207 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
2208
2209 if(!*ppEnumIDList) return E_OUTOFMEMORY;
2210
2211 return S_OK;
2212}
2213
2214/**************************************************************************
2215* ISF_MyComputer_fnBindToObject
2216*/
2217static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
2218 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
2219{
2220 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2221 GUID const * clsid;
2222 IShellFolder *pShellFolder, *pSubFolder;
2223 LPITEMIDLIST pidltemp;
2224 HRESULT hr;
2225
2226 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
2227 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
2228
2229 if(!pidl || !ppvOut) return E_INVALIDARG;
2230
2231 *ppvOut = NULL;
2232
2233 if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
2234 {
2235 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
2236 {
2237 return E_FAIL;
2238 }
2239 }
2240 else
2241 {
2242 if (!_ILIsDrive(pidl)) return E_INVALIDARG;
2243
2244 pidltemp = ILCloneFirst(pidl);
2245 pShellFolder = IShellFolder_Constructor(iface, pidltemp);
2246 ILFree(pidltemp);
2247 }
2248
2249 if (_ILIsPidlSimple(pidl)) /* no sub folders */
2250 {
2251 *ppvOut = pShellFolder;
2252 hr = S_OK;
2253 }
2254 else /* go deeper */
2255 {
2256 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL,
2257 riid, (LPVOID)&pSubFolder);
2258 IShellFolder_Release(pShellFolder);
2259 *ppvOut = pSubFolder;
2260 }
2261
2262 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
2263
2264 return hr;
2265}
2266
2267/**************************************************************************
2268* ISF_MyComputer_fnCreateViewObject
2269*/
2270static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
2271 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
2272{
2273 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2274
2275 LPSHELLVIEW pShellView;
2276 HRESULT hr = E_INVALIDARG;
2277
2278 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
2279
2280 if(ppvOut)
2281 {
2282 *ppvOut = NULL;
2283
2284 if(IsEqualIID(riid, &IID_IDropTarget))
2285 {
2286 WARN("IDropTarget not implemented\n");
2287 hr = E_NOTIMPL;
2288 }
2289 else if(IsEqualIID(riid, &IID_IContextMenu))
2290 {
2291 WARN("IContextMenu not implemented\n");
2292 hr = E_NOTIMPL;
2293 }
2294 else if(IsEqualIID(riid, &IID_IShellView))
2295 {
2296 pShellView = IShellView_Constructor((IShellFolder*)iface);
2297 if(pShellView)
2298 {
2299 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
2300 IShellView_Release(pShellView);
2301 }
2302 }
2303 }
2304 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
2305 return hr;
2306}
2307
2308/**************************************************************************
2309* ISF_MyComputer_fnGetAttributesOf
2310*/
2311static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
2312 IShellFolder2 * iface,
2313 UINT cidl,
2314 LPCITEMIDLIST *apidl,
2315 DWORD *rgfInOut)
2316{
2317 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2318
2319 HRESULT hr = S_OK;
2320
2321 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
2322
2323 if ( (!cidl) || (!apidl) || (!rgfInOut))
2324 return E_INVALIDARG;
2325
2326 while (cidl > 0 && *apidl)
2327 {
2328 pdump (*apidl);
2329 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
2330 apidl++;
2331 cidl--;
2332 }
2333
2334 TRACE("-- result=0x%08lx\n",*rgfInOut);
2335 return hr;
2336}
2337
2338/**************************************************************************
2339* ISF_MyComputer_fnGetDisplayNameOf
2340*
2341* NOTES
2342* The desktopfolder creates only complete paths (SHGDN_FORPARSING).
2343* SHGDN_INFOLDER makes no sense.
2344*/
2345static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
2346 IShellFolder2 * iface,
2347 LPCITEMIDLIST pidl,
2348 DWORD dwFlags,
2349 LPSTRRET strRet)
2350{
2351 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2352
2353 char szPath[MAX_PATH], szDrive[18];
2354 int len = 0;
2355 BOOL bSimplePidl;
2356
2357 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
2358 pdump(pidl);
2359
2360 if(!strRet) return E_INVALIDARG;
2361
2362 szPath[0]=0x00; szDrive[0]=0x00;
2363
2364
2365 bSimplePidl = _ILIsPidlSimple(pidl);
2366
2367 if (_ILIsSpecialFolder(pidl))
2368 {
2369 /* take names of special folders only if its only this folder */
2370 if ( bSimplePidl )
2371 {
2372 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2373 }
2374 }
2375 else
2376 {
2377 if (!_ILIsDrive(pidl))
2378 {
2379 ERR("Wrong pidl type\n");
2380 return E_INVALIDARG;
2381 }
2382
2383 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2384
2385 /* long view "lw_name (C:)" */
2386 if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
2387 {
2388 DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
2389
2390#ifdef __WIN32OS2__
2391//CB: floppy drives have a fixed name
2392 if ((szPath[0] == 'A') || (szPath[0] == 'a') || (szPath[0] == 'B') || (szPath[0] == 'b'))
2393 {
2394 //floppy
2395 strncpy(szDrive,szPath,2);
2396 //3.5 floppy
2397 LoadStringA(shell32_hInstance,IDS_35FLOPPY,szPath,sizeof(szPath)-10);
2398 //CB: todo: 5.25 floppy check
2399 strcat(szPath," (");
2400 strncat(szPath,szDrive,2);
2401 strcat(szPath,")");
2402 } else
2403 {
2404 GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2405 strcat (szDrive," (");
2406 strncat (szDrive, szPath, 2);
2407 strcat (szDrive,")");
2408 strcpy (szPath, szDrive);
2409 }
2410#else
2411 GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2412 strcat (szDrive," (");
2413 strncat (szDrive, szPath, 2);
2414 strcat (szDrive,")");
2415 strcpy (szPath, szDrive);
2416#endif
2417 }
2418 }
2419
2420 if (!bSimplePidl) /* go deeper if needed */
2421 {
2422 PathAddBackslashA(szPath);
2423 len = strlen(szPath);
2424
2425 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
2426 return E_OUTOFMEMORY;
2427 }
2428 strRet->uType = STRRET_CSTRA;
2429 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
2430
2431
2432 TRACE("-- (%p)->(%s)\n", This, szPath);
2433 return S_OK;
2434}
2435
2436static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
2437 IShellFolder2 * iface,
2438 GUID *pguid)
2439{
2440 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2441 FIXME("(%p)\n",This);
2442 return E_NOTIMPL;
2443}
2444static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
2445 IShellFolder2 * iface,
2446 IEnumExtraSearch **ppenum)
2447{
2448 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2449 FIXME("(%p)\n",This);
2450 return E_NOTIMPL;
2451}
2452static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
2453 IShellFolder2 * iface,
2454 DWORD dwRes,
2455 ULONG *pSort,
2456 ULONG *pDisplay)
2457{
2458 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2459
2460 TRACE("(%p)\n",This);
2461
2462 if (pSort) *pSort = 0;
2463 if (pDisplay) *pDisplay = 0;
2464
2465 return S_OK;
2466}
2467static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
2468 IShellFolder2 * iface,
2469 UINT iColumn,
2470 DWORD *pcsFlags)
2471{
2472 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2473
2474 TRACE("(%p)\n",This);
2475
2476 if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2477
2478 *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
2479
2480 return S_OK;
2481}
2482static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
2483 IShellFolder2 * iface,
2484 LPCITEMIDLIST pidl,
2485 const SHCOLUMNID *pscid,
2486 VARIANT *pv)
2487{
2488 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2489 FIXME("(%p)\n",This);
2490
2491 return E_NOTIMPL;
2492}
2493
2494/* fixme: drive size >4GB is rolling over */
2495static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
2496 IShellFolder2 * iface,
2497 LPCITEMIDLIST pidl,
2498 UINT iColumn,
2499 SHELLDETAILS *psd)
2500{
2501 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2502 HRESULT hr;
2503
2504 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2505
2506 if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2507
2508 if (!pidl)
2509 {
2510 psd->fmt = MyComputerSFHeader[iColumn].fmt;
2511 psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
2512 psd->str.uType = STRRET_CSTRA;
2513 LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2514 return S_OK;
2515 }
2516 else
2517 {
2518 char szPath[MAX_PATH];
2519 ULARGE_INTEGER ulBytes;
2520
2521 psd->str.u.cStr[0] = 0x00;
2522 psd->str.uType = STRRET_CSTRA;
2523 switch(iColumn)
2524 {
2525 case 0: /* name */
2526 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2527 break;
2528 case 1: /* type */
2529 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2530 break;
2531 case 2: /* total size */
2532 if (_ILIsDrive(pidl))
2533 {
2534 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2535 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
2536 StrFormatByteSizeA(ulBytes.LowPart, psd->str.u.cStr, MAX_PATH);
2537 }
2538 break;
2539 case 3: /* free size */
2540 if (_ILIsDrive(pidl))
2541 {
2542 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2543 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
2544 StrFormatByteSizeA(ulBytes.LowPart, psd->str.u.cStr, MAX_PATH);
2545 }
2546 break;
2547 }
2548 hr = S_OK;
2549 }
2550
2551 return hr;
2552}
2553static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
2554 IShellFolder2 * iface,
2555 LPCWSTR pwszName,
2556 SHCOLUMNID *pscid)
2557{
2558 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2559 FIXME("(%p)\n",This);
2560 return E_NOTIMPL;
2561}
2562
2563static ICOM_VTABLE(IShellFolder2) sfmcvt =
2564{
2565 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2566 IShellFolder_fnQueryInterface,
2567 IShellFolder_fnAddRef,
2568 IShellFolder_fnRelease,
2569 ISF_MyComputer_fnParseDisplayName,
2570 ISF_MyComputer_fnEnumObjects,
2571 ISF_MyComputer_fnBindToObject,
2572 IShellFolder_fnBindToStorage,
2573 IShellFolder_fnCompareIDs,
2574 ISF_MyComputer_fnCreateViewObject,
2575 ISF_MyComputer_fnGetAttributesOf,
2576 IShellFolder_fnGetUIObjectOf,
2577 ISF_MyComputer_fnGetDisplayNameOf,
2578 IShellFolder_fnSetNameOf,
2579
2580 /* ShellFolder2 */
2581 ISF_MyComputer_fnGetDefaultSearchGUID,
2582 ISF_MyComputer_fnEnumSearches,
2583 ISF_MyComputer_fnGetDefaultColumn,
2584 ISF_MyComputer_fnGetDefaultColumnState,
2585 ISF_MyComputer_fnGetDetailsEx,
2586 ISF_MyComputer_fnGetDetailsOf,
2587 ISF_MyComputer_fnMapNameToSCID
2588};
2589
2590
2591/************************************************************************
2592 * ISFPersistFolder_QueryInterface (IUnknown)
2593 *
2594 */
2595static HRESULT WINAPI ISFPersistFolder2_QueryInterface(
2596 IPersistFolder2 * iface,
2597 REFIID iid,
2598 LPVOID* ppvObj)
2599{
2600 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2601
2602 TRACE("(%p)\n", This);
2603
2604 return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
2605}
2606
2607/************************************************************************
2608 * ISFPersistFolder_AddRef (IUnknown)
2609 *
2610 */
2611static ULONG WINAPI ISFPersistFolder2_AddRef(
2612 IPersistFolder2 * iface)
2613{
2614 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2615
2616 TRACE("(%p)\n", This);
2617
2618 return IUnknown_AddRef(This->pUnkOuter);
2619}
2620
2621/************************************************************************
2622 * ISFPersistFolder_Release (IUnknown)
2623 *
2624 */
2625static ULONG WINAPI ISFPersistFolder2_Release(
2626 IPersistFolder2 * iface)
2627{
2628 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2629
2630 TRACE("(%p)\n", This);
2631
2632 return IUnknown_Release(This->pUnkOuter);
2633}
2634
2635/************************************************************************
2636 * ISFPersistFolder_GetClassID (IPersist)
2637 */
2638static HRESULT WINAPI ISFPersistFolder2_GetClassID(
2639 IPersistFolder2 * iface,
2640 CLSID * lpClassId)
2641{
2642 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2643
2644 TRACE("(%p)\n", This);
2645
2646 if (!lpClassId) return E_POINTER;
2647 *lpClassId = *This->pclsid;
2648
2649 return S_OK;
2650}
2651
2652/************************************************************************
2653 * ISFPersistFolder_Initialize (IPersistFolder)
2654 *
2655 * NOTES
2656 * sMyPath is not set. Don't know how to handle in a non rooted environment.
2657 */
2658static HRESULT WINAPI ISFPersistFolder2_Initialize(
2659 IPersistFolder2 * iface,
2660 LPCITEMIDLIST pidl)
2661{
2662 char sTemp[MAX_PATH];
2663 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2664
2665 TRACE("(%p)->(%p)\n", This, pidl);
2666
2667 /* free the old stuff */
2668 if(This->absPidl)
2669 {
2670 SHFree(This->absPidl);
2671 This->absPidl = NULL;
2672 }
2673 if(This->sMyPath)
2674 {
2675 SHFree(This->sMyPath);
2676 This->sMyPath = NULL;
2677 }
2678
2679 /* set my pidl */
2680 This->absPidl = ILClone(pidl);
2681
2682 /* set my path */
2683 if (SHGetPathFromIDListA(pidl, sTemp))
2684 {
2685 This->sMyPath = SHAlloc(strlen(sTemp)+1);
2686 strcpy(This->sMyPath, sTemp);
2687 }
2688
2689 TRACE("--(%p)->(%s)\n", This, This->sMyPath);
2690
2691 return S_OK;
2692}
2693
2694/**************************************************************************
2695* IPersistFolder2_fnGetCurFolder
2696*/
2697static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder(
2698 IPersistFolder2 * iface,
2699 LPITEMIDLIST * pidl)
2700{
2701 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2702
2703 TRACE("(%p)->(%p)\n",This, pidl);
2704
2705 if (!pidl) return E_POINTER;
2706
2707 *pidl = ILClone(This->absPidl);
2708
2709 return S_OK;
2710}
2711
2712static ICOM_VTABLE(IPersistFolder2) psfvt =
2713{
2714 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2715 ISFPersistFolder2_QueryInterface,
2716 ISFPersistFolder2_AddRef,
2717 ISFPersistFolder2_Release,
2718 ISFPersistFolder2_GetClassID,
2719 ISFPersistFolder2_Initialize,
2720 ISFPersistFolder2_fnGetCurFolder
2721};
2722
2723/****************************************************************************
2724 * ISFDropTarget implementation
2725 */
2726static BOOL ISFDropTarget_QueryDrop(
2727 IDropTarget *iface,
2728 DWORD dwKeyState,
2729 LPDWORD pdwEffect)
2730{
2731 DWORD dwEffect = *pdwEffect;
2732
2733 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2734
2735 *pdwEffect = DROPEFFECT_NONE;
2736
2737 if (This->fAcceptFmt)
2738 { /* Does our interpretation of the keystate ... */
2739 *pdwEffect = KeyStateToDropEffect(dwKeyState);
2740
2741 /* ... matches the desired effect ? */
2742 if (dwEffect & *pdwEffect)
2743 {
2744 return TRUE;
2745 }
2746 }
2747 return FALSE;
2748}
2749
2750static HRESULT WINAPI ISFDropTarget_QueryInterface(
2751 IDropTarget *iface,
2752 REFIID riid,
2753 LPVOID *ppvObj)
2754{
2755 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2756
2757 TRACE("(%p)\n", This);
2758
2759 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
2760}
2761
2762static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
2763{
2764 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2765
2766 TRACE("(%p)\n", This);
2767
2768 return IUnknown_AddRef(This->pUnkOuter);
2769}
2770
2771static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
2772{
2773 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2774
2775 TRACE("(%p)\n", This);
2776
2777 return IUnknown_Release(This->pUnkOuter);
2778}
2779
2780static HRESULT WINAPI ISFDropTarget_DragEnter(
2781 IDropTarget *iface,
2782 IDataObject *pDataObject,
2783 DWORD dwKeyState,
2784 POINTL pt,
2785 DWORD *pdwEffect)
2786{
2787 FORMATETC fmt;
2788
2789 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2790
2791 TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
2792
2793 InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
2794
2795 This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
2796
2797 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2798
2799 return S_OK;
2800}
2801
2802static HRESULT WINAPI ISFDropTarget_DragOver(
2803 IDropTarget *iface,
2804 DWORD dwKeyState,
2805 POINTL pt,
2806 DWORD *pdwEffect)
2807{
2808 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2809
2810 TRACE("(%p)\n",This);
2811
2812 if(!pdwEffect) return E_INVALIDARG;
2813
2814 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2815
2816 return S_OK;
2817}
2818
2819static HRESULT WINAPI ISFDropTarget_DragLeave(
2820 IDropTarget *iface)
2821{
2822 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2823
2824 TRACE("(%p)\n",This);
2825
2826 This->fAcceptFmt = FALSE;
2827
2828 return S_OK;
2829}
2830
2831static HRESULT WINAPI ISFDropTarget_Drop(
2832 IDropTarget *iface,
2833 IDataObject* pDataObject,
2834 DWORD dwKeyState,
2835 POINTL pt,
2836 DWORD *pdwEffect)
2837{
2838 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2839
2840 FIXME("(%p) object dropped\n",This);
2841
2842 return E_NOTIMPL;
2843}
2844
2845static struct ICOM_VTABLE(IDropTarget) dtvt =
2846{
2847 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2848 ISFDropTarget_QueryInterface,
2849 ISFDropTarget_AddRef,
2850 ISFDropTarget_Release,
2851 ISFDropTarget_DragEnter,
2852 ISFDropTarget_DragOver,
2853 ISFDropTarget_DragLeave,
2854 ISFDropTarget_Drop
2855};
Note: See TracBrowser for help on using the repository browser.