source: trunk/src/shell32/pidl.c@ 7904

Last change on this file since 7904 was 7904, checked in by sandervl, 24 years ago

extended logging added

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