- the colums in the shellview are now created depending on the
[wine] / dlls / shell32 / pidl.c
1 /*
2  *      pidl Handling
3  *
4  *      Copyright 1998  Juergen Schmied
5  *
6  * NOTES
7  *  a pidl == NULL means desktop and is legal
8  *
9  */
10
11 #include <ctype.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <assert.h>
15 #include "debugtools.h"
16 #include "shell.h"
17 #include "shlguid.h"
18 #include "winerror.h"
19 #include "winnls.h"
20 #include "winversion.h"
21 #include "shell32_main.h"
22 #include "shellapi.h"
23
24 #include "pidl.h"
25 #include "wine/undocshell.h"
26
27 DECLARE_DEBUG_CHANNEL(pidl)
28 DECLARE_DEBUG_CHANNEL(shell)
29
30 void pdump (LPCITEMIDLIST pidl)
31 {       DWORD type;
32         char * szData;
33         char * szShortName;
34         char szName[MAX_PATH];
35         BOOL bIsShellDebug;
36         
37         LPITEMIDLIST pidltemp = pidl;
38         if (!TRACE_ON(pidl))
39           return;
40
41         /* silence the sub-functions */
42         bIsShellDebug = TRACE_ON(shell);
43         __SET_DEBUGGING(__DBCL_TRACE, dbch_shell, FALSE);
44         __SET_DEBUGGING(__DBCL_TRACE, dbch_pidl, FALSE);
45
46         if (! pidltemp)
47         {
48           MESSAGE ("-------- pidl=NULL (Desktop)\n");
49         }
50         else
51         {
52           MESSAGE ("-------- pidl=%p\n", pidl);
53           if (pidltemp->mkid.cb)
54           { 
55             do
56             {
57               type   = _ILGetDataPointer(pidltemp)->type;
58               szData = _ILGetTextPointer(type, _ILGetDataPointer(pidltemp));
59               szShortName = _ILGetSTextPointer(type, _ILGetDataPointer(pidltemp));
60               _ILSimpleGetText(pidltemp, szName, MAX_PATH);
61
62               MESSAGE ("-- pidl=%p size=%u type=%lx name=%s (%s,%s)\n",
63                        pidltemp, pidltemp->mkid.cb,type,szName,debugstr_a(szData), debugstr_a(szShortName));
64
65               pidltemp = ILGetNext(pidltemp);
66
67             } while (pidltemp->mkid.cb);
68           }
69           else
70           {
71             MESSAGE ("empty pidl (Desktop)\n");
72           }
73         }
74
75         __SET_DEBUGGING(__DBCL_TRACE, dbch_shell, bIsShellDebug);
76         __SET_DEBUGGING(__DBCL_TRACE, dbch_pidl, TRUE);
77
78 }
79 #define BYTES_PRINTED 32
80 BOOL pcheck (LPCITEMIDLIST pidl)
81 {       DWORD type, ret=TRUE;
82         BOOL bIsPidlDebug;
83
84         LPITEMIDLIST pidltemp = pidl;
85
86         bIsPidlDebug = TRACE_ON(shell);
87         __SET_DEBUGGING(__DBCL_TRACE, dbch_pidl, FALSE);
88
89         if (pidltemp && pidltemp->mkid.cb)
90         { do
91           { type   = _ILGetDataPointer(pidltemp)->type;
92             switch (type)
93             { case PT_DESKTOP:
94               case PT_MYCOMP:
95               case PT_SPECIAL:
96               case PT_DRIVE:
97               case PT_DRIVE1:
98               case PT_DRIVE2:
99               case PT_DRIVE3:
100               case PT_FOLDER:
101               case PT_VALUE:
102               case PT_FOLDER1:
103               case PT_WORKGRP:
104               case PT_COMP:
105               case PT_NETWORK:
106               case PT_SHARE:
107               case PT_IESPECIAL:
108                 break;
109               default:
110               {
111                 char szTemp[BYTES_PRINTED*4 + 1];
112                 int i;
113                 unsigned char c;
114
115                 memset(szTemp, ' ', BYTES_PRINTED*4 + 1);
116                 for ( i = 0; (i<pidltemp->mkid.cb) && (i<BYTES_PRINTED); i++)
117                 {
118                   c = ((unsigned char *)pidltemp)[i];
119
120                   szTemp[i*3+0] = ((c>>4)>9)? (c>>4)+55 : (c>>4)+48;
121                   szTemp[i*3+1] = ((0x0F&c)>9)? (0x0F&c)+55 : (0x0F&c)+48;
122                   szTemp[i*3+2] = ' ';
123                   szTemp[i+BYTES_PRINTED*3]  =  (c>=0x20 && c <=0x80) ? c : '.';
124                 }
125                 szTemp[BYTES_PRINTED*4] = 0x00;
126                 ERR_(pidl)("unknown IDLIST type size=%u type=%lx\n%s\n",pidltemp->mkid.cb,type, szTemp);
127                 ret = FALSE;
128               }
129             }
130             pidltemp = ILGetNext(pidltemp);
131           } while (pidltemp->mkid.cb);
132         }
133         __SET_DEBUGGING(__DBCL_TRACE, dbch_pidl, bIsPidlDebug);
134         return ret;
135 }
136
137 /*************************************************************************
138  * ILGetDisplayName                     [SHELL32.15]
139  */
140 BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl,LPSTR path)
141 {
142         TRACE_(shell)("pidl=%p %p semi-stub\n",pidl,path);
143         return SHGetPathFromIDListA(pidl, path);
144 }
145 /*************************************************************************
146  * ILFindLastID [SHELL32.16]
147  *
148  * NOTES
149  *   observed: pidl=Desktop return=pidl
150  */
151 LPITEMIDLIST WINAPI ILFindLastID(LPITEMIDLIST pidl) 
152 {       LPITEMIDLIST   pidlLast = pidl;
153
154         TRACE_(pidl)("(pidl=%p)\n",pidl);
155
156         while (pidl->mkid.cb)
157         {
158           pidlLast = pidl;
159           pidl = ILGetNext(pidl);
160         }
161         return pidlLast;                
162 }
163 /*************************************************************************
164  * ILRemoveLastID [SHELL32.17]
165  *
166  * NOTES
167  *   when pidl=Desktop return=FALSE
168  */
169 BOOL WINAPI ILRemoveLastID(LPCITEMIDLIST pidl)
170 {
171         TRACE_(shell)("pidl=%p\n",pidl);
172
173         if (!pidl || !pidl->mkid.cb)
174           return 0;
175         ILFindLastID(pidl)->mkid.cb = 0;
176         return 1;
177 }
178
179 /*************************************************************************
180  * ILClone [SHELL32.18]
181  *
182  * NOTES
183  *    dupicate an idlist
184  */
185 LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl)
186 { DWORD    len;
187   LPITEMIDLIST  newpidl;
188
189   if (!pidl)
190     return NULL;
191     
192   len = ILGetSize(pidl);
193   newpidl = (LPITEMIDLIST)SHAlloc(len);
194   if (newpidl)
195     memcpy(newpidl,pidl,len);
196
197   TRACE_(pidl)("pidl=%p newpidl=%p\n",pidl, newpidl);
198   pdump(pidl);
199
200   return newpidl;
201 }
202 /*************************************************************************
203  * ILCloneFirst [SHELL32.19]
204  *
205  * NOTES
206  *  duplicates the first idlist of a complex pidl
207  */
208 LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl)
209 {       DWORD len;
210         LPITEMIDLIST pidlNew = NULL;
211         
212         TRACE_(pidl)("pidl=%p \n",pidl);
213         pdump(pidl);
214         
215         if (pidl)
216         {
217           len = pidl->mkid.cb;  
218           pidlNew = (LPITEMIDLIST) SHAlloc (len+2);
219           if (pidlNew)
220           {
221             memcpy(pidlNew,pidl,len+2);         /* 2 -> mind a desktop pidl */
222
223             if (len)
224               ILGetNext(pidlNew)->mkid.cb = 0x00;
225           }
226         }
227         TRACE_(pidl)("-- newpidl=%p\n",pidlNew);
228
229         return pidlNew;
230 }
231 /*************************************************************************
232  * ILLoadFromStream
233  *
234  * NOTES
235  *   the first two bytes are the len, the pidl is following then
236  */
237 HRESULT WINAPI ILLoadFromStream (IStream * pStream, LPITEMIDLIST * ppPidl)
238 {       WORD            wLen = 0;
239         DWORD           dwBytesRead;
240         HRESULT         ret = E_FAIL;
241         
242
243         TRACE_(shell)("%p %p\n", pStream ,  ppPidl);
244
245         if (*ppPidl)
246         { SHFree(*ppPidl);
247           *ppPidl = NULL;
248         }
249         
250         IStream_AddRef (pStream);
251
252         if (SUCCEEDED(IStream_Read(pStream, (LPVOID)&wLen, 2, &dwBytesRead)))
253         { *ppPidl = SHAlloc (wLen);
254           if (SUCCEEDED(IStream_Read(pStream, *ppPidl , wLen, &dwBytesRead)))
255           { ret = S_OK;
256           }
257           else
258           { SHFree(*ppPidl);
259             *ppPidl = NULL;
260           }
261         }
262         
263         /* we are not jet fully compatible */
264         if (!pcheck(*ppPidl))
265         { SHFree(*ppPidl);
266           *ppPidl = NULL;
267         }
268         
269
270         IStream_Release (pStream);
271
272         return ret;
273 }
274 /*************************************************************************
275  * SHILCreateFromPath   [SHELL32.28]
276  *
277  * NOTES
278  *   wraper for IShellFolder::ParseDisplayName()
279  */
280 HRESULT WINAPI SHILCreateFromPathA (LPCSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
281 {       LPSHELLFOLDER sf;
282         WCHAR lpszDisplayName[MAX_PATH];
283         DWORD pchEaten;
284         HRESULT ret = E_FAIL;
285         
286         TRACE_(shell)("%s %p 0x%08lx\n",path,ppidl,attributes?*attributes:0);
287
288         LocalToWideChar(lpszDisplayName, path, MAX_PATH);
289
290         if (SUCCEEDED (SHGetDesktopFolder(&sf)))
291         {
292           ret = IShellFolder_ParseDisplayName(sf,0, NULL,lpszDisplayName,&pchEaten,ppidl,attributes);
293           IShellFolder_Release(sf);
294         }
295         return ret;
296 }
297 HRESULT WINAPI SHILCreateFromPathW (LPCWSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
298 {       LPSHELLFOLDER sf;
299         DWORD pchEaten;
300         HRESULT ret = E_FAIL;
301         
302         TRACE_(shell)("%s %p 0x%08lx\n",debugstr_w(path),ppidl,attributes?*attributes:0);
303
304         if (SUCCEEDED (SHGetDesktopFolder(&sf)))
305         {
306           ret = IShellFolder_ParseDisplayName(sf,0, NULL, (LPWSTR) path, &pchEaten, ppidl, attributes);
307           IShellFolder_Release(sf);
308         }
309         return ret;
310 }
311 HRESULT WINAPI SHILCreateFromPathAW (LPCVOID path, LPITEMIDLIST * ppidl, DWORD * attributes)
312 {
313         if ( VERSION_OsIsUnicode())
314           return SHILCreateFromPathW (path, ppidl, attributes);
315         return SHILCreateFromPathA (path, ppidl, attributes);
316 }
317
318 /*************************************************************************
319  * SHCloneSpecialIDList [SHELL32.89]
320  * 
321  * PARAMETERS
322  *  hwndOwner   [in] 
323  *  nFolder     [in]    CSIDL_xxxxx ??
324  *
325  * RETURNS
326  *  pidl ??
327  * NOTES
328  *     exported by ordinal
329  */
330 LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner,DWORD nFolder,DWORD x3)
331 {       LPITEMIDLIST ppidl;
332         WARN_(shell)("(hwnd=0x%x,csidl=0x%lx,0x%lx):semi-stub.\n",
333                                          hwndOwner,nFolder,x3);
334
335         SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl);
336
337         return ppidl;
338 }
339
340 /*************************************************************************
341  * ILGlobalClone [SHELL32.97]
342  *
343  */
344 LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl)
345 {       DWORD    len;
346         LPITEMIDLIST  newpidl;
347
348         if (!pidl)
349           return NULL;
350     
351         len = ILGetSize(pidl);
352         newpidl = (LPITEMIDLIST)pCOMCTL32_Alloc(len);
353         if (newpidl)
354           memcpy(newpidl,pidl,len);
355
356         TRACE_(pidl)("pidl=%p newpidl=%p\n",pidl, newpidl);
357         pdump(pidl);
358
359         return newpidl;
360 }
361
362 /*************************************************************************
363  * ILIsEqual [SHELL32.21]
364  *
365  */
366 BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
367 {
368         char    szData1[MAX_PATH];
369         char    szData2[MAX_PATH];
370
371         LPITEMIDLIST pidltemp1 = pidl1;
372         LPITEMIDLIST pidltemp2 = pidl2;
373
374         TRACE_(pidl)("pidl1=%p pidl2=%p\n",pidl1, pidl2);
375
376         /* explorer reads from registry directly (StreamMRU),
377            so we can only check here */
378         if ((!pcheck (pidl1)) || (!pcheck (pidl2))) return FALSE;
379
380         pdump (pidl1);
381         pdump (pidl2);
382
383         if ( (!pidl1) || (!pidl2) ) return FALSE;
384         
385         while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
386         {
387             _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
388             _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
389
390             if (strcasecmp ( szData1, szData2 )!=0 )
391               return FALSE;
392
393             pidltemp1 = ILGetNext(pidltemp1);
394             pidltemp2 = ILGetNext(pidltemp2);
395         }       
396
397         if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb)
398         {
399           return TRUE;
400         }
401
402         return FALSE;
403 }
404 /*************************************************************************
405  * ILIsParent [SHELL32.23]
406  *
407  * parent=a/b   child=a/b/c -> true, c is in folder a/b
408  *              child=a/b/c/d -> false if bImmediate is true, d is not in folder a/b
409  *              child=a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b
410  */
411 BOOL WINAPI ILIsParent( LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate)
412 {
413         char    szData1[MAX_PATH];
414         char    szData2[MAX_PATH];
415
416         LPITEMIDLIST pParent = pidlParent;
417         LPITEMIDLIST pChild = pidlChild;
418         
419         TRACE_(pidl)("%p %p %x\n", pidlParent, pidlChild, bImmediate);
420
421         while (pParent->mkid.cb && pChild->mkid.cb)
422         {
423           _ILSimpleGetText(pParent, szData1, MAX_PATH);
424           _ILSimpleGetText(pChild, szData2, MAX_PATH);
425
426           if (strcasecmp ( szData1, szData2 )!=0 )
427             return FALSE;
428
429           pParent = ILGetNext(pParent);
430           pChild = ILGetNext(pChild);
431         }       
432         
433         if ( pParent->mkid.cb || ! pChild->mkid.cb)     /* child shorter or has equal length to parent */
434           return FALSE;
435         
436         if ( ILGetNext(pChild)->mkid.cb && bImmediate)  /* not immediate descent */
437           return FALSE;
438         
439         return TRUE;
440 }
441
442 /*************************************************************************
443  * ILFindChild [SHELL32.24]
444  *
445  * NOTES
446  *  Compares elements from pidl1 and pidl2.
447  *
448  *  pidl1 is desktop            pidl2
449  *  pidl1 shorter pidl2         pointer to first different element of pidl2
450  *                              if there was at least one equal element
451  *  pidl2 shorter pidl1         0
452  *  pidl2 equal pidl1           pointer to last 0x00-element of pidl2
453  */
454 LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
455 {
456         char    szData1[MAX_PATH];
457         char    szData2[MAX_PATH];
458
459         LPITEMIDLIST pidltemp1 = pidl1;
460         LPITEMIDLIST pidltemp2 = pidl2;
461         LPITEMIDLIST ret=NULL;
462
463         TRACE_(pidl)("pidl1=%p pidl2=%p\n",pidl1, pidl2);
464
465         /* explorer reads from registry directly (StreamMRU),
466            so we can only check here */
467         if ((!pcheck (pidl1)) || (!pcheck (pidl2)))
468           return FALSE;
469
470         pdump (pidl1);
471         pdump (pidl2);
472
473         if ( _ILIsDesktop(pidl1) )
474         {
475           ret = pidl2;
476         }
477         else
478         {
479           while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
480           {
481             _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
482             _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
483
484             if (strcasecmp(szData1,szData2))
485               break;
486
487             pidltemp1 = ILGetNext(pidltemp1);
488             pidltemp2 = ILGetNext(pidltemp2);
489             ret = pidltemp2;    
490           }
491
492           if (pidltemp1->mkid.cb)
493           {
494             ret = NULL; /* elements of pidl1 left*/
495           }
496         }
497         TRACE_(shell)("--- %p\n", ret);
498         return ret; /* pidl 1 is shorter */
499 }
500
501 /*************************************************************************
502  * ILCombine [SHELL32.25]
503  *
504  * NOTES
505  *  Concatenates two complex idlists.
506  *  The pidl is the first one, pidlsub the next one
507  *  Does not destroy the passed in idlists!
508  */
509 LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
510 {
511         DWORD    len1,len2;
512         LPITEMIDLIST  pidlNew;
513         
514         TRACE_(pidl)("pidl=%p pidl=%p\n",pidl1,pidl2);
515
516         if(!pidl1 && !pidl2) return NULL;
517
518         pdump (pidl1);
519         pdump (pidl2);
520
521         if(!pidl1)
522         {
523           pidlNew = ILClone(pidl2);
524           return pidlNew;
525         }
526
527         if(!pidl2)
528         {
529           pidlNew = ILClone(pidl1);
530           return pidlNew;
531         }
532
533         len1  = ILGetSize(pidl1)-2;
534         len2  = ILGetSize(pidl2);
535         pidlNew  = SHAlloc(len1+len2);
536
537         if (pidlNew)
538         {
539           memcpy(pidlNew,pidl1,len1);
540           memcpy(((BYTE *)pidlNew)+len1,pidl2,len2);
541         }
542
543         /*  TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
544         return pidlNew;
545 }
546 /*************************************************************************
547  *  SHGetRealIDL [SHELL32.98]
548  *
549  * NOTES
550  */
551 LPITEMIDLIST WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl, DWORD z)
552 {
553         FIXME_(pidl)("sf=%p pidl=%p 0x%04lx\n",lpsf,pidl,z);
554
555         pdump (pidl);
556         return 0;
557 }
558
559 /*************************************************************************
560  *  SHLogILFromFSIL [SHELL32.95]
561  *
562  * NOTES
563  *  pild = CSIDL_DESKTOP        ret = 0
564  *  pild = CSIDL_DRIVES         ret = 0
565  */
566 LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
567 {
568         FIXME_(pidl)("(pidl=%p)\n",pidl);
569
570         pdump(pidl);
571
572         return 0;
573 }
574
575 /*************************************************************************
576  * ILGetSize [SHELL32.152]
577  *  gets the byte size of an idlist including zero terminator (pidl)
578  *
579  * PARAMETERS
580  *  pidl ITEMIDLIST
581  *
582  * RETURNS
583  *  size of pidl
584  *
585  * NOTES
586  *  exported by ordinal
587  */
588 DWORD WINAPI ILGetSize(LPITEMIDLIST pidl)
589 {
590         LPSHITEMID si = &(pidl->mkid);
591         DWORD  len=0;
592
593         if (pidl)
594         { while (si->cb) 
595           { len += si->cb;
596             si  = (LPSHITEMID)(((LPBYTE)si)+si->cb);
597           }
598           len += 2;
599         }
600         TRACE_(pidl)("pidl=%p size=%lu\n",pidl, len);
601         return len;
602 }
603
604 /*************************************************************************
605  * ILGetNext [SHELL32.153]
606  *  gets the next simple pidl of a complex pidl
607  *
608  * observed return values:
609  *  null -> null
610  *  desktop -> null
611  *  simple pidl -> pointer to 0x0000 element
612  *
613  */
614 LPITEMIDLIST WINAPI ILGetNext(LPITEMIDLIST pidl)
615 {
616         WORD len;
617         
618         TRACE_(pidl)("(pidl=%p)\n",pidl);
619
620         if(pidl)
621         {
622           len =  pidl->mkid.cb;
623           if (len)
624           {
625             pidl = (LPITEMIDLIST) (((LPBYTE)pidl)+len);
626             return pidl;
627           }
628         }
629         return NULL;
630 }
631 /*************************************************************************
632  * ILAppend [SHELL32.154]
633  *
634  * NOTES
635  *  Adds the single item to the idlist indicated by pidl.
636  *  if bEnd is 0, adds the item to the front of the list,
637  *  otherwise adds the item to the end. (???)
638  *  Destroys the passed in idlist! (???)
639  */
640 LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl,LPCITEMIDLIST item,BOOL bEnd)
641 {
642         LPITEMIDLIST idlRet;
643
644         WARN_(pidl)("(pidl=%p,pidl=%p,%08u)semi-stub\n",pidl,item,bEnd);
645
646         pdump (pidl);
647         pdump (item);
648         
649         if (_ILIsDesktop(pidl))
650         {
651            idlRet = ILClone(item);
652            if (pidl)
653              SHFree (pidl);
654            return idlRet;
655         }
656
657         if (bEnd)
658         {
659           idlRet=ILCombine(pidl,item);
660         }
661         else
662         {
663           idlRet=ILCombine(item,pidl);
664         }
665
666         SHFree(pidl);
667         return idlRet;
668 }
669 /*************************************************************************
670  * ILFree [SHELL32.155]
671  *
672  * NOTES
673  *     free_check_ptr - frees memory (if not NULL)
674  *     allocated by SHMalloc allocator
675  *     exported by ordinal
676  */
677 DWORD WINAPI ILFree(LPITEMIDLIST pidl) 
678 {       TRACE_(pidl)("(pidl=0x%08lx)\n",(DWORD)pidl);
679
680         if (!pidl)
681           return FALSE;
682
683         return SHFree(pidl);
684 }
685 /*************************************************************************
686  * ILGlobalFree [SHELL32.156]
687  *
688  */
689 DWORD WINAPI ILGlobalFree( LPITEMIDLIST pidl)
690 {
691         TRACE_(pidl)("%p\n",pidl);
692
693         if (!pidl)
694           return FALSE;
695
696         return pCOMCTL32_Free (pidl);
697 }
698 /*************************************************************************
699  * ILCreateFromPath [SHELL32.157]
700  *
701  */
702 LPITEMIDLIST WINAPI ILCreateFromPathA (LPCSTR path) 
703 {
704         LPITEMIDLIST pidlnew;
705         DWORD attributes = 0;
706
707         TRACE_(shell)("%s\n",path);
708
709         if (SUCCEEDED (SHILCreateFromPathA (path, &pidlnew, &attributes)))
710           return pidlnew;
711         return FALSE;
712 }
713 LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path) 
714 {
715         LPITEMIDLIST pidlnew;
716         DWORD attributes = 0;
717
718         TRACE_(shell)("%s\n",debugstr_w(path));
719
720         if (SUCCEEDED (SHILCreateFromPathW (path, &pidlnew, &attributes)))
721           return pidlnew;
722         return FALSE;
723 }
724 LPITEMIDLIST WINAPI ILCreateFromPathAW (LPCVOID path) 
725 {
726         if ( VERSION_OsIsUnicode())
727           return ILCreateFromPathW (path);
728         return ILCreateFromPathA (path);
729 }
730 /*************************************************************************
731  *  SHSimpleIDListFromPath [SHELL32.162]
732  */
733 LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPSTR lpszPath)
734 {
735         LPITEMIDLIST    pidl=NULL;
736         HANDLE  hFile;
737         WIN32_FIND_DATAA        stffile;
738
739         TRACE_(pidl)("path=%s\n", lpszPath);
740
741         if (!lpszPath) return NULL;
742
743         hFile = FindFirstFileA(lpszPath, &stffile);
744
745         if ( hFile != INVALID_HANDLE_VALUE )
746         {
747           if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
748           {
749             pidl = _ILCreateFolder (&stffile);
750           }
751           else
752           {
753             pidl = _ILCreateValue (&stffile);
754           }
755           FindClose (hFile);
756         }
757         return pidl;
758 }
759 LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPWSTR lpszPath)
760 {
761         char    lpszTemp[MAX_PATH];
762         TRACE_(pidl)("path=L%s\n",debugstr_w(lpszPath));
763
764         WideCharToLocal(lpszTemp, lpszPath, MAX_PATH);
765
766         return SHSimpleIDListFromPathA (lpszTemp);
767 }
768
769 LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW (LPVOID lpszPath)
770 {
771         if ( VERSION_OsIsUnicode())
772           return SHSimpleIDListFromPathW (lpszPath);
773         return SHSimpleIDListFromPathA (lpszPath);
774 }
775
776 /*************************************************************************
777  * SHGetSpecialFolderLocation           [SHELL32.223]
778  *
779  * gets the folder locations from the registry and creates a pidl
780  * creates missing reg keys and directorys
781  * 
782  * PARAMS
783  *   hwndOwner [I]
784  *   nFolder   [I] CSIDL_xxxxx
785  *   ppidl     [O] PIDL of a special folder
786  *
787  */
788 HRESULT WINAPI SHGetSpecialFolderLocation(
789         HWND hwndOwner,
790         INT nFolder,
791         LPITEMIDLIST * ppidl)
792 {
793         CHAR            szPath[256];
794         HRESULT         hr = E_INVALIDARG;
795
796         TRACE_(shell)("(%04x,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
797
798         *ppidl = NULL;
799
800         if (ppidl)
801         {
802           switch (nFolder)
803           {
804             case CSIDL_DESKTOP:
805               *ppidl = _ILCreateDesktop();
806               hr = NOERROR;
807               break;
808
809             case CSIDL_DRIVES:
810               *ppidl = _ILCreateMyComputer();
811               hr = NOERROR;
812               break;
813
814             case CSIDL_NETWORK:
815               *ppidl = _ILCreateNetwork ();
816               hr = NOERROR;
817               break;
818
819             case CSIDL_CONTROLS:
820               *ppidl = _ILCreateControl ();
821               hr = NOERROR;
822               break;
823
824             case CSIDL_PRINTERS:
825               *ppidl = _ILCreatePrinter ();
826               hr = NOERROR;
827               break;
828
829             case CSIDL_BITBUCKET:
830               *ppidl = _ILCreateBitBucket ();
831               hr = NOERROR;
832               break;
833
834             default:
835               if (SHGetSpecialFolderPathA(hwndOwner, szPath, nFolder, TRUE))
836               {
837                 DWORD attributes=0;
838                 TRACE_(shell)("Value=%s\n",szPath);
839                 hr = SHILCreateFromPathA(szPath, ppidl, &attributes);
840               }
841           }
842         }
843
844         TRACE_(shell)("-- (new pidl %p)\n",*ppidl);
845         return hr;
846 }
847
848 /*************************************************************************
849  * SHGetDataFromIDListA [SHELL32.247]
850  *
851  */
852 HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
853 {
854         TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
855         
856         if (! psf || !dest )  return E_INVALIDARG;
857
858         switch (nFormat)
859         {
860           case SHGDFIL_FINDDATA:
861             {
862                WIN32_FIND_DATAA * pfd = dest;
863                CHAR     pszPath[MAX_PATH];
864                HANDLE   handle;
865
866                if ( len < sizeof (WIN32_FIND_DATAA)) {
867                  ERR_(shell)("%d does not find sizeof(finddata)\n",len);
868                  return E_INVALIDARG;
869                }
870
871                SHGetPathFromIDListA(pidl, pszPath);
872
873                if ((handle  = FindFirstFileA ( pszPath, pfd)))
874                  FindClose (handle);
875             }
876             return NOERROR;
877
878           case SHGDFIL_NETRESOURCE:
879           case SHGDFIL_DESCRIPTIONID:
880             FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
881             break;
882
883           default:
884             ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
885         }
886
887         return E_INVALIDARG;
888 }
889 /*************************************************************************
890  * SHGetDataFromIDListW [SHELL32.247]
891  *
892  */
893 HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len)
894 {
895         if (! psf || !dest )  return E_INVALIDARG;
896
897         switch (nFormat)
898         {
899           case SHGDFIL_FINDDATA:
900             {
901                WIN32_FIND_DATAW * pfd = dest;
902                WCHAR    pszPath[MAX_PATH];
903                HANDLE   handle;
904
905                if ( len < sizeof (WIN32_FIND_DATAW)) {
906                  ERR_(shell)("%d does not find sizeof(finddata)\n",len);
907                  return E_INVALIDARG;
908                }
909                SHGetPathFromIDListW(pidl, pszPath);
910                if ((handle  = FindFirstFileW ( pszPath, pfd)))
911                  FindClose (handle);
912             }
913             return NOERROR;
914           default: /* fallthrough */
915             break;
916         }
917         FIXME_(shell)("(sf=%p pidl=%p nFormat=0x%04x %p 0x%04x), unhandled.\n",psf,pidl,nFormat,dest,len);
918         return SHGetDataFromIDListA( psf, pidl, nFormat, dest, len);
919 }
920
921 /*************************************************************************
922  * SHGetPathFromIDListA         [SHELL32.261][NT 4.0: SHELL32.220]
923  *
924  * PARAMETERS
925  *  pidl,   [IN] pidl 
926  *  pszPath [OUT] path
927  *
928  * RETURNS 
929  *  path from a passed PIDL.
930  *
931  * NOTES
932  *      NULL returns FALSE
933  *      desktop pidl gives path to desktopdirectory back
934  *      special pidls returning FALSE
935  *
936  * FIXME
937  *  fnGetDisplayNameOf can return different types of OLEString
938  */
939 BOOL WINAPI SHGetPathFromIDListA (LPCITEMIDLIST pidl,LPSTR pszPath)
940 {       STRRET str;
941         LPSHELLFOLDER shellfolder;
942
943         TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
944
945         if (!pidl) return FALSE;
946
947         pdump(pidl);
948
949         if(_ILIsDesktop(pidl))
950         {
951            SHGetSpecialFolderPathA(0, pszPath, CSIDL_DESKTOPDIRECTORY, FALSE);  
952         }
953         else
954         {
955           if (SHGetDesktopFolder(&shellfolder)==S_OK)
956           {
957             IShellFolder_GetDisplayNameOf(shellfolder,pidl,SHGDN_FORPARSING,&str);
958             StrRetToStrNA (pszPath, MAX_PATH, &str, pidl);
959             IShellFolder_Release(shellfolder);
960           }
961         }
962         TRACE_(shell)("-- (%s)\n",pszPath);
963
964         return TRUE;
965 }
966 /*************************************************************************
967  * SHGetPathFromIDListW                         [SHELL32.262]
968  */
969 BOOL WINAPI SHGetPathFromIDListW (LPCITEMIDLIST pidl,LPWSTR pszPath)
970 {       char sTemp[MAX_PATH];
971
972         TRACE_(shell)("(pidl=%p)\n", pidl);
973
974         SHGetPathFromIDListA (pidl, sTemp);
975         lstrcpyAtoW(pszPath, sTemp);
976
977         TRACE_(shell)("-- (%s)\n",debugstr_w(pszPath));
978
979         return TRUE;
980 }
981
982 /*************************************************************************
983  *      SHBindToParent          [shell version 5.0]
984  */
985 HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
986 {
987         IShellFolder    * psf;
988         LPITEMIDLIST    pidlChild, pidlParent;
989         HRESULT         hr=E_FAIL;
990         
991         TRACE_(shell)("pidl=%p\n", pidl);
992         pdump(pidl);
993         
994         *ppv = NULL;
995         if (ppidlLast) *ppidlLast = NULL;
996
997         if (_ILIsPidlSimple(pidl))
998         {
999           /* we are on desktop level */
1000           if (ppidlLast) 
1001             *ppidlLast = ILClone(pidl);
1002           hr = SHGetDesktopFolder((IShellFolder**)ppv);
1003         }
1004         else
1005         {
1006           pidlChild =  ILClone(ILFindLastID(pidl));
1007           pidlParent = ILClone(pidl);
1008           ILRemoveLastID(pidlParent);
1009
1010           hr = SHGetDesktopFolder(&psf);
1011
1012           if (SUCCEEDED(hr))
1013             hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv);
1014
1015           if (SUCCEEDED(hr) && ppidlLast)
1016             *ppidlLast = pidlChild;
1017           else
1018             ILFree (pidlChild);
1019
1020           SHFree (pidlParent);
1021         }
1022
1023
1024         TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr);
1025         return hr;
1026 }
1027
1028 /*************************************************************************
1029  * SHGetPathFromIDListAW                [SHELL32.221][NT 4.0: SHELL32.219]
1030  */
1031 BOOL WINAPI SHGetPathFromIDListAW(LPCITEMIDLIST pidl,LPVOID pszPath)
1032 {
1033         TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
1034
1035         if (VERSION_OsIsUnicode())
1036           return SHGetPathFromIDListW(pidl,pszPath);
1037         return SHGetPathFromIDListA(pidl,pszPath);
1038 }
1039
1040 /**************************************************************************
1041  *
1042  *              internal functions
1043  *
1044  *      ### 1. section creating pidls ###
1045  *
1046  *************************************************************************
1047  *  _ILCreateDesktop()
1048  *  _ILCreateIExplore()
1049  *  _ILCreateMyComputer()
1050  *  _ILCreateDrive()
1051  *  _ILCreateFolder() 
1052  *  _ILCreateValue()
1053  */
1054 LPITEMIDLIST _ILCreateDesktop()
1055 {       TRACE_(pidl)("()\n");
1056         return _ILCreate(PT_DESKTOP, NULL, 0);
1057 }
1058
1059 LPITEMIDLIST _ILCreateMyComputer()
1060 {       TRACE_(pidl)("()\n");
1061         return _ILCreate(PT_MYCOMP, &IID_MyComputer, sizeof(GUID));
1062 }
1063
1064 LPITEMIDLIST _ILCreateIExplore()
1065 {       TRACE_(pidl)("()\n");
1066         return _ILCreate(PT_MYCOMP, &IID_IExplore, sizeof(GUID));
1067 }
1068
1069 LPITEMIDLIST _ILCreateControl()
1070 {       TRACE_(pidl)("()\n");
1071         return _ILCreate(PT_SPECIAL, &IID_Control, sizeof(GUID));
1072 }
1073
1074 LPITEMIDLIST _ILCreatePrinter()
1075 {       TRACE_(pidl)("()\n");
1076         return _ILCreate(PT_SPECIAL, &IID_Printer, sizeof(GUID));
1077 }
1078
1079 LPITEMIDLIST _ILCreateNetwork()
1080 {       TRACE_(pidl)("()\n");
1081         return _ILCreate(PT_MYCOMP, &IID_Network, sizeof(GUID));
1082 }
1083
1084 LPITEMIDLIST _ILCreateBitBucket()
1085 {       TRACE_(pidl)("()\n");
1086         return _ILCreate(PT_MYCOMP, &IID_BitBucket, sizeof(GUID));
1087 }
1088
1089 LPITEMIDLIST _ILCreateDrive( LPCSTR lpszNew)
1090 {       char sTemp[4];
1091         lstrcpynA (sTemp,lpszNew,4);
1092         sTemp[2]='\\';
1093         sTemp[3]=0x00;
1094         TRACE_(pidl)("(%s)\n",sTemp);
1095         return _ILCreate(PT_DRIVE,(LPVOID)&sTemp[0],4);
1096 }
1097
1098 LPITEMIDLIST _ILCreateFolder( WIN32_FIND_DATAA * stffile )
1099 {
1100         char    buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1101         char *  pbuff = buff;
1102         ULONG   len, len1;
1103         LPITEMIDLIST pidl;
1104         
1105         TRACE_(pidl)("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1106
1107         /* prepare buffer with both names */
1108         len = strlen (stffile->cFileName) + 1;
1109         memcpy (pbuff, stffile->cFileName, len);
1110         pbuff += len;
1111
1112         if (stffile->cAlternateFileName)
1113         {
1114           len1 = strlen (stffile->cAlternateFileName)+1;
1115           memcpy (pbuff, stffile->cAlternateFileName, len1);
1116         }
1117         else
1118         {
1119           len1 = 1;
1120           *pbuff = 0x00;
1121         }
1122
1123         pidl = _ILCreate(PT_FOLDER, (LPVOID)buff, len + len1);
1124         
1125         /* set attributes */
1126         if (pidl)
1127         {
1128           LPPIDLDATA pData;
1129           pData = _ILGetDataPointer(pidl);
1130           FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1131           pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1132           pData->u.folder.uFileAttribs=stffile->dwFileAttributes;
1133         }
1134
1135         return pidl;
1136 }
1137
1138 LPITEMIDLIST _ILCreateValue(WIN32_FIND_DATAA * stffile)
1139 {
1140         char    buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1141         char *  pbuff = buff;
1142         ULONG   len, len1;
1143         LPITEMIDLIST pidl;
1144         
1145         TRACE_(pidl)("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName);
1146
1147         /* prepare buffer with both names */
1148         len = strlen (stffile->cFileName) + 1;
1149         memcpy (pbuff, stffile->cFileName, len);
1150         pbuff += len;
1151
1152         if (stffile->cAlternateFileName)
1153         {
1154           len1 = strlen (stffile->cAlternateFileName)+1;
1155           memcpy (pbuff, stffile->cAlternateFileName, len1);
1156         }
1157         else
1158         {
1159           len1 = 1;
1160           *pbuff = 0x00;
1161         }
1162
1163         pidl = _ILCreate(PT_VALUE, (LPVOID)buff, len + len1);
1164         
1165         /* set attributes */
1166         if (pidl)
1167         {
1168           LPPIDLDATA pData;
1169           pData = _ILGetDataPointer(pidl);
1170           FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.folder.uFileDate,&pData->u.folder.uFileTime);
1171           pData->u.folder.dwFileSize = stffile->nFileSizeLow;
1172           pData->u.folder.uFileAttribs=stffile->dwFileAttributes;
1173         }
1174
1175         return pidl;
1176 }
1177
1178 LPITEMIDLIST _ILCreateSpecial(LPCSTR szGUID)
1179 {
1180         IID     iid;
1181         CLSIDFromString16(szGUID,&iid);
1182         return _ILCreate(PT_MYCOMP, &iid, sizeof(IID));
1183 }
1184
1185 /**************************************************************************
1186  *  _ILCreate()
1187  *  Creates a new PIDL
1188  *  type = PT_DESKTOP | PT_DRIVE | PT_FOLDER | PT_VALUE
1189  *  pIn = data
1190  *  uInSize = size of data (raw)
1191  */
1192
1193 LPITEMIDLIST _ILCreate(PIDLTYPE type, LPCVOID pIn, UINT16 uInSize)
1194 {       LPITEMIDLIST   pidlOut = NULL, pidlTemp = NULL;
1195         LPPIDLDATA     pData;
1196         UINT16         uSize = 0;
1197         LPSTR   pszDest;
1198         
1199         TRACE_(pidl)("(0x%02x %p %i)\n",type,pIn,uInSize);
1200
1201         switch (type)
1202         { case PT_DESKTOP:
1203             uSize = 0;
1204             pidlOut = SHAlloc(uSize + 2);
1205             pidlOut->mkid.cb = uSize;
1206             TRACE_(pidl)("- create Desktop\n");
1207             break;
1208
1209           case PT_MYCOMP:
1210             uSize = 2 + 2 + sizeof(GUID);
1211             pidlOut = SHAlloc(uSize + 2);
1212             ZeroMemory(pidlOut, uSize + 2);
1213             pidlOut->mkid.cb = uSize;
1214             pData =_ILGetDataPointer(pidlOut);
1215             pData->type = type;
1216             memcpy(&(pData->u.mycomp.guid), pIn, uInSize);
1217             TRACE_(pidl)("- create GUID-pidl\n");
1218             break;
1219
1220           case PT_DRIVE:
1221             uSize = 2 + 23;
1222             pidlOut = SHAlloc(uSize + 2);
1223             ZeroMemory(pidlOut, uSize + 2);
1224             pidlOut->mkid.cb = uSize;
1225             pData =_ILGetDataPointer(pidlOut);
1226             pData->type = type;
1227             pszDest =  _ILGetTextPointer(type, pData);
1228             memcpy(pszDest, pIn, uInSize);
1229             TRACE_(pidl)("- create Drive: %s\n",debugstr_a(pszDest));
1230             break;
1231
1232           case PT_FOLDER:
1233           case PT_VALUE:   
1234             uSize = 2 + 12 + uInSize;
1235             pidlOut = SHAlloc(uSize + 2);
1236             ZeroMemory(pidlOut, uSize + 2);
1237             pidlOut->mkid.cb = uSize;
1238             pData =_ILGetDataPointer(pidlOut);
1239             pData->type = type;
1240             pszDest =  _ILGetTextPointer(type, pData);
1241             memcpy(pszDest, pIn, uInSize);
1242             TRACE_(pidl)("- create Value: %s\n",debugstr_a(pszDest));
1243             break;
1244         }
1245         
1246         pidlTemp = ILGetNext(pidlOut);
1247         if (pidlTemp)
1248           pidlTemp->mkid.cb = 0x00;
1249
1250         TRACE_(pidl)("-- (pidl=%p, size=%u)\n", pidlOut, uSize);
1251         return pidlOut;
1252 }
1253
1254 /**************************************************************************
1255  *  _ILGetDrive()
1256  *
1257  *  Gets the text for the drive eg. 'c:\'
1258  *
1259  * RETURNS
1260  *  strlen (lpszText)
1261  */
1262 DWORD _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT16 uSize)
1263 {       TRACE_(pidl)("(%p,%p,%u)\n",pidl,pOut,uSize);
1264
1265         if(_ILIsMyComputer(pidl))
1266           pidl = ILGetNext(pidl);
1267
1268         if (pidl && _ILIsDrive(pidl))
1269           return _ILSimpleGetText(pidl, pOut, uSize);
1270
1271         return 0;
1272 }
1273
1274 /**************************************************************************
1275  *
1276  *      ### 2. section testing pidls ###
1277  *
1278  **************************************************************************
1279  *  _ILIsDesktop()
1280  *  _ILIsMyComputer()
1281  *  _ILIsSpecialFolder()
1282  *  _ILIsDrive()
1283  *  _ILIsFolder()
1284  *  _ILIsValue()
1285  *  _ILIsPidlSimple()
1286  */
1287 BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
1288 {       TRACE_(pidl)("(%p)\n",pidl);
1289         return ( !pidl || (pidl && pidl->mkid.cb == 0x00) );
1290 }
1291
1292 BOOL _ILIsMyComputer(LPCITEMIDLIST pidl)
1293 {
1294         REFIID iid = _ILGetGUIDPointer(pidl);
1295
1296         TRACE_(pidl)("(%p)\n",pidl);
1297
1298         if (iid)
1299           return IsEqualIID(iid, &IID_MyComputer);
1300         return FALSE;
1301 }
1302
1303 BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl)
1304 {
1305         LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1306         TRACE_(pidl)("(%p)\n",pidl);
1307         return (pidl && ( (lpPData && (PT_MYCOMP== lpPData->type || PT_SPECIAL== lpPData->type)) || 
1308                           (pidl && pidl->mkid.cb == 0x00)
1309                         ));
1310 }
1311
1312 BOOL _ILIsDrive(LPCITEMIDLIST pidl)
1313 {       LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1314         TRACE_(pidl)("(%p)\n",pidl);
1315         return (pidl && lpPData && (PT_DRIVE == lpPData->type ||
1316                                     PT_DRIVE1 == lpPData->type ||
1317                                     PT_DRIVE2 == lpPData->type ||
1318                                     PT_DRIVE3 == lpPData->type));
1319 }
1320
1321 BOOL _ILIsFolder(LPCITEMIDLIST pidl)
1322 {       LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1323         TRACE_(pidl)("(%p)\n",pidl);
1324         return (pidl && lpPData && (PT_FOLDER == lpPData->type || PT_FOLDER1 == lpPData->type));
1325 }
1326
1327 BOOL _ILIsValue(LPCITEMIDLIST pidl)
1328 {       LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1329         TRACE_(pidl)("(%p)\n",pidl);
1330         return (pidl && lpPData && PT_VALUE == lpPData->type);
1331 }
1332
1333 /**************************************************************************
1334  *      _ILIsPidlSimple
1335  */
1336 BOOL _ILIsPidlSimple ( LPCITEMIDLIST pidl)
1337 {
1338         BOOL ret = TRUE;
1339
1340         if(! _ILIsDesktop(pidl))        /* pidl=NULL or mkid.cb=0 */
1341         {
1342           WORD len = pidl->mkid.cb;
1343           LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((LPBYTE)pidl) + len );
1344           if (pidlnext->mkid.cb)
1345             ret = FALSE;
1346         }
1347
1348         TRACE_(pidl)("%s\n", ret ? "Yes" : "No");
1349         return ret;
1350 }
1351
1352 /**************************************************************************
1353  *
1354  *      ### 3. section getting values from pidls ###
1355  */
1356
1357  /**************************************************************************
1358  *  _ILSimpleGetText
1359  *
1360  * gets the text for the first item in the pidl (eg. simple pidl)
1361  *
1362  * returns the lenght of the string
1363  */
1364 DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
1365 {
1366         LPPIDLDATA      pData;
1367         DWORD           dwReturn=0; 
1368         LPSTR           szSrc;
1369         GUID const *    riid;
1370         char szTemp[MAX_PATH];
1371         
1372         TRACE_(pidl)("(%p %p %x)\n",pidl,szOut,uOutSize);
1373         
1374         if (!pidl) return 0;
1375
1376         if (szOut)
1377           *szOut = 0;
1378
1379         pData = _ILGetDataPointer(pidl);
1380
1381         if (!pData)                                     
1382         {
1383          /* desktop */
1384           if (HCR_GetClassName(&CLSID_ShellDesktop, szTemp, MAX_PATH))
1385           {
1386             if (szOut)
1387               lstrcpynA(szOut, szTemp, uOutSize);
1388
1389             dwReturn = strlen (szTemp);
1390           }
1391         }
1392         else if (( szSrc = _ILGetTextPointer(pData->type, pData) ))
1393         {
1394           /* filesystem */
1395           if (szOut)
1396             lstrcpynA(szOut, szSrc, MAX_PATH);
1397
1398           dwReturn = strlen(szSrc);
1399         }
1400         else if (( riid = _ILGetGUIDPointer(pidl) ))
1401         {
1402           /* special folder */
1403           if ( HCR_GetClassName(riid, szTemp, MAX_PATH) )
1404           {
1405             if (szOut)
1406               lstrcpynA(szOut, szTemp, uOutSize);
1407
1408             dwReturn = strlen (szTemp);
1409           }
1410         }
1411         else
1412         {
1413           ERR_(pidl)("-- no text\n");
1414         }
1415
1416         TRACE_(pidl)("-- (%p=%s 0x%08lx)\n",szOut,(char*)szOut,dwReturn);
1417         return dwReturn;
1418 }
1419
1420 /**************************************************************************
1421  *
1422  *      ### 4. getting pointers to parts of pidls ###
1423  *
1424  **************************************************************************
1425  *  _ILGetDataPointer()
1426  */
1427 LPPIDLDATA _ILGetDataPointer(LPITEMIDLIST pidl)
1428 {
1429         if(pidl && pidl->mkid.cb != 0x00)
1430           return (LPPIDLDATA) &(pidl->mkid.abID);
1431         return NULL;
1432 }
1433
1434 /**************************************************************************
1435  *  _ILGetTextPointer()
1436  * gets a pointer to the long filename string stored in the pidl
1437  */
1438 LPSTR _ILGetTextPointer(PIDLTYPE type, LPPIDLDATA pidldata)
1439 {/*     TRACE(pidl,"(type=%x data=%p)\n", type, pidldata);*/
1440
1441         if(!pidldata)
1442         { return NULL;
1443         }
1444
1445         switch (type)
1446         {
1447           case PT_MYCOMP:
1448           case PT_SPECIAL:
1449             return NULL;
1450
1451           case PT_DRIVE:
1452           case PT_DRIVE1:
1453           case PT_DRIVE2:
1454           case PT_DRIVE3:
1455             return (LPSTR)&(pidldata->u.drive.szDriveName);
1456
1457           case PT_FOLDER:
1458           case PT_FOLDER1:
1459           case PT_VALUE:
1460           case PT_IESPECIAL:
1461             return (LPSTR)&(pidldata->u.file.szNames);
1462
1463           case PT_WORKGRP:
1464           case PT_COMP:
1465           case PT_NETWORK:
1466           case PT_SHARE:
1467             return (LPSTR)&(pidldata->u.network.szNames);
1468         }
1469         return NULL;
1470 }
1471
1472 /**************************************************************************
1473  *  _ILGetSTextPointer()
1474  * gets a pointer to the short filename string stored in the pidl
1475  */
1476 LPSTR _ILGetSTextPointer(PIDLTYPE type, LPPIDLDATA pidldata)
1477 {/*     TRACE(pidl,"(type=%x data=%p)\n", type, pidldata);*/
1478
1479         if(!pidldata)
1480           return NULL;
1481
1482         switch (type)
1483         {
1484           case PT_FOLDER:
1485           case PT_VALUE:
1486           case PT_IESPECIAL:
1487             return (LPSTR)(pidldata->u.file.szNames + strlen (pidldata->u.file.szNames) + 1);
1488
1489           case PT_WORKGRP:
1490             return (LPSTR)(pidldata->u.network.szNames + strlen (pidldata->u.network.szNames) + 1);
1491         }
1492         return NULL;
1493 }
1494
1495 /**************************************************************************
1496  * _ILGetGUIDPointer()
1497  *
1498  * returns reference to guid stored in some pidls
1499  */
1500 REFIID _ILGetGUIDPointer(LPCITEMIDLIST pidl)
1501 {
1502         LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1503
1504         if (pdata)
1505         {
1506           switch (pdata->type)
1507           {
1508             case PT_SPECIAL:
1509             case PT_MYCOMP:
1510               return (REFIID) &(pdata->u.mycomp.guid);
1511           }
1512         }
1513         return NULL;
1514 }
1515
1516 /*************************************************************************
1517  * _ILGetFileDateTime
1518  *
1519  * Given the ItemIdList, get the FileTime
1520  *
1521  * PARAMS
1522  *      pidl        [I] The ItemIDList
1523  *      pFt         [I] the resulted FILETIME of the file
1524  *
1525  * RETURNS
1526  *     True if Successful
1527  *
1528  * NOTES
1529  *     
1530  */
1531 BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt)
1532 {
1533     LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1534
1535     switch (pdata->type)
1536     { 
1537         case PT_FOLDER:
1538             DosDateTimeToFileTime(pdata->u.folder.uFileDate, pdata->u.folder.uFileTime, pFt);
1539             break;          
1540         case PT_VALUE:
1541             DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt);
1542             break;
1543         default:
1544             return FALSE;
1545     }
1546     return TRUE;
1547 }
1548
1549 BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1550 {       
1551         FILETIME ft;
1552         SYSTEMTIME time;
1553
1554         if (! _ILGetFileDateTime( pidl, &ft )) return FALSE;
1555         
1556         FileTimeToSystemTime (&ft, &time);
1557         return GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL,  pOut, uOutSize);
1558 }
1559
1560 /*************************************************************************
1561  * _ILGetFileSize
1562  *
1563  * Given the ItemIdList, get the FileSize
1564  *
1565  * PARAMS
1566  *      pidl    [I] The ItemIDList
1567  *      pOut    [I] The buffer to save the result
1568  *      uOutsize [I] The size of the buffer
1569  *
1570  * RETURNS
1571  *     The FileSize
1572  *
1573  * NOTES
1574  *      pOut can be null when no string is needed
1575  *     
1576  */
1577 DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1578 {
1579         LPPIDLDATA pdata =_ILGetDataPointer(pidl);
1580         DWORD dwSize;
1581         
1582         switch (pdata->type)
1583         {
1584           case PT_VALUE:
1585             dwSize = pdata->u.file.dwFileSize;
1586             if (pOut) StrFormatByteSizeA(dwSize, pOut, uOutSize);
1587             return dwSize;
1588         }
1589         if (pOut) *pOut = 0x00;
1590         return 0;
1591 }
1592
1593 BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1594 {
1595         char szTemp[MAX_PATH];
1596         const char * pPoint;
1597         LPITEMIDLIST  pidlTemp=pidl;
1598         
1599         TRACE_(pidl)("pidl=%p\n",pidl);
1600
1601         if (!pidl) return FALSE;
1602         
1603         pidlTemp = ILFindLastID(pidl);
1604         
1605         if (!_ILIsValue(pidlTemp)) return FALSE;
1606         if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH)) return FALSE;
1607
1608         pPoint = PathFindExtensionA(szTemp);
1609
1610         if (! *pPoint) return FALSE;
1611
1612         pPoint++;
1613         lstrcpynA(pOut, pPoint, uOutSize);
1614         TRACE_(pidl)("%s\n",pOut);
1615
1616         return TRUE;
1617 }
1618
1619 /*************************************************************************
1620  * _ILGetFileType
1621  *
1622  * Given the ItemIdList, get the file type description
1623  *
1624  * PARAMS
1625  *      pidl        [I] The ItemIDList (simple)
1626  *      pOut        [I] The buffer to save the result
1627  *      uOutsize    [I] The size of the buffer
1628  *
1629  * RETURNS
1630  *      nothing
1631  *
1632  * NOTES
1633  *      This function copies as much as possible into the buffer. 
1634  */
1635 void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1636 {
1637         if(_ILIsValue(pidl))
1638         {
1639           char sTemp[64];
1640           if(uOutSize > 0)
1641           {
1642             pOut[0] = 0;
1643           }
1644           if (_ILGetExtension (pidl, sTemp, 64))
1645           {
1646             if (!( HCR_MapTypeToValue(sTemp, sTemp, 64, TRUE)
1647                 && HCR_MapTypeToValue(sTemp, pOut, uOutSize, FALSE )))
1648             {
1649               lstrcpynA (pOut, sTemp, uOutSize - 6);
1650               strcat (pOut, "-file");
1651             }
1652           }
1653         }
1654         else
1655         {
1656           lstrcpynA(pOut, "Folder", uOutSize);
1657         }
1658 }
1659
1660 /*************************************************************************
1661  * _ILGetAttributeStr
1662  *
1663  * Given the ItemIdList, get the Attrib string format
1664  *
1665  * PARAMS
1666  *      pidl        [I] The ItemIDList
1667  *      pOut        [I] The buffer to save the result
1668  *      uOutsize    [I] The size of the Buffer
1669  *
1670  * RETURNS
1671  *     True if successful
1672  *
1673  * NOTES
1674  *     
1675  */
1676 BOOL _ILGetAttributeStr(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
1677 {
1678     LPPIDLDATA pData =_ILGetDataPointer(pidl);
1679     WORD wAttrib;
1680     int i;
1681
1682     /* Need At Least 6 characters to represent the Attrib String */
1683     if(uOutSize < 6) 
1684     {
1685         return FALSE;
1686     }
1687     switch(pData->type)
1688     {
1689         case PT_FOLDER:
1690             wAttrib = pData->u.folder.uFileAttribs;
1691             break;
1692         case PT_VALUE:
1693             wAttrib = pData->u.file.uFileAttribs;
1694             break;
1695         default:
1696             return FALSE;
1697     }
1698     i=0;
1699     if(wAttrib & FILE_ATTRIBUTE_READONLY)
1700     {
1701         pOut[i++] = 'R';
1702     }
1703     if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
1704     {
1705         pOut[i++] = 'H';
1706     }
1707     if(wAttrib & FILE_ATTRIBUTE_SYSTEM)
1708     {
1709         pOut[i++] = 'S';
1710     }
1711     if(wAttrib & FILE_ATTRIBUTE_ARCHIVE)
1712     {
1713         pOut[i++] = 'A';
1714     }
1715     if(wAttrib & FILE_ATTRIBUTE_COMPRESSED)
1716     {
1717         pOut[i++] = 'C';
1718     }
1719     pOut[i] = 0x00;
1720     return TRUE;
1721 }
1722