Windows treats dialog control class ids 0-5 same way as 0x80-0x85.
[wine/gsoc_dplay.git] / dlls / shell32 / pidl.c
blob31315f6df42e6b2044a9c6c526b9f46cb7678696
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 * ILGetDisplayNameEx [SHELL32.186]
55 * Retrieves the display name of an ItemIDList
57 * PARAMS
58 * psf [I] Shell Folder to start with, if NULL the desktop is used
59 * pidl [I] ItemIDList relativ to the psf to get the display name for
60 * path [O] Filled in with the display name, assumed to be at least MAX_PATH long
61 * type [I] Type of display name to retrieve
62 * 0 = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR uses always the desktop as root
63 * 1 = SHGDN_NORMAL relative to the root folder
64 * 2 = SHGDN_INFOLDER relative to the root folder, only the last name
66 * RETURNS
67 * True if the display name could be retrieved successfully, False otherwise
69 BOOL WINAPI ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type)
71 BOOL ret = FALSE;
72 WCHAR wPath[MAX_PATH];
74 TRACE("%p %p %p %ld\n", psf, pidl, path, type);
76 if (!pidl || !path)
77 return FALSE;
79 ret = ILGetDisplayNameExW(psf, pidl, wPath, type);
80 WideCharToMultiByte(CP_ACP, 0, wPath, -1, path, MAX_PATH, NULL, NULL);
81 TRACE("%p %p %s\n", psf, pidl, debugstr_a(path));
83 return ret;
86 BOOL WINAPI ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type)
88 LPSHELLFOLDER psfParent, lsf = psf;
89 HRESULT ret = NO_ERROR;
90 LPITEMIDLIST pidllast;
91 STRRET strret;
92 DWORD flag;
94 TRACE("%p %p %p %ld\n", psf, pidl, path, type);
96 if (!pidl || !path)
97 return FALSE;
99 if (!lsf)
101 ret = SHGetDesktopFolder(&lsf);
102 if (FAILED(ret))
103 return FALSE;
106 if (type >= 0 && type <= 2)
108 switch (type)
110 case ILGDN_FORPARSING:
111 flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR;
112 break;
113 case ILGDN_NORMAL:
114 flag = SHGDN_NORMAL;
115 break;
116 case ILGDN_INFOLDER:
117 flag = SHGDN_INFOLDER;
118 break;
119 default:
120 FIXME("Unknown type parameter = %lx", type);
121 flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR;
122 break;
124 if (!*(LPWORD)pidl || type == ILGDN_FORPARSING)
126 ret = IShellFolder_GetDisplayNameOf(lsf, pidl, flag, &strret);
127 if (SUCCEEDED(ret))
129 ret = StrRetToStrNW(path, MAX_PATH, &strret, pidl);
132 else
134 ret = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidllast);
135 if (SUCCEEDED(ret))
137 ret = IShellFolder_GetDisplayNameOf(psfParent, pidllast, flag, &strret);
138 if (SUCCEEDED(ret))
140 ret = StrRetToStrNW(path, MAX_PATH, &strret, pidllast);
142 IShellFolder_Release(psfParent);
147 TRACE("%p %p %s\n", psf, pidl, debugstr_w(path));
149 if (!psf)
150 IShellFolder_Release(lsf);
151 return SUCCEEDED(ret);
154 BOOL WINAPI ILGetDisplayNameEx(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPVOID path, DWORD type)
156 TRACE_(shell)("%p %p %p %ld\n", psf, pidl, path, type);
157 if (SHELL_OsIsUnicode())
158 return ILGetDisplayNameExW(psf, pidl, path, type);
159 return ILGetDisplayNameExA(psf, pidl, path, type);
162 /*************************************************************************
163 * ILGetDisplayName [SHELL32.15]
165 BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl, LPVOID path)
167 TRACE_(shell)("%p %p\n", pidl, path);
168 if (SHELL_OsIsUnicode())
169 return ILGetDisplayNameExW(NULL, pidl, path, ILGDN_FORPARSING);
170 return ILGetDisplayNameExA(NULL, pidl, path, ILGDN_FORPARSING);
173 /*************************************************************************
174 * ILFindLastID [SHELL32.16]
176 * NOTES
177 * observed: pidl=Desktop return=pidl
179 LPITEMIDLIST WINAPI ILFindLastID(LPITEMIDLIST pidl)
180 { LPITEMIDLIST pidlLast = pidl;
182 TRACE("(pidl=%p)\n",pidl);
184 while (pidl->mkid.cb)
186 pidlLast = pidl;
187 pidl = ILGetNext(pidl);
189 return pidlLast;
191 /*************************************************************************
192 * ILRemoveLastID [SHELL32.17]
194 * NOTES
195 * when pidl=Desktop return=FALSE
197 BOOL WINAPI ILRemoveLastID(LPCITEMIDLIST pidl)
199 TRACE_(shell)("pidl=%p\n",pidl);
201 if (!pidl || !pidl->mkid.cb)
202 return 0;
203 ILFindLastID(pidl)->mkid.cb = 0;
204 return 1;
207 /*************************************************************************
208 * ILClone [SHELL32.18]
210 * NOTES
211 * duplicate an idlist
213 LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl)
214 { DWORD len;
215 LPITEMIDLIST newpidl;
217 if (!pidl)
218 return NULL;
220 len = ILGetSize(pidl);
221 newpidl = (LPITEMIDLIST)SHAlloc(len);
222 if (newpidl)
223 memcpy(newpidl,pidl,len);
225 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
226 pdump(pidl);
228 return newpidl;
230 /*************************************************************************
231 * ILCloneFirst [SHELL32.19]
233 * NOTES
234 * duplicates the first idlist of a complex pidl
236 LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl)
237 { DWORD len;
238 LPITEMIDLIST pidlNew = NULL;
240 TRACE("pidl=%p \n",pidl);
241 pdump(pidl);
243 if (pidl)
245 len = pidl->mkid.cb;
246 pidlNew = (LPITEMIDLIST) SHAlloc (len+2);
247 if (pidlNew)
249 memcpy(pidlNew,pidl,len+2); /* 2 -> mind a desktop pidl */
251 if (len)
252 ILGetNext(pidlNew)->mkid.cb = 0x00;
255 TRACE("-- newpidl=%p\n",pidlNew);
257 return pidlNew;
260 /*************************************************************************
261 * ILLoadFromStream (SHELL32.26)
263 * NOTES
264 * the first two bytes are the len, the pidl is following then
266 HRESULT WINAPI ILLoadFromStream (IStream * pStream, LPITEMIDLIST * ppPidl)
267 { WORD wLen = 0;
268 DWORD dwBytesRead;
269 HRESULT ret = E_FAIL;
272 TRACE_(shell)("%p %p\n", pStream , ppPidl);
274 if (*ppPidl)
275 { SHFree(*ppPidl);
276 *ppPidl = NULL;
279 IStream_AddRef (pStream);
281 if (SUCCEEDED(IStream_Read(pStream, (LPVOID)&wLen, 2, &dwBytesRead)))
282 { *ppPidl = SHAlloc (wLen);
283 if (SUCCEEDED(IStream_Read(pStream, *ppPidl , wLen, &dwBytesRead)))
284 { ret = S_OK;
286 else
287 { SHFree(*ppPidl);
288 *ppPidl = NULL;
292 /* we are not yet fully compatible */
293 if (!pcheck(*ppPidl))
294 { SHFree(*ppPidl);
295 *ppPidl = NULL;
299 IStream_Release (pStream);
301 return ret;
304 /*************************************************************************
305 * ILSaveToStream (SHELL32.27)
307 * NOTES
308 * the first two bytes are the len, the pidl is following then
310 HRESULT WINAPI ILSaveToStream (IStream * pStream, LPCITEMIDLIST pPidl)
312 LPITEMIDLIST pidl;
313 WORD wLen = 0;
314 HRESULT ret = E_FAIL;
316 TRACE_(shell)("%p %p\n", pStream, pPidl);
318 IStream_AddRef (pStream);
320 pidl = pPidl;
321 while (pidl->mkid.cb)
323 wLen += sizeof(WORD) + pidl->mkid.cb;
324 pidl = ILGetNext(pidl);
327 if (SUCCEEDED(IStream_Write(pStream, (LPVOID)&wLen, 2, NULL)))
329 if (SUCCEEDED(IStream_Write(pStream, pPidl, wLen, NULL)))
330 { ret = S_OK;
333 IStream_Release (pStream);
335 return ret;
338 HRESULT WINAPI SHILCreateFromPathA (LPCSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
339 { LPSHELLFOLDER sf;
340 WCHAR lpszDisplayName[MAX_PATH];
341 DWORD pchEaten;
342 HRESULT ret = E_FAIL;
344 TRACE_(shell)("%s %p 0x%08lx\n",path,ppidl,attributes?*attributes:0);
346 if (!MultiByteToWideChar( CP_ACP, 0, path, -1, lpszDisplayName, MAX_PATH ))
347 lpszDisplayName[MAX_PATH-1] = 0;
349 if (SUCCEEDED (SHGetDesktopFolder(&sf)))
351 ret = IShellFolder_ParseDisplayName(sf,0, NULL,lpszDisplayName,&pchEaten,ppidl,attributes);
352 IShellFolder_Release(sf);
354 return ret;
357 HRESULT WINAPI SHILCreateFromPathW (LPCWSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
358 { LPSHELLFOLDER sf;
359 DWORD pchEaten;
360 HRESULT ret = E_FAIL;
362 TRACE_(shell)("%s %p 0x%08lx\n",debugstr_w(path),ppidl,attributes?*attributes:0);
364 if (SUCCEEDED (SHGetDesktopFolder(&sf)))
366 ret = IShellFolder_ParseDisplayName(sf,0, NULL, (LPWSTR) path, &pchEaten, ppidl, attributes);
367 IShellFolder_Release(sf);
369 return ret;
372 /*************************************************************************
373 * SHILCreateFromPath [SHELL32.28]
375 * NOTES
376 * Wrapper for IShellFolder_ParseDisplayName().
378 HRESULT WINAPI SHILCreateFromPathAW (LPCVOID path, LPITEMIDLIST * ppidl, DWORD * attributes)
380 if ( SHELL_OsIsUnicode())
381 return SHILCreateFromPathW (path, ppidl, attributes);
382 return SHILCreateFromPathA (path, ppidl, attributes);
385 /*************************************************************************
386 * SHCloneSpecialIDList [SHELL32.89]
388 * PARAMETERS
389 * hwndOwner [in]
390 * nFolder [in] CSIDL_xxxxx ??
392 * RETURNS
393 * pidl ??
394 * NOTES
395 * exported by ordinal
397 LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner,DWORD nFolder,DWORD x3)
398 { LPITEMIDLIST ppidl;
399 WARN_(shell)("(hwnd=%p,csidl=0x%lx,0x%lx):semi-stub.\n",
400 hwndOwner,nFolder,x3);
402 SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl);
404 return ppidl;
407 /*************************************************************************
408 * ILGlobalClone [SHELL32.20]
411 LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl)
412 { DWORD len;
413 LPITEMIDLIST newpidl;
415 if (!pidl)
416 return NULL;
418 len = ILGetSize(pidl);
419 newpidl = (LPITEMIDLIST)Alloc(len);
420 if (newpidl)
421 memcpy(newpidl,pidl,len);
423 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
424 pdump(pidl);
426 return newpidl;
429 /*************************************************************************
430 * ILIsEqual [SHELL32.21]
433 BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
435 char szData1[MAX_PATH];
436 char szData2[MAX_PATH];
438 LPITEMIDLIST pidltemp1 = pidl1;
439 LPITEMIDLIST pidltemp2 = pidl2;
441 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
443 /* explorer reads from registry directly (StreamMRU),
444 so we can only check here */
445 if ((!pcheck (pidl1)) || (!pcheck (pidl2))) return FALSE;
447 pdump (pidl1);
448 pdump (pidl2);
450 if ( (!pidl1) || (!pidl2) ) return FALSE;
452 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
454 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
455 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
457 if (strcasecmp ( szData1, szData2 )!=0 )
458 return FALSE;
460 pidltemp1 = ILGetNext(pidltemp1);
461 pidltemp2 = ILGetNext(pidltemp2);
464 if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb)
466 return TRUE;
469 return FALSE;
471 /*************************************************************************
472 * ILIsParent [SHELL32.23]
474 * parent=a/b child=a/b/c -> true, c is in folder a/b
475 * child=a/b/c/d -> false if bImmediate is true, d is not in folder a/b
476 * child=a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b
478 BOOL WINAPI ILIsParent( LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate)
480 char szData1[MAX_PATH];
481 char szData2[MAX_PATH];
483 LPITEMIDLIST pParent = pidlParent;
484 LPITEMIDLIST pChild = pidlChild;
486 TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate);
488 while (pParent->mkid.cb && pChild->mkid.cb)
490 _ILSimpleGetText(pParent, szData1, MAX_PATH);
491 _ILSimpleGetText(pChild, szData2, MAX_PATH);
493 if (strcasecmp ( szData1, szData2 )!=0 )
494 return FALSE;
496 pParent = ILGetNext(pParent);
497 pChild = ILGetNext(pChild);
500 if ( pParent->mkid.cb || ! pChild->mkid.cb) /* child shorter or has equal length to parent */
501 return FALSE;
503 if ( ILGetNext(pChild)->mkid.cb && bImmediate) /* not immediate descent */
504 return FALSE;
506 return TRUE;
509 /*************************************************************************
510 * ILFindChild [SHELL32.24]
512 * NOTES
513 * Compares elements from pidl1 and pidl2.
515 * pidl1 is desktop pidl2
516 * pidl1 shorter pidl2 pointer to first different element of pidl2
517 * if there was at least one equal element
518 * pidl2 shorter pidl1 0
519 * pidl2 equal pidl1 pointer to last 0x00-element of pidl2
521 LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
523 char szData1[MAX_PATH];
524 char szData2[MAX_PATH];
526 LPITEMIDLIST pidltemp1 = pidl1;
527 LPITEMIDLIST pidltemp2 = pidl2;
528 LPITEMIDLIST ret=NULL;
530 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
532 /* explorer reads from registry directly (StreamMRU),
533 so we can only check here */
534 if ((!pcheck (pidl1)) || (!pcheck (pidl2)))
535 return FALSE;
537 pdump (pidl1);
538 pdump (pidl2);
540 if ( _ILIsDesktop(pidl1) )
542 ret = pidl2;
544 else
546 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
548 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
549 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
551 if (strcasecmp(szData1,szData2))
552 break;
554 pidltemp1 = ILGetNext(pidltemp1);
555 pidltemp2 = ILGetNext(pidltemp2);
556 ret = pidltemp2;
559 if (pidltemp1->mkid.cb)
561 ret = NULL; /* elements of pidl1 left*/
564 TRACE_(shell)("--- %p\n", ret);
565 return ret; /* pidl 1 is shorter */
568 /*************************************************************************
569 * ILCombine [SHELL32.25]
571 * NOTES
572 * Concatenates two complex idlists.
573 * The pidl is the first one, pidlsub the next one
574 * Does not destroy the passed in idlists!
576 LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
578 DWORD len1,len2;
579 LPITEMIDLIST pidlNew;
581 TRACE("pidl=%p pidl=%p\n",pidl1,pidl2);
583 if(!pidl1 && !pidl2) return NULL;
585 pdump (pidl1);
586 pdump (pidl2);
588 if(!pidl1)
590 pidlNew = ILClone(pidl2);
591 return pidlNew;
594 if(!pidl2)
596 pidlNew = ILClone(pidl1);
597 return pidlNew;
600 len1 = ILGetSize(pidl1)-2;
601 len2 = ILGetSize(pidl2);
602 pidlNew = SHAlloc(len1+len2);
604 if (pidlNew)
606 memcpy(pidlNew,pidl1,len1);
607 memcpy(((BYTE *)pidlNew)+len1,pidl2,len2);
610 /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
611 return pidlNew;
613 /*************************************************************************
614 * SHGetRealIDL [SHELL32.98]
616 * NOTES
618 LPITEMIDLIST WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl, DWORD z)
620 FIXME("sf=%p pidl=%p 0x%04lx\n",lpsf,pidl,z);
622 pdump (pidl);
623 return 0;
626 /*************************************************************************
627 * SHLogILFromFSIL [SHELL32.95]
629 * NOTES
630 * pild = CSIDL_DESKTOP ret = 0
631 * pild = CSIDL_DRIVES ret = 0
633 LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
635 FIXME("(pidl=%p)\n",pidl);
637 pdump(pidl);
639 return 0;
642 /*************************************************************************
643 * ILGetSize [SHELL32.152]
644 * gets the byte size of an idlist including zero terminator (pidl)
646 * PARAMETERS
647 * pidl ITEMIDLIST
649 * RETURNS
650 * size of pidl
652 * NOTES
653 * exported by ordinal
655 DWORD WINAPI ILGetSize(LPITEMIDLIST pidl)
657 LPSHITEMID si = &(pidl->mkid);
658 DWORD len=0;
660 if (pidl)
661 { while (si->cb)
662 { len += si->cb;
663 si = (LPSHITEMID)(((LPBYTE)si)+si->cb);
665 len += 2;
667 TRACE("pidl=%p size=%lu\n",pidl, len);
668 return len;
671 /*************************************************************************
672 * ILGetNext [SHELL32.153]
673 * gets the next simple pidl of a complex pidl
675 * observed return values:
676 * null -> null
677 * desktop -> null
678 * simple pidl -> pointer to 0x0000 element
681 LPITEMIDLIST WINAPI ILGetNext(LPITEMIDLIST pidl)
683 WORD len;
685 TRACE("%p\n", pidl);
687 if(pidl)
689 len = pidl->mkid.cb;
690 if (len)
692 pidl = (LPITEMIDLIST) (((LPBYTE)pidl)+len);
693 TRACE("-- %p\n", pidl);
694 return pidl;
697 return NULL;
699 /*************************************************************************
700 * ILAppend [SHELL32.154]
702 * NOTES
703 * Adds the single item to the idlist indicated by pidl.
704 * if bEnd is 0, adds the item to the front of the list,
705 * otherwise adds the item to the end. (???)
706 * Destroys the passed in idlist! (???)
708 LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl,LPCITEMIDLIST item,BOOL bEnd)
710 LPITEMIDLIST idlRet;
712 WARN("(pidl=%p,pidl=%p,%08u)semi-stub\n",pidl,item,bEnd);
714 pdump (pidl);
715 pdump (item);
717 if (_ILIsDesktop(pidl))
719 idlRet = ILClone(item);
720 if (pidl)
721 SHFree (pidl);
722 return idlRet;
725 if (bEnd)
727 idlRet=ILCombine(pidl,item);
729 else
731 idlRet=ILCombine(item,pidl);
734 SHFree(pidl);
735 return idlRet;
737 /*************************************************************************
738 * ILFree [SHELL32.155]
740 * NOTES
741 * free_check_ptr - frees memory (if not NULL)
742 * allocated by SHMalloc allocator
743 * exported by ordinal
745 DWORD WINAPI ILFree(LPITEMIDLIST pidl)
747 TRACE("(pidl=0x%08lx)\n",(DWORD)pidl);
749 if(!pidl) return FALSE;
750 SHFree(pidl);
751 return TRUE;
753 /*************************************************************************
754 * ILGlobalFree [SHELL32.156]
757 void WINAPI ILGlobalFree( LPCITEMIDLIST pidl)
759 TRACE("%p\n",pidl);
761 if(!pidl) return;
762 Free(pidl);
764 /*************************************************************************
765 * ILCreateFromPath [SHELL32.157]
768 LPITEMIDLIST WINAPI ILCreateFromPathA (LPCSTR path)
770 LPITEMIDLIST pidlnew;
771 DWORD attributes = 0;
773 TRACE_(shell)("%s\n",path);
775 if (SUCCEEDED (SHILCreateFromPathA (path, &pidlnew, &attributes)))
776 return pidlnew;
777 return FALSE;
779 LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path)
781 LPITEMIDLIST pidlnew;
782 DWORD attributes = 0;
784 TRACE_(shell)("%s\n",debugstr_w(path));
786 if (SUCCEEDED (SHILCreateFromPathW (path, &pidlnew, &attributes)))
787 return pidlnew;
788 return FALSE;
790 LPITEMIDLIST WINAPI ILCreateFromPathAW (LPCVOID path)
792 if ( SHELL_OsIsUnicode())
793 return ILCreateFromPathW (path);
794 return ILCreateFromPathA (path);
796 /*************************************************************************
797 * SHSimpleIDListFromPath [SHELL32.162]
799 LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPCSTR lpszPath)
801 LPITEMIDLIST pidl=NULL;
802 HANDLE hFile;
803 WIN32_FIND_DATAA stffile;
805 TRACE("path=%s\n", lpszPath);
807 if (!lpszPath) return NULL;
809 hFile = FindFirstFileA(lpszPath, &stffile);
811 if ( hFile != INVALID_HANDLE_VALUE )
813 if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
815 pidl = _ILCreateFolder (&stffile);
817 else
819 pidl = _ILCreateValue (&stffile);
821 FindClose (hFile);
823 return pidl;
825 LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPCWSTR lpszPath)
827 char lpszTemp[MAX_PATH];
828 TRACE("path=%s\n",debugstr_w(lpszPath));
830 if (!WideCharToMultiByte( CP_ACP, 0, lpszPath, -1, lpszTemp, sizeof(lpszTemp), NULL, NULL ))
831 lpszTemp[sizeof(lpszTemp)-1] = 0;
833 return SHSimpleIDListFromPathA (lpszTemp);
836 LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW (LPCVOID lpszPath)
838 if ( SHELL_OsIsUnicode())
839 return SHSimpleIDListFromPathW (lpszPath);
840 return SHSimpleIDListFromPathA (lpszPath);
843 /*************************************************************************
844 * SHGetSpecialFolderLocation [SHELL32.@]
846 * gets the folder locations from the registry and creates a pidl
847 * creates missing reg keys and directories
849 * PARAMS
850 * hwndOwner [I]
851 * nFolder [I] CSIDL_xxxxx
852 * ppidl [O] PIDL of a special folder
855 HRESULT WINAPI SHGetSpecialFolderLocation(
856 HWND hwndOwner,
857 INT nFolder,
858 LPITEMIDLIST * ppidl)
860 CHAR szPath[MAX_PATH];
861 HRESULT hr = E_INVALIDARG;
863 TRACE_(shell)("(%p,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
865 if (ppidl)
867 *ppidl = NULL;
868 switch (nFolder)
870 case CSIDL_DESKTOP:
871 *ppidl = _ILCreateDesktop();
872 break;
874 case CSIDL_DRIVES:
875 *ppidl = _ILCreateMyComputer();
876 break;
878 case CSIDL_NETWORK:
879 *ppidl = _ILCreateNetwork ();
880 break;
882 case CSIDL_CONTROLS:
883 *ppidl = _ILCreateControl ();
884 break;
886 case CSIDL_PRINTERS:
887 *ppidl = _ILCreatePrinter ();
888 break;
890 case CSIDL_BITBUCKET:
891 *ppidl = _ILCreateBitBucket ();
892 break;
894 default:
895 if (SHGetSpecialFolderPathA(hwndOwner, szPath, nFolder, TRUE))
897 DWORD attributes=0;
898 TRACE_(shell)("Value=%s\n",szPath);
899 hr = SHILCreateFromPathA(szPath, ppidl, &attributes);
902 if(*ppidl) hr = NOERROR;
905 TRACE_(shell)("-- (new pidl %p)\n",*ppidl);
906 return hr;
909 /*************************************************************************
910 * SHGetFolderLocation [SHELL32.@]
912 * NOTES
913 * the pidl can be a simple one. since we cant get the path out of the pidl
914 * we have to take all data from the pidl
916 HRESULT WINAPI SHGetFolderLocation(
917 HWND hwnd,
918 int csidl,
919 HANDLE hToken,
920 DWORD dwFlags,
921 LPITEMIDLIST *ppidl)
923 FIXME("%p 0x%08x %p 0x%08lx %p\n",
924 hwnd, csidl, hToken, dwFlags, ppidl);
925 return SHGetSpecialFolderLocation(hwnd, csidl, ppidl);
928 /*************************************************************************
929 * SHGetDataFromIDListA [SHELL32.247]
931 * NOTES
932 * the pidl can be a simple one. since we cant get the path out of the pidl
933 * we have to take all data from the pidl
935 HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
937 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
939 pdump(pidl);
940 if (!psf || !dest ) return E_INVALIDARG;
942 switch (nFormat)
944 case SHGDFIL_FINDDATA:
946 WIN32_FIND_DATAA * pfd = dest;
948 if ( len < sizeof (WIN32_FIND_DATAA)) return E_INVALIDARG;
950 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
951 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
952 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
953 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
954 lstrcpynA(pfd->cFileName,_ILGetTextPointer(pidl), MAX_PATH);
955 lstrcpynA(pfd->cAlternateFileName,_ILGetSTextPointer(pidl), 14);
957 return NOERROR;
959 case SHGDFIL_NETRESOURCE:
960 case SHGDFIL_DESCRIPTIONID:
961 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
962 break;
964 default:
965 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
968 return E_INVALIDARG;
970 /*************************************************************************
971 * SHGetDataFromIDListW [SHELL32.248]
974 HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
976 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
978 pdump(pidl);
980 if (! psf || !dest ) return E_INVALIDARG;
982 switch (nFormat)
984 case SHGDFIL_FINDDATA:
986 WIN32_FIND_DATAW * pfd = dest;
988 if ( len < sizeof (WIN32_FIND_DATAW)) return E_INVALIDARG;
990 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
991 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
992 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
993 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
994 if (!MultiByteToWideChar( CP_ACP, 0, _ILGetTextPointer(pidl), -1,
995 pfd->cFileName, MAX_PATH ))
996 pfd->cFileName[MAX_PATH-1] = 0;
997 if (!MultiByteToWideChar( CP_ACP, 0, _ILGetSTextPointer(pidl), -1,
998 pfd->cAlternateFileName, 14 ))
999 pfd->cFileName[13] = 0;
1001 return NOERROR;
1002 case SHGDFIL_NETRESOURCE:
1003 case SHGDFIL_DESCRIPTIONID:
1004 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
1005 break;
1007 default:
1008 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
1011 return E_INVALIDARG;
1014 /*************************************************************************
1015 * SHGetPathFromIDListA [SHELL32.@][NT 4.0: SHELL32.220]
1017 * PARAMETERS
1018 * pidl, [IN] pidl
1019 * pszPath [OUT] path
1021 * RETURNS
1022 * path from a passed PIDL.
1024 * NOTES
1025 * NULL returns FALSE
1026 * desktop pidl gives path to desktopdirectory back
1027 * special pidls returning FALSE
1029 BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath)
1031 HRESULT hr;
1032 STRRET str;
1033 LPSHELLFOLDER shellfolder;
1035 TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
1036 pdump(pidl);
1038 if (!pidl) return FALSE;
1040 hr = SHGetDesktopFolder(&shellfolder);
1041 if (SUCCEEDED (hr)) {
1042 hr = IShellFolder_GetDisplayNameOf(shellfolder,pidl,SHGDN_FORPARSING,&str);
1043 if(SUCCEEDED(hr)) {
1044 StrRetToStrNA (pszPath, MAX_PATH, &str, pidl);
1046 IShellFolder_Release(shellfolder);
1049 TRACE_(shell)("-- %s, 0x%08lx\n",pszPath, hr);
1050 return SUCCEEDED(hr);
1052 /*************************************************************************
1053 * SHGetPathFromIDListW [SHELL32.@]
1055 BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
1057 HRESULT hr;
1058 STRRET str;
1059 LPSHELLFOLDER shellfolder;
1061 TRACE_(shell)("(pidl=%p,%p)\n", pidl, debugstr_w(pszPath));
1062 pdump(pidl);
1064 if (!pidl) return FALSE;
1066 hr = SHGetDesktopFolder(&shellfolder);
1067 if (SUCCEEDED(hr)) {
1068 hr = IShellFolder_GetDisplayNameOf(shellfolder, pidl, SHGDN_FORPARSING, &str);
1069 if (SUCCEEDED(hr)) {
1070 StrRetToStrNW(pszPath, MAX_PATH, &str, pidl);
1072 IShellFolder_Release(shellfolder);
1075 TRACE_(shell)("-- %s, 0x%08lx\n",debugstr_w(pszPath), hr);
1076 return SUCCEEDED(hr);
1079 /*************************************************************************
1080 * SHBindToParent [shell version 5.0]
1082 HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
1084 IShellFolder * psf;
1085 LPITEMIDLIST pidlChild, pidlParent;
1086 HRESULT hr=E_FAIL;
1088 TRACE_(shell)("pidl=%p\n", pidl);
1089 pdump(pidl);
1091 *ppv = NULL;
1092 if (ppidlLast) *ppidlLast = NULL;
1094 if (_ILIsPidlSimple(pidl))
1096 /* we are on desktop level */
1097 if (ppidlLast)
1098 *ppidlLast = ILClone(pidl);
1099 hr = SHGetDesktopFolder((IShellFolder**)ppv);
1101 else
1103 pidlChild = ILClone(ILFindLastID(pidl));
1104 pidlParent = ILClone(pidl);
1105 ILRemoveLastID(pidlParent);
1107 hr = SHGetDesktopFolder(&psf);
1109 if (SUCCEEDED(hr))
1110 hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv);
1112 if (SUCCEEDED(hr) && ppidlLast)
1113 *ppidlLast = pidlChild;
1114 else
1115 ILFree (pidlChild);
1117 SHFree (pidlParent);
1118 if (psf) IShellFolder_Release(psf);
1122 TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr);
1123 return hr;
1126 /*************************************************************************
1127 * SHGetPathFromIDList [SHELL32.@][NT 4.0: SHELL32.219]
1129 BOOL WINAPI SHGetPathFromIDListAW(LPCITEMIDLIST pidl,LPVOID pszPath)
1131 TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
1133 if (SHELL_OsIsUnicode())
1134 return SHGetPathFromIDListW(pidl,pszPath);
1135 return SHGetPathFromIDListA(pidl,pszPath);
1138 /**************************************************************************
1140 * internal functions
1142 * ### 1. section creating pidls ###
1144 *************************************************************************
1145 * _ILCreateDesktop()
1146 * _ILCreateIExplore()
1147 * _ILCreateMyComputer()
1148 * _ILCreateDrive()
1149 * _ILCreateFolder()
1150 * _ILCreateValue()
1152 LPITEMIDLIST _ILCreateDesktop()
1153 { TRACE("()\n");
1154 return _ILCreate(PT_DESKTOP, NULL, 0);
1157 LPITEMIDLIST _ILCreateMyComputer()
1158 { TRACE("()\n");
1159 return _ILCreate(PT_MYCOMP, &CLSID_MyComputer, sizeof(GUID));
1162 LPITEMIDLIST _ILCreateIExplore()
1163 { TRACE("()\n");
1164 return _ILCreate(PT_MYCOMP, &CLSID_Internet, sizeof(GUID));
1167 LPITEMIDLIST _ILCreateControl()
1168 { TRACE("()\n");
1169 return _ILCreate(PT_SPECIAL, &CLSID_ControlPanel, sizeof(GUID));
1172 LPITEMIDLIST _ILCreatePrinter()
1173 { TRACE("()\n");
1174 return _ILCreate(PT_SPECIAL, &CLSID_Printers, sizeof(GUID));
1177 LPITEMIDLIST _ILCreateNetwork()
1178 { TRACE("()\n");
1179 return _ILCreate(PT_MYCOMP, &CLSID_NetworkPlaces, sizeof(GUID));
1182 LPITEMIDLIST _ILCreateBitBucket()
1183 { TRACE("()\n");
1184 return _ILCreate(PT_MYCOMP, &CLSID_RecycleBin, sizeof(GUID));
1187 LPITEMIDLIST _ILCreateDrive( LPCSTR lpszNew)
1188 { char sTemp[4];
1189 lstrcpynA (sTemp,lpszNew,4);
1190 sTemp[2]='\\';
1191 sTemp[3]=0x00;
1192 TRACE("(%s)\n",sTemp);
1193 return _ILCreate(PT_DRIVE,(LPVOID)&sTemp[0],4);
1196 LPITEMIDLIST _ILCreateFolder( WIN32_FIND_DATAA * stffile )
1198 char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1199 char * pbuff = buff;
1200 ULONG len, len1;
1201 LPITEMIDLIST pidl;
1203 TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1205 /* prepare buffer with both names */
1206 len = strlen (stffile->cFileName) + 1;
1207 memcpy (pbuff, stffile->cFileName, len);
1208 pbuff += len;
1210 if (stffile->cAlternateFileName)
1212 len1 = strlen (stffile->cAlternateFileName)+1;
1213 memcpy (pbuff, stffile->cAlternateFileName, len1);
1215 else
1217 len1 = 1;
1218 *pbuff = 0x00;
1221 pidl = _ILCreate(PT_FOLDER, (LPVOID)buff, len + len1);
1223 /* set attributes */
1224 if (pidl)
1226 LPPIDLDATA pData;
1227 pData = _ILGetDataPointer(pidl);
1228 FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1229 pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1230 pData->u.folder.uFileAttribs = stffile->dwFileAttributes;
1233 return pidl;
1236 LPITEMIDLIST _ILCreateValue(WIN32_FIND_DATAA * stffile)
1238 char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1239 char * pbuff = buff;
1240 ULONG len, len1;
1241 LPITEMIDLIST pidl;
1243 TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1245 /* prepare buffer with both names */
1246 len = strlen (stffile->cFileName) + 1;
1247 memcpy (pbuff, stffile->cFileName, len);
1248 pbuff += len;
1250 if (stffile->cAlternateFileName)
1252 len1 = strlen (stffile->cAlternateFileName)+1;
1253 memcpy (pbuff, stffile->cAlternateFileName, len1);
1255 else
1257 len1 = 1;
1258 *pbuff = 0x00;
1261 pidl = _ILCreate(PT_VALUE, (LPVOID)buff, len + len1);
1263 /* set attributes */
1264 if (pidl)
1266 LPPIDLDATA pData;
1267 pData = _ILGetDataPointer(pidl);
1268 FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1269 pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1270 pData->u.folder.uFileAttribs=stffile->dwFileAttributes;
1273 return pidl;
1276 LPITEMIDLIST _ILCreateFromPathA(LPCSTR szPath)
1278 HANDLE hFile;
1279 WIN32_FIND_DATAA stffile;
1280 LPITEMIDLIST pidl = NULL;
1282 hFile = FindFirstFileA(szPath, &stffile);
1283 if (hFile != INVALID_HANDLE_VALUE)
1285 if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1286 pidl = _ILCreateFolder(&stffile);
1287 else
1288 pidl = _ILCreateValue(&stffile);
1289 FindClose(hFile);
1291 return pidl;
1294 LPITEMIDLIST _ILCreateSpecial(LPCSTR szGUID)
1296 IID iid;
1298 if (!SUCCEEDED(SHCLSIDFromStringA(szGUID, &iid)))
1300 ERR("%s is not a GUID\n", szGUID);
1301 return NULL;
1303 return _ILCreate(PT_MYCOMP, &iid, sizeof(IID));
1306 /**************************************************************************
1307 * _ILCreate()
1308 * Creates a new PIDL
1309 * type = PT_DESKTOP | PT_DRIVE | PT_FOLDER | PT_VALUE
1310 * pIn = data
1311 * uInSize = size of data (raw)
1314 LPITEMIDLIST _ILCreate(PIDLTYPE type, LPCVOID pIn, UINT uInSize)
1316 LPITEMIDLIST pidlOut = NULL, pidlTemp = NULL;
1317 LPPIDLDATA pData;
1318 UINT uSize = 0;
1319 LPSTR pszDest;
1321 TRACE("(0x%02x %p %i)\n",type,pIn,uInSize);
1323 switch (type)
1325 case PT_DESKTOP:
1326 uSize = 0;
1327 break;
1328 case PT_SPECIAL:
1329 case PT_MYCOMP:
1330 uSize = 2 + 2 + sizeof(GUID);
1331 break;
1332 case PT_DRIVE:
1333 uSize = 2 + 23;
1334 break;
1335 case PT_FOLDER:
1336 case PT_VALUE:
1337 uSize = 2 + 12 + uInSize;
1338 break;
1339 default:
1340 FIXME("can't create type: 0x%08x\n",type);
1341 return NULL;
1344 if(!(pidlOut = SHAlloc(uSize + 2))) return NULL;
1345 ZeroMemory(pidlOut, uSize + 2);
1346 pidlOut->mkid.cb = uSize;
1348 switch (type)
1350 case PT_DESKTOP:
1351 TRACE("- create Desktop\n");
1352 break;
1354 case PT_SPECIAL:
1355 case PT_MYCOMP:
1356 pData =_ILGetDataPointer(pidlOut);
1357 pData->type = type;
1358 memcpy(&(pData->u.mycomp.guid), pIn, uInSize);
1359 TRACE("-- create GUID-pidl %s\n", debugstr_guid(&(pData->u.mycomp.guid)));
1360 break;
1362 case PT_DRIVE:
1363 pData =_ILGetDataPointer(pidlOut);
1364 pData->type = type;
1365 pszDest = _ILGetTextPointer(pidlOut);
1366 memcpy(pszDest, pIn, uInSize);
1367 TRACE("-- create Drive: %s\n",debugstr_a(pszDest));
1368 break;
1370 case PT_FOLDER:
1371 case PT_VALUE:
1372 pData =_ILGetDataPointer(pidlOut);
1373 pData->type = type;
1374 pszDest = _ILGetTextPointer(pidlOut);
1375 memcpy(pszDest, pIn, uInSize);
1376 TRACE("-- create Value: %s\n",debugstr_a(pszDest));
1377 break;
1380 pidlTemp = ILGetNext(pidlOut);
1381 if (pidlTemp)
1382 pidlTemp->mkid.cb = 0x00;
1384 TRACE("-- (pidl=%p, size=%u)\n", pidlOut, uSize);
1385 return pidlOut;
1388 /**************************************************************************
1389 * _ILGetDrive()
1391 * Gets the text for the drive eg. 'c:\'
1393 * RETURNS
1394 * strlen (lpszText)
1396 DWORD _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT uSize)
1397 { TRACE("(%p,%p,%u)\n",pidl,pOut,uSize);
1399 if(_ILIsMyComputer(pidl))
1400 pidl = ILGetNext(pidl);
1402 if (pidl && _ILIsDrive(pidl))
1403 return _ILSimpleGetText(pidl, pOut, uSize);
1405 return 0;
1408 /**************************************************************************
1410 * ### 2. section testing pidls ###
1412 **************************************************************************
1413 * _ILIsDesktop()
1414 * _ILIsMyComputer()
1415 * _ILIsSpecialFolder()
1416 * _ILIsDrive()
1417 * _ILIsFolder()
1418 * _ILIsValue()
1419 * _ILIsPidlSimple()
1421 BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
1422 { TRACE("(%p)\n",pidl);
1423 return pidl && pidl->mkid.cb ? 0 : 1;
1426 BOOL _ILIsMyComputer(LPCITEMIDLIST pidl)
1428 REFIID iid = _ILGetGUIDPointer(pidl);
1430 TRACE("(%p)\n",pidl);
1432 if (iid)
1433 return IsEqualIID(iid, &CLSID_MyComputer);
1434 return FALSE;
1437 BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl)
1439 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1440 TRACE("(%p)\n",pidl);
1441 return (pidl && ( (lpPData && (PT_MYCOMP== lpPData->type || PT_SPECIAL== lpPData->type)) ||
1442 (pidl && pidl->mkid.cb == 0x00)
1446 BOOL _ILIsDrive(LPCITEMIDLIST pidl)
1447 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1448 TRACE("(%p)\n",pidl);
1449 return (pidl && lpPData && (PT_DRIVE == lpPData->type ||
1450 PT_DRIVE1 == lpPData->type ||
1451 PT_DRIVE2 == lpPData->type ||
1452 PT_DRIVE3 == lpPData->type));
1455 BOOL _ILIsFolder(LPCITEMIDLIST pidl)
1456 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1457 TRACE("(%p)\n",pidl);
1458 return (pidl && lpPData && (PT_FOLDER == lpPData->type || PT_FOLDER1 == lpPData->type));
1461 BOOL _ILIsValue(LPCITEMIDLIST pidl)
1462 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1463 TRACE("(%p)\n",pidl);
1464 return (pidl && lpPData && PT_VALUE == lpPData->type);
1467 /**************************************************************************
1468 * _ILIsPidlSimple
1470 BOOL _ILIsPidlSimple ( LPCITEMIDLIST pidl)
1472 BOOL ret = TRUE;
1474 if(! _ILIsDesktop(pidl)) /* pidl=NULL or mkid.cb=0 */
1476 WORD len = pidl->mkid.cb;
1477 LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((LPBYTE)pidl) + len );
1478 if (pidlnext->mkid.cb)
1479 ret = FALSE;
1482 TRACE("%s\n", ret ? "Yes" : "No");
1483 return ret;
1486 /**************************************************************************
1488 * ### 3. section getting values from pidls ###
1491 /**************************************************************************
1492 * _ILSimpleGetText
1494 * gets the text for the first item in the pidl (eg. simple pidl)
1496 * returns the length of the string
1498 DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
1500 DWORD dwReturn=0;
1501 LPSTR szSrc;
1502 GUID const * riid;
1503 char szTemp[MAX_PATH];
1505 TRACE("(%p %p %x)\n",pidl,szOut,uOutSize);
1507 if (!pidl) return 0;
1509 if (szOut)
1510 *szOut = 0;
1512 if (_ILIsDesktop(pidl))
1514 /* desktop */
1515 if (HCR_GetClassNameA(&CLSID_ShellDesktop, szTemp, MAX_PATH))
1517 if (szOut)
1518 lstrcpynA(szOut, szTemp, uOutSize);
1520 dwReturn = strlen (szTemp);
1523 else if (( szSrc = _ILGetTextPointer(pidl) ))
1525 /* filesystem */
1526 if (szOut)
1527 lstrcpynA(szOut, szSrc, uOutSize);
1529 dwReturn = strlen(szSrc);
1531 else if (( riid = _ILGetGUIDPointer(pidl) ))
1533 /* special folder */
1534 if ( HCR_GetClassNameA(riid, szTemp, MAX_PATH) )
1536 if (szOut)
1537 lstrcpynA(szOut, szTemp, uOutSize);
1539 dwReturn = strlen (szTemp);
1542 else
1544 ERR("-- no text\n");
1547 TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_a(szOut),dwReturn);
1548 return dwReturn;
1551 /**************************************************************************
1553 * ### 4. getting pointers to parts of pidls ###
1555 **************************************************************************
1556 * _ILGetDataPointer()
1558 LPPIDLDATA _ILGetDataPointer(LPITEMIDLIST pidl)
1560 if(pidl && pidl->mkid.cb != 0x00)
1561 return (LPPIDLDATA) &(pidl->mkid.abID);
1562 return NULL;
1565 /**************************************************************************
1566 * _ILGetTextPointer()
1567 * gets a pointer to the long filename string stored in the pidl
1569 LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
1570 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1572 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1574 if (pdata)
1576 switch (pdata->type)
1578 case PT_MYCOMP:
1579 case PT_SPECIAL:
1580 return NULL;
1582 case PT_DRIVE:
1583 case PT_DRIVE1:
1584 case PT_DRIVE2:
1585 case PT_DRIVE3:
1586 return (LPSTR)&(pdata->u.drive.szDriveName);
1588 case PT_FOLDER:
1589 case PT_FOLDER1:
1590 case PT_VALUE:
1591 case PT_IESPECIAL1:
1592 case PT_IESPECIAL2:
1593 return (LPSTR)&(pdata->u.file.szNames);
1595 case PT_WORKGRP:
1596 case PT_COMP:
1597 case PT_NETWORK:
1598 case PT_SHARE:
1599 return (LPSTR)&(pdata->u.network.szNames);
1602 return NULL;
1605 /**************************************************************************
1606 * _ILGetSTextPointer()
1607 * gets a pointer to the short filename string stored in the pidl
1609 LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl)
1610 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1612 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1614 if (pdata)
1616 switch (pdata->type)
1618 case PT_FOLDER:
1619 case PT_VALUE:
1620 case PT_IESPECIAL1:
1621 case PT_IESPECIAL2:
1622 return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1);
1624 case PT_WORKGRP:
1625 return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1);
1628 return NULL;
1631 /**************************************************************************
1632 * _ILGetGUIDPointer()
1634 * returns reference to guid stored in some pidls
1636 REFIID _ILGetGUIDPointer(LPCITEMIDLIST pidl)
1638 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1640 TRACE("%p\n", pidl);
1642 if (pdata)
1644 TRACE("pdata->type 0x%04x\n", pdata->type);
1645 switch (pdata->type)
1647 case PT_SPECIAL:
1648 case PT_MYCOMP:
1649 return (REFIID) &(pdata->u.mycomp.guid);
1651 default:
1652 TRACE("Unknown pidl type 0x%04x\n", pdata->type);
1653 break;
1656 return NULL;
1659 /*************************************************************************
1660 * _ILGetFileDateTime
1662 * Given the ItemIdList, get the FileTime
1664 * PARAMS
1665 * pidl [I] The ItemIDList
1666 * pFt [I] the resulted FILETIME of the file
1668 * RETURNS
1669 * True if Successful
1671 * NOTES
1674 BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt)
1676 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1678 if(! pdata) return FALSE;
1680 switch (pdata->type)
1682 case PT_FOLDER:
1683 DosDateTimeToFileTime(pdata->u.folder.uFileDate, pdata->u.folder.uFileTime, pFt);
1684 break;
1685 case PT_VALUE:
1686 DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt);
1687 break;
1688 default:
1689 return FALSE;
1691 return TRUE;
1694 BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1696 FILETIME ft,lft;
1697 SYSTEMTIME time;
1698 BOOL ret;
1700 if (_ILGetFileDateTime( pidl, &ft )) {
1701 FileTimeToLocalFileTime(&ft, &lft);
1702 FileTimeToSystemTime (&lft, &time);
1703 ret = GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize);
1704 } else {
1705 pOut[0] = '\0';
1706 ret = FALSE;
1708 return ret;
1712 /*************************************************************************
1713 * _ILGetFileSize
1715 * Given the ItemIdList, get the FileSize
1717 * PARAMS
1718 * pidl [I] The ItemIDList
1719 * pOut [I] The buffer to save the result
1720 * uOutsize [I] The size of the buffer
1722 * RETURNS
1723 * The FileSize
1725 * NOTES
1726 * pOut can be null when no string is needed
1729 DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1731 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1732 DWORD dwSize;
1734 if(! pdata) return 0;
1736 switch (pdata->type)
1738 case PT_VALUE:
1739 dwSize = pdata->u.file.dwFileSize;
1740 if (pOut) StrFormatByteSizeA(dwSize, pOut, uOutSize);
1741 return dwSize;
1743 if (pOut) *pOut = 0x00;
1744 return 0;
1747 BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1749 char szTemp[MAX_PATH];
1750 const char * pPoint;
1751 LPITEMIDLIST pidlTemp=pidl;
1753 TRACE("pidl=%p\n",pidl);
1755 if (!pidl) return FALSE;
1757 pidlTemp = ILFindLastID(pidl);
1759 if (!_ILIsValue(pidlTemp)) return FALSE;
1760 if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH)) return FALSE;
1762 pPoint = PathFindExtensionA(szTemp);
1764 if (! *pPoint) return FALSE;
1766 pPoint++;
1767 lstrcpynA(pOut, pPoint, uOutSize);
1768 TRACE("%s\n",pOut);
1770 return TRUE;
1773 /*************************************************************************
1774 * _ILGetFileType
1776 * Given the ItemIdList, get the file type description
1778 * PARAMS
1779 * pidl [I] The ItemIDList (simple)
1780 * pOut [I] The buffer to save the result
1781 * uOutsize [I] The size of the buffer
1783 * RETURNS
1784 * nothing
1786 * NOTES
1787 * This function copies as much as possible into the buffer.
1789 void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1791 if(_ILIsValue(pidl))
1793 char sTemp[64];
1794 if(uOutSize > 0)
1796 pOut[0] = 0;
1798 if (_ILGetExtension (pidl, sTemp, 64))
1800 if (!( HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE)
1801 && HCR_MapTypeToValueA(sTemp, pOut, uOutSize, FALSE )))
1803 lstrcpynA (pOut, sTemp, uOutSize - 6);
1804 strcat (pOut, "-file");
1808 else
1810 lstrcpynA(pOut, "Folder", uOutSize);
1814 /*************************************************************************
1815 * _ILGetFileAttributes
1817 * Given the ItemIdList, get the Attrib string format
1819 * PARAMS
1820 * pidl [I] The ItemIDList
1821 * pOut [I] The buffer to save the result
1822 * uOutsize [I] The size of the Buffer
1824 * RETURNS
1825 * Attributes
1827 * FIXME
1828 * return value 0 in case of error is a valid return value
1831 DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1833 LPPIDLDATA pData =_ILGetDataPointer(pidl);
1834 WORD wAttrib = 0;
1835 int i;
1837 if(! pData) return 0;
1839 switch(pData->type)
1841 case PT_FOLDER:
1842 wAttrib = pData->u.folder.uFileAttribs;
1843 break;
1844 case PT_VALUE:
1845 wAttrib = pData->u.file.uFileAttribs;
1846 break;
1849 if(uOutSize >= 6)
1851 i=0;
1852 if(wAttrib & FILE_ATTRIBUTE_READONLY)
1854 pOut[i++] = 'R';
1856 if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
1858 pOut[i++] = 'H';
1860 if(wAttrib & FILE_ATTRIBUTE_SYSTEM)
1862 pOut[i++] = 'S';
1864 if(wAttrib & FILE_ATTRIBUTE_ARCHIVE)
1866 pOut[i++] = 'A';
1868 if(wAttrib & FILE_ATTRIBUTE_COMPRESSED)
1870 pOut[i++] = 'C';
1872 pOut[i] = 0x00;
1874 return wAttrib;
1877 /*************************************************************************
1878 * ILFreeaPidl
1880 * free a aPidl struct
1882 void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl)
1884 UINT i;
1886 if (apidl)
1888 for (i = 0; i < cidl; i++) SHFree(apidl[i]);
1889 SHFree(apidl);
1893 /*************************************************************************
1894 * ILCopyaPidl
1896 * copies an aPidl struct
1898 LPITEMIDLIST * _ILCopyaPidl(LPITEMIDLIST * apidlsrc, UINT cidl)
1900 UINT i;
1901 LPITEMIDLIST * apidldest = (LPITEMIDLIST*)SHAlloc(cidl * sizeof(LPITEMIDLIST));
1902 if(!apidlsrc) return NULL;
1904 for (i = 0; i < cidl; i++)
1905 apidldest[i] = ILClone(apidlsrc[i]);
1907 return apidldest;
1910 /*************************************************************************
1911 * _ILCopyCidaToaPidl
1913 * creates aPidl from CIDA
1915 LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida)
1917 UINT i;
1918 LPITEMIDLIST * dst = (LPITEMIDLIST*)SHAlloc(cida->cidl * sizeof(LPITEMIDLIST));
1920 if(!dst) return NULL;
1922 if (pidl)
1923 *pidl = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[0]]));
1925 for (i = 0; i < cida->cidl; i++)
1926 dst[i] = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[i + 1]]));
1928 return dst;