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

Last change on this file since 21512 was 21512, checked in by dmik, 15 years ago

Aligned the STRRET definition and made it available through shlwapi.h and shlobj.h for compatibility with Win32.

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