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

Last change on this file since 7012 was 7012, checked in by phaller, 24 years ago

performance improvement

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