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