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

Last change on this file since 4032 was 4032, checked in by phaller, 25 years ago

Synchronized shell32 with wine

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