ReactOS 0.4.15-dev-8222-g9164419
shellpath.c
Go to the documentation of this file.
1/*
2 * Path Functions
3 *
4 * Copyright 1998, 1999, 2000 Juergen Schmied
5 * Copyright 2004 Juan Lang
6 * Copyright 2018-2022 Katayama Hirofumi MZ
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 *
22 * NOTES:
23 *
24 * Many of these functions are in SHLWAPI.DLL also
25 *
26 */
27
28#define WIN32_NO_STATUS
29#define _INC_WINDOWS
30#define COBJMACROS
31
32#include <wine/config.h>
33
34#include <windef.h>
35#include <winbase.h>
36#include <shlobj.h>
37#include <undocshell.h>
38#include <shlwapi.h>
39#include <sddl.h>
40#include <strsafe.h>
41#include <wine/debug.h>
42#include <wine/unicode.h>
43#include <assert.h>
44
45#include <shlwapi_undoc.h>
46#include <shellutils.h>
47
48#include <userenv.h>
49
50#include "pidl.h"
51#include "shell32_main.h"
52#include "shresdef.h"
53
54#undef _WIN32_WINNT
55#define _WIN32_WINNT _WIN32_WINNT_WS03
56
58
59static const BOOL is_win64 = sizeof(void *) > sizeof(int);
60
61/* FIXME: Remove this */
62typedef enum _NT_PRODUCT_TYPE
63{
68
69/* FIXME: We cannot refresh the RtlGetNtProductType value before reboot. */
70static BOOL
72{
73 HKEY hKey;
74 LONG error;
75 WCHAR szValue[9];
76 DWORD cbValue;
77 static DWORD s_dwProductType = 0;
78
79 if (s_dwProductType != 0)
80 {
81 *ProductType = s_dwProductType;
82 return TRUE;
83 }
84
85 *ProductType = NtProductServer;
86
87 error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_READ, &hKey);
88 if (error)
89 return FALSE;
90
91 cbValue = sizeof(szValue);
92 error = RegGetValueW(hKey, NULL, L"ProductType", RRF_RT_REG_SZ, NULL, (PVOID)szValue, &cbValue);
93 if (!error)
94 {
95 if (lstrcmpW(szValue, L"WinNT") == 0)
96 *ProductType = NtProductWinNt;
97 else if (lstrcmpW(szValue, L"LanmanNT") == 0)
98 *ProductType = NtProductLanManNt;
99 }
100
101 s_dwProductType = *ProductType;
102
104 return TRUE;
105}
106
108{
109 WCHAR szRoot[] = L"C:\\";
110 assert(L'A' + iDrive <= L'Z');
111 szRoot[0] = (WCHAR)(L'A' + iDrive);
112 return GetDriveTypeW(szRoot) == DRIVE_REMOVABLE;
113}
114
115/*
116 ########## Combining and Constructing paths ##########
117*/
118
119static BOOL WINAPI
121 _Inout_ LPWSTR pszPath,
122 _In_opt_ LPCWSTR *ppszDirs,
123 _In_ BOOL bDoSearch,
124 _In_ DWORD dwWhich)
125{
126 if (*PathFindExtensionW(pszPath) != 0)
127 return FALSE;
128
129 if (bDoSearch)
130 return PathFindOnPathExW(pszPath, ppszDirs, dwWhich);
131 else
132 return PathFileExistsDefExtW(pszPath, dwWhich);
133}
134
135#if (_WIN32_WINNT >= _WIN32_WINNT_WS03)
137{
138 return PathIsUNCW(path) || (PathGetDriveNumberW(path) != -1 && path[2] == L'\\');
139}
140
142{
144 DWORD cch;
145
146 if (path == NULL)
147 return FALSE;
149 if (!cch || cch > _countof(path1))
150 return FALSE;
151 return (PathCombineW(path, path1, path) != NULL);
152}
153#endif
154
156
157static VOID WINAPI
159{
160 INT iDrive, cchPathLeft;
161 WCHAR szTemp[MAX_PATH], szRoot[MAX_PATH];
162 PWCHAR pchTemp = szTemp, pchPath;
163 BOOL bLFN;
164
165 TRACE("(%s,%s,0x%08x)\n", debugstr_w(pszPath), debugstr_w(pszDir), dwFlags);
166
167 /* Save pszPath path into szTemp for rebuilding the path later */
168 if (FAILED(StringCchCopyW(szTemp, _countof(szTemp), pszPath)))
169 return;
170
171 /* Replace every '/' by '\' */
172 FixSlashesAndColonW(szTemp);
173
174 cchPathLeft = MAX_PATH;
175
176 /* Build the root-like path on pszPath, and set pchTemp */
177 if (!PathIsUNCW(szTemp))
178 {
179 /*
180 * Non-UNC path.
181 * Determine and normalize the root drive.
182 */
183 iDrive = PathGetDriveNumberW(szTemp);
184 if (iDrive == -1)
185 {
186 /*
187 * No drive was specified in the path. Try to find one from the
188 * optional directory (if this fails, fall back to the one of the
189 * Windows directory).
190 */
191 if (!pszDir || FAILED(StringCchCopyW(szRoot, _countof(szRoot), pszDir)))
192 {
193 /* pszDir was invalid or NULL. Fall back to the
194 * Windows directory and find its root. */
195 szRoot[0] = UNICODE_NULL;
196 GetWindowsDirectoryW(szRoot, _countof(szRoot));
197 iDrive = PathGetDriveNumberW(szRoot);
198 if (iDrive != -1)
199 PathBuildRootW(szRoot, iDrive);
200 }
201
202 if (szTemp[0] == L'\\')
203 {
204 PathStripToRootW(szRoot);
205 }
206 }
207 else
208 {
209 /*
210 * A drive is specified in the path, that can be either of the
211 * form 'C:\xxx' or of the form 'C:xxx' (relative path). Isolate
212 * the root part 'C:' and the rest of the path 'xxx' in pchTemp.
213 */
214 PathBuildRootW(szRoot, iDrive);
215 pchTemp += 2;
216 if (*pchTemp == L'\\')
217 ++pchTemp;
218 }
219
220 bLFN = IsLFNDriveW(szRoot);
221 if (!bLFN)
222 {
223 PWCHAR pch;
224 for (pch = pchTemp; *pch != UNICODE_NULL; ++pch)
225 {
226#define VALID_SHORT_PATH_CHAR_CLASSES ( \
227 PATH_CHAR_CLASS_DOT | \
228 PATH_CHAR_CLASS_BACKSLASH | \
229 PATH_CHAR_CLASS_COLON | \
230 PATH_CHAR_CLASS_OTHER_VALID \
231)
233 {
234 *pch = L'_';
235 }
236 }
237 }
238
239 StringCchCopyW(pszPath, MAX_PATH, szRoot);
240 cchPathLeft -= lstrlenW(pszPath) + 1;
241 }
242 else /* UNC path: Begins with double backslash */
243 {
244 bLFN = IsLFNDriveW(pchTemp);
245 if (bLFN)
246 {
247 pszPath[2] = UNICODE_NULL; /* Cut off */
248 cchPathLeft -= (2 + 1);
249 pchTemp += 2;
250 }
251 else
252 {
253 PWCHAR pchSlash = StrChrW(pszPath + 2, L'\\');
254 if (pchSlash)
255 pchSlash = StrChrW(pchSlash + 1, L'\\');
256
257 if (pchSlash)
258 {
259 *(pchSlash + 1) = UNICODE_NULL; /* Cut off */
260 pchTemp += pchSlash - pszPath;
261 cchPathLeft -= (INT)(SIZE_T)(pchSlash - pszPath) + 1;
262 }
263 else
264 {
265 bLFN = TRUE;
266 pszPath[2] = UNICODE_NULL; /* Cut off */
267 cchPathLeft -= 2;
268 pchTemp += 2;
269 }
270 }
271 }
272 /* Now pszPath is a root-like path or an empty string. */
273
274 /* Start appending the path components of szTemp to pszPath. */
275 while (*pchTemp && cchPathLeft > 0)
276 {
277 /* Collapse any .\ and ..\ parts in the path */
278 if (*pchTemp == L'.')
279 {
280 BOOL bDots = FALSE; /* '.' or '..' ? */
281
282 if (pchTemp[1] == UNICODE_NULL || pchTemp[1] == L'\\')
283 {
284 /* Component '.' */
285 bDots = TRUE;
286 }
287 else if (pchTemp[1] == L'.' && (pchTemp[2] == UNICODE_NULL || pchTemp[2] == L'\\'))
288 {
289 /* Component '..' */
290 PathRemoveFileSpecW(pszPath); /* Remove the last component from pszPath */
291 bDots = TRUE;
292 }
293
294 /* If a '.' or '..' was encountered, skip to the next component */
295 if (bDots)
296 {
297 while (*pchTemp && *pchTemp != L'\\')
298 {
299 ++pchTemp;
300 }
301
302 while (*pchTemp == L'\\')
303 {
304 ++pchTemp;
305 }
306
307 continue;
308 }
309 }
310
311 /* Otherwise, copy the other path component */
312
313 if (!PathAddBackslashW(pszPath)) /* Append a backslash at the end */
314 break;
315
316 --cchPathLeft;
317
318 pchPath = &pszPath[lstrlenW(pszPath)];
319
320 if (!bLFN) /* Not LFN? */
321 {
322 /* Copy MS-DOS 8.3 filename */
323 PWCHAR pchDot = NULL;
324 INT ich;
325 WCHAR szTitle[8 + 1] = L"";
326 INT cchTitle = 0;
327 WCHAR szDotExtension[1 + 3 + 1] = L"";
328 INT cchDotExtension = 0;
329
330 /* Copy the component to szTitle and szDotExtension... */
331 while (*pchTemp && *pchTemp != L'\\')
332 {
333 if (*pchTemp == L'.')
334 {
335 pchDot = pchTemp; /* Remember the last position */
336
337 /* Clear szDotExtension */
338 cchDotExtension = 0;
339 ZeroMemory(szDotExtension, sizeof(szDotExtension));
340 }
341
342 if (pchDot)
343 {
344 if (cchDotExtension < 1 + 3)
345 szDotExtension[cchDotExtension++] = *pchTemp;
346 }
347 else
348 {
349 if (cchTitle < 8)
350 szTitle[cchTitle++] = *pchTemp;
351 }
352
353 ++pchTemp;
354 }
355
356 /* Add file title 'szTitle' to pchPath */
357 for (ich = 0; szTitle[ich] && cchPathLeft > 0; ++ich)
358 {
359 *pchPath++ = szTitle[ich];
360 --cchPathLeft;
361 }
362
363 /* Add file extension 'szDotExtension' to pchPath */
364 if (pchDot)
365 {
366 for (ich = 0; szDotExtension[ich] && cchPathLeft > 0; ++ich)
367 {
368 *pchPath++ = szDotExtension[ich];
369 --cchPathLeft;
370 }
371 }
372 }
373 else /* LFN */
374 {
375 /* Copy the component up to the next separator */
376 while (*pchTemp != UNICODE_NULL && *pchTemp != L'\\' && cchPathLeft > 0)
377 {
378 *pchPath++ = *pchTemp++;
379 --cchPathLeft;
380 }
381 }
382
383 /* Skip the backslashes */
384 while (*pchTemp == L'\\')
385 {
386 ++pchTemp;
387 }
388
389 /* Keep null-terminated */
390 *pchPath = UNICODE_NULL;
391 }
392
393 /* Remove any trailing backslash */
394 PathRemoveBackslashW(pszPath);
395
396 if (!(dwFlags & 1)) /* Remove the trailing dot? */
397 {
398 pchPath = CharPrevW(pszPath, pszPath + lstrlenW(pszPath));
399 if (*pchPath == L'.')
400 *pchPath = UNICODE_NULL;
401 }
402}
403
404/*************************************************************************
405 * PathAppend [SHELL32.36]
406 */
408 LPVOID lpszPath1,
409 LPCVOID lpszPath2)
410{
411 if (SHELL_OsIsUnicode())
412 return PathAppendW(lpszPath1, lpszPath2);
413 return PathAppendA(lpszPath1, lpszPath2);
414}
415
416/*************************************************************************
417 * PathGetExtensionA [internal]
418 *
419 * NOTES
420 * exported by ordinal
421 * return value points to the first char after the dot
422 */
424{
425 TRACE("(%s)\n",lpszPath);
426
427 lpszPath = PathFindExtensionA(lpszPath);
428 return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
429}
430
431/*************************************************************************
432 * PathGetExtensionW [internal]
433 */
435{
436 TRACE("(%s)\n",debugstr_w(lpszPath));
437
438 lpszPath = PathFindExtensionW(lpszPath);
439 return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
440}
441
442/*************************************************************************
443 * SHPathGetExtension [SHELL32.158]
444 */
446{
447 return PathGetExtensionW(lpszPath);
448}
449
450/*************************************************************************
451 * PathRemoveFileSpec [SHELL32.35]
452 */
454{
455 if (SHELL_OsIsUnicode())
456 return PathRemoveFileSpecW(lpszPath);
457 return PathRemoveFileSpecA(lpszPath);
458}
459
460/*
461 Path Manipulations
462*/
463
464/*************************************************************************
465 * PathGetShortPathA [internal]
466 */
467static void PathGetShortPathA(LPSTR pszPath)
468{
470
471 TRACE("%s\n", pszPath);
472
473 if (GetShortPathNameA(pszPath, path, MAX_PATH))
474 {
475 lstrcpyA(pszPath, path);
476 }
477}
478
479/*************************************************************************
480 * PathGetShortPathW [internal]
481 */
482static void PathGetShortPathW(LPWSTR pszPath)
483{
485
486 TRACE("%s\n", debugstr_w(pszPath));
487
488 if (GetShortPathNameW(pszPath, path, MAX_PATH))
489 {
490 lstrcpyW(pszPath, path);
491 }
492}
493
494/*************************************************************************
495 * PathGetShortPath [SHELL32.92]
496 */
498{
500 PathGetShortPathW(pszPath);
501 PathGetShortPathA(pszPath);
502}
503
504/*
505 ########## Path Testing ##########
506*/
507
508/*************************************************************************
509 * PathIsRoot [SHELL32.29]
510 */
512{
513 if (SHELL_OsIsUnicode())
514 return PathIsRootW(lpszPath);
515 return PathIsRootA(lpszPath);
516}
517
518/*************************************************************************
519 * PathIsExeA [internal]
520 */
521static BOOL PathIsExeA (LPCSTR lpszPath)
522{
523 LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
524 int i;
525 static const char * const lpszExtensions[] =
526 {"exe", "com", "pif", "cmd", "bat", "scf", "scr", NULL };
527
528 TRACE("path=%s\n",lpszPath);
529
530 for(i=0; lpszExtensions[i]; i++)
531 if (!lstrcmpiA(lpszExtension,lpszExtensions[i])) return TRUE;
532
533 return FALSE;
534}
535
536/*************************************************************************
537 * PathIsExeW [internal]
538 */
540{
541 LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
542 int i;
543 static const WCHAR lpszExtensions[][4] =
544 {L"exe", L"com", L"pif", L"cmd", L"bat", L"scf", L"scr", L"" };
545
546 TRACE("path=%s\n",debugstr_w(lpszPath));
547
548 for(i=0; lpszExtensions[i][0]; i++)
549 if (!wcsicmp(lpszExtension,lpszExtensions[i])) return TRUE;
550
551 return FALSE;
552}
553
554/*************************************************************************
555 * PathIsExe [SHELL32.43]
556 */
558{
559 if (SHELL_OsIsUnicode())
560 return PathIsExeW (path);
561 return PathIsExeA(path);
562}
563
564/*************************************************************************
565 * PathFileExists [SHELL32.45]
566 */
568{
569 if (SHELL_OsIsUnicode())
570 return PathFileExistsW (lpszPath);
571 return PathFileExistsA (lpszPath);
572}
573
574/*************************************************************************
575 * IsLFNDriveA [SHELL32.41]
576 */
578{
579 WCHAR szBuffW[MAX_PATH], *pszW = NULL;
580 if (lpszPath)
581 {
582 SHAnsiToUnicode(lpszPath, szBuffW, _countof(szBuffW));
583 pszW = szBuffW;
584 }
585 return IsLFNDriveW(pszW);
586}
587
588/*************************************************************************
589 * IsLFNDriveW [SHELL32.42]
590 */
592{
593 DWORD cchMaxFileName, iDrive;
594 WCHAR szRoot[MAX_PATH];
595
596 if (lpszPath == NULL || lpszPath[0] == UNICODE_NULL)
597 {
598 szRoot[0] = 0;
599 GetWindowsDirectoryW(szRoot, _countof(szRoot));
600 lpszPath = szRoot;
601 }
602
603 if (PathIsUNCW(lpszPath))
604 {
605 StringCchCopyW(szRoot, _countof(szRoot), lpszPath);
606 PathStripToRootW(szRoot);
607
608 if (StrChrW(szRoot + 2, L'\\') == NULL)
609 return TRUE; /* LFN */
610
611 StringCchCatW(szRoot, _countof(szRoot), L"\\"); /* Add a backslash */
612 }
613 else
614 {
615 iDrive = ((lpszPath[0] - L'A') & 0x1F);
616 PathBuildRootW(szRoot, iDrive);
617
618 if (!IsRemovableDrive(iDrive))
619 {
620 /* FIXME: Cache correctly */
621 }
622 }
623
624#define MSDOS_8DOT3_LEN 12 /* MS-DOS 8.3 filename == length 12 */
625
626 /* GetVolumeInformation requires a root path */
627 if (!GetVolumeInformationW(szRoot, NULL, 0, NULL, &cchMaxFileName, NULL, NULL, 0))
628 {
629 /* Don't return FALSE when GetVolumeInformationW fails. */
630 return TRUE;
631 }
632
633 return cchMaxFileName > MSDOS_8DOT3_LEN;
634}
635
636/*************************************************************************
637 * IsLFNDrive [SHELL32.119]
638 */
640{
641 if (SHELL_OsIsUnicode())
642 return IsLFNDriveW(lpszPath);
643 return IsLFNDriveA(lpszPath);
644}
645
646/*
647 ########## Creating Something Unique ##########
648*/
649/*************************************************************************
650 * PathMakeUniqueNameA [internal]
651 */
653 LPSTR lpszBuffer,
654 DWORD dwBuffSize,
655 LPCSTR lpszShortName,
656 LPCSTR lpszLongName,
657 LPCSTR lpszPathName)
658{
659 FIXME("%p %u %s %s %s stub\n",
660 lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
661 debugstr_a(lpszLongName), debugstr_a(lpszPathName));
662 return TRUE;
663}
664
665/*************************************************************************
666 * PathMakeUniqueNameW [internal]
667 */
669 LPWSTR lpszBuffer,
670 DWORD dwBuffSize,
671 LPCWSTR lpszShortName,
672 LPCWSTR lpszLongName,
673 LPCWSTR lpszPathName)
674{
675 FIXME("%p %u %s %s %s stub\n",
676 lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
677 debugstr_w(lpszLongName), debugstr_w(lpszPathName));
678 return TRUE;
679}
680
681/*************************************************************************
682 * PathMakeUniqueName [SHELL32.47]
683 */
685 LPVOID lpszBuffer,
686 DWORD dwBuffSize,
687 LPCVOID lpszShortName,
688 LPCVOID lpszLongName,
689 LPCVOID lpszPathName)
690{
691 if (SHELL_OsIsUnicode())
692 return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
693 return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
694}
695
696/*************************************************************************
697 * PathYetAnotherMakeUniqueName [SHELL32.75]
698 */
700{
701 WCHAR pathW[MAX_PATH], retW[MAX_PATH];
702 const WCHAR *file, *ext;
703 int i = 2;
704
705 TRACE("(%p, %s, %s, %s)\n", buffer, debugstr_w(path), debugstr_w(shortname), debugstr_w(longname));
706
707 file = longname ? longname : shortname;
708 PathCombineW(pathW, path, file);
709 strcpyW(retW, pathW);
711
713
714 /* now try to make it unique */
715 while (PathFileExistsW(retW))
716 {
717 sprintfW(retW, L"%s (%d)%s", pathW, i, ext);
718 i++;
719 }
720
721 strcpyW(buffer, retW);
722 TRACE("ret - %s\n", debugstr_w(buffer));
723
724 return TRUE;
725}
726
727/*
728 ########## cleaning and resolving paths ##########
729 */
730
731/*************************************************************************
732 * PathCleanupSpec [SHELL32.171]
733 *
734 * lpszFile is changed in place.
735 */
736int WINAPI PathCleanupSpec( LPCWSTR lpszPathW, LPWSTR lpszFileW )
737{
738 int i = 0;
739 DWORD rc = 0;
740 int length = 0;
741
742 if (SHELL_OsIsUnicode())
743 {
744 LPWSTR p = lpszFileW;
745
746 TRACE("Cleanup %s\n",debugstr_w(lpszFileW));
747
748 if (lpszPathW)
749 length = strlenW(lpszPathW);
750
751 while (*p)
752 {
753 int gct = PathGetCharTypeW(*p);
754 if (gct == GCT_INVALID || gct == GCT_WILD || gct == GCT_SEPARATOR)
755 {
756 lpszFileW[i]='-';
757 rc |= PCS_REPLACEDCHAR;
758 }
759 else
760 lpszFileW[i]=*p;
761 i++;
762 p++;
763 if (length + i == MAX_PATH)
764 {
766 break;
767 }
768 }
769 lpszFileW[i]=0;
770 }
771 else
772 {
773 LPSTR lpszFileA = (LPSTR)lpszFileW;
774 LPCSTR lpszPathA = (LPCSTR)lpszPathW;
775 LPSTR p = lpszFileA;
776
777 TRACE("Cleanup %s\n",debugstr_a(lpszFileA));
778
779 if (lpszPathA)
780 length = strlen(lpszPathA);
781
782 while (*p)
783 {
784 int gct = PathGetCharTypeA(*p);
785 if (gct == GCT_INVALID || gct == GCT_WILD || gct == GCT_SEPARATOR)
786 {
787 lpszFileA[i]='-';
788 rc |= PCS_REPLACEDCHAR;
789 }
790 else
791 lpszFileA[i]=*p;
792 i++;
793 p++;
794 if (length + i == MAX_PATH)
795 {
797 break;
798 }
799 }
800 lpszFileA[i]=0;
801 }
802 return rc;
803}
804
805/*************************************************************************
806 * PathQualifyA [SHELL32]
807 */
809{
811 TRACE("%s\n",pszPath);
815}
816
817/*************************************************************************
818 * PathQualifyW [SHELL32]
819 */
821{
822 TRACE("%s\n",debugstr_w(pszPath));
823 PathQualifyExW(pszPath, NULL, 0);
824}
825
826/*************************************************************************
827 * PathQualify [SHELL32.49]
828 */
830{
831 if (SHELL_OsIsUnicode())
832 PathQualifyW(pszPath);
833 else
834 PathQualifyA(pszPath);
835}
836
838{
839 BOOL ret = FALSE;
840 LPWSTR *dirsW = NULL;
841 DWORD iDir, cDirs, cbDirs;
842 WCHAR pathW[MAX_PATH];
843
844 TRACE("(%s,%p,0x%08x)\n", debugstr_a(path), dirs, flags);
845
846 if (dirs)
847 {
848 for (cDirs = 0; dirs[cDirs]; ++cDirs)
849 ;
850
851 cbDirs = (cDirs + 1) * sizeof(LPWSTR);
852 dirsW = SHAlloc(cbDirs);
853 if (!dirsW)
854 goto Cleanup;
855
856 ZeroMemory(dirsW, cbDirs);
857 for (iDir = 0; iDir < cDirs; ++iDir)
858 {
859 __SHCloneStrAtoW(&dirsW[iDir], dirs[iDir]);
860 if (dirsW[iDir] == NULL)
861 goto Cleanup;
862 }
863 }
864
865 SHAnsiToUnicode(path, pathW, _countof(pathW));
866
867 ret = PathResolveW(pathW, (LPCWSTR*)dirsW, flags);
868 if (ret)
870
871Cleanup:
872 if (dirsW)
873 {
874 for (iDir = 0; iDir < cDirs; ++iDir)
875 {
876 SHFree(dirsW[iDir]);
877 }
878 SHFree(dirsW);
879 }
880 return ret;
881}
882
884{
885 DWORD dwWhich = WHICH_DEFAULT; /* The extensions to be searched */
886
887 TRACE("(%s,%p,0x%08x)\n", debugstr_w(path), dirs, flags);
888
890 dwWhich &= ~WHICH_LNK; /* Don't search '.LNK' (shortcut) */
891
893 SetLastError(ERROR_FILE_NOT_FOUND); /* We set this error code at first in verification */
894
896
897 if (PathIsRootW(path)) /* Root path */
898 {
899 if (path[0] == L'\\' && path[1] == UNICODE_NULL) /* '\' only? */
900 PathQualifyExW(path, ((flags & PRF_FIRSTDIRDEF) ? *dirs : NULL), 0); /* Qualify */
901
903 return PathFileExistsAndAttributesW(path, NULL); /* Check the existence */
904
905 return TRUE;
906 }
907
908 if (PathIsFileSpecW(path)) /* Filename only */
909 {
910 /* Try to find the path with program extensions applied? */
912 PathSearchOnExtensionsW(path, dirs, TRUE, dwWhich))
913 {
914 return TRUE; /* Found */
915 }
916
917 /* Try to find the filename in the directories */
918 if (PathFindOnPathW(path, dirs))
919 goto CheckAbsoluteAndFinish;
920
921 return FALSE; /* Not found */
922 }
923
924 if (PathIsURLW(path)) /* URL? */
925 return FALSE;
926
927 /* Qualify the path */
928 PathQualifyExW(path, ((flags & PRF_FIRSTDIRDEF) ? *dirs : NULL), 1);
929
930 TRACE("(%s)\n", debugstr_w(path));
931
932 if (!(flags & PRF_VERIFYEXISTS)) /* Don't verify the existence? */
933 return TRUE;
934
935 /* Try to find the path with program extensions applied? */
937 !PathSearchOnExtensionsW(path, dirs, FALSE, dwWhich))
938 {
940 return FALSE; /* Not found */
941 }
942
943CheckAbsoluteAndFinish:
944#if (_WIN32_WINNT >= _WIN32_WINNT_WS03)
946 return TRUE;
947
949 return FALSE;
950
952#else
953 return TRUE; /* Found */
954#endif
955}
956
957/*************************************************************************
958 * PathResolve [SHELL32.51]
959 */
961{
962 if (SHELL_OsIsUnicode())
963 return PathResolveW(path, (LPCWSTR*)paths, flags);
964 else
965 return PathResolveA(path, (LPCSTR*)paths, flags);
966}
967
968/*************************************************************************
969* PathProcessCommandA
970*/
972 LPCSTR lpszPath,
973 LPSTR lpszBuff,
974 DWORD dwBuffSize,
976{
977 FIXME("%s %p 0x%04x 0x%04x stub\n",
978 lpszPath, lpszBuff, dwBuffSize, dwFlags);
979 if(!lpszPath) return -1;
980 if(lpszBuff) strcpy(lpszBuff, lpszPath);
981 return strlen(lpszPath);
982}
983
984/*************************************************************************
985* PathProcessCommandW
986*/
988 LPCWSTR lpszPath,
989 LPWSTR lpszBuff,
990 DWORD dwBuffSize,
992{
993 FIXME("(%s, %p, 0x%04x, 0x%04x) stub\n",
994 debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
995 if(!lpszPath) return -1;
996 if(lpszBuff) strcpyW(lpszBuff, lpszPath);
997 return strlenW(lpszPath);
998}
999
1000/*************************************************************************
1001* PathProcessCommand (SHELL32.653)
1002*/
1004 LPCVOID lpszPath,
1005 LPVOID lpszBuff,
1006 DWORD dwBuffSize,
1007 DWORD dwFlags)
1008{
1009 if (SHELL_OsIsUnicode())
1010 return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags);
1011 return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags);
1012}
1013
1014/*
1015 ########## special ##########
1016*/
1017
1018/* !! MISSING Win2k3-compatible paths from the list below; absent from Wine !! */
1019#ifndef __REACTOS__
1020static const WCHAR Application_DataW[] = L"Application Data";
1021static const WCHAR Local_Settings_Application_DataW[] = L"Local Settings\\Application Data";
1022static const WCHAR Local_Settings_HistoryW[] = L"Local Settings\\History";
1023static const WCHAR Local_Settings_Temporary_Internet_FilesW[] = L"Local Settings\\Temporary Internet Files";
1024static const WCHAR MusicW[] = L"Music";
1025static const WCHAR PicturesW[] = L"Pictures";
1026static const WCHAR Program_FilesW[] = L"Program Files";
1027static const WCHAR Program_Files_Common_FilesW[] = L"Program Files\\Common Files";
1028static const WCHAR Start_Menu_ProgramsW[] = L"Start Menu\\Programs";
1029static const WCHAR Start_Menu_Admin_ToolsW[] = L"Start Menu\\Programs\\Administrative Tools";
1030static const WCHAR Start_Menu_StartupW[] = L"Start Menu\\Programs\\StartUp";
1031#endif
1032
1033/* Long strings that are repeated many times: keep them here */
1034static const WCHAR szSHFolders[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
1035static const WCHAR szSHUserFolders[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
1036#ifndef __REACTOS__
1037static const WCHAR szKnownFolderDescriptions[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FolderDescriptions";
1038static const WCHAR szKnownFolderRedirections[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
1039#endif
1040
1041typedef enum _CSIDL_Type {
1043#ifdef __REACTOS__
1044 CSIDL_Type_InMyDocuments,
1045#endif
1054
1055/* Cannot use #if _WIN32_WINNT >= 0x0600 because _WIN32_WINNT == 0x0600 here. */
1056#ifndef __REACTOS__
1057#define CSIDL_CONTACTS 0x0043
1058#define CSIDL_DOWNLOADS 0x0047
1059#define CSIDL_LINKS 0x004d
1060#define CSIDL_APPDATA_LOCALLOW 0x004e
1061#define CSIDL_SAVED_GAMES 0x0062
1062#define CSIDL_SEARCHES 0x0063
1063#endif
1064
1065typedef struct
1066{
1070 LPCWSTR szDefaultPath; /* fallback string or resource ID */
1072} CSIDL_DATA;
1073
1074static const CSIDL_DATA CSIDL_Data[] =
1075{
1076 { /* 0x00 - CSIDL_DESKTOP */
1077 &FOLDERID_Desktop,
1079 L"Desktop",
1081#ifdef __REACTOS__
1082 0
1083#else
1085#endif
1086 },
1087 { /* 0x01 - CSIDL_INTERNET */
1088 &FOLDERID_InternetFolder,
1090 NULL,
1091 NULL
1092 },
1093 { /* 0x02 - CSIDL_PROGRAMS */
1094 &FOLDERID_Programs,
1096 L"Programs",
1098#ifdef __REACTOS__
1099 0
1100#else
1102#endif
1103 },
1104 { /* 0x03 - CSIDL_CONTROLS (.CPL files) */
1105 &FOLDERID_ControlPanelFolder,
1107 L"ControlPanelFolder",
1108 NULL,
1110 },
1111 { /* 0x04 - CSIDL_PRINTERS */
1112 &FOLDERID_PrintersFolder,
1114 L"PrintersFolder",
1115 NULL,
1117 },
1118 { /* 0x05 - CSIDL_PERSONAL */
1119 &FOLDERID_Documents,
1121 L"Personal",
1124 },
1125 { /* 0x06 - CSIDL_FAVORITES */
1126 &FOLDERID_Favorites,
1128 L"Favorites",
1131 },
1132 { /* 0x07 - CSIDL_STARTUP */
1133 &FOLDERID_Startup,
1135 L"StartUp",
1137 },
1138 { /* 0x08 - CSIDL_RECENT */
1139 &FOLDERID_Recent,
1141 L"Recent",
1144 },
1145 { /* 0x09 - CSIDL_SENDTO */
1146 &FOLDERID_SendTo,
1148 L"SendTo",
1150 },
1151 { /* 0x0a - CSIDL_BITBUCKET - Recycle Bin */
1152 &FOLDERID_RecycleBinFolder,
1154 L"RecycleBinFolder",
1155 NULL
1156 },
1157 { /* 0x0b - CSIDL_STARTMENU */
1158 &FOLDERID_StartMenu,
1160 L"Start Menu",
1163 },
1164 { /* 0x0c - CSIDL_MYDOCUMENTS */
1165 &GUID_NULL,
1166 CSIDL_Type_Disallowed, /* matches WinXP--can't get its path */
1167 NULL,
1168 NULL,
1170 },
1171 { /* 0x0d - CSIDL_MYMUSIC */
1172 &FOLDERID_Music,
1173#ifdef __REACTOS__
1174 CSIDL_Type_InMyDocuments,
1175#else
1177#endif
1178 L"My Music",
1181 },
1182 { /* 0x0e - CSIDL_MYVIDEO */
1183 &FOLDERID_Videos,
1184#ifdef __REACTOS__
1185 CSIDL_Type_InMyDocuments,
1186#else
1188#endif
1189 L"My Video",
1192 },
1193 { /* 0x0f - unassigned */
1194 &GUID_NULL,
1196 NULL,
1197 NULL,
1198 },
1199 { /* 0x10 - CSIDL_DESKTOPDIRECTORY */
1200 &FOLDERID_Desktop,
1202 L"Desktop",
1204#ifdef __REACTOS__
1205 0
1206#else
1208#endif
1209 },
1210 { /* 0x11 - CSIDL_DRIVES */
1211 &FOLDERID_ComputerFolder,
1213 L"MyComputerFolder",
1214 NULL,
1216 },
1217 { /* 0x12 - CSIDL_NETWORK */
1218 &FOLDERID_NetworkFolder,
1220 L"NetworkPlacesFolder",
1221 NULL,
1223 },
1224 { /* 0x13 - CSIDL_NETHOOD */
1225 &FOLDERID_NetHood,
1227 L"NetHood",
1230 },
1231 { /* 0x14 - CSIDL_FONTS */
1232 &FOLDERID_Fonts,
1234 L"Fonts",
1235 L"Fonts",
1237 },
1238 { /* 0x15 - CSIDL_TEMPLATES */
1239 &FOLDERID_Templates,
1241 L"Templates",
1243 },
1244 { /* 0x16 - CSIDL_COMMON_STARTMENU */
1245 &FOLDERID_CommonStartMenu,
1247 L"Common Start Menu",
1250 },
1251 { /* 0x17 - CSIDL_COMMON_PROGRAMS */
1252 &FOLDERID_CommonPrograms,
1254 L"Common Programs",
1256#ifdef __REACTOS__
1257 0
1258#else
1260#endif
1261 },
1262 { /* 0x18 - CSIDL_COMMON_STARTUP */
1263 &FOLDERID_CommonStartup,
1265 L"Common StartUp",
1267 },
1268 { /* 0x19 - CSIDL_COMMON_DESKTOPDIRECTORY */
1269 &FOLDERID_PublicDesktop,
1271 L"Common Desktop",
1273#ifdef __REACTOS__
1274 0
1275#else
1277#endif
1278 },
1279 { /* 0x1a - CSIDL_APPDATA */
1280 &FOLDERID_RoamingAppData,
1282 L"AppData",
1284 },
1285 { /* 0x1b - CSIDL_PRINTHOOD */
1286 &FOLDERID_PrintHood,
1288 L"PrintHood",
1291 },
1292 { /* 0x1c - CSIDL_LOCAL_APPDATA */
1293 &FOLDERID_LocalAppData,
1295 L"Local AppData",
1297 },
1298 { /* 0x1d - CSIDL_ALTSTARTUP */
1299 &GUID_NULL,
1301 NULL,
1302 NULL
1303 },
1304 { /* 0x1e - CSIDL_COMMON_ALTSTARTUP */
1305 &GUID_NULL,
1307 NULL,
1308 NULL
1309 },
1310 { /* 0x1f - CSIDL_COMMON_FAVORITES */
1311 &FOLDERID_Favorites,
1313 L"Common Favorites",
1316 },
1317 { /* 0x20 - CSIDL_INTERNET_CACHE */
1318 &FOLDERID_InternetCache,
1320 L"Cache",
1322 },
1323 { /* 0x21 - CSIDL_COOKIES */
1324 &FOLDERID_Cookies,
1326 L"Cookies",
1328 },
1329 { /* 0x22 - CSIDL_HISTORY */
1330 &FOLDERID_History,
1332 L"History",
1334 },
1335 { /* 0x23 - CSIDL_COMMON_APPDATA */
1336 &FOLDERID_ProgramData,
1338 L"Common AppData",
1340 },
1341 { /* 0x24 - CSIDL_WINDOWS */
1342 &FOLDERID_Windows,
1344 L"Windows",
1345 NULL,
1347 },
1348 { /* 0x25 - CSIDL_SYSTEM */
1349 &FOLDERID_System,
1351 L"System",
1352 NULL,
1354 },
1355 { /* 0x26 - CSIDL_PROGRAM_FILES */
1356 &FOLDERID_ProgramFiles,
1358 L"ProgramFiles",
1360#ifdef __REACTOS__
1361 0
1362#else
1364#endif
1365 },
1366 { /* 0x27 - CSIDL_MYPICTURES */
1367 &FOLDERID_Pictures,
1368#ifdef __REACTOS__
1369 CSIDL_Type_InMyDocuments,
1370#else
1372#endif
1373 L"My Pictures",
1376 },
1377 { /* 0x28 - CSIDL_PROFILE */
1378 &FOLDERID_Profile,
1380 NULL,
1381 NULL
1382 },
1383 { /* 0x29 - CSIDL_SYSTEMX86 */
1384 &FOLDERID_SystemX86,
1386 NULL,
1387 NULL,
1389 },
1390 { /* 0x2a - CSIDL_PROGRAM_FILESX86 */
1391 &FOLDERID_ProgramFilesX86,
1393 L"ProgramFilesX86",
1394 L"Program Files (x86)",
1396 },
1397 { /* 0x2b - CSIDL_PROGRAM_FILES_COMMON */
1398 &FOLDERID_ProgramFilesCommon,
1400 L"ProgramFilesCommon",
1403 },
1404 { /* 0x2c - CSIDL_PROGRAM_FILES_COMMONX86 */
1405 &FOLDERID_ProgramFilesCommonX86,
1407 L"ProgramFilesCommonX86",
1408 L"Program Files (x86)\\Common Files",
1410 },
1411 { /* 0x2d - CSIDL_COMMON_TEMPLATES */
1412 &FOLDERID_CommonTemplates,
1414 L"Common Templates",
1416 },
1417 { /* 0x2e - CSIDL_COMMON_DOCUMENTS */
1418 &FOLDERID_PublicDocuments,
1420 L"Common Documents",
1423 },
1424 { /* 0x2f - CSIDL_COMMON_ADMINTOOLS */
1425 &FOLDERID_CommonAdminTools,
1427 L"Common Administrative Tools",
1429 },
1430 { /* 0x30 - CSIDL_ADMINTOOLS */
1431 &FOLDERID_AdminTools,
1433 L"Administrative Tools",
1435 },
1436 { /* 0x31 - CSIDL_CONNECTIONS */
1437 &FOLDERID_ConnectionsFolder,
1439 L"ConnectionsFolder",
1440 NULL,
1442 },
1443 { /* 0x32 - unassigned */
1444 &GUID_NULL,
1446 NULL,
1447 NULL
1448 },
1449 { /* 0x33 - unassigned */
1450 &GUID_NULL,
1452 NULL,
1453 NULL
1454 },
1455 { /* 0x34 - unassigned */
1456 &GUID_NULL,
1458 NULL,
1459 NULL
1460 },
1461 { /* 0x35 - CSIDL_COMMON_MUSIC */
1462 &FOLDERID_PublicMusic,
1464 L"CommonMusic",
1467 },
1468 { /* 0x36 - CSIDL_COMMON_PICTURES */
1469 &FOLDERID_PublicPictures,
1471 L"CommonPictures",
1474 },
1475 { /* 0x37 - CSIDL_COMMON_VIDEO */
1476 &FOLDERID_PublicVideos,
1478 L"CommonVideo",
1481 },
1482 { /* 0x38 - CSIDL_RESOURCES */
1483 &FOLDERID_ResourceDir,
1485 NULL,
1486 L"Resources"
1487 },
1488 { /* 0x39 - CSIDL_RESOURCES_LOCALIZED */
1489 &FOLDERID_LocalizedResourcesDir,
1491 NULL,
1492 NULL
1493 },
1494 { /* 0x3a - CSIDL_COMMON_OEM_LINKS */
1495 &FOLDERID_CommonOEMLinks,
1497 NULL,
1498 L"OEM Links"
1499 },
1500 { /* 0x3b - CSIDL_CDBURN_AREA */
1501 &FOLDERID_CDBurning,
1503 L"CD Burning",
1504 L"Local Settings\\Application Data\\Microsoft\\CD Burning"
1505 },
1506 { /* 0x3c unassigned */
1507 &GUID_NULL,
1509 NULL,
1510 NULL
1511 },
1512 { /* 0x3d - CSIDL_COMPUTERSNEARME */
1513 &GUID_NULL,
1514 CSIDL_Type_Disallowed, /* FIXME */
1515 NULL,
1516 NULL
1517 },
1518 { /* 0x3e - CSIDL_PROFILES */
1519 &GUID_NULL,
1520 CSIDL_Type_Disallowed, /* oddly, this matches WinXP */
1521 NULL,
1522 NULL
1523 },
1524/* Cannot use #if _WIN32_WINNT >= 0x0600 because _WIN32_WINNT == 0x0600 here. */
1525#ifndef __REACTOS__
1526 { /* 0x3f */
1527 &FOLDERID_AddNewPrograms,
1529 NULL,
1530 NULL
1531 },
1532 { /* 0x40 */
1533 &FOLDERID_AppUpdates,
1535 NULL,
1536 NULL
1537 },
1538 { /* 0x41 */
1539 &FOLDERID_ChangeRemovePrograms,
1541 NULL,
1542 NULL
1543 },
1544 { /* 0x42 */
1545 &FOLDERID_ConflictFolder,
1547 NULL,
1548 NULL
1549 },
1550 { /* 0x43 - CSIDL_CONTACTS */
1551 &FOLDERID_Contacts,
1553 NULL,
1554 L"Contacts"
1555 },
1556 { /* 0x44 */
1557 &FOLDERID_DeviceMetadataStore,
1558 CSIDL_Type_Disallowed, /* FIXME */
1559 NULL,
1560 NULL
1561 },
1562 { /* 0x45 */
1563 &GUID_NULL,
1565 NULL,
1566 L"Documents"
1567 },
1568 { /* 0x46 */
1569 &FOLDERID_DocumentsLibrary,
1570 CSIDL_Type_Disallowed, /* FIXME */
1571 NULL,
1572 NULL
1573 },
1574 { /* 0x47 - CSIDL_DOWNLOADS */
1575 &FOLDERID_Downloads,
1576#ifdef __REACTOS__
1577 CSIDL_Type_InMyDocuments,
1578#else
1580#endif
1581 NULL,
1582 L"Downloads"
1583 },
1584 { /* 0x48 */
1585 &FOLDERID_Games,
1587 NULL,
1588 NULL
1589 },
1590 { /* 0x49 */
1591 &FOLDERID_GameTasks,
1592 CSIDL_Type_Disallowed, /* FIXME */
1593 NULL,
1594 NULL
1595 },
1596 { /* 0x4a */
1597 &FOLDERID_HomeGroup,
1599 NULL,
1600 NULL
1601 },
1602 { /* 0x4b */
1603 &FOLDERID_ImplicitAppShortcuts,
1604 CSIDL_Type_Disallowed, /* FIXME */
1605 NULL,
1606 NULL
1607 },
1608 { /* 0x4c */
1609 &FOLDERID_Libraries,
1610 CSIDL_Type_Disallowed, /* FIXME */
1611 NULL,
1612 NULL
1613 },
1614 { /* 0x4d - CSIDL_LINKS */
1615 &FOLDERID_Links,
1617 NULL,
1618 L"Links"
1619 },
1620 { /* 0x4e - CSIDL_APPDATA_LOCALLOW */
1621 &FOLDERID_LocalAppDataLow,
1623 NULL,
1624 L"AppData\\LocalLow"
1625 },
1626 { /* 0x4f */
1627 &FOLDERID_MusicLibrary,
1628 CSIDL_Type_Disallowed, /* FIXME */
1629 NULL,
1630 NULL
1631 },
1632 { /* 0x50 */
1633 &FOLDERID_OriginalImages,
1634 CSIDL_Type_Disallowed, /* FIXME */
1635 NULL,
1636 NULL
1637 },
1638 { /* 0x51 */
1639 &FOLDERID_PhotoAlbums,
1641 NULL,
1642 L"Pictures\\Slide Shows"
1643 },
1644 { /* 0x52 */
1645 &FOLDERID_PicturesLibrary,
1646 CSIDL_Type_Disallowed, /* FIXME */
1647 NULL,
1648 NULL
1649 },
1650 { /* 0x53 */
1651 &FOLDERID_Playlists,
1653 NULL,
1654 L"Music\\Playlists"
1655 },
1656 { /* 0x54 */
1657 &FOLDERID_ProgramFilesX64,
1659 NULL,
1660 NULL
1661 },
1662 { /* 0x55 */
1663 &FOLDERID_ProgramFilesCommonX64,
1665 NULL,
1666 NULL
1667 },
1668 { /* 0x56 */
1669 &FOLDERID_Public,
1670 CSIDL_Type_CurrVer, /* FIXME */
1671 NULL,
1672 L"Users\\Public"
1673 },
1674 { /* 0x57 */
1675 &FOLDERID_PublicDownloads,
1677 NULL,
1678 L"Downloads"
1679 },
1680 { /* 0x58 */
1681 &FOLDERID_PublicGameTasks,
1683 NULL,
1684 L"Microsoft\\Windows\\GameExplorer"
1685 },
1686 { /* 0x59 */
1687 &FOLDERID_PublicLibraries,
1689 NULL,
1690 L"Microsoft\\Windows\\Libraries"
1691 },
1692 { /* 0x5a */
1693 &FOLDERID_PublicRingtones,
1695 NULL,
1696 L"Microsoft\\Windows\\Ringtones"
1697 },
1698 { /* 0x5b */
1699 &FOLDERID_QuickLaunch,
1700 CSIDL_Type_Disallowed, /* FIXME */
1701 NULL,
1702 NULL
1703 },
1704 { /* 0x5c */
1705 &FOLDERID_RecordedTVLibrary,
1706 CSIDL_Type_Disallowed, /* FIXME */
1707 NULL,
1708 NULL
1709 },
1710 { /* 0x5d */
1711 &FOLDERID_Ringtones,
1712 CSIDL_Type_Disallowed, /* FIXME */
1713 NULL,
1714 NULL
1715 },
1716 { /* 0x5e */
1717 &FOLDERID_SampleMusic,
1719 NULL,
1720 L"Music\\Sample Music"
1721 },
1722 { /* 0x5f */
1723 &FOLDERID_SamplePictures,
1725 NULL,
1726 L"Pictures\\Sample Pictures"
1727 },
1728 { /* 0x60 */
1729 &FOLDERID_SamplePlaylists,
1731 NULL,
1732 L"Music\\Sample Playlists"
1733 },
1734 { /* 0x61 */
1735 &FOLDERID_SampleVideos,
1737 NULL,
1738 L"Videos\\Sample Videos"
1739 },
1740 { /* 0x62 - CSIDL_SAVED_GAMES */
1741 &FOLDERID_SavedGames,
1743 NULL,
1744 L"Saved Games"
1745 },
1746 { /* 0x63 - CSIDL_SEARCHES */
1747 &FOLDERID_SavedSearches,
1749 NULL,
1750 L"Searches"
1751 },
1752 { /* 0x64 */
1753 &FOLDERID_SEARCH_CSC,
1755 NULL,
1756 NULL
1757 },
1758 { /* 0x65 */
1759 &FOLDERID_SEARCH_MAPI,
1761 NULL,
1762 NULL
1763 },
1764 { /* 0x66 */
1765 &FOLDERID_SearchHome,
1767 NULL,
1768 NULL
1769 },
1770 { /* 0x67 */
1771 &FOLDERID_SidebarDefaultParts,
1772 CSIDL_Type_Disallowed, /* FIXME */
1773 NULL,
1774 NULL
1775 },
1776 { /* 0x68 */
1777 &FOLDERID_SidebarParts,
1778 CSIDL_Type_Disallowed, /* FIXME */
1779 NULL,
1780 NULL
1781 },
1782 { /* 0x69 */
1783 &FOLDERID_SyncManagerFolder,
1785 NULL,
1786 NULL
1787 },
1788 { /* 0x6a */
1789 &FOLDERID_SyncResultsFolder,
1791 NULL,
1792 NULL
1793 },
1794 { /* 0x6b */
1795 &FOLDERID_SyncSetupFolder,
1797 NULL,
1798 NULL
1799 },
1800 { /* 0x6c */
1801 &FOLDERID_UserPinned,
1802 CSIDL_Type_Disallowed, /* FIXME */
1803 NULL,
1804 NULL
1805 },
1806 { /* 0x6d */
1807 &FOLDERID_UserProfiles,
1809 L"Users",
1810 L"Users"
1811 },
1812 { /* 0x6e */
1813 &FOLDERID_UserProgramFiles,
1814 CSIDL_Type_Disallowed, /* FIXME */
1815 NULL,
1816 NULL
1817 },
1818 { /* 0x6f */
1819 &FOLDERID_UserProgramFilesCommon,
1820 CSIDL_Type_Disallowed, /* FIXME */
1821 NULL,
1822 NULL
1823 },
1824 { /* 0x70 */
1825 &FOLDERID_UsersFiles,
1827 NULL,
1828 NULL
1829 },
1830 { /* 0x71 */
1831 &FOLDERID_UsersLibraries,
1833 NULL,
1834 NULL
1835 },
1836 { /* 0x72 */
1837 &FOLDERID_VideosLibrary,
1838 CSIDL_Type_Disallowed, /* FIXME */
1839 NULL,
1840 NULL
1841 }
1842#endif
1843};
1844
1846{
1847 UINT csidl;
1848
1849 for (csidl = 0; csidl < _countof(CSIDL_Data); ++csidl)
1850 {
1851 const CSIDL_DATA *pData = &CSIDL_Data[csidl];
1852 if (pData->szValueName && lstrcmpiW(pszName, pData->szValueName) == 0)
1853 return csidl;
1854 }
1855
1856 return -1;
1857}
1858
1860{
1861 LPCWSTR pszPath, pchBackslash;
1863
1864 pchBackslash = StrChrW(pszStart, L'\\');
1865 if (pchBackslash)
1866 {
1867 *ppch = (LPWSTR)(pchBackslash + 1);
1868 *pcch = (pchBackslash - pszStart) + 1;
1869 StrCpyNW(szPath, pszStart, max(*pcch, _countof(szPath)));
1870 pszPath = szPath;
1871 }
1872 else
1873 {
1874 *ppch = NULL;
1875 *pcch = lstrlenW(pszStart);
1876 pszPath = pszStart;
1877 }
1878
1879 return SHGetSpecialFolderID(pszPath);
1880}
1881
1882#ifndef __REACTOS__
1884#else
1885static HRESULT _SHExpandEnvironmentStrings(HANDLE hToken, LPCWSTR szSrc, LPWSTR szDest, DWORD cchDest);
1886#endif
1887
1888/* Gets the value named value from the registry key
1889 * rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
1890 * (or from rootKey\userPrefix\... if userPrefix is not NULL) into path, which
1891 * is assumed to be MAX_PATH WCHARs in length.
1892 * If it exists, expands the value and writes the expanded value to
1893 * rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
1894 * Returns successful error code if the value was retrieved from the registry,
1895 * and a failure otherwise.
1896 */
1897#ifndef __REACTOS__
1899#else
1900static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, HANDLE hToken, LPCWSTR userPrefix,
1901#endif
1903{
1904 HRESULT hr;
1905 WCHAR shellFolderPath[MAX_PATH], userShellFolderPath[MAX_PATH];
1906 LPCWSTR pShellFolderPath, pUserShellFolderPath;
1907 HKEY userShellFolderKey, shellFolderKey;
1908 DWORD dwType, dwPathLen;
1909
1910 TRACE("%p,%s,%s,%p\n",rootKey, debugstr_w(userPrefix), debugstr_w(value),
1911 path);
1912
1913 if (userPrefix)
1914 {
1915 strcpyW(shellFolderPath, userPrefix);
1916 PathAddBackslashW(shellFolderPath);
1917 strcatW(shellFolderPath, szSHFolders);
1918 pShellFolderPath = shellFolderPath;
1919 strcpyW(userShellFolderPath, userPrefix);
1920 PathAddBackslashW(userShellFolderPath);
1921 strcatW(userShellFolderPath, szSHUserFolders);
1922 pUserShellFolderPath = userShellFolderPath;
1923 }
1924 else
1925 {
1926 pUserShellFolderPath = szSHUserFolders;
1927 pShellFolderPath = szSHFolders;
1928 }
1929
1930 if (RegCreateKeyW(rootKey, pShellFolderPath, &shellFolderKey))
1931 {
1932 TRACE("Failed to create %s\n", debugstr_w(pShellFolderPath));
1933 return E_FAIL;
1934 }
1935 if (RegCreateKeyW(rootKey, pUserShellFolderPath, &userShellFolderKey))
1936 {
1937 TRACE("Failed to create %s\n",
1938 debugstr_w(pUserShellFolderPath));
1939 RegCloseKey(shellFolderKey);
1940 return E_FAIL;
1941 }
1942
1943 dwPathLen = MAX_PATH * sizeof(WCHAR);
1944 if (!RegQueryValueExW(userShellFolderKey, value, NULL, &dwType,
1945 (LPBYTE)path, &dwPathLen) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
1946 {
1947 LONG ret;
1948
1949 path[dwPathLen / sizeof(WCHAR)] = '\0';
1950 if (dwType == REG_EXPAND_SZ && path[0] == '%')
1951 {
1952 WCHAR szTemp[MAX_PATH];
1953
1954#ifndef __REACTOS__
1956#else
1957 hr = _SHExpandEnvironmentStrings(hToken, path, szTemp, _countof(szTemp));
1958 if (FAILED(hr))
1959 goto end;
1960#endif
1961 lstrcpynW(path, szTemp, MAX_PATH);
1962 }
1963 ret = RegSetValueExW(shellFolderKey, value, 0, REG_SZ, (LPBYTE)path,
1964 (strlenW(path) + 1) * sizeof(WCHAR));
1965 if (ret != ERROR_SUCCESS)
1967 else
1968 hr = S_OK;
1969 }
1970 else
1971 hr = E_FAIL;
1972#ifdef __REACTOS__
1973end:
1974#endif
1975 RegCloseKey(shellFolderKey);
1976 RegCloseKey(userShellFolderKey);
1977 TRACE("returning 0x%08x\n", hr);
1978 return hr;
1979}
1980
1982{
1983 BOOL result;
1984 if (!hToken)
1985 {
1987 result = GetUserProfileDirectoryW(hToken, szPath, lpcchPath);
1988 CloseHandle(hToken);
1989 }
1990 else if ((INT) hToken == -1)
1991 {
1993 }
1994 else
1995 {
1996 result = GetUserProfileDirectoryW(hToken, szPath, lpcchPath);
1997 }
1998 TRACE("_SHGetUserProfileDirectoryW returning %S\n", szPath);
1999 return result;
2000}
2001
2002/* Gets a 'semi-expanded' default value of the CSIDL with index folder into
2003 * pszPath, based on the entries in CSIDL_Data. By semi-expanded, I mean:
2004 * - The entry's szDefaultPath may be either a string value or an integer
2005 * resource identifier. In the latter case, the string value of the resource
2006 * is written.
2007 * - Depending on the entry's type, the path may begin with an (unexpanded)
2008 * environment variable name. The caller is responsible for expanding
2009 * environment strings if so desired.
2010 * The types that are prepended with environment variables are:
2011 * CSIDL_Type_User: %USERPROFILE%
2012 * CSIDL_Type_AllUsers: %ALLUSERSPROFILE%
2013 * CSIDL_Type_CurrVer: %SystemDrive%
2014 * (Others might make sense too, but as yet are unneeded.)
2015 */
2016#ifndef __REACTOS__
2018#else
2019static HRESULT _SHGetDefaultValue(HANDLE hToken, BYTE folder, LPWSTR pszPath)
2020#endif
2021{
2022 HRESULT hr;
2023 WCHAR resourcePath[MAX_PATH];
2024#ifdef __REACTOS__
2025 NT_PRODUCT_TYPE ProductType;
2026#endif
2027
2028 TRACE("0x%02x,%p\n", folder, pszPath);
2029
2031 return E_INVALIDARG;
2032
2033 if (!pszPath)
2034 return E_INVALIDARG;
2035
2036#ifdef __REACTOS__
2037 if (hToken != NULL && hToken != (HANDLE)-1)
2038 {
2039 FIXME("unsupported for user other than current or default\n");
2040 }
2041#endif
2042
2043 if (!is_win64)
2044 {
2045 BOOL is_wow64;
2046
2047 switch (folder)
2048 {
2053 break;
2058 break;
2059 }
2060 }
2061
2062 switch (CSIDL_Data[folder].type)
2063 {
2064 case CSIDL_Type_User:
2065 strcpyW(pszPath, L"%USERPROFILE%");
2066 break;
2067#ifdef __REACTOS__
2068 case CSIDL_Type_InMyDocuments:
2069 strcpyW(pszPath, L"%USERPROFILE%");
2070 if (DoGetProductType(&ProductType) && ProductType == NtProductWinNt)
2071 {
2072 if (IS_INTRESOURCE(CSIDL_Data[CSIDL_MYDOCUMENTS].szDefaultPath))
2073 {
2074 WCHAR szItem[MAX_PATH];
2076 LOWORD(CSIDL_Data[CSIDL_MYDOCUMENTS].szDefaultPath),
2077 szItem, ARRAY_SIZE(szItem));
2078 PathAppendW(pszPath, szItem);
2079 }
2080 else
2081 {
2082 PathAppendW(pszPath, CSIDL_Data[CSIDL_MYDOCUMENTS].szDefaultPath);
2083 }
2084 }
2085 break;
2086#endif
2088#ifndef __REACTOS__
2089 strcpyW(pszPath, L"%PUBLIC%");
2090#else
2091 strcpyW(pszPath, L"%ALLUSERSPROFILE%");
2092#endif
2093 break;
2094 case CSIDL_Type_CurrVer:
2095 strcpyW(pszPath, L"%SystemDrive%");
2096 break;
2097 default:
2098 ; /* no corresponding env. var, do nothing */
2099 }
2100
2101 hr = S_OK;
2102 if (CSIDL_Data[folder].szDefaultPath)
2103 {
2104 if (IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath))
2105 {
2107 LOWORD(CSIDL_Data[folder].szDefaultPath), resourcePath, MAX_PATH))
2108 {
2109 PathAppendW(pszPath, resourcePath);
2110 }
2111 else
2112 {
2113 ERR("(%d,%s), LoadString failed, missing translation?\n", folder,
2114 debugstr_w(pszPath));
2115 hr = E_FAIL;
2116 }
2117 }
2118 else
2119 {
2120 PathAppendW(pszPath, CSIDL_Data[folder].szDefaultPath);
2121 }
2122 }
2123 TRACE("returning 0x%08x\n", hr);
2124 return hr;
2125}
2126
2127/* Gets the (unexpanded) value of the folder with index folder into pszPath.
2128 * The folder's type is assumed to be CSIDL_Type_CurrVer. Its default value
2129 * can be overridden in the HKLM\\Software\\Microsoft\\Windows\\CurrentVersion key.
2130 * If dwFlags has SHGFP_TYPE_DEFAULT set or if the value isn't overridden in
2131 * the registry, uses _SHGetDefaultValue to get the value.
2132 */
2134 LPWSTR pszPath)
2135{
2136 HRESULT hr;
2137
2138 TRACE("0x%08x,0x%02x,%p\n", dwFlags, folder, pszPath);
2139
2141 return E_INVALIDARG;
2143 return E_INVALIDARG;
2144 if (!pszPath)
2145 return E_INVALIDARG;
2146
2148#ifndef __REACTOS__
2149 hr = _SHGetDefaultValue(folder, pszPath);
2150#else
2151 hr = _SHGetDefaultValue(NULL, folder, pszPath);
2152#endif
2153 else
2154 {
2155 HKEY hKey;
2156
2157 if (RegCreateKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion", &hKey))
2158 hr = E_FAIL;
2159 else
2160 {
2161 DWORD dwType, dwPathLen = MAX_PATH * sizeof(WCHAR);
2162
2163 if (RegQueryValueExW(hKey, CSIDL_Data[folder].szValueName, NULL,
2164 &dwType, (LPBYTE)pszPath, &dwPathLen) ||
2165 (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
2166 {
2167#ifndef __REACTOS__
2168 hr = _SHGetDefaultValue(folder, pszPath);
2169#else
2170 hr = _SHGetDefaultValue(NULL, folder, pszPath);
2171#endif
2172 dwType = REG_EXPAND_SZ;
2173 switch (folder)
2174 {
2177 /* these two should never be set on 32-bit setups */
2178 if (!is_win64)
2179 {
2180 BOOL is_wow64;
2182 if (!is_wow64) break;
2183 }
2184 /* fall through */
2185 default:
2186 RegSetValueExW(hKey, CSIDL_Data[folder].szValueName, 0, dwType,
2187 (LPBYTE)pszPath, (strlenW(pszPath)+1)*sizeof(WCHAR));
2188 }
2189 }
2190 else
2191 {
2192 pszPath[dwPathLen / sizeof(WCHAR)] = '\0';
2193 hr = S_OK;
2194 }
2196 }
2197 }
2198 TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
2199 return hr;
2200}
2201
2203{
2204 char InfoBuffer[64];
2205 PTOKEN_USER UserInfo;
2206 DWORD InfoSize;
2207 LPWSTR SidStr;
2208
2209 UserInfo = (PTOKEN_USER) InfoBuffer;
2210 if (! GetTokenInformation(Token, TokenUser, InfoBuffer, sizeof(InfoBuffer),
2211 &InfoSize))
2212 {
2214 return NULL;
2215 UserInfo = HeapAlloc(GetProcessHeap(), 0, InfoSize);
2216 if (UserInfo == NULL)
2217 return NULL;
2218 if (! GetTokenInformation(Token, TokenUser, UserInfo, InfoSize,
2219 &InfoSize))
2220 {
2221 HeapFree(GetProcessHeap(), 0, UserInfo);
2222 return NULL;
2223 }
2224 }
2225
2226 if (! ConvertSidToStringSidW(UserInfo->User.Sid, &SidStr))
2227 SidStr = NULL;
2228
2229 if (UserInfo != (PTOKEN_USER) InfoBuffer)
2230 HeapFree(GetProcessHeap(), 0, UserInfo);
2231
2232 return SidStr;
2233}
2234
2235/* Gets the user's path (unexpanded) for the CSIDL with index folder:
2236 * If SHGFP_TYPE_DEFAULT is set, calls _SHGetDefaultValue for it. Otherwise
2237 * calls _SHGetUserShellFolderPath for it. Where it looks depends on hToken:
2238 * - if hToken is -1, looks in HKEY_USERS\.Default
2239 * - otherwise looks first in HKEY_CURRENT_USER, followed by HKEY_LOCAL_MACHINE
2240 * if HKEY_CURRENT_USER doesn't contain any entries. If both fail, finally
2241 * calls _SHGetDefaultValue for it.
2242 */
2244 LPWSTR pszPath)
2245{
2246 const WCHAR *szValueName;
2247 WCHAR buffer[40];
2248 HRESULT hr;
2249
2250 TRACE("%p,0x%08x,0x%02x,%p\n", hToken, dwFlags, folder, pszPath);
2251
2253 return E_INVALIDARG;
2254#ifdef __REACTOS__
2256 CSIDL_Data[folder].type != CSIDL_Type_InMyDocuments)
2257#else
2259#endif
2260 {
2261 return E_INVALIDARG;
2262 }
2263 if (!pszPath)
2264 return E_INVALIDARG;
2265
2267 {
2268#ifndef __REACTOS__
2269 hr = _SHGetDefaultValue(folder, pszPath);
2270#else
2271 hr = _SHGetDefaultValue(hToken, folder, pszPath);
2272#endif
2273 }
2274 else
2275 {
2276 static const WCHAR DefaultW[] = L".Default";
2277 LPCWSTR userPrefix = NULL;
2278 HKEY hRootKey;
2279
2280 if (hToken == (HANDLE)-1)
2281 {
2282 hRootKey = HKEY_USERS;
2283 userPrefix = DefaultW;
2284 }
2285 else if (hToken == NULL)
2286 hRootKey = HKEY_CURRENT_USER;
2287 else
2288 {
2289 hRootKey = HKEY_USERS;
2290 userPrefix = _GetUserSidStringFromToken(hToken);
2291 if (userPrefix == NULL)
2292 {
2293 hr = E_FAIL;
2294 goto error;
2295 }
2296 }
2297
2298 /* For CSIDL_Type_User we also use the GUID if no szValueName is provided */
2299 szValueName = CSIDL_Data[folder].szValueName;
2300 if (!szValueName)
2301 {
2303 szValueName = &buffer[0];
2304 }
2305
2306#ifndef __REACTOS__
2307 hr = _SHGetUserShellFolderPath(hRootKey, userPrefix, szValueName, pszPath);
2308 if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE)
2309 hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, szValueName, pszPath);
2310 if (FAILED(hr))
2311 hr = _SHGetDefaultValue(folder, pszPath);
2312#else
2313 hr = _SHGetUserShellFolderPath(hRootKey, hToken, userPrefix, szValueName, pszPath);
2314 if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE)
2315 hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, hToken, NULL, szValueName, pszPath);
2316 if (FAILED(hr))
2317 hr = _SHGetDefaultValue(hToken, folder, pszPath);
2318#endif
2319 if (userPrefix != NULL && userPrefix != DefaultW)
2320 LocalFree((HLOCAL) userPrefix);
2321 }
2322error:
2323 TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
2324 return hr;
2325}
2326
2327/* Gets the (unexpanded) path for the CSIDL with index folder. If dwFlags has
2328 * SHGFP_TYPE_DEFAULT set, calls _SHGetDefaultValue. Otherwise calls
2329 * _SHGetUserShellFolderPath for it, looking only in HKEY_LOCAL_MACHINE.
2330 * If this fails, falls back to _SHGetDefaultValue.
2331 */
2333 LPWSTR pszPath)
2334{
2335 HRESULT hr;
2336
2337 TRACE("0x%08x,0x%02x,%p\n", dwFlags, folder, pszPath);
2338
2340 return E_INVALIDARG;
2342 return E_INVALIDARG;
2343 if (!pszPath)
2344 return E_INVALIDARG;
2345
2347#ifndef __REACTOS__
2348 hr = _SHGetDefaultValue(folder, pszPath);
2349#else
2350 hr = _SHGetDefaultValue(NULL, folder, pszPath);
2351#endif
2352 else
2353 {
2354#ifndef __REACTOS__
2356#else
2358#endif
2359 CSIDL_Data[folder].szValueName, pszPath);
2360 if (FAILED(hr))
2361#ifndef __REACTOS__
2362 hr = _SHGetDefaultValue(folder, pszPath);
2363#else
2364 hr = _SHGetDefaultValue(NULL, folder, pszPath);
2365#endif
2366 }
2367 TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
2368 return hr;
2369}
2370
2371#ifndef __REACTOS__
2373{
2374 LONG lRet;
2375 DWORD disp;
2376
2377 lRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList", 0, NULL, 0,
2378 KEY_ALL_ACCESS, NULL, pKey, &disp);
2379 return HRESULT_FROM_WIN32(lRet);
2380}
2381
2382/* Reads the value named szValueName from the key profilesKey (assumed to be
2383 * opened by _SHOpenProfilesKey) into szValue, which is assumed to be MAX_PATH
2384 * WCHARs in length. If it doesn't exist, returns szDefault (and saves
2385 * szDefault to the registry).
2386 */
2387static HRESULT _SHGetProfilesValue(HKEY profilesKey, LPCWSTR szValueName,
2388 LPWSTR szValue, LPCWSTR szDefault)
2389{
2390 HRESULT hr;
2391 DWORD type, dwPathLen = MAX_PATH * sizeof(WCHAR);
2392 LONG lRet;
2393
2394 TRACE("%p,%s,%p,%s\n", profilesKey, debugstr_w(szValueName), szValue,
2395 debugstr_w(szDefault));
2396 lRet = RegQueryValueExW(profilesKey, szValueName, NULL, &type,
2397 (LPBYTE)szValue, &dwPathLen);
2398 if (!lRet && (type == REG_SZ || type == REG_EXPAND_SZ) && dwPathLen
2399 && *szValue)
2400 {
2401 dwPathLen /= sizeof(WCHAR);
2402 szValue[dwPathLen] = '\0';
2403 hr = S_OK;
2404 }
2405 else
2406 {
2407 /* Missing or invalid value, set a default */
2408 lstrcpynW(szValue, szDefault, MAX_PATH);
2409 TRACE("Setting missing value %s to %s\n", debugstr_w(szValueName),
2410 debugstr_w(szValue));
2411 lRet = RegSetValueExW(profilesKey, szValueName, 0, REG_EXPAND_SZ,
2412 (LPBYTE)szValue,
2413 (strlenW(szValue) + 1) * sizeof(WCHAR));
2414 if (lRet)
2415 hr = HRESULT_FROM_WIN32(lRet);
2416 else
2417 hr = S_OK;
2418 }
2419 TRACE("returning 0x%08x (output value is %s)\n", hr, debugstr_w(szValue));
2420 return hr;
2421}
2422#endif
2423
2424/* Attempts to expand environment variables from szSrc into szDest, which is
2425 * assumed to be MAX_PATH characters in length. Before referring to the
2426 * environment, handles a few variables directly, because the environment
2427 * variables may not be set when this is called (as during Wine's installation
2428 * when default values are being written to the registry).
2429 * The directly handled environment variables, and their source, are:
2430 * - ALLUSERSPROFILE, USERPROFILE: reads from the registry
2431 * - SystemDrive: uses GetSystemDirectoryW and uses the drive portion of its
2432 * path
2433 * If one of the directly handled environment variables is expanded, only
2434 * expands a single variable, and only in the beginning of szSrc.
2435 */
2436#ifndef __REACTOS__
2438#else
2439static HRESULT _SHExpandEnvironmentStrings(HANDLE hToken, LPCWSTR szSrc, LPWSTR szDest, DWORD cchDest)
2440#endif
2441{
2442 HRESULT hr;
2443#ifndef __REACTOS__
2444 WCHAR szTemp[MAX_PATH], szProfilesPrefix[MAX_PATH] = { 0 };
2445 HKEY key = NULL;
2446#else
2447 WCHAR szTemp[MAX_PATH];
2448#endif
2449
2450 TRACE("%s, %p\n", debugstr_w(szSrc), szDest);
2451
2452 if (!szSrc || !szDest) return E_INVALIDARG;
2453
2454 /* short-circuit if there's nothing to expand */
2455 if (szSrc[0] != '%')
2456 {
2457 strcpyW(szDest, szSrc);
2458 hr = S_OK;
2459 goto end;
2460 }
2461#ifndef __REACTOS__
2462 /* Get the profile prefix, we'll probably be needing it */
2464 if (SUCCEEDED(hr))
2465 {
2466 WCHAR def_val[MAX_PATH];
2467
2468 /* get the system drive */
2469 GetSystemDirectoryW(def_val, MAX_PATH);
2470 strcpyW( def_val + 3, L"Users" );
2471
2472 hr = _SHGetProfilesValue(key, L"ProfilesDirectory", szProfilesPrefix, def_val );
2473 }
2474#else
2475 hr = S_OK;
2476#endif
2477
2478 *szDest = 0;
2479 strcpyW(szTemp, szSrc);
2480 while (SUCCEEDED(hr) && szTemp[0] == '%')
2481 {
2482 if (!strncmpiW(szTemp, L"%ALLUSERSPROFILE%", ARRAY_SIZE(L"%ALLUSERSPROFILE%")-1))
2483 {
2484#ifndef __REACTOS__
2485 WCHAR szAllUsers[MAX_PATH];
2486
2487 strcpyW(szDest, szProfilesPrefix);
2488 hr = _SHGetProfilesValue(key, L"AllUsersProfile", szAllUsers, L"Public");
2489 PathAppendW(szDest, szAllUsers);
2490#else
2491 DWORD cchSize = cchDest;
2492 if (!GetAllUsersProfileDirectoryW(szDest, &cchSize))
2493 goto fallback_expand;
2494#endif
2495 PathAppendW(szDest, szTemp + ARRAY_SIZE(L"%ALLUSERSPROFILE%")-1);
2496 }
2497#ifndef __REACTOS__
2498 else if (!strncmpiW(szTemp, L"%PUBLIC%", ARRAY_SIZE(L"%PUBLIC%")-1))
2499 {
2500 WCHAR szAllUsers[MAX_PATH], def_val[MAX_PATH];
2501
2502 GetSystemDirectoryW(def_val, MAX_PATH);
2503 strcpyW( def_val + 3, L"Users\\Public" );
2504
2505 hr = _SHGetProfilesValue(key, L"Public", szAllUsers, def_val);
2506 PathAppendW(szDest, szAllUsers);
2507 PathAppendW(szDest, szTemp + ARRAY_SIZE(L"%PUBLIC%")-1);
2508 }
2509#endif
2510 else if (!strncmpiW(szTemp, L"%USERPROFILE%", ARRAY_SIZE(L"%USERPROFILE%")-1))
2511 {
2512#ifndef __REACTOS__
2514 DWORD userLen = MAX_PATH;
2515
2516 strcpyW(szDest, szProfilesPrefix);
2517 GetUserNameW(userName, &userLen);
2518 PathAppendW(szDest, userName);
2519#else
2520 DWORD cchSize = cchDest;
2521 if (!_SHGetUserProfileDirectoryW(hToken, szDest, &cchSize))
2522 goto fallback_expand;
2523#endif
2524 PathAppendW(szDest, szTemp + ARRAY_SIZE(L"%USERPROFILE%")-1);
2525 }
2526 else if (!strncmpiW(szTemp, L"%SystemDrive%", ARRAY_SIZE(L"%SystemDrive%")-1))
2527 {
2528#ifndef __REACTOS__
2530#else
2531 if (!GetSystemDirectoryW(szDest, cchDest))
2532 goto fallback_expand;
2533#endif
2534 strcpyW(szDest + 3, szTemp + ARRAY_SIZE(L"%SystemDrive%")-1 + 1);
2535 }
2536 else
2537#ifdef __REACTOS__
2538fallback_expand:
2539#endif
2540 {
2541#ifndef __REACTOS__
2542 DWORD ret = ExpandEnvironmentStringsW(szTemp, szDest, MAX_PATH);
2543#else
2544 DWORD ret = SHExpandEnvironmentStringsForUserW(hToken, szTemp, szDest, cchDest);
2545#endif
2546
2547#ifndef __REACTOS__
2548 if (ret > MAX_PATH)
2549#else
2550 if (ret > cchDest)
2551#endif
2553 else if (ret == 0)
2555 else if (!strcmpW( szTemp, szDest )) break; /* nothing expanded */
2556 }
2557 if (SUCCEEDED(hr)) strcpyW(szTemp, szDest);
2558 }
2559end:
2560#ifndef __REACTOS__
2561 if (key)
2563#endif
2564 TRACE("returning 0x%08x (input was %s, output is %s)\n", hr,
2565 debugstr_w(szSrc), debugstr_w(szDest));
2566 return hr;
2567}
2568
2569/*************************************************************************
2570 * SHGetFolderPathW [SHELL32.@]
2571 *
2572 * Convert nFolder to path.
2573 *
2574 * RETURNS
2575 * Success: S_OK
2576 * Failure: standard HRESULT error codes.
2577 *
2578 * NOTES
2579 * Most values can be overridden in either
2580 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
2581 * or in the same location in HKLM.
2582 * The "Shell Folders" registry key was used in NT4 and earlier systems.
2583 * Beginning with Windows 2000, the "User Shell Folders" key is used, so
2584 * changes made to it are made to the former key too. This synchronization is
2585 * done on-demand: not until someone requests the value of one of these paths
2586 * (by calling one of the SHGet functions) is the value synchronized.
2587 * Furthermore, the HKCU paths take precedence over the HKLM paths.
2588 */
2590 HWND hwndOwner, /* [I] owner window */
2591 int nFolder, /* [I] CSIDL identifying the folder */
2592 HANDLE hToken, /* [I] access token */
2593 DWORD dwFlags, /* [I] which path to return */
2594 LPWSTR pszPath) /* [O] converted path */
2595{
2596 HRESULT hr = SHGetFolderPathAndSubDirW(hwndOwner, nFolder, hToken, dwFlags, NULL, pszPath);
2599 return hr;
2600}
2601
2603 HWND hwndOwner, /* [I] owner window */
2604 int nFolder, /* [I] CSIDL identifying the folder */
2605 HANDLE hToken, /* [I] access token */
2606 DWORD dwFlags, /* [I] which path to return */
2607 LPCSTR pszSubPath, /* [I] sub directory of the specified folder */
2608 LPSTR pszPath) /* [O] converted path */
2609{
2610 int length;
2611 HRESULT hr = S_OK;
2612 LPWSTR pszSubPathW = NULL;
2613 LPWSTR pszPathW = NULL;
2614
2615 TRACE("%p,%#x,%p,%#x,%s,%p\n", hwndOwner, nFolder, hToken, dwFlags, debugstr_a(pszSubPath), pszPath);
2616
2617 if(pszPath) {
2618 pszPathW = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
2619 if(!pszPathW) {
2621 goto cleanup;
2622 }
2623 }
2624 TRACE("%08x,%08x,%s\n",nFolder, dwFlags, debugstr_w(pszSubPathW));
2625
2626 /* SHGetFolderPathAndSubDirW does not distinguish if pszSubPath isn't
2627 * set (null), or an empty string.therefore call it without the parameter set
2628 * if pszSubPath is an empty string
2629 */
2630 if (pszSubPath && pszSubPath[0]) {
2631 length = MultiByteToWideChar(CP_ACP, 0, pszSubPath, -1, NULL, 0);
2632 pszSubPathW = HeapAlloc(GetProcessHeap(), 0, length * sizeof(WCHAR));
2633 if(!pszSubPathW) {
2635 goto cleanup;
2636 }
2637 MultiByteToWideChar(CP_ACP, 0, pszSubPath, -1, pszSubPathW, length);
2638 }
2639
2640 hr = SHGetFolderPathAndSubDirW(hwndOwner, nFolder, hToken, dwFlags, pszSubPathW, pszPathW);
2641
2642 if (SUCCEEDED(hr) && pszPath)
2643 WideCharToMultiByte(CP_ACP, 0, pszPathW, -1, pszPath, MAX_PATH, NULL, NULL);
2644
2645cleanup:
2646 HeapFree(GetProcessHeap(), 0, pszPathW);
2647 HeapFree(GetProcessHeap(), 0, pszSubPathW);
2648 return hr;
2649}
2650
2651/*************************************************************************
2652 * SHGetFolderPathAndSubDirW [SHELL32.@]
2653 */
2655 HWND hwndOwner, /* [I] owner window */
2656 int nFolder, /* [I] CSIDL identifying the folder */
2657 HANDLE hToken, /* [I] access token */
2658 DWORD dwFlags, /* [I] which path to return */
2659 LPCWSTR pszSubPath,/* [I] sub directory of the specified folder */
2660 LPWSTR pszPath) /* [O] converted path */
2661{
2662 HRESULT hr;
2663 WCHAR szBuildPath[MAX_PATH], szTemp[MAX_PATH];
2666 int ret;
2667
2668 TRACE("%p,%#x,%p,%#x,%s,%p\n", hwndOwner, nFolder, hToken, dwFlags, debugstr_w(pszSubPath), pszPath);
2669
2670 /* Windows always NULL-terminates the resulting path regardless of success
2671 * or failure, so do so first
2672 */
2673 if (pszPath)
2674 *pszPath = '\0';
2675
2677 return E_INVALIDARG;
2679 return E_INVALIDARG;
2680 szTemp[0] = 0;
2682 switch (type)
2683 {
2685 hr = E_INVALIDARG;
2686 break;
2688 hr = S_FALSE;
2689 break;
2692 if (CSIDL_Data[folder].szDefaultPath &&
2693 !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) &&
2694 *CSIDL_Data[folder].szDefaultPath)
2695 {
2696 PathAddBackslashW(szTemp);
2697 strcatW(szTemp, CSIDL_Data[folder].szDefaultPath);
2698 }
2699 hr = S_OK;
2700 break;
2703 if (CSIDL_Data[folder].szDefaultPath &&
2704 !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) &&
2705 *CSIDL_Data[folder].szDefaultPath)
2706 {
2707 PathAddBackslashW(szTemp);
2708 strcatW(szTemp, CSIDL_Data[folder].szDefaultPath);
2709 }
2710 hr = S_OK;
2711 break;
2714 if (CSIDL_Data[folder].szDefaultPath &&
2715 !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) &&
2716 *CSIDL_Data[folder].szDefaultPath)
2717 {
2718 PathAddBackslashW(szTemp);
2719 strcatW(szTemp, CSIDL_Data[folder].szDefaultPath);
2720 }
2721 hr = S_OK;
2722 break;
2723 case CSIDL_Type_CurrVer:
2725 break;
2726 case CSIDL_Type_User:
2727#ifdef __REACTOS__
2728 case CSIDL_Type_InMyDocuments:
2729#endif
2730 hr = _SHGetUserProfilePath(hToken, dwFlags, folder, szTemp);
2731 break;
2734 break;
2735 default:
2736 FIXME("bogus type %d, please fix\n", type);
2737 hr = E_INVALIDARG;
2738 break;
2739 }
2740
2741 /* Expand environment strings if necessary */
2742 if (*szTemp == '%')
2743#ifndef __REACTOS__
2744 hr = _SHExpandEnvironmentStrings(szTemp, szBuildPath);
2745#else
2746 hr = _SHExpandEnvironmentStrings(hToken, szTemp, szBuildPath, _countof(szBuildPath));
2747#endif
2748 else
2749 strcpyW(szBuildPath, szTemp);
2750
2751 if (FAILED(hr)) goto end;
2752
2753 if(pszSubPath) {
2754 /* make sure the new path does not exceed the buffer length
2755 * and remember to backslash and terminate it */
2756 if(MAX_PATH < (lstrlenW(szBuildPath) + lstrlenW(pszSubPath) + 2)) {
2758 goto end;
2759 }
2760 PathAppendW(szBuildPath, pszSubPath);
2761 PathRemoveBackslashW(szBuildPath);
2762 }
2763 /* Copy the path if it's available before we might return */
2764 if (SUCCEEDED(hr) && pszPath)
2765 strcpyW(pszPath, szBuildPath);
2766
2767 /* if we don't care about existing directories we are ready */
2769
2770 if (PathFileExistsW(szBuildPath)) goto end;
2771
2772 /* not existing but we are not allowed to create it. The return value
2773 * is verified against shell32 version 6.0.
2774 */
2775 if (!(nFolder & CSIDL_FLAG_CREATE))
2776 {
2778 goto end;
2779 }
2780
2781 /* create directory/directories */
2782 ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, NULL);
2783 if (ret && ret != ERROR_ALREADY_EXISTS)
2784 {
2785 ERR("Failed to create directory %s.\n", debugstr_w(szBuildPath));
2786 hr = E_FAIL;
2787 goto end;
2788 }
2789
2790 TRACE("Created missing system directory %s\n", debugstr_w(szBuildPath));
2791
2792end:
2793#ifdef __REACTOS__
2794 /* create desktop.ini for custom icon */
2795 if ((nFolder & CSIDL_FLAG_CREATE) &&
2796 CSIDL_Data[folder].nShell32IconIndex)
2797 {
2798 WCHAR szIconLocation[MAX_PATH];
2800
2801 /* make the directory a read-only folder */
2802 dwAttributes = GetFileAttributesW(szBuildPath);
2804 SetFileAttributesW(szBuildPath, dwAttributes);
2805
2806 /* build the desktop.ini file path */
2807 PathAppendW(szBuildPath, L"desktop.ini");
2808
2809 /* build the icon location */
2810 StringCchPrintfW(szIconLocation, _countof(szIconLocation),
2811 L"%%SystemRoot%%\\system32\\shell32.dll,%d",
2812 CSIDL_Data[folder].nShell32IconIndex);
2813
2814 /* write desktop.ini */
2815 WritePrivateProfileStringW(L".ShellClassInfo", L"IconResource", szIconLocation, szBuildPath);
2816
2817 /* flush! */
2818 WritePrivateProfileStringW(NULL, NULL, NULL, szBuildPath);
2819
2820 /* make the desktop.ini a system and hidden file */
2821 dwAttributes = GetFileAttributesW(szBuildPath);
2823 SetFileAttributesW(szBuildPath, dwAttributes);
2824 }
2825#endif
2826
2827 TRACE("returning 0x%08x (final path is %s)\n", hr, debugstr_w(szBuildPath));
2828 return hr;
2829}
2830
2831/*************************************************************************
2832 * SHGetFolderPathA [SHELL32.@]
2833 *
2834 * See SHGetFolderPathW.
2835 */
2837 HWND hwndOwner,
2838 int nFolder,
2839 HANDLE hToken,
2840 DWORD dwFlags,
2841 LPSTR pszPath)
2842{
2843 WCHAR szTemp[MAX_PATH];
2844 HRESULT hr;
2845
2846 TRACE("%p,%d,%p,%#x,%p\n", hwndOwner, nFolder, hToken, dwFlags, pszPath);
2847
2848 if (pszPath)
2849 *pszPath = '\0';
2850 hr = SHGetFolderPathW(hwndOwner, nFolder, hToken, dwFlags, szTemp);
2851 if (SUCCEEDED(hr) && pszPath)
2852 WideCharToMultiByte(CP_ACP, 0, szTemp, -1, pszPath, MAX_PATH, NULL,
2853 NULL);
2854
2855 return hr;
2856}
2857
2858/* For each folder in folders, if its value has not been set in the registry,
2859 * calls _SHGetUserProfilePath or _SHGetAllUsersProfilePath (depending on the
2860 * folder's type) to get the unexpanded value first.
2861 * Writes the unexpanded value to User Shell Folders, and queries it with
2862 * SHGetFolderPathW to force the creation of the directory if it doesn't
2863 * already exist. SHGetFolderPathW also returns the expanded value, which
2864 * this then writes to Shell Folders.
2865 */
2866static HRESULT _SHRegisterFolders(HKEY hRootKey, HANDLE hToken,
2867 LPCWSTR szUserShellFolderPath, LPCWSTR szShellFolderPath, const UINT folders[],
2868 UINT foldersLen)
2869{
2870 const WCHAR *szValueName;
2871 WCHAR buffer[40];
2872 UINT i;
2874 HRESULT hr = S_OK;
2875 HKEY hUserKey = NULL, hKey = NULL;
2876 DWORD dwType, dwPathLen;
2877 LONG ret;
2878
2879 TRACE("%p,%p,%s,%p,%u\n", hRootKey, hToken,
2880 debugstr_w(szUserShellFolderPath), folders, foldersLen);
2881
2882 ret = RegCreateKeyW(hRootKey, szUserShellFolderPath, &hUserKey);
2883 if (ret)
2885 else
2886 {
2887 ret = RegCreateKeyW(hRootKey, szShellFolderPath, &hKey);
2888 if (ret)
2890 }
2891 for (i = 0; SUCCEEDED(hr) && i < foldersLen; i++)
2892 {
2893 dwPathLen = MAX_PATH * sizeof(WCHAR);
2894
2895 /* For CSIDL_Type_User we also use the GUID if no szValueName is provided */
2896 szValueName = CSIDL_Data[folders[i]].szValueName;
2897#ifdef __REACTOS__
2898 if (!szValueName &&
2899 (CSIDL_Data[folders[i]].type == CSIDL_Type_User ||
2900 CSIDL_Data[folders[i]].type == CSIDL_Type_InMyDocuments))
2901#else
2902 if (!szValueName && CSIDL_Data[folders[i]].type == CSIDL_Type_User)
2903#endif
2904 {
2905 StringFromGUID2( CSIDL_Data[folders[i]].id, buffer, 39 );
2906 szValueName = &buffer[0];
2907 }
2908
2909 if (!RegQueryValueExW(hUserKey, szValueName, NULL,
2910 &dwType, (LPBYTE)path, &dwPathLen) &&
2911 (dwType == REG_SZ || dwType == REG_EXPAND_SZ))
2912 {
2914 hToken, SHGFP_TYPE_CURRENT, path);
2915 }
2916 else
2917 {
2918 *path = '\0';
2919#ifdef __REACTOS__
2920 if (CSIDL_Data[folders[i]].type == CSIDL_Type_User ||
2921 CSIDL_Data[folders[i]].type == CSIDL_Type_InMyDocuments)
2922#else
2923 if (CSIDL_Data[folders[i]].type == CSIDL_Type_User)
2924#endif
2925 _SHGetUserProfilePath(hToken, SHGFP_TYPE_CURRENT, folders[i],
2926 path);
2927 else if (CSIDL_Data[folders[i]].type == CSIDL_Type_AllUsers)
2929 else if (CSIDL_Data[folders[i]].type == CSIDL_Type_WindowsPath)
2930 {
2932 if (CSIDL_Data[folders[i]].szDefaultPath &&
2933 !IS_INTRESOURCE(CSIDL_Data[folders[i]].szDefaultPath))
2934 {
2936 strcatW(path, CSIDL_Data[folders[i]].szDefaultPath);
2937 }
2938 }
2939 else
2940 hr = E_FAIL;
2941 if (*path)
2942 {
2943 ret = RegSetValueExW(hUserKey, szValueName, 0, REG_EXPAND_SZ,
2944 (LPBYTE)path, (strlenW(path) + 1) * sizeof(WCHAR));
2945 if (ret)
2947 else
2948 {
2950 hToken, SHGFP_TYPE_CURRENT, path);
2951 ret = RegSetValueExW(hKey, szValueName, 0, REG_SZ,
2952 (LPBYTE)path, (strlenW(path) + 1) * sizeof(WCHAR));
2953 if (ret)
2955 }
2956 }
2957 }
2958 }
2959 if (hUserKey)
2960 RegCloseKey(hUserKey);
2961 if (hKey)
2963
2964 TRACE("returning 0x%08x\n", hr);
2965 return hr;
2966}
2967
2969{
2970 static const UINT folders[] = {
2992/* Cannot use #if _WIN32_WINNT >= 0x0600 because _WIN32_WINNT == 0x0600 here. */
2993#ifndef __REACTOS__
3000#endif
3001 };
3002 WCHAR userShellFolderPath[MAX_PATH], shellFolderPath[MAX_PATH];
3003 LPCWSTR pUserShellFolderPath, pShellFolderPath;
3004 HRESULT hr = S_OK;
3005 HKEY hRootKey;
3006 HANDLE hToken;
3007
3008 TRACE("%s\n", bDefault ? "TRUE" : "FALSE");
3009 if (bDefault)
3010 {
3011 hToken = (HANDLE)-1;
3012 hRootKey = HKEY_USERS;
3013 strcpyW(userShellFolderPath, L".Default");
3014 PathAddBackslashW(userShellFolderPath);
3015 strcatW(userShellFolderPath, szSHUserFolders);
3016 pUserShellFolderPath = userShellFolderPath;
3017 strcpyW(shellFolderPath, L".Default");
3018 PathAddBackslashW(shellFolderPath);
3019 strcatW(shellFolderPath, szSHFolders);
3020 pShellFolderPath = shellFolderPath;
3021 }
3022 else
3023 {
3024 hToken = NULL;
3025 hRootKey = HKEY_CURRENT_USER;
3026 pUserShellFolderPath = szSHUserFolders;
3027 pShellFolderPath = szSHFolders;
3028 }
3029
3030 hr = _SHRegisterFolders(hRootKey, hToken, pUserShellFolderPath,
3031 pShellFolderPath, folders, ARRAY_SIZE(folders));
3032 TRACE("returning 0x%08x\n", hr);
3033 return hr;
3034}
3035
3037{
3038 static const UINT folders[] = {
3051 };
3052 HRESULT hr;
3053
3054 TRACE("\n");
3056 szSHFolders, folders, ARRAY_SIZE(folders));
3057 TRACE("returning 0x%08x\n", hr);
3058 return hr;
3059}
3060
3061/* Register the default values in the registry, as some apps seem to depend
3062 * on their presence. The set registered was taken from Windows XP.
3063 */
3065{
3066 HRESULT hr;
3067
3069 if (SUCCEEDED(hr))
3071 if (SUCCEEDED(hr))
3073 return hr;
3074}
3075
3076/*************************************************************************
3077 * SHGetSpecialFolderPathA [SHELL32.@]
3078 */
3080 HWND hwndOwner,
3081 LPSTR szPath,
3082 int nFolder,
3083 BOOL bCreate)
3084{
3085 return SHGetFolderPathA(hwndOwner, nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0), NULL, 0,
3086 szPath) == S_OK;
3087}
3088
3089/*************************************************************************
3090 * SHGetSpecialFolderPathW
3091 */
3093 HWND hwndOwner,
3094 LPWSTR szPath,
3095 int nFolder,
3096 BOOL bCreate)
3097{
3098 return SHGetFolderPathW(hwndOwner, nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0), NULL, 0,
3099 szPath) == S_OK;
3100}
3101
3102#ifdef __REACTOS__
3103HRESULT SHGetFolderLocationHelper(HWND hwnd, int nFolder, REFCLSID clsid, LPITEMIDLIST *ppidl)
3104{
3105 HRESULT hr;
3106 IShellFolder *psf;
3109 *ppidl = NULL;
3111 return hr;
3112 if (SUCCEEDED(hr = SHBindToObject(NULL, parent, &IID_IShellFolder, (void**)&psf)))
3113 {
3114 WCHAR clsidstr[2 + 38 + 1];
3115 clsidstr[0] = clsidstr[1] = L':';
3116 StringFromGUID2(clsid, clsidstr + 2, 38 + 1);
3117 hr = IShellFolder_ParseDisplayName(psf, hwnd, NULL, clsidstr, NULL, &child, NULL);
3118 if (SUCCEEDED(hr))
3119 *ppidl = ILCombine(parent, child);
3120 IShellFolder_Release(psf);
3121 ILFree(child);
3122 }
3123 ILFree(parent);
3124 return hr;
3125}
3126#endif
3127
3128/*************************************************************************
3129 * SHGetFolderLocation [SHELL32.@]
3130 *
3131 * Gets the folder locations from the registry and creates a pidl.
3132 *
3133 * PARAMS
3134 * hwndOwner [I]
3135 * nFolder [I] CSIDL_xxxxx
3136 * hToken [I] token representing user, or NULL for current user, or -1 for
3137 * default user
3138 * dwReserved [I] must be zero
3139 * ppidl [O] PIDL of a special folder
3140 *
3141 * RETURNS
3142 * Success: S_OK
3143 * Failure: Standard OLE-defined error result, S_FALSE or E_INVALIDARG
3144 *
3145 * NOTES
3146 * Creates missing reg keys and directories.
3147 * Mostly forwards to SHGetFolderPathW, but a few values of nFolder return
3148 * virtual folders that are handled here.
3149 */
3151 HWND hwndOwner,
3152 int nFolder,
3153 HANDLE hToken,
3155 LPITEMIDLIST *ppidl)
3156{
3158#ifdef __REACTOS__
3160#endif
3161
3162 TRACE("%p 0x%08x %p 0x%08x %p\n",
3163 hwndOwner, nFolder, hToken, dwReserved, ppidl);
3164
3165 if (!ppidl)
3166 return E_INVALIDARG;
3167 if (dwReserved)
3168 return E_INVALIDARG;
3169
3170#ifdef __REACTOS__
3171 if ((nFolder & CSIDL_FLAG_NO_ALIAS) &&
3173 {
3174 *ppidl = ILCreateFromPathW(szPath);
3175 if (*ppidl)
3176 return S_OK;
3177 }
3178#endif
3179 /* The virtual folders' locations are not user-dependent */
3180 *ppidl = NULL;
3181 switch (nFolder & CSIDL_FOLDER_MASK)
3182 {
3183 case CSIDL_DESKTOP:
3184 *ppidl = _ILCreateDesktop();
3185 break;
3186
3187 case CSIDL_PERSONAL:
3188 *ppidl = _ILCreateMyDocuments();
3189 break;
3190
3191 case CSIDL_INTERNET:
3192 *ppidl = _ILCreateIExplore();
3193 break;
3194
3195 case CSIDL_CONTROLS:
3196 *ppidl = _ILCreateControlPanel();
3197 break;
3198
3199 case CSIDL_PRINTERS:
3200 *ppidl = _ILCreatePrinters();
3201 break;
3202
3203 case CSIDL_BITBUCKET:
3204 *ppidl = _ILCreateBitBucket();
3205 break;
3206
3207 case CSIDL_DRIVES:
3208 *ppidl = _ILCreateMyComputer();
3209 break;
3210
3211 case CSIDL_NETWORK:
3212 *ppidl = _ILCreateNetwork();
3213 break;
3214
3215#ifdef __REACTOS__
3216 case CSIDL_CONNECTIONS:
3217 {
3218 EXTERN_C const CLSID CLSID_ConnectionFolder;
3219 hr = SHGetFolderLocationHelper(hwndOwner, CSIDL_CONTROLS, &CLSID_ConnectionFolder, ppidl);
3220 break;
3221 }
3222#endif
3223
3224 default:
3225 {
3227
3228 hr = SHGetFolderPathW(hwndOwner, nFolder, hToken,
3230 if (SUCCEEDED(hr))
3231 {
3232 DWORD attributes=0;
3233
3234 TRACE("Value=%s\n", debugstr_w(szPath));
3235 hr = SHILCreateFromPathW(szPath, ppidl, &attributes);
3236 }
3238 {
3239 /* unlike SHGetFolderPath, SHGetFolderLocation in shell32
3240 * version 6.0 returns E_FAIL for nonexistent paths
3241 */
3242 hr = E_FAIL;
3243 }
3244 }
3245 }
3246 if(*ppidl)
3247 hr = S_OK;
3248
3249 TRACE("-- (new pidl %p)\n",*ppidl);
3250 return hr;
3251}
3252
3253/*************************************************************************
3254 * SHGetSpecialFolderLocation [SHELL32.@]
3255 *
3256 * NOTES
3257 * In NT5, SHGetSpecialFolderLocation needs the <winntdir>/Recent
3258 * directory.
3259 */
3261 HWND hwndOwner,
3262 INT nFolder,
3263 LPITEMIDLIST * ppidl)
3264{
3266
3267 TRACE("(%p,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
3268
3269 if (!ppidl)
3270 return E_INVALIDARG;
3271
3272 hr = SHGetFolderLocation(hwndOwner, nFolder, NULL, 0, ppidl);
3273 return hr;
3274}
#define PRF_VERIFYEXISTS
Definition: PathResolve.cpp:38
#define PRF_TRYPROGRAMEXTENSIONS
Definition: PathResolve.cpp:40
#define PRF_REQUIREABSOLUTE
Definition: PathResolve.cpp:45
#define PRF_FIRSTDIRDEF
Definition: PathResolve.cpp:41
#define PRF_DONTFINDLNK
Definition: PathResolve.cpp:42
#define shell32_hInstance
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define ARRAY_SIZE(A)
Definition: main.h:33
#define IDS_PROGRAMS
Definition: resource.h:69
#define EXTERN_C
Definition: basetyps.h:12
#define FIXME(fmt,...)
Definition: debug.h:114
#define ERR(fmt,...)
Definition: debug.h:113
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define IDS_PERSONAL
Definition: desktop.c:27
#define APIENTRY
Definition: api.h:79
#define IDI_SHELL_NETWORK_FOLDER
Definition: resource.h:5
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LSTATUS WINAPI RegGetValueW(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: reg.c:1931
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
LONG WINAPI RegCreateKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1201
BOOL WINAPI GetUserNameW(LPWSTR lpszName, LPDWORD lpSize)
Definition: misc.c:291
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:411
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:294
BOOL WINAPI ConvertSidToStringSidW(PSID Sid, LPWSTR *StringSid)
Definition: security.c:3583
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:468
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define GetCurrentProcess()
Definition: compat.h:759
#define IsWow64Process
Definition: compat.h:760
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define wcsicmp
Definition: compat.h:15
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR *const ext[]
Definition: module.c:53
#define IDS_FAVORITES
Definition: resource.h:35
static void cleanup(void)
Definition: main.c:1335
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:794
BOOL WINAPI GetVolumeInformationW(IN LPCWSTR lpRootPathName, IN LPWSTR lpVolumeNameBuffer, IN DWORD nVolumeNameSize, OUT LPDWORD lpVolumeSerialNumber OPTIONAL, OUT LPDWORD lpMaximumComponentLength OPTIONAL, OUT LPDWORD lpFileSystemFlags OPTIONAL, OUT LPWSTR lpFileSystemNameBuffer OPTIONAL, IN DWORD nFileSystemNameSize)
Definition: volume.c:226
DWORD WINAPI GetShortPathNameA(IN LPCSTR lpszLongPath, OUT LPSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1752
UINT WINAPI GetSystemWow64DirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2421
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1833
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
BOOL WINAPI WritePrivateProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR string, LPCWSTR filename)
Definition: profile.c:1453
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4242
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4261
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4223
BOOL is_wow64
Definition: msi.c:54
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
Definition: compobj.c:2434
#define RRF_RT_REG_SZ
Definition: driver.c:575
EXTERN_C HRESULT SHBindToObject(_In_opt_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ REFIID riid, _Out_ void **ppvObj)
Definition: utils.cpp:220
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:326
LPVOID WINAPI SHAlloc(SIZE_T len)
Definition: shellole.c:304
#define CSIDL_LINKS
Definition: shellpath.c:1059
static LPWSTR PathGetExtensionW(LPCWSTR lpszPath)
Definition: shellpath.c:434
#define CSIDL_APPDATA_LOCALLOW
Definition: shellpath.c:1060
VOID WINAPI PathQualifyAW(LPVOID pszPath)
Definition: shellpath.c:829
BOOL WINAPI PathIsRootAW(LPCVOID lpszPath)
Definition: shellpath.c:511
VOID WINAPI PathQualifyA(LPSTR pszPath)
Definition: shellpath.c:808
static const WCHAR Program_Files_Common_FilesW[]
Definition: shellpath.c:1027
static VOID WINAPI PathQualifyExW(_Inout_ LPWSTR pszPath, _Inout_opt_ LPCWSTR pszDir, _In_ DWORD dwFlags)
Definition: shellpath.c:158
static BOOL DoGetProductType(PNT_PRODUCT_TYPE ProductType)
Definition: shellpath.c:71
HRESULT SHELL_RegisterShellFolders(void)
Definition: shellpath.c:3064
static const WCHAR szKnownFolderRedirections[]
Definition: shellpath.c:1038
HRESULT WINAPI SHGetSpecialFolderLocation(HWND hwndOwner, INT nFolder, LPITEMIDLIST *ppidl)
Definition: shellpath.c:3260
enum _CSIDL_Type CSIDL_Type
LPVOID WINAPI SHPathGetExtensionW(LPCWSTR lpszPath, DWORD void1, DWORD void2)
Definition: shellpath.c:445
BOOL WINAPI IsLFNDriveAW(LPCVOID lpszPath)
Definition: shellpath.c:639
static const WCHAR Start_Menu_Admin_ToolsW[]
Definition: shellpath.c:1029
static const WCHAR szSHUserFolders[]
Definition: shellpath.c:1035
#define CSIDL_DOWNLOADS
Definition: shellpath.c:1058
HRESULT WINAPI SHGetFolderLocation(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwReserved, LPITEMIDLIST *ppidl)
Definition: shellpath.c:3150
#define VALID_SHORT_PATH_CHAR_CLASSES
HRESULT WINAPI SHGetFolderPathW(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath)
Definition: shellpath.c:2589
static const WCHAR Local_Settings_HistoryW[]
Definition: shellpath.c:1022
static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder, LPWSTR pszPath)
Definition: shellpath.c:2133
static BOOL PathMakeUniqueNameW(LPWSTR lpszBuffer, DWORD dwBuffSize, LPCWSTR lpszShortName, LPCWSTR lpszLongName, LPCWSTR lpszPathName)
Definition: shellpath.c:668
static LPSTR PathGetExtensionA(LPCSTR lpszPath)
Definition: shellpath.c:423
static HRESULT _SHRegisterUserShellFolders(BOOL bDefault)
Definition: shellpath.c:2968
BOOL WINAPI PathAppendAW(LPVOID lpszPath1, LPCVOID lpszPath2)
Definition: shellpath.c:407
static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest)
Definition: shellpath.c:2437
static void PathGetShortPathA(LPSTR pszPath)
Definition: shellpath.c:467
static BOOL PathMakeUniqueNameA(LPSTR lpszBuffer, DWORD dwBuffSize, LPCSTR lpszShortName, LPCSTR lpszLongName, LPCSTR lpszPathName)
Definition: shellpath.c:652
BOOL WINAPI PathIsExeAW(LPCVOID path)
Definition: shellpath.c:557
BOOL WINAPI PathFileExistsAW(LPCVOID lpszPath)
Definition: shellpath.c:567
static const WCHAR Program_FilesW[]
Definition: shellpath.c:1026
static const BOOL is_win64
Definition: shellpath.c:59
#define CSIDL_SEARCHES
Definition: shellpath.c:1062
_CSIDL_Type
Definition: shellpath.c:1041
@ CSIDL_Type_CurrVer
Definition: shellpath.c:1047
@ CSIDL_Type_AllUsers
Definition: shellpath.c:1046
@ CSIDL_Type_WindowsPath
Definition: shellpath.c:1050
@ CSIDL_Type_Disallowed
Definition: shellpath.c:1048
@ CSIDL_Type_SystemX86Path
Definition: shellpath.c:1052
@ CSIDL_Type_SystemPath
Definition: shellpath.c:1051
@ CSIDL_Type_User
Definition: shellpath.c:1042
@ CSIDL_Type_NonExistent
Definition: shellpath.c:1049
HRESULT WINAPI SHGetFolderPathAndSubDirW(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPCWSTR pszSubPath, LPWSTR pszPath)
Definition: shellpath.c:2654
static HRESULT _SHOpenProfilesKey(PHKEY pKey)
Definition: shellpath.c:2372
#define CSIDL_SAVED_GAMES
Definition: shellpath.c:1061
static LONG PathProcessCommandW(LPCWSTR lpszPath, LPWSTR lpszBuff, DWORD dwBuffSize, DWORD dwFlags)
Definition: shellpath.c:987
static BOOL WINAPI PathMakeAbsoluteW(_Inout_ LPWSTR path)
Definition: shellpath.c:141
BOOL WINAPI IsLFNDriveW(LPCWSTR lpszPath)
Definition: shellpath.c:591
static HRESULT _SHGetAllUsersProfilePath(DWORD dwFlags, BYTE folder, LPWSTR pszPath)
Definition: shellpath.c:2332
HRESULT WINAPI SHGetFolderPathAndSubDirA(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPCSTR pszSubPath, LPSTR pszPath)
Definition: shellpath.c:2602
INT Shell_ParseSpecialFolder(_In_ LPCWSTR pszStart, _Out_ LPWSTR *ppch, _Out_ INT *pcch)
Definition: shellpath.c:1859
static HRESULT _SHGetDefaultValue(BYTE folder, LPWSTR pszPath)
Definition: shellpath.c:2017
static BOOL PathIsExeA(LPCSTR lpszPath)
Definition: shellpath.c:521
static const WCHAR Start_Menu_ProgramsW[]
Definition: shellpath.c:1028
static const WCHAR szSHFolders[]
Definition: shellpath.c:1034
BOOL APIENTRY IsRemovableDrive(DWORD iDrive)
Definition: shellpath.c:107
INT SHGetSpecialFolderID(_In_ LPCWSTR pszName)
Definition: shellpath.c:1845
static HRESULT _SHGetProfilesValue(HKEY profilesKey, LPCWSTR szValueName, LPWSTR szValue, LPCWSTR szDefault)
Definition: shellpath.c:2387
static const CSIDL_DATA CSIDL_Data[]
Definition: shellpath.c:1074
static BOOL WINAPI PathSearchOnExtensionsW(_Inout_ LPWSTR pszPath, _In_opt_ LPCWSTR *ppszDirs, _In_ BOOL bDoSearch, _In_ DWORD dwWhich)
Definition: shellpath.c:120
static const WCHAR Local_Settings_Temporary_Internet_FilesW[]
Definition: shellpath.c:1023
static const WCHAR Start_Menu_StartupW[]
Definition: shellpath.c:1030
static const WCHAR szKnownFolderDescriptions[]
Definition: shellpath.c:1037
VOID WINAPI PathQualifyW(LPWSTR pszPath)
Definition: shellpath.c:820
BOOL WINAPI PathMakeUniqueNameAW(LPVOID lpszBuffer, DWORD dwBuffSize, LPCVOID lpszShortName, LPCVOID lpszLongName, LPCVOID lpszPathName)
Definition: shellpath.c:684
BOOL WINAPI PathResolveA(LPSTR path, LPCSTR *dirs, DWORD flags)
Definition: shellpath.c:837
BOOL _SHGetUserProfileDirectoryW(HANDLE hToken, LPWSTR szPath, LPDWORD lpcchPath)
Definition: shellpath.c:1981
LONG WINAPI PathProcessCommandAW(LPCVOID lpszPath, LPVOID lpszBuff, DWORD dwBuffSize, DWORD dwFlags)
Definition: shellpath.c:1003
VOID WINAPI PathGetShortPathAW(LPVOID pszPath)
Definition: shellpath.c:497
static const WCHAR MusicW[]
Definition: shellpath.c:1024
BOOL WINAPI PathResolveW(_Inout_ LPWSTR path, _Inout_opt_ LPCWSTR *dirs, _In_ DWORD flags)
Definition: shellpath.c:883
static HRESULT _SHRegisterCommonShellFolders(void)
Definition: shellpath.c:3036
static LPWSTR _GetUserSidStringFromToken(HANDLE Token)
Definition: shellpath.c:2202
BOOL WINAPI PathResolveAW(LPVOID path, LPCVOID *paths, DWORD flags)
Definition: shellpath.c:960
static const WCHAR PicturesW[]
Definition: shellpath.c:1025
static LONG PathProcessCommandA(LPCSTR lpszPath, LPSTR lpszBuff, DWORD dwBuffSize, DWORD dwFlags)
Definition: shellpath.c:971
static HRESULT _SHRegisterFolders(HKEY hRootKey, HANDLE hToken, LPCWSTR szUserShellFolderPath, LPCWSTR szShellFolderPath, const UINT folders[], UINT foldersLen)
Definition: shellpath.c:2866
int WINAPI PathCleanupSpec(LPCWSTR lpszPathW, LPWSTR lpszFileW)
Definition: shellpath.c:736
static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags, BYTE folder, LPWSTR pszPath)
Definition: shellpath.c:2243
static const WCHAR Application_DataW[]
Definition: shellpath.c:1020
BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath)
Definition: shellpath.c:453
BOOL WINAPI SHGetSpecialFolderPathA(HWND hwndOwner, LPSTR szPath, int nFolder, BOOL bCreate)
Definition: shellpath.c:3079
HRESULT WINAPI SHGetFolderPathA(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPSTR pszPath)
Definition: shellpath.c:2836
BOOL WINAPI PathYetAnotherMakeUniqueName(LPWSTR buffer, LPCWSTR path, LPCWSTR shortname, LPCWSTR longname)
Definition: shellpath.c:699
#define MSDOS_8DOT3_LEN
BOOL WINAPI SHGetSpecialFolderPathW(HWND hwndOwner, LPWSTR szPath, int nFolder, BOOL bCreate)
Definition: shellpath.c:3092
BOOL PathIsExeW(LPCWSTR lpszPath)
Definition: shellpath.c:539
static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix, LPCWSTR value, LPWSTR path)
Definition: shellpath.c:1898
static void PathGetShortPathW(LPWSTR pszPath)
Definition: shellpath.c:482
BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath)
Definition: shellpath.c:577
static const WCHAR Local_Settings_Application_DataW[]
Definition: shellpath.c:1021
static BOOL WINAPI PathIsAbsoluteW(_In_ LPCWSTR path)
Definition: shellpath.c:136
enum _NT_PRODUCT_TYPE NT_PRODUCT_TYPE
#define CSIDL_CONTACTS
Definition: shellpath.c:1057
enum _NT_PRODUCT_TYPE * PNT_PRODUCT_TYPE
_NT_PRODUCT_TYPE
Definition: shellpath.c:63
@ NtProductWinNt
Definition: shellpath.c:64
@ NtProductLanManNt
Definition: shellpath.c:65
@ NtProductServer
Definition: shellpath.c:66
VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
Definition: ordinal.c:4514
int WINAPI PathGetDriveNumberW(const WCHAR *path)
Definition: path.c:553
BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
Definition: path.c:629
BOOL WINAPI PathFindOnPathW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs)
Definition: path.c:1403
UINT WINAPI PathGetCharTypeA(UCHAR ch)
Definition: path.c:3026
BOOL WINAPI PathRemoveFileSpecA(LPSTR lpszPath)
Definition: path.c:586
BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
Definition: path.c:733
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:447
void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
Definition: path.c:823
LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive)
Definition: path.c:348
BOOL WINAPI PathFileExistsA(LPCSTR lpszPath)
Definition: path.c:1755
BOOL WINAPI PathIsRootW(LPCWSTR lpszPath)
Definition: path.c:1642
BOOL WINAPI PathIsRootA(LPCSTR lpszPath)
Definition: path.c:1602
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1777
VOID WINAPI PathUnquoteSpacesW(LPWSTR lpszPath)
Definition: path.c:1034
BOOL WINAPI PathIsUNCW(LPCWSTR lpszPath)
Definition: path.c:2266
BOOL WINAPI PathFindOnPathExW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs, DWORD dwWhich)
Definition: path.c:1351
LPSTR WINAPI PathFindExtensionA(LPCSTR lpszPath)
Definition: path.c:422
BOOL WINAPI PathIsValidCharW(WCHAR c, DWORD class)
Definition: path.c:4419
UINT WINAPI PathGetCharTypeW(WCHAR ch)
Definition: path.c:3036
BOOL WINAPI PathIsFileSpecW(LPCWSTR lpszPath)
Definition: path.c:2133
BOOL WINAPI PathFileExistsAndAttributesW(LPCWSTR lpszPath, DWORD *dwAttr)
Definition: path.c:1832
BOOL WINAPI PathFileExistsDefExtW(LPWSTR lpszPath, DWORD dwWhich)
Definition: path.c:1117
LPWSTR WINAPI PathRemoveBackslashW(LPWSTR lpszPath)
Definition: path.c:867
DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
Definition: string.c:2667
INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
Definition: string.c:2791
LPWSTR WINAPI StrCpyNW(LPWSTR dst, LPCWSTR src, int count)
Definition: string.c:536
BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
Definition: url.c:2432
#define IShellFolder_ParseDisplayName
Definition: utils.cpp:14
BOOL WINAPI GetAllUsersProfileDirectoryW(_Out_opt_ LPWSTR lpProfileDir, _Inout_ LPDWORD lpcchSize)
Definition: profile.c:1310
BOOL WINAPI GetDefaultUserProfileDirectoryW(_Out_opt_ LPWSTR lpProfileDir, _Inout_ LPDWORD lpcchSize)
Definition: profile.c:1443
BOOL WINAPI GetUserProfileDirectoryW(_In_ HANDLE hToken, _Out_opt_ LPWSTR lpProfileDir, _Inout_ LPDWORD lpcchSize)
Definition: profile.c:1792
static const WCHAR Cleanup[]
Definition: register.c:80
#define assert(x)
Definition: debug.h:53
r parent
Definition: btrfs.c:3010
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxRegKey * pKey
FxAutoRegKey hKey
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304
GLsizei const GLuint * paths
Definition: glext.h:11717
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define GUID_NULL
Definition: ks.h:106
#define REG_SZ
Definition: layer.c:22
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
TCHAR szTitle[MAX_LOADSTRING]
Definition: magnifier.c:35
#define error(str)
Definition: mkdosfs.c:1605
#define pch(ap)
Definition: match.c:418
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
LPCWSTR szPath
Definition: env.c:37
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:202
static HWND child
Definition: cursoricon.c:298
static const WCHAR path1[]
Definition: path.c:28
#define _Inout_
Definition: ms_sal.h:378
#define _Inout_opt_
Definition: ms_sal.h:379
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
REFCLSID clsid
Definition: msctf.c:82
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED _In_opt_ LPTRANSMIT_FILE_BUFFERS _In_ DWORD dwReserved
Definition: mswsock.h:95
unsigned int UINT
Definition: ndis.h:50
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define KEY_READ
Definition: nt_native.h:1023
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define UNICODE_NULL
#define L(x)
Definition: ntvdm.h:50
#define PathAppendA
Definition: pathcch.h:308
#define PathCombineW
Definition: pathcch.h:317
#define PathAddBackslashW
Definition: pathcch.h:301
#define PathAppendW
Definition: pathcch.h:309
#define LOWORD(l)
Definition: pedump.c:82
long LONG
Definition: pedump.c:60
LPITEMIDLIST _ILCreateMyComputer(void)
Definition: pidl.c:1646
LPITEMIDLIST _ILCreateIExplore(void)
Definition: pidl.c:1658
void WINAPI ILFree(LPITEMIDLIST pidl)
Definition: pidl.c:940
HRESULT WINAPI SHILCreateFromPathW(LPCWSTR path, LPITEMIDLIST *ppidl, DWORD *attributes)
Definition: pidl.c:401
LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
Definition: pidl.c:712
LPITEMIDLIST _ILCreateDesktop(void)
Definition: pidl.c:1635
LPITEMIDLIST _ILCreateNetwork(void)
Definition: pidl.c:1710
LPITEMIDLIST _ILCreatePrinters(void)
Definition: pidl.c:1683
LPITEMIDLIST _ILCreateControlPanel(void)
Definition: pidl.c:1664
LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path)
Definition: pidl.c:997
LPITEMIDLIST _ILCreateMyDocuments(void)
Definition: pidl.c:1652
LPITEMIDLIST _ILCreateBitBucket(void)
Definition: pidl.c:1716
#define INT
Definition: polytest.cpp:20
#define REFIID
Definition: guiddef.h:118
#define REFCLSID
Definition: guiddef.h:117
#define strncmpiW(s1, s2, n)
Definition: unicode.h:46
#define strcmpW(s1, s2)
Definition: unicode.h:44
#define strlenW(s)
Definition: unicode.h:34
#define strcatW(d, s)
Definition: unicode.h:36
#define sprintfW
Definition: unicode.h:64
#define strcpyW(d, s)
Definition: unicode.h:35
static __inline BOOL SHELL_OsIsUnicode(void)
Definition: shell32_main.h:140
static __inline LPWSTR __SHCloneStrAtoW(WCHAR **target, const char *source)
Definition: shell32_main.h:170
_In_ LPCSTR pszDir
Definition: shellapi.h:584
#define CSIDL_FLAG_CREATE
int WINAPI SHCreateDirectoryExW(HWND hWnd, LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
Definition: shlfileop.cpp:905
HRESULT hr
Definition: shlfolder.c:183
#define CSIDL_COMMON_TEMPLATES
Definition: shlobj.h:2210
#define CSIDL_COMMON_DESKTOPDIRECTORY
Definition: shlobj.h:2190
#define CSIDL_TEMPLATES
Definition: shlobj.h:2186
#define CSIDL_PROGRAM_FILES
Definition: shlobj.h:2203
#define CSIDL_INTERNET_CACHE
Definition: shlobj.h:2197
_In_ int _In_ BOOL bCreate
Definition: shlobj.h:1519
#define CSIDL_DESKTOPDIRECTORY
Definition: shlobj.h:2181
#define CSIDL_SENDTO
Definition: shlobj.h:2175
#define CSIDL_RECENT
Definition: shlobj.h:2174
#define CSIDL_MYDOCUMENTS
Definition: shlobj.h:2178
#define CSIDL_ADMINTOOLS
Definition: shlobj.h:2213
#define CSIDL_COMMON_STARTMENU
Definition: shlobj.h:2187
@ SHGFP_TYPE_DEFAULT
Definition: shlobj.h:2143
@ SHGFP_TYPE_CURRENT
Definition: shlobj.h:2142
#define PCS_REPLACEDCHAR
Definition: shlobj.h:367
#define CSIDL_FONTS
Definition: shlobj.h:2185
#define CSIDL_PERSONAL
Definition: shlobj.h:2171
#define CSIDL_FAVORITES
Definition: shlobj.h:2172
#define CSIDL_FLAG_NO_ALIAS
Definition: shlobj.h:2226
#define CSIDL_COMMON_APPDATA
Definition: shlobj.h:2200
#define CSIDL_CONNECTIONS
Definition: shlobj.h:2214
#define CSIDL_COMMON_PROGRAMS
Definition: shlobj.h:2188
#define PCS_PATHTOOLONG
Definition: shlobj.h:370
#define CSIDL_FLAG_DONT_VERIFY
Definition: shlobj.h:2227
#define CSIDL_MYPICTURES
Definition: shlobj.h:2204
#define CSIDL_COOKIES
Definition: shlobj.h:2198
#define CSIDL_COMMON_FAVORITES
Definition: shlobj.h:2196
#define CSIDL_PRINTERS
Definition: shlobj.h:2170
#define CSIDL_HISTORY
Definition: shlobj.h:2199
#define CSIDL_LOCAL_APPDATA
Definition: shlobj.h:2193
#define CSIDL_PROGRAM_FILES_COMMONX86
Definition: shlobj.h:2209
#define CSIDL_PROGRAM_FILES_COMMON
Definition: shlobj.h:2208
#define CSIDL_COMMON_MUSIC
Definition: shlobj.h:2215
#define PCS_FATAL
Definition: shlobj.h:366
#define CSIDL_COMMON_VIDEO
Definition: shlobj.h:2217
#define CSIDL_FOLDER_MASK
Definition: shlobj.h:2224
#define CSIDL_DESKTOP
Definition: shlobj.h:2166
#define CSIDL_NETWORK
Definition: shlobj.h:2183
#define CSIDL_STARTMENU
Definition: shlobj.h:2177
#define CSIDL_PROGRAM_FILESX86
Definition: shlobj.h:2207
#define CSIDL_COMMON_PICTURES
Definition: shlobj.h:2216
#define CSIDL_PROGRAMS
Definition: shlobj.h:2168
#define CSIDL_COMMON_STARTUP
Definition: shlobj.h:2189
#define CSIDL_APPDATA
Definition: shlobj.h:2191
#define CSIDL_PRINTHOOD
Definition: shlobj.h:2192
#define CSIDL_STARTUP
Definition: shlobj.h:2173
#define CSIDL_DRIVES
Definition: shlobj.h:2182
#define CSIDL_MYMUSIC
Definition: shlobj.h:2179
#define CSIDL_INTERNET
Definition: shlobj.h:2167
#define CSIDL_COMMON_DOCUMENTS
Definition: shlobj.h:2211
#define CSIDL_CONTROLS
Definition: shlobj.h:2169
#define CSIDL_BITBUCKET
Definition: shlobj.h:2176
#define CSIDL_NETHOOD
Definition: shlobj.h:2184
#define CSIDL_COMMON_ADMINTOOLS
Definition: shlobj.h:2212
#define CSIDL_MYVIDEO
Definition: shlobj.h:2180
_In_ int nFolder
Definition: shlobj.h:1518
#define GCT_SEPARATOR
Definition: shlwapi.h:779
#define GCT_INVALID
Definition: shlwapi.h:775
#define GCT_WILD
Definition: shlwapi.h:778
#define WHICH_DEFAULT
#define IDS_RECENT
Definition: shresdef.h:90
#define IDS_NETHOOD
Definition: shresdef.h:96
#define IDI_SHELL_MY_DOCUMENTS
Definition: shresdef.h:685
#define IDS_MYVIDEO
Definition: shresdef.h:94
#define IDI_SHELL_MY_MUSIC
Definition: shresdef.h:687
#define IDS_COOKIES
Definition: shresdef.h:102
#define IDI_SHELL_MY_PICTURES
Definition: shresdef.h:686
#define IDI_SHELL_TSKBAR_STARTMENU
Definition: shresdef.h:595
#define IDS_MYMUSIC
Definition: shresdef.h:93
#define IDI_SHELL_COMPUTER_FOLDER
Definition: shresdef.h:598
#define IDI_SHELL_DESKTOP
Definition: shresdef.h:590
#define IDI_SHELL_FAVORITES
Definition: shresdef.h:599
#define IDS_INTERNET_CACHE
Definition: shresdef.h:101
#define IDS_STARTUP
Definition: shresdef.h:89
#define IDS_COMMON_VIDEO
Definition: shresdef.h:111
#define IDI_SHELL_MY_MOVIES
Definition: shresdef.h:688
#define IDI_SHELL_PROGRAMS_FOLDER
Definition: shresdef.h:575
#define IDI_SHELL_RECENT_DOCUMENTS
Definition: shresdef.h:576
#define IDI_SHELL_NETWORK
Definition: shresdef.h:570
#define IDS_APPDATA
Definition: shresdef.h:98
#define IDI_SHELL_PRINTERS_FOLDER
Definition: shresdef.h:593
#define IDS_TEMPLATES
Definition: shresdef.h:97
#define IDS_COMMON_PICTURES
Definition: shresdef.h:110
#define IDS_PROGRAM_FILES_COMMON
Definition: shresdef.h:106
#define IDS_DESKTOPDIRECTORY
Definition: shresdef.h:95
#define IDS_PRINTHOOD
Definition: shresdef.h:99
#define IDS_SENDTO
Definition: shresdef.h:91
#define IDI_SHELL_NETWORK_CONNECTIONS
Definition: shresdef.h:644
#define IDI_SHELL_FONTS_FOLDER
Definition: shresdef.h:594
#define IDS_COMMON_MUSIC
Definition: shresdef.h:109
#define IDS_ADMINTOOLS
Definition: shresdef.h:108
#define IDS_MYPICTURES
Definition: shresdef.h:105
#define IDI_SHELL_CONTROL_PANEL
Definition: shresdef.h:577
#define IDS_STARTMENU
Definition: shresdef.h:92
#define IDS_PROGRAM_FILES
Definition: shresdef.h:104
#define IDS_HISTORY
Definition: shresdef.h:103
#define IDS_LOCAL_APPDATA
Definition: shresdef.h:100
#define IDI_SHELL_SYSTEM_GEAR
Definition: shresdef.h:724
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
INT nShell32IconIndex
Definition: shellpath.c:1071
CSIDL_Type type
Definition: shellpath.c:1068
LPCWSTR szDefaultPath
Definition: shellpath.c:1070
LPCWSTR szValueName
Definition: shellpath.c:1069
const KNOWNFOLDERID * id
Definition: shellpath.c:1067
SID_AND_ATTRIBUTES User
Definition: setypes.h:1010
Definition: fci.c:127
Definition: fci.c:116
Definition: copy.c:22
#define max(a, b)
Definition: svc.c:63
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
unsigned char * LPBYTE
Definition: typedefs.h:53
PVOID HANDLE
Definition: typedefs.h:73
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
Definition: pdh_main.c:94
DWORD dwAttributes
Definition: vdmdbg.h:34
int ret
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define DRIVE_REMOVABLE
Definition: winbase.h:251
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
CONST void * LPCVOID
Definition: windef.h:191
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_NOT_SUFFICIENT_BUFFER
Definition: winerror.h:2345
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define HKEY_USERS
Definition: winreg.h:13
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
LPWSTR WINAPI CharPrevW(_In_ LPCWSTR, _In_ LPCWSTR)
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
static const WCHAR userName[]
Definition: wnet.c:2156
struct _TOKEN_USER * PTOKEN_USER
#define TOKEN_QUERY
Definition: setypes.h:928
@ TokenUser
Definition: setypes.h:966
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193