4 * Copyright 1998 Juergen Schmied
7 * a pidl == NULL means desktop and is legal
18 #include "interfaces.h"
25 #include "shell32_main.h"
29 void pdump (LPCITEMIDLIST pidl
)
32 LPITEMIDLIST pidltemp
= pidl
;
34 { TRACE(pidl
,"-------- pidl = NULL (Root)\n");
37 TRACE(pidl
,"-------- pidl=%p \n", pidl
);
38 if (pidltemp
->mkid
.cb
)
40 { type
= _ILGetDataPointer(pidltemp
)->type
;
41 szData
= _ILGetTextPointer(type
, _ILGetDataPointer(pidltemp
));
43 TRACE(pidl
,"---- pidl=%p size=%u type=%lx %s\n",pidltemp
, pidltemp
->mkid
.cb
,type
,debugstr_a(szData
));
45 pidltemp
= ILGetNext(pidltemp
);
46 } while (pidltemp
->mkid
.cb
);
50 TRACE(pidl
,"empty pidl (Desktop)\n");
52 /*************************************************************************
53 * ILGetDisplayName [SHELL32.15]
55 BOOL32 WINAPI
ILGetDisplayName(LPCITEMIDLIST iil
,LPSTR path
)
56 { FIXME(pidl
,"(%p,%p),stub, return e:!\n",iil
,path
);
60 /*************************************************************************
61 * ILFindLastID [SHELL32.16]
63 LPITEMIDLIST WINAPI
ILFindLastID(LPITEMIDLIST pidl
)
64 { LPITEMIDLIST pidlLast
= NULL
;
66 TRACE(pidl
,"(pidl=%p)\n",pidl
);
69 { while(pidl
->mkid
.cb
)
70 { pidlLast
= (LPITEMIDLIST
)pidl
;
71 pidl
= ILGetNext(pidl
);
76 /*************************************************************************
77 * ILRemoveLastID [SHELL32.17]
79 * Removes the last item
81 BOOL32 WINAPI
ILRemoveLastID(LPCITEMIDLIST pidl
)
82 { TRACE(shell
,"pidl=%p\n",pidl
);
83 if (!pidl
|| !pidl
->mkid
.cb
)
85 ILFindLastID(pidl
)->mkid
.cb
= 0;
89 /*************************************************************************
90 * ILClone [SHELL32.18]
95 LPITEMIDLIST WINAPI
ILClone (LPCITEMIDLIST pidl
)
99 TRACE(pidl
,"%p\n",pidl
);
106 len
= ILGetSize(pidl
);
107 newpidl
= (LPITEMIDLIST
)SHAlloc(len
);
109 memcpy(newpidl
,pidl
,len
);
112 /*************************************************************************
113 * ILCloneFirst [SHELL32.19]
116 * duplicates the first idlist of a complex pidl
118 LPITEMIDLIST WINAPI
ILCloneFirst(LPCITEMIDLIST pidl
)
120 LPITEMIDLIST newpidl
=NULL
;
121 TRACE(pidl
,"pidl=%p\n",pidl
);
124 { len
= pidl
->mkid
.cb
;
125 newpidl
= (LPITEMIDLIST
) SHAlloc (len
+2);
127 { memcpy(newpidl
,pidl
,len
);
128 ILGetNext(newpidl
)->mkid
.cb
= 0x00;
134 /*************************************************************************
135 * ILIsEqual [SHELL32.21]
138 BOOL32 WINAPI
ILIsEqual(LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
139 { FIXME(pidl
,"pidl1=%p pidl2=%p stub\n",pidl1
, pidl2
);
144 /*************************************************************************
145 * ILFindChild [SHELL32.24]
148 DWORD WINAPI
ILFindChild(LPCITEMIDLIST pidl1
,LPCITEMIDLIST pidl2
)
149 { FIXME(pidl
,"%p %p stub\n",pidl1
,pidl2
);
155 /*************************************************************************
156 * ILCombine [SHELL32.25]
159 * Concatenates two complex idlists.
160 * The pidl is the first one, pidlsub the next one
161 * Does not destroy the passed in idlists!
163 LPITEMIDLIST WINAPI
ILCombine(LPCITEMIDLIST pidl1
,LPCITEMIDLIST pidl2
)
165 LPITEMIDLIST pidlNew
;
167 TRACE(pidl
,"pidl=%p pidl=%p\n",pidl1
,pidl2
);
177 { pidlNew
= ILClone(pidl2
);
182 { pidlNew
= ILClone(pidl1
);
186 len1
= ILGetSize(pidl1
)-2;
187 len2
= ILGetSize(pidl2
);
188 pidlNew
= SHAlloc(len1
+len2
);
191 { memcpy(pidlNew
,pidl1
,len1
);
192 memcpy(((BYTE
*)pidlNew
)+len1
,pidl2
,len2
);
195 /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
198 /*************************************************************************
199 * SHLogILFromFSIL [SHELL32.95]
202 * might be the prepending of MyComputer to a filesystem pidl (?)
204 LPITEMIDLIST WINAPI
SHLogILFromFSIL(LPITEMIDLIST pidl
)
205 { FIXME(pidl
,"(pidl=%p)\n",pidl
);
207 return ILClone(pidl
);
210 /*************************************************************************
211 * ILGetSize [SHELL32.152]
212 * gets the byte size of an idlist including zero terminator (pidl)
221 * exported by ordinal
223 DWORD WINAPI
ILGetSize(LPITEMIDLIST pidl
)
224 { LPSHITEMID si
= &(pidl
->mkid
);
227 /*TRACE(pidl,"pidl=%p\n",pidl);*/
232 si
= (LPSHITEMID
)(((LPBYTE
)si
)+si
->cb
);
236 /*TRACE(pidl,"-- size=%lu\n",len);*/
239 /*************************************************************************
240 * ILGetNext [SHELL32.153]
241 * gets the next simple pidl of a complex pidl
247 * pointer to next element
250 LPITEMIDLIST WINAPI
ILGetNext(LPITEMIDLIST pidl
)
251 { LPITEMIDLIST nextpidl
;
253 /* TRACE(pidl,"(pidl=%p)\n",pidl);*/
255 { nextpidl
= (LPITEMIDLIST
)(LPBYTE
)(((LPBYTE
)pidl
) + pidl
->mkid
.cb
);
262 /*************************************************************************
263 * ILAppend [SHELL32.154]
266 * Adds the single item to the idlist indicated by pidl.
267 * if bEnd is 0, adds the item to the front of the list,
268 * otherwise adds the item to the end.
269 * Destroys the passed in idlist!
271 LPITEMIDLIST WINAPI
ILAppend(LPITEMIDLIST pidl
,LPCITEMIDLIST item
,BOOL32 bEnd
)
272 { FIXME(pidl
,"(pidl=%p,pidl=%p,%08u)stub\n",pidl
,item
,bEnd
);
275 /*************************************************************************
276 * ILFree [SHELL32.155]
279 * free_check_ptr - frees memory (if not NULL)
280 * allocated by SHMalloc allocator
281 * exported by ordinal
283 DWORD WINAPI
ILFree(LPVOID pidl
)
284 { TRACE(pidl
,"(pidl=0x%08lx)\n",(DWORD
)pidl
);
289 /*************************************************************************
290 * ILCreateFromPath [SHELL32.157]
293 LPITEMIDLIST WINAPI
ILCreateFromPath(LPSTR path
)
294 { LPSHELLFOLDER shellfolder
;
295 LPITEMIDLIST pidlnew
;
296 CHAR pszTemp
[MAX_PATH
*2];
297 LPWSTR lpszDisplayName
= (LPWSTR
)&pszTemp
[0];
300 TRACE(pidl
,"(path=%s)\n",path
);
302 LocalToWideChar32(lpszDisplayName
, path
, MAX_PATH
);
304 if (SHGetDesktopFolder(&shellfolder
)==S_OK
)
305 { shellfolder
->lpvtbl
->fnParseDisplayName(shellfolder
,0, NULL
,lpszDisplayName
,&pchEaten
,&pidlnew
,NULL
);
306 shellfolder
->lpvtbl
->fnRelease(shellfolder
);
311 /**************************************************************************
315 /**************************************************************************
317 * _ILCreateMyComputer()
322 LPITEMIDLIST WINAPI
_ILCreateDesktop()
323 { TRACE(pidl
,"()\n");
324 return _ILCreate(PT_DESKTOP
, NULL
, 0);
326 LPITEMIDLIST WINAPI
_ILCreateMyComputer()
327 { TRACE(pidl
,"()\n");
328 return _ILCreate(PT_MYCOMP
, (void *)"My Computer", strlen ("My Computer")+1);
330 LPITEMIDLIST WINAPI
_ILCreateDrive( LPCSTR lpszNew
)
332 strncpy (sTemp
,lpszNew
,4);
335 TRACE(pidl
,"(%s)\n",sTemp
);
336 return _ILCreate(PT_DRIVE
,(LPVOID
)&sTemp
[0],4);
338 LPITEMIDLIST WINAPI
_ILCreateFolder( LPCSTR lpszNew
)
339 { TRACE(pidl
,"(%s)\n",lpszNew
);
340 return _ILCreate(PT_FOLDER
, (LPVOID
)lpszNew
, strlen(lpszNew
)+1);
342 LPITEMIDLIST WINAPI
_ILCreateValue(LPCSTR lpszNew
)
343 { TRACE(pidl
,"(%s)\n",lpszNew
);
344 return _ILCreate(PT_VALUE
, (LPVOID
)lpszNew
, strlen(lpszNew
)+1);
347 /**************************************************************************
352 BOOL32 WINAPI
_ILGetDrive(LPCITEMIDLIST pidl
,LPSTR pOut
, UINT16 uSize
)
353 { LPITEMIDLIST pidlTemp
=NULL
;
355 TRACE(pidl
,"(%p,%p,%u)\n",pidl
,pOut
,uSize
);
356 if(_ILIsMyComputer(pidl
))
357 { pidlTemp
= ILGetNext(pidl
);
359 else if (pidlTemp
&& _ILIsDrive(pidlTemp
))
360 { return (BOOL32
)_ILGetData(PT_DRIVE
, pidlTemp
, (LPVOID
)pOut
, uSize
);
364 /**************************************************************************
366 * Gets the text for only this item
368 DWORD WINAPI
_ILGetItemText(LPCITEMIDLIST pidl
, LPSTR lpszText
, UINT16 uSize
)
369 { TRACE(pidl
,"(pidl=%p %p %x)\n",pidl
,lpszText
,uSize
);
370 if (_ILIsMyComputer(pidl
))
371 { return _ILGetData(PT_MYCOMP
, pidl
, (LPVOID
)lpszText
, uSize
);
373 if (_ILIsDrive(pidl
))
374 { return _ILGetData(PT_DRIVE
, pidl
, (LPVOID
)lpszText
, uSize
);
376 if (_ILIsFolder (pidl
))
377 { return _ILGetData(PT_FOLDER
, pidl
, (LPVOID
)lpszText
, uSize
);
379 return _ILGetData(PT_VALUE
, pidl
, (LPVOID
)lpszText
, uSize
);
381 /**************************************************************************
387 BOOL32 WINAPI
_ILIsDesktop(LPCITEMIDLIST pidl
)
388 { TRACE(pidl
,"(%p)\n",pidl
);
393 return ( pidl
->mkid
.cb
== 0x00 );
396 BOOL32 WINAPI
_ILIsMyComputer(LPCITEMIDLIST pidl
)
398 TRACE(pidl
,"(%p)\n",pidl
);
403 pData
= _ILGetDataPointer(pidl
);
404 return (PT_MYCOMP
== pData
->type
);
407 BOOL32 WINAPI
_ILIsDrive(LPCITEMIDLIST pidl
)
409 TRACE(pidl
,"(%p)\n",pidl
);
414 pData
= _ILGetDataPointer(pidl
);
415 return (PT_DRIVE
== pData
->type
);
418 BOOL32 WINAPI
_ILIsFolder(LPCITEMIDLIST pidl
)
420 TRACE(pidl
,"(%p)\n",pidl
);
425 pData
= _ILGetDataPointer(pidl
);
426 return (PT_FOLDER
== pData
->type
);
429 BOOL32 WINAPI
_ILIsValue(LPCITEMIDLIST pidl
)
431 TRACE(pidl
,"(%p)\n",pidl
);
436 pData
= _ILGetDataPointer(pidl
);
437 return (PT_VALUE
== pData
->type
);
439 /**************************************************************************
443 BOOL32 WINAPI
_ILHasFolders( LPSTR pszPath
, LPCITEMIDLIST pidl
)
444 { BOOL32 bResult
= FALSE
;
445 WIN32_FIND_DATA32A stffile
;
448 TRACE(pidl
,"%p %p\n", pszPath
, pidl
);
450 hFile
= FindFirstFile32A(pszPath
,&stffile
);
452 { if (! (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) )
455 } while( FindNextFile32A(hFile
,&stffile
));
461 /**************************************************************************
463 * Creates a Path string from a PIDL, filtering out the special Folders
465 DWORD WINAPI
_ILGetFolderText(LPCITEMIDLIST pidl
,LPSTR lpszPath
, DWORD dwSize
)
466 { LPITEMIDLIST pidlTemp
;
470 TRACE(pidl
,"(%p)\n",pidl
);
476 if(_ILIsMyComputer(pidl
))
477 { pidlTemp
= ILGetNext(pidl
);
478 TRACE(pidl
,"-- skip My Computer\n");
481 { pidlTemp
= (LPITEMIDLIST
)pidl
;
484 //if this is NULL, return the required size of the buffer
486 { while(pidlTemp
->mkid
.cb
)
487 { LPPIDLDATA pData
= _ILGetDataPointer(pidlTemp
);
488 pText
= _ILGetTextPointer(pData
->type
,pData
);
490 /*add the length of this item plus one for the backslash
491 fixme: is one to much, drive has its own backslash*/
492 dwCopied
+= strlen(pText
) + 1;
493 pidlTemp
= ILGetNext(pidlTemp
);
496 //add one for the NULL terminator
497 TRACE(pidl
,"-- (size=%lu)\n",dwCopied
);
503 while(pidlTemp
->mkid
.cb
&& (dwCopied
< dwSize
))
504 { LPPIDLDATA pData
= _ILGetDataPointer(pidlTemp
);
506 //if this item is a value, then skip it and finish
507 if(PT_VALUE
== pData
->type
)
510 pText
= _ILGetTextPointer(pData
->type
,pData
);
511 strcat(lpszPath
, pText
);
512 PathAddBackslash(lpszPath
);
513 dwCopied
+= strlen(pText
) + 1;
514 pidlTemp
= ILGetNext(pidlTemp
);
516 TRACE(pidl
,"-- (size=%lu,%s)\n",dwCopied
,lpszPath
);
519 //remove the last backslash if necessary
521 { if(*(lpszPath
+ strlen(lpszPath
) - 1) == '\\')
522 { *(lpszPath
+ strlen(lpszPath
) - 1) = 0;
526 TRACE(pidl
,"-- (path=%s)\n",lpszPath
);
531 /**************************************************************************
533 * Gets the text for the last item in the list
535 DWORD WINAPI
_ILGetValueText(
536 LPCITEMIDLIST pidl
, LPSTR lpszValue
, DWORD dwSize
)
537 { LPITEMIDLIST pidlTemp
=pidl
;
538 CHAR szText
[MAX_PATH
];
540 TRACE(pidl
,"(pidl=%p %p 0x%08lx)\n",pidl
,lpszValue
,dwSize
);
546 while(pidlTemp
->mkid
.cb
&& !_ILIsValue(pidlTemp
))
547 { pidlTemp
= ILGetNext(pidlTemp
);
550 if(!pidlTemp
->mkid
.cb
)
554 _ILGetItemText( pidlTemp
, szText
, sizeof(szText
));
557 { return strlen(szText
) + 1;
559 strcpy(lpszValue
, szText
);
560 TRACE(pidl
,"-- (pidl=%p %p=%s 0x%08lx)\n",pidl
,lpszValue
,lpszValue
,dwSize
);
561 return strlen(lpszValue
);
563 /**************************************************************************
566 * used from ShellView
568 DWORD WINAPI
_ILGetDataText( LPCITEMIDLIST pidlPath
, LPCITEMIDLIST pidlValue
, LPSTR lpszOut
, DWORD dwOutSize
)
573 FIXME(pidl
,"(pidl=%p pidl=%p) stub\n",pidlPath
,pidlValue
);
575 if(!lpszOut
|| !pidlPath
|| !pidlValue
)
579 /* fixme: get the driveletter*/
581 //assemble the Folder string
582 dwNameSize
= _ILGetFolderText(pidlPath
, NULL
, 0);
583 lpszFolder
= (LPSTR
)HeapAlloc(GetProcessHeap(),0,dwNameSize
);
587 _ILGetFolderText(pidlPath
, lpszFolder
, dwNameSize
);
589 //assemble the value name
590 dwNameSize
= _ILGetValueText(pidlValue
, NULL
, 0);
591 lpszValueName
= (LPSTR
)HeapAlloc(GetProcessHeap(),0,dwNameSize
);
593 { HeapFree(GetProcessHeap(),0,lpszFolder
);
596 _ILGetValueText(pidlValue
, lpszValueName
, dwNameSize
);
598 /* fixme: we've got the path now do something with it*/
600 HeapFree(GetProcessHeap(),0,lpszFolder
);
601 HeapFree(GetProcessHeap(),0,lpszValueName
);
603 TRACE(pidl
,"-- (%p=%s 0x%08lx)\n",lpszOut
,lpszOut
,dwOutSize
);
608 /**************************************************************************
610 * Create a string that includes the Drive name, the folder text and
613 DWORD WINAPI
_ILGetPidlPath( LPCITEMIDLIST pidl
, LPSTR lpszOut
, DWORD dwOutSize
)
617 TRACE(pidl
,"(%p,%lu)\n",lpszOut
,dwOutSize
);
626 dwOutSize
-= _ILGetFolderText(pidl
, lpszTemp
, dwOutSize
);
628 //add a backslash if necessary
629 len
= strlen(lpszTemp
);
630 if (len
&& lpszTemp
[len
-1]!='\\')
631 { lpszTemp
[len
+0]='\\';
632 lpszTemp
[len
+1]='\0';
636 lpszTemp
= lpszOut
+ strlen(lpszOut
);
638 //add the value string
639 _ILGetValueText(pidl
, lpszTemp
, dwOutSize
);
641 //remove the last backslash if necessary
642 if(*(lpszOut
+ strlen(lpszOut
) - 1) == '\\')
643 { *(lpszOut
+ strlen(lpszOut
) - 1) = 0;
646 TRACE(pidl
,"-- (%p=%s,%lu)\n",lpszOut
,lpszOut
,dwOutSize
);
648 return strlen(lpszOut
);
652 /**************************************************************************
655 * type = PT_DESKTOP | PT_DRIVE | PT_FOLDER | PT_VALUE
657 * uInSize = size of data
660 LPITEMIDLIST WINAPI
_ILCreate(PIDLTYPE type
, LPVOID pIn
, UINT16 uInSize
)
661 { LPITEMIDLIST pidlOut
=NULL
;
663 LPITEMIDLIST pidlTemp
=NULL
;
667 TRACE(pidl
,"(%x %p %x)\n",type
,pIn
,uInSize
);
669 if ( type
== PT_DESKTOP
)
670 { pidlOut
= SHAlloc(2);
671 pidlOut
->mkid
.cb
=0x0000;
679 /* the sizes of: cb(2), pidldata-1, szText+1, next cb(2) */
685 uSize
= 4 + (sizeof(PIDLDATA
)) + uInSize
;
687 pidlOut
= SHAlloc(uSize
);
690 { pidlTemp
->mkid
.cb
= uSize
- 2;
691 pData
=_ILGetDataPointer(pidlTemp
);
692 pszDest
= _ILGetTextPointer(type
, pData
);
696 memcpy(pszDest
, pIn
, uInSize
);
697 TRACE(pidl
,"- create My Computer: %s\n",debugstr_a(pszDest
));
700 memcpy(pszDest
, pIn
, uInSize
);
701 TRACE(pidl
,"- create Drive: %s\n",debugstr_a(pszDest
));
705 memcpy(pszDest
, pIn
, uInSize
);
706 TRACE(pidl
,"- create Value: %s\n",debugstr_a(pszDest
));
709 FIXME(pidl
,"-- wrong argument\n");
713 pidlTemp
= ILGetNext(pidlTemp
);
714 pidlTemp
->mkid
.cb
= 0x00;
716 TRACE(pidl
,"-- (pidl=%p, size=%u)\n",pidlOut
,uSize
-2);
719 /**************************************************************************
720 * _ILGetData(PIDLTYPE, LPCITEMIDLIST, LPVOID, UINT16)
722 DWORD WINAPI
_ILGetData(PIDLTYPE type
, LPCITEMIDLIST pidl
, LPVOID pOut
, UINT16 uOutSize
)
727 TRACE(pidl
,"(%x %p %p %x)\n",type
,pidl
,pOut
,uOutSize
);
735 pData
= _ILGetDataPointer(pidl
);
736 if ( pData
->type
!= type
)
737 { ERR(pidl
,"-- wrong type\n");
740 pszSrc
= _ILGetTextPointer(pData
->type
, pData
);
746 strncpy((LPSTR
)pOut
, "My Computer", uOutSize
);
747 dwReturn
= strlen((LPSTR
)pOut
);
753 strncpy((LPSTR
)pOut
, pszSrc
, uOutSize
);
754 dwReturn
= strlen((LPSTR
)pOut
);
759 strncpy((LPSTR
)pOut
, pszSrc
, uOutSize
);
760 dwReturn
= strlen((LPSTR
)pOut
);
763 ERR(pidl
,"-- unknown type\n");
766 TRACE(pidl
,"-- (%p=%s 0x%08lx)\n",pOut
,(char*)pOut
,dwReturn
);
771 /**************************************************************************
772 * _ILGetDataPointer()
774 LPPIDLDATA WINAPI
_ILGetDataPointer(LPITEMIDLIST pidl
)
778 /* TRACE(pidl,"(%p)\n", pidl);*/
779 return (LPPIDLDATA
)(&pidl
->mkid
.abID
);
781 /**************************************************************************
782 * _ILGetTextPointer()
783 * gets a pointer to the string stored in the pidl
785 LPSTR WINAPI
_ILGetTextPointer(PIDLTYPE type
, LPPIDLDATA pidldata
)
786 {/* TRACE(pidl,"(type=%x data=%p)\n", type, pidldata);*/
793 return (LPSTR
)&(pidldata
->u
.drive
.szDriveName
);
797 return (LPSTR
)&(pidldata
->u
.file
.szText
);