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

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

.

File size: 72.8 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, ODIN_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 int nReturn;
867 IShellFolder * psf;
868 HRESULT hr = E_OUTOFMEMORY;
869 LPCITEMIDLIST pidlTemp;
870 PIDLTYPE pt1, pt2;
871
872// TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
873// pdump (pidl1);
874// pdump (pidl2);
875
876 if (!pidl1 && !pidl2)
877 {
878 hr = ResultFromShort(0);
879 }
880 else if (!pidl1)
881 {
882 hr = ResultFromShort(-1);
883 }
884 else if (!pidl2)
885 {
886 hr = ResultFromShort(1);
887 }
888 else
889 {
890 LPPIDLDATA pd1, pd2;
891 pd1 = _ILGetDataPointer(pidl1);
892 pd2 = _ILGetDataPointer(pidl2);
893
894 /* compate the types. sort order is the PT_* constant */
895 pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
896 pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
897
898 if (pt1 != pt2)
899 {
900 hr = ResultFromShort(pt1-pt2);
901 }
902 else /* same type of pidl */
903 {
904// _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
905// _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
906// nReturn = strcasecmp(szTemp1, szTemp2);
907 nReturn = _ILSimpleCompareText( pidl1, pidl2 );
908
909 if (nReturn == 0) /* first pidl different ? */
910 {
911 pidl1 = ODIN_ILGetNext(pidl1);
912
913 if (pidl1 && pidl1->mkid.cb) /* go deeper? */
914 {
915 pidlTemp = ODIN_ILCloneFirst(pidl1);
916 pidl2 = ODIN_ILGetNext(pidl2);
917
918 hr = IShellFolder_BindToObject(iface, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
919 if (SUCCEEDED(hr))
920 {
921 nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
922 IShellFolder_Release(psf);
923 hr = ResultFromShort(nReturn);
924 }
925 ODIN_ILFree(pidlTemp);
926 }
927 else
928 {
929 pidl2 = ODIN_ILGetNext(pidl2);
930 if (pidl2 && pidl2->mkid.cb) /* go deeper on #2 ? */
931 hr = ResultFromShort(-1); /* two different */
932 else
933 hr = ResultFromShort(nReturn); /* two equal simple pidls */
934 }
935 }
936 else
937 {
938 hr = ResultFromShort(nReturn); /* two different simple pidls */
939 }
940 }
941 }
942
943 TRACE("-- res=0x%08lx\n", hr);
944 return hr;
945}
946
947/**************************************************************************
948* IShellFolder_fnCreateViewObject
949*/
950static HRESULT WINAPI IShellFolder_fnCreateViewObject(
951 IShellFolder2 * iface,
952 HWND hwndOwner,
953 REFIID riid,
954 LPVOID *ppvOut)
955{
956 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
957
958 LPSHELLVIEW pShellView;
959 HRESULT hr = E_INVALIDARG;
960
961 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
962
963 if(ppvOut)
964 {
965 *ppvOut = NULL;
966
967 if(IsEqualIID(riid, &IID_IDropTarget))
968 {
969 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, ppvOut);
970 }
971 else if(IsEqualIID(riid, &IID_IContextMenu))
972 {
973 FIXME("IContextMenu not implemented\n");
974 hr = E_NOTIMPL;
975 }
976 else if(IsEqualIID(riid, &IID_IShellView))
977 {
978 pShellView = IShellView_Constructor((IShellFolder*)iface);
979 if(pShellView)
980 {
981 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
982 IShellView_Release(pShellView);
983 }
984 }
985 }
986 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
987 return hr;
988}
989
990/**************************************************************************
991* IShellFolder_fnGetAttributesOf
992*
993* PARAMETERS
994* UINT cidl, //[in ] num elements in pidl array
995* LPCITEMIDLIST* apidl, //[in ] simple pidl array
996* ULONG* rgfInOut) //[out] result array
997*
998*/
999static HRESULT WINAPI IShellFolder_fnGetAttributesOf(
1000 IShellFolder2 * iface,
1001 UINT cidl,
1002 LPCITEMIDLIST *apidl,
1003 DWORD *rgfInOut)
1004{
1005 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1006
1007 HRESULT hr = S_OK;
1008
1009 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
1010
1011 if ( (!cidl) || (!apidl) || (!rgfInOut))
1012 return E_INVALIDARG;
1013
1014 while (cidl > 0 && *apidl)
1015 {
1016 pdump (*apidl);
1017 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1018 apidl++;
1019 cidl--;
1020 }
1021
1022 TRACE("-- result=0x%08lx\n",*rgfInOut);
1023
1024 return hr;
1025}
1026/**************************************************************************
1027* IShellFolder_fnGetUIObjectOf
1028*
1029* PARAMETERS
1030* HWND hwndOwner, //[in ] Parent window for any output
1031* UINT cidl, //[in ] array size
1032* LPCITEMIDLIST* apidl, //[in ] simple pidl array
1033* REFIID riid, //[in ] Requested Interface
1034* UINT* prgfInOut, //[ ] reserved
1035* LPVOID* ppvObject) //[out] Resulting Interface
1036*
1037* NOTES
1038* This function gets asked to return "view objects" for one or more (multiple select)
1039* items:
1040* The viewobject typically is an COM object with one of the following interfaces:
1041* IExtractIcon,IDataObject,IContextMenu
1042* In order to support icon positions in the default Listview your DataObject
1043* must implement the SetData method (in addition to GetData :) - the shell passes
1044* a barely documented "Icon positions" structure to SetData when the drag starts,
1045* and GetData's it if the drop is in another explorer window that needs the positions.
1046*/
1047static HRESULT WINAPI IShellFolder_fnGetUIObjectOf(
1048 IShellFolder2 * iface,
1049 HWND hwndOwner,
1050 UINT cidl,
1051 LPCITEMIDLIST * apidl,
1052 REFIID riid,
1053 UINT * prgfInOut,
1054 LPVOID * ppvOut)
1055{
1056 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1057
1058 LPITEMIDLIST pidl;
1059 IUnknown* pObj = NULL;
1060 HRESULT hr = E_INVALIDARG;
1061
1062 TRACE("(%p)->(0x%04x,%u,apidl=%p,\n\tIID:%s,%p,%p)\n",
1063 This,hwndOwner,cidl,apidl,debugstr_guid(riid),prgfInOut,ppvOut);
1064
1065 if (ppvOut)
1066 {
1067 *ppvOut = NULL;
1068
1069 if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
1070 {
1071 pObj = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl);
1072 hr = S_OK;
1073 }
1074 else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
1075 {
1076 pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
1077 hr = S_OK;
1078 }
1079 else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
1080 {
1081 pidl = ODIN_ILCombine(This->absPidl,apidl[0]);
1082 pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
1083 ODIN_SHFree(pidl);
1084 hr = S_OK;
1085 }
1086 else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
1087 {
1088 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pObj);
1089 }
1090 else
1091 {
1092 hr = E_NOINTERFACE;
1093 }
1094
1095 if(!pObj)
1096 hr = E_OUTOFMEMORY;
1097
1098 *ppvOut = pObj;
1099 }
1100 TRACE("(%p)->hr=0x%08lx\n",This, hr);
1101 return hr;
1102}
1103
1104/**************************************************************************
1105* IShellFolder_fnGetDisplayNameOf
1106* Retrieves the display name for the specified file object or subfolder
1107*
1108* PARAMETERS
1109* LPCITEMIDLIST pidl, //[in ] complex pidl to item
1110* DWORD dwFlags, //[in ] SHGNO formatting flags
1111* LPSTRRET lpName) //[out] Returned display name
1112*
1113* FIXME
1114* if the name is in the pidl the ret value should be a STRRET_OFFSET
1115*/
1116#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
1117#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
1118
1119static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
1120 IShellFolder2 * iface,
1121 LPCITEMIDLIST pidl,
1122 DWORD dwFlags,
1123 LPSTRRET strRet)
1124{
1125 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1126
1127 CHAR szPath[MAX_PATH]= "";
1128 int len = 0;
1129 BOOL bSimplePidl;
1130
1131 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1132 pdump(pidl);
1133
1134 if(!pidl || !strRet) return E_INVALIDARG;
1135
1136 bSimplePidl = _ILIsPidlSimple(pidl);
1137
1138 /* take names of special folders only if its only this folder */
1139 if (_ILIsSpecialFolder(pidl))
1140 {
1141 if ( bSimplePidl)
1142 {
1143 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1144 }
1145 }
1146 else
1147 {
1148 if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
1149 {
1150 strcpy (szPath, This->sMyPath); /* get path to root*/
1151 PathAddBackslashA(szPath);
1152 len = strlen(szPath);
1153 }
1154 _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
1155 }
1156
1157 if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl) /* go deeper if needed */
1158 {
1159 PathAddBackslashA(szPath);
1160 len = strlen(szPath);
1161
1162 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath + len, MAX_PATH - len)))
1163 return E_OUTOFMEMORY;
1164 }
1165 strRet->uType = STRRET_CSTRA;
1166 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1167
1168 TRACE("-- (%p)->(%s)\n", This, szPath);
1169 return S_OK;
1170}
1171
1172/**************************************************************************
1173* IShellFolder_fnSetNameOf
1174* Changes the name of a file object or subfolder, possibly changing its item
1175* identifier in the process.
1176*
1177* PARAMETERS
1178* HWND hwndOwner, //[in ] Owner window for output
1179* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
1180* LPCOLESTR lpszName, //[in ] the items new display name
1181* DWORD dwFlags, //[in ] SHGNO formatting flags
1182* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
1183*/
1184static HRESULT WINAPI IShellFolder_fnSetNameOf(
1185 IShellFolder2 * iface,
1186 HWND hwndOwner,
1187 LPCITEMIDLIST pidl, /*simple pidl*/
1188 LPCOLESTR lpName,
1189 DWORD dwFlags,
1190 LPITEMIDLIST *pPidlOut)
1191{
1192 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1193 char szSrc[MAX_PATH], szDest[MAX_PATH];
1194 int len;
1195 BOOL bIsFolder = _ILIsFolder(ILFindLastID(pidl));
1196
1197 TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p)\n",
1198 This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut);
1199
1200 /* build source path */
1201 if (dwFlags & SHGDN_INFOLDER)
1202 {
1203 strcpy(szSrc, This->sMyPath);
1204 PathAddBackslashA(szSrc);
1205 len = strlen (szSrc);
1206 _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len);
1207 }
1208 else
1209 {
1210 SHGetPathFromIDListA(pidl, szSrc);
1211 }
1212
1213 /* build destination path */
1214 strcpy(szDest, This->sMyPath);
1215 PathAddBackslashA(szDest);
1216 len = strlen (szDest);
1217 WideCharToMultiByte( CP_ACP, 0, lpName, -1, szDest+len, MAX_PATH-len, NULL, NULL );
1218 szDest[MAX_PATH-1] = 0;
1219 TRACE("src=%s dest=%s\n", szSrc, szDest);
1220 if ( MoveFileA(szSrc, szDest) )
1221 {
1222 if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest);
1223 SHChangeNotifyA( bIsFolder?SHCNE_RENAMEFOLDER:SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
1224 return S_OK;
1225 }
1226 return E_FAIL;
1227}
1228
1229static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(
1230 IShellFolder2 * iface,
1231 GUID *pguid)
1232{
1233 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1234 FIXME("(%p)\n",This);
1235 return E_NOTIMPL;
1236}
1237static HRESULT WINAPI IShellFolder_fnEnumSearches(
1238 IShellFolder2 * iface,
1239 IEnumExtraSearch **ppenum)
1240{
1241 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1242 FIXME("(%p)\n",This);
1243 return E_NOTIMPL;
1244}
1245static HRESULT WINAPI IShellFolder_fnGetDefaultColumn(
1246 IShellFolder2 * iface,
1247 DWORD dwRes,
1248 ULONG *pSort,
1249 ULONG *pDisplay)
1250{
1251 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1252
1253 TRACE("(%p)\n",This);
1254
1255 if (pSort) *pSort = 0;
1256 if (pDisplay) *pDisplay = 0;
1257
1258 return S_OK;
1259}
1260static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState(
1261 IShellFolder2 * iface,
1262 UINT iColumn,
1263 DWORD *pcsFlags)
1264{
1265 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1266
1267 TRACE("(%p)\n",This);
1268
1269 if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1270
1271 *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
1272
1273 return S_OK;
1274}
1275static HRESULT WINAPI IShellFolder_fnGetDetailsEx(
1276 IShellFolder2 * iface,
1277 LPCITEMIDLIST pidl,
1278 const SHCOLUMNID *pscid,
1279 VARIANT *pv)
1280{
1281 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1282 FIXME("(%p)\n",This);
1283
1284 return E_NOTIMPL;
1285}
1286static HRESULT WINAPI IShellFolder_fnGetDetailsOf(
1287 IShellFolder2 * iface,
1288 LPCITEMIDLIST pidl,
1289 UINT iColumn,
1290 SHELLDETAILS *psd)
1291{
1292 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1293 HRESULT hr = E_FAIL;
1294
1295 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1296
1297 if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1298
1299 if (!pidl)
1300 {
1301 /* the header titles */
1302 psd->fmt = GenericSFHeader[iColumn].fmt;
1303 psd->cxChar = GenericSFHeader[iColumn].cxChar;
1304 psd->str.uType = STRRET_CSTRA;
1305 LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
1306 return S_OK;
1307 }
1308 else
1309 {
1310 /* the data from the pidl */
1311 switch(iColumn)
1312 {
1313 case 0: /* name */
1314 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
1315 break;
1316 case 1: /* size */
1317 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
1318 break;
1319 case 2: /* type */
1320 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
1321 break;
1322 case 3: /* date */
1323 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
1324 break;
1325 case 4: /* attributes */
1326 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
1327 break;
1328 }
1329 hr = S_OK;
1330 psd->str.uType = STRRET_CSTRA;
1331 }
1332
1333 return hr;
1334}
1335static HRESULT WINAPI IShellFolder_fnMapNameToSCID(
1336 IShellFolder2 * iface,
1337 LPCWSTR pwszName,
1338 SHCOLUMNID *pscid)
1339{
1340 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1341 FIXME("(%p)\n",This);
1342 return E_NOTIMPL;
1343}
1344
1345static ICOM_VTABLE(IShellFolder2) sfvt =
1346{
1347 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1348 IShellFolder_fnQueryInterface,
1349 IShellFolder_fnAddRef,
1350 IShellFolder_fnRelease,
1351 IShellFolder_fnParseDisplayName,
1352 IShellFolder_fnEnumObjects,
1353 IShellFolder_fnBindToObject,
1354 IShellFolder_fnBindToStorage,
1355 IShellFolder_fnCompareIDs,
1356 IShellFolder_fnCreateViewObject,
1357 IShellFolder_fnGetAttributesOf,
1358 IShellFolder_fnGetUIObjectOf,
1359 IShellFolder_fnGetDisplayNameOf,
1360 IShellFolder_fnSetNameOf,
1361
1362 /* ShellFolder2 */
1363 IShellFolder_fnGetDefaultSearchGUID,
1364 IShellFolder_fnEnumSearches,
1365 IShellFolder_fnGetDefaultColumn,
1366 IShellFolder_fnGetDefaultColumnState,
1367 IShellFolder_fnGetDetailsEx,
1368 IShellFolder_fnGetDetailsOf,
1369 IShellFolder_fnMapNameToSCID
1370};
1371
1372/****************************************************************************
1373 * ISFHelper for IShellFolder implementation
1374 */
1375
1376static HRESULT WINAPI ISFHelper_fnQueryInterface(
1377 ISFHelper *iface,
1378 REFIID riid,
1379 LPVOID *ppvObj)
1380{
1381 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1382
1383 TRACE("(%p)\n", This);
1384
1385 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
1386}
1387
1388static ULONG WINAPI ISFHelper_fnAddRef(
1389 ISFHelper *iface)
1390{
1391 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1392
1393 TRACE("(%p)\n", This);
1394
1395 return IUnknown_AddRef(This->pUnkOuter);
1396}
1397
1398static ULONG WINAPI ISFHelper_fnRelease(
1399 ISFHelper *iface)
1400{
1401 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1402
1403 TRACE("(%p)\n", This);
1404
1405 return IUnknown_Release(This->pUnkOuter);
1406}
1407
1408
1409/****************************************************************************
1410 * ISFHelper_fnAddFolder
1411 *
1412 * creates a unique folder name
1413 */
1414
1415static HRESULT WINAPI ISFHelper_fnGetUniqueName(
1416 ISFHelper *iface,
1417 LPSTR lpName,
1418 UINT uLen)
1419{
1420 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1421 IEnumIDList * penum;
1422 HRESULT hr;
1423 char szText[MAX_PATH];
1424 char * szNewFolder = "New Folder";
1425
1426 TRACE("(%p)(%s %u)\n", This, lpName, uLen);
1427
1428 if (uLen < strlen(szNewFolder) + 4) return E_POINTER;
1429
1430 strcpy(lpName, szNewFolder);
1431
1432 hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
1433 if (penum)
1434 {
1435 LPITEMIDLIST pidl;
1436 DWORD dwFetched;
1437 int i=1;
1438
1439next: IEnumIDList_Reset(penum);
1440 while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched)
1441 {
1442 _ILSimpleGetText(pidl, szText, MAX_PATH);
1443 if (0 == strcasecmp(szText, lpName))
1444 {
1445 sprintf(lpName, "%s %d", szNewFolder, i++);
1446 if (i > 99)
1447 {
1448 hr = E_FAIL;
1449 break;
1450 }
1451 goto next;
1452 }
1453 }
1454
1455 IEnumIDList_Release(penum);
1456 }
1457 return hr;
1458}
1459
1460/****************************************************************************
1461 * ISFHelper_fnAddFolder
1462 *
1463 * adds a new folder.
1464 */
1465
1466static HRESULT WINAPI ISFHelper_fnAddFolder(
1467 ISFHelper *iface,
1468 HWND hwnd,
1469 LPCSTR lpName,
1470 LPITEMIDLIST* ppidlOut)
1471{
1472 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1473 char lpstrNewDir[MAX_PATH];
1474 DWORD bRes;
1475 HRESULT hres = E_FAIL;
1476
1477 TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut);
1478
1479 strcpy(lpstrNewDir, This->sMyPath);
1480 PathAddBackslashA(lpstrNewDir);
1481 strcat(lpstrNewDir, lpName);
1482
1483 bRes = CreateDirectoryA(lpstrNewDir, NULL);
1484
1485 if (bRes)
1486 {
1487 LPITEMIDLIST pidl, pidlitem;
1488
1489 pidlitem = SHSimpleIDListFromPathA(lpstrNewDir);
1490
1491 pidl = ODIN_ILCombine(This->absPidl, pidlitem);
1492 SHChangeNotifyA(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
1493 ODIN_SHFree(pidl);
1494
1495 if (ppidlOut) *ppidlOut = pidlitem;
1496 hres = S_OK;
1497 }
1498 else
1499 {
1500 char lpstrText[128+MAX_PATH];
1501 char lpstrTempText[128];
1502 char lpstrCaption[256];
1503
1504 /* Cannot Create folder because of permissions */
1505 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText));
1506 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption));
1507 sprintf(lpstrText,lpstrTempText, lpstrNewDir);
1508 MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
1509 }
1510
1511 return hres;
1512}
1513
1514/****************************************************************************
1515 * ISFHelper_fnDeleteItems
1516 *
1517 * deletes items in folder
1518 */
1519static HRESULT WINAPI ISFHelper_fnDeleteItems(
1520 ISFHelper *iface,
1521 UINT cidl,
1522 LPCITEMIDLIST* apidl)
1523{
1524 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1525 int i;
1526 char szPath[MAX_PATH];
1527 BOOL bConfirm = TRUE;
1528
1529 TRACE("(%p)(%u %p)\n", This, cidl, apidl);
1530
1531 /* deleting multiple items so give a slightly different warning */
1532 if(cidl != 1)
1533 {
1534 char tmp[8];
1535 snprintf(tmp, sizeof(tmp), "%d", cidl);
1536 if(!SHELL_WarnItemDelete(ASK_DELETE_MULTIPLE_ITEM, tmp))
1537 return E_FAIL;
1538 bConfirm = FALSE;
1539 }
1540
1541 for(i=0; i< cidl; i++)
1542 {
1543 strcpy(szPath, This->sMyPath);
1544 PathAddBackslashA(szPath);
1545 _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
1546
1547 if (_ILIsFolder(apidl[i]))
1548 {
1549 LPITEMIDLIST pidl;
1550 TRACE("delete %s\n", szPath);
1551 if (! SHELL_DeleteDirectoryA(szPath, bConfirm))
1552 {
1553 TRACE("delete %s failed, bConfirm=%d", szPath, bConfirm);
1554 return E_FAIL;
1555 }
1556 pidl = ODIN_ILCombine(This->absPidl, apidl[i]);
1557 SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
1558 ODIN_SHFree(pidl);
1559 }
1560 else if (_ILIsValue(apidl[i]))
1561 {
1562 LPITEMIDLIST pidl;
1563
1564 TRACE("delete %s\n", szPath);
1565 if (! SHELL_DeleteFileA(szPath, bConfirm))
1566 {
1567 TRACE("delete %s failed, bConfirm=%d", szPath, bConfirm);
1568 return E_FAIL;
1569 }
1570 pidl = ODIN_ILCombine(This->absPidl, apidl[i]);
1571 SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1572 ODIN_SHFree(pidl);
1573 }
1574
1575 }
1576 return S_OK;
1577}
1578
1579/****************************************************************************
1580 * ISFHelper_fnCopyItems
1581 *
1582 * copys items to this folder
1583 */
1584static HRESULT WINAPI ISFHelper_fnCopyItems(
1585 ISFHelper *iface,
1586 IShellFolder* pSFFrom,
1587 UINT cidl,
1588 LPCITEMIDLIST *apidl)
1589{
1590 int i;
1591 IPersistFolder2 * ppf2=NULL;
1592 char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
1593 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1594
1595 TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1596
1597 IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
1598 if (ppf2)
1599 {
1600 LPITEMIDLIST pidl;
1601 if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
1602 {
1603 for (i=0; i<cidl; i++)
1604 {
1605 SHGetPathFromIDListA(pidl, szSrcPath);
1606 PathAddBackslashA(szSrcPath);
1607 _ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
1608
1609 strcpy(szDstPath, This->sMyPath);
1610 PathAddBackslashA(szDstPath);
1611 _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
1612 MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
1613 }
1614 ODIN_SHFree(pidl);
1615 }
1616 IPersistFolder2_Release(ppf2);
1617 }
1618 return S_OK;
1619}
1620
1621static ICOM_VTABLE(ISFHelper) shvt =
1622{
1623 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1624 ISFHelper_fnQueryInterface,
1625 ISFHelper_fnAddRef,
1626 ISFHelper_fnRelease,
1627 ISFHelper_fnGetUniqueName,
1628 ISFHelper_fnAddFolder,
1629 ISFHelper_fnDeleteItems,
1630 ISFHelper_fnCopyItems,
1631};
1632
1633/***********************************************************************
1634* [Desktopfolder] IShellFolder implementation
1635*/
1636static struct ICOM_VTABLE(IShellFolder2) sfdvt;
1637
1638static shvheader DesktopSFHeader [] =
1639{
1640 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
1641 { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1642 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1643 { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
1644 { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
1645};
1646#define DESKTOPSHELLVIEWCOLUMNS 5
1647
1648/**************************************************************************
1649* ISF_Desktop_Constructor
1650*
1651*/
1652IShellFolder * ISF_Desktop_Constructor()
1653{
1654 IGenericSFImpl * sf;
1655
1656 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1657 sf->ref=1;
1658 ICOM_VTBL(sf)=&unkvt;
1659 sf->lpvtblShellFolder=&sfdvt;
1660 sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1661 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
1662
1663 TRACE("(%p)\n",sf);
1664
1665 shell32_ObjCount++;
1666 return _IShellFolder_(sf);
1667}
1668
1669/**************************************************************************
1670 * ISF_Desktop_fnQueryInterface
1671 *
1672 * NOTES supports not IPersist/IPersistFolder
1673 */
1674static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1675 IShellFolder2 * iface,
1676 REFIID riid,
1677 LPVOID *ppvObj)
1678{
1679 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1680
1681 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1682
1683 *ppvObj = NULL;
1684
1685 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
1686 {
1687 *ppvObj = _IUnknown_(This);
1688 }
1689 else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
1690 {
1691 *ppvObj = _IShellFolder_(This);
1692 }
1693 else if(IsEqualIID(riid, &IID_IShellFolder2)) /*IShellFolder2*/
1694 {
1695 *ppvObj = _IShellFolder_(This);
1696 }
1697
1698 if(*ppvObj)
1699 {
1700 IUnknown_AddRef((IUnknown*)(*ppvObj));
1701 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1702 return S_OK;
1703 }
1704 TRACE("-- Interface: E_NOINTERFACE\n");
1705 return E_NOINTERFACE;
1706}
1707
1708/**************************************************************************
1709* ISF_Desktop_fnParseDisplayName
1710*
1711* NOTES
1712* "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1713* to MyComputer
1714*/
1715static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1716 IShellFolder2 * iface,
1717 HWND hwndOwner,
1718 LPBC pbcReserved,
1719 LPOLESTR lpszDisplayName,
1720 DWORD *pchEaten,
1721 LPITEMIDLIST *ppidl,
1722 DWORD *pdwAttributes)
1723{
1724 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1725
1726 LPCWSTR szNext=NULL;
1727 LPITEMIDLIST pidlTemp=NULL;
1728 HRESULT hr=E_OUTOFMEMORY;
1729
1730 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1731 This,hwndOwner,pbcReserved,lpszDisplayName,
1732 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1733
1734 *ppidl = 0;
1735 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1736
1737 /* fixme no real parsing implemented */
1738 pidlTemp = _ILCreateMyComputer();
1739 szNext = lpszDisplayName;
1740
1741 if (szNext && *szNext)
1742 {
1743 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1744 }
1745 else
1746 {
1747 hr = S_OK;
1748
1749 if (pdwAttributes && *pdwAttributes)
1750 {
1751 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
1752 }
1753 }
1754
1755 *ppidl = pidlTemp;
1756
1757 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1758
1759 return hr;
1760}
1761
1762/**************************************************************************
1763* ISF_Desktop_fnEnumObjects
1764*/
1765static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1766 IShellFolder2 * iface,
1767 HWND hwndOwner,
1768 DWORD dwFlags,
1769 LPENUMIDLIST* ppEnumIDList)
1770{
1771 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1772
1773 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1774
1775 *ppEnumIDList = NULL;
1776 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1777
1778 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1779
1780 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1781
1782 return S_OK;
1783}
1784
1785/**************************************************************************
1786* ISF_Desktop_fnBindToObject
1787*/
1788static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
1789 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1790{
1791 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1792 GUID const * clsid;
1793 IShellFolder *pShellFolder, *pSubFolder;
1794
1795 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
1796 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
1797
1798 *ppvOut = NULL;
1799
1800 if ((clsid=_ILGetGUIDPointer(pidl)))
1801 {
1802 if ( IsEqualIID(clsid, &CLSID_MyComputer))
1803 {
1804 pShellFolder = ISF_MyComputer_Constructor();
1805 }
1806 else
1807 {
1808 /* shell extension */
1809 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1810 {
1811 return E_INVALIDARG;
1812 }
1813 }
1814 }
1815 else
1816 {
1817 /* file system folder on the desktop */
1818 LPITEMIDLIST deskpidl, firstpidl, completepidl;
1819 IPersistFolder * ppf;
1820
1821 /* combine pidls */
1822 SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
1823 firstpidl = ODIN_ILCloneFirst(pidl);
1824 completepidl = ODIN_ILCombine(deskpidl, firstpidl);
1825
1826 pShellFolder = IShellFolder_Constructor(NULL, NULL);
1827 if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf)))
1828 {
1829 IPersistFolder_Initialize(ppf, completepidl);
1830 IPersistFolder_Release(ppf);
1831 }
1832 ODIN_ILFree(completepidl);
1833 ODIN_ILFree(deskpidl);
1834 ODIN_ILFree(firstpidl);
1835 }
1836
1837 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1838 {
1839 *ppvOut = pShellFolder;
1840 }
1841 else /* go deeper */
1842 {
1843 IShellFolder_BindToObject(pShellFolder, ODIN_ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1844 IShellFolder_Release(pShellFolder);
1845 *ppvOut = pSubFolder;
1846 }
1847
1848 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1849
1850 return S_OK;
1851}
1852
1853/**************************************************************************
1854* ISF_Desktop_fnCreateViewObject
1855*/
1856static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
1857 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1858{
1859 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1860
1861 LPSHELLVIEW pShellView;
1862 HRESULT hr = E_INVALIDARG;
1863
1864 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
1865
1866 if(ppvOut)
1867 {
1868 *ppvOut = NULL;
1869
1870 if(IsEqualIID(riid, &IID_IDropTarget))
1871 {
1872 WARN("IDropTarget not implemented\n");
1873 hr = E_NOTIMPL;
1874 }
1875 else if(IsEqualIID(riid, &IID_IContextMenu))
1876 {
1877 WARN("IContextMenu not implemented\n");
1878 hr = E_NOTIMPL;
1879 }
1880 else if(IsEqualIID(riid, &IID_IShellView))
1881 {
1882 pShellView = IShellView_Constructor((IShellFolder*)iface);
1883 if(pShellView)
1884 {
1885 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1886 IShellView_Release(pShellView);
1887 }
1888 }
1889 }
1890 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1891 return hr;
1892}
1893
1894/**************************************************************************
1895* ISF_Desktop_fnGetAttributesOf
1896*/
1897static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
1898 IShellFolder2 * iface,
1899 UINT cidl,
1900 LPCITEMIDLIST *apidl,
1901 DWORD *rgfInOut)
1902{
1903 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1904
1905 HRESULT hr = S_OK;
1906
1907 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1908
1909 if ( (!cidl) || (!apidl) || (!rgfInOut))
1910 return E_INVALIDARG;
1911
1912 while (cidl > 0 && *apidl)
1913 {
1914 pdump (*apidl);
1915 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1916 apidl++;
1917 cidl--;
1918 }
1919
1920 TRACE("-- result=0x%08lx\n",*rgfInOut);
1921
1922 return hr;
1923}
1924
1925/**************************************************************************
1926* ISF_Desktop_fnGetDisplayNameOf
1927*
1928* NOTES
1929* special case: pidl = null gives desktop-name back
1930*/
1931static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1932 IShellFolder2 * iface,
1933 LPCITEMIDLIST pidl,
1934 DWORD dwFlags,
1935 LPSTRRET strRet)
1936{
1937 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1938
1939 CHAR szPath[MAX_PATH]= "";
1940
1941 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1942 pdump(pidl);
1943
1944 if(!strRet) return E_INVALIDARG;
1945
1946 if(!pidl)
1947 {
1948 HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1949 }
1950 else if ( _ILIsPidlSimple(pidl) )
1951 {
1952 _ILSimpleGetText(pidl, szPath, MAX_PATH);
1953 }
1954 else
1955 {
1956 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
1957 return E_OUTOFMEMORY;
1958 }
1959 strRet->uType = STRRET_CSTRA;
1960 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1961
1962
1963 TRACE("-- (%p)->(%s)\n", This, szPath);
1964 return S_OK;
1965}
1966
1967static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
1968 IShellFolder2 * iface,
1969 GUID *pguid)
1970{
1971 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1972 FIXME("(%p)\n",This);
1973 return E_NOTIMPL;
1974}
1975static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
1976 IShellFolder2 * iface,
1977 IEnumExtraSearch **ppenum)
1978{
1979 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1980 FIXME("(%p)\n",This);
1981 return E_NOTIMPL;
1982}
1983static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
1984 IShellFolder2 * iface,
1985 DWORD dwRes,
1986 ULONG *pSort,
1987 ULONG *pDisplay)
1988{
1989 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1990
1991 TRACE("(%p)\n",This);
1992
1993 if (pSort) *pSort = 0;
1994 if (pDisplay) *pDisplay = 0;
1995
1996 return S_OK;
1997}
1998static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
1999 IShellFolder2 * iface,
2000 UINT iColumn,
2001 DWORD *pcsFlags)
2002{
2003 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2004
2005 TRACE("(%p)\n",This);
2006
2007 if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2008
2009 *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
2010
2011 return S_OK;
2012}
2013static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
2014 IShellFolder2 * iface,
2015 LPCITEMIDLIST pidl,
2016 const SHCOLUMNID *pscid,
2017 VARIANT *pv)
2018{
2019 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2020 FIXME("(%p)\n",This);
2021
2022 return E_NOTIMPL;
2023}
2024static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
2025 IShellFolder2 * iface,
2026 LPCITEMIDLIST pidl,
2027 UINT iColumn,
2028 SHELLDETAILS *psd)
2029{
2030 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2031 HRESULT hr = E_FAIL;;
2032
2033 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2034
2035 if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2036
2037 if (!pidl)
2038 {
2039 psd->fmt = DesktopSFHeader[iColumn].fmt;
2040 psd->cxChar = DesktopSFHeader[iColumn].cxChar;
2041 psd->str.uType = STRRET_CSTRA;
2042 LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2043 return S_OK;
2044 }
2045 else
2046 {
2047 /* the data from the pidl */
2048 switch(iColumn)
2049 {
2050 case 0: /* name */
2051 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2052 break;
2053 case 1: /* size */
2054 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
2055 break;
2056 case 2: /* type */
2057 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2058 break;
2059 case 3: /* date */
2060 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
2061 break;
2062 case 4: /* attributes */
2063 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
2064 break;
2065 }
2066 hr = S_OK;
2067 psd->str.uType = STRRET_CSTRA;
2068 }
2069
2070 return hr;
2071}
2072static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
2073 IShellFolder2 * iface,
2074 LPCWSTR pwszName,
2075 SHCOLUMNID *pscid)
2076{
2077 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2078 FIXME("(%p)\n",This);
2079 return E_NOTIMPL;
2080}
2081
2082static ICOM_VTABLE(IShellFolder2) sfdvt =
2083{
2084 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2085 ISF_Desktop_fnQueryInterface,
2086 IShellFolder_fnAddRef,
2087 IShellFolder_fnRelease,
2088 ISF_Desktop_fnParseDisplayName,
2089 ISF_Desktop_fnEnumObjects,
2090 ISF_Desktop_fnBindToObject,
2091 IShellFolder_fnBindToStorage,
2092 IShellFolder_fnCompareIDs,
2093 ISF_Desktop_fnCreateViewObject,
2094 ISF_Desktop_fnGetAttributesOf,
2095 IShellFolder_fnGetUIObjectOf,
2096 ISF_Desktop_fnGetDisplayNameOf,
2097 IShellFolder_fnSetNameOf,
2098
2099 /* ShellFolder2 */
2100 ISF_Desktop_fnGetDefaultSearchGUID,
2101 ISF_Desktop_fnEnumSearches,
2102 ISF_Desktop_fnGetDefaultColumn,
2103 ISF_Desktop_fnGetDefaultColumnState,
2104 ISF_Desktop_fnGetDetailsEx,
2105 ISF_Desktop_fnGetDetailsOf,
2106 ISF_Desktop_fnMapNameToSCID
2107};
2108
2109
2110/***********************************************************************
2111* IShellFolder [MyComputer] implementation
2112*/
2113
2114static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
2115
2116static shvheader MyComputerSFHeader [] =
2117{
2118 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
2119 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2120 { IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2121 { IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2122};
2123#define MYCOMPUTERSHELLVIEWCOLUMNS 4
2124
2125/**************************************************************************
2126* ISF_MyComputer_Constructor
2127*/
2128static IShellFolder * ISF_MyComputer_Constructor(void)
2129{
2130 IGenericSFImpl * sf;
2131
2132 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
2133 sf->ref=1;
2134
2135 ICOM_VTBL(sf)=&unkvt;
2136 sf->lpvtblShellFolder=&sfmcvt;
2137 sf->lpvtblPersistFolder2 = &psfvt;
2138 sf->pclsid = (CLSID*)&CLSID_SFMyComp;
2139 sf->absPidl=_ILCreateMyComputer(); /* my qualified pidl */
2140 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
2141
2142 TRACE("(%p)\n",sf);
2143
2144 shell32_ObjCount++;
2145 return _IShellFolder_(sf);
2146}
2147
2148/**************************************************************************
2149* ISF_MyComputer_fnParseDisplayName
2150*/
2151static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
2152 IShellFolder2 * iface,
2153 HWND hwndOwner,
2154 LPBC pbcReserved,
2155 LPOLESTR lpszDisplayName,
2156 DWORD *pchEaten,
2157 LPITEMIDLIST *ppidl,
2158 DWORD *pdwAttributes)
2159{
2160 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2161
2162 HRESULT hr = E_OUTOFMEMORY;
2163 LPCWSTR szNext=NULL;
2164 WCHAR szElement[MAX_PATH];
2165 CHAR szTempA[MAX_PATH];
2166 LPITEMIDLIST pidlTemp;
2167
2168 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
2169 This,hwndOwner,pbcReserved,lpszDisplayName,
2170 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
2171
2172 *ppidl = 0;
2173 if (pchEaten) *pchEaten = 0; /* strange but like the original */
2174
2175 /* do we have an absolute path name ? */
2176 if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
2177 lpszDisplayName[2] == (WCHAR)'\\')
2178 {
2179 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
2180 WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
2181 pidlTemp = _ILCreateDrive(szTempA);
2182
2183 if (szNext && *szNext)
2184 {
2185 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
2186 }
2187 else
2188 {
2189 if (pdwAttributes && *pdwAttributes)
2190 {
2191 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
2192 }
2193 hr = S_OK;
2194 }
2195 *ppidl = pidlTemp;
2196 }
2197
2198 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
2199
2200 return hr;
2201}
2202
2203/**************************************************************************
2204* ISF_MyComputer_fnEnumObjects
2205*/
2206static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
2207 IShellFolder2 * iface,
2208 HWND hwndOwner,
2209 DWORD dwFlags,
2210 LPENUMIDLIST* ppEnumIDList)
2211{
2212 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2213
2214 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
2215
2216 *ppEnumIDList = NULL;
2217 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
2218
2219 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
2220
2221 if(!*ppEnumIDList) return E_OUTOFMEMORY;
2222
2223 return S_OK;
2224}
2225
2226/**************************************************************************
2227* ISF_MyComputer_fnBindToObject
2228*/
2229static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
2230 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
2231{
2232 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2233 GUID const * clsid;
2234 IShellFolder *pShellFolder, *pSubFolder;
2235 LPITEMIDLIST pidltemp;
2236
2237 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
2238 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
2239
2240 if(!pidl || !ppvOut) return E_INVALIDARG;
2241
2242 *ppvOut = NULL;
2243
2244 if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
2245 {
2246 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
2247 {
2248 return E_FAIL;
2249 }
2250 }
2251 else
2252 {
2253 if (!_ILIsDrive(pidl)) return E_INVALIDARG;
2254
2255 pidltemp = ODIN_ILCloneFirst(pidl);
2256 pShellFolder = IShellFolder_Constructor(iface, pidltemp);
2257 ODIN_ILFree(pidltemp);
2258 }
2259
2260 if (_ILIsPidlSimple(pidl)) /* no sub folders */
2261 {
2262 *ppvOut = pShellFolder;
2263 }
2264 else /* go deeper */
2265 {
2266 IShellFolder_BindToObject(pShellFolder, ODIN_ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder);
2267 IShellFolder_Release(pShellFolder);
2268 *ppvOut = pSubFolder;
2269 }
2270
2271 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
2272
2273 return S_OK;
2274}
2275
2276/**************************************************************************
2277* ISF_MyComputer_fnCreateViewObject
2278*/
2279static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
2280 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
2281{
2282 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2283
2284 LPSHELLVIEW pShellView;
2285 HRESULT hr = E_INVALIDARG;
2286
2287 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
2288
2289 if(ppvOut)
2290 {
2291 *ppvOut = NULL;
2292
2293 if(IsEqualIID(riid, &IID_IDropTarget))
2294 {
2295 WARN("IDropTarget not implemented\n");
2296 hr = E_NOTIMPL;
2297 }
2298 else if(IsEqualIID(riid, &IID_IContextMenu))
2299 {
2300 WARN("IContextMenu not implemented\n");
2301 hr = E_NOTIMPL;
2302 }
2303 else if(IsEqualIID(riid, &IID_IShellView))
2304 {
2305 pShellView = IShellView_Constructor((IShellFolder*)iface);
2306 if(pShellView)
2307 {
2308 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
2309 IShellView_Release(pShellView);
2310 }
2311 }
2312 }
2313 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
2314 return hr;
2315}
2316
2317/**************************************************************************
2318* ISF_MyComputer_fnGetAttributesOf
2319*/
2320static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
2321 IShellFolder2 * iface,
2322 UINT cidl,
2323 LPCITEMIDLIST *apidl,
2324 DWORD *rgfInOut)
2325{
2326 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2327
2328 HRESULT hr = S_OK;
2329
2330 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
2331
2332 if ( (!cidl) || (!apidl) || (!rgfInOut))
2333 return E_INVALIDARG;
2334
2335 while (cidl > 0 && *apidl)
2336 {
2337 pdump (*apidl);
2338 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
2339 apidl++;
2340 cidl--;
2341 }
2342
2343 TRACE("-- result=0x%08lx\n",*rgfInOut);
2344 return hr;
2345}
2346
2347/**************************************************************************
2348* ISF_MyComputer_fnGetDisplayNameOf
2349*
2350* NOTES
2351* The desktopfolder creates only complete paths (SHGDN_FORPARSING).
2352* SHGDN_INFOLDER makes no sense.
2353*/
2354static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
2355 IShellFolder2 * iface,
2356 LPCITEMIDLIST pidl,
2357 DWORD dwFlags,
2358 LPSTRRET strRet)
2359{
2360 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2361
2362 char szPath[MAX_PATH], szDrive[18];
2363 int len = 0;
2364 BOOL bSimplePidl;
2365
2366 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
2367 pdump(pidl);
2368
2369 if(!strRet) return E_INVALIDARG;
2370
2371 szPath[0]=0x00; szDrive[0]=0x00;
2372
2373
2374 bSimplePidl = _ILIsPidlSimple(pidl);
2375
2376 if (_ILIsSpecialFolder(pidl))
2377 {
2378 /* take names of special folders only if its only this folder */
2379 if ( bSimplePidl )
2380 {
2381 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2382 }
2383 }
2384 else
2385 {
2386 if (!_ILIsDrive(pidl))
2387 {
2388 ERR("Wrong pidl type\n");
2389 return E_INVALIDARG;
2390 }
2391
2392 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2393
2394 /* long view "lw_name (C:)" */
2395 if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
2396 {
2397 DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
2398
2399#ifdef __WIN32OS2__
2400//CB: floppy drives have a fixed name
2401 if ((szPath[0] == 'A') || (szPath[0] == 'a') || (szPath[0] == 'B') || (szPath[0] == 'b'))
2402 {
2403 //floppy
2404 strncpy(szDrive,szPath,2);
2405 //3.5 floppy
2406 LoadStringA(shell32_hInstance,IDS_35FLOPPY,szPath,sizeof(szPath)-10);
2407 //CB: todo: 5.25 floppy check
2408 strcat(szPath," (");
2409 strncat(szPath,szDrive,2);
2410 strcat(szPath,")");
2411 } else
2412 {
2413 GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2414 strcat (szDrive," (");
2415 strncat (szDrive, szPath, 2);
2416 strcat (szDrive,")");
2417 strcpy (szPath, szDrive);
2418 }
2419#else
2420 GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2421 strcat (szDrive," (");
2422 strncat (szDrive, szPath, 2);
2423 strcat (szDrive,")");
2424 strcpy (szPath, szDrive);
2425#endif
2426 }
2427 }
2428
2429 if (!bSimplePidl) /* go deeper if needed */
2430 {
2431 PathAddBackslashA(szPath);
2432 len = strlen(szPath);
2433
2434 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
2435 return E_OUTOFMEMORY;
2436 }
2437 strRet->uType = STRRET_CSTRA;
2438 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
2439
2440
2441 TRACE("-- (%p)->(%s)\n", This, szPath);
2442 return S_OK;
2443}
2444
2445static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
2446 IShellFolder2 * iface,
2447 GUID *pguid)
2448{
2449 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2450 FIXME("(%p)\n",This);
2451 return E_NOTIMPL;
2452}
2453static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
2454 IShellFolder2 * iface,
2455 IEnumExtraSearch **ppenum)
2456{
2457 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2458 FIXME("(%p)\n",This);
2459 return E_NOTIMPL;
2460}
2461static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
2462 IShellFolder2 * iface,
2463 DWORD dwRes,
2464 ULONG *pSort,
2465 ULONG *pDisplay)
2466{
2467 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2468
2469 TRACE("(%p)\n",This);
2470
2471 if (pSort) *pSort = 0;
2472 if (pDisplay) *pDisplay = 0;
2473
2474 return S_OK;
2475}
2476static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
2477 IShellFolder2 * iface,
2478 UINT iColumn,
2479 DWORD *pcsFlags)
2480{
2481 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2482
2483 TRACE("(%p)\n",This);
2484
2485 if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2486
2487 *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
2488
2489 return S_OK;
2490}
2491static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
2492 IShellFolder2 * iface,
2493 LPCITEMIDLIST pidl,
2494 const SHCOLUMNID *pscid,
2495 VARIANT *pv)
2496{
2497 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2498 FIXME("(%p)\n",This);
2499
2500 return E_NOTIMPL;
2501}
2502
2503/* fixme: drive size >4GB is rolling over */
2504static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
2505 IShellFolder2 * iface,
2506 LPCITEMIDLIST pidl,
2507 UINT iColumn,
2508 SHELLDETAILS *psd)
2509{
2510 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2511 HRESULT hr;
2512
2513 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2514
2515 if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2516
2517 if (!pidl)
2518 {
2519 psd->fmt = MyComputerSFHeader[iColumn].fmt;
2520 psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
2521 psd->str.uType = STRRET_CSTRA;
2522 LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2523 return S_OK;
2524 }
2525 else
2526 {
2527 char szPath[MAX_PATH];
2528 ULARGE_INTEGER ulBytes;
2529
2530 psd->str.u.cStr[0] = 0x00;
2531 psd->str.uType = STRRET_CSTRA;
2532 switch(iColumn)
2533 {
2534 case 0: /* name */
2535 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2536 break;
2537 case 1: /* type */
2538 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2539 break;
2540 case 2: /* total size */
2541 if (_ILIsDrive(pidl))
2542 {
2543 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2544 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
2545 StrFormatByteSizeA(ulBytes.LowPart, psd->str.u.cStr, MAX_PATH);
2546 }
2547 break;
2548 case 3: /* free size */
2549 if (_ILIsDrive(pidl))
2550 {
2551 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2552 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
2553 StrFormatByteSizeA(ulBytes.LowPart, psd->str.u.cStr, MAX_PATH);
2554 }
2555 break;
2556 }
2557 hr = S_OK;
2558 }
2559
2560 return hr;
2561}
2562static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
2563 IShellFolder2 * iface,
2564 LPCWSTR pwszName,
2565 SHCOLUMNID *pscid)
2566{
2567 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2568 FIXME("(%p)\n",This);
2569 return E_NOTIMPL;
2570}
2571
2572static ICOM_VTABLE(IShellFolder2) sfmcvt =
2573{
2574 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2575 IShellFolder_fnQueryInterface,
2576 IShellFolder_fnAddRef,
2577 IShellFolder_fnRelease,
2578 ISF_MyComputer_fnParseDisplayName,
2579 ISF_MyComputer_fnEnumObjects,
2580 ISF_MyComputer_fnBindToObject,
2581 IShellFolder_fnBindToStorage,
2582 IShellFolder_fnCompareIDs,
2583 ISF_MyComputer_fnCreateViewObject,
2584 ISF_MyComputer_fnGetAttributesOf,
2585 IShellFolder_fnGetUIObjectOf,
2586 ISF_MyComputer_fnGetDisplayNameOf,
2587 IShellFolder_fnSetNameOf,
2588
2589 /* ShellFolder2 */
2590 ISF_MyComputer_fnGetDefaultSearchGUID,
2591 ISF_MyComputer_fnEnumSearches,
2592 ISF_MyComputer_fnGetDefaultColumn,
2593 ISF_MyComputer_fnGetDefaultColumnState,
2594 ISF_MyComputer_fnGetDetailsEx,
2595 ISF_MyComputer_fnGetDetailsOf,
2596 ISF_MyComputer_fnMapNameToSCID
2597};
2598
2599
2600/************************************************************************
2601 * ISFPersistFolder_QueryInterface (IUnknown)
2602 *
2603 */
2604static HRESULT WINAPI ISFPersistFolder2_QueryInterface(
2605 IPersistFolder2 * iface,
2606 REFIID iid,
2607 LPVOID* ppvObj)
2608{
2609 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2610
2611 TRACE("(%p)\n", This);
2612
2613 return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
2614}
2615
2616/************************************************************************
2617 * ISFPersistFolder_AddRef (IUnknown)
2618 *
2619 */
2620static ULONG WINAPI ISFPersistFolder2_AddRef(
2621 IPersistFolder2 * iface)
2622{
2623 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2624
2625 TRACE("(%p)\n", This);
2626
2627 return IUnknown_AddRef(This->pUnkOuter);
2628}
2629
2630/************************************************************************
2631 * ISFPersistFolder_Release (IUnknown)
2632 *
2633 */
2634static ULONG WINAPI ISFPersistFolder2_Release(
2635 IPersistFolder2 * iface)
2636{
2637 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2638
2639 TRACE("(%p)\n", This);
2640
2641 return IUnknown_Release(This->pUnkOuter);
2642}
2643
2644/************************************************************************
2645 * ISFPersistFolder_GetClassID (IPersist)
2646 */
2647static HRESULT WINAPI ISFPersistFolder2_GetClassID(
2648 IPersistFolder2 * iface,
2649 CLSID * lpClassId)
2650{
2651 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2652
2653 TRACE("(%p)\n", This);
2654
2655 if (!lpClassId) return E_POINTER;
2656 *lpClassId = *This->pclsid;
2657
2658 return S_OK;
2659}
2660
2661/************************************************************************
2662 * ISFPersistFolder_Initialize (IPersistFolder)
2663 *
2664 * NOTES
2665 * sMyPath is not set. Don't know how to handle in a non rooted environment.
2666 */
2667static HRESULT WINAPI ISFPersistFolder2_Initialize(
2668 IPersistFolder2 * iface,
2669 LPCITEMIDLIST pidl)
2670{
2671 char sTemp[MAX_PATH];
2672 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2673
2674 TRACE("(%p)->(%p)\n", This, pidl);
2675
2676 /* free the old stuff */
2677 if(This->absPidl)
2678 {
2679 ODIN_SHFree(This->absPidl);
2680 This->absPidl = NULL;
2681 }
2682 if(This->sMyPath)
2683 {
2684 ODIN_SHFree(This->sMyPath);
2685 This->sMyPath = NULL;
2686 }
2687
2688 /* set my pidl */
2689 This->absPidl = ILClone(pidl);
2690
2691 /* set my path */
2692 if (SHGetPathFromIDListA(pidl, sTemp))
2693 {
2694 This->sMyPath = ODIN_SHAlloc(strlen(sTemp)+1);
2695 strcpy(This->sMyPath, sTemp);
2696 }
2697
2698 TRACE("--(%p)->(%s)\n", This, This->sMyPath);
2699
2700 return S_OK;
2701}
2702
2703/**************************************************************************
2704* IPersistFolder2_fnGetCurFolder
2705*/
2706static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder(
2707 IPersistFolder2 * iface,
2708 LPITEMIDLIST * pidl)
2709{
2710 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2711
2712 TRACE("(%p)->(%p)\n",This, pidl);
2713
2714 if (!pidl) return E_POINTER;
2715
2716 *pidl = ILClone(This->absPidl);
2717
2718 return S_OK;
2719}
2720
2721static ICOM_VTABLE(IPersistFolder2) psfvt =
2722{
2723 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2724 ISFPersistFolder2_QueryInterface,
2725 ISFPersistFolder2_AddRef,
2726 ISFPersistFolder2_Release,
2727 ISFPersistFolder2_GetClassID,
2728 ISFPersistFolder2_Initialize,
2729 ISFPersistFolder2_fnGetCurFolder
2730};
2731
2732/****************************************************************************
2733 * ISFDropTarget implementation
2734 */
2735static BOOL ISFDropTarget_QueryDrop(
2736 IDropTarget *iface,
2737 DWORD dwKeyState,
2738 LPDWORD pdwEffect)
2739{
2740 DWORD dwEffect = *pdwEffect;
2741
2742 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2743
2744 *pdwEffect = DROPEFFECT_NONE;
2745
2746 if (This->fAcceptFmt)
2747 { /* Does our interpretation of the keystate ... */
2748 *pdwEffect = KeyStateToDropEffect(dwKeyState);
2749
2750 /* ... matches the desired effect ? */
2751 if (dwEffect & *pdwEffect)
2752 {
2753 return TRUE;
2754 }
2755 }
2756 return FALSE;
2757}
2758
2759static HRESULT WINAPI ISFDropTarget_QueryInterface(
2760 IDropTarget *iface,
2761 REFIID riid,
2762 LPVOID *ppvObj)
2763{
2764 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2765
2766 TRACE("(%p)\n", This);
2767
2768 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
2769}
2770
2771static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
2772{
2773 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2774
2775 TRACE("(%p)\n", This);
2776
2777 return IUnknown_AddRef(This->pUnkOuter);
2778}
2779
2780static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
2781{
2782 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2783
2784 TRACE("(%p)\n", This);
2785
2786 return IUnknown_Release(This->pUnkOuter);
2787}
2788
2789static HRESULT WINAPI ISFDropTarget_DragEnter(
2790 IDropTarget *iface,
2791 IDataObject *pDataObject,
2792 DWORD dwKeyState,
2793 POINTL pt,
2794 DWORD *pdwEffect)
2795{
2796 FORMATETC fmt;
2797
2798 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2799
2800 TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
2801
2802 InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
2803
2804 This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
2805
2806 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2807
2808 return S_OK;
2809}
2810
2811static HRESULT WINAPI ISFDropTarget_DragOver(
2812 IDropTarget *iface,
2813 DWORD dwKeyState,
2814 POINTL pt,
2815 DWORD *pdwEffect)
2816{
2817 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2818
2819 TRACE("(%p)\n",This);
2820
2821 if(!pdwEffect) return E_INVALIDARG;
2822
2823 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2824
2825 return S_OK;
2826}
2827
2828static HRESULT WINAPI ISFDropTarget_DragLeave(
2829 IDropTarget *iface)
2830{
2831 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2832
2833 TRACE("(%p)\n",This);
2834
2835 This->fAcceptFmt = FALSE;
2836
2837 return S_OK;
2838}
2839
2840static HRESULT WINAPI ISFDropTarget_Drop(
2841 IDropTarget *iface,
2842 IDataObject* pDataObject,
2843 DWORD dwKeyState,
2844 POINTL pt,
2845 DWORD *pdwEffect)
2846{
2847 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2848
2849 FIXME("(%p) object dropped\n",This);
2850
2851 return E_NOTIMPL;
2852}
2853
2854static struct ICOM_VTABLE(IDropTarget) dtvt =
2855{
2856 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2857 ISFDropTarget_QueryInterface,
2858 ISFDropTarget_AddRef,
2859 ISFDropTarget_Release,
2860 ISFDropTarget_DragEnter,
2861 ISFDropTarget_DragOver,
2862 ISFDropTarget_DragLeave,
2863 ISFDropTarget_Drop
2864};
Note: See TracBrowser for help on using the repository browser.