Release 20030408.
[wine/gsoc-2012-control.git] / dlls / shell32 / pidl.c
blobdd35668ae094c1836b23b05dc14f819fc01f9018
1 /*
2 * pidl Handling
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
20 * NOTES
21 * a pidl == NULL means desktop and is legal
25 #include "config.h"
26 #include "wine/port.h"
28 #include <ctype.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include "winbase.h"
32 #include "winreg.h"
33 #include "shlguid.h"
34 #include "winerror.h"
35 #include "winnls.h"
36 #include "undocshell.h"
37 #include "shell32_main.h"
38 #include "shellapi.h"
39 #include "shlwapi.h"
41 #include "pidl.h"
42 #include "debughlp.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(pidl);
46 WINE_DECLARE_DEBUG_CHANNEL(shell);
48 /* from comctl32.dll */
49 extern LPVOID WINAPI Alloc(INT);
50 extern BOOL WINAPI Free(LPVOID);
52 /*************************************************************************
53 * ILGetDisplayName [SHELL32.15]
55 BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl,LPSTR path)
57 TRACE_(shell)("pidl=%p %p semi-stub\n",pidl,path);
58 return SHGetPathFromIDListA(pidl, path);
60 /*************************************************************************
61 * ILFindLastID [SHELL32.16]
63 * NOTES
64 * observed: pidl=Desktop return=pidl
66 LPITEMIDLIST WINAPI ILFindLastID(LPITEMIDLIST pidl)
67 { LPITEMIDLIST pidlLast = pidl;
69 TRACE("(pidl=%p)\n",pidl);
71 while (pidl->mkid.cb)
73 pidlLast = pidl;
74 pidl = ILGetNext(pidl);
76 return pidlLast;
78 /*************************************************************************
79 * ILRemoveLastID [SHELL32.17]
81 * NOTES
82 * when pidl=Desktop return=FALSE
84 BOOL WINAPI ILRemoveLastID(LPCITEMIDLIST pidl)
86 TRACE_(shell)("pidl=%p\n",pidl);
88 if (!pidl || !pidl->mkid.cb)
89 return 0;
90 ILFindLastID(pidl)->mkid.cb = 0;
91 return 1;
94 /*************************************************************************
95 * ILClone [SHELL32.18]
97 * NOTES
98 * duplicate an idlist
100 LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl)
101 { DWORD len;
102 LPITEMIDLIST newpidl;
104 if (!pidl)
105 return NULL;
107 len = ILGetSize(pidl);
108 newpidl = (LPITEMIDLIST)SHAlloc(len);
109 if (newpidl)
110 memcpy(newpidl,pidl,len);
112 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
113 pdump(pidl);
115 return newpidl;
117 /*************************************************************************
118 * ILCloneFirst [SHELL32.19]
120 * NOTES
121 * duplicates the first idlist of a complex pidl
123 LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl)
124 { DWORD len;
125 LPITEMIDLIST pidlNew = NULL;
127 TRACE("pidl=%p \n",pidl);
128 pdump(pidl);
130 if (pidl)
132 len = pidl->mkid.cb;
133 pidlNew = (LPITEMIDLIST) SHAlloc (len+2);
134 if (pidlNew)
136 memcpy(pidlNew,pidl,len+2); /* 2 -> mind a desktop pidl */
138 if (len)
139 ILGetNext(pidlNew)->mkid.cb = 0x00;
142 TRACE("-- newpidl=%p\n",pidlNew);
144 return pidlNew;
147 /*************************************************************************
148 * ILLoadFromStream (SHELL32.26)
150 * NOTES
151 * the first two bytes are the len, the pidl is following then
153 HRESULT WINAPI ILLoadFromStream (IStream * pStream, LPITEMIDLIST * ppPidl)
154 { WORD wLen = 0;
155 DWORD dwBytesRead;
156 HRESULT ret = E_FAIL;
159 TRACE_(shell)("%p %p\n", pStream , ppPidl);
161 if (*ppPidl)
162 { SHFree(*ppPidl);
163 *ppPidl = NULL;
166 IStream_AddRef (pStream);
168 if (SUCCEEDED(IStream_Read(pStream, (LPVOID)&wLen, 2, &dwBytesRead)))
169 { *ppPidl = SHAlloc (wLen);
170 if (SUCCEEDED(IStream_Read(pStream, *ppPidl , wLen, &dwBytesRead)))
171 { ret = S_OK;
173 else
174 { SHFree(*ppPidl);
175 *ppPidl = NULL;
179 /* we are not yet fully compatible */
180 if (!pcheck(*ppPidl))
181 { SHFree(*ppPidl);
182 *ppPidl = NULL;
186 IStream_Release (pStream);
188 return ret;
191 /*************************************************************************
192 * ILSaveToStream (SHELL32.27)
194 * NOTES
195 * the first two bytes are the len, the pidl is following then
197 HRESULT WINAPI ILSaveToStream (IStream * pStream, LPCITEMIDLIST pPidl)
199 LPITEMIDLIST pidl;
200 WORD wLen = 0;
201 HRESULT ret = E_FAIL;
203 TRACE_(shell)("%p %p\n", pStream, pPidl);
205 IStream_AddRef (pStream);
207 pidl = pPidl;
208 while (pidl->mkid.cb)
210 wLen += sizeof(WORD) + pidl->mkid.cb;
211 pidl = ILGetNext(pidl);
214 if (SUCCEEDED(IStream_Write(pStream, (LPVOID)&wLen, 2, NULL)))
216 if (SUCCEEDED(IStream_Write(pStream, pPidl, wLen, NULL)))
217 { ret = S_OK;
222 IStream_Release (pStream);
224 return ret;
227 HRESULT WINAPI SHILCreateFromPathA (LPCSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
228 { LPSHELLFOLDER sf;
229 WCHAR lpszDisplayName[MAX_PATH];
230 DWORD pchEaten;
231 HRESULT ret = E_FAIL;
233 TRACE_(shell)("%s %p 0x%08lx\n",path,ppidl,attributes?*attributes:0);
235 if (!MultiByteToWideChar( CP_ACP, 0, path, -1, lpszDisplayName, MAX_PATH ))
236 lpszDisplayName[MAX_PATH-1] = 0;
238 if (SUCCEEDED (SHGetDesktopFolder(&sf)))
240 ret = IShellFolder_ParseDisplayName(sf,0, NULL,lpszDisplayName,&pchEaten,ppidl,attributes);
241 IShellFolder_Release(sf);
243 return ret;
246 HRESULT WINAPI SHILCreateFromPathW (LPCWSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
247 { LPSHELLFOLDER sf;
248 DWORD pchEaten;
249 HRESULT ret = E_FAIL;
251 TRACE_(shell)("%s %p 0x%08lx\n",debugstr_w(path),ppidl,attributes?*attributes:0);
253 if (SUCCEEDED (SHGetDesktopFolder(&sf)))
255 ret = IShellFolder_ParseDisplayName(sf,0, NULL, (LPWSTR) path, &pchEaten, ppidl, attributes);
256 IShellFolder_Release(sf);
258 return ret;
261 /*************************************************************************
262 * SHILCreateFromPath [SHELL32.28]
264 * NOTES
265 * Wrapper for IShellFolder_ParseDisplayName().
267 HRESULT WINAPI SHILCreateFromPathAW (LPCVOID path, LPITEMIDLIST * ppidl, DWORD * attributes)
269 if ( SHELL_OsIsUnicode())
270 return SHILCreateFromPathW (path, ppidl, attributes);
271 return SHILCreateFromPathA (path, ppidl, attributes);
274 /*************************************************************************
275 * SHCloneSpecialIDList [SHELL32.89]
277 * PARAMETERS
278 * hwndOwner [in]
279 * nFolder [in] CSIDL_xxxxx ??
281 * RETURNS
282 * pidl ??
283 * NOTES
284 * exported by ordinal
286 LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner,DWORD nFolder,DWORD x3)
287 { LPITEMIDLIST ppidl;
288 WARN_(shell)("(hwnd=%p,csidl=0x%lx,0x%lx):semi-stub.\n",
289 hwndOwner,nFolder,x3);
291 SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl);
293 return ppidl;
296 /*************************************************************************
297 * ILGlobalClone [SHELL32.20]
300 LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl)
301 { DWORD len;
302 LPITEMIDLIST newpidl;
304 if (!pidl)
305 return NULL;
307 len = ILGetSize(pidl);
308 newpidl = (LPITEMIDLIST)Alloc(len);
309 if (newpidl)
310 memcpy(newpidl,pidl,len);
312 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
313 pdump(pidl);
315 return newpidl;
318 /*************************************************************************
319 * ILIsEqual [SHELL32.21]
322 BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
324 char szData1[MAX_PATH];
325 char szData2[MAX_PATH];
327 LPITEMIDLIST pidltemp1 = pidl1;
328 LPITEMIDLIST pidltemp2 = pidl2;
330 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
332 /* explorer reads from registry directly (StreamMRU),
333 so we can only check here */
334 if ((!pcheck (pidl1)) || (!pcheck (pidl2))) return FALSE;
336 pdump (pidl1);
337 pdump (pidl2);
339 if ( (!pidl1) || (!pidl2) ) return FALSE;
341 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
343 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
344 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
346 if (strcasecmp ( szData1, szData2 )!=0 )
347 return FALSE;
349 pidltemp1 = ILGetNext(pidltemp1);
350 pidltemp2 = ILGetNext(pidltemp2);
353 if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb)
355 return TRUE;
358 return FALSE;
360 /*************************************************************************
361 * ILIsParent [SHELL32.23]
363 * parent=a/b child=a/b/c -> true, c is in folder a/b
364 * child=a/b/c/d -> false if bImmediate is true, d is not in folder a/b
365 * child=a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b
367 BOOL WINAPI ILIsParent( LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate)
369 char szData1[MAX_PATH];
370 char szData2[MAX_PATH];
372 LPITEMIDLIST pParent = pidlParent;
373 LPITEMIDLIST pChild = pidlChild;
375 TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate);
377 while (pParent->mkid.cb && pChild->mkid.cb)
379 _ILSimpleGetText(pParent, szData1, MAX_PATH);
380 _ILSimpleGetText(pChild, szData2, MAX_PATH);
382 if (strcasecmp ( szData1, szData2 )!=0 )
383 return FALSE;
385 pParent = ILGetNext(pParent);
386 pChild = ILGetNext(pChild);
389 if ( pParent->mkid.cb || ! pChild->mkid.cb) /* child shorter or has equal length to parent */
390 return FALSE;
392 if ( ILGetNext(pChild)->mkid.cb && bImmediate) /* not immediate descent */
393 return FALSE;
395 return TRUE;
398 /*************************************************************************
399 * ILFindChild [SHELL32.24]
401 * NOTES
402 * Compares elements from pidl1 and pidl2.
404 * pidl1 is desktop pidl2
405 * pidl1 shorter pidl2 pointer to first different element of pidl2
406 * if there was at least one equal element
407 * pidl2 shorter pidl1 0
408 * pidl2 equal pidl1 pointer to last 0x00-element of pidl2
410 LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
412 char szData1[MAX_PATH];
413 char szData2[MAX_PATH];
415 LPITEMIDLIST pidltemp1 = pidl1;
416 LPITEMIDLIST pidltemp2 = pidl2;
417 LPITEMIDLIST ret=NULL;
419 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
421 /* explorer reads from registry directly (StreamMRU),
422 so we can only check here */
423 if ((!pcheck (pidl1)) || (!pcheck (pidl2)))
424 return FALSE;
426 pdump (pidl1);
427 pdump (pidl2);
429 if ( _ILIsDesktop(pidl1) )
431 ret = pidl2;
433 else
435 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
437 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
438 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
440 if (strcasecmp(szData1,szData2))
441 break;
443 pidltemp1 = ILGetNext(pidltemp1);
444 pidltemp2 = ILGetNext(pidltemp2);
445 ret = pidltemp2;
448 if (pidltemp1->mkid.cb)
450 ret = NULL; /* elements of pidl1 left*/
453 TRACE_(shell)("--- %p\n", ret);
454 return ret; /* pidl 1 is shorter */
457 /*************************************************************************
458 * ILCombine [SHELL32.25]
460 * NOTES
461 * Concatenates two complex idlists.
462 * The pidl is the first one, pidlsub the next one
463 * Does not destroy the passed in idlists!
465 LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
467 DWORD len1,len2;
468 LPITEMIDLIST pidlNew;
470 TRACE("pidl=%p pidl=%p\n",pidl1,pidl2);
472 if(!pidl1 && !pidl2) return NULL;
474 pdump (pidl1);
475 pdump (pidl2);
477 if(!pidl1)
479 pidlNew = ILClone(pidl2);
480 return pidlNew;
483 if(!pidl2)
485 pidlNew = ILClone(pidl1);
486 return pidlNew;
489 len1 = ILGetSize(pidl1)-2;
490 len2 = ILGetSize(pidl2);
491 pidlNew = SHAlloc(len1+len2);
493 if (pidlNew)
495 memcpy(pidlNew,pidl1,len1);
496 memcpy(((BYTE *)pidlNew)+len1,pidl2,len2);
499 /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
500 return pidlNew;
502 /*************************************************************************
503 * SHGetRealIDL [SHELL32.98]
505 * NOTES
507 LPITEMIDLIST WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl, DWORD z)
509 FIXME("sf=%p pidl=%p 0x%04lx\n",lpsf,pidl,z);
511 pdump (pidl);
512 return 0;
515 /*************************************************************************
516 * SHLogILFromFSIL [SHELL32.95]
518 * NOTES
519 * pild = CSIDL_DESKTOP ret = 0
520 * pild = CSIDL_DRIVES ret = 0
522 LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
524 FIXME("(pidl=%p)\n",pidl);
526 pdump(pidl);
528 return 0;
531 /*************************************************************************
532 * ILGetSize [SHELL32.152]
533 * gets the byte size of an idlist including zero terminator (pidl)
535 * PARAMETERS
536 * pidl ITEMIDLIST
538 * RETURNS
539 * size of pidl
541 * NOTES
542 * exported by ordinal
544 DWORD WINAPI ILGetSize(LPITEMIDLIST pidl)
546 LPSHITEMID si = &(pidl->mkid);
547 DWORD len=0;
549 if (pidl)
550 { while (si->cb)
551 { len += si->cb;
552 si = (LPSHITEMID)(((LPBYTE)si)+si->cb);
554 len += 2;
556 TRACE("pidl=%p size=%lu\n",pidl, len);
557 return len;
560 /*************************************************************************
561 * ILGetNext [SHELL32.153]
562 * gets the next simple pidl of a complex pidl
564 * observed return values:
565 * null -> null
566 * desktop -> null
567 * simple pidl -> pointer to 0x0000 element
570 LPITEMIDLIST WINAPI ILGetNext(LPITEMIDLIST pidl)
572 WORD len;
574 TRACE("%p\n", pidl);
576 if(pidl)
578 len = pidl->mkid.cb;
579 if (len)
581 pidl = (LPITEMIDLIST) (((LPBYTE)pidl)+len);
582 TRACE("-- %p\n", pidl);
583 return pidl;
586 return NULL;
588 /*************************************************************************
589 * ILAppend [SHELL32.154]
591 * NOTES
592 * Adds the single item to the idlist indicated by pidl.
593 * if bEnd is 0, adds the item to the front of the list,
594 * otherwise adds the item to the end. (???)
595 * Destroys the passed in idlist! (???)
597 LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl,LPCITEMIDLIST item,BOOL bEnd)
599 LPITEMIDLIST idlRet;
601 WARN("(pidl=%p,pidl=%p,%08u)semi-stub\n",pidl,item,bEnd);
603 pdump (pidl);
604 pdump (item);
606 if (_ILIsDesktop(pidl))
608 idlRet = ILClone(item);
609 if (pidl)
610 SHFree (pidl);
611 return idlRet;
614 if (bEnd)
616 idlRet=ILCombine(pidl,item);
618 else
620 idlRet=ILCombine(item,pidl);
623 SHFree(pidl);
624 return idlRet;
626 /*************************************************************************
627 * ILFree [SHELL32.155]
629 * NOTES
630 * free_check_ptr - frees memory (if not NULL)
631 * allocated by SHMalloc allocator
632 * exported by ordinal
634 DWORD WINAPI ILFree(LPITEMIDLIST pidl)
636 TRACE("(pidl=0x%08lx)\n",(DWORD)pidl);
638 if(!pidl) return FALSE;
639 SHFree(pidl);
640 return TRUE;
642 /*************************************************************************
643 * ILGlobalFree [SHELL32.156]
646 void WINAPI ILGlobalFree( LPCITEMIDLIST pidl)
648 TRACE("%p\n",pidl);
650 if(!pidl) return;
651 Free(pidl);
653 /*************************************************************************
654 * ILCreateFromPath [SHELL32.157]
657 LPITEMIDLIST WINAPI ILCreateFromPathA (LPCSTR path)
659 LPITEMIDLIST pidlnew;
660 DWORD attributes = 0;
662 TRACE_(shell)("%s\n",path);
664 if (SUCCEEDED (SHILCreateFromPathA (path, &pidlnew, &attributes)))
665 return pidlnew;
666 return FALSE;
668 LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path)
670 LPITEMIDLIST pidlnew;
671 DWORD attributes = 0;
673 TRACE_(shell)("%s\n",debugstr_w(path));
675 if (SUCCEEDED (SHILCreateFromPathW (path, &pidlnew, &attributes)))
676 return pidlnew;
677 return FALSE;
679 LPITEMIDLIST WINAPI ILCreateFromPathAW (LPCVOID path)
681 if ( SHELL_OsIsUnicode())
682 return ILCreateFromPathW (path);
683 return ILCreateFromPathA (path);
685 /*************************************************************************
686 * SHSimpleIDListFromPath [SHELL32.162]
688 LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPCSTR lpszPath)
690 LPITEMIDLIST pidl=NULL;
691 HANDLE hFile;
692 WIN32_FIND_DATAA stffile;
694 TRACE("path=%s\n", lpszPath);
696 if (!lpszPath) return NULL;
698 hFile = FindFirstFileA(lpszPath, &stffile);
700 if ( hFile != INVALID_HANDLE_VALUE )
702 if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
704 pidl = _ILCreateFolder (&stffile);
706 else
708 pidl = _ILCreateValue (&stffile);
710 FindClose (hFile);
712 return pidl;
714 LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPCWSTR lpszPath)
716 char lpszTemp[MAX_PATH];
717 TRACE("path=%s\n",debugstr_w(lpszPath));
719 if (!WideCharToMultiByte( CP_ACP, 0, lpszPath, -1, lpszTemp, sizeof(lpszTemp), NULL, NULL ))
720 lpszTemp[sizeof(lpszTemp)-1] = 0;
722 return SHSimpleIDListFromPathA (lpszTemp);
725 LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW (LPCVOID lpszPath)
727 if ( SHELL_OsIsUnicode())
728 return SHSimpleIDListFromPathW (lpszPath);
729 return SHSimpleIDListFromPathA (lpszPath);
732 /*************************************************************************
733 * SHGetSpecialFolderLocation [SHELL32.@]
735 * gets the folder locations from the registry and creates a pidl
736 * creates missing reg keys and directories
738 * PARAMS
739 * hwndOwner [I]
740 * nFolder [I] CSIDL_xxxxx
741 * ppidl [O] PIDL of a special folder
744 HRESULT WINAPI SHGetSpecialFolderLocation(
745 HWND hwndOwner,
746 INT nFolder,
747 LPITEMIDLIST * ppidl)
749 CHAR szPath[MAX_PATH];
750 HRESULT hr = E_INVALIDARG;
752 TRACE_(shell)("(%p,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
754 if (ppidl)
756 *ppidl = NULL;
757 switch (nFolder)
759 case CSIDL_DESKTOP:
760 *ppidl = _ILCreateDesktop();
761 break;
763 case CSIDL_DRIVES:
764 *ppidl = _ILCreateMyComputer();
765 break;
767 case CSIDL_NETWORK:
768 *ppidl = _ILCreateNetwork ();
769 break;
771 case CSIDL_CONTROLS:
772 *ppidl = _ILCreateControl ();
773 break;
775 case CSIDL_PRINTERS:
776 *ppidl = _ILCreatePrinter ();
777 break;
779 case CSIDL_BITBUCKET:
780 *ppidl = _ILCreateBitBucket ();
781 break;
783 default:
784 if (SHGetSpecialFolderPathA(hwndOwner, szPath, nFolder, TRUE))
786 DWORD attributes=0;
787 TRACE_(shell)("Value=%s\n",szPath);
788 hr = SHILCreateFromPathA(szPath, ppidl, &attributes);
791 if(*ppidl) hr = NOERROR;
794 TRACE_(shell)("-- (new pidl %p)\n",*ppidl);
795 return hr;
798 /*************************************************************************
799 * SHGetFolderLocation [SHELL32.@]
801 * NOTES
802 * the pidl can be a simple one. since we cant get the path out of the pidl
803 * we have to take all data from the pidl
805 HRESULT WINAPI SHGetFolderLocation(
806 HWND hwnd,
807 int csidl,
808 HANDLE hToken,
809 DWORD dwFlags,
810 LPITEMIDLIST *ppidl)
812 FIXME("%p 0x%08x %p 0x%08lx %p\n",
813 hwnd, csidl, hToken, dwFlags, ppidl);
814 return SHGetSpecialFolderLocation(hwnd, csidl, ppidl);
817 /*************************************************************************
818 * SHGetDataFromIDListA [SHELL32.247]
820 * NOTES
821 * the pidl can be a simple one. since we cant get the path out of the pidl
822 * we have to take all data from the pidl
824 HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
826 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
828 pdump(pidl);
829 if (!psf || !dest ) return E_INVALIDARG;
831 switch (nFormat)
833 case SHGDFIL_FINDDATA:
835 WIN32_FIND_DATAA * pfd = dest;
837 if ( len < sizeof (WIN32_FIND_DATAA)) return E_INVALIDARG;
839 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
840 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
841 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
842 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
843 lstrcpynA(pfd->cFileName,_ILGetTextPointer(pidl), MAX_PATH);
844 lstrcpynA(pfd->cAlternateFileName,_ILGetSTextPointer(pidl), 14);
846 return NOERROR;
848 case SHGDFIL_NETRESOURCE:
849 case SHGDFIL_DESCRIPTIONID:
850 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
851 break;
853 default:
854 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
857 return E_INVALIDARG;
859 /*************************************************************************
860 * SHGetDataFromIDListW [SHELL32.248]
863 HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
865 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
867 pdump(pidl);
869 if (! psf || !dest ) return E_INVALIDARG;
871 switch (nFormat)
873 case SHGDFIL_FINDDATA:
875 WIN32_FIND_DATAW * pfd = dest;
877 if ( len < sizeof (WIN32_FIND_DATAW)) return E_INVALIDARG;
879 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
880 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
881 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
882 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
883 if (!MultiByteToWideChar( CP_ACP, 0, _ILGetTextPointer(pidl), -1,
884 pfd->cFileName, MAX_PATH ))
885 pfd->cFileName[MAX_PATH-1] = 0;
886 if (!MultiByteToWideChar( CP_ACP, 0, _ILGetSTextPointer(pidl), -1,
887 pfd->cAlternateFileName, 14 ))
888 pfd->cFileName[13] = 0;
890 return NOERROR;
891 case SHGDFIL_NETRESOURCE:
892 case SHGDFIL_DESCRIPTIONID:
893 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
894 break;
896 default:
897 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
900 return E_INVALIDARG;
903 /*************************************************************************
904 * SHGetPathFromIDListA [SHELL32.@][NT 4.0: SHELL32.220]
906 * PARAMETERS
907 * pidl, [IN] pidl
908 * pszPath [OUT] path
910 * RETURNS
911 * path from a passed PIDL.
913 * NOTES
914 * NULL returns FALSE
915 * desktop pidl gives path to desktopdirectory back
916 * special pidls returning FALSE
918 BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath)
920 HRESULT hr;
921 STRRET str;
922 LPSHELLFOLDER shellfolder;
924 TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
925 pdump(pidl);
927 if (!pidl) return FALSE;
929 hr = SHGetDesktopFolder(&shellfolder);
930 if (SUCCEEDED (hr)) {
931 hr = IShellFolder_GetDisplayNameOf(shellfolder,pidl,SHGDN_FORPARSING,&str);
932 if(SUCCEEDED(hr)) {
933 StrRetToStrNA (pszPath, MAX_PATH, &str, pidl);
935 IShellFolder_Release(shellfolder);
938 TRACE_(shell)("-- %s, 0x%08lx\n",pszPath, hr);
939 return SUCCEEDED(hr);
941 /*************************************************************************
942 * SHGetPathFromIDListW [SHELL32.@]
944 BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
946 HRESULT hr;
947 STRRET str;
948 LPSHELLFOLDER shellfolder;
950 TRACE_(shell)("(pidl=%p,%p)\n", pidl, debugstr_w(pszPath));
951 pdump(pidl);
953 if (!pidl) return FALSE;
955 hr = SHGetDesktopFolder(&shellfolder);
956 if (SUCCEEDED(hr)) {
957 hr = IShellFolder_GetDisplayNameOf(shellfolder, pidl, SHGDN_FORPARSING, &str);
958 if (SUCCEEDED(hr)) {
959 StrRetToStrNW(pszPath, MAX_PATH, &str, pidl);
961 IShellFolder_Release(shellfolder);
964 TRACE_(shell)("-- %s, 0x%08lx\n",debugstr_w(pszPath), hr);
965 return SUCCEEDED(hr);
968 /*************************************************************************
969 * SHBindToParent [shell version 5.0]
971 HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
973 IShellFolder * psf;
974 LPITEMIDLIST pidlChild, pidlParent;
975 HRESULT hr=E_FAIL;
977 TRACE_(shell)("pidl=%p\n", pidl);
978 pdump(pidl);
980 *ppv = NULL;
981 if (ppidlLast) *ppidlLast = NULL;
983 if (_ILIsPidlSimple(pidl))
985 /* we are on desktop level */
986 if (ppidlLast)
987 *ppidlLast = ILClone(pidl);
988 hr = SHGetDesktopFolder((IShellFolder**)ppv);
990 else
992 pidlChild = ILClone(ILFindLastID(pidl));
993 pidlParent = ILClone(pidl);
994 ILRemoveLastID(pidlParent);
996 hr = SHGetDesktopFolder(&psf);
998 if (SUCCEEDED(hr))
999 hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv);
1001 if (SUCCEEDED(hr) && ppidlLast)
1002 *ppidlLast = pidlChild;
1003 else
1004 ILFree (pidlChild);
1006 SHFree (pidlParent);
1007 if (psf) IShellFolder_Release(psf);
1011 TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr);
1012 return hr;
1015 /*************************************************************************
1016 * SHGetPathFromIDList [SHELL32.@][NT 4.0: SHELL32.219]
1018 BOOL WINAPI SHGetPathFromIDListAW(LPCITEMIDLIST pidl,LPVOID pszPath)
1020 TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
1022 if (SHELL_OsIsUnicode())
1023 return SHGetPathFromIDListW(pidl,pszPath);
1024 return SHGetPathFromIDListA(pidl,pszPath);
1027 /**************************************************************************
1029 * internal functions
1031 * ### 1. section creating pidls ###
1033 *************************************************************************
1034 * _ILCreateDesktop()
1035 * _ILCreateIExplore()
1036 * _ILCreateMyComputer()
1037 * _ILCreateDrive()
1038 * _ILCreateFolder()
1039 * _ILCreateValue()
1041 LPITEMIDLIST _ILCreateDesktop()
1042 { TRACE("()\n");
1043 return _ILCreate(PT_DESKTOP, NULL, 0);
1046 LPITEMIDLIST _ILCreateMyComputer()
1047 { TRACE("()\n");
1048 return _ILCreate(PT_MYCOMP, &CLSID_MyComputer, sizeof(GUID));
1051 LPITEMIDLIST _ILCreateIExplore()
1052 { TRACE("()\n");
1053 return _ILCreate(PT_MYCOMP, &CLSID_Internet, sizeof(GUID));
1056 LPITEMIDLIST _ILCreateControl()
1057 { TRACE("()\n");
1058 return _ILCreate(PT_SPECIAL, &CLSID_ControlPanel, sizeof(GUID));
1061 LPITEMIDLIST _ILCreatePrinter()
1062 { TRACE("()\n");
1063 return _ILCreate(PT_SPECIAL, &CLSID_Printers, sizeof(GUID));
1066 LPITEMIDLIST _ILCreateNetwork()
1067 { TRACE("()\n");
1068 return _ILCreate(PT_MYCOMP, &CLSID_NetworkPlaces, sizeof(GUID));
1071 LPITEMIDLIST _ILCreateBitBucket()
1072 { TRACE("()\n");
1073 return _ILCreate(PT_MYCOMP, &CLSID_RecycleBin, sizeof(GUID));
1076 LPITEMIDLIST _ILCreateDrive( LPCSTR lpszNew)
1077 { char sTemp[4];
1078 lstrcpynA (sTemp,lpszNew,4);
1079 sTemp[2]='\\';
1080 sTemp[3]=0x00;
1081 TRACE("(%s)\n",sTemp);
1082 return _ILCreate(PT_DRIVE,(LPVOID)&sTemp[0],4);
1085 LPITEMIDLIST _ILCreateFolder( WIN32_FIND_DATAA * stffile )
1087 char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1088 char * pbuff = buff;
1089 ULONG len, len1;
1090 LPITEMIDLIST pidl;
1092 TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1094 /* prepare buffer with both names */
1095 len = strlen (stffile->cFileName) + 1;
1096 memcpy (pbuff, stffile->cFileName, len);
1097 pbuff += len;
1099 if (stffile->cAlternateFileName)
1101 len1 = strlen (stffile->cAlternateFileName)+1;
1102 memcpy (pbuff, stffile->cAlternateFileName, len1);
1104 else
1106 len1 = 1;
1107 *pbuff = 0x00;
1110 pidl = _ILCreate(PT_FOLDER, (LPVOID)buff, len + len1);
1112 /* set attributes */
1113 if (pidl)
1115 LPPIDLDATA pData;
1116 pData = _ILGetDataPointer(pidl);
1117 FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1118 pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1119 pData->u.folder.uFileAttribs = stffile->dwFileAttributes;
1122 return pidl;
1125 LPITEMIDLIST _ILCreateValue(WIN32_FIND_DATAA * stffile)
1127 char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1128 char * pbuff = buff;
1129 ULONG len, len1;
1130 LPITEMIDLIST pidl;
1132 TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1134 /* prepare buffer with both names */
1135 len = strlen (stffile->cFileName) + 1;
1136 memcpy (pbuff, stffile->cFileName, len);
1137 pbuff += len;
1139 if (stffile->cAlternateFileName)
1141 len1 = strlen (stffile->cAlternateFileName)+1;
1142 memcpy (pbuff, stffile->cAlternateFileName, len1);
1144 else
1146 len1 = 1;
1147 *pbuff = 0x00;
1150 pidl = _ILCreate(PT_VALUE, (LPVOID)buff, len + len1);
1152 /* set attributes */
1153 if (pidl)
1155 LPPIDLDATA pData;
1156 pData = _ILGetDataPointer(pidl);
1157 FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1158 pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1159 pData->u.folder.uFileAttribs=stffile->dwFileAttributes;
1162 return pidl;
1165 LPITEMIDLIST _ILCreateFromPathA(LPCSTR szPath)
1167 HANDLE hFile;
1168 WIN32_FIND_DATAA stffile;
1169 LPITEMIDLIST pidl = NULL;
1171 hFile = FindFirstFileA(szPath, &stffile);
1172 if (hFile != INVALID_HANDLE_VALUE)
1174 if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1175 pidl = _ILCreateFolder(&stffile);
1176 else
1177 pidl = _ILCreateValue(&stffile);
1178 FindClose(hFile);
1180 return pidl;
1183 LPITEMIDLIST _ILCreateSpecial(LPCSTR szGUID)
1185 IID iid;
1187 if (!SUCCEEDED(SHCLSIDFromStringA(szGUID, &iid)))
1189 ERR("%s is not a GUID\n", szGUID);
1190 return NULL;
1192 return _ILCreate(PT_MYCOMP, &iid, sizeof(IID));
1195 /**************************************************************************
1196 * _ILCreate()
1197 * Creates a new PIDL
1198 * type = PT_DESKTOP | PT_DRIVE | PT_FOLDER | PT_VALUE
1199 * pIn = data
1200 * uInSize = size of data (raw)
1203 LPITEMIDLIST _ILCreate(PIDLTYPE type, LPCVOID pIn, UINT uInSize)
1205 LPITEMIDLIST pidlOut = NULL, pidlTemp = NULL;
1206 LPPIDLDATA pData;
1207 UINT uSize = 0;
1208 LPSTR pszDest;
1210 TRACE("(0x%02x %p %i)\n",type,pIn,uInSize);
1212 switch (type)
1214 case PT_DESKTOP:
1215 uSize = 0;
1216 break;
1217 case PT_SPECIAL:
1218 case PT_MYCOMP:
1219 uSize = 2 + 2 + sizeof(GUID);
1220 break;
1221 case PT_DRIVE:
1222 uSize = 2 + 23;
1223 break;
1224 case PT_FOLDER:
1225 case PT_VALUE:
1226 uSize = 2 + 12 + uInSize;
1227 break;
1228 default:
1229 FIXME("can't create type: 0x%08x\n",type);
1230 return NULL;
1233 if(!(pidlOut = SHAlloc(uSize + 2))) return NULL;
1234 ZeroMemory(pidlOut, uSize + 2);
1235 pidlOut->mkid.cb = uSize;
1237 switch (type)
1239 case PT_DESKTOP:
1240 TRACE("- create Desktop\n");
1241 break;
1243 case PT_SPECIAL:
1244 case PT_MYCOMP:
1245 pData =_ILGetDataPointer(pidlOut);
1246 pData->type = type;
1247 memcpy(&(pData->u.mycomp.guid), pIn, uInSize);
1248 TRACE("-- create GUID-pidl %s\n", debugstr_guid(&(pData->u.mycomp.guid)));
1249 break;
1251 case PT_DRIVE:
1252 pData =_ILGetDataPointer(pidlOut);
1253 pData->type = type;
1254 pszDest = _ILGetTextPointer(pidlOut);
1255 memcpy(pszDest, pIn, uInSize);
1256 TRACE("-- create Drive: %s\n",debugstr_a(pszDest));
1257 break;
1259 case PT_FOLDER:
1260 case PT_VALUE:
1261 pData =_ILGetDataPointer(pidlOut);
1262 pData->type = type;
1263 pszDest = _ILGetTextPointer(pidlOut);
1264 memcpy(pszDest, pIn, uInSize);
1265 TRACE("-- create Value: %s\n",debugstr_a(pszDest));
1266 break;
1269 pidlTemp = ILGetNext(pidlOut);
1270 if (pidlTemp)
1271 pidlTemp->mkid.cb = 0x00;
1273 TRACE("-- (pidl=%p, size=%u)\n", pidlOut, uSize);
1274 return pidlOut;
1277 /**************************************************************************
1278 * _ILGetDrive()
1280 * Gets the text for the drive eg. 'c:\'
1282 * RETURNS
1283 * strlen (lpszText)
1285 DWORD _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT uSize)
1286 { TRACE("(%p,%p,%u)\n",pidl,pOut,uSize);
1288 if(_ILIsMyComputer(pidl))
1289 pidl = ILGetNext(pidl);
1291 if (pidl && _ILIsDrive(pidl))
1292 return _ILSimpleGetText(pidl, pOut, uSize);
1294 return 0;
1297 /**************************************************************************
1299 * ### 2. section testing pidls ###
1301 **************************************************************************
1302 * _ILIsDesktop()
1303 * _ILIsMyComputer()
1304 * _ILIsSpecialFolder()
1305 * _ILIsDrive()
1306 * _ILIsFolder()
1307 * _ILIsValue()
1308 * _ILIsPidlSimple()
1310 BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
1311 { TRACE("(%p)\n",pidl);
1312 return pidl && pidl->mkid.cb ? 0 : 1;
1315 BOOL _ILIsMyComputer(LPCITEMIDLIST pidl)
1317 REFIID iid = _ILGetGUIDPointer(pidl);
1319 TRACE("(%p)\n",pidl);
1321 if (iid)
1322 return IsEqualIID(iid, &CLSID_MyComputer);
1323 return FALSE;
1326 BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl)
1328 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1329 TRACE("(%p)\n",pidl);
1330 return (pidl && ( (lpPData && (PT_MYCOMP== lpPData->type || PT_SPECIAL== lpPData->type)) ||
1331 (pidl && pidl->mkid.cb == 0x00)
1335 BOOL _ILIsDrive(LPCITEMIDLIST pidl)
1336 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1337 TRACE("(%p)\n",pidl);
1338 return (pidl && lpPData && (PT_DRIVE == lpPData->type ||
1339 PT_DRIVE1 == lpPData->type ||
1340 PT_DRIVE2 == lpPData->type ||
1341 PT_DRIVE3 == lpPData->type));
1344 BOOL _ILIsFolder(LPCITEMIDLIST pidl)
1345 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1346 TRACE("(%p)\n",pidl);
1347 return (pidl && lpPData && (PT_FOLDER == lpPData->type || PT_FOLDER1 == lpPData->type));
1350 BOOL _ILIsValue(LPCITEMIDLIST pidl)
1351 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1352 TRACE("(%p)\n",pidl);
1353 return (pidl && lpPData && PT_VALUE == lpPData->type);
1356 /**************************************************************************
1357 * _ILIsPidlSimple
1359 BOOL _ILIsPidlSimple ( LPCITEMIDLIST pidl)
1361 BOOL ret = TRUE;
1363 if(! _ILIsDesktop(pidl)) /* pidl=NULL or mkid.cb=0 */
1365 WORD len = pidl->mkid.cb;
1366 LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((LPBYTE)pidl) + len );
1367 if (pidlnext->mkid.cb)
1368 ret = FALSE;
1371 TRACE("%s\n", ret ? "Yes" : "No");
1372 return ret;
1375 /**************************************************************************
1377 * ### 3. section getting values from pidls ###
1380 /**************************************************************************
1381 * _ILSimpleGetText
1383 * gets the text for the first item in the pidl (eg. simple pidl)
1385 * returns the length of the string
1387 DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
1389 DWORD dwReturn=0;
1390 LPSTR szSrc;
1391 GUID const * riid;
1392 char szTemp[MAX_PATH];
1394 TRACE("(%p %p %x)\n",pidl,szOut,uOutSize);
1396 if (!pidl) return 0;
1398 if (szOut)
1399 *szOut = 0;
1401 if (_ILIsDesktop(pidl))
1403 /* desktop */
1404 if (HCR_GetClassNameA(&CLSID_ShellDesktop, szTemp, MAX_PATH))
1406 if (szOut)
1407 lstrcpynA(szOut, szTemp, uOutSize);
1409 dwReturn = strlen (szTemp);
1412 else if (( szSrc = _ILGetTextPointer(pidl) ))
1414 /* filesystem */
1415 if (szOut)
1416 lstrcpynA(szOut, szSrc, uOutSize);
1418 dwReturn = strlen(szSrc);
1420 else if (( riid = _ILGetGUIDPointer(pidl) ))
1422 /* special folder */
1423 if ( HCR_GetClassNameA(riid, szTemp, MAX_PATH) )
1425 if (szOut)
1426 lstrcpynA(szOut, szTemp, uOutSize);
1428 dwReturn = strlen (szTemp);
1431 else
1433 ERR("-- no text\n");
1436 TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_a(szOut),dwReturn);
1437 return dwReturn;
1440 /**************************************************************************
1442 * ### 4. getting pointers to parts of pidls ###
1444 **************************************************************************
1445 * _ILGetDataPointer()
1447 LPPIDLDATA _ILGetDataPointer(LPITEMIDLIST pidl)
1449 if(pidl && pidl->mkid.cb != 0x00)
1450 return (LPPIDLDATA) &(pidl->mkid.abID);
1451 return NULL;
1454 /**************************************************************************
1455 * _ILGetTextPointer()
1456 * gets a pointer to the long filename string stored in the pidl
1458 LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
1459 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1461 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1463 if (pdata)
1465 switch (pdata->type)
1467 case PT_MYCOMP:
1468 case PT_SPECIAL:
1469 return NULL;
1471 case PT_DRIVE:
1472 case PT_DRIVE1:
1473 case PT_DRIVE2:
1474 case PT_DRIVE3:
1475 return (LPSTR)&(pdata->u.drive.szDriveName);
1477 case PT_FOLDER:
1478 case PT_FOLDER1:
1479 case PT_VALUE:
1480 case PT_IESPECIAL1:
1481 case PT_IESPECIAL2:
1482 return (LPSTR)&(pdata->u.file.szNames);
1484 case PT_WORKGRP:
1485 case PT_COMP:
1486 case PT_NETWORK:
1487 case PT_SHARE:
1488 return (LPSTR)&(pdata->u.network.szNames);
1491 return NULL;
1494 /**************************************************************************
1495 * _ILGetSTextPointer()
1496 * gets a pointer to the short filename string stored in the pidl
1498 LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl)
1499 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1501 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1503 if (pdata)
1505 switch (pdata->type)
1507 case PT_FOLDER:
1508 case PT_VALUE:
1509 case PT_IESPECIAL1:
1510 case PT_IESPECIAL2:
1511 return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1);
1513 case PT_WORKGRP:
1514 return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1);
1517 return NULL;
1520 /**************************************************************************
1521 * _ILGetGUIDPointer()
1523 * returns reference to guid stored in some pidls
1525 REFIID _ILGetGUIDPointer(LPCITEMIDLIST pidl)
1527 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1529 TRACE("%p\n", pidl);
1531 if (pdata)
1533 TRACE("pdata->type 0x%04x\n", pdata->type);
1534 switch (pdata->type)
1536 case PT_SPECIAL:
1537 case PT_MYCOMP:
1538 return (REFIID) &(pdata->u.mycomp.guid);
1540 default:
1541 TRACE("Unknown pidl type 0x%04x\n", pdata->type);
1542 break;
1545 return NULL;
1548 /*************************************************************************
1549 * _ILGetFileDateTime
1551 * Given the ItemIdList, get the FileTime
1553 * PARAMS
1554 * pidl [I] The ItemIDList
1555 * pFt [I] the resulted FILETIME of the file
1557 * RETURNS
1558 * True if Successful
1560 * NOTES
1563 BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt)
1565 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1567 if(! pdata) return FALSE;
1569 switch (pdata->type)
1571 case PT_FOLDER:
1572 DosDateTimeToFileTime(pdata->u.folder.uFileDate, pdata->u.folder.uFileTime, pFt);
1573 break;
1574 case PT_VALUE:
1575 DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt);
1576 break;
1577 default:
1578 return FALSE;
1580 return TRUE;
1583 BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1585 FILETIME ft,lft;
1586 SYSTEMTIME time;
1587 BOOL ret;
1589 if (_ILGetFileDateTime( pidl, &ft )) {
1590 FileTimeToLocalFileTime(&ft, &lft);
1591 FileTimeToSystemTime (&lft, &time);
1592 ret = GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize);
1593 } else {
1594 pOut[0] = '\0';
1595 ret = FALSE;
1597 return ret;
1601 /*************************************************************************
1602 * _ILGetFileSize
1604 * Given the ItemIdList, get the FileSize
1606 * PARAMS
1607 * pidl [I] The ItemIDList
1608 * pOut [I] The buffer to save the result
1609 * uOutsize [I] The size of the buffer
1611 * RETURNS
1612 * The FileSize
1614 * NOTES
1615 * pOut can be null when no string is needed
1618 DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1620 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1621 DWORD dwSize;
1623 if(! pdata) return 0;
1625 switch (pdata->type)
1627 case PT_VALUE:
1628 dwSize = pdata->u.file.dwFileSize;
1629 if (pOut) StrFormatByteSizeA(dwSize, pOut, uOutSize);
1630 return dwSize;
1632 if (pOut) *pOut = 0x00;
1633 return 0;
1636 BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1638 char szTemp[MAX_PATH];
1639 const char * pPoint;
1640 LPITEMIDLIST pidlTemp=pidl;
1642 TRACE("pidl=%p\n",pidl);
1644 if (!pidl) return FALSE;
1646 pidlTemp = ILFindLastID(pidl);
1648 if (!_ILIsValue(pidlTemp)) return FALSE;
1649 if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH)) return FALSE;
1651 pPoint = PathFindExtensionA(szTemp);
1653 if (! *pPoint) return FALSE;
1655 pPoint++;
1656 lstrcpynA(pOut, pPoint, uOutSize);
1657 TRACE("%s\n",pOut);
1659 return TRUE;
1662 /*************************************************************************
1663 * _ILGetFileType
1665 * Given the ItemIdList, get the file type description
1667 * PARAMS
1668 * pidl [I] The ItemIDList (simple)
1669 * pOut [I] The buffer to save the result
1670 * uOutsize [I] The size of the buffer
1672 * RETURNS
1673 * nothing
1675 * NOTES
1676 * This function copies as much as possible into the buffer.
1678 void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1680 if(_ILIsValue(pidl))
1682 char sTemp[64];
1683 if(uOutSize > 0)
1685 pOut[0] = 0;
1687 if (_ILGetExtension (pidl, sTemp, 64))
1689 if (!( HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE)
1690 && HCR_MapTypeToValueA(sTemp, pOut, uOutSize, FALSE )))
1692 lstrcpynA (pOut, sTemp, uOutSize - 6);
1693 strcat (pOut, "-file");
1697 else
1699 lstrcpynA(pOut, "Folder", uOutSize);
1703 /*************************************************************************
1704 * _ILGetFileAttributes
1706 * Given the ItemIdList, get the Attrib string format
1708 * PARAMS
1709 * pidl [I] The ItemIDList
1710 * pOut [I] The buffer to save the result
1711 * uOutsize [I] The size of the Buffer
1713 * RETURNS
1714 * Attributes
1716 * FIXME
1717 * return value 0 in case of error is a valid return value
1720 DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1722 LPPIDLDATA pData =_ILGetDataPointer(pidl);
1723 WORD wAttrib = 0;
1724 int i;
1726 if(! pData) return 0;
1728 switch(pData->type)
1730 case PT_FOLDER:
1731 wAttrib = pData->u.folder.uFileAttribs;
1732 break;
1733 case PT_VALUE:
1734 wAttrib = pData->u.file.uFileAttribs;
1735 break;
1738 if(uOutSize >= 6)
1740 i=0;
1741 if(wAttrib & FILE_ATTRIBUTE_READONLY)
1743 pOut[i++] = 'R';
1745 if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
1747 pOut[i++] = 'H';
1749 if(wAttrib & FILE_ATTRIBUTE_SYSTEM)
1751 pOut[i++] = 'S';
1753 if(wAttrib & FILE_ATTRIBUTE_ARCHIVE)
1755 pOut[i++] = 'A';
1757 if(wAttrib & FILE_ATTRIBUTE_COMPRESSED)
1759 pOut[i++] = 'C';
1761 pOut[i] = 0x00;
1763 return wAttrib;
1766 /*************************************************************************
1767 * ILFreeaPidl
1769 * free a aPidl struct
1771 void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl)
1773 UINT i;
1775 if (apidl)
1777 for (i = 0; i < cidl; i++) SHFree(apidl[i]);
1778 SHFree(apidl);
1782 /*************************************************************************
1783 * ILCopyaPidl
1785 * copies an aPidl struct
1787 LPITEMIDLIST * _ILCopyaPidl(LPITEMIDLIST * apidlsrc, UINT cidl)
1789 UINT i;
1790 LPITEMIDLIST * apidldest = (LPITEMIDLIST*)SHAlloc(cidl * sizeof(LPITEMIDLIST));
1791 if(!apidlsrc) return NULL;
1793 for (i = 0; i < cidl; i++)
1794 apidldest[i] = ILClone(apidlsrc[i]);
1796 return apidldest;
1799 /*************************************************************************
1800 * _ILCopyCidaToaPidl
1802 * creates aPidl from CIDA
1804 LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida)
1806 UINT i;
1807 LPITEMIDLIST * dst = (LPITEMIDLIST*)SHAlloc(cida->cidl * sizeof(LPITEMIDLIST));
1809 if(!dst) return NULL;
1811 if (pidl)
1812 *pidl = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[0]]));
1814 for (i = 0; i < cida->cidl; i++)
1815 dst[i] = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[i + 1]]));
1817 return dst;