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

Last change on this file since 10010 was 9885, checked in by sandervl, 22 years ago

DT: minor updates

File size: 72.5 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 "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#ifdef __WIN32OS2__
902 //SvL: shortcut for efficiency. might have to remove it
903 // in the future if this method is changed
904 pidl2 = ILGetNext(pidl2);
905
906 nReturn = IShellFolder_CompareIDs(iface, 0, pidl1, pidl2);
907 hr = ResultFromShort(nReturn);
908#else
909 pidlTemp = ILCloneFirst(pidl1);
910 pidl2 = ILGetNext(pidl2);
911
912 hr = IShellFolder_BindToObject(iface, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
913 if (SUCCEEDED(hr))
914 {
915 nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
916 IShellFolder_Release(psf);
917 hr = ResultFromShort(nReturn);
918 }
919 ILFree(pidlTemp);
920#endif
921 }
922 else
923 {
924 pidl2 = ILGetNext(pidl2);
925 if (pidl2 && pidl2->mkid.cb) /* go deeper on #2 ? */
926 hr = ResultFromShort(-1); /* two different */
927 else
928 hr = ResultFromShort(nReturn); /* two equal simple pidls */
929 }
930 }
931 else
932 {
933 hr = ResultFromShort(nReturn); /* two different simple pidls */
934 }
935 }
936 }
937
938 TRACE("-- res=0x%08lx\n", hr);
939 return hr;
940}
941
942/**************************************************************************
943* IShellFolder_fnCreateViewObject
944*/
945static HRESULT WINAPI IShellFolder_fnCreateViewObject(
946 IShellFolder2 * iface,
947 HWND hwndOwner,
948 REFIID riid,
949 LPVOID *ppvOut)
950{
951 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
952
953 LPSHELLVIEW pShellView;
954 HRESULT hr = E_INVALIDARG;
955
956 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
957
958 if(ppvOut)
959 {
960 *ppvOut = NULL;
961
962 if(IsEqualIID(riid, &IID_IDropTarget))
963 {
964 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, ppvOut);
965 }
966 else if(IsEqualIID(riid, &IID_IContextMenu))
967 {
968 FIXME("IContextMenu not implemented\n");
969 hr = E_NOTIMPL;
970 }
971 else if(IsEqualIID(riid, &IID_IShellView))
972 {
973 pShellView = IShellView_Constructor((IShellFolder*)iface);
974 if(pShellView)
975 {
976 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
977 IShellView_Release(pShellView);
978 }
979 }
980 }
981 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
982 return hr;
983}
984
985/**************************************************************************
986* IShellFolder_fnGetAttributesOf
987*
988* PARAMETERS
989* UINT cidl, //[in ] num elements in pidl array
990* LPCITEMIDLIST* apidl, //[in ] simple pidl array
991* ULONG* rgfInOut) //[out] result array
992*
993*/
994static HRESULT WINAPI IShellFolder_fnGetAttributesOf(
995 IShellFolder2 * iface,
996 UINT cidl,
997 LPCITEMIDLIST *apidl,
998 DWORD *rgfInOut)
999{
1000 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1001
1002 HRESULT hr = S_OK;
1003
1004 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
1005
1006 if ( (!cidl) || (!apidl) || (!rgfInOut))
1007 return E_INVALIDARG;
1008
1009 while (cidl > 0 && *apidl)
1010 {
1011 pdump (*apidl);
1012 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1013 apidl++;
1014 cidl--;
1015 }
1016
1017 TRACE("-- result=0x%08lx\n",*rgfInOut);
1018
1019 return hr;
1020}
1021/**************************************************************************
1022* IShellFolder_fnGetUIObjectOf
1023*
1024* PARAMETERS
1025* HWND hwndOwner, //[in ] Parent window for any output
1026* UINT cidl, //[in ] array size
1027* LPCITEMIDLIST* apidl, //[in ] simple pidl array
1028* REFIID riid, //[in ] Requested Interface
1029* UINT* prgfInOut, //[ ] reserved
1030* LPVOID* ppvObject) //[out] Resulting Interface
1031*
1032* NOTES
1033* This function gets asked to return "view objects" for one or more (multiple select)
1034* items:
1035* The viewobject typically is an COM object with one of the following interfaces:
1036* IExtractIcon,IDataObject,IContextMenu
1037* In order to support icon positions in the default Listview your DataObject
1038* must implement the SetData method (in addition to GetData :) - the shell passes
1039* a barely documented "Icon positions" structure to SetData when the drag starts,
1040* and GetData's it if the drop is in another explorer window that needs the positions.
1041*/
1042static HRESULT WINAPI IShellFolder_fnGetUIObjectOf(
1043 IShellFolder2 * iface,
1044 HWND hwndOwner,
1045 UINT cidl,
1046 LPCITEMIDLIST * apidl,
1047 REFIID riid,
1048 UINT * prgfInOut,
1049 LPVOID * ppvOut)
1050{
1051 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1052
1053 LPITEMIDLIST pidl;
1054 IUnknown* pObj = NULL;
1055 HRESULT hr = E_INVALIDARG;
1056
1057 TRACE("(%p)->(0x%04x,%u,apidl=%p,\n\tIID:%s,%p,%p)\n",
1058 This,hwndOwner,cidl,apidl,debugstr_guid(riid),prgfInOut,ppvOut);
1059
1060 if (ppvOut)
1061 {
1062 *ppvOut = NULL;
1063
1064 if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
1065 {
1066 pObj = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl);
1067 hr = S_OK;
1068 }
1069 else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
1070 {
1071 pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
1072 hr = S_OK;
1073 }
1074 else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
1075 {
1076 pidl = ILCombine(This->absPidl,apidl[0]);
1077 pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
1078 SHFree(pidl);
1079 hr = S_OK;
1080 }
1081 else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
1082 {
1083 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pObj);
1084 }
1085 else
1086 {
1087 hr = E_NOINTERFACE;
1088 }
1089
1090 if(!pObj)
1091 hr = E_OUTOFMEMORY;
1092
1093 *ppvOut = pObj;
1094 }
1095 TRACE("(%p)->hr=0x%08lx\n",This, hr);
1096 return hr;
1097}
1098
1099/**************************************************************************
1100* IShellFolder_fnGetDisplayNameOf
1101* Retrieves the display name for the specified file object or subfolder
1102*
1103* PARAMETERS
1104* LPCITEMIDLIST pidl, //[in ] complex pidl to item
1105* DWORD dwFlags, //[in ] SHGNO formatting flags
1106* LPSTRRET lpName) //[out] Returned display name
1107*
1108* FIXME
1109* if the name is in the pidl the ret value should be a STRRET_OFFSET
1110*/
1111#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
1112#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
1113
1114static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
1115 IShellFolder2 * iface,
1116 LPCITEMIDLIST pidl,
1117 DWORD dwFlags,
1118 LPSTRRET strRet)
1119{
1120 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1121
1122 CHAR szPath[MAX_PATH]= "";
1123 int len = 0;
1124 BOOL bSimplePidl;
1125
1126 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1127 pdump(pidl);
1128
1129 if(!pidl || !strRet) return E_INVALIDARG;
1130
1131 bSimplePidl = _ILIsPidlSimple(pidl);
1132
1133 /* take names of special folders only if its only this folder */
1134 if (_ILIsSpecialFolder(pidl))
1135 {
1136 if ( bSimplePidl)
1137 {
1138 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1139 }
1140 }
1141 else
1142 {
1143 if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
1144 {
1145 strcpy (szPath, This->sMyPath); /* get path to root*/
1146 PathAddBackslashA(szPath);
1147 len = strlen(szPath);
1148 }
1149 _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
1150 }
1151
1152 if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl) /* go deeper if needed */
1153 {
1154 PathAddBackslashA(szPath);
1155 len = strlen(szPath);
1156
1157 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath + len, MAX_PATH - len)))
1158 return E_OUTOFMEMORY;
1159 }
1160 strRet->uType = STRRET_CSTRA;
1161 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1162
1163 TRACE("-- (%p)->(%s)\n", This, szPath);
1164 return S_OK;
1165}
1166
1167/**************************************************************************
1168* IShellFolder_fnSetNameOf
1169* Changes the name of a file object or subfolder, possibly changing its item
1170* identifier in the process.
1171*
1172* PARAMETERS
1173* HWND hwndOwner, //[in ] Owner window for output
1174* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
1175* LPCOLESTR lpszName, //[in ] the items new display name
1176* DWORD dwFlags, //[in ] SHGNO formatting flags
1177* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
1178*/
1179static HRESULT WINAPI IShellFolder_fnSetNameOf(
1180 IShellFolder2 * iface,
1181 HWND hwndOwner,
1182 LPCITEMIDLIST pidl, /*simple pidl*/
1183 LPCOLESTR lpName,
1184 DWORD dwFlags,
1185 LPITEMIDLIST *pPidlOut)
1186{
1187 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1188 char szSrc[MAX_PATH], szDest[MAX_PATH];
1189 int len;
1190 BOOL bIsFolder = _ILIsFolder(ILFindLastID(pidl));
1191
1192 TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p)\n",
1193 This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut);
1194
1195 /* build source path */
1196 if (dwFlags & SHGDN_INFOLDER)
1197 {
1198#ifdef __WIN32OS2__
1199 //@PF Block 'My Computer' and other stuff from crashing us
1200 if (!This->sMyPath) return E_FAIL;
1201#endif
1202 strcpy(szSrc, This->sMyPath);
1203 PathAddBackslashA(szSrc);
1204 len = strlen (szSrc);
1205 _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len);
1206 }
1207 else
1208 {
1209 SHGetPathFromIDListA(pidl, szSrc);
1210 }
1211
1212 /* build destination path */
1213 strcpy(szDest, This->sMyPath);
1214 PathAddBackslashA(szDest);
1215 len = strlen (szDest);
1216 WideCharToMultiByte( CP_ACP, 0, lpName, -1, szDest+len, MAX_PATH-len, NULL, NULL );
1217 szDest[MAX_PATH-1] = 0;
1218 TRACE("src=%s dest=%s\n", szSrc, szDest);
1219 if ( MoveFileA(szSrc, szDest) )
1220 {
1221 if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest);
1222 SHChangeNotify( bIsFolder?SHCNE_RENAMEFOLDER:SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
1223 return S_OK;
1224 }
1225 return E_FAIL;
1226}
1227
1228static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(
1229 IShellFolder2 * iface,
1230 GUID *pguid)
1231{
1232 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1233 FIXME("(%p)\n",This);
1234 return E_NOTIMPL;
1235}
1236static HRESULT WINAPI IShellFolder_fnEnumSearches(
1237 IShellFolder2 * iface,
1238 IEnumExtraSearch **ppenum)
1239{
1240 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1241 FIXME("(%p)\n",This);
1242 return E_NOTIMPL;
1243}
1244static HRESULT WINAPI IShellFolder_fnGetDefaultColumn(
1245 IShellFolder2 * iface,
1246 DWORD dwRes,
1247 ULONG *pSort,
1248 ULONG *pDisplay)
1249{
1250 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1251
1252 TRACE("(%p)\n",This);
1253
1254 if (pSort) *pSort = 0;
1255 if (pDisplay) *pDisplay = 0;
1256
1257 return S_OK;
1258}
1259static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState(
1260 IShellFolder2 * iface,
1261 UINT iColumn,
1262 DWORD *pcsFlags)
1263{
1264 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1265
1266 TRACE("(%p)\n",This);
1267
1268 if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1269
1270 *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
1271
1272 return S_OK;
1273}
1274static HRESULT WINAPI IShellFolder_fnGetDetailsEx(
1275 IShellFolder2 * iface,
1276 LPCITEMIDLIST pidl,
1277 const SHCOLUMNID *pscid,
1278 VARIANT *pv)
1279{
1280 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1281 FIXME("(%p)\n",This);
1282
1283 return E_NOTIMPL;
1284}
1285static HRESULT WINAPI IShellFolder_fnGetDetailsOf(
1286 IShellFolder2 * iface,
1287 LPCITEMIDLIST pidl,
1288 UINT iColumn,
1289 SHELLDETAILS *psd)
1290{
1291 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1292 HRESULT hr = E_FAIL;
1293
1294 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1295
1296 if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1297
1298 if (!pidl)
1299 {
1300 /* the header titles */
1301 psd->fmt = GenericSFHeader[iColumn].fmt;
1302 psd->cxChar = GenericSFHeader[iColumn].cxChar;
1303 psd->str.uType = STRRET_CSTRA;
1304 LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
1305 return S_OK;
1306 }
1307 else
1308 {
1309 /* the data from the pidl */
1310 switch(iColumn)
1311 {
1312 case 0: /* name */
1313 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
1314 break;
1315 case 1: /* size */
1316 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
1317 break;
1318 case 2: /* type */
1319 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
1320 break;
1321 case 3: /* date */
1322 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
1323 break;
1324 case 4: /* attributes */
1325 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
1326 break;
1327 }
1328 hr = S_OK;
1329 psd->str.uType = STRRET_CSTRA;
1330 }
1331
1332 return hr;
1333}
1334static HRESULT WINAPI IShellFolder_fnMapNameToSCID(
1335 IShellFolder2 * iface,
1336 LPCWSTR pwszName,
1337 SHCOLUMNID *pscid)
1338{
1339 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1340 FIXME("(%p)\n",This);
1341 return E_NOTIMPL;
1342}
1343
1344static ICOM_VTABLE(IShellFolder2) sfvt =
1345{
1346 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1347 IShellFolder_fnQueryInterface,
1348 IShellFolder_fnAddRef,
1349 IShellFolder_fnRelease,
1350 IShellFolder_fnParseDisplayName,
1351 IShellFolder_fnEnumObjects,
1352 IShellFolder_fnBindToObject,
1353 IShellFolder_fnBindToStorage,
1354 IShellFolder_fnCompareIDs,
1355 IShellFolder_fnCreateViewObject,
1356 IShellFolder_fnGetAttributesOf,
1357 IShellFolder_fnGetUIObjectOf,
1358 IShellFolder_fnGetDisplayNameOf,
1359 IShellFolder_fnSetNameOf,
1360
1361 /* ShellFolder2 */
1362 IShellFolder_fnGetDefaultSearchGUID,
1363 IShellFolder_fnEnumSearches,
1364 IShellFolder_fnGetDefaultColumn,
1365 IShellFolder_fnGetDefaultColumnState,
1366 IShellFolder_fnGetDetailsEx,
1367 IShellFolder_fnGetDetailsOf,
1368 IShellFolder_fnMapNameToSCID
1369};
1370
1371/****************************************************************************
1372 * ISFHelper for IShellFolder implementation
1373 */
1374
1375static HRESULT WINAPI ISFHelper_fnQueryInterface(
1376 ISFHelper *iface,
1377 REFIID riid,
1378 LPVOID *ppvObj)
1379{
1380 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1381
1382 TRACE("(%p)\n", This);
1383
1384 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
1385}
1386
1387static ULONG WINAPI ISFHelper_fnAddRef(
1388 ISFHelper *iface)
1389{
1390 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1391
1392 TRACE("(%p)\n", This);
1393
1394 return IUnknown_AddRef(This->pUnkOuter);
1395}
1396
1397static ULONG WINAPI ISFHelper_fnRelease(
1398 ISFHelper *iface)
1399{
1400 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1401
1402 TRACE("(%p)\n", This);
1403
1404 return IUnknown_Release(This->pUnkOuter);
1405}
1406
1407
1408/****************************************************************************
1409 * ISFHelper_fnAddFolder
1410 *
1411 * creates a unique folder name
1412 */
1413
1414static HRESULT WINAPI ISFHelper_fnGetUniqueName(
1415 ISFHelper *iface,
1416 LPSTR lpName,
1417 UINT uLen)
1418{
1419 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1420 IEnumIDList * penum;
1421 HRESULT hr;
1422 char szText[MAX_PATH];
1423 char * szNewFolder = "New Folder";
1424
1425 TRACE("(%p)(%s %u)\n", This, lpName, uLen);
1426
1427 if (uLen < strlen(szNewFolder) + 4) return E_POINTER;
1428
1429 strcpy(lpName, szNewFolder);
1430
1431 hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
1432 if (penum)
1433 {
1434 LPITEMIDLIST pidl;
1435 DWORD dwFetched;
1436 int i=1;
1437
1438next: IEnumIDList_Reset(penum);
1439 while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched)
1440 {
1441 _ILSimpleGetText(pidl, szText, MAX_PATH);
1442 if (0 == strcasecmp(szText, lpName))
1443 {
1444 sprintf(lpName, "%s %d", szNewFolder, i++);
1445 if (i > 99)
1446 {
1447 hr = E_FAIL;
1448 break;
1449 }
1450 goto next;
1451 }
1452 }
1453
1454 IEnumIDList_Release(penum);
1455 }
1456 return hr;
1457}
1458
1459/****************************************************************************
1460 * ISFHelper_fnAddFolder
1461 *
1462 * adds a new folder.
1463 */
1464
1465static HRESULT WINAPI ISFHelper_fnAddFolder(
1466 ISFHelper *iface,
1467 HWND hwnd,
1468 LPCSTR lpName,
1469 LPITEMIDLIST* ppidlOut)
1470{
1471 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1472 char lpstrNewDir[MAX_PATH];
1473 DWORD bRes;
1474 HRESULT hres = E_FAIL;
1475
1476 TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut);
1477
1478 strcpy(lpstrNewDir, This->sMyPath);
1479 PathAddBackslashA(lpstrNewDir);
1480 strcat(lpstrNewDir, lpName);
1481
1482 bRes = CreateDirectoryA(lpstrNewDir, NULL);
1483
1484 if (bRes)
1485 {
1486 LPITEMIDLIST pidl, pidlitem;
1487
1488 pidlitem = SHSimpleIDListFromPathA(lpstrNewDir);
1489
1490 pidl = ILCombine(This->absPidl, pidlitem);
1491 SHChangeNotify(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
1492 SHFree(pidl);
1493
1494 if (ppidlOut) *ppidlOut = pidlitem;
1495 hres = S_OK;
1496 }
1497 else
1498 {
1499 char lpstrText[128+MAX_PATH];
1500 char lpstrTempText[128];
1501 char lpstrCaption[256];
1502
1503 /* Cannot Create folder because of permissions */
1504 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText));
1505 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption));
1506 sprintf(lpstrText,lpstrTempText, lpstrNewDir);
1507 MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
1508 }
1509
1510 return hres;
1511}
1512
1513/****************************************************************************
1514 * ISFHelper_fnDeleteItems
1515 *
1516 * deletes items in folder
1517 */
1518static HRESULT WINAPI ISFHelper_fnDeleteItems(
1519 ISFHelper *iface,
1520 UINT cidl,
1521 LPCITEMIDLIST* apidl)
1522{
1523 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1524 int i;
1525 char szPath[MAX_PATH];
1526 BOOL bConfirm = TRUE;
1527
1528 TRACE("(%p)(%u %p)\n", This, cidl, apidl);
1529
1530 /* deleting multiple items so give a slightly different warning */
1531 if(cidl != 1)
1532 {
1533 char tmp[8];
1534 snprintf(tmp, sizeof(tmp), "%d", cidl);
1535 if(!SHELL_ConfirmDialog(ASK_DELETE_MULTIPLE_ITEM, tmp))
1536 return E_FAIL;
1537 bConfirm = FALSE;
1538 }
1539
1540 for(i=0; i< cidl; i++)
1541 {
1542 strcpy(szPath, This->sMyPath);
1543 PathAddBackslashA(szPath);
1544 _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
1545
1546 if (_ILIsFolder(apidl[i]))
1547 {
1548 LPITEMIDLIST pidl;
1549 TRACE("delete %s\n", szPath);
1550 if (! SHELL_DeleteDirectoryA(szPath, bConfirm))
1551 {
1552 TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1553 return E_FAIL;
1554 }
1555 pidl = ILCombine(This->absPidl, apidl[i]);
1556 SHChangeNotify(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
1557 SHFree(pidl);
1558 }
1559 else if (_ILIsValue(apidl[i]))
1560 {
1561 LPITEMIDLIST pidl;
1562
1563 TRACE("delete %s\n", szPath);
1564 if (! SHELL_DeleteFileA(szPath, bConfirm))
1565 {
1566 TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1567 return E_FAIL;
1568 }
1569 pidl = ILCombine(This->absPidl, apidl[i]);
1570 SHChangeNotify(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1571 SHFree(pidl);
1572 }
1573
1574 }
1575 return S_OK;
1576}
1577
1578/****************************************************************************
1579 * ISFHelper_fnCopyItems
1580 *
1581 * copies items to this folder
1582 */
1583static HRESULT WINAPI ISFHelper_fnCopyItems(
1584 ISFHelper *iface,
1585 IShellFolder* pSFFrom,
1586 UINT cidl,
1587 LPCITEMIDLIST *apidl)
1588{
1589 int i;
1590 IPersistFolder2 * ppf2=NULL;
1591 char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
1592 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1593
1594 TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1595
1596 IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
1597 if (ppf2)
1598 {
1599 LPITEMIDLIST pidl;
1600 if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
1601 {
1602 for (i=0; i<cidl; i++)
1603 {
1604 SHGetPathFromIDListA(pidl, szSrcPath);
1605 PathAddBackslashA(szSrcPath);
1606 _ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
1607
1608 strcpy(szDstPath, This->sMyPath);
1609 PathAddBackslashA(szDstPath);
1610 _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
1611 MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
1612 }
1613 SHFree(pidl);
1614 }
1615 IPersistFolder2_Release(ppf2);
1616 }
1617 return S_OK;
1618}
1619
1620static ICOM_VTABLE(ISFHelper) shvt =
1621{
1622 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1623 ISFHelper_fnQueryInterface,
1624 ISFHelper_fnAddRef,
1625 ISFHelper_fnRelease,
1626 ISFHelper_fnGetUniqueName,
1627 ISFHelper_fnAddFolder,
1628 ISFHelper_fnDeleteItems,
1629 ISFHelper_fnCopyItems,
1630};
1631
1632/***********************************************************************
1633* [Desktopfolder] IShellFolder implementation
1634*/
1635static struct ICOM_VTABLE(IShellFolder2) sfdvt;
1636
1637static shvheader DesktopSFHeader [] =
1638{
1639 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
1640 { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1641 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1642 { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
1643 { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
1644};
1645#define DESKTOPSHELLVIEWCOLUMNS 5
1646
1647/**************************************************************************
1648* ISF_Desktop_Constructor
1649*
1650*/
1651IShellFolder * ISF_Desktop_Constructor()
1652{
1653 IGenericSFImpl * sf;
1654
1655 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1656 sf->ref=1;
1657 ICOM_VTBL(sf)=&unkvt;
1658 sf->lpvtblShellFolder=&sfdvt;
1659 sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1660 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
1661
1662 TRACE("(%p)\n",sf);
1663
1664 shell32_ObjCount++;
1665 return _IShellFolder_(sf);
1666}
1667
1668/**************************************************************************
1669 * ISF_Desktop_fnQueryInterface
1670 *
1671 * NOTES supports not IPersist/IPersistFolder
1672 */
1673static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1674 IShellFolder2 * iface,
1675 REFIID riid,
1676 LPVOID *ppvObj)
1677{
1678 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1679
1680 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1681
1682 *ppvObj = NULL;
1683
1684 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
1685 {
1686 *ppvObj = _IUnknown_(This);
1687 }
1688 else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
1689 {
1690 *ppvObj = _IShellFolder_(This);
1691 }
1692 else if(IsEqualIID(riid, &IID_IShellFolder2)) /*IShellFolder2*/
1693 {
1694 *ppvObj = _IShellFolder_(This);
1695 }
1696
1697 if(*ppvObj)
1698 {
1699 IUnknown_AddRef((IUnknown*)(*ppvObj));
1700 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1701 return S_OK;
1702 }
1703 TRACE("-- Interface: E_NOINTERFACE\n");
1704 return E_NOINTERFACE;
1705}
1706
1707/**************************************************************************
1708* ISF_Desktop_fnParseDisplayName
1709*
1710* NOTES
1711* "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1712* to MyComputer
1713*/
1714static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1715 IShellFolder2 * iface,
1716 HWND hwndOwner,
1717 LPBC pbcReserved,
1718 LPOLESTR lpszDisplayName,
1719 DWORD *pchEaten,
1720 LPITEMIDLIST *ppidl,
1721 DWORD *pdwAttributes)
1722{
1723 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1724
1725 LPCWSTR szNext=NULL;
1726 LPITEMIDLIST pidlTemp=NULL;
1727 HRESULT hr=E_OUTOFMEMORY;
1728
1729 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1730 This,hwndOwner,pbcReserved,lpszDisplayName,
1731 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1732
1733 *ppidl = 0;
1734 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1735
1736 /* FIXME no real parsing implemented */
1737 pidlTemp = _ILCreateMyComputer();
1738 szNext = lpszDisplayName;
1739
1740 if (szNext && *szNext)
1741 {
1742 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1743 }
1744 else
1745 {
1746 hr = S_OK;
1747
1748 if (pdwAttributes && *pdwAttributes)
1749 {
1750 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
1751 }
1752 }
1753
1754 *ppidl = pidlTemp;
1755
1756 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1757
1758 return hr;
1759}
1760
1761/**************************************************************************
1762* ISF_Desktop_fnEnumObjects
1763*/
1764static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1765 IShellFolder2 * iface,
1766 HWND hwndOwner,
1767 DWORD dwFlags,
1768 LPENUMIDLIST* ppEnumIDList)
1769{
1770 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1771
1772 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1773
1774 *ppEnumIDList = NULL;
1775 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1776
1777 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1778
1779 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1780
1781 return S_OK;
1782}
1783
1784/**************************************************************************
1785* ISF_Desktop_fnBindToObject
1786*/
1787static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
1788 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1789{
1790 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1791 GUID const * clsid;
1792 IShellFolder *pShellFolder, *pSubFolder;
1793 HRESULT hr;
1794
1795 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
1796 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
1797
1798 *ppvOut = NULL;
1799
1800 if ((clsid=_ILGetGUIDPointer(pidl)))
1801 {
1802 if ( IsEqualIID(clsid, &CLSID_MyComputer))
1803 {
1804 pShellFolder = ISF_MyComputer_Constructor();
1805 }
1806 else
1807 {
1808 /* shell extension */
1809 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1810 {
1811 return E_INVALIDARG;
1812 }
1813 }
1814 }
1815 else
1816 {
1817 /* file system folder on the desktop */
1818 LPITEMIDLIST deskpidl, firstpidl, completepidl;
1819 IPersistFolder * ppf;
1820
1821 /* combine pidls */
1822 SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
1823 firstpidl = ILCloneFirst(pidl);
1824 completepidl = ILCombine(deskpidl, firstpidl);
1825
1826 pShellFolder = IShellFolder_Constructor(NULL, NULL);
1827 if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf)))
1828 {
1829 IPersistFolder_Initialize(ppf, completepidl);
1830 IPersistFolder_Release(ppf);
1831 }
1832 ILFree(completepidl);
1833 ILFree(deskpidl);
1834 ILFree(firstpidl);
1835 }
1836
1837 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1838 {
1839 *ppvOut = pShellFolder;
1840 hr = S_OK;
1841 }
1842 else /* go deeper */
1843 {
1844 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1845 IShellFolder_Release(pShellFolder);
1846 *ppvOut = pSubFolder;
1847 }
1848
1849 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
1850
1851 return hr;
1852}
1853
1854/**************************************************************************
1855* ISF_Desktop_fnCreateViewObject
1856*/
1857static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
1858 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1859{
1860 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1861
1862 LPSHELLVIEW pShellView;
1863 HRESULT hr = E_INVALIDARG;
1864
1865 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
1866
1867 if(ppvOut)
1868 {
1869 *ppvOut = NULL;
1870
1871 if(IsEqualIID(riid, &IID_IDropTarget))
1872 {
1873 WARN("IDropTarget not implemented\n");
1874 hr = E_NOTIMPL;
1875 }
1876 else if(IsEqualIID(riid, &IID_IContextMenu))
1877 {
1878 WARN("IContextMenu not implemented\n");
1879 hr = E_NOTIMPL;
1880 }
1881 else if(IsEqualIID(riid, &IID_IShellView))
1882 {
1883 pShellView = IShellView_Constructor((IShellFolder*)iface);
1884 if(pShellView)
1885 {
1886 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1887 IShellView_Release(pShellView);
1888 }
1889 }
1890 }
1891 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1892 return hr;
1893}
1894
1895/**************************************************************************
1896* ISF_Desktop_fnGetAttributesOf
1897*/
1898static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
1899 IShellFolder2 * iface,
1900 UINT cidl,
1901 LPCITEMIDLIST *apidl,
1902 DWORD *rgfInOut)
1903{
1904 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1905
1906 HRESULT hr = S_OK;
1907
1908 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1909
1910 if ( (!cidl) || (!apidl) || (!rgfInOut))
1911 return E_INVALIDARG;
1912
1913 while (cidl > 0 && *apidl)
1914 {
1915 pdump (*apidl);
1916 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1917 apidl++;
1918 cidl--;
1919 }
1920
1921 TRACE("-- result=0x%08lx\n",*rgfInOut);
1922
1923 return hr;
1924}
1925
1926/**************************************************************************
1927* ISF_Desktop_fnGetDisplayNameOf
1928*
1929* NOTES
1930* special case: pidl = null gives desktop-name back
1931*/
1932static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1933 IShellFolder2 * iface,
1934 LPCITEMIDLIST pidl,
1935 DWORD dwFlags,
1936 LPSTRRET strRet)
1937{
1938 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1939
1940 CHAR szPath[MAX_PATH]= "";
1941
1942 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1943 pdump(pidl);
1944
1945 if(!strRet) return E_INVALIDARG;
1946
1947 if(!pidl)
1948 {
1949 HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1950 }
1951 else if ( _ILIsPidlSimple(pidl) )
1952 {
1953 _ILSimpleGetText(pidl, szPath, MAX_PATH);
1954 }
1955 else
1956 {
1957 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
1958 return E_OUTOFMEMORY;
1959 }
1960 strRet->uType = STRRET_CSTRA;
1961 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1962
1963
1964 TRACE("-- (%p)->(%s)\n", This, szPath);
1965 return S_OK;
1966}
1967
1968static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
1969 IShellFolder2 * iface,
1970 GUID *pguid)
1971{
1972 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1973 FIXME("(%p)\n",This);
1974 return E_NOTIMPL;
1975}
1976static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
1977 IShellFolder2 * iface,
1978 IEnumExtraSearch **ppenum)
1979{
1980 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1981 FIXME("(%p)\n",This);
1982 return E_NOTIMPL;
1983}
1984static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
1985 IShellFolder2 * iface,
1986 DWORD dwRes,
1987 ULONG *pSort,
1988 ULONG *pDisplay)
1989{
1990 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1991
1992 TRACE("(%p)\n",This);
1993
1994 if (pSort) *pSort = 0;
1995 if (pDisplay) *pDisplay = 0;
1996
1997 return S_OK;
1998}
1999static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
2000 IShellFolder2 * iface,
2001 UINT iColumn,
2002 DWORD *pcsFlags)
2003{
2004 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2005
2006 TRACE("(%p)\n",This);
2007
2008 if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2009
2010 *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
2011
2012 return S_OK;
2013}
2014static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
2015 IShellFolder2 * iface,
2016 LPCITEMIDLIST pidl,
2017 const SHCOLUMNID *pscid,
2018 VARIANT *pv)
2019{
2020 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2021 FIXME("(%p)\n",This);
2022
2023 return E_NOTIMPL;
2024}
2025static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
2026 IShellFolder2 * iface,
2027 LPCITEMIDLIST pidl,
2028 UINT iColumn,
2029 SHELLDETAILS *psd)
2030{
2031 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2032 HRESULT hr = E_FAIL;;
2033
2034 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2035
2036 if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2037
2038 if (!pidl)
2039 {
2040 psd->fmt = DesktopSFHeader[iColumn].fmt;
2041 psd->cxChar = DesktopSFHeader[iColumn].cxChar;
2042 psd->str.uType = STRRET_CSTRA;
2043 LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2044 return S_OK;
2045 }
2046 else
2047 {
2048 /* the data from the pidl */
2049 switch(iColumn)
2050 {
2051 case 0: /* name */
2052 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2053 break;
2054 case 1: /* size */
2055 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
2056 break;
2057 case 2: /* type */
2058 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2059 break;
2060 case 3: /* date */
2061 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
2062 break;
2063 case 4: /* attributes */
2064 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
2065 break;
2066 }
2067 hr = S_OK;
2068 psd->str.uType = STRRET_CSTRA;
2069 }
2070
2071 return hr;
2072}
2073static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
2074 IShellFolder2 * iface,
2075 LPCWSTR pwszName,
2076 SHCOLUMNID *pscid)
2077{
2078 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2079 FIXME("(%p)\n",This);
2080 return E_NOTIMPL;
2081}
2082
2083static ICOM_VTABLE(IShellFolder2) sfdvt =
2084{
2085 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2086 ISF_Desktop_fnQueryInterface,
2087 IShellFolder_fnAddRef,
2088 IShellFolder_fnRelease,
2089 ISF_Desktop_fnParseDisplayName,
2090 ISF_Desktop_fnEnumObjects,
2091 ISF_Desktop_fnBindToObject,
2092 IShellFolder_fnBindToStorage,
2093 IShellFolder_fnCompareIDs,
2094 ISF_Desktop_fnCreateViewObject,
2095 ISF_Desktop_fnGetAttributesOf,
2096 IShellFolder_fnGetUIObjectOf,
2097 ISF_Desktop_fnGetDisplayNameOf,
2098 IShellFolder_fnSetNameOf,
2099
2100 /* ShellFolder2 */
2101 ISF_Desktop_fnGetDefaultSearchGUID,
2102 ISF_Desktop_fnEnumSearches,
2103 ISF_Desktop_fnGetDefaultColumn,
2104 ISF_Desktop_fnGetDefaultColumnState,
2105 ISF_Desktop_fnGetDetailsEx,
2106 ISF_Desktop_fnGetDetailsOf,
2107 ISF_Desktop_fnMapNameToSCID
2108};
2109
2110
2111/***********************************************************************
2112* IShellFolder [MyComputer] implementation
2113*/
2114
2115static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
2116
2117static shvheader MyComputerSFHeader [] =
2118{
2119 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
2120 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2121 { IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2122 { IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2123};
2124#define MYCOMPUTERSHELLVIEWCOLUMNS 4
2125
2126/**************************************************************************
2127* ISF_MyComputer_Constructor
2128*/
2129static IShellFolder * ISF_MyComputer_Constructor(void)
2130{
2131 IGenericSFImpl * sf;
2132
2133 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
2134 sf->ref=1;
2135
2136 ICOM_VTBL(sf)=&unkvt;
2137 sf->lpvtblShellFolder=&sfmcvt;
2138 sf->lpvtblPersistFolder2 = &psfvt;
2139 sf->pclsid = (CLSID*)&CLSID_SFMyComp;
2140 sf->absPidl=_ILCreateMyComputer(); /* my qualified pidl */
2141 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
2142
2143 TRACE("(%p)\n",sf);
2144
2145 shell32_ObjCount++;
2146 return _IShellFolder_(sf);
2147}
2148
2149/**************************************************************************
2150* ISF_MyComputer_fnParseDisplayName
2151*/
2152static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
2153 IShellFolder2 * iface,
2154 HWND hwndOwner,
2155 LPBC pbcReserved,
2156 LPOLESTR lpszDisplayName,
2157 DWORD *pchEaten,
2158 LPITEMIDLIST *ppidl,
2159 DWORD *pdwAttributes)
2160{
2161 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2162
2163 HRESULT hr = E_OUTOFMEMORY;
2164 LPCWSTR szNext=NULL;
2165 WCHAR szElement[MAX_PATH];
2166 CHAR szTempA[MAX_PATH];
2167 LPITEMIDLIST pidlTemp;
2168
2169 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
2170 This,hwndOwner,pbcReserved,lpszDisplayName,
2171 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
2172
2173 *ppidl = 0;
2174 if (pchEaten) *pchEaten = 0; /* strange but like the original */
2175
2176 /* do we have an absolute path name ? */
2177 if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
2178 lpszDisplayName[2] == (WCHAR)'\\')
2179 {
2180 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
2181 WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
2182 pidlTemp = _ILCreateDrive(szTempA);
2183
2184 if (szNext && *szNext)
2185 {
2186 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
2187 }
2188 else
2189 {
2190 if (pdwAttributes && *pdwAttributes)
2191 {
2192 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
2193 }
2194 hr = S_OK;
2195 }
2196 *ppidl = pidlTemp;
2197 }
2198
2199 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
2200
2201 return hr;
2202}
2203
2204/**************************************************************************
2205* ISF_MyComputer_fnEnumObjects
2206*/
2207static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
2208 IShellFolder2 * iface,
2209 HWND hwndOwner,
2210 DWORD dwFlags,
2211 LPENUMIDLIST* ppEnumIDList)
2212{
2213 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2214
2215 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
2216
2217 *ppEnumIDList = NULL;
2218 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
2219
2220 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
2221
2222 if(!*ppEnumIDList) return E_OUTOFMEMORY;
2223
2224 return S_OK;
2225}
2226
2227/**************************************************************************
2228* ISF_MyComputer_fnBindToObject
2229*/
2230static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
2231 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
2232{
2233 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2234 GUID const * clsid;
2235 IShellFolder *pShellFolder, *pSubFolder;
2236 LPITEMIDLIST pidltemp;
2237 HRESULT hr;
2238
2239 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
2240 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
2241
2242 if(!pidl || !ppvOut) return E_INVALIDARG;
2243
2244 *ppvOut = NULL;
2245
2246 if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
2247 {
2248 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
2249 {
2250 return E_FAIL;
2251 }
2252 }
2253 else
2254 {
2255 if (!_ILIsDrive(pidl)) return E_INVALIDARG;
2256
2257 pidltemp = ILCloneFirst(pidl);
2258 pShellFolder = IShellFolder_Constructor(iface, pidltemp);
2259 ILFree(pidltemp);
2260 }
2261
2262 if (_ILIsPidlSimple(pidl)) /* no sub folders */
2263 {
2264 *ppvOut = pShellFolder;
2265 hr = S_OK;
2266 }
2267 else /* go deeper */
2268 {
2269 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL,
2270 riid, (LPVOID)&pSubFolder);
2271 IShellFolder_Release(pShellFolder);
2272 *ppvOut = pSubFolder;
2273 }
2274
2275 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
2276
2277 return hr;
2278}
2279
2280/**************************************************************************
2281* ISF_MyComputer_fnCreateViewObject
2282*/
2283static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
2284 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
2285{
2286 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2287
2288 LPSHELLVIEW pShellView;
2289 HRESULT hr = E_INVALIDARG;
2290
2291 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
2292
2293 if(ppvOut)
2294 {
2295 *ppvOut = NULL;
2296
2297 if(IsEqualIID(riid, &IID_IDropTarget))
2298 {
2299 WARN("IDropTarget not implemented\n");
2300 hr = E_NOTIMPL;
2301 }
2302 else if(IsEqualIID(riid, &IID_IContextMenu))
2303 {
2304 WARN("IContextMenu not implemented\n");
2305 hr = E_NOTIMPL;
2306 }
2307 else if(IsEqualIID(riid, &IID_IShellView))
2308 {
2309 pShellView = IShellView_Constructor((IShellFolder*)iface);
2310 if(pShellView)
2311 {
2312 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
2313 IShellView_Release(pShellView);
2314 }
2315 }
2316 }
2317 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
2318 return hr;
2319}
2320
2321/**************************************************************************
2322* ISF_MyComputer_fnGetAttributesOf
2323*/
2324static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
2325 IShellFolder2 * iface,
2326 UINT cidl,
2327 LPCITEMIDLIST *apidl,
2328 DWORD *rgfInOut)
2329{
2330 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2331
2332 HRESULT hr = S_OK;
2333
2334 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
2335
2336 if ( (!cidl) || (!apidl) || (!rgfInOut))
2337 return E_INVALIDARG;
2338
2339 while (cidl > 0 && *apidl)
2340 {
2341 pdump (*apidl);
2342 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
2343 apidl++;
2344 cidl--;
2345 }
2346
2347 TRACE("-- result=0x%08lx\n",*rgfInOut);
2348 return hr;
2349}
2350
2351/**************************************************************************
2352* ISF_MyComputer_fnGetDisplayNameOf
2353*
2354* NOTES
2355* The desktopfolder creates only complete paths (SHGDN_FORPARSING).
2356* SHGDN_INFOLDER makes no sense.
2357*/
2358static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
2359 IShellFolder2 * iface,
2360 LPCITEMIDLIST pidl,
2361 DWORD dwFlags,
2362 LPSTRRET strRet)
2363{
2364 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2365
2366 char szPath[MAX_PATH], szDrive[18];
2367 int len = 0;
2368 BOOL bSimplePidl;
2369
2370 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
2371 pdump(pidl);
2372
2373 if(!strRet) return E_INVALIDARG;
2374
2375 szPath[0]=0x00; szDrive[0]=0x00;
2376
2377
2378 bSimplePidl = _ILIsPidlSimple(pidl);
2379
2380 if (_ILIsSpecialFolder(pidl))
2381 {
2382 /* take names of special folders only if its only this folder */
2383 if ( bSimplePidl )
2384 {
2385 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2386 }
2387 }
2388 else
2389 {
2390 if (!_ILIsDrive(pidl))
2391 {
2392 ERR("Wrong pidl type\n");
2393 return E_INVALIDARG;
2394 }
2395
2396 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2397
2398 /* long view "lw_name (C:)" */
2399 if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
2400 {
2401 DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
2402
2403#ifdef __WIN32OS2__
2404//CB: floppy drives have a fixed name
2405 if ((szPath[0] == 'A') || (szPath[0] == 'a') || (szPath[0] == 'B') || (szPath[0] == 'b'))
2406 {
2407 //floppy
2408 strncpy(szDrive,szPath,2);
2409 //3.5 floppy
2410 LoadStringA(shell32_hInstance,IDS_35FLOPPY,szPath,sizeof(szPath)-10);
2411 //CB: todo: 5.25 floppy check
2412 strcat(szPath," (");
2413 strncat(szPath,szDrive,2);
2414 strcat(szPath,")");
2415 } else
2416 {
2417 GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2418 strcat (szDrive," (");
2419 strncat (szDrive, szPath, 2);
2420 strcat (szDrive,")");
2421 strcpy (szPath, szDrive);
2422 }
2423#else
2424 GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2425 strcat (szDrive," (");
2426 strncat (szDrive, szPath, 2);
2427 strcat (szDrive,")");
2428 strcpy (szPath, szDrive);
2429#endif
2430 }
2431 }
2432
2433 if (!bSimplePidl) /* go deeper if needed */
2434 {
2435 PathAddBackslashA(szPath);
2436 len = strlen(szPath);
2437
2438 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
2439 return E_OUTOFMEMORY;
2440 }
2441 strRet->uType = STRRET_CSTRA;
2442 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
2443
2444
2445 TRACE("-- (%p)->(%s)\n", This, szPath);
2446 return S_OK;
2447}
2448
2449static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
2450 IShellFolder2 * iface,
2451 GUID *pguid)
2452{
2453 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2454 FIXME("(%p)\n",This);
2455 return E_NOTIMPL;
2456}
2457static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
2458 IShellFolder2 * iface,
2459 IEnumExtraSearch **ppenum)
2460{
2461 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2462 FIXME("(%p)\n",This);
2463 return E_NOTIMPL;
2464}
2465static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
2466 IShellFolder2 * iface,
2467 DWORD dwRes,
2468 ULONG *pSort,
2469 ULONG *pDisplay)
2470{
2471 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2472
2473 TRACE("(%p)\n",This);
2474
2475 if (pSort) *pSort = 0;
2476 if (pDisplay) *pDisplay = 0;
2477
2478 return S_OK;
2479}
2480static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
2481 IShellFolder2 * iface,
2482 UINT iColumn,
2483 DWORD *pcsFlags)
2484{
2485 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2486
2487 TRACE("(%p)\n",This);
2488
2489 if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2490
2491 *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
2492
2493 return S_OK;
2494}
2495static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
2496 IShellFolder2 * iface,
2497 LPCITEMIDLIST pidl,
2498 const SHCOLUMNID *pscid,
2499 VARIANT *pv)
2500{
2501 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2502 FIXME("(%p)\n",This);
2503
2504 return E_NOTIMPL;
2505}
2506
2507/* fixme: drive size >4GB is rolling over */
2508static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
2509 IShellFolder2 * iface,
2510 LPCITEMIDLIST pidl,
2511 UINT iColumn,
2512 SHELLDETAILS *psd)
2513{
2514 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2515 HRESULT hr;
2516
2517 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2518
2519 if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2520
2521 if (!pidl)
2522 {
2523 psd->fmt = MyComputerSFHeader[iColumn].fmt;
2524 psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
2525 psd->str.uType = STRRET_CSTRA;
2526 LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2527 return S_OK;
2528 }
2529 else
2530 {
2531 char szPath[MAX_PATH];
2532 ULARGE_INTEGER ulBytes;
2533
2534 psd->str.u.cStr[0] = 0x00;
2535 psd->str.uType = STRRET_CSTRA;
2536 switch(iColumn)
2537 {
2538 case 0: /* name */
2539 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2540 break;
2541 case 1: /* type */
2542 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2543 break;
2544 case 2: /* total size */
2545 if (_ILIsDrive(pidl))
2546 {
2547 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2548 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
2549 StrFormatByteSizeA(ulBytes.LowPart, psd->str.u.cStr, MAX_PATH);
2550 }
2551 break;
2552 case 3: /* free size */
2553 if (_ILIsDrive(pidl))
2554 {
2555 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2556 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
2557 StrFormatByteSizeA(ulBytes.LowPart, psd->str.u.cStr, MAX_PATH);
2558 }
2559 break;
2560 }
2561 hr = S_OK;
2562 }
2563
2564 return hr;
2565}
2566static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
2567 IShellFolder2 * iface,
2568 LPCWSTR pwszName,
2569 SHCOLUMNID *pscid)
2570{
2571 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2572 FIXME("(%p)\n",This);
2573 return E_NOTIMPL;
2574}
2575
2576static ICOM_VTABLE(IShellFolder2) sfmcvt =
2577{
2578 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2579 IShellFolder_fnQueryInterface,
2580 IShellFolder_fnAddRef,
2581 IShellFolder_fnRelease,
2582 ISF_MyComputer_fnParseDisplayName,
2583 ISF_MyComputer_fnEnumObjects,
2584 ISF_MyComputer_fnBindToObject,
2585 IShellFolder_fnBindToStorage,
2586 IShellFolder_fnCompareIDs,
2587 ISF_MyComputer_fnCreateViewObject,
2588 ISF_MyComputer_fnGetAttributesOf,
2589 IShellFolder_fnGetUIObjectOf,
2590 ISF_MyComputer_fnGetDisplayNameOf,
2591 IShellFolder_fnSetNameOf,
2592
2593 /* ShellFolder2 */
2594 ISF_MyComputer_fnGetDefaultSearchGUID,
2595 ISF_MyComputer_fnEnumSearches,
2596 ISF_MyComputer_fnGetDefaultColumn,
2597 ISF_MyComputer_fnGetDefaultColumnState,
2598 ISF_MyComputer_fnGetDetailsEx,
2599 ISF_MyComputer_fnGetDetailsOf,
2600 ISF_MyComputer_fnMapNameToSCID
2601};
2602
2603
2604/************************************************************************
2605 * ISFPersistFolder_QueryInterface (IUnknown)
2606 *
2607 */
2608static HRESULT WINAPI ISFPersistFolder2_QueryInterface(
2609 IPersistFolder2 * iface,
2610 REFIID iid,
2611 LPVOID* ppvObj)
2612{
2613 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2614
2615 TRACE("(%p)\n", This);
2616
2617 return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
2618}
2619
2620/************************************************************************
2621 * ISFPersistFolder_AddRef (IUnknown)
2622 *
2623 */
2624static ULONG WINAPI ISFPersistFolder2_AddRef(
2625 IPersistFolder2 * iface)
2626{
2627 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2628
2629 TRACE("(%p)\n", This);
2630
2631 return IUnknown_AddRef(This->pUnkOuter);
2632}
2633
2634/************************************************************************
2635 * ISFPersistFolder_Release (IUnknown)
2636 *
2637 */
2638static ULONG WINAPI ISFPersistFolder2_Release(
2639 IPersistFolder2 * iface)
2640{
2641 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2642
2643 TRACE("(%p)\n", This);
2644
2645 return IUnknown_Release(This->pUnkOuter);
2646}
2647
2648/************************************************************************
2649 * ISFPersistFolder_GetClassID (IPersist)
2650 */
2651static HRESULT WINAPI ISFPersistFolder2_GetClassID(
2652 IPersistFolder2 * iface,
2653 CLSID * lpClassId)
2654{
2655 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2656
2657 TRACE("(%p)\n", This);
2658
2659 if (!lpClassId) return E_POINTER;
2660 *lpClassId = *This->pclsid;
2661
2662 return S_OK;
2663}
2664
2665/************************************************************************
2666 * ISFPersistFolder_Initialize (IPersistFolder)
2667 *
2668 * NOTES
2669 * sMyPath is not set. Don't know how to handle in a non rooted environment.
2670 */
2671static HRESULT WINAPI ISFPersistFolder2_Initialize(
2672 IPersistFolder2 * iface,
2673 LPCITEMIDLIST pidl)
2674{
2675 char sTemp[MAX_PATH];
2676 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2677
2678 TRACE("(%p)->(%p)\n", This, pidl);
2679
2680 /* free the old stuff */
2681 if(This->absPidl)
2682 {
2683 SHFree(This->absPidl);
2684 This->absPidl = NULL;
2685 }
2686 if(This->sMyPath)
2687 {
2688 SHFree(This->sMyPath);
2689 This->sMyPath = NULL;
2690 }
2691
2692 /* set my pidl */
2693 This->absPidl = ILClone(pidl);
2694
2695 /* set my path */
2696 if (SHGetPathFromIDListA(pidl, sTemp))
2697 {
2698 This->sMyPath = SHAlloc(strlen(sTemp)+1);
2699 strcpy(This->sMyPath, sTemp);
2700 }
2701
2702 TRACE("--(%p)->(%s)\n", This, This->sMyPath);
2703
2704 return S_OK;
2705}
2706
2707/**************************************************************************
2708* IPersistFolder2_fnGetCurFolder
2709*/
2710static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder(
2711 IPersistFolder2 * iface,
2712 LPITEMIDLIST * pidl)
2713{
2714 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2715
2716 TRACE("(%p)->(%p)\n",This, pidl);
2717
2718 if (!pidl) return E_POINTER;
2719
2720 *pidl = ILClone(This->absPidl);
2721
2722 return S_OK;
2723}
2724
2725static ICOM_VTABLE(IPersistFolder2) psfvt =
2726{
2727 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2728 ISFPersistFolder2_QueryInterface,
2729 ISFPersistFolder2_AddRef,
2730 ISFPersistFolder2_Release,
2731 ISFPersistFolder2_GetClassID,
2732 ISFPersistFolder2_Initialize,
2733 ISFPersistFolder2_fnGetCurFolder
2734};
2735
2736/****************************************************************************
2737 * ISFDropTarget implementation
2738 */
2739static BOOL ISFDropTarget_QueryDrop(
2740 IDropTarget *iface,
2741 DWORD dwKeyState,
2742 LPDWORD pdwEffect)
2743{
2744 DWORD dwEffect = *pdwEffect;
2745
2746 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2747
2748 *pdwEffect = DROPEFFECT_NONE;
2749
2750 if (This->fAcceptFmt)
2751 { /* Does our interpretation of the keystate ... */
2752 *pdwEffect = KeyStateToDropEffect(dwKeyState);
2753
2754 /* ... matches the desired effect ? */
2755 if (dwEffect & *pdwEffect)
2756 {
2757 return TRUE;
2758 }
2759 }
2760 return FALSE;
2761}
2762
2763static HRESULT WINAPI ISFDropTarget_QueryInterface(
2764 IDropTarget *iface,
2765 REFIID riid,
2766 LPVOID *ppvObj)
2767{
2768 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2769
2770 TRACE("(%p)\n", This);
2771
2772 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
2773}
2774
2775static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
2776{
2777 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2778
2779 TRACE("(%p)\n", This);
2780
2781 return IUnknown_AddRef(This->pUnkOuter);
2782}
2783
2784static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
2785{
2786 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2787
2788 TRACE("(%p)\n", This);
2789
2790 return IUnknown_Release(This->pUnkOuter);
2791}
2792
2793static HRESULT WINAPI ISFDropTarget_DragEnter(
2794 IDropTarget *iface,
2795 IDataObject *pDataObject,
2796 DWORD dwKeyState,
2797 POINTL pt,
2798 DWORD *pdwEffect)
2799{
2800 FORMATETC fmt;
2801
2802 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2803
2804 TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
2805
2806 InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
2807
2808 This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
2809
2810 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2811
2812 return S_OK;
2813}
2814
2815static HRESULT WINAPI ISFDropTarget_DragOver(
2816 IDropTarget *iface,
2817 DWORD dwKeyState,
2818 POINTL pt,
2819 DWORD *pdwEffect)
2820{
2821 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2822
2823 TRACE("(%p)\n",This);
2824
2825 if(!pdwEffect) return E_INVALIDARG;
2826
2827 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2828
2829 return S_OK;
2830}
2831
2832static HRESULT WINAPI ISFDropTarget_DragLeave(
2833 IDropTarget *iface)
2834{
2835 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2836
2837 TRACE("(%p)\n",This);
2838
2839 This->fAcceptFmt = FALSE;
2840
2841 return S_OK;
2842}
2843
2844static HRESULT WINAPI ISFDropTarget_Drop(
2845 IDropTarget *iface,
2846 IDataObject* pDataObject,
2847 DWORD dwKeyState,
2848 POINTL pt,
2849 DWORD *pdwEffect)
2850{
2851 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2852
2853 FIXME("(%p) object dropped\n",This);
2854
2855 return E_NOTIMPL;
2856}
2857
2858static struct ICOM_VTABLE(IDropTarget) dtvt =
2859{
2860 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2861 ISFDropTarget_QueryInterface,
2862 ISFDropTarget_AddRef,
2863 ISFDropTarget_Release,
2864 ISFDropTarget_DragEnter,
2865 ISFDropTarget_DragOver,
2866 ISFDropTarget_DragLeave,
2867 ISFDropTarget_Drop
2868};
Note: See TracBrowser for help on using the repository browser.