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