[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / wine / pidl.c
1 /*
2 * pidl Handling
3 *
4 * Copyright 1998 Juergen Schmied
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * NOTES
21 * a pidl == NULL means desktop and is legal
22 *
23 */
24
25 #include <wine/config.h>
26
27 #define WIN32_NO_STATUS
28 #define _INC_WINDOWS
29 #define COBJMACROS
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
32
33 #include <windef.h>
34 #include <winbase.h>
35 #include <strsafe.h>
36 #include <shlobj.h>
37 #include <undocshell.h>
38 #include <shlwapi.h>
39 #include <shlguid_undoc.h>
40 #include <wine/debug.h>
41 #include <wine/unicode.h>
42
43 #include "pidl.h"
44 #include "shell32_main.h"
45 #include "shresdef.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(pidl);
48 WINE_DECLARE_DEBUG_CHANNEL(shell);
49
50 /* from comctl32.dll */
51 extern LPVOID WINAPI Alloc(INT);
52 extern BOOL WINAPI Free(LPVOID);
53
54 static LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl);
55 static LPWSTR _ILGetTextPointerW(LPCITEMIDLIST pidl);
56
57 /*************************************************************************
58 * ILGetDisplayNameExA
59 *
60 * Retrieves the display name of an ItemIDList
61 *
62 * PARAMS
63 * psf [I] Shell Folder to start with, if NULL the desktop is used
64 * pidl [I] ItemIDList relative to the psf to get the display name for
65 * path [O] Filled in with the display name, assumed to be at least MAX_PATH long
66 * type [I] Type of display name to retrieve
67 * 0 = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR uses always the desktop as root
68 * 1 = SHGDN_NORMAL relative to the root folder
69 * 2 = SHGDN_INFOLDER relative to the root folder, only the last name
70 *
71 * RETURNS
72 * True if the display name could be retrieved successfully, False otherwise
73 */
74 static BOOL ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type)
75 {
76 BOOL ret = FALSE;
77 WCHAR wPath[MAX_PATH];
78
79 TRACE("%p %p %p %d\n", psf, pidl, path, type);
80
81 if (!pidl || !path)
82 return FALSE;
83
84 ret = ILGetDisplayNameExW(psf, pidl, wPath, type);
85 WideCharToMultiByte(CP_ACP, 0, wPath, -1, path, MAX_PATH, NULL, NULL);
86 TRACE("%p %p %s\n", psf, pidl, debugstr_a(path));
87
88 return ret;
89 }
90
91 BOOL ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type)
92 {
93 LPSHELLFOLDER psfParent, lsf = psf;
94 HRESULT ret = NO_ERROR;
95 LPCITEMIDLIST pidllast;
96 STRRET strret;
97 DWORD flag;
98
99 TRACE("%p %p %p %x\n", psf, pidl, path, type);
100
101 if (!pidl || !path)
102 return FALSE;
103
104 if (!lsf)
105 {
106 ret = SHGetDesktopFolder(&lsf);
107 if (FAILED(ret))
108 return FALSE;
109 }
110
111 switch (type)
112 {
113 case ILGDN_FORPARSING:
114 flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR;
115 break;
116 case ILGDN_NORMAL:
117 flag = SHGDN_NORMAL;
118 break;
119 case ILGDN_INFOLDER:
120 flag = SHGDN_INFOLDER;
121 break;
122 default:
123 FIXME("Unknown type parameter = %x\n", type);
124 flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR;
125 break;
126 }
127
128 if (!*(const WORD*)pidl || type == ILGDN_FORPARSING)
129 {
130 ret = IShellFolder_GetDisplayNameOf(lsf, pidl, flag, &strret);
131 if (SUCCEEDED(ret))
132 {
133 if(!StrRetToStrNW(path, MAX_PATH, &strret, pidl))
134 ret = E_FAIL;
135 }
136 }
137 else
138 {
139 ret = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidllast);
140 if (SUCCEEDED(ret))
141 {
142 ret = IShellFolder_GetDisplayNameOf(psfParent, pidllast, flag, &strret);
143 if (SUCCEEDED(ret))
144 {
145 if(!StrRetToStrNW(path, MAX_PATH, &strret, pidllast))
146 ret = E_FAIL;
147 }
148 IShellFolder_Release(psfParent);
149 }
150 }
151
152 TRACE("%p %p %s\n", psf, pidl, debugstr_w(path));
153
154 if (!psf)
155 IShellFolder_Release(lsf);
156 return SUCCEEDED(ret);
157 }
158
159 /*************************************************************************
160 * ILGetDisplayNameEx [SHELL32.186]
161 */
162 BOOL WINAPI ILGetDisplayNameEx(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPVOID path, DWORD type)
163 {
164 TRACE_(shell)("%p %p %p %d\n", psf, pidl, path, type);
165
166 if (SHELL_OsIsUnicode())
167 return ILGetDisplayNameExW(psf, pidl, path, type);
168 return ILGetDisplayNameExA(psf, pidl, path, type);
169 }
170
171 /*************************************************************************
172 * ILGetDisplayName [SHELL32.15]
173 */
174 BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl, LPVOID path)
175 {
176 TRACE_(shell)("%p %p\n", pidl, path);
177
178 if (SHELL_OsIsUnicode())
179 return ILGetDisplayNameExW(NULL, pidl, path, ILGDN_FORPARSING);
180 return ILGetDisplayNameExA(NULL, pidl, path, ILGDN_FORPARSING);
181 }
182
183 /*************************************************************************
184 * ILFindLastID [SHELL32.16]
185 *
186 * NOTES
187 * observed: pidl=Desktop return=pidl
188 */
189 LPITEMIDLIST WINAPI ILFindLastID(LPCITEMIDLIST pidl)
190 {
191 LPCITEMIDLIST pidlLast = pidl;
192
193 TRACE("(pidl=%p)\n",pidl);
194
195 if (!pidl)
196 return NULL;
197
198 while (pidl->mkid.cb)
199 {
200 pidlLast = pidl;
201 pidl = ILGetNext(pidl);
202 }
203 return (LPITEMIDLIST)pidlLast;
204 }
205
206 /*************************************************************************
207 * ILRemoveLastID [SHELL32.17]
208 *
209 * NOTES
210 * when pidl=Desktop return=FALSE
211 */
212 BOOL WINAPI ILRemoveLastID(LPITEMIDLIST pidl)
213 {
214 TRACE_(shell)("pidl=%p\n",pidl);
215
216 if (_ILIsEmpty(pidl))
217 return FALSE;
218 ILFindLastID(pidl)->mkid.cb = 0;
219 return TRUE;
220 }
221
222 /*************************************************************************
223 * ILClone [SHELL32.18]
224 *
225 * NOTES
226 * duplicate an idlist
227 */
228 LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl)
229 {
230 DWORD len;
231 LPITEMIDLIST newpidl;
232
233 if (!pidl)
234 return NULL;
235
236 len = ILGetSize(pidl);
237 newpidl = SHAlloc(len);
238 if (newpidl)
239 memcpy(newpidl,pidl,len);
240
241 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
242 pdump(pidl);
243
244 return newpidl;
245 }
246
247 /*************************************************************************
248 * ILCloneFirst [SHELL32.19]
249 *
250 * NOTES
251 * duplicates the first idlist of a complex pidl
252 */
253 LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl)
254 {
255 DWORD len;
256 LPITEMIDLIST pidlNew = NULL;
257
258 TRACE("pidl=%p\n", pidl);
259 pdump(pidl);
260
261 if (pidl)
262 {
263 len = pidl->mkid.cb;
264 pidlNew = SHAlloc(len+2);
265 if (pidlNew)
266 {
267 memcpy(pidlNew,pidl,len+2); /* 2 -> mind a desktop pidl */
268
269 if (len)
270 ILGetNext(pidlNew)->mkid.cb = 0x00;
271 }
272 }
273 TRACE("-- newpidl=%p\n",pidlNew);
274
275 return pidlNew;
276 }
277
278 /*************************************************************************
279 * ILLoadFromStream (SHELL32.26)
280 *
281 * NOTES
282 * the first two bytes are the len, the pidl is following then
283 */
284 HRESULT WINAPI ILLoadFromStream (IStream * pStream, LPITEMIDLIST * ppPidl)
285 {
286 WORD wLen = 0;
287 DWORD dwBytesRead;
288 HRESULT ret = E_FAIL;
289
290
291 TRACE_(shell)("%p %p\n", pStream , ppPidl);
292
293 SHFree(*ppPidl);
294 *ppPidl = NULL;
295
296 IStream_AddRef (pStream);
297
298 if (SUCCEEDED(IStream_Read(pStream, &wLen, 2, &dwBytesRead)))
299 {
300 TRACE("PIDL length is %d\n", wLen);
301 if (wLen != 0)
302 {
303 *ppPidl = SHAlloc (wLen);
304 if (SUCCEEDED(IStream_Read(pStream, *ppPidl , wLen, &dwBytesRead)))
305 {
306 TRACE("Stream read OK\n");
307 ret = S_OK;
308 }
309 else
310 {
311 WARN("reading pidl failed\n");
312 SHFree(*ppPidl);
313 *ppPidl = NULL;
314 }
315 }
316 else
317 {
318 *ppPidl = NULL;
319 ret = S_OK;
320 }
321 }
322
323 /* we are not yet fully compatible */
324 if (*ppPidl && !pcheck(*ppPidl))
325 {
326 WARN("Check failed\n");
327 SHFree(*ppPidl);
328 *ppPidl = NULL;
329 }
330
331 IStream_Release (pStream);
332 TRACE("done\n");
333 return ret;
334 }
335
336 /*************************************************************************
337 * ILSaveToStream (SHELL32.27)
338 *
339 * NOTES
340 * the first two bytes are the len, the pidl is following then
341 */
342 HRESULT WINAPI ILSaveToStream (IStream * pStream, LPCITEMIDLIST pPidl)
343 {
344 WORD wLen = 0;
345 HRESULT ret = E_FAIL;
346
347 TRACE_(shell)("%p %p\n", pStream, pPidl);
348
349 IStream_AddRef (pStream);
350
351 wLen = ILGetSize(pPidl);
352
353 if (SUCCEEDED(IStream_Write(pStream, &wLen, 2, NULL)))
354 {
355 if (SUCCEEDED(IStream_Write(pStream, pPidl, wLen, NULL)))
356 ret = S_OK;
357 }
358 IStream_Release (pStream);
359
360 return ret;
361 }
362
363 /*************************************************************************
364 * SHILCreateFromPath [SHELL32.28]
365 *
366 * Create an ItemIDList from a path
367 *
368 * PARAMS
369 * path [I]
370 * ppidl [O]
371 * attributes [I/O] requested attributes on call and actual attributes when
372 * the function returns
373 *
374 * RETURNS
375 * NO_ERROR if successful, or an OLE errer code otherwise
376 *
377 * NOTES
378 * Wrapper for IShellFolder_ParseDisplayName().
379 */
380 HRESULT WINAPI SHILCreateFromPathA(LPCSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
381 {
382 WCHAR lpszDisplayName[MAX_PATH];
383
384 TRACE_(shell)("%s %p 0x%08x\n", path, ppidl, attributes ? *attributes : 0);
385
386 if (!MultiByteToWideChar(CP_ACP, 0, path, -1, lpszDisplayName, MAX_PATH))
387 lpszDisplayName[MAX_PATH-1] = 0;
388
389 return SHILCreateFromPathW(lpszDisplayName, ppidl, attributes);
390 }
391
392 HRESULT WINAPI SHILCreateFromPathW(LPCWSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
393 {
394 LPSHELLFOLDER sf;
395 DWORD pchEaten;
396 HRESULT ret = E_FAIL;
397
398 TRACE_(shell)("%s %p 0x%08x\n", debugstr_w(path), ppidl, attributes ? *attributes : 0);
399
400 if (SUCCEEDED (SHGetDesktopFolder(&sf)))
401 {
402 ret = IShellFolder_ParseDisplayName(sf, 0, NULL, (LPWSTR)path, &pchEaten, ppidl, attributes);
403 IShellFolder_Release(sf);
404 }
405 return ret;
406 }
407
408 HRESULT WINAPI SHILCreateFromPathAW (LPCVOID path, LPITEMIDLIST * ppidl, DWORD * attributes)
409 {
410 if ( SHELL_OsIsUnicode())
411 return SHILCreateFromPathW (path, ppidl, attributes);
412 return SHILCreateFromPathA (path, ppidl, attributes);
413 }
414
415 /*************************************************************************
416 * SHCloneSpecialIDList [SHELL32.89]
417 *
418 * Create an ItemIDList to one of the special folders.
419
420 * PARAMS
421 * hwndOwner [in]
422 * nFolder [in] CSIDL_xxxxx
423 * fCreate [in] Create folder if it does not exist
424 *
425 * RETURNS
426 * Success: The newly created pidl
427 * Failure: NULL, if inputs are invalid.
428 *
429 * NOTES
430 * exported by ordinal.
431 * Caller is responsible for deallocating the returned ItemIDList with the
432 * shells IMalloc interface, aka ILFree.
433 */
434 LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner, int nFolder, BOOL fCreate)
435 {
436 LPITEMIDLIST ppidl;
437 TRACE_(shell)("(hwnd=%p,csidl=0x%x,%s).\n", hwndOwner, nFolder, fCreate ? "T" : "F");
438
439 if (fCreate)
440 nFolder |= CSIDL_FLAG_CREATE;
441
442 SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl);
443 return ppidl;
444 }
445
446 /*************************************************************************
447 * ILGlobalClone [SHELL32.20]
448 *
449 * Clones an ItemIDList using Alloc.
450 *
451 * PARAMS
452 * pidl [I] ItemIDList to clone
453 *
454 * RETURNS
455 * Newly allocated ItemIDList.
456 *
457 * NOTES
458 * exported by ordinal.
459 */
460 LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl)
461 {
462 DWORD len;
463 LPITEMIDLIST newpidl;
464
465 if (!pidl)
466 return NULL;
467
468 len = ILGetSize(pidl);
469 newpidl = Alloc(len);
470 if (newpidl)
471 memcpy(newpidl,pidl,len);
472
473 TRACE("pidl=%p newpidl=%p\n",pidl, newpidl);
474 pdump(pidl);
475
476 return newpidl;
477 }
478
479 /*************************************************************************
480 * ILIsEqual [SHELL32.21]
481 *
482 */
483 BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
484 {
485 char szData1[MAX_PATH];
486 char szData2[MAX_PATH];
487
488 LPCITEMIDLIST pidltemp1 = pidl1;
489 LPCITEMIDLIST pidltemp2 = pidl2;
490
491 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
492
493 /*
494 * Explorer reads from registry directly (StreamMRU),
495 * so we can only check here
496 */
497 if (!pcheck(pidl1) || !pcheck (pidl2))
498 return FALSE;
499
500 pdump (pidl1);
501 pdump (pidl2);
502
503 if (!pidl1 || !pidl2)
504 return FALSE;
505
506 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
507 {
508 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
509 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
510
511 if (strcasecmp( szData1, szData2 ))
512 return FALSE;
513
514 pidltemp1 = ILGetNext(pidltemp1);
515 pidltemp2 = ILGetNext(pidltemp2);
516 }
517
518 if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb)
519 return TRUE;
520
521 return FALSE;
522 }
523
524 /*************************************************************************
525 * ILIsParent [SHELL32.23]
526 *
527 * Verifies that pidlParent is indeed the (immediate) parent of pidlChild.
528 *
529 * PARAMS
530 * pidlParent [I]
531 * pidlChild [I]
532 * bImmediate [I] only return true if the parent is the direct parent
533 * of the child
534 *
535 * RETURNS
536 * True if the parent ItemIDlist is a complete part of the child ItemIdList,
537 * False otherwise.
538 *
539 * NOTES
540 * parent = a/b, child = a/b/c -> true, c is in folder a/b
541 * child = a/b/c/d -> false if bImmediate is true, d is not in folder a/b
542 * child = a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b
543 * child = a/b -> false if bImmediate is true
544 * child = a/b -> true if bImmediate is false
545 */
546 BOOL WINAPI ILIsParent(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate)
547 {
548 char szData1[MAX_PATH];
549 char szData2[MAX_PATH];
550 LPCITEMIDLIST pParent = pidlParent;
551 LPCITEMIDLIST pChild = pidlChild;
552
553 TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate);
554
555 if (!pParent || !pChild)
556 return FALSE;
557
558 while (pParent->mkid.cb && pChild->mkid.cb)
559 {
560 _ILSimpleGetText(pParent, szData1, MAX_PATH);
561 _ILSimpleGetText(pChild, szData2, MAX_PATH);
562
563 if (strcasecmp( szData1, szData2 ))
564 return FALSE;
565
566 pParent = ILGetNext(pParent);
567 pChild = ILGetNext(pChild);
568 }
569
570 /* child has shorter name than parent */
571 if (pParent->mkid.cb)
572 return FALSE;
573
574 /* not immediate descent */
575 if ((!pChild->mkid.cb || ILGetNext(pChild)->mkid.cb) && bImmediate)
576 return FALSE;
577
578 return TRUE;
579 }
580
581 /*************************************************************************
582 * ILFindChild [SHELL32.24]
583 *
584 * Compares elements from pidl1 and pidl2.
585 *
586 * PARAMS
587 * pidl1 [I]
588 * pidl2 [I]
589 *
590 * RETURNS
591 * pidl1 is desktop pidl2
592 * pidl1 shorter pidl2 pointer to first different element of pidl2
593 * if there was at least one equal element
594 * pidl2 shorter pidl1 0
595 * pidl2 equal pidl1 pointer to last 0x00-element of pidl2
596 *
597 * NOTES
598 * exported by ordinal.
599 */
600 LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
601 {
602 char szData1[MAX_PATH];
603 char szData2[MAX_PATH];
604
605 LPCITEMIDLIST pidltemp1 = pidl1;
606 LPCITEMIDLIST pidltemp2 = pidl2;
607 LPCITEMIDLIST ret=NULL;
608
609 TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
610
611 /* explorer reads from registry directly (StreamMRU),
612 so we can only check here */
613 if ((!pcheck (pidl1)) || (!pcheck (pidl2)))
614 return FALSE;
615
616 pdump (pidl1);
617 pdump (pidl2);
618
619 if (_ILIsDesktop(pidl1))
620 {
621 ret = pidl2;
622 }
623 else
624 {
625 while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
626 {
627 _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
628 _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
629
630 if (strcasecmp(szData1,szData2))
631 break;
632
633 pidltemp1 = ILGetNext(pidltemp1);
634 pidltemp2 = ILGetNext(pidltemp2);
635 ret = pidltemp2;
636 }
637
638 if (pidltemp1->mkid.cb)
639 ret = NULL; /* elements of pidl1 left*/
640 }
641 TRACE_(shell)("--- %p\n", ret);
642 return (LPITEMIDLIST)ret; /* pidl 1 is shorter */
643 }
644
645 /*************************************************************************
646 * ILCombine [SHELL32.25]
647 *
648 * Concatenates two complex ItemIDLists.
649 *
650 * PARAMS
651 * pidl1 [I] first complex ItemIDLists
652 * pidl2 [I] complex ItemIDLists to append
653 *
654 * RETURNS
655 * if both pidl's == NULL NULL
656 * if pidl1 == NULL cloned pidl2
657 * if pidl2 == NULL cloned pidl1
658 * otherwise new pidl with pidl2 appended to pidl1
659 *
660 * NOTES
661 * exported by ordinal.
662 * Does not destroy the passed in ItemIDLists!
663 */
664 LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
665 {
666 DWORD len1,len2;
667 LPITEMIDLIST pidlNew;
668
669 TRACE("pidl=%p pidl=%p\n",pidl1,pidl2);
670
671 if (!pidl1 && !pidl2) return NULL;
672
673 pdump (pidl1);
674 pdump (pidl2);
675
676 if (!pidl1)
677 {
678 pidlNew = ILClone(pidl2);
679 return pidlNew;
680 }
681
682 if (!pidl2)
683 {
684 pidlNew = ILClone(pidl1);
685 return pidlNew;
686 }
687
688 len1 = ILGetSize(pidl1)-2;
689 len2 = ILGetSize(pidl2);
690 pidlNew = SHAlloc(len1+len2);
691
692 if (pidlNew)
693 {
694 memcpy(pidlNew,pidl1,len1);
695 memcpy(((BYTE *)pidlNew)+len1,pidl2,len2);
696 }
697
698 /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
699 return pidlNew;
700 }
701
702 /*************************************************************************
703 * SHGetRealIDL [SHELL32.98]
704 *
705 * NOTES
706 */
707 HRESULT WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPCITEMIDLIST pidlSimple, LPITEMIDLIST *pidlReal)
708 {
709 IDataObject* pDataObj;
710 HRESULT hr;
711
712 hr = IShellFolder_GetUIObjectOf(lpsf, 0, 1, &pidlSimple,
713 &IID_IDataObject, 0, (LPVOID*)&pDataObj);
714 if (SUCCEEDED(hr))
715 {
716 STGMEDIUM medium;
717 FORMATETC fmt;
718
719 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
720 fmt.ptd = NULL;
721 fmt.dwAspect = DVASPECT_CONTENT;
722 fmt.lindex = -1;
723 fmt.tymed = TYMED_HGLOBAL;
724
725 hr = IDataObject_GetData(pDataObj, &fmt, &medium);
726
727 IDataObject_Release(pDataObj);
728
729 if (SUCCEEDED(hr))
730 {
731 /*assert(pida->cidl==1);*/
732 LPIDA pida = GlobalLock(medium.u.hGlobal);
733
734 LPCITEMIDLIST pidl_folder = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
735 LPCITEMIDLIST pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]);
736
737 *pidlReal = ILCombine(pidl_folder, pidl_child);
738
739 if (!*pidlReal)
740 hr = E_OUTOFMEMORY;
741
742 GlobalUnlock(medium.u.hGlobal);
743 GlobalFree(medium.u.hGlobal);
744 }
745 }
746
747 return hr;
748 }
749
750 /*************************************************************************
751 * SHLogILFromFSIL [SHELL32.95]
752 *
753 * NOTES
754 * pild = CSIDL_DESKTOP ret = 0
755 * pild = CSIDL_DRIVES ret = 0
756 */
757 LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
758 {
759 FIXME("(pidl=%p)\n",pidl);
760
761 pdump(pidl);
762
763 return 0;
764 }
765
766 /*************************************************************************
767 * ILGetSize [SHELL32.152]
768 *
769 * Gets the byte size of an ItemIDList including zero terminator
770 *
771 * PARAMS
772 * pidl [I] ItemIDList
773 *
774 * RETURNS
775 * size of pidl in bytes
776 *
777 * NOTES
778 * exported by ordinal
779 */
780 UINT WINAPI ILGetSize(LPCITEMIDLIST pidl)
781 {
782 LPCSHITEMID si;
783 UINT len=0;
784
785 if (pidl)
786 {
787 si = &(pidl->mkid);
788
789 while (si->cb)
790 {
791 len += si->cb;
792 si = (LPCSHITEMID)(((const BYTE*)si)+si->cb);
793 }
794 len += 2;
795 }
796 TRACE("pidl=%p size=%u\n",pidl, len);
797 return len;
798 }
799
800 /*************************************************************************
801 * ILGetNext [SHELL32.153]
802 *
803 * Gets the next ItemID of an ItemIDList
804 *
805 * PARAMS
806 * pidl [I] ItemIDList
807 *
808 * RETURNS
809 * null -> null
810 * desktop -> null
811 * simple pidl -> pointer to 0x0000 element
812 *
813 * NOTES
814 * exported by ordinal.
815 */
816 LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl)
817 {
818 WORD len;
819
820 TRACE("%p\n", pidl);
821
822 if (pidl)
823 {
824 len = pidl->mkid.cb;
825 if (len)
826 {
827 pidl = (LPCITEMIDLIST) (((const BYTE*)pidl)+len);
828 TRACE("-- %p\n", pidl);
829 return (LPITEMIDLIST)pidl;
830 }
831 }
832 return NULL;
833 }
834
835 /*************************************************************************
836 * ILAppendID [SHELL32.154]
837 *
838 * Adds the single ItemID item to the ItemIDList indicated by pidl.
839 * If bEnd is FALSE, inserts the item in the front of the list,
840 * otherwise it adds the item to the end. (???)
841 *
842 * PARAMS
843 * pidl [I] ItemIDList to extend
844 * item [I] ItemID to prepend/append
845 * bEnd [I] Indicates if the item should be appended
846 *
847 * NOTES
848 * Destroys the passed in idlist! (???)
849 */
850 LPITEMIDLIST WINAPI ILAppendID(LPITEMIDLIST pidl, LPCSHITEMID item, BOOL bEnd)
851 {
852 LPITEMIDLIST idlRet;
853 LPCITEMIDLIST itemid = (LPCITEMIDLIST)item;
854
855 WARN("(pidl=%p,pidl=%p,%08u)semi-stub\n",pidl,item,bEnd);
856
857 pdump (pidl);
858 pdump (itemid);
859
860 if (_ILIsDesktop(pidl))
861 {
862 idlRet = ILClone(itemid);
863 SHFree (pidl);
864 return idlRet;
865 }
866
867 if (bEnd)
868 idlRet = ILCombine(pidl, itemid);
869 else
870 idlRet = ILCombine(itemid, pidl);
871
872 SHFree(pidl);
873 return idlRet;
874 }
875
876 /*************************************************************************
877 * ILFree [SHELL32.155]
878 *
879 * Frees memory (if not NULL) allocated by SHMalloc allocator
880 *
881 * PARAMS
882 * pidl [I]
883 *
884 * RETURNS
885 * Nothing
886 *
887 * NOTES
888 * exported by ordinal
889 */
890 void WINAPI ILFree(LPITEMIDLIST pidl)
891 {
892 TRACE("(pidl=%p)\n",pidl);
893 SHFree(pidl);
894 }
895
896 /*************************************************************************
897 * ILGlobalFree [SHELL32.156]
898 *
899 * Frees memory (if not NULL) allocated by Alloc allocator
900 *
901 * PARAMS
902 * pidl [I]
903 *
904 * RETURNS
905 * Nothing
906 *
907 * NOTES
908 * exported by ordinal.
909 */
910 void WINAPI ILGlobalFree( LPITEMIDLIST pidl)
911 {
912 TRACE("%p\n", pidl);
913
914 Free(pidl);
915 }
916
917 /*************************************************************************
918 * ILCreateFromPathA [SHELL32.189]
919 *
920 * Creates a complex ItemIDList from a path and returns it.
921 *
922 * PARAMS
923 * path [I]
924 *
925 * RETURNS
926 * the newly created complex ItemIDList or NULL if failed
927 *
928 * NOTES
929 * exported by ordinal.
930 */
931 LPITEMIDLIST WINAPI ILCreateFromPathA (LPCSTR path)
932 {
933 LPITEMIDLIST pidlnew = NULL;
934
935 TRACE_(shell)("%s\n", debugstr_a(path));
936
937 if (SUCCEEDED(SHILCreateFromPathA(path, &pidlnew, NULL)))
938 return pidlnew;
939 return NULL;
940 }
941
942 /*************************************************************************
943 * ILCreateFromPathW [SHELL32.190]
944 *
945 * See ILCreateFromPathA.
946 */
947 LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path)
948 {
949 LPITEMIDLIST pidlnew = NULL;
950
951 TRACE_(shell)("%s\n", debugstr_w(path));
952
953 if (SUCCEEDED(SHILCreateFromPathW(path, &pidlnew, NULL)))
954 return pidlnew;
955 return NULL;
956 }
957
958 /*************************************************************************
959 * ILCreateFromPath [SHELL32.157]
960 */
961 LPITEMIDLIST WINAPI ILCreateFromPathAW (LPCVOID path)
962 {
963 if ( SHELL_OsIsUnicode())
964 return ILCreateFromPathW (path);
965 return ILCreateFromPathA (path);
966 }
967
968 /*************************************************************************
969 * _ILParsePathW [internal]
970 *
971 * Creates an ItemIDList from a path and returns it.
972 *
973 * PARAMS
974 * path [I] path to parse and convert into an ItemIDList
975 * lpFindFile [I] pointer to buffer to initialize the FileSystem
976 * Bind Data object with
977 * bBindCtx [I] indicates to create a BindContext and assign a
978 * FileSystem Bind Data object
979 * ppidl [O] the newly create ItemIDList
980 * prgfInOut [I/O] requested attributes on input and actual
981 * attributes on return
982 *
983 * RETURNS
984 * NO_ERROR on success or an OLE error code
985 *
986 * NOTES
987 * If either lpFindFile is non-NULL or bBindCtx is TRUE, this function
988 * creates a BindContext object and assigns a FileSystem Bind Data object
989 * to it, passing the BindContext to IShellFolder_ParseDisplayName. Each
990 * IShellFolder uses that FileSystem Bind Data object of the BindContext
991 * to pass data about the current path element to the next object. This
992 * is used to avoid having to verify the current path element on disk, so
993 * that creating an ItemIDList from a nonexistent path still can work.
994 */
995 static HRESULT _ILParsePathW(LPCWSTR path, LPWIN32_FIND_DATAW lpFindFile,
996 BOOL bBindCtx, LPITEMIDLIST *ppidl, LPDWORD prgfInOut)
997 {
998 LPSHELLFOLDER pSF = NULL;
999 LPBC pBC = NULL;
1000 HRESULT ret;
1001
1002 TRACE("%s %p %d (%p)->%p (%p)->0x%x\n", debugstr_w(path), lpFindFile, bBindCtx,
1003 ppidl, ppidl ? *ppidl : NULL,
1004 prgfInOut, prgfInOut ? *prgfInOut : 0);
1005
1006 ret = SHGetDesktopFolder(&pSF);
1007 if (FAILED(ret))
1008 return ret;
1009
1010 if (lpFindFile || bBindCtx)
1011 ret = IFileSystemBindData_Constructor(lpFindFile, &pBC);
1012
1013 if (SUCCEEDED(ret))
1014 {
1015 ret = IShellFolder_ParseDisplayName(pSF, 0, pBC, (LPOLESTR)path, NULL, ppidl, prgfInOut);
1016 }
1017
1018 if (pBC)
1019 {
1020 IBindCtx_Release(pBC);
1021 pBC = NULL;
1022 }
1023
1024 IShellFolder_Release(pSF);
1025
1026 if (FAILED(ret) && ppidl)
1027 *ppidl = NULL;
1028
1029 TRACE("%s %p 0x%x\n", debugstr_w(path), ppidl ? *ppidl : NULL, prgfInOut ? *prgfInOut : 0);
1030
1031 return ret;
1032 }
1033
1034 /*************************************************************************
1035 * SHSimpleIDListFromPath [SHELL32.162]
1036 *
1037 * Creates a simple ItemIDList from a path and returns it. This function
1038 * does not fail on nonexistent paths.
1039 *
1040 * PARAMS
1041 * path [I] path to parse and convert into an ItemIDList
1042 *
1043 * RETURNS
1044 * the newly created simple ItemIDList
1045 *
1046 * NOTES
1047 * Simple in the name does not mean a relative ItemIDList but rather a
1048 * fully qualified list, where only the file name is filled in and the
1049 * directory flag for those ItemID elements this is known about, eg.
1050 * it is not the last element in the ItemIDList or the actual directory
1051 * exists on disk.
1052 * exported by ordinal.
1053 */
1054 LPITEMIDLIST WINAPI SHSimpleIDListFromPathA(LPCSTR lpszPath)
1055 {
1056 LPITEMIDLIST pidl = NULL;
1057 LPWSTR wPath = NULL;
1058 int len;
1059
1060 TRACE("%s\n", debugstr_a(lpszPath));
1061
1062 if (lpszPath)
1063 {
1064 len = MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, NULL, 0);
1065 wPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1066 MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, wPath, len);
1067 }
1068
1069 _ILParsePathW(wPath, NULL, TRUE, &pidl, NULL);
1070
1071 HeapFree(GetProcessHeap(), 0, wPath);
1072 TRACE("%s %p\n", debugstr_a(lpszPath), pidl);
1073 return pidl;
1074 }
1075
1076 LPITEMIDLIST WINAPI SHSimpleIDListFromPathW(LPCWSTR lpszPath)
1077 {
1078 LPITEMIDLIST pidl = NULL;
1079
1080 TRACE("%s\n", debugstr_w(lpszPath));
1081
1082 _ILParsePathW(lpszPath, NULL, TRUE, &pidl, NULL);
1083 TRACE("%s %p\n", debugstr_w(lpszPath), pidl);
1084 return pidl;
1085 }
1086
1087 LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW(LPCVOID lpszPath)
1088 {
1089 if ( SHELL_OsIsUnicode())
1090 return SHSimpleIDListFromPathW (lpszPath);
1091 return SHSimpleIDListFromPathA (lpszPath);
1092 }
1093
1094 /*************************************************************************
1095 * SHGetDataFromIDListA [SHELL32.247]
1096 *
1097 * NOTES
1098 * the pidl can be a simple one. since we can't get the path out of the pidl
1099 * we have to take all data from the pidl
1100 */
1101 HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl,
1102 int nFormat, LPVOID dest, int len)
1103 {
1104 LPSTR filename, shortname;
1105 WIN32_FIND_DATAA * pfd;
1106
1107 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
1108
1109 pdump(pidl);
1110 if (!psf || !dest)
1111 return E_INVALIDARG;
1112
1113 switch (nFormat)
1114 {
1115 case SHGDFIL_FINDDATA:
1116 pfd = dest;
1117
1118 if (_ILIsDrive(pidl) || _ILIsSpecialFolder(pidl))
1119 return E_INVALIDARG;
1120
1121 if (len < sizeof(WIN32_FIND_DATAA))
1122 return E_INVALIDARG;
1123
1124 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
1125 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
1126 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
1127 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
1128
1129 filename = _ILGetTextPointer(pidl);
1130 shortname = _ILGetSTextPointer(pidl);
1131
1132 if (filename)
1133 lstrcpynA(pfd->cFileName, filename, sizeof(pfd->cFileName));
1134 else
1135 pfd->cFileName[0] = '\0';
1136
1137 if (shortname)
1138 lstrcpynA(pfd->cAlternateFileName, shortname, sizeof(pfd->cAlternateFileName));
1139 else
1140 pfd->cAlternateFileName[0] = '\0';
1141 return S_OK;
1142
1143 case SHGDFIL_NETRESOURCE:
1144 case SHGDFIL_DESCRIPTIONID:
1145 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
1146 break;
1147
1148 default:
1149 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
1150 }
1151
1152 return E_INVALIDARG;
1153 }
1154
1155 /*************************************************************************
1156 * SHGetDataFromIDListW [SHELL32.248]
1157 *
1158 */
1159 HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl,
1160 int nFormat, LPVOID dest, int len)
1161 {
1162 LPSTR filename, shortname;
1163 WIN32_FIND_DATAW * pfd = dest;
1164
1165 TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len);
1166
1167 pdump(pidl);
1168
1169 if (!psf || !dest)
1170 return E_INVALIDARG;
1171
1172 switch (nFormat)
1173 {
1174 case SHGDFIL_FINDDATA:
1175 pfd = dest;
1176
1177 if (_ILIsDrive(pidl))
1178 return E_INVALIDARG;
1179
1180 if (len < sizeof(WIN32_FIND_DATAW))
1181 return E_INVALIDARG;
1182
1183 ZeroMemory(pfd, sizeof (WIN32_FIND_DATAW));
1184 _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
1185 pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
1186 pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
1187
1188 filename = _ILGetTextPointer(pidl);
1189 shortname = _ILGetSTextPointer(pidl);
1190
1191 if (!filename)
1192 pfd->cFileName[0] = '\0';
1193 else if (!MultiByteToWideChar(CP_ACP, 0, filename, -1, pfd->cFileName, MAX_PATH))
1194 pfd->cFileName[MAX_PATH-1] = 0;
1195
1196 if (!shortname)
1197 pfd->cAlternateFileName[0] = '\0';
1198 else if (!MultiByteToWideChar(CP_ACP, 0, shortname, -1, pfd->cAlternateFileName, 14))
1199 pfd->cAlternateFileName[13] = 0;
1200 return S_OK;
1201
1202 case SHGDFIL_NETRESOURCE:
1203 case SHGDFIL_DESCRIPTIONID:
1204 FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
1205 break;
1206
1207 default:
1208 ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
1209 }
1210
1211 return E_INVALIDARG;
1212 }
1213
1214 /*************************************************************************
1215 * SHGetPathFromIDListA [SHELL32.@][NT 4.0: SHELL32.220]
1216 *
1217 * PARAMETERS
1218 * pidl, [IN] pidl
1219 * pszPath [OUT] path
1220 *
1221 * RETURNS
1222 * path from a passed PIDL.
1223 *
1224 * NOTES
1225 * NULL returns FALSE
1226 * desktop pidl gives path to desktop directory back
1227 * special pidls returning FALSE
1228 */
1229 BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath)
1230 {
1231 WCHAR wszPath[MAX_PATH];
1232 BOOL bSuccess;
1233
1234 bSuccess = SHGetPathFromIDListW(pidl, wszPath);
1235 WideCharToMultiByte(CP_ACP, 0, wszPath, -1, pszPath, MAX_PATH, NULL, NULL);
1236
1237 return bSuccess;
1238 }
1239
1240 /*************************************************************************
1241 * SHGetPathFromIDListW [SHELL32.@]
1242 *
1243 * See SHGetPathFromIDListA.
1244 */
1245 BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
1246 {
1247 HRESULT hr;
1248 LPCITEMIDLIST pidlLast;
1249 LPSHELLFOLDER psfFolder;
1250 DWORD dwAttributes;
1251 STRRET strret;
1252
1253 TRACE_(shell)("(pidl=%p,%p)\n", pidl, pszPath);
1254 pdump(pidl);
1255
1256 *pszPath = '\0';
1257 if (!pidl)
1258 return FALSE;
1259
1260 hr = SHBindToParent(pidl, &IID_IShellFolder, (VOID**)&psfFolder, &pidlLast);
1261 if (FAILED(hr))
1262 {
1263 ERR("SHBindToParent failed: %x\n", hr);
1264 return FALSE;
1265 }
1266
1267 dwAttributes = SFGAO_FILESYSTEM;
1268 hr = IShellFolder_GetAttributesOf(psfFolder, 1, &pidlLast, &dwAttributes);
1269 if (FAILED(hr) || !(dwAttributes & SFGAO_FILESYSTEM)) {
1270 WARN("Wrong dwAttributes or GetAttributesOf failed: %x\n", hr);
1271 IShellFolder_Release(psfFolder);
1272 return FALSE;
1273 }
1274
1275 hr = IShellFolder_GetDisplayNameOf(psfFolder, pidlLast, SHGDN_FORPARSING, &strret);
1276 IShellFolder_Release(psfFolder);
1277 if (FAILED(hr)) return FALSE;
1278
1279 hr = StrRetToBufW(&strret, pidlLast, pszPath, MAX_PATH);
1280
1281 TRACE_(shell)("-- %s, 0x%08x\n",debugstr_w(pszPath), hr);
1282 return SUCCEEDED(hr);
1283 }
1284
1285 /*************************************************************************
1286 * SHBindToParent [shell version 5.0]
1287 */
1288 HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
1289 {
1290 IShellFolder * psfDesktop;
1291 HRESULT hr=E_FAIL;
1292
1293 TRACE_(shell)("pidl=%p\n", pidl);
1294 pdump(pidl);
1295
1296 if (!pidl || !ppv)
1297 return E_INVALIDARG;
1298
1299 *ppv = NULL;
1300 if (ppidlLast)
1301 *ppidlLast = NULL;
1302
1303 hr = SHGetDesktopFolder(&psfDesktop);
1304 if (FAILED(hr))
1305 return hr;
1306
1307 if (_ILIsPidlSimple(pidl))
1308 {
1309 /* we are on desktop level */
1310 hr = IShellFolder_QueryInterface(psfDesktop, riid, ppv);
1311 }
1312 else
1313 {
1314 LPITEMIDLIST pidlParent = ILClone(pidl);
1315 ILRemoveLastID(pidlParent);
1316 hr = IShellFolder_BindToObject(psfDesktop, pidlParent, NULL, riid, ppv);
1317 SHFree (pidlParent);
1318 }
1319
1320 IShellFolder_Release(psfDesktop);
1321
1322 if (SUCCEEDED(hr) && ppidlLast)
1323 *ppidlLast = ILFindLastID(pidl);
1324
1325 TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08x\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr);
1326 return hr;
1327 }
1328
1329 /*************************************************************************
1330 * SHParseDisplayName [shell version 6.0]
1331 */
1332 HRESULT WINAPI SHParseDisplayName(LPCWSTR pszName, IBindCtx *pbc,
1333 LPITEMIDLIST *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut)
1334 {
1335 IShellFolder *psfDesktop;
1336 HRESULT hr=E_FAIL;
1337 ULONG dwAttr=sfgaoIn;
1338
1339 if(!ppidl)
1340 return E_INVALIDARG;
1341
1342 if (!pszName)
1343 {
1344 *ppidl = NULL;
1345 return E_INVALIDARG;
1346 }
1347
1348 hr = SHGetDesktopFolder(&psfDesktop);
1349 if (FAILED(hr))
1350 {
1351 *ppidl = NULL;
1352 return hr;
1353 }
1354
1355 hr = IShellFolder_ParseDisplayName(psfDesktop, (HWND)NULL, pbc, (LPOLESTR)pszName, (ULONG *)NULL, ppidl, &dwAttr);
1356
1357 IShellFolder_Release(psfDesktop);
1358
1359 if (SUCCEEDED(hr))
1360 {
1361 if (psfgaoOut) *psfgaoOut = dwAttr;
1362 }
1363 else
1364 {
1365 *ppidl = NULL;
1366 }
1367
1368 return hr;
1369 }
1370
1371 #ifndef __REACTOS__
1372
1373 /*************************************************************************
1374 * SHGetNameFromIDList [SHELL32.@]
1375 */
1376 HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWSTR *ppszName)
1377 {
1378 IShellFolder *psfparent;
1379 LPCITEMIDLIST child_pidl;
1380 STRRET disp_name;
1381 HRESULT ret;
1382
1383 TRACE("%p 0x%08x %p\n", pidl, sigdnName, ppszName);
1384
1385 *ppszName = NULL;
1386 ret = SHBindToParent(pidl, &IID_IShellFolder, (void**)&psfparent, &child_pidl);
1387 if(SUCCEEDED(ret))
1388 {
1389 switch(sigdnName)
1390 {
1391 /* sigdnName & 0xffff */
1392 case SIGDN_NORMALDISPLAY: /* SHGDN_NORMAL */
1393 case SIGDN_PARENTRELATIVEPARSING: /* SHGDN_INFOLDER | SHGDN_FORPARSING */
1394 case SIGDN_PARENTRELATIVEEDITING: /* SHGDN_INFOLDER | SHGDN_FOREDITING */
1395 case SIGDN_DESKTOPABSOLUTEPARSING: /* SHGDN_FORPARSING */
1396 case SIGDN_DESKTOPABSOLUTEEDITING: /* SHGDN_FOREDITING | SHGDN_FORADDRESSBAR*/
1397 case SIGDN_PARENTRELATIVEFORADDRESSBAR: /* SIGDN_INFOLDER | SHGDN_FORADDRESSBAR */
1398 case SIGDN_PARENTRELATIVE: /* SIGDN_INFOLDER */
1399
1400 disp_name.uType = STRRET_WSTR;
1401 ret = IShellFolder_GetDisplayNameOf(psfparent, child_pidl,
1402 sigdnName & 0xffff,
1403 &disp_name);
1404 if(SUCCEEDED(ret))
1405 ret = StrRetToStrW(&disp_name, pidl, ppszName);
1406
1407 break;
1408
1409 case SIGDN_FILESYSPATH:
1410 *ppszName = CoTaskMemAlloc(sizeof(WCHAR)*MAX_PATH);
1411 if(SHGetPathFromIDListW(pidl, *ppszName))
1412 {
1413 TRACE("Got string %s\n", debugstr_w(*ppszName));
1414 ret = S_OK;
1415 }
1416 else
1417 {
1418 CoTaskMemFree(*ppszName);
1419 ret = E_INVALIDARG;
1420 }
1421 break;
1422
1423 case SIGDN_URL:
1424 default:
1425 FIXME("Unsupported SIGDN %x\n", sigdnName);
1426 ret = E_FAIL;
1427 }
1428
1429 IShellFolder_Release(psfparent);
1430 }
1431 return ret;
1432 }
1433
1434 /*************************************************************************
1435 * SHGetIDListFromObject [SHELL32.@]
1436 */
1437 HRESULT WINAPI SHGetIDListFromObject(IUnknown *punk, PIDLIST_ABSOLUTE *ppidl)
1438 {
1439 IPersistIDList *ppersidl;
1440 IPersistFolder2 *ppf2;
1441 IDataObject *pdo;
1442 IFolderView *pfv;
1443 HRESULT ret;
1444
1445 if(!punk)
1446 return E_NOINTERFACE;
1447
1448 *ppidl = NULL;
1449
1450 /* Try IPersistIDList */
1451 ret = IUnknown_QueryInterface(punk, &IID_IPersistIDList, (void**)&ppersidl);
1452 if(SUCCEEDED(ret))
1453 {
1454 TRACE("IPersistIDList (%p)\n", ppersidl);
1455 ret = IPersistIDList_GetIDList(ppersidl, ppidl);
1456 IPersistIDList_Release(ppersidl);
1457 if(SUCCEEDED(ret))
1458 return ret;
1459 }
1460
1461 /* Try IPersistFolder2 */
1462 ret = IUnknown_QueryInterface(punk, &IID_IPersistFolder2, (void**)&ppf2);
1463 if(SUCCEEDED(ret))
1464 {
1465 TRACE("IPersistFolder2 (%p)\n", ppf2);
1466 ret = IPersistFolder2_GetCurFolder(ppf2, ppidl);
1467 IPersistFolder2_Release(ppf2);
1468 if(SUCCEEDED(ret))
1469 return ret;
1470 }
1471
1472 /* Try IDataObject */
1473 ret = IUnknown_QueryInterface(punk, &IID_IDataObject, (void**)&pdo);
1474 if(SUCCEEDED(ret))
1475 {
1476 IShellItem *psi;
1477 TRACE("IDataObject (%p)\n", pdo);
1478 ret = SHGetItemFromDataObject(pdo, DOGIF_ONLY_IF_ONE,
1479 &IID_IShellItem, (void**)&psi);
1480 if(SUCCEEDED(ret))
1481 {
1482 ret = SHGetIDListFromObject((IUnknown*)psi, ppidl);
1483 IShellItem_Release(psi);
1484 }
1485 IDataObject_Release(pdo);
1486
1487 if(SUCCEEDED(ret))
1488 return ret;
1489 }
1490
1491 /* Try IFolderView */
1492 ret = IUnknown_QueryInterface(punk, &IID_IFolderView, (void**)&pfv);
1493 if(SUCCEEDED(ret))
1494 {
1495 IShellFolder *psf;
1496 TRACE("IFolderView (%p)\n", pfv);
1497 ret = IFolderView_GetFolder(pfv, &IID_IShellFolder, (void**)&psf);
1498 if(SUCCEEDED(ret))
1499 {
1500 /* We might be able to get IPersistFolder2 from a shellfolder. */
1501 ret = SHGetIDListFromObject((IUnknown*)psf, ppidl);
1502 }
1503 IFolderView_Release(pfv);
1504 return ret;
1505 }
1506
1507 return ret;
1508 }
1509
1510 #endif /* !__REACTOS__ */
1511
1512 /**************************************************************************
1513 *
1514 * internal functions
1515 *
1516 * ### 1. section creating pidls ###
1517 *
1518 *************************************************************************
1519 */
1520
1521 /* Basic PIDL constructor. Allocates size + 5 bytes, where:
1522 * - two bytes are SHITEMID.cb
1523 * - one byte is PIDLDATA.type
1524 * - two bytes are the NULL PIDL terminator
1525 * Sets type of the returned PIDL to type.
1526 */
1527 static LPITEMIDLIST _ILAlloc(PIDLTYPE type, unsigned int size)
1528 {
1529 LPITEMIDLIST pidlOut = NULL;
1530
1531 pidlOut = SHAlloc(size + 5);
1532 if(pidlOut)
1533 {
1534 LPPIDLDATA pData;
1535 LPITEMIDLIST pidlNext;
1536
1537 ZeroMemory(pidlOut, size + 5);
1538 pidlOut->mkid.cb = size + 3;
1539
1540 pData = _ILGetDataPointer(pidlOut);
1541 if (pData)
1542 pData->type = type;
1543
1544 pidlNext = ILGetNext(pidlOut);
1545 if (pidlNext)
1546 pidlNext->mkid.cb = 0x00;
1547 TRACE("-- (pidl=%p, size=%u)\n", pidlOut, size);
1548 }
1549
1550 return pidlOut;
1551 }
1552
1553 LPITEMIDLIST _ILCreateDesktop(void)
1554 {
1555 LPITEMIDLIST ret;
1556
1557 TRACE("()\n");
1558 ret = SHAlloc(2);
1559 if (ret)
1560 ret->mkid.cb = 0;
1561 return ret;
1562 }
1563
1564 LPITEMIDLIST _ILCreateMyComputer(void)
1565 {
1566 TRACE("()\n");
1567 return _ILCreateGuid(PT_GUID, &CLSID_MyComputer);
1568 }
1569
1570 LPITEMIDLIST _ILCreateMyDocuments(void)
1571 {
1572 TRACE("()\n");
1573 return _ILCreateGuid(PT_GUID, &CLSID_MyDocuments);
1574 }
1575
1576 LPITEMIDLIST _ILCreateIExplore(void)
1577 {
1578 TRACE("()\n");
1579 return _ILCreateGuid(PT_GUID, &CLSID_Internet);
1580 }
1581
1582 LPITEMIDLIST _ILCreateControlPanel(void)
1583 {
1584 LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL;
1585
1586 TRACE("()\n");
1587 if (parent)
1588 {
1589 LPITEMIDLIST cpl = _ILCreateGuid(PT_SHELLEXT, &CLSID_ControlPanel);
1590
1591 if (cpl)
1592 {
1593 ret = ILCombine(parent, cpl);
1594 SHFree(cpl);
1595 }
1596 SHFree(parent);
1597 }
1598 return ret;
1599 }
1600
1601 LPITEMIDLIST _ILCreatePrinters(void)
1602 {
1603 LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL;
1604
1605 TRACE("()\n");
1606 if (parent)
1607 {
1608 LPITEMIDLIST printers = _ILCreateGuid(PT_YAGUID, &CLSID_Printers);
1609
1610 if (printers)
1611 {
1612 ret = ILCombine(parent, printers);
1613 SHFree(printers);
1614 }
1615 SHFree(parent);
1616 }
1617 return ret;
1618 }
1619
1620 LPITEMIDLIST _ILCreateNetwork(void)
1621 {
1622 TRACE("()\n");
1623 return _ILCreateGuid(PT_GUID, &CLSID_NetworkPlaces);
1624 }
1625
1626 LPITEMIDLIST _ILCreateBitBucket(void)
1627 {
1628 TRACE("()\n");
1629 return _ILCreateGuid(PT_GUID, &CLSID_RecycleBin);
1630 }
1631
1632 LPITEMIDLIST _ILCreateAdminTools(void)
1633 {
1634 TRACE("()\n");
1635 return _ILCreateGuid(PT_GUID, &CLSID_AdminFolderShortcut); //FIXME
1636 }
1637
1638 LPITEMIDLIST _ILCreateGuid(PIDLTYPE type, REFIID guid)
1639 {
1640 LPITEMIDLIST pidlOut;
1641
1642 if (type == PT_SHELLEXT || type == PT_GUID || type == PT_YAGUID)
1643 {
1644 pidlOut = _ILAlloc(type, sizeof(GUIDStruct));
1645 if (pidlOut)
1646 {
1647 LPPIDLDATA pData = _ILGetDataPointer(pidlOut);
1648
1649 pData->u.guid.guid = *guid;
1650 TRACE("-- create GUID-pidl %s\n",
1651 debugstr_guid(&(pData->u.guid.guid)));
1652 }
1653 }
1654 else
1655 {
1656 WARN("%d: invalid type for GUID\n", type);
1657 pidlOut = NULL;
1658 }
1659 return pidlOut;
1660 }
1661
1662 #ifndef __REACTOS__
1663 LPITEMIDLIST _ILCreateGuidFromStrA(LPCSTR szGUID)
1664 {
1665 IID iid;
1666
1667 if (FAILED(SHCLSIDFromStringA(szGUID, &iid)))
1668 {
1669 ERR("%s is not a GUID\n", szGUID);
1670 return NULL;
1671 }
1672 return _ILCreateGuid(PT_GUID, &iid);
1673 }
1674 #endif
1675
1676 LPITEMIDLIST _ILCreateGuidFromStrW(LPCWSTR szGUID)
1677 {
1678 IID iid;
1679
1680 #ifndef __REACTOS__
1681 if (FAILED(SHCLSIDFromStringW(szGUID, &iid)))
1682 #else
1683 if (!GUIDFromStringW(szGUID, &iid))
1684 #endif
1685 {
1686 ERR("%s is not a GUID\n", debugstr_w(szGUID));
1687 return NULL;
1688 }
1689 return _ILCreateGuid(PT_GUID, &iid);
1690 }
1691
1692 LPITEMIDLIST _ILCreateFromFindDataW( const WIN32_FIND_DATAW *wfd )
1693 {
1694 char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
1695 DWORD len, len1, wlen, alen;
1696 LPITEMIDLIST pidl;
1697 PIDLTYPE type;
1698
1699 if (!wfd)
1700 return NULL;
1701
1702 TRACE("(%s, %s)\n",debugstr_w(wfd->cAlternateFileName), debugstr_w(wfd->cFileName));
1703
1704 /* prepare buffer with both names */
1705 len = WideCharToMultiByte(CP_ACP,0,wfd->cFileName,-1,buff,MAX_PATH,NULL,NULL);
1706 len1 = WideCharToMultiByte(CP_ACP,0,wfd->cAlternateFileName,-1, buff+len, sizeof(buff)-len, NULL, NULL);
1707 alen = len + len1;
1708
1709 type = (wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? PT_FOLDER : PT_VALUE;
1710
1711 wlen = lstrlenW(wfd->cFileName) + 1;
1712 pidl = _ILAlloc(type, FIELD_OFFSET(FileStruct, szNames[alen + (alen & 1)]) +
1713 FIELD_OFFSET(FileStructW, wszName[wlen]) + sizeof(WORD));
1714 if (pidl)
1715 {
1716 LPPIDLDATA pData = _ILGetDataPointer(pidl);
1717 FileStruct *fs = &pData->u.file;
1718 FileStructW *fsw;
1719 WORD *pOffsetW;
1720
1721 FileTimeToDosDateTime( &wfd->ftLastWriteTime, &fs->uFileDate, &fs->uFileTime);
1722 fs->dwFileSize = wfd->nFileSizeLow;
1723 fs->uFileAttribs = wfd->dwFileAttributes;
1724 memcpy(fs->szNames, buff, alen);
1725
1726 fsw = (FileStructW*)(pData->u.file.szNames + alen + (alen & 0x1));
1727 fsw->cbLen = FIELD_OFFSET(FileStructW, wszName[wlen]) + sizeof(WORD);
1728 FileTimeToDosDateTime( &wfd->ftCreationTime, &fsw->uCreationDate, &fsw->uCreationTime);
1729 FileTimeToDosDateTime( &wfd->ftLastAccessTime, &fsw->uLastAccessDate, &fsw->uLastAccessTime);
1730 memcpy(fsw->wszName, wfd->cFileName, wlen * sizeof(WCHAR));
1731
1732 pOffsetW = (WORD*)((LPBYTE)pidl + pidl->mkid.cb - sizeof(WORD));
1733 *pOffsetW = (LPBYTE)fsw - (LPBYTE)pidl;
1734 TRACE("-- Set Value: %s\n",debugstr_w(fsw->wszName));
1735 }
1736 return pidl;
1737
1738 }
1739
1740 HRESULT _ILCreateFromPathW(LPCWSTR szPath, LPITEMIDLIST* ppidl)
1741 {
1742 HANDLE hFile;
1743 WIN32_FIND_DATAW stffile;
1744
1745 if (!ppidl)
1746 return E_INVALIDARG;
1747
1748 hFile = FindFirstFileW(szPath, &stffile);
1749 if (hFile == INVALID_HANDLE_VALUE)
1750 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
1751
1752 FindClose(hFile);
1753
1754 *ppidl = _ILCreateFromFindDataW(&stffile);
1755
1756 return *ppidl ? S_OK : E_OUTOFMEMORY;
1757 }
1758
1759 LPITEMIDLIST _ILCreateDrive(LPCWSTR lpszNew)
1760 {
1761 LPITEMIDLIST pidlOut;
1762
1763 TRACE("(%s)\n",debugstr_w(lpszNew));
1764
1765 pidlOut = _ILAlloc(PT_DRIVE, sizeof(DriveStruct));
1766 if (pidlOut)
1767 {
1768 LPSTR pszDest;
1769
1770 pszDest = _ILGetTextPointer(pidlOut);
1771 if (pszDest)
1772 {
1773 strcpy(pszDest, "x:\\");
1774 pszDest[0]=toupperW(lpszNew[0]);
1775 TRACE("-- create Drive: %s\n", debugstr_a(pszDest));
1776 }
1777 }
1778 return pidlOut;
1779 }
1780
1781 LPITEMIDLIST _ILCreateEntireNetwork(void)
1782 {
1783 LPITEMIDLIST pidlOut;
1784
1785 TRACE("\n");
1786
1787 pidlOut = _ILAlloc(PT_NETWORK, FIELD_OFFSET(PIDLDATA, u.network.szNames[sizeof("Entire Network")]));
1788 if (pidlOut)
1789 {
1790 LPPIDLDATA pData = _ILGetDataPointer(pidlOut);
1791
1792 pData->u.network.dummy = 0;
1793 strcpy(pData->u.network.szNames, "Entire Network");
1794 }
1795 return pidlOut;
1796 }
1797
1798 /**************************************************************************
1799 * _ILGetDrive()
1800 *
1801 * Gets the text for the drive eg. 'c:\'
1802 *
1803 * RETURNS
1804 * strlen (lpszText)
1805 */
1806 DWORD _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT uSize)
1807 {
1808 TRACE("(%p,%p,%u)\n",pidl,pOut,uSize);
1809
1810 if(_ILIsMyComputer(pidl))
1811 pidl = ILGetNext(pidl);
1812
1813 if (pidl && _ILIsDrive(pidl))
1814 return _ILSimpleGetText(pidl, pOut, uSize);
1815
1816 return 0;
1817 }
1818
1819 /**************************************************************************
1820 *
1821 * ### 2. section testing pidls ###
1822 *
1823 **************************************************************************
1824 * _ILIsUnicode()
1825 * _ILIsDesktop()
1826 * _ILIsMyComputer()
1827 * _ILIsSpecialFolder()
1828 * _ILIsDrive()
1829 * _ILIsFolder()
1830 * _ILIsValue()
1831 * _ILIsPidlSimple()
1832 */
1833 BOOL _ILIsUnicode(LPCITEMIDLIST pidl)
1834 {
1835 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1836
1837 TRACE("(%p)\n",pidl);
1838
1839 return (pidl && lpPData && PT_VALUEW == lpPData->type);
1840 }
1841
1842 BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
1843 {
1844 TRACE("(%p)\n",pidl);
1845
1846 return !pidl || !pidl->mkid.cb;
1847 }
1848
1849 BOOL _ILIsMyDocuments(LPCITEMIDLIST pidl)
1850 {
1851 IID *iid = _ILGetGUIDPointer(pidl);
1852
1853 TRACE("(%p)\n", pidl);
1854
1855 if (iid)
1856 return IsEqualIID(iid, &CLSID_MyDocuments);
1857 return FALSE;
1858 }
1859
1860 BOOL _ILIsNetHood(LPCITEMIDLIST pidl)
1861 {
1862 IID *iid = _ILGetGUIDPointer(pidl);
1863
1864 TRACE("(%p)\n", pidl);
1865
1866 if (iid)
1867 return IsEqualIID(iid, &CLSID_NetworkPlaces);
1868 return FALSE;
1869 }
1870
1871 BOOL _ILIsMyComputer(LPCITEMIDLIST pidl)
1872 {
1873 REFIID iid = _ILGetGUIDPointer(pidl);
1874
1875 TRACE("(%p)\n",pidl);
1876
1877 if (iid)
1878 return IsEqualIID(iid, &CLSID_MyComputer);
1879 return FALSE;
1880 }
1881
1882 BOOL _ILIsBitBucket(LPCITEMIDLIST pidl)
1883 {
1884 IID *iid = _ILGetGUIDPointer(pidl);
1885
1886 TRACE("(%p)\n", pidl);
1887
1888 if (iid)
1889 return IsEqualIID(iid, &CLSID_RecycleBin);
1890 return FALSE;
1891 }
1892
1893 BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl)
1894 {
1895 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1896
1897 TRACE("(%p)\n",pidl);
1898
1899 return (pidl && ( (lpPData && (PT_GUID== lpPData->type || PT_SHELLEXT== lpPData->type || PT_YAGUID == lpPData->type)) ||
1900 (pidl && pidl->mkid.cb == 0x00)
1901 ));
1902 }
1903
1904 BOOL _ILIsDrive(LPCITEMIDLIST pidl)
1905 {
1906 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1907
1908 TRACE("(%p)\n",pidl);
1909
1910 return (pidl && lpPData && (PT_DRIVE == lpPData->type ||
1911 PT_DRIVE1 == lpPData->type ||
1912 PT_DRIVE2 == lpPData->type ||
1913 PT_DRIVE3 == lpPData->type));
1914 }
1915
1916 BOOL _ILIsFolder(LPCITEMIDLIST pidl)
1917 {
1918 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1919
1920 TRACE("(%p)\n",pidl);
1921
1922 return (pidl && lpPData && (PT_FOLDER == lpPData->type || PT_FOLDER1 == lpPData->type));
1923 }
1924
1925 BOOL _ILIsValue(LPCITEMIDLIST pidl)
1926 {
1927 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1928
1929 TRACE("(%p)\n",pidl);
1930
1931 return (pidl && lpPData && PT_VALUE == lpPData->type);
1932 }
1933
1934 BOOL _ILIsCPanelStruct(LPCITEMIDLIST pidl)
1935 {
1936 LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
1937
1938 TRACE("(%p)\n",pidl);
1939
1940 return (pidl && lpPData && (lpPData->type == 0));
1941 }
1942
1943 /**************************************************************************
1944 * _ILIsPidlSimple
1945 */
1946 BOOL _ILIsPidlSimple(LPCITEMIDLIST pidl)
1947 {
1948 BOOL ret = TRUE;
1949
1950 if(! _ILIsDesktop(pidl)) /* pidl=NULL or mkid.cb=0 */
1951 {
1952 WORD len = pidl->mkid.cb;
1953 LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((const BYTE*)pidl) + len );
1954
1955 if (pidlnext->mkid.cb)
1956 ret = FALSE;
1957 }
1958
1959 TRACE("%s\n", ret ? "Yes" : "No");
1960 return ret;
1961 }
1962
1963 /**************************************************************************
1964 *
1965 * ### 3. section getting values from pidls ###
1966 */
1967
1968 /**************************************************************************
1969 * _ILSimpleGetText
1970 *
1971 * gets the text for the first item in the pidl (eg. simple pidl)
1972 *
1973 * returns the length of the string
1974 */
1975 DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
1976 {
1977 DWORD dwReturn=0;
1978 LPSTR szSrc;
1979 LPWSTR szSrcW;
1980 GUID const * riid;
1981 char szTemp[MAX_PATH];
1982
1983 TRACE("(%p %p %x)\n",pidl,szOut,uOutSize);
1984
1985 if (!pidl)
1986 return 0;
1987
1988 if (szOut)
1989 *szOut = 0;
1990
1991 if (_ILIsDesktop(pidl))
1992 {
1993 /* desktop */
1994 if (HCR_GetClassNameA(&CLSID_ShellDesktop, szTemp, MAX_PATH))
1995 {
1996 if (szOut)
1997 lstrcpynA(szOut, szTemp, uOutSize);
1998
1999 dwReturn = strlen (szTemp);
2000 }
2001 }
2002 else if (( szSrc = _ILGetTextPointer(pidl) ))
2003 {
2004 /* filesystem */
2005 if (szOut)
2006 lstrcpynA(szOut, szSrc, uOutSize);
2007
2008 dwReturn = strlen(szSrc);
2009 }
2010 else if (( szSrcW = _ILGetTextPointerW(pidl) ))
2011 {
2012 /* unicode filesystem */
2013 WideCharToMultiByte(CP_ACP,0,szSrcW, -1, szTemp, MAX_PATH, NULL, NULL);
2014
2015 if (szOut)
2016 lstrcpynA(szOut, szTemp, uOutSize);
2017
2018 dwReturn = strlen (szTemp);
2019 }
2020 else if (( riid = _ILGetGUIDPointer(pidl) ))
2021 {
2022 /* special folder */
2023 if ( HCR_GetClassNameA(riid, szTemp, MAX_PATH) )
2024 {
2025 if (szOut)
2026 lstrcpynA(szOut, szTemp, uOutSize);
2027
2028 dwReturn = strlen (szTemp);
2029 }
2030 }
2031 else
2032 {
2033 ERR("-- no text\n");
2034 }
2035
2036 TRACE("-- (%p=%s 0x%08x)\n",szOut,debugstr_a(szOut),dwReturn);
2037 return dwReturn;
2038 }
2039
2040 /**************************************************************************
2041 * _ILSimpleGetTextW
2042 *
2043 * gets the text for the first item in the pidl (eg. simple pidl)
2044 *
2045 * returns the length of the string
2046 */
2047 DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR szOut, UINT uOutSize)
2048 {
2049 DWORD dwReturn;
2050 FileStructW *pFileStructW = _ILGetFileStructW(pidl);
2051
2052 TRACE("(%p %p %x)\n",pidl,szOut,uOutSize);
2053
2054 if (pFileStructW) {
2055 lstrcpynW(szOut, pFileStructW->wszName, uOutSize);
2056 dwReturn = lstrlenW(pFileStructW->wszName);
2057 } else {
2058 GUID const * riid;
2059 WCHAR szTemp[MAX_PATH];
2060 LPSTR szSrc;
2061 LPWSTR szSrcW;
2062 dwReturn=0;
2063
2064 if (!pidl)
2065 return 0;
2066
2067 if (szOut)
2068 *szOut = 0;
2069
2070 if (_ILIsDesktop(pidl))
2071 {
2072 /* desktop */
2073 if (HCR_GetClassNameW(&CLSID_ShellDesktop, szTemp, MAX_PATH))
2074 {
2075 if (szOut)
2076 lstrcpynW(szOut, szTemp, uOutSize);
2077
2078 dwReturn = lstrlenW (szTemp);
2079 }
2080 }
2081 else if (( szSrcW = _ILGetTextPointerW(pidl) ))
2082 {
2083 /* unicode filesystem */
2084 if (szOut)
2085 lstrcpynW(szOut, szSrcW, uOutSize);
2086
2087 dwReturn = lstrlenW(szSrcW);
2088 }
2089 else if (( szSrc = _ILGetTextPointer(pidl) ))
2090 {
2091 /* filesystem */
2092 MultiByteToWideChar(CP_ACP, 0, szSrc, -1, szTemp, MAX_PATH);
2093
2094 if (szOut)
2095 lstrcpynW(szOut, szTemp, uOutSize);
2096
2097 dwReturn = lstrlenW (szTemp);
2098 }
2099 else if (( riid = _ILGetGUIDPointer(pidl) ))
2100 {
2101 /* special folder */
2102 if ( HCR_GetClassNameW(riid, szTemp, MAX_PATH) )
2103 {
2104 if (szOut)
2105 lstrcpynW(szOut, szTemp, uOutSize);
2106
2107 dwReturn = lstrlenW (szTemp);
2108 }
2109 }
2110 else
2111 {
2112 ERR("-- no text\n");
2113 }
2114 }
2115
2116 TRACE("-- (%p=%s 0x%08x)\n",szOut,debugstr_w(szOut),dwReturn);
2117 return dwReturn;
2118 }
2119
2120 /**************************************************************************
2121 *
2122 * ### 4. getting pointers to parts of pidls ###
2123 *
2124 **************************************************************************
2125 * _ILGetDataPointer()
2126 */
2127 LPPIDLDATA _ILGetDataPointer(LPCITEMIDLIST pidl)
2128 {
2129 if(!_ILIsEmpty(pidl))
2130 return (LPPIDLDATA)pidl->mkid.abID;
2131 return NULL;
2132 }
2133
2134 /**************************************************************************
2135 * _ILGetTextPointerW()
2136 * gets a pointer to the unicode long filename string stored in the pidl
2137 */
2138 static LPWSTR _ILGetTextPointerW(LPCITEMIDLIST pidl)
2139 {
2140 /* TRACE(pidl,"(pidl%p)\n", pidl);*/
2141
2142 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
2143
2144 if (!pdata)
2145 return NULL;
2146
2147 switch (pdata->type)
2148 {
2149 case PT_GUID:
2150 case PT_SHELLEXT:
2151 case PT_YAGUID:
2152 return NULL;
2153
2154 case PT_DRIVE:
2155 case PT_DRIVE1:
2156 case PT_DRIVE2:
2157 case PT_DRIVE3:
2158 /*return (LPSTR)&(pdata->u.drive.szDriveName);*/
2159 return NULL;
2160
2161 case PT_FOLDER:
2162 case PT_FOLDER1:
2163 case PT_VALUE:
2164 case PT_IESPECIAL1:
2165 case PT_IESPECIAL2:
2166 /*return (LPSTR)&(pdata->u.file.szNames);*/
2167 return NULL;
2168
2169 case PT_WORKGRP:
2170 case PT_COMP:
2171 case PT_NETWORK:
2172 case PT_NETPROVIDER:
2173 case PT_SHARE:
2174 /*return (LPSTR)&(pdata->u.network.szNames);*/
2175 return NULL;
2176
2177 case PT_VALUEW:
2178 return (LPWSTR)pdata->u.file.szNames;
2179
2180 #ifdef __REACTOS__ /* r54423 */
2181 case PT_CPLAPPLET:
2182 return pdata->u.cpanel.szName;
2183 #endif
2184
2185 }
2186 return NULL;
2187 }
2188
2189
2190 /**************************************************************************
2191 * _ILGetTextPointer()
2192 * gets a pointer to the long filename string stored in the pidl
2193 */
2194 LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
2195 {
2196 /* TRACE(pidl,"(pidl%p)\n", pidl);*/
2197
2198 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
2199
2200 if (!pdata)
2201 return NULL;
2202
2203 switch (pdata->type)
2204 {
2205 case PT_GUID:
2206 case PT_SHELLEXT:
2207 case PT_YAGUID:
2208 return NULL;
2209
2210 case PT_DRIVE:
2211 case PT_DRIVE1:
2212 case PT_DRIVE2:
2213 case PT_DRIVE3:
2214 return pdata->u.drive.szDriveName;
2215
2216 case PT_FOLDER:
2217 case PT_FOLDER1:
2218 case PT_VALUE:
2219 case PT_IESPECIAL1:
2220 case PT_IESPECIAL2:
2221 return pdata->u.file.szNames;
2222
2223 case PT_WORKGRP:
2224 case PT_COMP:
2225 case PT_NETWORK:
2226 case PT_NETPROVIDER:
2227 case PT_SHARE:
2228 return pdata->u.network.szNames;
2229 }
2230 return NULL;
2231 }
2232
2233 /**************************************************************************
2234 * _ILGetSTextPointer()
2235 * gets a pointer to the short filename string stored in the pidl
2236 */
2237 static LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl)
2238 {
2239 /* TRACE(pidl,"(pidl%p)\n", pidl); */
2240
2241 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
2242
2243 if (!pdata)
2244 return NULL;
2245
2246 switch (pdata->type)
2247 {
2248 case PT_FOLDER:
2249 case PT_VALUE:
2250 case PT_IESPECIAL1:
2251 case PT_IESPECIAL2:
2252 return pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1;
2253
2254 case PT_WORKGRP:
2255 return pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1;
2256 }
2257 return NULL;
2258 }
2259
2260 /**************************************************************************
2261 * _ILGetGUIDPointer()
2262 *
2263 * returns reference to guid stored in some pidls
2264 */
2265 IID* _ILGetGUIDPointer(LPCITEMIDLIST pidl)
2266 {
2267 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
2268
2269 TRACE("%p\n", pidl);
2270
2271 if (!pdata)
2272 return NULL;
2273
2274 TRACE("pdata->type 0x%04x\n", pdata->type);
2275 switch (pdata->type)
2276 {
2277 case PT_SHELLEXT:
2278 case PT_GUID:
2279 case PT_YAGUID:
2280 return &(pdata->u.guid.guid);
2281
2282 default:
2283 TRACE("Unknown pidl type 0x%04x\n", pdata->type);
2284 break;
2285 }
2286 return NULL;
2287 }
2288
2289 /******************************************************************************
2290 * _ILGetFileStructW [Internal]
2291 *
2292 * Get pointer the a SHITEMID's FileStructW field if present
2293 *
2294 * PARAMS
2295 * pidl [I] The SHITEMID
2296 *
2297 * RETURNS
2298 * Success: Pointer to pidl's FileStructW field.
2299 * Failure: NULL
2300 */
2301 FileStructW* _ILGetFileStructW(LPCITEMIDLIST pidl) {
2302 FileStructW *pFileStructW;
2303 WORD cbOffset;
2304
2305 if (!(_ILIsValue(pidl) || _ILIsFolder(pidl)))
2306 return NULL;
2307
2308 cbOffset = *(const WORD *)((const BYTE *)pidl + pidl->mkid.cb - sizeof(WORD));
2309 pFileStructW = (FileStructW*)((LPBYTE)pidl + cbOffset);
2310
2311 /* Currently I don't see a fool prove way to figure out if a pidl is for sure of WinXP
2312 * style with a FileStructW member. If we switch all our shellfolder-implementations to
2313 * the new format, this won't be a problem. For now, we do as many sanity checks as possible. */
2314 if ((cbOffset & 0x1) || /* FileStructW member is word aligned in the pidl */
2315 /* FileStructW is positioned after FileStruct */
2316 cbOffset < sizeof(pidl->mkid.cb) + sizeof(PIDLTYPE) + sizeof(FileStruct) ||
2317 /* There has to be enough space at cbOffset in the pidl to hold FileStructW and cbOffset */
2318 cbOffset > pidl->mkid.cb - sizeof(cbOffset) - sizeof(FileStructW) ||
2319 pidl->mkid.cb != cbOffset + pFileStructW->cbLen)
2320 {
2321 WARN("Invalid pidl format (cbOffset = %d)!\n", cbOffset);
2322 return NULL;
2323 }
2324
2325 return pFileStructW;
2326 }
2327
2328 /*************************************************************************
2329 * _ILGetFileDateTime
2330 *
2331 * Given the ItemIdList, get the FileTime
2332 *
2333 * PARAMS
2334 * pidl [I] The ItemIDList
2335 * pFt [I] the resulted FILETIME of the file
2336 *
2337 * RETURNS
2338 * True if Successful
2339 *
2340 * NOTES
2341 *
2342 */
2343 BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt)
2344 {
2345 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
2346
2347 if (!pdata)
2348 return FALSE;
2349
2350 switch (pdata->type)
2351 {
2352 case PT_FOLDER:
2353 case PT_VALUE:
2354 DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt);
2355 break;
2356 default:
2357 return FALSE;
2358 }
2359 return TRUE;
2360 }
2361
2362 BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
2363 {
2364 FILETIME ft,lft;
2365 SYSTEMTIME time;
2366 BOOL ret;
2367
2368 if (_ILGetFileDateTime( pidl, &ft ))
2369 {
2370 FileTimeToLocalFileTime(&ft, &lft);
2371 FileTimeToSystemTime (&lft, &time);
2372
2373 ret = GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize);
2374 if (ret)
2375 {
2376 /* Append space + time without seconds */
2377 pOut[ret-1] = ' ';
2378 GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &pOut[ret], uOutSize - ret);
2379 }
2380 }
2381 else
2382 {
2383 pOut[0] = '\0';
2384 ret = FALSE;
2385 }
2386 return ret;
2387 }
2388
2389 /*************************************************************************
2390 * _ILGetFileSize
2391 *
2392 * Given the ItemIdList, get the FileSize
2393 *
2394 * PARAMS
2395 * pidl [I] The ItemIDList
2396 * pOut [I] The buffer to save the result
2397 * uOutsize [I] The size of the buffer
2398 *
2399 * RETURNS
2400 * The FileSize
2401 *
2402 * NOTES
2403 * pOut can be null when no string is needed
2404 *
2405 */
2406 DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
2407 {
2408 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
2409 DWORD dwSize;
2410
2411 if (!pdata)
2412 return 0;
2413
2414 switch (pdata->type)
2415 {
2416 case PT_VALUE:
2417 dwSize = pdata->u.file.dwFileSize;
2418 if (pOut)
2419 StrFormatKBSizeA(dwSize, pOut, uOutSize);
2420 return dwSize;
2421 }
2422 if (pOut)
2423 *pOut = 0x00;
2424 return 0;
2425 }
2426
2427 BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
2428 {
2429 char szTemp[MAX_PATH];
2430 const char * pPoint;
2431 LPCITEMIDLIST pidlTemp=pidl;
2432
2433 TRACE("pidl=%p\n",pidl);
2434
2435 if (!pidl)
2436 return FALSE;
2437
2438 pidlTemp = ILFindLastID(pidl);
2439
2440 if (!_ILIsValue(pidlTemp))
2441 return FALSE;
2442 if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH))
2443 return FALSE;
2444
2445 pPoint = PathFindExtensionA(szTemp);
2446
2447 if (!*pPoint)
2448 return FALSE;
2449
2450 pPoint++;
2451 lstrcpynA(pOut, pPoint, uOutSize);
2452 TRACE("%s\n",pOut);
2453
2454 return TRUE;
2455 }
2456
2457 /*************************************************************************
2458 * _ILGetFileType
2459 *
2460 * Given the ItemIdList, get the file type description
2461 *
2462 * PARAMS
2463 * pidl [I] The ItemIDList (simple)
2464 * pOut [I] The buffer to save the result
2465 * uOutsize [I] The size of the buffer
2466 *
2467 * RETURNS
2468 * nothing
2469 *
2470 * NOTES
2471 * This function copies as much as possible into the buffer.
2472 */
2473 void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
2474 {
2475 #ifdef __REACTOS__ /* r32966 */
2476 char sType[64];
2477 #endif
2478
2479 if(_ILIsValue(pidl))
2480 {
2481 char sTemp[64];
2482
2483 if(uOutSize > 0)
2484 pOut[0] = 0;
2485 #ifdef __REACTOS__ /* r32966 */
2486 if (_ILGetExtension (pidl, sType, 64))
2487 {
2488 if (HCR_MapTypeToValueA(sType, sTemp, 64, TRUE))
2489 {
2490 /* retrieve description */
2491 if(HCR_MapTypeToValueA(sTemp, pOut, uOutSize, FALSE ))
2492 return;
2493 }
2494 /* display Ext-file as description */
2495 _strupr(sType);
2496 /* load localized file string */
2497 sTemp[0] = '\0';
2498 if(LoadStringA(shell32_hInstance, IDS_ANY_FILE, sTemp, 64))
2499 {
2500 sTemp[63] = '\0';
2501 StringCchPrintfA(pOut, uOutSize, sTemp, sType);
2502 }
2503 }
2504 #else
2505 if (_ILGetExtension (pidl, sTemp, 64))
2506 {
2507 if (!( HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE)
2508 && HCR_MapTypeToValueA(sTemp, pOut, uOutSize, FALSE )))
2509 {
2510 lstrcpynA (pOut, sTemp, uOutSize - 6);
2511 strcat (pOut, "-file");
2512 }
2513 }
2514 #endif
2515 }
2516 else
2517 #ifdef __REACTOS__ /* r32966 */
2518 {
2519 pOut[0] = '\0';
2520 LoadStringA(shell32_hInstance, IDS_DIRECTORY, pOut, uOutSize);
2521 /* make sure its null terminated */
2522 pOut[uOutSize-1] = '\0';
2523 }
2524 #else
2525 lstrcpynA(pOut, "Folder", uOutSize);
2526 #endif
2527 }
2528
2529 /*************************************************************************
2530 * _ILGetFileAttributes
2531 *
2532 * Given the ItemIdList, get the Attrib string format
2533 *
2534 * PARAMS
2535 * pidl [I] The ItemIDList
2536 * pOut [I] The buffer to save the result
2537 * uOutsize [I] The size of the Buffer
2538 *
2539 * RETURNS
2540 * Attributes
2541 *
2542 * FIXME
2543 * return value 0 in case of error is a valid return value
2544 *
2545 */
2546 DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
2547 {
2548 LPPIDLDATA pData = _ILGetDataPointer(pidl);
2549 WORD wAttrib = 0;
2550 int i;
2551
2552 if (!pData)
2553 return 0;
2554
2555 switch(pData->type)
2556 {
2557 case PT_FOLDER:
2558 case PT_VALUE:
2559 wAttrib = pData->u.file.uFileAttribs;
2560 break;
2561 }
2562
2563 if(uOutSize >= 6)
2564 {
2565 i=0;
2566 if(wAttrib & FILE_ATTRIBUTE_READONLY)
2567 pOut[i++] = 'R';
2568 if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
2569 pOut[i++] = 'H';
2570 if(wAttrib & FILE_ATTRIBUTE_SYSTEM)
2571 pOut[i++] = 'S';
2572 if(wAttrib & FILE_ATTRIBUTE_ARCHIVE)
2573 pOut[i++] = 'A';
2574 if(wAttrib & FILE_ATTRIBUTE_COMPRESSED)
2575 pOut[i++] = 'C';
2576 pOut[i] = 0x00;
2577 }
2578 return wAttrib;
2579 }
2580
2581 /*************************************************************************
2582 * ILFreeaPidl
2583 *
2584 * frees an aPidl struct
2585 */
2586 void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl)
2587 {
2588 UINT i;
2589
2590 if (apidl)
2591 {
2592 for (i = 0; i < cidl; i++)
2593 SHFree(apidl[i]);
2594 SHFree(apidl);
2595 }
2596 }
2597
2598 /*************************************************************************
2599 * ILCopyaPidl
2600 *
2601 * copies an aPidl struct
2602 */
2603 PITEMID_CHILD* _ILCopyaPidl(PCUITEMID_CHILD_ARRAY apidlsrc, UINT cidl)
2604 {
2605 UINT i;
2606 PITEMID_CHILD *apidldest;
2607
2608 if (!apidlsrc)
2609 return NULL;
2610
2611 apidldest = SHAlloc(cidl * sizeof(PITEMID_CHILD));
2612
2613 for (i = 0; i < cidl; i++)
2614 apidldest[i] = ILClone(apidlsrc[i]);
2615
2616 return apidldest;
2617 }
2618
2619 /*************************************************************************
2620 * _ILCopyCidaToaPidl
2621 *
2622 * creates aPidl from CIDA
2623 */
2624 LPITEMIDLIST* _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, const CIDA * cida)
2625 {
2626 UINT i;
2627 LPITEMIDLIST *dst;
2628
2629 dst = SHAlloc(cida->cidl * sizeof(LPITEMIDLIST));
2630 if (!dst)
2631 return NULL;
2632
2633 if (pidl)
2634 *pidl = ILClone((LPCITEMIDLIST)(&((const BYTE*)cida)[cida->aoffset[0]]));
2635
2636 for (i = 0; i < cida->cidl; i++)
2637 dst[i] = ILClone((LPCITEMIDLIST)(&((const BYTE*)cida)[cida->aoffset[i + 1]]));
2638
2639 return dst;
2640 }