source: trunk/src/shell32/pidl.cpp@ 3243

Last change on this file since 3243 was 3243, checked in by cbratschi, 25 years ago

merged with Corel WINE 20000324

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