4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
7 * IShellFolder2 and related interfaces
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
28 /***************************************************************************
29 * SHELL32_GetCustomFolderAttributeFromPath (internal function)
31 * Gets a value from the folder's desktop.ini file, if one exists.
34 * pwszFolderPath[I] Folder containing the desktop.ini file.
35 * pwszHeading [I] Heading in .ini file.
36 * pwszAttribute [I] Attribute in .ini file.
37 * pwszValue [O] Buffer to store value into.
38 * cchValue [I] Size in characters including NULL of buffer pointed to
42 * TRUE if returned non-NULL value.
45 static BOOL __inline
SHELL32_GetCustomFolderAttributeFromPath(
46 LPWSTR pwszFolderPath
, LPCWSTR pwszHeading
, LPCWSTR pwszAttribute
,
47 LPWSTR pwszValue
, DWORD cchValue
)
49 static const WCHAR wszDesktopIni
[] =
50 {'d','e','s','k','t','o','p','.','i','n','i',0};
51 static const WCHAR wszDefault
[] = {0};
53 PathAddBackslashW(pwszFolderPath
);
54 PathAppendW(pwszFolderPath
, wszDesktopIni
);
55 return GetPrivateProfileStringW(pwszHeading
, pwszAttribute
, wszDefault
,
56 pwszValue
, cchValue
, pwszFolderPath
);
59 /***************************************************************************
60 * GetNextElement (internal function)
62 * Gets a part of a string till the first backslash.
65 * pszNext [IN] string to get the element from
66 * pszOut [IN] pointer to buffer which receives string
67 * dwOut [IN] length of pszOut
70 * LPSTR pointer to first, not yet parsed char
73 LPCWSTR
GetNextElementW (LPCWSTR pszNext
, LPWSTR pszOut
, DWORD dwOut
)
75 LPCWSTR pszTail
= pszNext
;
78 TRACE ("(%s %p 0x%08x)\n", debugstr_w (pszNext
), pszOut
, dwOut
);
82 if (!pszNext
|| !*pszNext
)
85 while (*pszTail
&& (*pszTail
!= (WCHAR
) '\\'))
88 dwCopy
= pszTail
- pszNext
+ 1;
89 lstrcpynW (pszOut
, pszNext
, (dwOut
< dwCopy
) ? dwOut
: dwCopy
);
96 TRACE ("--(%s %s 0x%08x %p)\n", debugstr_w (pszNext
), debugstr_w (pszOut
), dwOut
, pszTail
);
100 HRESULT
SHELL32_ParseNextElement (IShellFolder2
* psf
, HWND hwndOwner
, LPBC pbc
,
101 LPITEMIDLIST
* pidlInOut
, LPOLESTR szNext
, DWORD
* pEaten
, DWORD
* pdwAttributes
)
103 HRESULT hr
= E_INVALIDARG
;
104 LPITEMIDLIST pidlIn
= pidlInOut
? *pidlInOut
: NULL
;
105 LPITEMIDLIST pidlOut
= NULL
;
106 LPITEMIDLIST pidlTemp
= NULL
;
107 CComPtr
<IShellFolder
> psfChild
;
109 TRACE ("(%p, %p, %p, %s)\n", psf
, pbc
, pidlIn
, debugstr_w (szNext
));
111 /* get the shellfolder for the child pidl and let it analyse further */
112 hr
= psf
->BindToObject(pidlIn
, pbc
, IID_PPV_ARG(IShellFolder
, &psfChild
));
116 hr
= psfChild
->ParseDisplayName(hwndOwner
, pbc
, szNext
, pEaten
, &pidlOut
, pdwAttributes
);
120 pidlTemp
= ILCombine (pidlIn
, pidlOut
);
135 *pidlInOut
= pidlTemp
;
137 TRACE ("-- pidl=%p ret=0x%08x\n", pidlInOut
? *pidlInOut
: NULL
, hr
);
141 /***********************************************************************
142 * SHELL32_CoCreateInitSF
144 * Creates a shell folder and initializes it with a pidl and a root folder
145 * via IPersistFolder3 or IPersistFolder.
148 * pathRoot can be NULL for Folders being a drive.
149 * In this case the absolute path is built from pidlChild (eg. C:)
151 static HRESULT
SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot
, LPCWSTR pathRoot
,
152 LPCITEMIDLIST pidlChild
, REFCLSID clsid
, IShellFolder
** ppsfOut
)
155 CComPtr
<IShellFolder
> pShellFolder
;
157 TRACE ("%p %s %p\n", pidlRoot
, debugstr_w(pathRoot
), pidlChild
);
159 hr
= SHCoCreateInstance(NULL
, &clsid
, NULL
, IID_PPV_ARG(IShellFolder
, &pShellFolder
));
162 LPITEMIDLIST pidlAbsolute
= ILCombine (pidlRoot
, pidlChild
);
163 CComPtr
<IPersistFolder
> ppf
;
164 CComPtr
<IPersistFolder3
> ppf3
;
166 if (SUCCEEDED(pShellFolder
->QueryInterface(IID_PPV_ARG(IPersistFolder3
, &ppf3
))))
168 PERSIST_FOLDER_TARGET_INFO ppfti
;
170 ZeroMemory (&ppfti
, sizeof (ppfti
));
172 /* fill the PERSIST_FOLDER_TARGET_INFO */
173 ppfti
.dwAttributes
= -1;
179 lstrcpynW (ppfti
.szTargetParsingName
, pathRoot
, MAX_PATH
- 1);
180 PathAddBackslashW(ppfti
.szTargetParsingName
); /* FIXME: why have drives a backslash here ? */
185 int len
= wcslen(ppfti
.szTargetParsingName
);
187 if (!_ILSimpleGetTextW(pidlChild
, ppfti
.szTargetParsingName
+ len
, MAX_PATH
- len
))
191 ppf3
->InitializeEx(NULL
, pidlAbsolute
, &ppfti
);
193 else if (SUCCEEDED((hr
= pShellFolder
->QueryInterface(IID_PPV_ARG(IPersistFolder
, &ppf
)))))
195 ppf
->Initialize(pidlAbsolute
);
197 ILFree (pidlAbsolute
);
200 *ppsfOut
= pShellFolder
.Detach();
202 TRACE ("-- (%p) ret=0x%08x\n", *ppsfOut
, hr
);
207 void SHELL32_GetCLSIDForDirectory(LPCWSTR pathRoot
, LPCITEMIDLIST pidl
, CLSID
* pclsidFolder
)
209 static const WCHAR wszDotShellClassInfo
[] = {
210 '.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0 };
211 static const WCHAR wszCLSID
[] = {'C','L','S','I','D',0};
212 WCHAR wszCLSIDValue
[CHARS_IN_GUID
], wszFolderPath
[MAX_PATH
], *pwszPathTail
= wszFolderPath
;
214 /* see if folder CLSID should be overridden by desktop.ini file */
216 lstrcpynW(wszFolderPath
, pathRoot
, MAX_PATH
);
217 pwszPathTail
= PathAddBackslashW(wszFolderPath
);
220 _ILSimpleGetTextW(pidl
,pwszPathTail
,MAX_PATH
- (int)(pwszPathTail
- wszFolderPath
));
222 if (SHELL32_GetCustomFolderAttributeFromPath (wszFolderPath
,
223 wszDotShellClassInfo
, wszCLSID
, wszCLSIDValue
, CHARS_IN_GUID
))
224 CLSIDFromString (wszCLSIDValue
, pclsidFolder
);
227 /***********************************************************************
228 * SHELL32_BindToFS [Internal]
230 * Common code for IShellFolder_BindToObject.
233 * pidlRoot [I] The parent shell folder's absolute pidl.
234 * pathRoot [I] Absolute dos path of the parent shell folder.
235 * pidlComplete [I] PIDL of the child. Relative to pidlRoot.
236 * riid [I] GUID of the interface, which ppvOut shall be bound to.
237 * ppvOut [O] A reference to the child's interface (riid).
240 * pidlComplete has to contain at least one non empty SHITEMID.
241 * This function makes special assumptions on the shell namespace, which
242 * means you probably can't use it for your IShellFolder implementation.
244 HRESULT
SHELL32_BindToFS (LPCITEMIDLIST pidlRoot
,
245 LPCWSTR pathRoot
, LPCITEMIDLIST pidlComplete
, REFIID riid
, LPVOID
* ppvOut
)
247 CComPtr
<IShellFolder
> pSF
;
249 LPCITEMIDLIST pidlChild
;
251 if (!pidlRoot
|| !ppvOut
|| !pidlComplete
|| !pidlComplete
->mkid
.cb
)
254 if (_ILIsValue(pidlComplete
))
256 ERR("Binding to file is unimplemented\n");
257 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
259 if (!_ILIsFolder(pidlComplete
) && !_ILIsDrive(pidlComplete
))
261 ERR("Got an unknown type of pidl!\n");
267 pidlChild
= (_ILIsPidlSimple (pidlComplete
)) ? pidlComplete
: ILCloneFirst (pidlComplete
);
269 CLSID clsidFolder
= CLSID_ShellFSFolder
;
270 DWORD attributes
= _ILGetFileAttributes(ILFindLastID(pidlChild
), NULL
, 0);
271 if ((attributes
& (FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_READONLY
)) != 0)
272 SHELL32_GetCLSIDForDirectory(pathRoot
, pidlChild
, &clsidFolder
);
274 hr
= SHELL32_CoCreateInitSF (pidlRoot
, pathRoot
, pidlChild
, clsidFolder
, &pSF
);
276 if (pidlChild
!= pidlComplete
)
277 ILFree ((LPITEMIDLIST
)pidlChild
);
279 if (SUCCEEDED (hr
)) {
280 if (_ILIsPidlSimple (pidlComplete
)) {
282 hr
= pSF
->QueryInterface(riid
, ppvOut
);
285 hr
= pSF
->BindToObject(ILGetNext (pidlComplete
), NULL
, riid
, ppvOut
);
289 TRACE ("-- returning (%p) %08x\n", *ppvOut
, hr
);
294 HRESULT
SHELL32_BindToGuidItem(LPCITEMIDLIST pidlRoot
,
295 PCUIDLIST_RELATIVE pidl
,
300 CComPtr
<IPersistFolder
> pFolder
;
303 if (!pidlRoot
|| !ppvOut
|| !pidl
|| !pidl
->mkid
.cb
)
308 GUID
*pGUID
= _ILGetGUIDPointer(pidl
);
311 ERR("SHELL32_BindToGuidItem called for non guid item!\n");
315 hr
= SHCoCreateInstance(NULL
, pGUID
, NULL
, IID_PPV_ARG(IPersistFolder
, &pFolder
));
319 if (_ILIsPidlSimple (pidl
))
321 hr
= pFolder
->Initialize(ILCombine(pidlRoot
, pidl
));
325 return pFolder
->QueryInterface(riid
, ppvOut
);
329 LPITEMIDLIST pidlChild
= ILCloneFirst (pidl
);
331 return E_OUTOFMEMORY
;
333 hr
= pFolder
->Initialize(ILCombine(pidlRoot
, pidlChild
));
338 CComPtr
<IShellFolder
> psf
;
339 hr
= pFolder
->QueryInterface(IID_PPV_ARG(IShellFolder
, &psf
));
343 return psf
->BindToObject(ILGetNext (pidl
), pbcReserved
, riid
, ppvOut
);
347 /***********************************************************************
348 * SHELL32_GetDisplayNameOfChild
350 * Retrieves the display name of a child object of a shellfolder.
352 * For a pidl eg. [subpidl1][subpidl2][subpidl3]:
353 * - it binds to the child shellfolder [subpidl1]
354 * - asks it for the displayname of [subpidl2][subpidl3]
356 * Is possible the pidl is a simple pidl. In this case it asks the
357 * subfolder for the displayname of an empty pidl. The subfolder
358 * returns the own displayname eg. "::{guid}". This is used for
359 * virtual folders with the registry key WantsFORPARSING set.
361 HRESULT
SHELL32_GetDisplayNameOfChild (IShellFolder2
* psf
,
362 LPCITEMIDLIST pidl
, DWORD dwFlags
, LPSTRRET strRet
)
364 LPITEMIDLIST pidlFirst
= ILCloneFirst(pidl
);
366 return E_OUTOFMEMORY
;
368 CComPtr
<IShellFolder
> psfChild
;
369 HRESULT hr
= psf
->BindToObject(pidlFirst
, NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
372 hr
= psfChild
->GetDisplayNameOf(ILGetNext (pidl
), dwFlags
, strRet
);
379 HRESULT
HCR_GetClassName(REFIID riid
, LPSTRRET strRet
)
382 WCHAR wstrName
[MAX_PATH
+1];
383 bRet
= HCR_GetClassNameW(CLSID_MyDocuments
, wstrName
, MAX_PATH
);
387 return SHSetStrRet(strRet
, wstrName
);
390 HRESULT
SHELL32_GetDisplayNameOfGUIDItem(IShellFolder2
* psf
, LPCWSTR pszFolderPath
, PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
393 GUID
const *clsid
= _ILGetGUIDPointer (pidl
);
398 /* First of all check if we need to query the name from the child item */
399 if (GET_SHGDN_FOR (dwFlags
) == SHGDN_FORPARSING
&&
400 GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
)
402 int bWantsForParsing
;
405 * We can only get a filesystem path from a shellfolder if the
406 * value WantsFORPARSING in CLSID\\{...}\\shellfolder exists.
408 * Exception: The MyComputer folder doesn't have this key,
409 * but any other filesystem backed folder it needs it.
411 if (IsEqualIID (*clsid
, CLSID_MyComputer
))
413 bWantsForParsing
= TRUE
;
418 if (HCR_RegOpenClassIDKey(*clsid
, &hkeyClass
))
420 LONG res
= SHGetValueW(hkeyClass
, L
"Shellfolder", L
"WantsForParsing", NULL
, NULL
, NULL
);
421 bWantsForParsing
= (res
== ERROR_SUCCESS
);
422 RegCloseKey(hkeyClass
);
426 if (bWantsForParsing
)
429 * we need the filesystem path to the destination folder.
430 * Only the folder itself can know it
432 return SHELL32_GetDisplayNameOfChild (psf
, pidl
, dwFlags
, strRet
);
436 /* Allocate the buffer for the result */
437 LPWSTR pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
439 return E_OUTOFMEMORY
;
443 if (GET_SHGDN_FOR (dwFlags
) == SHGDN_FORPARSING
)
445 wcscpy(pszPath
, pszFolderPath
);
446 PWCHAR pItemName
= &pszPath
[wcslen(pszPath
)];
448 /* parsing name like ::{...} */
451 SHELL32_GUIDToStringW (*clsid
, &pItemName
[2]);
455 /* user friendly name */
456 if (!HCR_GetClassNameW (*clsid
, pszPath
, MAX_PATH
))
462 strRet
->uType
= STRRET_WSTR
;
463 strRet
->pOleStr
= pszPath
;
467 CoTaskMemFree(pszPath
);
473 /***********************************************************************
474 * SHELL32_GetItemAttributes
478 * folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER
479 * file: 0x40000177 FILESYSTEM
480 * drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR
481 * mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR
482 * (seems to be default for shell extensions if no registry entry exists)
485 * folder: 0xF0400177 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER
486 * file: 0x40400177 FILESYSTEM | CANMONIKER
487 * drive 0xF0400154 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER | CANRENAME (LABEL)
489 * According to the MSDN documentation this function should not set flags. It claims only to reset flags when necessary.
490 * However it turns out the native shell32.dll _sets_ flags in several cases - so do we.
493 static const DWORD dwSupportedAttr
=
494 SFGAO_CANCOPY
| /*0x00000001 */
495 SFGAO_CANMOVE
| /*0x00000002 */
496 SFGAO_CANLINK
| /*0x00000004 */
497 SFGAO_CANRENAME
| /*0x00000010 */
498 SFGAO_CANDELETE
| /*0x00000020 */
499 SFGAO_HASPROPSHEET
| /*0x00000040 */
500 SFGAO_DROPTARGET
| /*0x00000100 */
501 SFGAO_LINK
| /*0x00010000 */
502 SFGAO_READONLY
| /*0x00040000 */
503 SFGAO_HIDDEN
| /*0x00080000 */
504 SFGAO_FILESYSANCESTOR
| /*0x10000000 */
505 SFGAO_FOLDER
| /*0x20000000 */
506 SFGAO_FILESYSTEM
| /*0x40000000 */
507 SFGAO_HASSUBFOLDER
; /*0x80000000 */
509 HRESULT
SHELL32_GetGuidItemAttributes (IShellFolder
* psf
, LPCITEMIDLIST pidl
, LPDWORD pdwAttributes
)
511 if (!_ILIsSpecialFolder(pidl
))
513 ERR("Got wrong type of pidl!\n");
514 *pdwAttributes
&= SFGAO_CANLINK
;
518 if (*pdwAttributes
& ~dwSupportedAttr
)
520 WARN ("attributes 0x%08x not implemented\n", (*pdwAttributes
& ~dwSupportedAttr
));
521 *pdwAttributes
&= dwSupportedAttr
;
524 /* First try to get them from the registry */
525 if (HCR_GetFolderAttributes(pidl
, pdwAttributes
) && *pdwAttributes
)
531 /* If we can't get it from the registry we have to query the child */
532 CComPtr
<IShellFolder
> psf2
;
533 if (SUCCEEDED(psf
->BindToObject(pidl
, 0, IID_PPV_ARG(IShellFolder
, &psf2
))))
535 return psf2
->GetAttributesOf(0, NULL
, pdwAttributes
);
539 *pdwAttributes
&= SFGAO_CANLINK
;
543 HRESULT
SHELL32_GetFSItemAttributes(IShellFolder
* psf
, LPCITEMIDLIST pidl
, LPDWORD pdwAttributes
)
545 DWORD dwFileAttributes
, dwShellAttributes
;
547 if (!_ILIsFolder(pidl
) && !_ILIsValue(pidl
))
549 ERR("Got wrong type of pidl!\n");
550 *pdwAttributes
&= SFGAO_CANLINK
;
554 if (*pdwAttributes
& ~dwSupportedAttr
)
556 WARN ("attributes 0x%08x not implemented\n", (*pdwAttributes
& ~dwSupportedAttr
));
557 *pdwAttributes
&= dwSupportedAttr
;
560 dwFileAttributes
= _ILGetFileAttributes(pidl
, NULL
, 0);
562 /* Set common attributes */
563 dwShellAttributes
= *pdwAttributes
;
564 dwShellAttributes
|= SFGAO_FILESYSTEM
| SFGAO_DROPTARGET
| SFGAO_HASPROPSHEET
| SFGAO_CANDELETE
|
565 SFGAO_CANRENAME
| SFGAO_CANLINK
| SFGAO_CANMOVE
| SFGAO_CANCOPY
;
567 if (dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
569 dwShellAttributes
|= (SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_FILESYSANCESTOR
);
572 dwShellAttributes
&= ~(SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_FILESYSANCESTOR
);
574 if (dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
)
575 dwShellAttributes
|= SFGAO_HIDDEN
;
577 dwShellAttributes
&= ~SFGAO_HIDDEN
;
579 if (dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
580 dwShellAttributes
|= SFGAO_READONLY
;
582 dwShellAttributes
&= ~SFGAO_READONLY
;
584 if (SFGAO_LINK
& *pdwAttributes
)
588 if (!_ILGetExtension(pidl
, ext
, MAX_PATH
) || lstrcmpiA(ext
, "lnk"))
589 dwShellAttributes
&= ~SFGAO_LINK
;
592 if (SFGAO_HASSUBFOLDER
& *pdwAttributes
)
594 CComPtr
<IShellFolder
> psf2
;
595 if (SUCCEEDED(psf
->BindToObject(pidl
, 0, IID_PPV_ARG(IShellFolder
, &psf2
))))
597 CComPtr
<IEnumIDList
> pEnumIL
;
598 if (SUCCEEDED(psf2
->EnumObjects(0, SHCONTF_FOLDERS
, &pEnumIL
)))
600 if (pEnumIL
->Skip(1) != S_OK
)
601 dwShellAttributes
&= ~SFGAO_HASSUBFOLDER
;
606 *pdwAttributes
&= dwShellAttributes
;
608 TRACE ("-- 0x%08x\n", *pdwAttributes
);
612 /***********************************************************************
615 HRESULT
SHELL32_CompareIDs(IShellFolder
* iface
, LPARAM lParam
, LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
619 char szTemp1
[MAX_PATH
];
620 char szTemp2
[MAX_PATH
];
622 LPITEMIDLIST firstpidl
;
623 LPITEMIDLIST nextpidl1
;
624 LPITEMIDLIST nextpidl2
;
625 CComPtr
<IShellFolder
> psf
;
627 /* test for empty pidls */
628 BOOL isEmpty1
= _ILIsDesktop(pidl1
);
629 BOOL isEmpty2
= _ILIsDesktop(pidl2
);
631 if (isEmpty1
&& isEmpty2
)
632 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
634 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (WORD
) -1);
636 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 1);
638 /* test for different types. Sort order is the PT_* constant */
639 type1
= _ILGetDataPointer(pidl1
)->type
;
640 type2
= _ILGetDataPointer(pidl2
)->type
;
642 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (WORD
) -1);
643 else if (type1
> type2
)
644 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 1);
646 /* test for name of pidl */
647 _ILSimpleGetText(pidl1
, szTemp1
, MAX_PATH
);
648 _ILSimpleGetText(pidl2
, szTemp2
, MAX_PATH
);
649 nReturn
= lstrcmpiA(szTemp1
, szTemp2
);
651 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (WORD
) -1);
652 else if (nReturn
> 0)
653 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 1);
655 /* test of complex pidls */
656 firstpidl
= ILCloneFirst(pidl1
);
657 nextpidl1
= ILGetNext(pidl1
);
658 nextpidl2
= ILGetNext(pidl2
);
660 /* optimizing: test special cases and bind not deeper */
661 /* the deeper shellfolder would do the same */
662 isEmpty1
= _ILIsDesktop(nextpidl1
);
663 isEmpty2
= _ILIsDesktop(nextpidl2
);
665 if (isEmpty1
&& isEmpty2
)
667 nReturn
= MAKE_HRESULT( SEVERITY_SUCCESS
, 0, 0 );
671 nReturn
= MAKE_HRESULT( SEVERITY_SUCCESS
, 0, (WORD
)-1 );
675 nReturn
= MAKE_HRESULT( SEVERITY_SUCCESS
, 0, 1 );
678 else if (SUCCEEDED(iface
->BindToObject(firstpidl
, NULL
, IID_PPV_ARG(IShellFolder
, &psf
)))) {
679 nReturn
= psf
->CompareIDs(lParam
, nextpidl1
, nextpidl2
);
685 HRESULT
SH_ParseGuidDisplayName(IShellFolder2
* pFolder
,
688 LPOLESTR lpszDisplayName
,
690 PIDLIST_RELATIVE
*ppidl
,
691 DWORD
*pdwAttributes
)
695 if (!lpszDisplayName
|| !ppidl
)
703 UINT cch
= wcslen(lpszDisplayName
);
704 if (cch
< 39 || lpszDisplayName
[0] != L
':' || lpszDisplayName
[1] != L
':')
707 pidl
= _ILCreateGuidFromStrW(lpszDisplayName
+ 2);
714 if (pdwAttributes
&& *pdwAttributes
)
716 SHELL32_GetGuidItemAttributes(pFolder
, *ppidl
, pdwAttributes
);
721 HRESULT hr
= SHELL32_ParseNextElement(pFolder
, hwndOwner
, pbc
, &pidl
, lpszDisplayName
+ 41, pchEaten
, pdwAttributes
);
732 HRESULT
SHELL32_SetNameOfGuidItem(PCUITEMID_CHILD pidl
, LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
734 GUID
const *clsid
= _ILGetGUIDPointer (pidl
);
741 ERR("Pidl is not reg item!\n");
745 hr
= StringFromCLSID(*clsid
, &pStr
);
746 if (FAILED_UNEXPECTEDLY(hr
))
749 swprintf(szName
, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", pStr
);
751 DWORD cbData
= (wcslen(lpName
) + 1) * sizeof(WCHAR
);
752 LONG res
= SHSetValueW(HKEY_CURRENT_USER
, szName
, NULL
, RRF_RT_REG_SZ
, lpName
, cbData
);
756 if (res
== ERROR_SUCCESS
)
758 *pPidlOut
= ILClone(pidl
);
765 HRESULT
SHELL32_GetDetailsOfGuidItem(IShellFolder2
* psf
, PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
767 GUID
const *clsid
= _ILGetGUIDPointer (pidl
);
771 ERR("Pidl is not reg item!\n");
778 return psf
->GetDisplayNameOf(pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
779 case 1: /* comment */
781 if (HCR_RegOpenClassIDKey(*clsid
, &hKey
))
783 psd
->str
.cStr
[0] = 0x00;
784 psd
->str
.uType
= STRRET_CSTR
;
785 RegLoadMUIStringA(hKey
, "InfoTip", psd
->str
.cStr
, MAX_PATH
, NULL
, 0, NULL
);
793 /***********************************************************************
798 HRESULT WINAPI
SHCreateLinks( HWND hWnd
, LPCSTR lpszDir
, IDataObject
* lpDataObject
,
799 UINT uFlags
, LPITEMIDLIST
*lppidlLinks
)
801 FIXME("%p %s %p %08x %p\n", hWnd
, lpszDir
, lpDataObject
, uFlags
, lppidlLinks
);
805 /***********************************************************************
806 * SHOpenFolderAndSelectItems
812 SHOpenFolderAndSelectItems(LPITEMIDLIST pidlFolder
,
814 PCUITEMID_CHILD_ARRAY apidl
,
817 FIXME("SHOpenFolderAndSelectItems() stub\n");