4 * Copyright 1998 Juergen Schmied
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * a pidl == NULL means desktop and is legal
26 #include "wine/port.h"
33 #define NONAMELESSUNION
34 #define NONAMELESSSTRUCT
42 #include "undocshell.h"
43 #include "shell32_main.h"
49 #include "wine/debug.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(pidl
);
52 WINE_DECLARE_DEBUG_CHANNEL(shell
);
54 /* from comctl32.dll */
55 extern LPVOID WINAPI
Alloc(INT
);
56 extern BOOL WINAPI
Free(LPVOID
);
58 /*************************************************************************
59 * ILGetDisplayNameEx [SHELL32.186]
61 * Retrieves the display name of an ItemIDList
64 * psf [I] Shell Folder to start with, if NULL the desktop is used
65 * pidl [I] ItemIDList relativ to the psf to get the display name for
66 * path [O] Filled in with the display name, assumed to be at least MAX_PATH long
67 * type [I] Type of display name to retrieve
68 * 0 = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR uses always the desktop as root
69 * 1 = SHGDN_NORMAL relative to the root folder
70 * 2 = SHGDN_INFOLDER relative to the root folder, only the last name
73 * True if the display name could be retrieved successfully, False otherwise
75 BOOL WINAPI
ILGetDisplayNameExA(LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
, LPSTR path
, DWORD type
)
78 WCHAR wPath
[MAX_PATH
];
80 TRACE("%p %p %p %ld\n", psf
, pidl
, path
, type
);
85 ret
= ILGetDisplayNameExW(psf
, pidl
, wPath
, type
);
86 WideCharToMultiByte(CP_ACP
, 0, wPath
, -1, path
, MAX_PATH
, NULL
, NULL
);
87 TRACE("%p %p %s\n", psf
, pidl
, debugstr_a(path
));
92 BOOL WINAPI
ILGetDisplayNameExW(LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
, LPWSTR path
, DWORD type
)
94 LPSHELLFOLDER psfParent
, lsf
= psf
;
95 HRESULT ret
= NO_ERROR
;
96 LPCITEMIDLIST pidllast
;
100 TRACE("%p %p %p %ld\n", psf
, pidl
, path
, type
);
107 ret
= SHGetDesktopFolder(&lsf
);
112 if (type
>= 0 && type
<= 2)
116 case ILGDN_FORPARSING
:
117 flag
= SHGDN_FORPARSING
| SHGDN_FORADDRESSBAR
;
123 flag
= SHGDN_INFOLDER
;
126 FIXME("Unknown type parameter = %lx\n", type
);
127 flag
= SHGDN_FORPARSING
| SHGDN_FORADDRESSBAR
;
130 if (!*(LPWORD
)pidl
|| type
== ILGDN_FORPARSING
)
132 ret
= IShellFolder_GetDisplayNameOf(lsf
, pidl
, flag
, &strret
);
135 ret
= StrRetToStrNW(path
, MAX_PATH
, &strret
, pidl
);
140 ret
= SHBindToParent(pidl
, &IID_IShellFolder
, (LPVOID
*)&psfParent
, &pidllast
);
143 ret
= IShellFolder_GetDisplayNameOf(psfParent
, pidllast
, flag
, &strret
);
146 ret
= StrRetToStrNW(path
, MAX_PATH
, &strret
, pidllast
);
148 IShellFolder_Release(psfParent
);
153 TRACE("%p %p %s\n", psf
, pidl
, debugstr_w(path
));
156 IShellFolder_Release(lsf
);
157 return SUCCEEDED(ret
);
160 BOOL WINAPI
ILGetDisplayNameEx(LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
, LPVOID path
, DWORD type
)
162 TRACE_(shell
)("%p %p %p %ld\n", psf
, pidl
, path
, type
);
163 if (SHELL_OsIsUnicode())
164 return ILGetDisplayNameExW(psf
, pidl
, path
, type
);
165 return ILGetDisplayNameExA(psf
, pidl
, path
, type
);
168 /*************************************************************************
169 * ILGetDisplayName [SHELL32.15]
171 BOOL WINAPI
ILGetDisplayName(LPCITEMIDLIST pidl
, LPVOID path
)
173 TRACE_(shell
)("%p %p\n", pidl
, path
);
174 if (SHELL_OsIsUnicode())
175 return ILGetDisplayNameExW(NULL
, pidl
, path
, ILGDN_FORPARSING
);
176 return ILGetDisplayNameExA(NULL
, pidl
, path
, ILGDN_FORPARSING
);
179 /*************************************************************************
180 * ILFindLastID [SHELL32.16]
183 * observed: pidl=Desktop return=pidl
185 LPITEMIDLIST WINAPI
ILFindLastID(LPCITEMIDLIST pidl
)
187 LPCITEMIDLIST pidlLast
= pidl
;
189 TRACE("(pidl=%p)\n",pidl
);
194 while (pidl
->mkid
.cb
)
197 pidl
= ILGetNext(pidl
);
199 return (LPITEMIDLIST
)pidlLast
;
201 /*************************************************************************
202 * ILRemoveLastID [SHELL32.17]
205 * when pidl=Desktop return=FALSE
207 BOOL WINAPI
ILRemoveLastID(LPCITEMIDLIST pidl
)
209 TRACE_(shell
)("pidl=%p\n",pidl
);
211 if (!pidl
|| !pidl
->mkid
.cb
)
213 ILFindLastID(pidl
)->mkid
.cb
= 0;
217 /*************************************************************************
218 * ILClone [SHELL32.18]
221 * duplicate an idlist
223 LPITEMIDLIST WINAPI
ILClone (LPCITEMIDLIST pidl
)
225 LPITEMIDLIST newpidl
;
230 len
= ILGetSize(pidl
);
231 newpidl
= (LPITEMIDLIST
)SHAlloc(len
);
233 memcpy(newpidl
,pidl
,len
);
235 TRACE("pidl=%p newpidl=%p\n",pidl
, newpidl
);
240 /*************************************************************************
241 * ILCloneFirst [SHELL32.19]
244 * duplicates the first idlist of a complex pidl
246 LPITEMIDLIST WINAPI
ILCloneFirst(LPCITEMIDLIST pidl
)
248 LPITEMIDLIST pidlNew
= NULL
;
250 TRACE("pidl=%p \n",pidl
);
256 pidlNew
= (LPITEMIDLIST
) SHAlloc (len
+2);
259 memcpy(pidlNew
,pidl
,len
+2); /* 2 -> mind a desktop pidl */
262 ILGetNext(pidlNew
)->mkid
.cb
= 0x00;
265 TRACE("-- newpidl=%p\n",pidlNew
);
270 /*************************************************************************
271 * ILLoadFromStream (SHELL32.26)
274 * the first two bytes are the len, the pidl is following then
276 HRESULT WINAPI
ILLoadFromStream (IStream
* pStream
, LPITEMIDLIST
* ppPidl
)
279 HRESULT ret
= E_FAIL
;
282 TRACE_(shell
)("%p %p\n", pStream
, ppPidl
);
289 IStream_AddRef (pStream
);
291 if (SUCCEEDED(IStream_Read(pStream
, (LPVOID
)&wLen
, 2, &dwBytesRead
)))
293 TRACE("PIDL length is %d\n", wLen
);
295 *ppPidl
= SHAlloc (wLen
);
296 if (SUCCEEDED(IStream_Read(pStream
, *ppPidl
, wLen
, &dwBytesRead
))) {
297 TRACE("Stream read OK\n");
300 WARN("reading pidl failed\n");
310 /* we are not yet fully compatible */
311 if (*ppPidl
&& !pcheck(*ppPidl
))
313 WARN("Check failed\n");
319 IStream_Release (pStream
);
324 /*************************************************************************
325 * ILSaveToStream (SHELL32.27)
328 * the first two bytes are the len, the pidl is following then
330 HRESULT WINAPI
ILSaveToStream (IStream
* pStream
, LPCITEMIDLIST pPidl
)
334 HRESULT ret
= E_FAIL
;
336 TRACE_(shell
)("%p %p\n", pStream
, pPidl
);
338 IStream_AddRef (pStream
);
341 while (pidl
->mkid
.cb
)
343 wLen
+= sizeof(WORD
) + pidl
->mkid
.cb
;
344 pidl
= ILGetNext(pidl
);
347 if (SUCCEEDED(IStream_Write(pStream
, (LPVOID
)&wLen
, 2, NULL
)))
349 if (SUCCEEDED(IStream_Write(pStream
, pPidl
, wLen
, NULL
)))
353 IStream_Release (pStream
);
358 /*************************************************************************
359 * SHILCreateFromPath [SHELL32.28]
361 * Create an ItemIDList from a path
366 * attributes [I/O] requested attributes on call and actual attributes when
367 * the function returns
370 * NO_ERROR if successful, or an OLE errer code otherwise
373 * Wrapper for IShellFolder_ParseDisplayName().
375 HRESULT WINAPI
SHILCreateFromPathA(LPCSTR path
, LPITEMIDLIST
* ppidl
, DWORD
* attributes
)
378 WCHAR lpszDisplayName
[MAX_PATH
];
380 HRESULT ret
= E_FAIL
;
382 TRACE_(shell
)("%s %p 0x%08lx\n", path
, ppidl
, attributes
? *attributes
: 0);
384 if (!MultiByteToWideChar(CP_ACP
, 0, path
, -1, lpszDisplayName
, MAX_PATH
))
385 lpszDisplayName
[MAX_PATH
-1] = 0;
387 if (SUCCEEDED (SHGetDesktopFolder(&sf
)))
389 ret
= IShellFolder_ParseDisplayName(sf
, 0, NULL
, lpszDisplayName
, &pchEaten
, ppidl
, attributes
);
390 IShellFolder_Release(sf
);
395 HRESULT WINAPI
SHILCreateFromPathW(LPCWSTR path
, LPITEMIDLIST
* ppidl
, DWORD
* attributes
)
399 HRESULT ret
= E_FAIL
;
401 TRACE_(shell
)("%s %p 0x%08lx\n", debugstr_w(path
), ppidl
, attributes
? *attributes
: 0);
403 if (SUCCEEDED (SHGetDesktopFolder(&sf
)))
405 ret
= IShellFolder_ParseDisplayName(sf
, 0, NULL
, (LPWSTR
)path
, &pchEaten
, ppidl
, attributes
);
406 IShellFolder_Release(sf
);
411 HRESULT WINAPI
SHILCreateFromPathAW (LPCVOID path
, LPITEMIDLIST
* ppidl
, DWORD
* attributes
)
413 if ( SHELL_OsIsUnicode())
414 return SHILCreateFromPathW (path
, ppidl
, attributes
);
415 return SHILCreateFromPathA (path
, ppidl
, attributes
);
418 /*************************************************************************
419 * SHCloneSpecialIDList [SHELL32.89]
421 * Create an ItemIDList to one of the special folders.
425 * nFolder [in] CSIDL_xxxxx
426 * fCreate [in] Create folder if it does not exist
429 * Success: The newly created pidl
430 * Failure: NULL, if inputs are invalid.
433 * exported by ordinal.
434 * Caller is responsible for deallocating the returned ItemIDList with the
435 * shells IMalloc interface, aka ILFree.
437 LPITEMIDLIST WINAPI
SHCloneSpecialIDList(HWND hwndOwner
, DWORD nFolder
, BOOL fCreate
)
438 { LPITEMIDLIST ppidl
;
439 TRACE_(shell
)("(hwnd=%p,csidl=0x%lx,%s).\n", hwndOwner
, nFolder
, fCreate
? "T" : "F");
442 nFolder
|= CSIDL_FLAG_CREATE
;
444 SHGetSpecialFolderLocation(hwndOwner
, nFolder
, &ppidl
);
448 /*************************************************************************
449 * ILGlobalClone [SHELL32.20]
451 * Clones an ItemIDList using Alloc.
454 * pidl [I] ItemIDList to clone
457 * Newly allocated ItemIDList.
460 * exported by ordinal.
462 LPITEMIDLIST WINAPI
ILGlobalClone(LPCITEMIDLIST pidl
)
464 LPITEMIDLIST newpidl
;
469 len
= ILGetSize(pidl
);
470 newpidl
= (LPITEMIDLIST
)Alloc(len
);
472 memcpy(newpidl
,pidl
,len
);
474 TRACE("pidl=%p newpidl=%p\n",pidl
, newpidl
);
480 /*************************************************************************
481 * ILIsEqual [SHELL32.21]
484 BOOL WINAPI
ILIsEqual(LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
486 char szData1
[MAX_PATH
];
487 char szData2
[MAX_PATH
];
489 LPCITEMIDLIST pidltemp1
= pidl1
;
490 LPCITEMIDLIST pidltemp2
= pidl2
;
492 TRACE("pidl1=%p pidl2=%p\n",pidl1
, pidl2
);
494 /* explorer reads from registry directly (StreamMRU),
495 so we can only check here */
496 if ((!pcheck (pidl1
)) || (!pcheck (pidl2
))) return FALSE
;
501 if ( (!pidl1
) || (!pidl2
) ) return FALSE
;
503 while (pidltemp1
->mkid
.cb
&& pidltemp2
->mkid
.cb
)
505 _ILSimpleGetText(pidltemp1
, szData1
, MAX_PATH
);
506 _ILSimpleGetText(pidltemp2
, szData2
, MAX_PATH
);
508 if (strcasecmp ( szData1
, szData2
)!=0 )
511 pidltemp1
= ILGetNext(pidltemp1
);
512 pidltemp2
= ILGetNext(pidltemp2
);
515 if (!pidltemp1
->mkid
.cb
&& !pidltemp2
->mkid
.cb
)
522 /*************************************************************************
523 * ILIsParent [SHELL32.23]
525 * Verifies that pidlParent is indeed the (immediate) parent of pidlChild.
530 * bImmediate [I] only return true if the parent is the direct parent
534 * True if the parent ItemIDlist is a complete part of the child ItemIdList,
538 * parent = a/b, child = a/b/c -> true, c is in folder a/b
539 * child = a/b/c/d -> false if bImmediate is true, d is not in folder a/b
540 * child = a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b
542 BOOL WINAPI
ILIsParent(LPCITEMIDLIST pidlParent
, LPCITEMIDLIST pidlChild
, BOOL bImmediate
)
544 char szData1
[MAX_PATH
];
545 char szData2
[MAX_PATH
];
547 LPCITEMIDLIST pParent
= pidlParent
;
548 LPCITEMIDLIST pChild
= pidlChild
;
550 TRACE("%p %p %x\n", pidlParent
, pidlChild
, bImmediate
);
552 if (!pParent
|| !pChild
) return FALSE
;
554 while (pParent
->mkid
.cb
&& pChild
->mkid
.cb
)
556 _ILSimpleGetText(pParent
, szData1
, MAX_PATH
);
557 _ILSimpleGetText(pChild
, szData2
, MAX_PATH
);
559 if (strcasecmp ( szData1
, szData2
)!=0 )
562 pParent
= ILGetNext(pParent
);
563 pChild
= ILGetNext(pChild
);
566 if ( pParent
->mkid
.cb
|| ! pChild
->mkid
.cb
) /* child shorter or has equal length to parent */
569 if ( ILGetNext(pChild
)->mkid
.cb
&& bImmediate
) /* not immediate descent */
575 /*************************************************************************
576 * ILFindChild [SHELL32.24]
578 * Compares elements from pidl1 and pidl2.
585 * pidl1 is desktop pidl2
586 * pidl1 shorter pidl2 pointer to first different element of pidl2
587 * if there was at least one equal element
588 * pidl2 shorter pidl1 0
589 * pidl2 equal pidl1 pointer to last 0x00-element of pidl2
592 * exported by ordinal.
594 LPITEMIDLIST WINAPI
ILFindChild(LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
596 char szData1
[MAX_PATH
];
597 char szData2
[MAX_PATH
];
599 LPCITEMIDLIST pidltemp1
= pidl1
;
600 LPCITEMIDLIST pidltemp2
= pidl2
;
601 LPCITEMIDLIST ret
=NULL
;
603 TRACE("pidl1=%p pidl2=%p\n",pidl1
, pidl2
);
605 /* explorer reads from registry directly (StreamMRU),
606 so we can only check here */
607 if ((!pcheck (pidl1
)) || (!pcheck (pidl2
)))
613 if ( _ILIsDesktop(pidl1
) )
619 while (pidltemp1
->mkid
.cb
&& pidltemp2
->mkid
.cb
)
621 _ILSimpleGetText(pidltemp1
, szData1
, MAX_PATH
);
622 _ILSimpleGetText(pidltemp2
, szData2
, MAX_PATH
);
624 if (strcasecmp(szData1
,szData2
))
627 pidltemp1
= ILGetNext(pidltemp1
);
628 pidltemp2
= ILGetNext(pidltemp2
);
632 if (pidltemp1
->mkid
.cb
)
634 ret
= NULL
; /* elements of pidl1 left*/
637 TRACE_(shell
)("--- %p\n", ret
);
638 return (LPITEMIDLIST
)ret
; /* pidl 1 is shorter */
641 /*************************************************************************
642 * ILCombine [SHELL32.25]
644 * Concatenates two complex ItemIDLists.
647 * pidl1 [I] first complex ItemIDLists
648 * pidl2 [I] complex ItemIDLists to append
651 * if both pidl's == NULL NULL
652 * if pidl1 == NULL cloned pidl2
653 * if pidl2 == NULL cloned pidl1
654 * otherwise new pidl with pidl2 appended to pidl1
657 * exported by ordinal.
658 * Does not destroy the passed in ItemIDLists!
660 LPITEMIDLIST WINAPI
ILCombine(LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
663 LPITEMIDLIST pidlNew
;
665 TRACE("pidl=%p pidl=%p\n",pidl1
,pidl2
);
667 if(!pidl1
&& !pidl2
) return NULL
;
674 pidlNew
= ILClone(pidl2
);
680 pidlNew
= ILClone(pidl1
);
684 len1
= ILGetSize(pidl1
)-2;
685 len2
= ILGetSize(pidl2
);
686 pidlNew
= SHAlloc(len1
+len2
);
690 memcpy(pidlNew
,pidl1
,len1
);
691 memcpy(((BYTE
*)pidlNew
)+len1
,pidl2
,len2
);
694 /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
698 /*************************************************************************
699 * SHGetRealIDL [SHELL32.98]
703 HRESULT WINAPI
SHGetRealIDL(LPSHELLFOLDER lpsf
, LPCITEMIDLIST pidlSimple
, LPITEMIDLIST
*pidlReal
)
705 IDataObject
* pDataObj
;
706 HRESULT hr
= IShellFolder_GetUIObjectOf(lpsf
, 0, 1, &pidlSimple
, &IID_IDataObject
, 0, (LPVOID
*)&pDataObj
);
712 fmt
.cfFormat
= RegisterClipboardFormatA(CFSTR_SHELLIDLIST
);
714 fmt
.dwAspect
= DVASPECT_CONTENT
;
716 fmt
.tymed
= TYMED_HGLOBAL
;
718 hr
= IDataObject_GetData(pDataObj
, &fmt
, &medium
);
720 IDataObject_Release(pDataObj
);
723 /*assert(pida->cidl==1);*/
724 LPIDA pida
= (LPIDA
)GlobalLock(medium
.u
.hGlobal
);
726 LPCITEMIDLIST pidl_folder
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[0]);
727 LPCITEMIDLIST pidl_child
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[1]);
729 *pidlReal
= ILCombine(pidl_folder
, pidl_child
);
734 GlobalUnlock(medium
.u
.hGlobal
);
735 GlobalFree(medium
.u
.hGlobal
);
742 /*************************************************************************
743 * SHLogILFromFSIL [SHELL32.95]
746 * pild = CSIDL_DESKTOP ret = 0
747 * pild = CSIDL_DRIVES ret = 0
749 LPITEMIDLIST WINAPI
SHLogILFromFSIL(LPITEMIDLIST pidl
)
751 FIXME("(pidl=%p)\n",pidl
);
758 /*************************************************************************
759 * ILGetSize [SHELL32.152]
761 * Gets the byte size of an ItemIDList including zero terminator
764 * pidl [I] ItemIDList
767 * size of pidl in bytes
770 * exported by ordinal
772 UINT WINAPI
ILGetSize(LPCITEMIDLIST pidl
)
774 LPCSHITEMID si
= &(pidl
->mkid
);
780 si
= (LPSHITEMID
)(((LPBYTE
)si
)+si
->cb
);
784 TRACE("pidl=%p size=%u\n",pidl
, len
);
788 /*************************************************************************
789 * ILGetNext [SHELL32.153]
791 * Gets the next ItemID of an ItemIDList
794 * pidl [I] ItemIDList
799 * simple pidl -> pointer to 0x0000 element
802 * exported by ordinal.
804 LPITEMIDLIST WINAPI
ILGetNext(LPCITEMIDLIST pidl
)
815 pidl
= (LPITEMIDLIST
) (((LPBYTE
)pidl
)+len
);
816 TRACE("-- %p\n", pidl
);
817 return (LPITEMIDLIST
)pidl
;
823 /*************************************************************************
824 * ILAppend [SHELL32.154]
826 * Adds the single ItemID item to the ItemIDList indicated by pidl.
827 * If bEnd is FALSE, inserts the item in the front of the list,
828 * otherwise it adds the item to the end. (???)
831 * pidl [I] ItemIDList to extend
832 * item [I] ItemID to prepend/append
833 * bEnd [I] Indicates if the item should be appended
836 * Destroys the passed in idlist! (???)
838 LPITEMIDLIST WINAPI
ILAppend(LPITEMIDLIST pidl
, LPCITEMIDLIST item
, BOOL bEnd
)
842 WARN("(pidl=%p,pidl=%p,%08u)semi-stub\n",pidl
,item
,bEnd
);
847 if (_ILIsDesktop(pidl
))
849 idlRet
= ILClone(item
);
857 idlRet
= ILCombine(pidl
, item
);
861 idlRet
= ILCombine(item
, pidl
);
868 /*************************************************************************
869 * ILFree [SHELL32.155]
871 * Frees memory (if not NULL) allocated by SHMalloc allocator
877 * exported by ordinal
879 void WINAPI
ILFree(LPITEMIDLIST pidl
)
881 TRACE("(pidl=%p)\n",pidl
);
882 if(pidl
) SHFree(pidl
);
885 /*************************************************************************
886 * ILGlobalFree [SHELL32.156]
888 * Frees memory (if not NULL) allocated by Alloc allocator
894 * exported by ordinal.
896 void WINAPI
ILGlobalFree( LPITEMIDLIST pidl
)
904 /*************************************************************************
905 * ILCreateFromPathA [SHELL32.189]
907 * Creates a complex ItemIDList from a path and returns it.
913 * the newly created complex ItemIDList or NULL if failed
916 * exported by ordinal.
919 LPITEMIDLIST WINAPI
ILCreateFromPathA (LPCSTR path
)
921 LPITEMIDLIST pidlnew
= NULL
;
923 TRACE_(shell
)("%s\n", debugstr_a(path
));
925 if (SUCCEEDED(SHILCreateFromPathA(path
, &pidlnew
, NULL
)))
930 /*************************************************************************
931 * ILCreateFromPathW [SHELL32.190]
933 LPITEMIDLIST WINAPI
ILCreateFromPathW (LPCWSTR path
)
935 LPITEMIDLIST pidlnew
= NULL
;
937 TRACE_(shell
)("%s\n", debugstr_w(path
));
939 if (SUCCEEDED(SHILCreateFromPathW(path
, &pidlnew
, NULL
)))
944 /*************************************************************************
945 * ILCreateFromPath [SHELL32.157]
947 LPITEMIDLIST WINAPI
ILCreateFromPathAW (LPCVOID path
)
949 if ( SHELL_OsIsUnicode())
950 return ILCreateFromPathW (path
);
951 return ILCreateFromPathA (path
);
954 /*************************************************************************
955 * _ILParsePathW [internal]
957 * Creates an ItemIDList from a path and returns it.
960 * path [I] path to parse and convert into an ItemIDList
961 * lpFindFile [I] pointer to buffer to initialize the FileSystem
962 * Bind Data object with
963 * bBindCtx [I] indicates to create a BindContext and assign a
964 * FileSystem Bind Data object
965 * ppidl [O] the newly create ItemIDList
966 * prgfInOut [I/O] requested attributes on input and actual
967 * attributes on return
970 * NO_ERROR on success or an OLE error code
973 * If either lpFindFile is non-NULL or bBindCtx is TRUE, this function
974 * creates a BindContext object and assigns a FileSystem Bind Data object
975 * to it, passing the BindContext to IShellFolder_ParseDisplayName. Each
976 * IShellFolder uses that FileSystem Bind Data object of the BindContext
977 * to pass data about the current path element to the next object. This
978 * is used to avoid having to verify the current path element on disk, so
979 * that creating an ItemIDList from a non-existent path still can work.
981 static HRESULT WINAPI
_ILParsePathW(LPCWSTR path
, LPWIN32_FIND_DATAW lpFindFile
,
982 BOOL bBindCtx
, LPITEMIDLIST
*ppidl
, LPDWORD prgfInOut
)
984 LPSHELLFOLDER pSF
= NULL
;
988 TRACE("%s %p %d (%p)->%p (%p)->0x%lx\n", debugstr_w(path
), lpFindFile
, bBindCtx
,
989 ppidl
, ppidl
? *ppidl
: NULL
,
990 prgfInOut
, prgfInOut
? *prgfInOut
: 0);
992 ret
= SHGetDesktopFolder(&pSF
);
998 if (lpFindFile
|| bBindCtx
)
999 ret
= IFileSystemBindData_Constructor(lpFindFile
, &pBC
);
1003 ret
= IShellFolder_ParseDisplayName(pSF
, 0, pBC
, (LPOLESTR
)path
, NULL
, ppidl
, prgfInOut
);
1008 IBindCtx_Release(pBC
);
1012 IShellFolder_Release(pSF
);
1014 if (!SUCCEEDED(ret
) && ppidl
)
1017 TRACE("%s %p 0x%lx\n", debugstr_w(path
), ppidl
? *ppidl
: NULL
, prgfInOut
? *prgfInOut
: 0);
1022 /*************************************************************************
1023 * SHSimpleIDListFromPath [SHELL32.162]
1025 * Creates a simple ItemIDList from a path and returns it. This function
1026 * does not fail on non-existent paths.
1029 * path [I] path to parse and convert into an ItemIDList
1032 * the newly created simple ItemIDList
1035 * Simple in the name does not mean a relative ItemIDList but rather a
1036 * fully qualified list, where only the file name is filled in and the
1037 * directory flag for those ItemID elements this is known about, eg.
1038 * it is not the last element in the ItemIDList or the actual directory
1040 * exported by ordinal.
1042 LPITEMIDLIST WINAPI
SHSimpleIDListFromPathA(LPCSTR lpszPath
)
1044 LPITEMIDLIST pidl
= NULL
;
1045 LPWSTR wPath
= NULL
;
1048 TRACE("%s\n", debugstr_a(lpszPath
));
1052 len
= MultiByteToWideChar(CP_ACP
, 0, lpszPath
, -1, NULL
, 0);
1053 wPath
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1054 MultiByteToWideChar(CP_ACP
, 0, lpszPath
, -1, wPath
, len
);
1057 _ILParsePathW(wPath
, NULL
, TRUE
, &pidl
, NULL
);
1059 if (wPath
) HeapFree(GetProcessHeap(), 0, wPath
);
1060 TRACE("%s %p\n", debugstr_a(lpszPath
), pidl
);
1064 LPITEMIDLIST WINAPI
SHSimpleIDListFromPathW(LPCWSTR lpszPath
)
1066 LPITEMIDLIST pidl
= NULL
;
1068 TRACE("%s\n", debugstr_w(lpszPath
));
1070 _ILParsePathW(lpszPath
, NULL
, TRUE
, &pidl
, NULL
);
1071 TRACE("%s %p\n", debugstr_w(lpszPath
), pidl
);
1075 LPITEMIDLIST WINAPI
SHSimpleIDListFromPathAW(LPCVOID lpszPath
)
1077 if ( SHELL_OsIsUnicode())
1078 return SHSimpleIDListFromPathW (lpszPath
);
1079 return SHSimpleIDListFromPathA (lpszPath
);
1082 /*************************************************************************
1083 * SHGetDataFromIDListA [SHELL32.247]
1086 * the pidl can be a simple one. since we can't get the path out of the pidl
1087 * we have to take all data from the pidl
1089 HRESULT WINAPI
SHGetDataFromIDListA(LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
, int nFormat
, LPVOID dest
, int len
)
1091 TRACE_(shell
)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf
,pidl
,nFormat
,dest
,len
);
1094 if (!psf
|| !dest
) return E_INVALIDARG
;
1098 case SHGDFIL_FINDDATA
:
1100 LPSTR filename
, shortname
;
1101 WIN32_FIND_DATAA
* pfd
= dest
;
1103 if (_ILIsDrive(pidl
))
1104 return E_INVALIDARG
;
1106 if (len
< (int)sizeof(WIN32_FIND_DATAA
)) return E_INVALIDARG
;
1108 ZeroMemory(pfd
, sizeof (WIN32_FIND_DATAA
));
1109 _ILGetFileDateTime( pidl
, &(pfd
->ftLastWriteTime
));
1110 pfd
->dwFileAttributes
= _ILGetFileAttributes(pidl
, NULL
, 0);
1111 pfd
->nFileSizeLow
= _ILGetFileSize ( pidl
, NULL
, 0);
1113 filename
= _ILGetTextPointer(pidl
);
1114 shortname
= _ILGetSTextPointer(pidl
);
1117 lstrcpynA(pfd
->cFileName
, filename
, MAX_PATH
);
1119 pfd
->cFileName
[0] = '\0';
1122 lstrcpynA(pfd
->cAlternateFileName
, shortname
, MAX_PATH
);
1124 pfd
->cAlternateFileName
[0] = '\0';
1128 case SHGDFIL_NETRESOURCE
:
1129 case SHGDFIL_DESCRIPTIONID
:
1130 FIXME_(shell
)("SHGDFIL %i stub\n", nFormat
);
1134 ERR_(shell
)("Unknown SHGDFIL %i, please report\n", nFormat
);
1137 return E_INVALIDARG
;
1140 /*************************************************************************
1141 * SHGetDataFromIDListW [SHELL32.248]
1144 HRESULT WINAPI
SHGetDataFromIDListW(LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
, int nFormat
, LPVOID dest
, int len
)
1146 TRACE_(shell
)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf
,pidl
,nFormat
,dest
,len
);
1150 if (! psf
|| !dest
) return E_INVALIDARG
;
1154 case SHGDFIL_FINDDATA
:
1156 LPSTR filename
, shortname
;
1157 WIN32_FIND_DATAW
* pfd
= dest
;
1159 if (_ILIsDrive(pidl
))
1160 return E_INVALIDARG
;
1162 if (len
< (int)sizeof(WIN32_FIND_DATAW
)) return E_INVALIDARG
;
1164 ZeroMemory(pfd
, sizeof (WIN32_FIND_DATAA
));
1165 _ILGetFileDateTime( pidl
, &(pfd
->ftLastWriteTime
));
1166 pfd
->dwFileAttributes
= _ILGetFileAttributes(pidl
, NULL
, 0);
1167 pfd
->nFileSizeLow
= _ILGetFileSize ( pidl
, NULL
, 0);
1169 filename
= _ILGetTextPointer(pidl
);
1170 shortname
= _ILGetSTextPointer(pidl
);
1173 pfd
->cFileName
[0] = '\0';
1174 else if (!MultiByteToWideChar(CP_ACP
, 0, filename
, -1, pfd
->cFileName
, MAX_PATH
))
1175 pfd
->cFileName
[MAX_PATH
-1] = 0;
1178 pfd
->cAlternateFileName
[0] = '\0';
1179 else if (!MultiByteToWideChar(CP_ACP
, 0, shortname
, -1, pfd
->cAlternateFileName
, 14))
1180 pfd
->cAlternateFileName
[13] = 0;
1183 case SHGDFIL_NETRESOURCE
:
1184 case SHGDFIL_DESCRIPTIONID
:
1185 FIXME_(shell
)("SHGDFIL %i stub\n", nFormat
);
1189 ERR_(shell
)("Unknown SHGDFIL %i, please report\n", nFormat
);
1192 return E_INVALIDARG
;
1195 /*************************************************************************
1196 * SHELL_GetPathFromIDListA
1198 HRESULT
SHELL_GetPathFromIDListA(LPCITEMIDLIST pidl
, LPSTR pszPath
, UINT uOutSize
)
1204 /* One case is a PIDL rooted at desktop level */
1205 if (_ILIsValue(pidl
) || _ILIsFolder(pidl
)) {
1206 hr
= SHGetSpecialFolderPathA(0, pszPath
, CSIDL_DESKTOP
, FALSE
);
1209 PathAddBackslashA(pszPath
);
1211 /* The only other valid case is a item ID list beginning at "My Computer" */
1212 else if (_ILIsMyComputer(pidl
))
1213 pidl
= ILGetNext(pidl
);
1215 if (SUCCEEDED(hr
)) {
1218 while(pidl
&& pidl
->mkid
.cb
) {
1219 if (_ILIsSpecialFolder(pidl
))
1220 {hr
= E_INVALIDARG
; break;}
1222 txt
= _ILGetTextPointer(pidl
);
1224 {hr
= E_INVALIDARG
; break;}
1226 if (lstrlenA(txt
) > pidl
->mkid
.cb
)
1227 ERR("pidl %p is borked\n",pidl
);
1229 /* make sure there's enough space for the next segment */
1230 if ( (lstrlenA(txt
) + lstrlenA(pszPath
)) > uOutSize
)
1231 {hr
= E_INVALIDARG
; break;}
1232 lstrcatA( pszPath
, txt
);
1234 pidl
= ILGetNext(pidl
);
1236 {hr
= E_INVALIDARG
; break;}
1238 if (!pidl
->mkid
.cb
) {
1239 /* We are at the end and successfully converted the complete PIDL. */
1243 if( (lstrlenA(pszPath
) + 1) > uOutSize
)
1244 {hr
= E_INVALIDARG
; break;}
1245 if (!PathAddBackslashA(pszPath
))
1246 {hr
= E_INVALIDARG
; break;}
1251 TRACE_(shell
)("-- %s, 0x%08lx\n", pszPath
, hr
);
1255 /*************************************************************************
1256 * SHGetPathFromIDListA [SHELL32.@][NT 4.0: SHELL32.220]
1260 * pszPath [OUT] path
1263 * path from a passed PIDL.
1266 * NULL returns FALSE
1267 * desktop pidl gives path to desktop directory back
1268 * special pidls returning FALSE
1270 BOOL WINAPI
SHGetPathFromIDListA(LPCITEMIDLIST pidl
, LPSTR pszPath
)
1274 TRACE_(shell
)("(pidl=%p,%p)\n",pidl
,pszPath
);
1280 hr
= SHELL_GetPathFromIDListA(pidl
, pszPath
, MAX_PATH
);
1282 return SUCCEEDED(hr
);
1285 /*************************************************************************
1286 * SHELL_GetPathFromIDListW
1288 HRESULT
SHELL_GetPathFromIDListW(LPCITEMIDLIST pidl
, LPWSTR pszPath
, UINT uOutSize
)
1295 /* One case is a PIDL rooted at desktop level */
1296 if (_ILIsValue(pidl
) || _ILIsFolder(pidl
)) {
1297 hr
= SHGetSpecialFolderPathW(0, pszPath
, CSIDL_DESKTOP
, FALSE
);
1300 PathAddBackslashW(pszPath
);
1302 /* The only other valid case is a item ID list beginning at "My Computer" */
1303 else if (_ILIsMyComputer(pidl
))
1304 pidl
= ILGetNext(pidl
);
1306 if (SUCCEEDED(hr
)) {
1309 while(pidl
&& pidl
->mkid
.cb
) {
1310 if (_ILIsSpecialFolder(pidl
))
1311 {hr
= E_INVALIDARG
; break;}
1313 txt
= _ILGetTextPointer(pidl
);
1315 {hr
= E_INVALIDARG
; break;}
1317 if (lstrlenA(txt
) > pidl
->mkid
.cb
)
1318 ERR("pidl %p is borked\n",pidl
);
1319 len
= MultiByteToWideChar(CP_ACP
, 0, txt
, -1, NULL
, 0);
1320 if ( (lstrlenW(pszPath
) + len
) > uOutSize
)
1321 {hr
= E_INVALIDARG
; break;}
1323 MultiByteToWideChar(CP_ACP
, 0, txt
, -1,
1324 &pszPath
[lstrlenW(pszPath
)], len
);
1326 pidl
= ILGetNext(pidl
);
1328 {hr
= E_INVALIDARG
; break;}
1330 if (!pidl
->mkid
.cb
) {
1331 /* We are at the end and successfully converted the complete PIDL. */
1335 if ( (lstrlenW(pszPath
) + 1) > uOutSize
)
1336 {hr
= E_INVALIDARG
; break;}
1337 if (!PathAddBackslashW(pszPath
))
1338 {hr
= E_INVALIDARG
; break;}
1343 TRACE_(shell
)("-- %s, 0x%08lx\n", debugstr_w(pszPath
), hr
);
1347 /*************************************************************************
1348 * SHGetPathFromIDListW [SHELL32.@]
1350 BOOL WINAPI
SHGetPathFromIDListW(LPCITEMIDLIST pidl
, LPWSTR pszPath
)
1354 TRACE_(shell
)("(pidl=%p,%p)\n", pidl
, debugstr_w(pszPath
));
1360 hr
= SHELL_GetPathFromIDListW(pidl
, pszPath
, MAX_PATH
);
1362 TRACE_(shell
)("-- %s, 0x%08lx\n",debugstr_w(pszPath
), hr
);
1363 return SUCCEEDED(hr
);
1366 /*************************************************************************
1367 * SHGetPathFromIDList [SHELL32.@][NT 4.0: SHELL32.219]
1369 BOOL WINAPI
SHGetPathFromIDListAW(LPCITEMIDLIST pidl
,LPVOID pszPath
)
1371 TRACE_(shell
)("(pidl=%p,%p)\n",pidl
,pszPath
);
1373 if (SHELL_OsIsUnicode())
1374 return SHGetPathFromIDListW(pidl
,pszPath
);
1375 return SHGetPathFromIDListA(pidl
,pszPath
);
1378 /*************************************************************************
1379 * SHBindToParent [shell version 5.0]
1381 HRESULT WINAPI
SHBindToParent(LPCITEMIDLIST pidl
, REFIID riid
, LPVOID
*ppv
, LPCITEMIDLIST
*ppidlLast
)
1384 LPITEMIDLIST pidlChild
, pidlParent
;
1387 TRACE_(shell
)("pidl=%p\n", pidl
);
1391 if (ppidlLast
) *ppidlLast
= NULL
;
1393 if (_ILIsPidlSimple(pidl
))
1395 IShellFolder
* desktop
;
1397 /* we are on desktop level */
1398 hr
= SHGetDesktopFolder(&desktop
);
1402 hr
= IShellFolder_QueryInterface(desktop
, riid
, ppv
);
1404 if (SUCCEEDED(hr
) && ppidlLast
)
1405 *ppidlLast
= ILClone(pidl
);
1407 IShellFolder_Release(desktop
);
1412 pidlChild
= ILClone(ILFindLastID(pidl
));
1413 pidlParent
= ILClone(pidl
);
1414 ILRemoveLastID(pidlParent
);
1416 hr
= SHGetDesktopFolder(&psf
);
1419 hr
= IShellFolder_BindToObject(psf
, pidlParent
, NULL
, riid
, ppv
);
1421 if (SUCCEEDED(hr
) && ppidlLast
)
1422 *ppidlLast
= pidlChild
;
1426 SHFree (pidlParent
);
1427 if (psf
) IShellFolder_Release(psf
);
1431 TRACE_(shell
)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv
, (ppidlLast
)?*ppidlLast
:NULL
, hr
);
1435 /**************************************************************************
1437 * internal functions
1439 * ### 1. section creating pidls ###
1441 *************************************************************************
1443 LPITEMIDLIST
_ILAlloc(PIDLTYPE type
, size_t size
)
1445 LPITEMIDLIST pidlOut
= NULL
;
1447 if((pidlOut
= SHAlloc(size
+ 5)))
1450 LPITEMIDLIST pidlNext
;
1452 ZeroMemory(pidlOut
, size
+ 5);
1453 pidlOut
->mkid
.cb
= size
+ 3;
1455 if ((pData
= _ILGetDataPointer(pidlOut
)))
1458 if ((pidlNext
= ILGetNext(pidlOut
)))
1459 pidlNext
->mkid
.cb
= 0x00;
1460 TRACE("-- (pidl=%p, size=%u)\n", pidlOut
, size
);
1466 LPITEMIDLIST
_ILCreateDesktop()
1477 LPITEMIDLIST
_ILCreateMyComputer()
1479 return _ILCreateGuid(PT_GUID
, &CLSID_MyComputer
);
1482 LPITEMIDLIST
_ILCreateIExplore()
1484 return _ILCreateGuid(PT_GUID
, &CLSID_Internet
);
1487 LPITEMIDLIST
_ILCreateControlPanel()
1489 LPITEMIDLIST parent
= _ILCreateGuid(PT_GUID
, &CLSID_MyComputer
), ret
= NULL
;
1494 LPITEMIDLIST cpl
= _ILCreateGuid(PT_GUID
, &CLSID_ControlPanel
);
1498 ret
= ILCombine(parent
, cpl
);
1506 LPITEMIDLIST
_ILCreatePrinters()
1508 LPITEMIDLIST parent
= _ILCreateGuid(PT_GUID
, &CLSID_MyComputer
), ret
= NULL
;
1513 LPITEMIDLIST printers
= _ILCreateGuid(PT_GUID
, &CLSID_Printers
);
1517 ret
= ILCombine(parent
, printers
);
1525 LPITEMIDLIST
_ILCreateNetwork()
1527 return _ILCreateGuid(PT_GUID
, &CLSID_NetworkPlaces
);
1530 LPITEMIDLIST
_ILCreateBitBucket()
1532 return _ILCreateGuid(PT_GUID
, &CLSID_RecycleBin
);
1535 LPITEMIDLIST
_ILCreateGuid(PIDLTYPE type
, REFIID guid
)
1537 LPITEMIDLIST pidlOut
;
1539 if (type
== PT_SHELLEXT
|| type
== PT_GUID
)
1541 pidlOut
= _ILAlloc(type
, sizeof(GUIDStruct
));
1544 LPPIDLDATA pData
= _ILGetDataPointer(pidlOut
);
1546 memcpy(&(pData
->u
.guid
.guid
), guid
, sizeof(GUID
));
1547 TRACE("-- create GUID-pidl %s\n",
1548 debugstr_guid(&(pData
->u
.guid
.guid
)));
1553 WARN("%d: invalid type for GUID\n", type
);
1559 LPITEMIDLIST
_ILCreateGuidFromStrA(LPCSTR szGUID
)
1563 if (!SUCCEEDED(SHCLSIDFromStringA(szGUID
, &iid
)))
1565 ERR("%s is not a GUID\n", szGUID
);
1568 return _ILCreateGuid(PT_GUID
, &iid
);
1571 LPITEMIDLIST
_ILCreateFromFindDataA(WIN32_FIND_DATAA
* stffile
)
1573 char buff
[MAX_PATH
+ 14 +1]; /* see WIN32_FIND_DATA */
1574 char * pbuff
= buff
;
1582 TRACE("(%s, %s)\n",stffile
->cAlternateFileName
, stffile
->cFileName
);
1584 /* prepare buffer with both names */
1585 len
= strlen (stffile
->cFileName
) + 1;
1586 memcpy (pbuff
, stffile
->cFileName
, len
);
1589 len1
= strlen (stffile
->cAlternateFileName
)+1;
1590 memcpy (pbuff
, stffile
->cAlternateFileName
, len1
);
1592 type
= (stffile
->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ? PT_FOLDER
:
1594 /* FileStruct already has one byte for the first name, so use len - 1 in
1597 if ((pidl
= _ILAlloc(type
, sizeof(FileStruct
) + (len
- 1) + len1
)))
1602 /* set attributes */
1603 if ((pData
= _ILGetDataPointer(pidl
)))
1606 FileTimeToDosDateTime(&(stffile
->ftLastWriteTime
),&pData
->u
.file
.uFileDate
,&pData
->u
.file
.uFileTime
);
1607 pData
->u
.file
.dwFileSize
= stffile
->nFileSizeLow
;
1608 pData
->u
.file
.uFileAttribs
= (WORD
)stffile
->dwFileAttributes
;
1610 if ((pszDest
= _ILGetTextPointer(pidl
)))
1612 memcpy(pszDest
, buff
, len
+ len1
);
1613 TRACE("-- create Value: %s\n",debugstr_a(pszDest
));
1619 HRESULT
_ILCreateFromPathA(LPCSTR szPath
, LPITEMIDLIST
* ppidl
)
1622 WIN32_FIND_DATAA stffile
;
1625 return E_INVALIDARG
;
1627 hFile
= FindFirstFileA(szPath
, &stffile
);
1629 if (hFile
== INVALID_HANDLE_VALUE
)
1630 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
1634 *ppidl
= _ILCreateFromFindDataA(&stffile
);
1636 return *ppidl
? S_OK
: E_OUTOFMEMORY
;
1639 LPITEMIDLIST
_ILCreateDrive(LPCWSTR lpszNew
)
1642 LPITEMIDLIST pidlOut
;
1644 sTemp
[0]=toupperW(lpszNew
[0]);
1648 TRACE("(%s)\n",debugstr_w(sTemp
));
1650 if ((pidlOut
= _ILAlloc(PT_DRIVE
, sizeof(DriveStruct
))))
1654 if ((pszDest
= _ILGetTextPointer(pidlOut
)))
1656 WideCharToMultiByte(CP_ACP
, 0, sTemp
, sizeof(sTemp
)/sizeof(WCHAR
), pszDest
, sizeof(sTemp
)/sizeof(WCHAR
), NULL
, NULL
);
1657 TRACE("-- create Drive: %s\n", debugstr_a(pszDest
));
1663 /**************************************************************************
1666 * Gets the text for the drive eg. 'c:\'
1671 DWORD
_ILGetDrive(LPCITEMIDLIST pidl
,LPSTR pOut
, UINT uSize
)
1672 { TRACE("(%p,%p,%u)\n",pidl
,pOut
,uSize
);
1674 if(_ILIsMyComputer(pidl
))
1675 pidl
= ILGetNext(pidl
);
1677 if (pidl
&& _ILIsDrive(pidl
))
1678 return _ILSimpleGetText(pidl
, pOut
, uSize
);
1683 /**************************************************************************
1685 * ### 2. section testing pidls ###
1687 **************************************************************************
1690 * _ILIsSpecialFolder()
1696 BOOL
_ILIsDesktop(LPCITEMIDLIST pidl
)
1697 { TRACE("(%p)\n",pidl
);
1698 return pidl
&& pidl
->mkid
.cb
? 0 : 1;
1701 BOOL
_ILIsMyComputer(LPCITEMIDLIST pidl
)
1703 REFIID iid
= _ILGetGUIDPointer(pidl
);
1705 TRACE("(%p)\n",pidl
);
1708 return IsEqualIID(iid
, &CLSID_MyComputer
);
1712 BOOL
_ILIsSpecialFolder (LPCITEMIDLIST pidl
)
1714 LPPIDLDATA lpPData
= _ILGetDataPointer(pidl
);
1715 TRACE("(%p)\n",pidl
);
1716 return (pidl
&& ( (lpPData
&& (PT_GUID
== lpPData
->type
|| PT_SHELLEXT
== lpPData
->type
)) ||
1717 (pidl
&& pidl
->mkid
.cb
== 0x00)
1721 BOOL
_ILIsDrive(LPCITEMIDLIST pidl
)
1722 { LPPIDLDATA lpPData
= _ILGetDataPointer(pidl
);
1723 TRACE("(%p)\n",pidl
);
1724 return (pidl
&& lpPData
&& (PT_DRIVE
== lpPData
->type
||
1725 PT_DRIVE1
== lpPData
->type
||
1726 PT_DRIVE2
== lpPData
->type
||
1727 PT_DRIVE3
== lpPData
->type
));
1730 BOOL
_ILIsFolder(LPCITEMIDLIST pidl
)
1731 { LPPIDLDATA lpPData
= _ILGetDataPointer(pidl
);
1732 TRACE("(%p)\n",pidl
);
1733 return (pidl
&& lpPData
&& (PT_FOLDER
== lpPData
->type
|| PT_FOLDER1
== lpPData
->type
));
1736 BOOL
_ILIsValue(LPCITEMIDLIST pidl
)
1737 { LPPIDLDATA lpPData
= _ILGetDataPointer(pidl
);
1738 TRACE("(%p)\n",pidl
);
1739 return (pidl
&& lpPData
&& PT_VALUE
== lpPData
->type
);
1742 BOOL
_ILIsCPanelStruct(LPCITEMIDLIST pidl
)
1743 { LPPIDLDATA lpPData
= _ILGetDataPointer(pidl
);
1744 TRACE("(%p)\n",pidl
);
1745 return (pidl
&& lpPData
&& (lpPData
->type
== 0));
1748 /**************************************************************************
1751 BOOL
_ILIsPidlSimple ( LPCITEMIDLIST pidl
)
1755 if(! _ILIsDesktop(pidl
)) /* pidl=NULL or mkid.cb=0 */
1757 WORD len
= pidl
->mkid
.cb
;
1758 LPCITEMIDLIST pidlnext
= (LPCITEMIDLIST
) (((LPBYTE
)pidl
) + len
);
1759 if (pidlnext
->mkid
.cb
)
1763 TRACE("%s\n", ret
? "Yes" : "No");
1767 /**************************************************************************
1769 * ### 3. section getting values from pidls ###
1772 /**************************************************************************
1775 * gets the text for the first item in the pidl (eg. simple pidl)
1777 * returns the length of the string
1779 DWORD
_ILSimpleGetText (LPCITEMIDLIST pidl
, LPSTR szOut
, UINT uOutSize
)
1784 char szTemp
[MAX_PATH
];
1786 TRACE("(%p %p %x)\n",pidl
,szOut
,uOutSize
);
1788 if (!pidl
) return 0;
1793 if (_ILIsDesktop(pidl
))
1796 if (HCR_GetClassNameA(&CLSID_ShellDesktop
, szTemp
, MAX_PATH
))
1799 lstrcpynA(szOut
, szTemp
, uOutSize
);
1801 dwReturn
= strlen (szTemp
);
1804 else if (( szSrc
= _ILGetTextPointer(pidl
) ))
1808 lstrcpynA(szOut
, szSrc
, uOutSize
);
1810 dwReturn
= strlen(szSrc
);
1812 else if (( riid
= _ILGetGUIDPointer(pidl
) ))
1814 /* special folder */
1815 if ( HCR_GetClassNameA(riid
, szTemp
, MAX_PATH
) )
1818 lstrcpynA(szOut
, szTemp
, uOutSize
);
1820 dwReturn
= strlen (szTemp
);
1825 ERR("-- no text\n");
1828 TRACE("-- (%p=%s 0x%08lx)\n",szOut
,debugstr_a(szOut
),dwReturn
);
1832 /**************************************************************************
1835 * gets the text for the first item in the pidl (eg. simple pidl)
1837 * returns the length of the string
1839 DWORD
_ILSimpleGetTextW (LPCITEMIDLIST pidl
, LPWSTR szOut
, UINT uOutSize
)
1842 char szTemp
[MAX_PATH
];
1844 TRACE("(%p %p %x)\n",pidl
,szOut
,uOutSize
);
1846 dwReturn
= _ILSimpleGetText(pidl
, szTemp
, uOutSize
);
1848 if (!MultiByteToWideChar(CP_ACP
, 0, szTemp
, -1, szOut
, MAX_PATH
))
1851 TRACE("-- (%p=%s 0x%08lx)\n",szOut
,debugstr_w(szOut
),dwReturn
);
1855 /**************************************************************************
1857 * ### 4. getting pointers to parts of pidls ###
1859 **************************************************************************
1860 * _ILGetDataPointer()
1862 LPPIDLDATA
_ILGetDataPointer(LPCITEMIDLIST pidl
)
1864 if(pidl
&& pidl
->mkid
.cb
!= 0x00)
1865 return (LPPIDLDATA
) &(pidl
->mkid
.abID
);
1869 /**************************************************************************
1870 * _ILGetTextPointer()
1871 * gets a pointer to the long filename string stored in the pidl
1873 LPSTR
_ILGetTextPointer(LPCITEMIDLIST pidl
)
1874 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1876 LPPIDLDATA pdata
= _ILGetDataPointer(pidl
);
1880 switch (pdata
->type
)
1890 return (LPSTR
)&(pdata
->u
.drive
.szDriveName
);
1898 return (LPSTR
)&(pdata
->u
.file
.szNames
);
1903 case PT_NETPROVIDER
:
1905 return (LPSTR
)&(pdata
->u
.network
.szNames
);
1911 /**************************************************************************
1912 * _ILGetSTextPointer()
1913 * gets a pointer to the short filename string stored in the pidl
1915 LPSTR
_ILGetSTextPointer(LPCITEMIDLIST pidl
)
1916 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1918 LPPIDLDATA pdata
=_ILGetDataPointer(pidl
);
1922 switch (pdata
->type
)
1929 return (LPSTR
)(pdata
->u
.file
.szNames
+ strlen (pdata
->u
.file
.szNames
) + 1);
1932 return (LPSTR
)(pdata
->u
.network
.szNames
+ strlen (pdata
->u
.network
.szNames
) + 1);
1938 /**************************************************************************
1939 * _ILGetGUIDPointer()
1941 * returns reference to guid stored in some pidls
1943 REFIID
_ILGetGUIDPointer(LPCITEMIDLIST pidl
)
1945 LPPIDLDATA pdata
=_ILGetDataPointer(pidl
);
1947 TRACE("%p\n", pidl
);
1951 TRACE("pdata->type 0x%04x\n", pdata
->type
);
1952 switch (pdata
->type
)
1956 return (REFIID
) &(pdata
->u
.guid
.guid
);
1959 TRACE("Unknown pidl type 0x%04x\n", pdata
->type
);
1966 /*************************************************************************
1967 * _ILGetFileDateTime
1969 * Given the ItemIdList, get the FileTime
1972 * pidl [I] The ItemIDList
1973 * pFt [I] the resulted FILETIME of the file
1976 * True if Successful
1981 BOOL
_ILGetFileDateTime(LPCITEMIDLIST pidl
, FILETIME
*pFt
)
1983 LPPIDLDATA pdata
= _ILGetDataPointer(pidl
);
1985 if(! pdata
) return FALSE
;
1987 switch (pdata
->type
)
1991 DosDateTimeToFileTime(pdata
->u
.file
.uFileDate
, pdata
->u
.file
.uFileTime
, pFt
);
1999 BOOL
_ILGetFileDate (LPCITEMIDLIST pidl
, LPSTR pOut
, UINT uOutSize
)
2005 if (_ILGetFileDateTime( pidl
, &ft
)) {
2006 FileTimeToLocalFileTime(&ft
, &lft
);
2007 FileTimeToSystemTime (&lft
, &time
);
2008 ret
= GetDateFormatA(LOCALE_USER_DEFAULT
,DATE_SHORTDATE
,&time
, NULL
, pOut
, uOutSize
);
2017 /*************************************************************************
2020 * Given the ItemIdList, get the FileSize
2023 * pidl [I] The ItemIDList
2024 * pOut [I] The buffer to save the result
2025 * uOutsize [I] The size of the buffer
2031 * pOut can be null when no string is needed
2034 DWORD
_ILGetFileSize (LPCITEMIDLIST pidl
, LPSTR pOut
, UINT uOutSize
)
2036 LPPIDLDATA pdata
= _ILGetDataPointer(pidl
);
2039 if(! pdata
) return 0;
2041 switch (pdata
->type
)
2044 dwSize
= pdata
->u
.file
.dwFileSize
;
2045 if (pOut
) StrFormatByteSizeA(dwSize
, pOut
, uOutSize
);
2048 if (pOut
) *pOut
= 0x00;
2052 BOOL
_ILGetExtension (LPCITEMIDLIST pidl
, LPSTR pOut
, UINT uOutSize
)
2054 char szTemp
[MAX_PATH
];
2055 const char * pPoint
;
2056 LPCITEMIDLIST pidlTemp
=pidl
;
2058 TRACE("pidl=%p\n",pidl
);
2060 if (!pidl
) return FALSE
;
2062 pidlTemp
= ILFindLastID(pidl
);
2064 if (!_ILIsValue(pidlTemp
)) return FALSE
;
2065 if (!_ILSimpleGetText(pidlTemp
, szTemp
, MAX_PATH
)) return FALSE
;
2067 pPoint
= PathFindExtensionA(szTemp
);
2069 if (! *pPoint
) return FALSE
;
2072 lstrcpynA(pOut
, pPoint
, uOutSize
);
2078 /*************************************************************************
2081 * Given the ItemIdList, get the file type description
2084 * pidl [I] The ItemIDList (simple)
2085 * pOut [I] The buffer to save the result
2086 * uOutsize [I] The size of the buffer
2092 * This function copies as much as possible into the buffer.
2094 void _ILGetFileType(LPCITEMIDLIST pidl
, LPSTR pOut
, UINT uOutSize
)
2096 if(_ILIsValue(pidl
))
2103 if (_ILGetExtension (pidl
, sTemp
, 64))
2105 if (!( HCR_MapTypeToValueA(sTemp
, sTemp
, 64, TRUE
)
2106 && HCR_MapTypeToValueA(sTemp
, pOut
, uOutSize
, FALSE
)))
2108 lstrcpynA (pOut
, sTemp
, uOutSize
- 6);
2109 strcat (pOut
, "-file");
2115 lstrcpynA(pOut
, "Folder", uOutSize
);
2119 /*************************************************************************
2120 * _ILGetFileAttributes
2122 * Given the ItemIdList, get the Attrib string format
2125 * pidl [I] The ItemIDList
2126 * pOut [I] The buffer to save the result
2127 * uOutsize [I] The size of the Buffer
2133 * return value 0 in case of error is a valid return value
2136 DWORD
_ILGetFileAttributes(LPCITEMIDLIST pidl
, LPSTR pOut
, UINT uOutSize
)
2138 LPPIDLDATA pData
= _ILGetDataPointer(pidl
);
2142 if(! pData
) return 0;
2148 wAttrib
= pData
->u
.file
.uFileAttribs
;
2155 if(wAttrib
& FILE_ATTRIBUTE_READONLY
)
2159 if(wAttrib
& FILE_ATTRIBUTE_HIDDEN
)
2163 if(wAttrib
& FILE_ATTRIBUTE_SYSTEM
)
2167 if(wAttrib
& FILE_ATTRIBUTE_ARCHIVE
)
2171 if(wAttrib
& FILE_ATTRIBUTE_COMPRESSED
)
2180 /*************************************************************************
2183 * free a aPidl struct
2185 void _ILFreeaPidl(LPITEMIDLIST
* apidl
, UINT cidl
)
2191 for (i
= 0; i
< cidl
; i
++) SHFree(apidl
[i
]);
2196 /*************************************************************************
2199 * copies an aPidl struct
2201 LPITEMIDLIST
* _ILCopyaPidl(LPCITEMIDLIST
* apidlsrc
, UINT cidl
)
2204 LPITEMIDLIST
* apidldest
= (LPITEMIDLIST
*)SHAlloc(cidl
* sizeof(LPITEMIDLIST
));
2205 if(!apidlsrc
) return NULL
;
2207 for (i
= 0; i
< cidl
; i
++)
2208 apidldest
[i
] = ILClone(apidlsrc
[i
]);
2213 /*************************************************************************
2214 * _ILCopyCidaToaPidl
2216 * creates aPidl from CIDA
2218 LPITEMIDLIST
* _ILCopyCidaToaPidl(LPITEMIDLIST
* pidl
, LPIDA cida
)
2221 LPITEMIDLIST
* dst
= (LPITEMIDLIST
*)SHAlloc(cida
->cidl
* sizeof(LPITEMIDLIST
));
2223 if(!dst
) return NULL
;
2226 *pidl
= ILClone((LPITEMIDLIST
)(&((LPBYTE
)cida
)[cida
->aoffset
[0]]));
2228 for (i
= 0; i
< cida
->cidl
; i
++)
2229 dst
[i
] = ILClone((LPITEMIDLIST
)(&((LPBYTE
)cida
)[cida
->aoffset
[i
+ 1]]));