Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / shell32 / pidl.c
blob26bf730f5e8bbc4f4e1cfd35bad1d820baccfed5
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 <stdarg.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winreg.h"
35 #include "objbase.h"
36 #include "shlguid.h"
37 #include "winerror.h"
38 #include "winnls.h"
39 #include "undocshell.h"
40 #include "shell32_main.h"
41 #include "shellapi.h"
42 #include "shlwapi.h"
44 #include "pidl.h"
45 #include "debughlp.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(pidl);
49 WINE_DECLARE_DEBUG_CHANNEL(shell);
51 /* from comctl32.dll */
52 extern LPVOID WINAPI Alloc(INT);
53 extern BOOL WINAPI Free(LPVOID);
55 /*************************************************************************
56 * ILGetDisplayNameEx [SHELL32.186]
58 * Retrieves the display name of an ItemIDList
60 * PARAMS
61 * psf [I] Shell Folder to start with, if NULL the desktop is used
62 * pidl [I] ItemIDList relativ to the psf to get the display name for
63 * path [O] Filled in with the display name, assumed to be at least MAX_PATH long
64 * type [I] Type of display name to retrieve
65 * 0 = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR uses always the desktop as root
66 * 1 = SHGDN_NORMAL relative to the root folder
67 * 2 = SHGDN_INFOLDER relative to the root folder, only the last name
69 * RETURNS
70 * True if the display name could be retrieved successfully, False otherwise
72 BOOL WINAPI ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type)
74 BOOL ret = FALSE;
75 WCHAR wPath[MAX_PATH];
77 TRACE("%p %p %p %ld\n", psf, pidl, path, type);
79 if (!pidl || !path)
80 return FALSE;
82 ret = ILGetDisplayNameExW(psf, pidl, wPath, type);
83 WideCharToMultiByte(CP_ACP, 0, wPath, -1, path, MAX_PATH, NULL, NULL);
84 TRACE("%p %p %s\n", psf, pidl, debugstr_a(path));
86 return ret;
89 BOOL WINAPI ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type)
91 LPSHELLFOLDER psfParent, lsf = psf;
92 HRESULT ret = NO_ERROR;
93 LPCITEMIDLIST pidllast;
94 STRRET strret;
95 DWORD flag;
97 TRACE("%p %p %p %ld\n", psf, pidl, path, type);
99 if (!pidl || !path)
100 return FALSE;
102 if (!lsf)
104 ret = SHGetDesktopFolder(&lsf);
105 if (FAILED(ret))
106 return FALSE;
109 if (type >= 0 && type <= 2)
111 switch (type)
113 case ILGDN_FORPARSING:
114 flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR;
115 break;
116 case ILGDN_NORMAL:
117 flag = SHGDN_NORMAL;
118 break;
119 case ILGDN_INFOLDER:
120 flag = SHGDN_INFOLDER;
121 break;
122 default:
123 FIXME("Unknown type parameter = %lx", type);
124 flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR;
125 break;
127 if (!*(LPWORD)pidl || type == ILGDN_FORPARSING)
129 ret = IShellFolder_GetDisplayNameOf(lsf, pidl, flag, &strret);
130 if (SUCCEEDED(ret))
132 ret = StrRetToStrNW(path, MAX_PATH, &strret, pidl);
135 else
137 ret = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidllast);
138 if (SUCCEEDED(ret))
140 ret = IShellFolder_GetDisplayNameOf(psfParent, pidllast, flag, &strret);
141 if (SUCCEEDED(ret))
143 ret = StrRetToStrNW(path, MAX_PATH, &strret, pidllast);
145 IShellFolder_Release(psfParent);
150 TRACE("%p %p %s\n", psf, pidl, debugstr_w(path));
152 if (!psf)
153 IShellFolder_Release(lsf);
154 return SUCCEEDED(ret);
157 BOOL WINAPI ILGetDisplayNameEx(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPVOID path, DWORD type)
159 TRACE_(shell)("%p %p %p %ld\n", psf, pidl, path, type);
160 if (SHELL_OsIsUnicode())
161 return ILGetDisplayNameExW(psf, pidl, path, type);
162 return ILGetDisplayNameExA(psf, pidl, path, type);
165 /*************************************************************************
166 * ILGetDisplayName [SHELL32.15]
168 BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl, LPVOID path)
170 TRACE_(shell)("%p %p\n", pidl, path);
171 if (SHELL_OsIsUnicode())
172 return ILGetDisplayNameExW(NULL, pidl, path, ILGDN_FORPARSING);
173 return ILGetDisplayNameExA(NULL, pidl, path, ILGDN_FORPARSING);
176 /*************************************************************************
177 * ILFindLastID [SHELL32.16]
179 * NOTES
180 * observed: pidl=Desktop return=pidl
182 LPITEMIDLIST WINAPI ILFindLastID(LPCITEMIDLIST pidl)
183 { LPCITEMIDLIST pidlLast = pidl;
185 TRACE("(pidl=%p)\n",pidl);
187 while (pidl->mkid.cb)
189 pidlLast = pidl;
190 pidl = ILGetNext(pidl);
192 return (LPITEMIDLIST)pidlLast;
194 /*************************************************************************
195 * ILRemoveLastID [SHELL32.17]
197 * NOTES
198 * when pidl=Desktop return=FALSE
200 BOOL WINAPI ILRemoveLastID(LPCITEMIDLIST pidl)
202 TRACE_(shell)("pidl=%p\n",pidl);
204 if (!pidl || !pidl->mkid.cb)
205 return 0;
206 ILFindLastID(pidl)->mkid.cb = 0;
207 return 1;
210 /*************************************************************************
211 * ILClone [SHELL32.18]
213 * NOTES
214 * duplicate an idlist
216 LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl)
217 { DWORD len;
218 LPITEMIDLIST newpidl;
220 if (!pidl)
221 return NULL;
223 len = ILGetSize(pidl);
224 newpidl = (LPITEMIDLIST)SHAlloc(len);
225 if (newpidl)
226 memcpy(newpidl,pidl,len);
228 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
229 pdump(pidl);
231 return newpidl;
233 /*************************************************************************
234 * ILCloneFirst [SHELL32.19]
236 * NOTES
237 * duplicates the first idlist of a complex pidl
239 LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl)
240 { DWORD len;
241 LPITEMIDLIST pidlNew = NULL;
243 TRACE("pidl=%p \n",pidl);
244 pdump(pidl);
246 if (pidl)
248 len = pidl->mkid.cb;
249 pidlNew = (LPITEMIDLIST) SHAlloc (len+2);
250 if (pidlNew)
252 memcpy(pidlNew,pidl,len+2); /* 2 -> mind a desktop pidl */
254 if (len)
255 ILGetNext(pidlNew)->mkid.cb = 0x00;
258 TRACE("-- newpidl=%p\n",pidlNew);
260 return pidlNew;
263 /*************************************************************************
264 * ILLoadFromStream (SHELL32.26)
266 * NOTES
267 * the first two bytes are the len, the pidl is following then
269 HRESULT WINAPI ILLoadFromStream (IStream * pStream, LPITEMIDLIST * ppPidl)
270 { WORD wLen = 0;
271 DWORD dwBytesRead;
272 HRESULT ret = E_FAIL;
275 TRACE_(shell)("%p %p\n", pStream , ppPidl);
277 if (*ppPidl)
278 { SHFree(*ppPidl);
279 *ppPidl = NULL;
282 IStream_AddRef (pStream);
284 if (SUCCEEDED(IStream_Read(pStream, (LPVOID)&wLen, 2, &dwBytesRead)))
286 TRACE("PIDL length is %d\n", wLen);
287 if (wLen != 0) {
288 *ppPidl = SHAlloc (wLen);
289 if (SUCCEEDED(IStream_Read(pStream, *ppPidl , wLen, &dwBytesRead))) {
290 TRACE("Stream read OK\n");
291 ret = S_OK;
292 } else {
293 WARN("reading pidl failed\n");
294 SHFree(*ppPidl);
295 *ppPidl = NULL;
297 } else {
298 *ppPidl = NULL;
299 ret = S_OK;
303 /* we are not yet fully compatible */
304 if (*ppPidl && !pcheck(*ppPidl))
306 WARN("Check failed\n");
307 SHFree(*ppPidl);
308 *ppPidl = NULL;
312 IStream_Release (pStream);
313 TRACE("done\n");
314 return ret;
317 /*************************************************************************
318 * ILSaveToStream (SHELL32.27)
320 * NOTES
321 * the first two bytes are the len, the pidl is following then
323 HRESULT WINAPI ILSaveToStream (IStream * pStream, LPCITEMIDLIST pPidl)
325 LPCITEMIDLIST pidl;
326 WORD wLen = 0;
327 HRESULT ret = E_FAIL;
329 TRACE_(shell)("%p %p\n", pStream, pPidl);
331 IStream_AddRef (pStream);
333 pidl = pPidl;
334 while (pidl->mkid.cb)
336 wLen += sizeof(WORD) + pidl->mkid.cb;
337 pidl = ILGetNext(pidl);
340 if (SUCCEEDED(IStream_Write(pStream, (LPVOID)&wLen, 2, NULL)))
342 if (SUCCEEDED(IStream_Write(pStream, pPidl, wLen, NULL)))
343 { ret = S_OK;
346 IStream_Release (pStream);
348 return ret;
351 HRESULT WINAPI SHILCreateFromPathA (LPCSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
352 { LPSHELLFOLDER sf;
353 WCHAR lpszDisplayName[MAX_PATH];
354 DWORD pchEaten;
355 HRESULT ret = E_FAIL;
357 TRACE_(shell)("%s %p 0x%08lx\n",path,ppidl,attributes?*attributes:0);
359 if (!MultiByteToWideChar( CP_ACP, 0, path, -1, lpszDisplayName, MAX_PATH ))
360 lpszDisplayName[MAX_PATH-1] = 0;
362 if (SUCCEEDED (SHGetDesktopFolder(&sf)))
364 ret = IShellFolder_ParseDisplayName(sf,0, NULL,lpszDisplayName,&pchEaten,ppidl,attributes);
365 IShellFolder_Release(sf);
367 return ret;
370 HRESULT WINAPI SHILCreateFromPathW (LPCWSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
371 { LPSHELLFOLDER sf;
372 DWORD pchEaten;
373 HRESULT ret = E_FAIL;
375 TRACE_(shell)("%s %p 0x%08lx\n",debugstr_w(path),ppidl,attributes?*attributes:0);
377 if (SUCCEEDED (SHGetDesktopFolder(&sf)))
379 ret = IShellFolder_ParseDisplayName(sf,0, NULL, (LPWSTR) path, &pchEaten, ppidl, attributes);
380 IShellFolder_Release(sf);
382 return ret;
385 /*************************************************************************
386 * SHILCreateFromPath [SHELL32.28]
388 * NOTES
389 * Wrapper for IShellFolder_ParseDisplayName().
391 HRESULT WINAPI SHILCreateFromPathAW (LPCVOID path, LPITEMIDLIST * ppidl, DWORD * attributes)
393 if ( SHELL_OsIsUnicode())
394 return SHILCreateFromPathW (path, ppidl, attributes);
395 return SHILCreateFromPathA (path, ppidl, attributes);
398 /*************************************************************************
399 * SHCloneSpecialIDList [SHELL32.89]
401 * PARAMETERS
402 * hwndOwner [in]
403 * nFolder [in] CSIDL_xxxxx ??
405 * RETURNS
406 * pidl ??
407 * NOTES
408 * exported by ordinal
410 LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner,DWORD nFolder,DWORD x3)
411 { LPITEMIDLIST ppidl;
412 WARN_(shell)("(hwnd=%p,csidl=0x%lx,0x%lx):semi-stub.\n",
413 hwndOwner,nFolder,x3);
415 SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl);
417 return ppidl;
420 /*************************************************************************
421 * ILGlobalClone [SHELL32.20]
424 LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl)
425 { DWORD len;
426 LPITEMIDLIST newpidl;
428 if (!pidl)
429 return NULL;
431 len = ILGetSize(pidl);
432 newpidl = (LPITEMIDLIST)Alloc(len);
433 if (newpidl)
434 memcpy(newpidl,pidl,len);
436 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
437 pdump(pidl);
439 return newpidl;
442 /*************************************************************************
443 * ILIsEqual [SHELL32.21]
446 BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
448 char szData1[MAX_PATH];
449 char szData2[MAX_PATH];
451 LPCITEMIDLIST pidltemp1 = pidl1;
452 LPCITEMIDLIST pidltemp2 = pidl2;
454 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
456 /* explorer reads from registry directly (StreamMRU),
457 so we can only check here */
458 if ((!pcheck (pidl1)) || (!pcheck (pidl2))) return FALSE;
460 pdump (pidl1);
461 pdump (pidl2);
463 if ( (!pidl1) || (!pidl2) ) return FALSE;
465 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
467 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
468 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
470 if (strcasecmp ( szData1, szData2 )!=0 )
471 return FALSE;
473 pidltemp1 = ILGetNext(pidltemp1);
474 pidltemp2 = ILGetNext(pidltemp2);
477 if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb)
479 return TRUE;
482 return FALSE;
484 /*************************************************************************
485 * ILIsParent [SHELL32.23]
487 * parent=a/b child=a/b/c -> true, c is in folder a/b
488 * child=a/b/c/d -> false if bImmediate is true, d is not in folder a/b
489 * child=a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b
491 BOOL WINAPI ILIsParent( LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate)
493 char szData1[MAX_PATH];
494 char szData2[MAX_PATH];
496 LPCITEMIDLIST pParent = pidlParent;
497 LPCITEMIDLIST pChild = pidlChild;
499 TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate);
501 while (pParent->mkid.cb && pChild->mkid.cb)
503 _ILSimpleGetText(pParent, szData1, MAX_PATH);
504 _ILSimpleGetText(pChild, szData2, MAX_PATH);
506 if (strcasecmp ( szData1, szData2 )!=0 )
507 return FALSE;
509 pParent = ILGetNext(pParent);
510 pChild = ILGetNext(pChild);
513 if ( pParent->mkid.cb || ! pChild->mkid.cb) /* child shorter or has equal length to parent */
514 return FALSE;
516 if ( ILGetNext(pChild)->mkid.cb && bImmediate) /* not immediate descent */
517 return FALSE;
519 return TRUE;
522 /*************************************************************************
523 * ILFindChild [SHELL32.24]
525 * NOTES
526 * Compares elements from pidl1 and pidl2.
528 * pidl1 is desktop pidl2
529 * pidl1 shorter pidl2 pointer to first different element of pidl2
530 * if there was at least one equal element
531 * pidl2 shorter pidl1 0
532 * pidl2 equal pidl1 pointer to last 0x00-element of pidl2
534 LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
536 char szData1[MAX_PATH];
537 char szData2[MAX_PATH];
539 LPCITEMIDLIST pidltemp1 = pidl1;
540 LPCITEMIDLIST pidltemp2 = pidl2;
541 LPCITEMIDLIST ret=NULL;
543 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
545 /* explorer reads from registry directly (StreamMRU),
546 so we can only check here */
547 if ((!pcheck (pidl1)) || (!pcheck (pidl2)))
548 return FALSE;
550 pdump (pidl1);
551 pdump (pidl2);
553 if ( _ILIsDesktop(pidl1) )
555 ret = pidl2;
557 else
559 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
561 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
562 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
564 if (strcasecmp(szData1,szData2))
565 break;
567 pidltemp1 = ILGetNext(pidltemp1);
568 pidltemp2 = ILGetNext(pidltemp2);
569 ret = pidltemp2;
572 if (pidltemp1->mkid.cb)
574 ret = NULL; /* elements of pidl1 left*/
577 TRACE_(shell)("--- %p\n", ret);
578 return (LPITEMIDLIST)ret; /* pidl 1 is shorter */
581 /*************************************************************************
582 * ILCombine [SHELL32.25]
584 * NOTES
585 * Concatenates two complex idlists.
586 * The pidl is the first one, pidlsub the next one
587 * Does not destroy the passed in idlists!
589 LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
591 DWORD len1,len2;
592 LPITEMIDLIST pidlNew;
594 TRACE("pidl=%p pidl=%p\n",pidl1,pidl2);
596 if(!pidl1 && !pidl2) return NULL;
598 pdump (pidl1);
599 pdump (pidl2);
601 if(!pidl1)
603 pidlNew = ILClone(pidl2);
604 return pidlNew;
607 if(!pidl2)
609 pidlNew = ILClone(pidl1);
610 return pidlNew;
613 len1 = ILGetSize(pidl1)-2;
614 len2 = ILGetSize(pidl2);
615 pidlNew = SHAlloc(len1+len2);
617 if (pidlNew)
619 memcpy(pidlNew,pidl1,len1);
620 memcpy(((BYTE *)pidlNew)+len1,pidl2,len2);
623 /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
624 return pidlNew;
626 /*************************************************************************
627 * SHGetRealIDL [SHELL32.98]
629 * NOTES
631 LPITEMIDLIST WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl, DWORD z)
633 FIXME("sf=%p pidl=%p 0x%04lx\n",lpsf,pidl,z);
635 pdump (pidl);
636 return 0;
639 /*************************************************************************
640 * SHLogILFromFSIL [SHELL32.95]
642 * NOTES
643 * pild = CSIDL_DESKTOP ret = 0
644 * pild = CSIDL_DRIVES ret = 0
646 LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
648 FIXME("(pidl=%p)\n",pidl);
650 pdump(pidl);
652 return 0;
655 /*************************************************************************
656 * ILGetSize [SHELL32.152]
657 * gets the byte size of an idlist including zero terminator (pidl)
659 * PARAMETERS
660 * pidl ITEMIDLIST
662 * RETURNS
663 * size of pidl
665 * NOTES
666 * exported by ordinal
668 DWORD WINAPI ILGetSize(LPCITEMIDLIST pidl)
670 LPCSHITEMID si = &(pidl->mkid);
671 DWORD len=0;
673 if (pidl)
674 { while (si->cb)
675 { len += si->cb;
676 si = (LPSHITEMID)(((LPBYTE)si)+si->cb);
678 len += 2;
680 TRACE("pidl=%p size=%lu\n",pidl, len);
681 return len;
684 /*************************************************************************
685 * ILGetNext [SHELL32.153]
686 * gets the next simple pidl of a complex pidl
688 * observed return values:
689 * null -> null
690 * desktop -> null
691 * simple pidl -> pointer to 0x0000 element
694 LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl)
696 WORD len;
698 TRACE("%p\n", pidl);
700 if(pidl)
702 len = pidl->mkid.cb;
703 if (len)
705 pidl = (LPITEMIDLIST) (((LPBYTE)pidl)+len);
706 TRACE("-- %p\n", pidl);
707 return (LPITEMIDLIST)pidl;
710 return NULL;
712 /*************************************************************************
713 * ILAppend [SHELL32.154]
715 * NOTES
716 * Adds the single item to the idlist indicated by pidl.
717 * if bEnd is 0, adds the item to the front of the list,
718 * otherwise adds the item to the end. (???)
719 * Destroys the passed in idlist! (???)
721 LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl,LPCITEMIDLIST item,BOOL bEnd)
723 LPITEMIDLIST idlRet;
725 WARN("(pidl=%p,pidl=%p,%08u)semi-stub\n",pidl,item,bEnd);
727 pdump (pidl);
728 pdump (item);
730 if (_ILIsDesktop(pidl))
732 idlRet = ILClone(item);
733 if (pidl)
734 SHFree (pidl);
735 return idlRet;
738 if (bEnd)
740 idlRet=ILCombine(pidl,item);
742 else
744 idlRet=ILCombine(item,pidl);
747 SHFree(pidl);
748 return idlRet;
750 /*************************************************************************
751 * ILFree [SHELL32.155]
753 * NOTES
754 * free_check_ptr - frees memory (if not NULL)
755 * allocated by SHMalloc allocator
756 * exported by ordinal
758 DWORD WINAPI ILFree(LPITEMIDLIST pidl)
760 TRACE("(pidl=0x%08lx)\n",(DWORD)pidl);
762 if(!pidl) return FALSE;
763 SHFree(pidl);
764 return TRUE;
766 /*************************************************************************
767 * ILGlobalFree [SHELL32.156]
770 void WINAPI ILGlobalFree( LPITEMIDLIST pidl)
772 TRACE("%p\n",pidl);
774 if(!pidl) return;
775 Free(pidl);
777 /*************************************************************************
778 * ILCreateFromPath [SHELL32.157]
781 LPITEMIDLIST WINAPI ILCreateFromPathA (LPCSTR path)
783 LPITEMIDLIST pidlnew;
784 DWORD attributes = 0;
786 TRACE_(shell)("%s\n",path);
788 if (SUCCEEDED (SHILCreateFromPathA (path, &pidlnew, &attributes)))
789 return pidlnew;
790 return FALSE;
792 LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path)
794 LPITEMIDLIST pidlnew;
795 DWORD attributes = 0;
797 TRACE_(shell)("%s\n",debugstr_w(path));
799 if (SUCCEEDED (SHILCreateFromPathW (path, &pidlnew, &attributes)))
800 return pidlnew;
801 return FALSE;
803 LPITEMIDLIST WINAPI ILCreateFromPathAW (LPCVOID path)
805 if ( SHELL_OsIsUnicode())
806 return ILCreateFromPathW (path);
807 return ILCreateFromPathA (path);
809 /*************************************************************************
810 * SHSimpleIDListFromPath [SHELL32.162]
812 LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPCSTR lpszPath)
814 LPITEMIDLIST pidl=NULL;
815 HANDLE hFile;
816 WIN32_FIND_DATAA stffile;
818 TRACE("path=%s\n", lpszPath);
820 if (!lpszPath) return NULL;
822 hFile = FindFirstFileA(lpszPath, &stffile);
824 if ( hFile != INVALID_HANDLE_VALUE )
826 if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
828 pidl = _ILCreateFolder (&stffile);
830 else
832 pidl = _ILCreateValue (&stffile);
834 FindClose (hFile);
836 return pidl;
838 LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPCWSTR lpszPath)
840 char lpszTemp[MAX_PATH];
841 TRACE("path=%s\n",debugstr_w(lpszPath));
843 if (!WideCharToMultiByte( CP_ACP, 0, lpszPath, -1, lpszTemp, sizeof(lpszTemp), NULL, NULL ))
844 lpszTemp[sizeof(lpszTemp)-1] = 0;
846 return SHSimpleIDListFromPathA (lpszTemp);
849 LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW (LPCVOID lpszPath)
851 if ( SHELL_OsIsUnicode())
852 return SHSimpleIDListFromPathW (lpszPath);
853 return SHSimpleIDListFromPathA (lpszPath);
856 /*************************************************************************
857 * SHGetSpecialFolderLocation [SHELL32.@]
859 * gets the folder locations from the registry and creates a pidl
860 * creates missing reg keys and directories
862 * PARAMS
863 * hwndOwner [I]
864 * nFolder [I] CSIDL_xxxxx
865 * ppidl [O] PIDL of a special folder
868 HRESULT WINAPI SHGetSpecialFolderLocation(
869 HWND hwndOwner,
870 INT nFolder,
871 LPITEMIDLIST * ppidl)
873 CHAR szPath[MAX_PATH];
874 HRESULT hr = E_INVALIDARG;
876 TRACE_(shell)("(%p,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
878 if (ppidl)
880 *ppidl = NULL;
881 switch (nFolder)
883 case CSIDL_DESKTOP:
884 *ppidl = _ILCreateDesktop();
885 break;
887 case CSIDL_DRIVES:
888 *ppidl = _ILCreateMyComputer();
889 break;
891 case CSIDL_NETWORK:
892 *ppidl = _ILCreateNetwork ();
893 break;
895 case CSIDL_CONTROLS:
896 *ppidl = _ILCreateControl ();
897 break;
899 case CSIDL_PRINTERS:
900 *ppidl = _ILCreatePrinter ();
901 break;
903 case CSIDL_BITBUCKET:
904 *ppidl = _ILCreateBitBucket ();
905 break;
907 default:
908 if (SHGetSpecialFolderPathA(hwndOwner, szPath, nFolder, TRUE))
910 DWORD attributes=0;
911 TRACE_(shell)("Value=%s\n",szPath);
912 hr = SHILCreateFromPathA(szPath, ppidl, &attributes);
915 if(*ppidl) hr = NOERROR;
918 TRACE_(shell)("-- (new pidl %p)\n",*ppidl);
919 return hr;
922 /*************************************************************************
923 * SHGetFolderLocation [SHELL32.@]
925 * NOTES
926 * the pidl can be a simple one. since we cant get the path out of the pidl
927 * we have to take all data from the pidl
929 HRESULT WINAPI SHGetFolderLocation(
930 HWND hwnd,
931 int csidl,
932 HANDLE hToken,
933 DWORD dwFlags,
934 LPITEMIDLIST *ppidl)
936 FIXME("%p 0x%08x %p 0x%08lx %p\n",
937 hwnd, csidl, hToken, dwFlags, ppidl);
938 return SHGetSpecialFolderLocation(hwnd, csidl, ppidl);
941 /*************************************************************************
942 * SHGetDataFromIDListA [SHELL32.247]
944 * NOTES
945 * the pidl can be a simple one. since we cant get the path out of the pidl
946 * we have to take all data from the pidl
948 HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
950 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
952 pdump(pidl);
953 if (!psf || !dest ) return E_INVALIDARG;
955 switch (nFormat)
957 case SHGDFIL_FINDDATA:
959 WIN32_FIND_DATAA * pfd = dest;
961 if ( len < sizeof (WIN32_FIND_DATAA)) return E_INVALIDARG;
963 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
964 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
965 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
966 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
967 lstrcpynA(pfd->cFileName,_ILGetTextPointer(pidl), MAX_PATH);
968 lstrcpynA(pfd->cAlternateFileName,_ILGetSTextPointer(pidl), 14);
970 return NOERROR;
972 case SHGDFIL_NETRESOURCE:
973 case SHGDFIL_DESCRIPTIONID:
974 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
975 break;
977 default:
978 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
981 return E_INVALIDARG;
983 /*************************************************************************
984 * SHGetDataFromIDListW [SHELL32.248]
987 HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
989 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
991 pdump(pidl);
993 if (! psf || !dest ) return E_INVALIDARG;
995 switch (nFormat)
997 case SHGDFIL_FINDDATA:
999 WIN32_FIND_DATAW * pfd = dest;
1001 if ( len < sizeof (WIN32_FIND_DATAW)) return E_INVALIDARG;
1003 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
1004 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
1005 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
1006 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
1007 if (!MultiByteToWideChar( CP_ACP, 0, _ILGetTextPointer(pidl), -1,
1008 pfd->cFileName, MAX_PATH ))
1009 pfd->cFileName[MAX_PATH-1] = 0;
1010 if (!MultiByteToWideChar( CP_ACP, 0, _ILGetSTextPointer(pidl), -1,
1011 pfd->cAlternateFileName, 14 ))
1012 pfd->cFileName[13] = 0;
1014 return NOERROR;
1015 case SHGDFIL_NETRESOURCE:
1016 case SHGDFIL_DESCRIPTIONID:
1017 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
1018 break;
1020 default:
1021 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
1024 return E_INVALIDARG;
1027 /*************************************************************************
1028 * SHGetPathFromIDListA [SHELL32.@][NT 4.0: SHELL32.220]
1030 * PARAMETERS
1031 * pidl, [IN] pidl
1032 * pszPath [OUT] path
1034 * RETURNS
1035 * path from a passed PIDL.
1037 * NOTES
1038 * NULL returns FALSE
1039 * desktop pidl gives path to desktopdirectory back
1040 * special pidls returning FALSE
1042 BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath)
1044 HRESULT hr;
1045 STRRET str;
1046 LPSHELLFOLDER shellfolder;
1048 TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
1049 pdump(pidl);
1051 if (!pidl) return FALSE;
1053 hr = SHGetDesktopFolder(&shellfolder);
1054 if (SUCCEEDED (hr)) {
1055 hr = IShellFolder_GetDisplayNameOf(shellfolder,pidl,SHGDN_FORPARSING,&str);
1056 if(SUCCEEDED(hr)) {
1057 StrRetToStrNA (pszPath, MAX_PATH, &str, pidl);
1059 IShellFolder_Release(shellfolder);
1062 TRACE_(shell)("-- %s, 0x%08lx\n",pszPath, hr);
1063 return SUCCEEDED(hr);
1065 /*************************************************************************
1066 * SHGetPathFromIDListW [SHELL32.@]
1068 BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
1070 HRESULT hr;
1071 STRRET str;
1072 LPSHELLFOLDER shellfolder;
1074 TRACE_(shell)("(pidl=%p,%p)\n", pidl, debugstr_w(pszPath));
1075 pdump(pidl);
1077 if (!pidl) return FALSE;
1079 hr = SHGetDesktopFolder(&shellfolder);
1080 if (SUCCEEDED(hr)) {
1081 hr = IShellFolder_GetDisplayNameOf(shellfolder, pidl, SHGDN_FORPARSING, &str);
1082 if (SUCCEEDED(hr)) {
1083 StrRetToStrNW(pszPath, MAX_PATH, &str, pidl);
1085 IShellFolder_Release(shellfolder);
1088 TRACE_(shell)("-- %s, 0x%08lx\n",debugstr_w(pszPath), hr);
1089 return SUCCEEDED(hr);
1092 /*************************************************************************
1093 * SHBindToParent [shell version 5.0]
1095 HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
1097 IShellFolder * psf;
1098 LPITEMIDLIST pidlChild, pidlParent;
1099 HRESULT hr=E_FAIL;
1101 TRACE_(shell)("pidl=%p\n", pidl);
1102 pdump(pidl);
1104 *ppv = NULL;
1105 if (ppidlLast) *ppidlLast = NULL;
1107 if (_ILIsPidlSimple(pidl))
1109 /* we are on desktop level */
1110 if (ppidlLast)
1111 *ppidlLast = ILClone(pidl);
1112 hr = SHGetDesktopFolder((IShellFolder**)ppv);
1114 else
1116 pidlChild = ILClone(ILFindLastID(pidl));
1117 pidlParent = ILClone(pidl);
1118 ILRemoveLastID(pidlParent);
1120 hr = SHGetDesktopFolder(&psf);
1122 if (SUCCEEDED(hr))
1123 hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv);
1125 if (SUCCEEDED(hr) && ppidlLast)
1126 *ppidlLast = pidlChild;
1127 else
1128 ILFree (pidlChild);
1130 SHFree (pidlParent);
1131 if (psf) IShellFolder_Release(psf);
1135 TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr);
1136 return hr;
1139 /*************************************************************************
1140 * SHGetPathFromIDList [SHELL32.@][NT 4.0: SHELL32.219]
1142 BOOL WINAPI SHGetPathFromIDListAW(LPCITEMIDLIST pidl,LPVOID pszPath)
1144 TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
1146 if (SHELL_OsIsUnicode())
1147 return SHGetPathFromIDListW(pidl,pszPath);
1148 return SHGetPathFromIDListA(pidl,pszPath);
1151 /**************************************************************************
1153 * internal functions
1155 * ### 1. section creating pidls ###
1157 *************************************************************************
1158 * _ILCreateDesktop()
1159 * _ILCreateIExplore()
1160 * _ILCreateMyComputer()
1161 * _ILCreateDrive()
1162 * _ILCreateFolder()
1163 * _ILCreateValue()
1165 LPITEMIDLIST _ILCreateDesktop()
1166 { TRACE("()\n");
1167 return _ILCreate(PT_DESKTOP, NULL, 0);
1170 LPITEMIDLIST _ILCreateMyComputer()
1171 { TRACE("()\n");
1172 return _ILCreate(PT_MYCOMP, &CLSID_MyComputer, sizeof(GUID));
1175 LPITEMIDLIST _ILCreateIExplore()
1176 { TRACE("()\n");
1177 return _ILCreate(PT_MYCOMP, &CLSID_Internet, sizeof(GUID));
1180 LPITEMIDLIST _ILCreateControl()
1181 { TRACE("()\n");
1182 return _ILCreate(PT_SPECIAL, &CLSID_ControlPanel, sizeof(GUID));
1185 LPITEMIDLIST _ILCreatePrinter()
1186 { TRACE("()\n");
1187 return _ILCreate(PT_SPECIAL, &CLSID_Printers, sizeof(GUID));
1190 LPITEMIDLIST _ILCreateNetwork()
1191 { TRACE("()\n");
1192 return _ILCreate(PT_MYCOMP, &CLSID_NetworkPlaces, sizeof(GUID));
1195 LPITEMIDLIST _ILCreateBitBucket()
1196 { TRACE("()\n");
1197 return _ILCreate(PT_MYCOMP, &CLSID_RecycleBin, sizeof(GUID));
1200 LPITEMIDLIST _ILCreateDrive( LPCSTR lpszNew)
1201 { char sTemp[4];
1202 lstrcpynA (sTemp,lpszNew,4);
1203 sTemp[2]='\\';
1204 sTemp[3]=0x00;
1205 TRACE("(%s)\n",sTemp);
1206 return _ILCreate(PT_DRIVE,(LPVOID)&sTemp[0],4);
1209 LPITEMIDLIST _ILCreateFolder( WIN32_FIND_DATAA * stffile )
1211 char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1212 char * pbuff = buff;
1213 ULONG len, len1;
1214 LPITEMIDLIST pidl;
1216 TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1218 /* prepare buffer with both names */
1219 len = strlen (stffile->cFileName) + 1;
1220 memcpy (pbuff, stffile->cFileName, len);
1221 pbuff += len;
1223 if (stffile->cAlternateFileName)
1225 len1 = strlen (stffile->cAlternateFileName)+1;
1226 memcpy (pbuff, stffile->cAlternateFileName, len1);
1228 else
1230 len1 = 1;
1231 *pbuff = 0x00;
1234 pidl = _ILCreate(PT_FOLDER, (LPVOID)buff, len + len1);
1236 /* set attributes */
1237 if (pidl)
1239 LPPIDLDATA pData;
1240 pData = _ILGetDataPointer(pidl);
1241 FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1242 pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1243 pData->u.folder.uFileAttribs = stffile->dwFileAttributes;
1246 return pidl;
1249 LPITEMIDLIST _ILCreateValue(WIN32_FIND_DATAA * stffile)
1251 char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1252 char * pbuff = buff;
1253 ULONG len, len1;
1254 LPITEMIDLIST pidl;
1256 TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1258 /* prepare buffer with both names */
1259 len = strlen (stffile->cFileName) + 1;
1260 memcpy (pbuff, stffile->cFileName, len);
1261 pbuff += len;
1263 if (stffile->cAlternateFileName)
1265 len1 = strlen (stffile->cAlternateFileName)+1;
1266 memcpy (pbuff, stffile->cAlternateFileName, len1);
1268 else
1270 len1 = 1;
1271 *pbuff = 0x00;
1274 pidl = _ILCreate(PT_VALUE, (LPVOID)buff, len + len1);
1276 /* set attributes */
1277 if (pidl)
1279 LPPIDLDATA pData;
1280 pData = _ILGetDataPointer(pidl);
1281 FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1282 pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1283 pData->u.folder.uFileAttribs=stffile->dwFileAttributes;
1286 return pidl;
1289 LPITEMIDLIST _ILCreateFromPathA(LPCSTR szPath)
1291 HANDLE hFile;
1292 WIN32_FIND_DATAA stffile;
1293 LPITEMIDLIST pidl = NULL;
1295 hFile = FindFirstFileA(szPath, &stffile);
1296 if (hFile != INVALID_HANDLE_VALUE)
1298 if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1299 pidl = _ILCreateFolder(&stffile);
1300 else
1301 pidl = _ILCreateValue(&stffile);
1302 FindClose(hFile);
1304 return pidl;
1307 LPITEMIDLIST _ILCreateSpecial(LPCSTR szGUID)
1309 IID iid;
1311 if (!SUCCEEDED(SHCLSIDFromStringA(szGUID, &iid)))
1313 ERR("%s is not a GUID\n", szGUID);
1314 return NULL;
1316 return _ILCreate(PT_MYCOMP, &iid, sizeof(IID));
1319 /**************************************************************************
1320 * _ILCreate()
1321 * Creates a new PIDL
1322 * type = PT_DESKTOP | PT_DRIVE | PT_FOLDER | PT_VALUE
1323 * pIn = data
1324 * uInSize = size of data (raw)
1327 LPITEMIDLIST _ILCreate(PIDLTYPE type, LPCVOID pIn, UINT uInSize)
1329 LPITEMIDLIST pidlOut = NULL, pidlTemp = NULL;
1330 LPPIDLDATA pData;
1331 UINT uSize = 0;
1332 LPSTR pszDest;
1334 TRACE("(0x%02x %p %i)\n",type,pIn,uInSize);
1336 switch (type)
1338 case PT_DESKTOP:
1339 uSize = 0;
1340 break;
1341 case PT_SPECIAL:
1342 case PT_MYCOMP:
1343 uSize = 2 + 2 + sizeof(GUID);
1344 break;
1345 case PT_DRIVE:
1346 uSize = 2 + 23;
1347 break;
1348 case PT_FOLDER:
1349 case PT_VALUE:
1350 uSize = 2 + 12 + uInSize;
1351 break;
1352 default:
1353 FIXME("can't create type: 0x%08x\n",type);
1354 return NULL;
1357 if(!(pidlOut = SHAlloc(uSize + 2))) return NULL;
1358 ZeroMemory(pidlOut, uSize + 2);
1359 pidlOut->mkid.cb = uSize;
1361 switch (type)
1363 case PT_DESKTOP:
1364 TRACE("- create Desktop\n");
1365 break;
1367 case PT_SPECIAL:
1368 case PT_MYCOMP:
1369 pData = _ILGetDataPointer(pidlOut);
1370 pData->type = type;
1371 memcpy(&(pData->u.mycomp.guid), pIn, uInSize);
1372 TRACE("-- create GUID-pidl %s\n", debugstr_guid(&(pData->u.mycomp.guid)));
1373 break;
1375 case PT_DRIVE:
1376 pData = _ILGetDataPointer(pidlOut);
1377 pData->type = type;
1378 pszDest = _ILGetTextPointer(pidlOut);
1379 memcpy(pszDest, pIn, uInSize);
1380 TRACE("-- create Drive: %s\n",debugstr_a(pszDest));
1381 break;
1383 case PT_FOLDER:
1384 case PT_VALUE:
1385 pData = _ILGetDataPointer(pidlOut);
1386 pData->type = type;
1387 pszDest = _ILGetTextPointer(pidlOut);
1388 memcpy(pszDest, pIn, uInSize);
1389 TRACE("-- create Value: %s\n",debugstr_a(pszDest));
1390 break;
1393 pidlTemp = ILGetNext(pidlOut);
1394 if (pidlTemp)
1395 pidlTemp->mkid.cb = 0x00;
1397 TRACE("-- (pidl=%p, size=%u)\n", pidlOut, uSize);
1398 return pidlOut;
1401 /**************************************************************************
1402 * _ILGetDrive()
1404 * Gets the text for the drive eg. 'c:\'
1406 * RETURNS
1407 * strlen (lpszText)
1409 DWORD _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT uSize)
1410 { TRACE("(%p,%p,%u)\n",pidl,pOut,uSize);
1412 if(_ILIsMyComputer(pidl))
1413 pidl = ILGetNext(pidl);
1415 if (pidl && _ILIsDrive(pidl))
1416 return _ILSimpleGetText(pidl, pOut, uSize);
1418 return 0;
1421 /**************************************************************************
1423 * ### 2. section testing pidls ###
1425 **************************************************************************
1426 * _ILIsDesktop()
1427 * _ILIsMyComputer()
1428 * _ILIsSpecialFolder()
1429 * _ILIsDrive()
1430 * _ILIsFolder()
1431 * _ILIsValue()
1432 * _ILIsPidlSimple()
1434 BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
1435 { TRACE("(%p)\n",pidl);
1436 return pidl && pidl->mkid.cb ? 0 : 1;
1439 BOOL _ILIsMyComputer(LPCITEMIDLIST pidl)
1441 REFIID iid = _ILGetGUIDPointer(pidl);
1443 TRACE("(%p)\n",pidl);
1445 if (iid)
1446 return IsEqualIID(iid, &CLSID_MyComputer);
1447 return FALSE;
1450 BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl)
1452 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1453 TRACE("(%p)\n",pidl);
1454 return (pidl && ( (lpPData && (PT_MYCOMP== lpPData->type || PT_SPECIAL== lpPData->type)) ||
1455 (pidl && pidl->mkid.cb == 0x00)
1459 BOOL _ILIsDrive(LPCITEMIDLIST pidl)
1460 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1461 TRACE("(%p)\n",pidl);
1462 return (pidl && lpPData && (PT_DRIVE == lpPData->type ||
1463 PT_DRIVE1 == lpPData->type ||
1464 PT_DRIVE2 == lpPData->type ||
1465 PT_DRIVE3 == lpPData->type));
1468 BOOL _ILIsFolder(LPCITEMIDLIST pidl)
1469 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1470 TRACE("(%p)\n",pidl);
1471 return (pidl && lpPData && (PT_FOLDER == lpPData->type || PT_FOLDER1 == lpPData->type));
1474 BOOL _ILIsValue(LPCITEMIDLIST pidl)
1475 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1476 TRACE("(%p)\n",pidl);
1477 return (pidl && lpPData && PT_VALUE == lpPData->type);
1480 /**************************************************************************
1481 * _ILIsPidlSimple
1483 BOOL _ILIsPidlSimple ( LPCITEMIDLIST pidl)
1485 BOOL ret = TRUE;
1487 if(! _ILIsDesktop(pidl)) /* pidl=NULL or mkid.cb=0 */
1489 WORD len = pidl->mkid.cb;
1490 LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((LPBYTE)pidl) + len );
1491 if (pidlnext->mkid.cb)
1492 ret = FALSE;
1495 TRACE("%s\n", ret ? "Yes" : "No");
1496 return ret;
1499 /**************************************************************************
1501 * ### 3. section getting values from pidls ###
1504 /**************************************************************************
1505 * _ILSimpleGetText
1507 * gets the text for the first item in the pidl (eg. simple pidl)
1509 * returns the length of the string
1511 DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
1513 DWORD dwReturn=0;
1514 LPSTR szSrc;
1515 GUID const * riid;
1516 char szTemp[MAX_PATH];
1518 TRACE("(%p %p %x)\n",pidl,szOut,uOutSize);
1520 if (!pidl) return 0;
1522 if (szOut)
1523 *szOut = 0;
1525 if (_ILIsDesktop(pidl))
1527 /* desktop */
1528 if (HCR_GetClassNameA(&CLSID_ShellDesktop, szTemp, MAX_PATH))
1530 if (szOut)
1531 lstrcpynA(szOut, szTemp, uOutSize);
1533 dwReturn = strlen (szTemp);
1536 else if (( szSrc = _ILGetTextPointer(pidl) ))
1538 /* filesystem */
1539 if (szOut)
1540 lstrcpynA(szOut, szSrc, uOutSize);
1542 dwReturn = strlen(szSrc);
1544 else if (( riid = _ILGetGUIDPointer(pidl) ))
1546 /* special folder */
1547 if ( HCR_GetClassNameA(riid, szTemp, MAX_PATH) )
1549 if (szOut)
1550 lstrcpynA(szOut, szTemp, uOutSize);
1552 dwReturn = strlen (szTemp);
1555 else
1557 ERR("-- no text\n");
1560 TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_a(szOut),dwReturn);
1561 return dwReturn;
1564 /**************************************************************************
1565 * _ILSimpleGetTextW
1567 * gets the text for the first item in the pidl (eg. simple pidl)
1569 * returns the length of the string
1571 DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR szOut, UINT uOutSize)
1573 DWORD dwReturn;
1574 char szTemp[MAX_PATH];
1576 TRACE("(%p %p %x)\n",pidl,szOut,uOutSize);
1578 dwReturn = _ILSimpleGetText(pidl, szTemp, uOutSize);
1580 if (!MultiByteToWideChar(CP_ACP, 0, szTemp, -1, szOut, MAX_PATH))
1581 *szOut = 0;
1583 TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_w(szOut),dwReturn);
1584 return dwReturn;
1587 /**************************************************************************
1589 * ### 4. getting pointers to parts of pidls ###
1591 **************************************************************************
1592 * _ILGetDataPointer()
1594 LPPIDLDATA _ILGetDataPointer(LPCITEMIDLIST pidl)
1596 if(pidl && pidl->mkid.cb != 0x00)
1597 return (LPPIDLDATA) &(pidl->mkid.abID);
1598 return NULL;
1601 /**************************************************************************
1602 * _ILGetTextPointer()
1603 * gets a pointer to the long filename string stored in the pidl
1605 LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
1606 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1608 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
1610 if (pdata)
1612 switch (pdata->type)
1614 case PT_MYCOMP:
1615 case PT_SPECIAL:
1616 return NULL;
1618 case PT_DRIVE:
1619 case PT_DRIVE1:
1620 case PT_DRIVE2:
1621 case PT_DRIVE3:
1622 return (LPSTR)&(pdata->u.drive.szDriveName);
1624 case PT_FOLDER:
1625 case PT_FOLDER1:
1626 case PT_VALUE:
1627 case PT_IESPECIAL1:
1628 case PT_IESPECIAL2:
1629 return (LPSTR)&(pdata->u.file.szNames);
1631 case PT_WORKGRP:
1632 case PT_COMP:
1633 case PT_NETWORK:
1634 case PT_NETPROVIDER:
1635 case PT_SHARE:
1636 return (LPSTR)&(pdata->u.network.szNames);
1639 return NULL;
1642 /**************************************************************************
1643 * _ILGetSTextPointer()
1644 * gets a pointer to the short filename string stored in the pidl
1646 LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl)
1647 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1649 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1651 if (pdata)
1653 switch (pdata->type)
1655 case PT_FOLDER:
1656 case PT_VALUE:
1657 case PT_IESPECIAL1:
1658 case PT_IESPECIAL2:
1659 return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1);
1661 case PT_WORKGRP:
1662 return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1);
1665 return NULL;
1668 /**************************************************************************
1669 * _ILGetGUIDPointer()
1671 * returns reference to guid stored in some pidls
1673 REFIID _ILGetGUIDPointer(LPCITEMIDLIST pidl)
1675 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1677 TRACE("%p\n", pidl);
1679 if (pdata)
1681 TRACE("pdata->type 0x%04x\n", pdata->type);
1682 switch (pdata->type)
1684 case PT_SPECIAL:
1685 case PT_MYCOMP:
1686 return (REFIID) &(pdata->u.mycomp.guid);
1688 default:
1689 TRACE("Unknown pidl type 0x%04x\n", pdata->type);
1690 break;
1693 return NULL;
1696 /*************************************************************************
1697 * _ILGetFileDateTime
1699 * Given the ItemIdList, get the FileTime
1701 * PARAMS
1702 * pidl [I] The ItemIDList
1703 * pFt [I] the resulted FILETIME of the file
1705 * RETURNS
1706 * True if Successful
1708 * NOTES
1711 BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt)
1713 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
1715 if(! pdata) return FALSE;
1717 switch (pdata->type)
1719 case PT_FOLDER:
1720 DosDateTimeToFileTime(pdata->u.folder.uFileDate, pdata->u.folder.uFileTime, pFt);
1721 break;
1722 case PT_VALUE:
1723 DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt);
1724 break;
1725 default:
1726 return FALSE;
1728 return TRUE;
1731 BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1733 FILETIME ft,lft;
1734 SYSTEMTIME time;
1735 BOOL ret;
1737 if (_ILGetFileDateTime( pidl, &ft )) {
1738 FileTimeToLocalFileTime(&ft, &lft);
1739 FileTimeToSystemTime (&lft, &time);
1740 ret = GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize);
1741 } else {
1742 pOut[0] = '\0';
1743 ret = FALSE;
1745 return ret;
1749 /*************************************************************************
1750 * _ILGetFileSize
1752 * Given the ItemIdList, get the FileSize
1754 * PARAMS
1755 * pidl [I] The ItemIDList
1756 * pOut [I] The buffer to save the result
1757 * uOutsize [I] The size of the buffer
1759 * RETURNS
1760 * The FileSize
1762 * NOTES
1763 * pOut can be null when no string is needed
1766 DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1768 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
1769 DWORD dwSize;
1771 if(! pdata) return 0;
1773 switch (pdata->type)
1775 case PT_VALUE:
1776 dwSize = pdata->u.file.dwFileSize;
1777 if (pOut) StrFormatByteSizeA(dwSize, pOut, uOutSize);
1778 return dwSize;
1780 if (pOut) *pOut = 0x00;
1781 return 0;
1784 BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1786 char szTemp[MAX_PATH];
1787 const char * pPoint;
1788 LPCITEMIDLIST pidlTemp=pidl;
1790 TRACE("pidl=%p\n",pidl);
1792 if (!pidl) return FALSE;
1794 pidlTemp = ILFindLastID(pidl);
1796 if (!_ILIsValue(pidlTemp)) return FALSE;
1797 if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH)) return FALSE;
1799 pPoint = PathFindExtensionA(szTemp);
1801 if (! *pPoint) return FALSE;
1803 pPoint++;
1804 lstrcpynA(pOut, pPoint, uOutSize);
1805 TRACE("%s\n",pOut);
1807 return TRUE;
1810 /*************************************************************************
1811 * _ILGetFileType
1813 * Given the ItemIdList, get the file type description
1815 * PARAMS
1816 * pidl [I] The ItemIDList (simple)
1817 * pOut [I] The buffer to save the result
1818 * uOutsize [I] The size of the buffer
1820 * RETURNS
1821 * nothing
1823 * NOTES
1824 * This function copies as much as possible into the buffer.
1826 void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1828 if(_ILIsValue(pidl))
1830 char sTemp[64];
1831 if(uOutSize > 0)
1833 pOut[0] = 0;
1835 if (_ILGetExtension (pidl, sTemp, 64))
1837 if (!( HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE)
1838 && HCR_MapTypeToValueA(sTemp, pOut, uOutSize, FALSE )))
1840 lstrcpynA (pOut, sTemp, uOutSize - 6);
1841 strcat (pOut, "-file");
1845 else
1847 lstrcpynA(pOut, "Folder", uOutSize);
1851 /*************************************************************************
1852 * _ILGetFileAttributes
1854 * Given the ItemIdList, get the Attrib string format
1856 * PARAMS
1857 * pidl [I] The ItemIDList
1858 * pOut [I] The buffer to save the result
1859 * uOutsize [I] The size of the Buffer
1861 * RETURNS
1862 * Attributes
1864 * FIXME
1865 * return value 0 in case of error is a valid return value
1868 DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1870 LPPIDLDATA pData = _ILGetDataPointer(pidl);
1871 WORD wAttrib = 0;
1872 int i;
1874 if(! pData) return 0;
1876 switch(pData->type)
1878 case PT_FOLDER:
1879 wAttrib = pData->u.folder.uFileAttribs;
1880 break;
1881 case PT_VALUE:
1882 wAttrib = pData->u.file.uFileAttribs;
1883 break;
1886 if(uOutSize >= 6)
1888 i=0;
1889 if(wAttrib & FILE_ATTRIBUTE_READONLY)
1891 pOut[i++] = 'R';
1893 if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
1895 pOut[i++] = 'H';
1897 if(wAttrib & FILE_ATTRIBUTE_SYSTEM)
1899 pOut[i++] = 'S';
1901 if(wAttrib & FILE_ATTRIBUTE_ARCHIVE)
1903 pOut[i++] = 'A';
1905 if(wAttrib & FILE_ATTRIBUTE_COMPRESSED)
1907 pOut[i++] = 'C';
1909 pOut[i] = 0x00;
1911 return wAttrib;
1914 /*************************************************************************
1915 * ILFreeaPidl
1917 * free a aPidl struct
1919 void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl)
1921 UINT i;
1923 if (apidl)
1925 for (i = 0; i < cidl; i++) SHFree(apidl[i]);
1926 SHFree(apidl);
1930 /*************************************************************************
1931 * ILCopyaPidl
1933 * copies an aPidl struct
1935 LPITEMIDLIST* _ILCopyaPidl(LPCITEMIDLIST * apidlsrc, UINT cidl)
1937 UINT i;
1938 LPITEMIDLIST * apidldest = (LPITEMIDLIST*)SHAlloc(cidl * sizeof(LPITEMIDLIST));
1939 if(!apidlsrc) return NULL;
1941 for (i = 0; i < cidl; i++)
1942 apidldest[i] = ILClone(apidlsrc[i]);
1944 return apidldest;
1947 /*************************************************************************
1948 * _ILCopyCidaToaPidl
1950 * creates aPidl from CIDA
1952 LPITEMIDLIST* _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida)
1954 UINT i;
1955 LPITEMIDLIST * dst = (LPITEMIDLIST*)SHAlloc(cida->cidl * sizeof(LPITEMIDLIST));
1957 if(!dst) return NULL;
1959 if (pidl)
1960 *pidl = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[0]]));
1962 for (i = 0; i < cida->cidl; i++)
1963 dst[i] = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[i + 1]]));
1965 return dst;