Moved all the documented shlwapi functions out of undocshell.h into
[wine/hacks.git] / dlls / shell32 / pidl.c
blobe0bed0c1d3b3cab42ecfa979d72eb616125cf624
1 /*
2 * pidl Handling
4 * Copyright 1998 Juergen Schmied
6 * NOTES
7 * a pidl == NULL means desktop and is legal
9 */
11 #include <ctype.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "winbase.h"
15 #include "debugtools.h"
16 #include "shlguid.h"
17 #include "winerror.h"
18 #include "winnls.h"
19 #include "wine/undocshell.h"
20 #include "shell32_main.h"
21 #include "shellapi.h"
22 #include "shlwapi.h"
24 #include "pidl.h"
26 DEFAULT_DEBUG_CHANNEL(pidl);
27 DECLARE_DEBUG_CHANNEL(shell);
29 void pdump (LPCITEMIDLIST pidl)
31 BOOL bIsShellDebug;
33 LPITEMIDLIST pidltemp = pidl;
34 if (!TRACE_ON(pidl))
35 return;
37 /* silence the sub-functions */
38 bIsShellDebug = TRACE_ON(shell);
39 __SET_DEBUGGING(__DBCL_TRACE, __wine_dbch_shell, FALSE);
40 __SET_DEBUGGING(__DBCL_TRACE, __wine_dbch_pidl, FALSE);
42 if (! pidltemp)
44 MESSAGE ("-------- pidl=NULL (Desktop)\n");
46 else
48 MESSAGE ("-------- pidl=%p\n", pidl);
49 if (pidltemp->mkid.cb)
53 DWORD dwAttrib = 0;
54 LPPIDLDATA pData = _ILGetDataPointer(pidltemp);
55 DWORD type = pData->type;
56 LPSTR szLongName = _ILGetTextPointer(pidltemp);
57 LPSTR szShortName = _ILGetSTextPointer(pidltemp);
58 char szName[MAX_PATH];
60 _ILSimpleGetText(pidltemp, szName, MAX_PATH);
61 if( PT_FOLDER == type)
62 dwAttrib = pData->u.folder.uFileAttribs;
63 else if( PT_VALUE == type)
64 dwAttrib = pData->u.file.uFileAttribs;
66 MESSAGE ("-- pidl=%p size=%u type=%lx attr=0x%08lx name=%s (%s,%s)\n",
67 pidltemp, pidltemp->mkid.cb,type,dwAttrib,szName,debugstr_a(szLongName), debugstr_a(szShortName));
69 pidltemp = ILGetNext(pidltemp);
71 } while (pidltemp->mkid.cb);
73 else
75 MESSAGE ("empty pidl (Desktop)\n");
77 pcheck(pidl);
80 __SET_DEBUGGING(__DBCL_TRACE, __wine_dbch_shell, bIsShellDebug);
81 __SET_DEBUGGING(__DBCL_TRACE, __wine_dbch_pidl, TRUE);
84 #define BYTES_PRINTED 32
85 BOOL pcheck (LPCITEMIDLIST pidl)
86 { DWORD type, ret=TRUE;
87 BOOL bIsPidlDebug;
89 LPITEMIDLIST pidltemp = pidl;
91 bIsPidlDebug = TRACE_ON(shell);
92 __SET_DEBUGGING(__DBCL_TRACE, __wine_dbch_pidl, FALSE);
94 if (pidltemp && pidltemp->mkid.cb)
95 { do
96 { type = _ILGetDataPointer(pidltemp)->type;
97 switch (type)
98 { case PT_DESKTOP:
99 case PT_MYCOMP:
100 case PT_SPECIAL:
101 case PT_DRIVE:
102 case PT_DRIVE1:
103 case PT_DRIVE2:
104 case PT_DRIVE3:
105 case PT_FOLDER:
106 case PT_VALUE:
107 case PT_FOLDER1:
108 case PT_WORKGRP:
109 case PT_COMP:
110 case PT_NETWORK:
111 case PT_SHARE:
112 case PT_IESPECIAL:
113 break;
114 default:
116 char szTemp[BYTES_PRINTED*4 + 1];
117 int i;
118 unsigned char c;
120 memset(szTemp, ' ', BYTES_PRINTED*4 + 1);
121 for ( i = 0; (i<pidltemp->mkid.cb) && (i<BYTES_PRINTED); i++)
123 c = ((unsigned char *)pidltemp)[i];
125 szTemp[i*3+0] = ((c>>4)>9)? (c>>4)+55 : (c>>4)+48;
126 szTemp[i*3+1] = ((0x0F&c)>9)? (0x0F&c)+55 : (0x0F&c)+48;
127 szTemp[i*3+2] = ' ';
128 szTemp[i+BYTES_PRINTED*3] = (c>=0x20 && c <=0x80) ? c : '.';
130 szTemp[BYTES_PRINTED*4] = 0x00;
131 ERR("unknown IDLIST type size=%u type=%lx\n%s\n",pidltemp->mkid.cb,type, szTemp);
132 ret = FALSE;
135 pidltemp = ILGetNext(pidltemp);
136 } while (pidltemp->mkid.cb);
138 __SET_DEBUGGING(__DBCL_TRACE, __wine_dbch_pidl, bIsPidlDebug);
139 return ret;
142 /*************************************************************************
143 * ILGetDisplayName [SHELL32.15]
145 BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl,LPSTR path)
147 TRACE_(shell)("pidl=%p %p semi-stub\n",pidl,path);
148 return SHGetPathFromIDListA(pidl, path);
150 /*************************************************************************
151 * ILFindLastID [SHELL32.16]
153 * NOTES
154 * observed: pidl=Desktop return=pidl
156 LPITEMIDLIST WINAPI ILFindLastID(LPITEMIDLIST pidl)
157 { LPITEMIDLIST pidlLast = pidl;
159 TRACE("(pidl=%p)\n",pidl);
161 while (pidl->mkid.cb)
163 pidlLast = pidl;
164 pidl = ILGetNext(pidl);
166 return pidlLast;
168 /*************************************************************************
169 * ILRemoveLastID [SHELL32.17]
171 * NOTES
172 * when pidl=Desktop return=FALSE
174 BOOL WINAPI ILRemoveLastID(LPCITEMIDLIST pidl)
176 TRACE_(shell)("pidl=%p\n",pidl);
178 if (!pidl || !pidl->mkid.cb)
179 return 0;
180 ILFindLastID(pidl)->mkid.cb = 0;
181 return 1;
184 /*************************************************************************
185 * ILClone [SHELL32.18]
187 * NOTES
188 * dupicate an idlist
190 LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl)
191 { DWORD len;
192 LPITEMIDLIST newpidl;
194 if (!pidl)
195 return NULL;
197 len = ILGetSize(pidl);
198 newpidl = (LPITEMIDLIST)SHAlloc(len);
199 if (newpidl)
200 memcpy(newpidl,pidl,len);
202 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
203 pdump(pidl);
205 return newpidl;
207 /*************************************************************************
208 * ILCloneFirst [SHELL32.19]
210 * NOTES
211 * duplicates the first idlist of a complex pidl
213 LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl)
214 { DWORD len;
215 LPITEMIDLIST pidlNew = NULL;
217 TRACE("pidl=%p \n",pidl);
218 pdump(pidl);
220 if (pidl)
222 len = pidl->mkid.cb;
223 pidlNew = (LPITEMIDLIST) SHAlloc (len+2);
224 if (pidlNew)
226 memcpy(pidlNew,pidl,len+2); /* 2 -> mind a desktop pidl */
228 if (len)
229 ILGetNext(pidlNew)->mkid.cb = 0x00;
232 TRACE("-- newpidl=%p\n",pidlNew);
234 return pidlNew;
236 /*************************************************************************
237 * ILLoadFromStream
239 * NOTES
240 * the first two bytes are the len, the pidl is following then
242 HRESULT WINAPI ILLoadFromStream (IStream * pStream, LPITEMIDLIST * ppPidl)
243 { WORD wLen = 0;
244 DWORD dwBytesRead;
245 HRESULT ret = E_FAIL;
248 TRACE_(shell)("%p %p\n", pStream , ppPidl);
250 if (*ppPidl)
251 { SHFree(*ppPidl);
252 *ppPidl = NULL;
255 IStream_AddRef (pStream);
257 if (SUCCEEDED(IStream_Read(pStream, (LPVOID)&wLen, 2, &dwBytesRead)))
258 { *ppPidl = SHAlloc (wLen);
259 if (SUCCEEDED(IStream_Read(pStream, *ppPidl , wLen, &dwBytesRead)))
260 { ret = S_OK;
262 else
263 { SHFree(*ppPidl);
264 *ppPidl = NULL;
268 /* we are not jet fully compatible */
269 if (!pcheck(*ppPidl))
270 { SHFree(*ppPidl);
271 *ppPidl = NULL;
275 IStream_Release (pStream);
277 return ret;
279 /*************************************************************************
280 * SHILCreateFromPath [SHELL32.28]
282 * NOTES
283 * wraper for IShellFolder::ParseDisplayName()
285 HRESULT WINAPI SHILCreateFromPathA (LPCSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
286 { LPSHELLFOLDER sf;
287 WCHAR lpszDisplayName[MAX_PATH];
288 DWORD pchEaten;
289 HRESULT ret = E_FAIL;
291 TRACE_(shell)("%s %p 0x%08lx\n",path,ppidl,attributes?*attributes:0);
293 if (!MultiByteToWideChar( CP_ACP, 0, path, -1, lpszDisplayName, MAX_PATH ))
294 lpszDisplayName[MAX_PATH-1] = 0;
296 if (SUCCEEDED (SHGetDesktopFolder(&sf)))
298 ret = IShellFolder_ParseDisplayName(sf,0, NULL,lpszDisplayName,&pchEaten,ppidl,attributes);
299 IShellFolder_Release(sf);
301 return ret;
303 HRESULT WINAPI SHILCreateFromPathW (LPCWSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
304 { LPSHELLFOLDER sf;
305 DWORD pchEaten;
306 HRESULT ret = E_FAIL;
308 TRACE_(shell)("%s %p 0x%08lx\n",debugstr_w(path),ppidl,attributes?*attributes:0);
310 if (SUCCEEDED (SHGetDesktopFolder(&sf)))
312 ret = IShellFolder_ParseDisplayName(sf,0, NULL, (LPWSTR) path, &pchEaten, ppidl, attributes);
313 IShellFolder_Release(sf);
315 return ret;
317 HRESULT WINAPI SHILCreateFromPathAW (LPCVOID path, LPITEMIDLIST * ppidl, DWORD * attributes)
319 if ( SHELL_OsIsUnicode())
320 return SHILCreateFromPathW (path, ppidl, attributes);
321 return SHILCreateFromPathA (path, ppidl, attributes);
324 /*************************************************************************
325 * SHCloneSpecialIDList [SHELL32.89]
327 * PARAMETERS
328 * hwndOwner [in]
329 * nFolder [in] CSIDL_xxxxx ??
331 * RETURNS
332 * pidl ??
333 * NOTES
334 * exported by ordinal
336 LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner,DWORD nFolder,DWORD x3)
337 { LPITEMIDLIST ppidl;
338 WARN_(shell)("(hwnd=0x%x,csidl=0x%lx,0x%lx):semi-stub.\n",
339 hwndOwner,nFolder,x3);
341 SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl);
343 return ppidl;
346 /*************************************************************************
347 * ILGlobalClone [SHELL32.97]
350 LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl)
351 { DWORD len;
352 LPITEMIDLIST newpidl;
354 if (!pidl)
355 return NULL;
357 len = ILGetSize(pidl);
358 newpidl = (LPITEMIDLIST)pCOMCTL32_Alloc(len);
359 if (newpidl)
360 memcpy(newpidl,pidl,len);
362 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
363 pdump(pidl);
365 return newpidl;
368 /*************************************************************************
369 * ILIsEqual [SHELL32.21]
372 BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
374 char szData1[MAX_PATH];
375 char szData2[MAX_PATH];
377 LPITEMIDLIST pidltemp1 = pidl1;
378 LPITEMIDLIST pidltemp2 = pidl2;
380 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
382 /* explorer reads from registry directly (StreamMRU),
383 so we can only check here */
384 if ((!pcheck (pidl1)) || (!pcheck (pidl2))) return FALSE;
386 pdump (pidl1);
387 pdump (pidl2);
389 if ( (!pidl1) || (!pidl2) ) return FALSE;
391 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
393 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
394 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
396 if (strcasecmp ( szData1, szData2 )!=0 )
397 return FALSE;
399 pidltemp1 = ILGetNext(pidltemp1);
400 pidltemp2 = ILGetNext(pidltemp2);
403 if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb)
405 return TRUE;
408 return FALSE;
410 /*************************************************************************
411 * ILIsParent [SHELL32.23]
413 * parent=a/b child=a/b/c -> true, c is in folder a/b
414 * child=a/b/c/d -> false if bImmediate is true, d is not in folder a/b
415 * child=a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b
417 BOOL WINAPI ILIsParent( LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate)
419 char szData1[MAX_PATH];
420 char szData2[MAX_PATH];
422 LPITEMIDLIST pParent = pidlParent;
423 LPITEMIDLIST pChild = pidlChild;
425 TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate);
427 while (pParent->mkid.cb && pChild->mkid.cb)
429 _ILSimpleGetText(pParent, szData1, MAX_PATH);
430 _ILSimpleGetText(pChild, szData2, MAX_PATH);
432 if (strcasecmp ( szData1, szData2 )!=0 )
433 return FALSE;
435 pParent = ILGetNext(pParent);
436 pChild = ILGetNext(pChild);
439 if ( pParent->mkid.cb || ! pChild->mkid.cb) /* child shorter or has equal length to parent */
440 return FALSE;
442 if ( ILGetNext(pChild)->mkid.cb && bImmediate) /* not immediate descent */
443 return FALSE;
445 return TRUE;
448 /*************************************************************************
449 * ILFindChild [SHELL32.24]
451 * NOTES
452 * Compares elements from pidl1 and pidl2.
454 * pidl1 is desktop pidl2
455 * pidl1 shorter pidl2 pointer to first different element of pidl2
456 * if there was at least one equal element
457 * pidl2 shorter pidl1 0
458 * pidl2 equal pidl1 pointer to last 0x00-element of pidl2
460 LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
462 char szData1[MAX_PATH];
463 char szData2[MAX_PATH];
465 LPITEMIDLIST pidltemp1 = pidl1;
466 LPITEMIDLIST pidltemp2 = pidl2;
467 LPITEMIDLIST ret=NULL;
469 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
471 /* explorer reads from registry directly (StreamMRU),
472 so we can only check here */
473 if ((!pcheck (pidl1)) || (!pcheck (pidl2)))
474 return FALSE;
476 pdump (pidl1);
477 pdump (pidl2);
479 if ( _ILIsDesktop(pidl1) )
481 ret = pidl2;
483 else
485 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
487 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
488 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
490 if (strcasecmp(szData1,szData2))
491 break;
493 pidltemp1 = ILGetNext(pidltemp1);
494 pidltemp2 = ILGetNext(pidltemp2);
495 ret = pidltemp2;
498 if (pidltemp1->mkid.cb)
500 ret = NULL; /* elements of pidl1 left*/
503 TRACE_(shell)("--- %p\n", ret);
504 return ret; /* pidl 1 is shorter */
507 /*************************************************************************
508 * ILCombine [SHELL32.25]
510 * NOTES
511 * Concatenates two complex idlists.
512 * The pidl is the first one, pidlsub the next one
513 * Does not destroy the passed in idlists!
515 LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
517 DWORD len1,len2;
518 LPITEMIDLIST pidlNew;
520 TRACE("pidl=%p pidl=%p\n",pidl1,pidl2);
522 if(!pidl1 && !pidl2) return NULL;
524 pdump (pidl1);
525 pdump (pidl2);
527 if(!pidl1)
529 pidlNew = ILClone(pidl2);
530 return pidlNew;
533 if(!pidl2)
535 pidlNew = ILClone(pidl1);
536 return pidlNew;
539 len1 = ILGetSize(pidl1)-2;
540 len2 = ILGetSize(pidl2);
541 pidlNew = SHAlloc(len1+len2);
543 if (pidlNew)
545 memcpy(pidlNew,pidl1,len1);
546 memcpy(((BYTE *)pidlNew)+len1,pidl2,len2);
549 /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
550 return pidlNew;
552 /*************************************************************************
553 * SHGetRealIDL [SHELL32.98]
555 * NOTES
557 LPITEMIDLIST WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl, DWORD z)
559 FIXME("sf=%p pidl=%p 0x%04lx\n",lpsf,pidl,z);
561 pdump (pidl);
562 return 0;
565 /*************************************************************************
566 * SHLogILFromFSIL [SHELL32.95]
568 * NOTES
569 * pild = CSIDL_DESKTOP ret = 0
570 * pild = CSIDL_DRIVES ret = 0
572 LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
574 FIXME("(pidl=%p)\n",pidl);
576 pdump(pidl);
578 return 0;
581 /*************************************************************************
582 * ILGetSize [SHELL32.152]
583 * gets the byte size of an idlist including zero terminator (pidl)
585 * PARAMETERS
586 * pidl ITEMIDLIST
588 * RETURNS
589 * size of pidl
591 * NOTES
592 * exported by ordinal
594 DWORD WINAPI ILGetSize(LPITEMIDLIST pidl)
596 LPSHITEMID si = &(pidl->mkid);
597 DWORD len=0;
599 if (pidl)
600 { while (si->cb)
601 { len += si->cb;
602 si = (LPSHITEMID)(((LPBYTE)si)+si->cb);
604 len += 2;
606 TRACE("pidl=%p size=%lu\n",pidl, len);
607 return len;
610 /*************************************************************************
611 * ILGetNext [SHELL32.153]
612 * gets the next simple pidl of a complex pidl
614 * observed return values:
615 * null -> null
616 * desktop -> null
617 * simple pidl -> pointer to 0x0000 element
620 LPITEMIDLIST WINAPI ILGetNext(LPITEMIDLIST pidl)
622 WORD len;
624 TRACE("(pidl=%p)\n",pidl);
626 if(pidl)
628 len = pidl->mkid.cb;
629 if (len)
631 pidl = (LPITEMIDLIST) (((LPBYTE)pidl)+len);
632 return pidl;
635 return NULL;
637 /*************************************************************************
638 * ILAppend [SHELL32.154]
640 * NOTES
641 * Adds the single item to the idlist indicated by pidl.
642 * if bEnd is 0, adds the item to the front of the list,
643 * otherwise adds the item to the end. (???)
644 * Destroys the passed in idlist! (???)
646 LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl,LPCITEMIDLIST item,BOOL bEnd)
648 LPITEMIDLIST idlRet;
650 WARN("(pidl=%p,pidl=%p,%08u)semi-stub\n",pidl,item,bEnd);
652 pdump (pidl);
653 pdump (item);
655 if (_ILIsDesktop(pidl))
657 idlRet = ILClone(item);
658 if (pidl)
659 SHFree (pidl);
660 return idlRet;
663 if (bEnd)
665 idlRet=ILCombine(pidl,item);
667 else
669 idlRet=ILCombine(item,pidl);
672 SHFree(pidl);
673 return idlRet;
675 /*************************************************************************
676 * ILFree [SHELL32.155]
678 * NOTES
679 * free_check_ptr - frees memory (if not NULL)
680 * allocated by SHMalloc allocator
681 * exported by ordinal
683 DWORD WINAPI ILFree(LPITEMIDLIST pidl)
685 TRACE("(pidl=0x%08lx)\n",(DWORD)pidl);
687 if(!pidl) return FALSE;
688 SHFree(pidl);
689 return TRUE;
691 /*************************************************************************
692 * ILGlobalFree [SHELL32.156]
695 void WINAPI ILGlobalFree( LPCITEMIDLIST pidl)
697 TRACE("%p\n",pidl);
699 if(!pidl) return;
700 pCOMCTL32_Free(pidl);
702 /*************************************************************************
703 * ILCreateFromPath [SHELL32.157]
706 LPITEMIDLIST WINAPI ILCreateFromPathA (LPCSTR path)
708 LPITEMIDLIST pidlnew;
709 DWORD attributes = 0;
711 TRACE_(shell)("%s\n",path);
713 if (SUCCEEDED (SHILCreateFromPathA (path, &pidlnew, &attributes)))
714 return pidlnew;
715 return FALSE;
717 LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path)
719 LPITEMIDLIST pidlnew;
720 DWORD attributes = 0;
722 TRACE_(shell)("%s\n",debugstr_w(path));
724 if (SUCCEEDED (SHILCreateFromPathW (path, &pidlnew, &attributes)))
725 return pidlnew;
726 return FALSE;
728 LPITEMIDLIST WINAPI ILCreateFromPathAW (LPCVOID path)
730 if ( SHELL_OsIsUnicode())
731 return ILCreateFromPathW (path);
732 return ILCreateFromPathA (path);
734 /*************************************************************************
735 * SHSimpleIDListFromPath [SHELL32.162]
737 LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPCSTR lpszPath)
739 LPITEMIDLIST pidl=NULL;
740 HANDLE hFile;
741 WIN32_FIND_DATAA stffile;
743 TRACE("path=%s\n", lpszPath);
745 if (!lpszPath) return NULL;
747 hFile = FindFirstFileA(lpszPath, &stffile);
749 if ( hFile != INVALID_HANDLE_VALUE )
751 if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
753 pidl = _ILCreateFolder (&stffile);
755 else
757 pidl = _ILCreateValue (&stffile);
759 FindClose (hFile);
761 return pidl;
763 LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPCWSTR lpszPath)
765 char lpszTemp[MAX_PATH];
766 TRACE("path=%s\n",debugstr_w(lpszPath));
768 if (!WideCharToMultiByte( CP_ACP, 0, lpszPath, -1, lpszTemp, sizeof(lpszTemp), NULL, NULL ))
769 lpszTemp[sizeof(lpszTemp)-1] = 0;
771 return SHSimpleIDListFromPathA (lpszTemp);
774 LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW (LPCVOID lpszPath)
776 if ( SHELL_OsIsUnicode())
777 return SHSimpleIDListFromPathW (lpszPath);
778 return SHSimpleIDListFromPathA (lpszPath);
781 /*************************************************************************
782 * SHGetSpecialFolderLocation [SHELL32.223]
784 * gets the folder locations from the registry and creates a pidl
785 * creates missing reg keys and directorys
787 * PARAMS
788 * hwndOwner [I]
789 * nFolder [I] CSIDL_xxxxx
790 * ppidl [O] PIDL of a special folder
793 HRESULT WINAPI SHGetSpecialFolderLocation(
794 HWND hwndOwner,
795 INT nFolder,
796 LPITEMIDLIST * ppidl)
798 CHAR szPath[MAX_PATH];
799 HRESULT hr = E_INVALIDARG;
801 TRACE_(shell)("(%04x,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
803 if (ppidl)
805 *ppidl = NULL;
806 switch (nFolder)
808 case CSIDL_DESKTOP:
809 *ppidl = _ILCreateDesktop();
810 break;
812 case CSIDL_DRIVES:
813 *ppidl = _ILCreateMyComputer();
814 break;
816 case CSIDL_NETWORK:
817 *ppidl = _ILCreateNetwork ();
818 break;
820 case CSIDL_CONTROLS:
821 *ppidl = _ILCreateControl ();
822 break;
824 case CSIDL_PRINTERS:
825 *ppidl = _ILCreatePrinter ();
826 break;
828 case CSIDL_BITBUCKET:
829 *ppidl = _ILCreateBitBucket ();
830 break;
832 default:
833 if (SHGetSpecialFolderPathA(hwndOwner, szPath, nFolder, TRUE))
835 DWORD attributes=0;
836 TRACE_(shell)("Value=%s\n",szPath);
837 hr = SHILCreateFromPathA(szPath, ppidl, &attributes);
840 if(*ppidl) hr = NOERROR;
843 TRACE_(shell)("-- (new pidl %p)\n",*ppidl);
844 return hr;
847 /*************************************************************************
848 * SHGetFolderLocation [SHELL32]
850 * NOTES
851 * the pidl can be a simple one. since we cant get the path out of the pidl
852 * we have to take all data from the pidl
854 HRESULT WINAPI SHGetFolderLocation(
855 HWND hwnd,
856 int csidl,
857 HANDLE hToken,
858 DWORD dwFlags,
859 LPITEMIDLIST *ppidl)
861 FIXME("0x%04x 0x%08x 0x%08x 0x%08lx %p\n",
862 hwnd, csidl, hToken, dwFlags, ppidl);
863 return SHGetSpecialFolderLocation(hwnd, csidl, ppidl);
866 /*************************************************************************
867 * SHGetDataFromIDListA [SHELL32.247]
869 * NOTES
870 * the pidl can be a simple one. since we cant get the path out of the pidl
871 * we have to take all data from the pidl
873 HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
875 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
877 pdump(pidl);
878 if (!psf || !dest ) return E_INVALIDARG;
880 switch (nFormat)
882 case SHGDFIL_FINDDATA:
884 WIN32_FIND_DATAA * pfd = dest;
886 if ( len < sizeof (WIN32_FIND_DATAA)) return E_INVALIDARG;
888 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
889 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
890 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
891 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
892 lstrcpynA(pfd->cFileName,_ILGetTextPointer(pidl), MAX_PATH);
893 lstrcpynA(pfd->cAlternateFileName,_ILGetSTextPointer(pidl), 14);
895 return NOERROR;
897 case SHGDFIL_NETRESOURCE:
898 case SHGDFIL_DESCRIPTIONID:
899 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
900 break;
902 default:
903 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
906 return E_INVALIDARG;
908 /*************************************************************************
909 * SHGetDataFromIDListW [SHELL32.247]
912 HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
914 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
916 pdump(pidl);
918 if (! psf || !dest ) return E_INVALIDARG;
920 switch (nFormat)
922 case SHGDFIL_FINDDATA:
924 WIN32_FIND_DATAW * pfd = dest;
926 if ( len < sizeof (WIN32_FIND_DATAW)) return E_INVALIDARG;
928 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
929 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
930 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
931 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
932 if (!MultiByteToWideChar( CP_ACP, 0, _ILGetTextPointer(pidl), -1,
933 pfd->cFileName, MAX_PATH ))
934 pfd->cFileName[MAX_PATH-1] = 0;
935 if (!MultiByteToWideChar( CP_ACP, 0, _ILGetSTextPointer(pidl), -1,
936 pfd->cAlternateFileName, 14 ))
937 pfd->cFileName[13] = 0;
939 return NOERROR;
940 case SHGDFIL_NETRESOURCE:
941 case SHGDFIL_DESCRIPTIONID:
942 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
943 break;
945 default:
946 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
949 return E_INVALIDARG;
952 /*************************************************************************
953 * SHGetPathFromIDListA [SHELL32.261][NT 4.0: SHELL32.220]
955 * PARAMETERS
956 * pidl, [IN] pidl
957 * pszPath [OUT] path
959 * RETURNS
960 * path from a passed PIDL.
962 * NOTES
963 * NULL returns FALSE
964 * desktop pidl gives path to desktopdirectory back
965 * special pidls returning FALSE
967 * FIXME
968 * fnGetDisplayNameOf can return different types of OLEString
970 BOOL WINAPI SHGetPathFromIDListA (LPCITEMIDLIST pidl,LPSTR pszPath)
971 { STRRET str;
972 LPSHELLFOLDER shellfolder;
974 TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
976 if (!pidl) return FALSE;
978 pdump(pidl);
980 if(_ILIsDesktop(pidl))
982 SHGetSpecialFolderPathA(0, pszPath, CSIDL_DESKTOPDIRECTORY, FALSE);
984 else if (_ILIsSpecialFolder(ILFindLastID(pidl)))
986 /* we are somewhere in a special folder */
987 return FALSE;
989 else
991 if (SHGetDesktopFolder(&shellfolder)==S_OK)
993 IShellFolder_GetDisplayNameOf(shellfolder,pidl,SHGDN_FORPARSING,&str);
994 StrRetToStrNA (pszPath, MAX_PATH, &str, pidl);
995 IShellFolder_Release(shellfolder);
998 TRACE_(shell)("-- (%s)\n",pszPath);
1000 return TRUE;
1002 /*************************************************************************
1003 * SHGetPathFromIDListW [SHELL32.262]
1005 BOOL WINAPI SHGetPathFromIDListW (LPCITEMIDLIST pidl,LPWSTR pszPath)
1006 { char sTemp[MAX_PATH];
1008 TRACE_(shell)("(pidl=%p)\n", pidl);
1010 SHGetPathFromIDListA (pidl, sTemp);
1011 MultiByteToWideChar( CP_ACP, 0, sTemp, -1, pszPath, MAX_PATH );
1013 TRACE_(shell)("-- (%s)\n",debugstr_w(pszPath));
1015 return TRUE;
1018 /*************************************************************************
1019 * SHBindToParent [shell version 5.0]
1021 HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
1023 IShellFolder * psf;
1024 LPITEMIDLIST pidlChild, pidlParent;
1025 HRESULT hr=E_FAIL;
1027 TRACE_(shell)("pidl=%p\n", pidl);
1028 pdump(pidl);
1030 *ppv = NULL;
1031 if (ppidlLast) *ppidlLast = NULL;
1033 if (_ILIsPidlSimple(pidl))
1035 /* we are on desktop level */
1036 if (ppidlLast)
1037 *ppidlLast = ILClone(pidl);
1038 hr = SHGetDesktopFolder((IShellFolder**)ppv);
1040 else
1042 pidlChild = ILClone(ILFindLastID(pidl));
1043 pidlParent = ILClone(pidl);
1044 ILRemoveLastID(pidlParent);
1046 hr = SHGetDesktopFolder(&psf);
1048 if (SUCCEEDED(hr))
1049 hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv);
1051 if (SUCCEEDED(hr) && ppidlLast)
1052 *ppidlLast = pidlChild;
1053 else
1054 ILFree (pidlChild);
1056 SHFree (pidlParent);
1057 if (psf) IShellFolder_Release(psf);
1061 TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr);
1062 return hr;
1065 /*************************************************************************
1066 * SHGetPathFromIDListAW [SHELL32.221][NT 4.0: SHELL32.219]
1068 BOOL WINAPI SHGetPathFromIDListAW(LPCITEMIDLIST pidl,LPVOID pszPath)
1070 TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
1072 if (SHELL_OsIsUnicode())
1073 return SHGetPathFromIDListW(pidl,pszPath);
1074 return SHGetPathFromIDListA(pidl,pszPath);
1077 /**************************************************************************
1079 * internal functions
1081 * ### 1. section creating pidls ###
1083 *************************************************************************
1084 * _ILCreateDesktop()
1085 * _ILCreateIExplore()
1086 * _ILCreateMyComputer()
1087 * _ILCreateDrive()
1088 * _ILCreateFolder()
1089 * _ILCreateValue()
1091 LPITEMIDLIST _ILCreateDesktop()
1092 { TRACE("()\n");
1093 return _ILCreate(PT_DESKTOP, NULL, 0);
1096 LPITEMIDLIST _ILCreateMyComputer()
1097 { TRACE("()\n");
1098 return _ILCreate(PT_MYCOMP, &CLSID_MyComputer, sizeof(GUID));
1101 LPITEMIDLIST _ILCreateIExplore()
1102 { TRACE("()\n");
1103 return _ILCreate(PT_MYCOMP, &CLSID_Internet, sizeof(GUID));
1106 LPITEMIDLIST _ILCreateControl()
1107 { TRACE("()\n");
1108 return _ILCreate(PT_SPECIAL, &CLSID_ControlPanel, sizeof(GUID));
1111 LPITEMIDLIST _ILCreatePrinter()
1112 { TRACE("()\n");
1113 return _ILCreate(PT_SPECIAL, &CLSID_Printers, sizeof(GUID));
1116 LPITEMIDLIST _ILCreateNetwork()
1117 { TRACE("()\n");
1118 return _ILCreate(PT_MYCOMP, &CLSID_NetworkPlaces, sizeof(GUID));
1121 LPITEMIDLIST _ILCreateBitBucket()
1122 { TRACE("()\n");
1123 return _ILCreate(PT_MYCOMP, &CLSID_RecycleBin, sizeof(GUID));
1126 LPITEMIDLIST _ILCreateDrive( LPCSTR lpszNew)
1127 { char sTemp[4];
1128 lstrcpynA (sTemp,lpszNew,4);
1129 sTemp[2]='\\';
1130 sTemp[3]=0x00;
1131 TRACE("(%s)\n",sTemp);
1132 return _ILCreate(PT_DRIVE,(LPVOID)&sTemp[0],4);
1135 LPITEMIDLIST _ILCreateFolder( WIN32_FIND_DATAA * stffile )
1137 char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1138 char * pbuff = buff;
1139 ULONG len, len1;
1140 LPITEMIDLIST pidl;
1142 TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1144 /* prepare buffer with both names */
1145 len = strlen (stffile->cFileName) + 1;
1146 memcpy (pbuff, stffile->cFileName, len);
1147 pbuff += len;
1149 if (stffile->cAlternateFileName)
1151 len1 = strlen (stffile->cAlternateFileName)+1;
1152 memcpy (pbuff, stffile->cAlternateFileName, len1);
1154 else
1156 len1 = 1;
1157 *pbuff = 0x00;
1160 pidl = _ILCreate(PT_FOLDER, (LPVOID)buff, len + len1);
1162 /* set attributes */
1163 if (pidl)
1165 LPPIDLDATA pData;
1166 pData = _ILGetDataPointer(pidl);
1167 FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1168 pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1169 pData->u.folder.uFileAttribs=stffile->dwFileAttributes;
1172 return pidl;
1175 LPITEMIDLIST _ILCreateValue(WIN32_FIND_DATAA * stffile)
1177 char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1178 char * pbuff = buff;
1179 ULONG len, len1;
1180 LPITEMIDLIST pidl;
1182 TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1184 /* prepare buffer with both names */
1185 len = strlen (stffile->cFileName) + 1;
1186 memcpy (pbuff, stffile->cFileName, len);
1187 pbuff += len;
1189 if (stffile->cAlternateFileName)
1191 len1 = strlen (stffile->cAlternateFileName)+1;
1192 memcpy (pbuff, stffile->cAlternateFileName, len1);
1194 else
1196 len1 = 1;
1197 *pbuff = 0x00;
1200 pidl = _ILCreate(PT_VALUE, (LPVOID)buff, len + len1);
1202 /* set attributes */
1203 if (pidl)
1205 LPPIDLDATA pData;
1206 pData = _ILGetDataPointer(pidl);
1207 FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1208 pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1209 pData->u.folder.uFileAttribs=stffile->dwFileAttributes;
1212 return pidl;
1215 LPITEMIDLIST _ILCreateSpecial(LPCSTR szGUID)
1217 IID iid;
1218 WCHAR buffer[40];
1220 if (!MultiByteToWideChar( CP_ACP, 0, szGUID, -1, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1221 return NULL;
1222 CLSIDFromString( buffer, &iid );
1223 return _ILCreate(PT_MYCOMP, &iid, sizeof(IID));
1226 /**************************************************************************
1227 * _ILCreate()
1228 * Creates a new PIDL
1229 * type = PT_DESKTOP | PT_DRIVE | PT_FOLDER | PT_VALUE
1230 * pIn = data
1231 * uInSize = size of data (raw)
1234 LPITEMIDLIST _ILCreate(PIDLTYPE type, LPCVOID pIn, UINT uInSize)
1236 LPITEMIDLIST pidlOut = NULL, pidlTemp = NULL;
1237 LPPIDLDATA pData;
1238 UINT uSize = 0;
1239 LPSTR pszDest;
1241 TRACE("(0x%02x %p %i)\n",type,pIn,uInSize);
1243 switch (type)
1245 case PT_DESKTOP:
1246 uSize = 0;
1247 break;
1248 case PT_SPECIAL:
1249 case PT_MYCOMP:
1250 uSize = 2 + 2 + sizeof(GUID);
1251 break;
1252 case PT_DRIVE:
1253 uSize = 2 + 23;
1254 break;
1255 case PT_FOLDER:
1256 case PT_VALUE:
1257 uSize = 2 + 12 + uInSize;
1258 break;
1259 default:
1260 FIXME("can't create type: 0x%08x\n",type);
1261 return NULL;
1264 if(!(pidlOut = SHAlloc(uSize + 2))) return NULL;
1265 ZeroMemory(pidlOut, uSize + 2);
1266 pidlOut->mkid.cb = uSize;
1268 switch (type)
1270 case PT_DESKTOP:
1271 TRACE("- create Desktop\n");
1272 break;
1274 case PT_SPECIAL:
1275 case PT_MYCOMP:
1276 pData =_ILGetDataPointer(pidlOut);
1277 pData->type = type;
1278 memcpy(&(pData->u.mycomp.guid), pIn, uInSize);
1279 TRACE("- create GUID-pidl\n");
1280 break;
1282 case PT_DRIVE:
1283 pData =_ILGetDataPointer(pidlOut);
1284 pData->type = type;
1285 pszDest = _ILGetTextPointer(pidlOut);
1286 memcpy(pszDest, pIn, uInSize);
1287 TRACE("- create Drive: %s\n",debugstr_a(pszDest));
1288 break;
1290 case PT_FOLDER:
1291 case PT_VALUE:
1292 pData =_ILGetDataPointer(pidlOut);
1293 pData->type = type;
1294 pszDest = _ILGetTextPointer(pidlOut);
1295 memcpy(pszDest, pIn, uInSize);
1296 TRACE("- create Value: %s\n",debugstr_a(pszDest));
1297 break;
1300 pidlTemp = ILGetNext(pidlOut);
1301 if (pidlTemp)
1302 pidlTemp->mkid.cb = 0x00;
1304 TRACE("-- (pidl=%p, size=%u)\n", pidlOut, uSize);
1305 return pidlOut;
1308 /**************************************************************************
1309 * _ILGetDrive()
1311 * Gets the text for the drive eg. 'c:\'
1313 * RETURNS
1314 * strlen (lpszText)
1316 DWORD _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT uSize)
1317 { TRACE("(%p,%p,%u)\n",pidl,pOut,uSize);
1319 if(_ILIsMyComputer(pidl))
1320 pidl = ILGetNext(pidl);
1322 if (pidl && _ILIsDrive(pidl))
1323 return _ILSimpleGetText(pidl, pOut, uSize);
1325 return 0;
1328 /**************************************************************************
1330 * ### 2. section testing pidls ###
1332 **************************************************************************
1333 * _ILIsDesktop()
1334 * _ILIsMyComputer()
1335 * _ILIsSpecialFolder()
1336 * _ILIsDrive()
1337 * _ILIsFolder()
1338 * _ILIsValue()
1339 * _ILIsPidlSimple()
1341 BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
1342 { TRACE("(%p)\n",pidl);
1343 return ( !pidl || (pidl && pidl->mkid.cb == 0x00) );
1346 BOOL _ILIsMyComputer(LPCITEMIDLIST pidl)
1348 REFIID iid = _ILGetGUIDPointer(pidl);
1350 TRACE("(%p)\n",pidl);
1352 if (iid)
1353 return IsEqualIID(iid, &CLSID_MyComputer);
1354 return FALSE;
1357 BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl)
1359 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1360 TRACE("(%p)\n",pidl);
1361 return (pidl && ( (lpPData && (PT_MYCOMP== lpPData->type || PT_SPECIAL== lpPData->type)) ||
1362 (pidl && pidl->mkid.cb == 0x00)
1366 BOOL _ILIsDrive(LPCITEMIDLIST pidl)
1367 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1368 TRACE("(%p)\n",pidl);
1369 return (pidl && lpPData && (PT_DRIVE == lpPData->type ||
1370 PT_DRIVE1 == lpPData->type ||
1371 PT_DRIVE2 == lpPData->type ||
1372 PT_DRIVE3 == lpPData->type));
1375 BOOL _ILIsFolder(LPCITEMIDLIST pidl)
1376 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1377 TRACE("(%p)\n",pidl);
1378 return (pidl && lpPData && (PT_FOLDER == lpPData->type || PT_FOLDER1 == lpPData->type));
1381 BOOL _ILIsValue(LPCITEMIDLIST pidl)
1382 { LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1383 TRACE("(%p)\n",pidl);
1384 return (pidl && lpPData && PT_VALUE == lpPData->type);
1387 /**************************************************************************
1388 * _ILIsPidlSimple
1390 BOOL _ILIsPidlSimple ( LPCITEMIDLIST pidl)
1392 BOOL ret = TRUE;
1394 if(! _ILIsDesktop(pidl)) /* pidl=NULL or mkid.cb=0 */
1396 WORD len = pidl->mkid.cb;
1397 LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((LPBYTE)pidl) + len );
1398 if (pidlnext->mkid.cb)
1399 ret = FALSE;
1402 TRACE("%s\n", ret ? "Yes" : "No");
1403 return ret;
1406 /**************************************************************************
1408 * ### 3. section getting values from pidls ###
1411 /**************************************************************************
1412 * _ILSimpleGetText
1414 * gets the text for the first item in the pidl (eg. simple pidl)
1416 * returns the length of the string
1418 DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
1420 DWORD dwReturn=0;
1421 LPSTR szSrc;
1422 GUID const * riid;
1423 char szTemp[MAX_PATH];
1425 TRACE("(%p %p %x)\n",pidl,szOut,uOutSize);
1427 if (!pidl) return 0;
1429 if (szOut)
1430 *szOut = 0;
1432 if (_ILIsDesktop(pidl))
1434 /* desktop */
1435 if (HCR_GetClassName(&CLSID_ShellDesktop, szTemp, MAX_PATH))
1437 if (szOut)
1438 lstrcpynA(szOut, szTemp, uOutSize);
1440 dwReturn = strlen (szTemp);
1443 else if (( szSrc = _ILGetTextPointer(pidl) ))
1445 /* filesystem */
1446 if (szOut)
1447 lstrcpynA(szOut, szSrc, uOutSize);
1449 dwReturn = strlen(szSrc);
1451 else if (( riid = _ILGetGUIDPointer(pidl) ))
1453 /* special folder */
1454 if ( HCR_GetClassName(riid, szTemp, MAX_PATH) )
1456 if (szOut)
1457 lstrcpynA(szOut, szTemp, uOutSize);
1459 dwReturn = strlen (szTemp);
1462 else
1464 ERR("-- no text\n");
1467 TRACE("-- (%p=%s 0x%08lx)\n",szOut,(char*)szOut,dwReturn);
1468 return dwReturn;
1471 /**************************************************************************
1473 * ### 4. getting pointers to parts of pidls ###
1475 **************************************************************************
1476 * _ILGetDataPointer()
1478 LPPIDLDATA _ILGetDataPointer(LPITEMIDLIST pidl)
1480 if(pidl && pidl->mkid.cb != 0x00)
1481 return (LPPIDLDATA) &(pidl->mkid.abID);
1482 return NULL;
1485 /**************************************************************************
1486 * _ILGetTextPointer()
1487 * gets a pointer to the long filename string stored in the pidl
1489 LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
1490 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1492 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1494 if (pdata)
1496 switch (pdata->type)
1498 case PT_MYCOMP:
1499 case PT_SPECIAL:
1500 return NULL;
1502 case PT_DRIVE:
1503 case PT_DRIVE1:
1504 case PT_DRIVE2:
1505 case PT_DRIVE3:
1506 return (LPSTR)&(pdata->u.drive.szDriveName);
1508 case PT_FOLDER:
1509 case PT_FOLDER1:
1510 case PT_VALUE:
1511 case PT_IESPECIAL:
1512 return (LPSTR)&(pdata->u.file.szNames);
1514 case PT_WORKGRP:
1515 case PT_COMP:
1516 case PT_NETWORK:
1517 case PT_SHARE:
1518 return (LPSTR)&(pdata->u.network.szNames);
1521 return NULL;
1524 /**************************************************************************
1525 * _ILGetSTextPointer()
1526 * gets a pointer to the short filename string stored in the pidl
1528 LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl)
1529 {/* TRACE(pidl,"(pidl%p)\n", pidl);*/
1531 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1533 if (pdata)
1535 switch (pdata->type)
1537 case PT_FOLDER:
1538 case PT_VALUE:
1539 case PT_IESPECIAL:
1540 return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1);
1542 case PT_WORKGRP:
1543 return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1);
1546 return NULL;
1549 /**************************************************************************
1550 * _ILGetGUIDPointer()
1552 * returns reference to guid stored in some pidls
1554 REFIID _ILGetGUIDPointer(LPCITEMIDLIST pidl)
1556 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1558 if (pdata)
1560 switch (pdata->type)
1562 case PT_SPECIAL:
1563 case PT_MYCOMP:
1564 return (REFIID) &(pdata->u.mycomp.guid);
1567 return NULL;
1570 /*************************************************************************
1571 * _ILGetFileDateTime
1573 * Given the ItemIdList, get the FileTime
1575 * PARAMS
1576 * pidl [I] The ItemIDList
1577 * pFt [I] the resulted FILETIME of the file
1579 * RETURNS
1580 * True if Successful
1582 * NOTES
1585 BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt)
1587 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1589 if(! pdata) return FALSE;
1591 switch (pdata->type)
1593 case PT_FOLDER:
1594 DosDateTimeToFileTime(pdata->u.folder.uFileDate, pdata->u.folder.uFileTime, pFt);
1595 break;
1596 case PT_VALUE:
1597 DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt);
1598 break;
1599 default:
1600 return FALSE;
1602 return TRUE;
1605 BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1607 FILETIME ft,lft;
1608 SYSTEMTIME time;
1610 if (! _ILGetFileDateTime( pidl, &ft )) return FALSE;
1612 FileTimeToLocalFileTime(&ft, &lft);
1613 FileTimeToSystemTime (&lft, &time);
1614 return GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize);
1617 /*************************************************************************
1618 * _ILGetFileSize
1620 * Given the ItemIdList, get the FileSize
1622 * PARAMS
1623 * pidl [I] The ItemIDList
1624 * pOut [I] The buffer to save the result
1625 * uOutsize [I] The size of the buffer
1627 * RETURNS
1628 * The FileSize
1630 * NOTES
1631 * pOut can be null when no string is needed
1634 DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1636 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1637 DWORD dwSize;
1639 if(! pdata) return 0;
1641 switch (pdata->type)
1643 case PT_VALUE:
1644 dwSize = pdata->u.file.dwFileSize;
1645 if (pOut) StrFormatByteSizeA(dwSize, pOut, uOutSize);
1646 return dwSize;
1648 if (pOut) *pOut = 0x00;
1649 return 0;
1652 BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1654 char szTemp[MAX_PATH];
1655 const char * pPoint;
1656 LPITEMIDLIST pidlTemp=pidl;
1658 TRACE("pidl=%p\n",pidl);
1660 if (!pidl) return FALSE;
1662 pidlTemp = ILFindLastID(pidl);
1664 if (!_ILIsValue(pidlTemp)) return FALSE;
1665 if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH)) return FALSE;
1667 pPoint = PathFindExtensionA(szTemp);
1669 if (! *pPoint) return FALSE;
1671 pPoint++;
1672 lstrcpynA(pOut, pPoint, uOutSize);
1673 TRACE("%s\n",pOut);
1675 return TRUE;
1678 /*************************************************************************
1679 * _ILGetFileType
1681 * Given the ItemIdList, get the file type description
1683 * PARAMS
1684 * pidl [I] The ItemIDList (simple)
1685 * pOut [I] The buffer to save the result
1686 * uOutsize [I] The size of the buffer
1688 * RETURNS
1689 * nothing
1691 * NOTES
1692 * This function copies as much as possible into the buffer.
1694 void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1696 if(_ILIsValue(pidl))
1698 char sTemp[64];
1699 if(uOutSize > 0)
1701 pOut[0] = 0;
1703 if (_ILGetExtension (pidl, sTemp, 64))
1705 if (!( HCR_MapTypeToValue(sTemp, sTemp, 64, TRUE)
1706 && HCR_MapTypeToValue(sTemp, pOut, uOutSize, FALSE )))
1708 lstrcpynA (pOut, sTemp, uOutSize - 6);
1709 strcat (pOut, "-file");
1713 else
1715 lstrcpynA(pOut, "Folder", uOutSize);
1719 /*************************************************************************
1720 * _ILGetFileAttributes
1722 * Given the ItemIdList, get the Attrib string format
1724 * PARAMS
1725 * pidl [I] The ItemIDList
1726 * pOut [I] The buffer to save the result
1727 * uOutsize [I] The size of the Buffer
1729 * RETURNS
1730 * Attributes
1732 * FIXME
1733 * return value 0 in case of error is a valid return value
1736 DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1738 LPPIDLDATA pData =_ILGetDataPointer(pidl);
1739 WORD wAttrib = 0;
1740 int i;
1742 if(! pData) return 0;
1744 switch(pData->type)
1746 case PT_FOLDER:
1747 wAttrib = pData->u.folder.uFileAttribs;
1748 break;
1749 case PT_VALUE:
1750 wAttrib = pData->u.file.uFileAttribs;
1751 break;
1754 if(uOutSize >= 6)
1756 i=0;
1757 if(wAttrib & FILE_ATTRIBUTE_READONLY)
1759 pOut[i++] = 'R';
1761 if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
1763 pOut[i++] = 'H';
1765 if(wAttrib & FILE_ATTRIBUTE_SYSTEM)
1767 pOut[i++] = 'S';
1769 if(wAttrib & FILE_ATTRIBUTE_ARCHIVE)
1771 pOut[i++] = 'A';
1773 if(wAttrib & FILE_ATTRIBUTE_COMPRESSED)
1775 pOut[i++] = 'C';
1777 pOut[i] = 0x00;
1779 return wAttrib;
1782 /*************************************************************************
1783 * ILFreeaPidl
1785 * free a aPidl struct
1787 void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl)
1789 int i;
1791 if(apidl)
1793 for(i = 0; i < cidl; i++) SHFree(apidl[i]);
1794 SHFree(apidl);
1798 /*************************************************************************
1799 * ILCopyaPidl
1801 * copys a aPidl struct
1803 LPITEMIDLIST * _ILCopyaPidl(LPITEMIDLIST * apidlsrc, UINT cidl)
1805 int i;
1806 LPITEMIDLIST * apidldest = (LPITEMIDLIST*)SHAlloc(cidl * sizeof(LPITEMIDLIST));
1807 if(!apidlsrc) return NULL;
1809 for(i = 0; i < cidl; i++)
1810 apidldest[i] = ILClone(apidlsrc[i]);
1812 return apidldest;
1815 /*************************************************************************
1816 * _ILCopyCidaToaPidl
1818 * creates aPidl from CIDA
1820 LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPCIDA cida)
1822 int i;
1823 LPITEMIDLIST * dst = (LPITEMIDLIST*)SHAlloc(cida->cidl * sizeof(LPITEMIDLIST));
1825 if(!dst) return NULL;
1827 if (pidl)
1828 *pidl = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[0]]));
1830 for(i = 0; i < cida->cidl; i++)
1831 dst[i] = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[i + 1]]));
1833 return dst;