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

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

.

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