New structures DVASPECT, TYMED, IDLList.
[wine/testsucceed.git] / dlls / shell32 / pidl.c
blob9645a2ffdec0d5703e32b92e92953f7ead9aa140
1 /*
2 * pidl Handling
4 * Copyright 1998 Juergen Schmied
6 * NOTES
7 * a pidl == NULL means desktop and is legal
9 */
11 #include <ctype.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "ole.h"
15 #include "ole2.h"
16 #include "debug.h"
17 #include "compobj.h"
18 #include "interfaces.h"
19 #include "shlobj.h"
20 #include "shell.h"
21 #include "winerror.h"
22 #include "winnls.h"
23 #include "winproc.h"
24 #include "commctrl.h"
25 #include "shell32_main.h"
27 #include "pidl.h"
29 void pdump (LPCITEMIDLIST pidl)
30 { DWORD type;
31 CHAR * szData;
32 LPITEMIDLIST pidltemp = pidl;
33 if (! pidltemp)
34 { TRACE(pidl,"-------- pidl = NULL (Root)\n");
35 return;
37 TRACE(pidl,"-------- pidl=%p \n", pidl);
38 if (pidltemp->mkid.cb)
39 { do
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);
47 return;
49 else
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);
57 strcpy(path,"e:\\");
58 return TRUE;
60 /*************************************************************************
61 * ILFindLastID [SHELL32.16]
63 LPITEMIDLIST WINAPI ILFindLastID(LPITEMIDLIST pidl)
64 { LPITEMIDLIST pidlLast = NULL;
66 TRACE(pidl,"(pidl=%p)\n",pidl);
68 if(pidl)
69 { while(pidl->mkid.cb)
70 { pidlLast = (LPITEMIDLIST)pidl;
71 pidl = ILGetNext(pidl);
74 return pidlLast;
76 /*************************************************************************
77 * ILRemoveLastID [SHELL32.17]
78 * NOTES
79 * Removes the last item
81 BOOL32 WINAPI ILRemoveLastID(LPCITEMIDLIST pidl)
82 { TRACE(shell,"pidl=%p\n",pidl);
83 if (!pidl || !pidl->mkid.cb)
84 return 0;
85 ILFindLastID(pidl)->mkid.cb = 0;
86 return 1;
89 /*************************************************************************
90 * ILClone [SHELL32.18]
92 * NOTES
93 * dupicate an idlist
95 LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl)
96 { DWORD len;
97 LPITEMIDLIST newpidl;
99 if (!pidl)
100 return NULL;
102 len = ILGetSize(pidl);
103 newpidl = (LPITEMIDLIST)SHAlloc(len);
104 if (newpidl)
105 memcpy(newpidl,pidl,len);
107 TRACE(pidl,"pidl=%p newpidl=%p\n",pidl, newpidl);
108 pdump(pidl);
110 return newpidl;
112 /*************************************************************************
113 * ILCloneFirst [SHELL32.19]
115 * NOTES
116 * duplicates the first idlist of a complex pidl
118 LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl)
119 { DWORD len;
120 LPITEMIDLIST newpidl=NULL;
122 if (pidl)
123 { len = pidl->mkid.cb;
124 newpidl = (LPITEMIDLIST) SHAlloc (len+2);
125 if (newpidl)
126 { memcpy(newpidl,pidl,len);
127 ILGetNext(newpidl)->mkid.cb = 0x00;
130 TRACE(pidl,"pidl=%p newpidl=%p\n",pidl, newpidl);
132 return newpidl;
134 /*************************************************************************
135 * ILIsEqual [SHELL32.21]
138 BOOL32 WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
139 { FIXME(pidl,"pidl1=%p pidl2=%p stub\n",pidl1, pidl2);
140 pdump (pidl1);
141 pdump (pidl2);
142 return FALSE;
144 /*************************************************************************
145 * ILFindChild [SHELL32.24]
148 DWORD WINAPI ILFindChild(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
149 { FIXME(pidl,"%p %p stub\n",pidl1,pidl2);
150 pdump (pidl1);
151 pdump (pidl2);
152 return 0;
155 /*************************************************************************
156 * ILCombine [SHELL32.25]
158 * NOTES
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)
164 { DWORD len1,len2;
165 LPITEMIDLIST pidlNew;
167 TRACE(pidl,"pidl=%p pidl=%p\n",pidl1,pidl2);
169 if(!pidl1 && !pidl2)
170 { return NULL;
173 pdump (pidl1);
174 pdump (pidl2);
176 if(!pidl1)
177 { pidlNew = ILClone(pidl2);
178 return pidlNew;
181 if(!pidl2)
182 { pidlNew = ILClone(pidl1);
183 return pidlNew;
186 len1 = ILGetSize(pidl1)-2;
187 len2 = ILGetSize(pidl2);
188 pidlNew = SHAlloc(len1+len2);
190 if (pidlNew)
191 { memcpy(pidlNew,pidl1,len1);
192 memcpy(((BYTE *)pidlNew)+len1,pidl2,len2);
195 /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
196 return pidlNew;
198 /*************************************************************************
199 * SHLogILFromFSIL [SHELL32.95]
201 * NOTES
202 * might be the prepending of MyComputer to a filesystem pidl (?)
204 LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
205 { FIXME(pidl,"(pidl=%p)\n",pidl);
206 pdump(pidl);
207 return ILClone(pidl);
210 /*************************************************************************
211 * ILGetSize [SHELL32.152]
212 * gets the byte size of an idlist including zero terminator (pidl)
214 * PARAMETERS
215 * pidl ITEMIDLIST
217 * RETURNS
218 * size of pidl
220 * NOTES
221 * exported by ordinal
223 DWORD WINAPI ILGetSize(LPITEMIDLIST pidl)
224 { LPSHITEMID si = &(pidl->mkid);
225 DWORD len=0;
227 if (pidl)
228 { while (si->cb)
229 { len += si->cb;
230 si = (LPSHITEMID)(((LPBYTE)si)+si->cb);
232 len += 2;
234 TRACE(pidl,"pidl=%p size=%lu\n",pidl, len);
235 return len;
237 /*************************************************************************
238 * ILGetNext [SHELL32.153]
239 * gets the next simple pidl of a complex pidl
241 * PARAMETERS
242 * pidl ITEMIDLIST
244 * RETURNS
245 * pointer to next element
248 LPITEMIDLIST WINAPI ILGetNext(LPITEMIDLIST pidl)
249 { LPITEMIDLIST nextpidl;
251 TRACE(pidl,"(pidl=%p)\n",pidl);
252 if(pidl)
253 { nextpidl = (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
254 return nextpidl;
256 else
257 { return (NULL);
260 /*************************************************************************
261 * ILAppend [SHELL32.154]
263 * NOTES
264 * Adds the single item to the idlist indicated by pidl.
265 * if bEnd is 0, adds the item to the front of the list,
266 * otherwise adds the item to the end.
267 * Destroys the passed in idlist!
269 LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl,LPCITEMIDLIST item,BOOL32 bEnd)
270 { FIXME(pidl,"(pidl=%p,pidl=%p,%08u)stub\n",pidl,item,bEnd);
271 return NULL;
273 /*************************************************************************
274 * ILFree [SHELL32.155]
276 * NOTES
277 * free_check_ptr - frees memory (if not NULL)
278 * allocated by SHMalloc allocator
279 * exported by ordinal
281 DWORD WINAPI ILFree(LPVOID pidl)
282 { TRACE(pidl,"(pidl=0x%08lx)\n",(DWORD)pidl);
283 if (!pidl)
284 return 0;
285 return SHFree(pidl);
287 /*************************************************************************
288 * ILCreateFromPath [SHELL32.157]
291 LPITEMIDLIST WINAPI ILCreateFromPath(LPSTR path)
292 { LPSHELLFOLDER shellfolder;
293 LPITEMIDLIST pidlnew;
294 CHAR pszTemp[MAX_PATH*2];
295 LPWSTR lpszDisplayName = (LPWSTR)&pszTemp[0];
296 DWORD pchEaten;
298 TRACE(pidl,"(path=%s)\n",path);
300 LocalToWideChar32(lpszDisplayName, path, MAX_PATH);
302 if (SHGetDesktopFolder(&shellfolder)==S_OK)
303 { shellfolder->lpvtbl->fnParseDisplayName(shellfolder,0, NULL,lpszDisplayName,&pchEaten,&pidlnew,NULL);
304 shellfolder->lpvtbl->fnRelease(shellfolder);
306 return pidlnew;
309 /**************************************************************************
310 * internal functions
313 /**************************************************************************
314 * _ILCreateDesktop()
315 * _ILCreateMyComputer()
316 * _ILCreateDrive()
317 * _ILCreateFolder()
318 * _ILCreateValue()
320 LPITEMIDLIST WINAPI _ILCreateDesktop()
321 { TRACE(pidl,"()\n");
322 return _ILCreate(PT_DESKTOP, NULL, 0);
324 LPITEMIDLIST WINAPI _ILCreateMyComputer()
325 { TRACE(pidl,"()\n");
326 return _ILCreate(PT_MYCOMP, (void *)"My Computer", strlen ("My Computer")+1);
328 LPITEMIDLIST WINAPI _ILCreateDrive( LPCSTR lpszNew)
329 { char sTemp[4];
330 strncpy (sTemp,lpszNew,4);
331 sTemp[2]='\\';
332 sTemp[3]=0x00;
333 TRACE(pidl,"(%s)\n",sTemp);
334 return _ILCreate(PT_DRIVE,(LPVOID)&sTemp[0],4);
336 LPITEMIDLIST WINAPI _ILCreateFolder( LPCSTR lpszNew)
337 { TRACE(pidl,"(%s)\n",lpszNew);
338 return _ILCreate(PT_FOLDER, (LPVOID)lpszNew, strlen(lpszNew)+1);
340 LPITEMIDLIST WINAPI _ILCreateValue(LPCSTR lpszNew)
341 { TRACE(pidl,"(%s)\n",lpszNew);
342 return _ILCreate(PT_VALUE, (LPVOID)lpszNew, strlen(lpszNew)+1);
345 /**************************************************************************
346 * _ILGetDrive()
348 * FIXME: quick hack
350 BOOL32 WINAPI _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT16 uSize)
351 { LPITEMIDLIST pidlTemp=NULL;
353 TRACE(pidl,"(%p,%p,%u)\n",pidl,pOut,uSize);
354 if(_ILIsMyComputer(pidl))
355 { pidlTemp = ILGetNext(pidl);
357 else if (pidlTemp && _ILIsDrive(pidlTemp))
358 { return (BOOL32)_ILGetData(PT_DRIVE, pidlTemp, (LPVOID)pOut, uSize);
360 return FALSE;
362 /**************************************************************************
363 * _ILGetItemText()
364 * Gets the text for only this item
366 DWORD WINAPI _ILGetItemText(LPCITEMIDLIST pidl, LPSTR lpszText, UINT16 uSize)
367 { TRACE(pidl,"(pidl=%p %p %x)\n",pidl,lpszText,uSize);
368 if (_ILIsMyComputer(pidl))
369 { return _ILGetData(PT_MYCOMP, pidl, (LPVOID)lpszText, uSize);
371 if (_ILIsDrive(pidl))
372 { return _ILGetData(PT_DRIVE, pidl, (LPVOID)lpszText, uSize);
374 if (_ILIsFolder (pidl))
375 { return _ILGetData(PT_FOLDER, pidl, (LPVOID)lpszText, uSize);
377 return _ILGetData(PT_VALUE, pidl, (LPVOID)lpszText, uSize);
379 /**************************************************************************
380 * _ILIsDesktop()
381 * _ILIsDrive()
382 * _ILIsFolder()
383 * _ILIsValue()
385 BOOL32 WINAPI _ILIsDesktop(LPCITEMIDLIST pidl)
386 { TRACE(pidl,"(%p)\n",pidl);
388 if (! pidl)
389 return TRUE;
391 return ( pidl->mkid.cb == 0x00 );
394 BOOL32 WINAPI _ILIsMyComputer(LPCITEMIDLIST pidl)
395 { LPPIDLDATA pData;
396 TRACE(pidl,"(%p)\n",pidl);
398 if (! pidl)
399 return FALSE;
401 pData = _ILGetDataPointer(pidl);
402 return (PT_MYCOMP == pData->type);
405 BOOL32 WINAPI _ILIsDrive(LPCITEMIDLIST pidl)
406 { LPPIDLDATA pData;
407 TRACE(pidl,"(%p)\n",pidl);
409 if (! pidl)
410 return FALSE;
412 pData = _ILGetDataPointer(pidl);
413 return (PT_DRIVE == pData->type);
416 BOOL32 WINAPI _ILIsFolder(LPCITEMIDLIST pidl)
417 { LPPIDLDATA pData;
418 TRACE(pidl,"(%p)\n",pidl);
420 if (! pidl)
421 return FALSE;
423 pData = _ILGetDataPointer(pidl);
424 return (PT_FOLDER == pData->type);
427 BOOL32 WINAPI _ILIsValue(LPCITEMIDLIST pidl)
428 { LPPIDLDATA pData;
429 TRACE(pidl,"(%p)\n",pidl);
431 if (! pidl)
432 return FALSE;
434 pData = _ILGetDataPointer(pidl);
435 return (PT_VALUE == pData->type);
437 /**************************************************************************
438 * _ILHasFolders()
439 * fixme: quick hack
441 BOOL32 WINAPI _ILHasFolders( LPSTR pszPath, LPCITEMIDLIST pidl)
442 { BOOL32 bResult= FALSE;
443 WIN32_FIND_DATA32A stffile;
444 HANDLE32 hFile;
446 TRACE(pidl,"%p %p\n", pszPath, pidl);
448 hFile = FindFirstFile32A(pszPath,&stffile);
450 { if (! (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
451 { bResult= TRUE;
453 } while( FindNextFile32A(hFile,&stffile));
454 FindClose32 (hFile);
456 return bResult;
459 /**************************************************************************
460 * _ILGetFolderText()
461 * Creates a Path string from a PIDL, filtering out the special Folders
463 DWORD WINAPI _ILGetFolderText(LPCITEMIDLIST pidl,LPSTR lpszPath, DWORD dwSize)
464 { LPITEMIDLIST pidlTemp;
465 DWORD dwCopied = 0;
466 LPSTR pText;
468 TRACE(pidl,"(%p path=%p)\n",pidl, lpszPath);
470 if(!pidl)
471 { return 0;
474 if(_ILIsMyComputer(pidl))
475 { pidlTemp = ILGetNext(pidl);
476 TRACE(pidl,"-- skip My Computer\n");
478 else
479 { pidlTemp = (LPITEMIDLIST)pidl;
482 //if this is NULL, return the required size of the buffer
483 if(!lpszPath)
484 { while(pidlTemp->mkid.cb)
485 { LPPIDLDATA pData = _ILGetDataPointer(pidlTemp);
486 pText = _ILGetTextPointer(pData->type,pData);
488 /*add the length of this item plus one for the backslash
489 fixme: is one to much, drive has its own backslash*/
490 dwCopied += strlen(pText) + 1;
491 pidlTemp = ILGetNext(pidlTemp);
494 //add one for the NULL terminator
495 TRACE(pidl,"-- (size=%lu)\n",dwCopied);
496 return dwCopied + 1;
499 *lpszPath = 0;
501 while(pidlTemp->mkid.cb && (dwCopied < dwSize))
502 { LPPIDLDATA pData = _ILGetDataPointer(pidlTemp);
504 //if this item is a value, then skip it and finish
505 if(PT_VALUE == pData->type)
506 { break;
508 pText = _ILGetTextPointer(pData->type,pData);
509 strcat(lpszPath, pText);
510 PathAddBackslash(lpszPath);
511 dwCopied += strlen(pText) + 1;
512 pidlTemp = ILGetNext(pidlTemp);
514 TRACE(pidl,"-- (size=%lu,%s)\n",dwCopied,lpszPath);
517 //remove the last backslash if necessary
518 if(dwCopied)
519 { if(*(lpszPath + strlen(lpszPath) - 1) == '\\')
520 { *(lpszPath + strlen(lpszPath) - 1) = 0;
521 dwCopied--;
524 TRACE(pidl,"-- (path=%s)\n",lpszPath);
525 return dwCopied;
529 /**************************************************************************
530 * _ILGetValueText()
531 * Gets the text for the last item in the list
533 DWORD WINAPI _ILGetValueText(
534 LPCITEMIDLIST pidl, LPSTR lpszValue, DWORD dwSize)
535 { LPITEMIDLIST pidlTemp=pidl;
536 CHAR szText[MAX_PATH];
538 TRACE(pidl,"(pidl=%p %p 0x%08lx)\n",pidl,lpszValue,dwSize);
540 if(!pidl)
541 { return 0;
544 while(pidlTemp->mkid.cb && !_ILIsValue(pidlTemp))
545 { pidlTemp = ILGetNext(pidlTemp);
548 if(!pidlTemp->mkid.cb)
549 { return 0;
552 _ILGetItemText( pidlTemp, szText, sizeof(szText));
554 if(!lpszValue)
555 { return strlen(szText) + 1;
557 strcpy(lpszValue, szText);
558 TRACE(pidl,"-- (pidl=%p %p=%s 0x%08lx)\n",pidl,lpszValue,lpszValue,dwSize);
559 return strlen(lpszValue);
561 /**************************************************************************
562 * _ILGetDataText()
563 * NOTES
564 * used from ShellView
566 DWORD WINAPI _ILGetDataText( LPCITEMIDLIST pidlPath, LPCITEMIDLIST pidlValue, LPSTR lpszOut, DWORD dwOutSize)
567 { LPSTR lpszFolder,
568 lpszValueName;
569 DWORD dwNameSize;
571 FIXME(pidl,"(pidl=%p pidl=%p) stub\n",pidlPath,pidlValue);
573 if(!lpszOut || !pidlPath || !pidlValue)
574 { return FALSE;
577 /* fixme: get the driveletter*/
579 //assemble the Folder string
580 dwNameSize = _ILGetFolderText(pidlPath, NULL, 0);
581 lpszFolder = (LPSTR)HeapAlloc(GetProcessHeap(),0,dwNameSize);
582 if(!lpszFolder)
583 { return FALSE;
585 _ILGetFolderText(pidlPath, lpszFolder, dwNameSize);
587 //assemble the value name
588 dwNameSize = _ILGetValueText(pidlValue, NULL, 0);
589 lpszValueName = (LPSTR)HeapAlloc(GetProcessHeap(),0,dwNameSize);
590 if(!lpszValueName)
591 { HeapFree(GetProcessHeap(),0,lpszFolder);
592 return FALSE;
594 _ILGetValueText(pidlValue, lpszValueName, dwNameSize);
596 /* fixme: we've got the path now do something with it*/
598 HeapFree(GetProcessHeap(),0,lpszFolder);
599 HeapFree(GetProcessHeap(),0,lpszValueName);
601 TRACE(pidl,"-- (%p=%s 0x%08lx)\n",lpszOut,lpszOut,dwOutSize);
603 return TRUE;
606 /**************************************************************************
607 * _ILGetPidlPath()
608 * Create a string that includes the Drive name, the folder text and
609 * the value text.
611 DWORD WINAPI _ILGetPidlPath( LPCITEMIDLIST pidl, LPSTR lpszOut, DWORD dwOutSize)
612 { LPSTR lpszTemp;
613 WORD len;
615 TRACE(pidl,"(%p,%lu)\n",lpszOut,dwOutSize);
617 if(!lpszOut)
618 { return 0;
621 *lpszOut = 0;
622 lpszTemp = lpszOut;
624 dwOutSize -= _ILGetFolderText(pidl, lpszTemp, dwOutSize);
626 //add a backslash if necessary
627 len = strlen(lpszTemp);
628 if (len && lpszTemp[len-1]!='\\')
629 { lpszTemp[len+0]='\\';
630 lpszTemp[len+1]='\0';
631 dwOutSize--;
634 lpszTemp = lpszOut + strlen(lpszOut);
636 //add the value string
637 _ILGetValueText(pidl, lpszTemp, dwOutSize);
639 //remove the last backslash if necessary
640 if(*(lpszOut + strlen(lpszOut) - 1) == '\\')
641 { *(lpszOut + strlen(lpszOut) - 1) = 0;
644 TRACE(pidl,"-- (%p=%s,%lu)\n",lpszOut,lpszOut,dwOutSize);
646 return strlen(lpszOut);
650 /**************************************************************************
651 * _ILCreate()
652 * Creates a new PIDL
653 * type = PT_DESKTOP | PT_DRIVE | PT_FOLDER | PT_VALUE
654 * pIn = data
655 * uInSize = size of data
658 LPITEMIDLIST WINAPI _ILCreate(PIDLTYPE type, LPVOID pIn, UINT16 uInSize)
659 { LPITEMIDLIST pidlOut=NULL;
660 UINT16 uSize;
661 LPITEMIDLIST pidlTemp=NULL;
662 LPPIDLDATA pData;
663 LPSTR pszDest;
665 TRACE(pidl,"(%x %p %x)\n",type,pIn,uInSize);
667 if ( type == PT_DESKTOP)
668 { pidlOut = SHAlloc(2);
669 pidlOut->mkid.cb=0x0000;
670 return pidlOut;
673 if (! pIn)
674 { return NULL;
677 /* the sizes of: cb(2), pidldata-1, szText+1, next cb(2) */
678 switch (type)
679 { case PT_DRIVE:
680 uSize = 4 + 9;
681 break;
682 default:
683 uSize = 4 + (sizeof(PIDLDATA)) + uInSize;
685 pidlOut = SHAlloc(uSize);
686 pidlTemp = pidlOut;
687 if(pidlOut)
688 { pidlTemp->mkid.cb = uSize - 2;
689 pData =_ILGetDataPointer(pidlTemp);
690 pszDest = _ILGetTextPointer(type, pData);
691 pData->type = type;
692 switch(type)
693 { case PT_MYCOMP:
694 memcpy(pszDest, pIn, uInSize);
695 TRACE(pidl,"- create My Computer: %s\n",debugstr_a(pszDest));
696 break;
697 case PT_DRIVE:
698 memcpy(pszDest, pIn, uInSize);
699 TRACE(pidl,"- create Drive: %s\n",debugstr_a(pszDest));
700 break;
701 case PT_FOLDER:
702 case PT_VALUE:
703 memcpy(pszDest, pIn, uInSize);
704 TRACE(pidl,"- create Value: %s\n",debugstr_a(pszDest));
705 break;
706 default:
707 FIXME(pidl,"-- wrong argument\n");
708 break;
711 pidlTemp = ILGetNext(pidlTemp);
712 pidlTemp->mkid.cb = 0x00;
714 TRACE(pidl,"-- (pidl=%p, size=%u)\n",pidlOut,uSize-2);
715 return pidlOut;
717 /**************************************************************************
718 * _ILGetData(PIDLTYPE, LPCITEMIDLIST, LPVOID, UINT16)
720 DWORD WINAPI _ILGetData(PIDLTYPE type, LPCITEMIDLIST pidl, LPVOID pOut, UINT16 uOutSize)
721 { LPPIDLDATA pData;
722 DWORD dwReturn=0;
723 LPSTR pszSrc;
725 TRACE(pidl,"(%x %p %p %x)\n",type,pidl,pOut,uOutSize);
727 if(!pidl)
728 { return 0;
731 *(LPSTR)pOut = 0;
733 pData = _ILGetDataPointer(pidl);
734 if ( pData->type != type)
735 { ERR(pidl,"-- wrong type\n");
736 return 0;
738 pszSrc = _ILGetTextPointer(pData->type, pData);
740 switch(type)
741 { case PT_MYCOMP:
742 if(uOutSize < 1)
743 return 0;
744 strncpy((LPSTR)pOut, "My Computer", uOutSize);
745 dwReturn = strlen((LPSTR)pOut);
746 break;
748 case PT_DRIVE:
749 if(uOutSize < 1)
750 return 0;
751 strncpy((LPSTR)pOut, pszSrc, uOutSize);
752 dwReturn = strlen((LPSTR)pOut);
753 break;
755 case PT_FOLDER:
756 case PT_VALUE:
757 strncpy((LPSTR)pOut, pszSrc, uOutSize);
758 dwReturn = strlen((LPSTR)pOut);
759 break;
760 default:
761 ERR(pidl,"-- unknown type\n");
762 break;
764 TRACE(pidl,"-- (%p=%s 0x%08lx)\n",pOut,(char*)pOut,dwReturn);
765 return dwReturn;
769 /**************************************************************************
770 * _ILGetDataPointer()
772 LPPIDLDATA WINAPI _ILGetDataPointer(LPITEMIDLIST pidl)
773 { if(!pidl)
774 { return NULL;
776 /* TRACE(pidl,"(%p)\n", pidl);*/
777 return (LPPIDLDATA)(&pidl->mkid.abID);
779 /**************************************************************************
780 * _ILGetTextPointer()
781 * gets a pointer to the string stored in the pidl
783 LPSTR WINAPI _ILGetTextPointer(PIDLTYPE type, LPPIDLDATA pidldata)
784 {/* TRACE(pidl,"(type=%x data=%p)\n", type, pidldata);*/
786 if(!pidldata)
787 { return NULL;
789 switch (type)
790 { case PT_DRIVE:
791 return (LPSTR)&(pidldata->u.drive.szDriveName);
792 case PT_MYCOMP:
793 case PT_FOLDER:
794 case PT_VALUE:
795 return (LPSTR)&(pidldata->u.file.szText);
797 return NULL;
800 /**************************************************************************
801 * IDLList "Item ID List List"
804 static UINT32 IDLList_GetState(LPIDLLIST this);
805 static LPITEMIDLIST IDLList_GetElement(LPIDLLIST this, UINT32 nIndex);
806 static UINT32 IDLList_GetCount(LPIDLLIST this);
807 static BOOL32 IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl);
808 static BOOL32 IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT32 cidl);
809 static BOOL32 IDLList_InitList(LPIDLLIST this);
810 static void IDLList_CleanList(LPIDLLIST this);
812 static IDLList_VTable idllvt =
813 { IDLList_GetState,
814 IDLList_GetElement,
815 IDLList_GetCount,
816 IDLList_StoreItem,
817 IDLList_AddItems,
818 IDLList_InitList,
819 IDLList_CleanList
822 LPIDLLIST IDLList_Constructor (UINT32 uStep)
823 { LPIDLLIST lpidll;
824 if (!(lpidll = (LPIDLLIST)HeapAlloc(GetProcessHeap(),0,sizeof(IDLList))))
825 return NULL;
827 lpidll->lpvtbl=&idllvt;
828 lpidll->uStep=uStep;
829 lpidll->dpa=NULL;
831 TRACE (shell,"(%p)\n",lpidll);
832 return lpidll;
834 void IDLList_Destructor(LPIDLLIST this)
835 { TRACE (shell,"(%p)\n",this);
836 IDLList_CleanList(this);
839 static UINT32 IDLList_GetState(LPIDLLIST this)
840 { TRACE (shell,"(%p)->(uStep=%u dpa=%p)\n",this, this->uStep, this->dpa);
842 if (this->uStep == 0)
843 { if (this->dpa)
844 return(State_Init);
845 return(State_OutOfMem);
847 return(State_UnInit);
849 static LPITEMIDLIST IDLList_GetElement(LPIDLLIST this, UINT32 nIndex)
850 { TRACE (shell,"(%p)->(index=%u)\n",this, nIndex);
851 return((LPITEMIDLIST)DPA_GetPtr(this->dpa, nIndex));
853 static UINT32 IDLList_GetCount(LPIDLLIST this)
854 { TRACE (shell,"(%p)\n",this);
855 return(IDLList_GetState(this)==State_Init ? DPA_GetPtrCount(this->dpa) : 0);
857 static BOOL32 IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl)
858 { TRACE (shell,"(%p)->(pidl=%p)\n",this, pidl);
859 if (pidl)
860 { if (IDLList_InitList(this) && DPA_InsertPtr(this->dpa, 0x7fff, (LPSTR)pidl)>=0)
861 return(TRUE);
862 ILFree(pidl);
864 IDLList_CleanList(this);
865 return(FALSE);
867 static BOOL32 IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT32 cidl)
868 { INT32 i;
869 TRACE (shell,"(%p)->(apidl=%p cidl=%u)\n",this, apidl, cidl);
871 for (i=0; i<cidl; ++i)
872 { if (!IDLList_StoreItem(this, ILClone((LPCITEMIDLIST)apidl[i])))
873 return(FALSE);
875 return(TRUE);
877 static BOOL32 IDLList_InitList(LPIDLLIST this)
878 { TRACE (shell,"(%p)\n",this);
879 switch (IDLList_GetState(this))
880 { case State_Init:
881 return(TRUE);
883 case State_OutOfMem:
884 return(FALSE);
886 case State_UnInit:
887 default:
888 this->dpa = DPA_Create(this->uStep);
889 this->uStep = 0;
890 return(IDLList_InitList(this));
893 static void IDLList_CleanList(LPIDLLIST this)
894 { INT32 i;
895 TRACE (shell,"(%p)\n",this);
897 if (this->uStep != 0)
898 { this->dpa = NULL;
899 this->uStep = 0;
900 return;
903 if (!this->dpa)
904 { return;
907 for (i=DPA_GetPtrCount(this->dpa)-1; i>=0; --i)
908 { ILFree(IDLList_GetElement(this,i));
911 DPA_Destroy(this->dpa);
912 this->dpa=NULL;