source: trunk/src/shell32/pidl.c

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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