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

Last change on this file since 6650 was 6650, checked in by bird, 24 years ago

Added $Id:$ keyword.

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