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

Last change on this file since 4121 was 4121, checked in by sandervl, 25 years ago

complete merge with shell32 from wine 20000801

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