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