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

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

.

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