* The Shell.. for a long time we dreamed of having a compatible, properly working...
[reactos.git] / reactos / dll / win32 / shell32 / wine / shellpath.c
similarity index 51%
rename from reactos/dll/win32/shell32/shellpath.cpp
rename to reactos/dll/win32/shell32/wine/shellpath.c
index 7d2c2f0..7e3f506 100644 (file)
  *
  */
 
-#include "precomp.h"
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COBJMACROS
 
+#include <wine/config.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include <shlobj.h>
+#include <undocshell.h>
+#include <shlwapi.h>
 #include <sddl.h>
+#include <wine/debug.h>
+#include <wine/unicode.h>
+
+#include <userenv.h>
+
+#include "pidl.h"
+#include "shell32_main.h"
+#include "shresdef.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
+static const BOOL is_win64 = sizeof(void *) > sizeof(int);
+
+typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+
+static LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
+
+BOOL IsWow64()
+{
+    BOOL bIsWow64 = FALSE;
+
+    if (!fnIsWow64Process)
+    {
+        fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
+            GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
+    }
+
+    if (!fnIsWow64Process)
+        return FALSE;
+
+    if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
+        return FALSE;
+
+    return bIsWow64;
+}
+
+
 /*
-    ########## Combining and Constructing paths ##########
+       ########## Combining and Constructing paths ##########
 */
 
 /*************************************************************************
- * PathAppend        [SHELL32.36]
+ * PathAppend          [SHELL32.36]
  */
 BOOL WINAPI PathAppendAW(
-    LPVOID lpszPath1,
-    LPCVOID lpszPath2)
+       LPVOID lpszPath1,
+       LPCVOID lpszPath2)
 {
-    if (SHELL_OsIsUnicode())
-      return PathAppendW((LPWSTR)lpszPath1, (LPCWSTR)lpszPath2);
-    return PathAppendA((LPSTR)lpszPath1, (LPCSTR)lpszPath2);
+       if (SHELL_OsIsUnicode())
+         return PathAppendW(lpszPath1, lpszPath2);
+       return PathAppendA(lpszPath1, lpszPath2);
 }
 
 /*************************************************************************
- * PathBuildRoot        [SHELL32.30]
+ * PathBuildRoot               [SHELL32.30]
  */
 LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive)
 {
-    if(SHELL_OsIsUnicode())
-      return PathBuildRootW((LPWSTR)lpszPath, drive);
-    return PathBuildRootA((LPSTR)lpszPath, drive);
+       if(SHELL_OsIsUnicode())
+         return PathBuildRootW(lpszPath, drive);
+       return PathBuildRootA(lpszPath, drive);
 }
 
 /*************************************************************************
- * PathGetExtensionA        [internal]
+ * PathGetExtensionA           [internal]
  *
  * NOTES
  *  exported by ordinal
@@ -65,21 +108,21 @@ LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive)
  */
 static LPSTR PathGetExtensionA(LPCSTR lpszPath)
 {
-    TRACE("(%s)\n",lpszPath);
+       TRACE("(%s)\n",lpszPath);
 
-    lpszPath = PathFindExtensionA(lpszPath);
-    return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
+       lpszPath = PathFindExtensionA(lpszPath);
+       return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
 }
 
 /*************************************************************************
- * PathGetExtensionW        [internal]
+ * PathGetExtensionW           [internal]
  */
 static LPWSTR PathGetExtensionW(LPCWSTR lpszPath)
 {
-    TRACE("(%s)\n",debugstr_w(lpszPath));
+       TRACE("(%s)\n",debugstr_w(lpszPath));
 
-    lpszPath = PathFindExtensionW(lpszPath);
-    return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
+       lpszPath = PathFindExtensionW(lpszPath);
+       return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
 }
 
 /*************************************************************************
@@ -95,13 +138,13 @@ EXTERN_C LPVOID WINAPI SHPathGetExtensionW(LPCWSTR lpszPath, DWORD void1, DWORD
  */
 BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath)
 {
-    if (SHELL_OsIsUnicode())
-      return PathRemoveFileSpecW((LPWSTR)lpszPath);
-    return PathRemoveFileSpecA((LPSTR)lpszPath);
+       if (SHELL_OsIsUnicode())
+         return PathRemoveFileSpecW(lpszPath);
+       return PathRemoveFileSpecA(lpszPath);
 }
 
 /*
-    Path Manipulations
+       Path Manipulations
 */
 
 /*************************************************************************
@@ -109,14 +152,14 @@ BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath)
  */
 static void PathGetShortPathA(LPSTR pszPath)
 {
-    CHAR path[MAX_PATH];
+       CHAR path[MAX_PATH];
 
-    TRACE("%s\n", pszPath);
+       TRACE("%s\n", pszPath);
 
-    if (GetShortPathNameA(pszPath, path, MAX_PATH))
-    {
-      lstrcpyA(pszPath, path);
-    }
+       if (GetShortPathNameA(pszPath, path, MAX_PATH))
+       {
+         lstrcpyA(pszPath, path);
+       }
 }
 
 /*************************************************************************
@@ -124,216 +167,231 @@ static void PathGetShortPathA(LPSTR pszPath)
  */
 static void PathGetShortPathW(LPWSTR pszPath)
 {
-    WCHAR path[MAX_PATH];
+       WCHAR path[MAX_PATH];
 
-    TRACE("%s\n", debugstr_w(pszPath));
+       TRACE("%s\n", debugstr_w(pszPath));
 
-    if (GetShortPathNameW(pszPath, path, MAX_PATH))
-    {
-      wcscpy(pszPath, path);
-    }
+       if (GetShortPathNameW(pszPath, path, MAX_PATH))
+       {
+         lstrcpyW(pszPath, path);
+       }
 }
 
 /*************************************************************************
  * PathGetShortPath [SHELL32.92]
  */
-EXTERN_C VOID WINAPI PathGetShortPathAW(LPVOID pszPath)
+VOID WINAPI PathGetShortPathAW(LPVOID pszPath)
 {
-    if(SHELL_OsIsUnicode())
-      PathGetShortPathW((LPWSTR)pszPath);
-    PathGetShortPathA((LPSTR)pszPath);
+       if(SHELL_OsIsUnicode())
+         PathGetShortPathW(pszPath);
+       PathGetShortPathA(pszPath);
 }
 
 /*
-    ########## Path Testing ##########
+       ########## Path Testing ##########
 */
 
 /*************************************************************************
- * PathIsRoot        [SHELL32.29]
+ * PathIsRoot          [SHELL32.29]
  */
 BOOL WINAPI PathIsRootAW(LPCVOID lpszPath)
 {
-    if (SHELL_OsIsUnicode())
-      return PathIsRootW((LPWSTR)lpszPath);
-    return PathIsRootA((LPSTR)lpszPath);
+       if (SHELL_OsIsUnicode())
+         return PathIsRootW(lpszPath);
+       return PathIsRootA(lpszPath);
 }
 
 /*************************************************************************
- *  PathIsExeA        [internal]
+ *  PathIsExeA         [internal]
  */
 static BOOL PathIsExeA (LPCSTR lpszPath)
 {
-    LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
+       LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
         int i;
         static const char * const lpszExtensions[] =
             {"exe", "com", "pif", "cmd", "bat", "scf", "scr", NULL };
 
-    TRACE("path=%s\n",lpszPath);
+       TRACE("path=%s\n",lpszPath);
 
-    for(i=0; lpszExtensions[i]; i++)
-      if (!lstrcmpiA(lpszExtension,lpszExtensions[i])) return TRUE;
+       for(i=0; lpszExtensions[i]; i++)
+         if (!lstrcmpiA(lpszExtension,lpszExtensions[i])) return TRUE;
 
-    return FALSE;
+       return FALSE;
 }
 
 /*************************************************************************
- *  PathIsExeW        [internal]
+ *  PathIsExeW         [internal]
  */
 BOOL PathIsExeW (LPCWSTR lpszPath)
 {
-    LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
+       LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
         int i;
         static const WCHAR lpszExtensions[][4] =
             {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','f','\0'},
              {'c','m','d','\0'}, {'b','a','t','\0'}, {'s','c','f','\0'},
              {'s','c','r','\0'}, {'\0'} };
 
-    TRACE("path=%s\n",debugstr_w(lpszPath));
+       TRACE("path=%s\n",debugstr_w(lpszPath));
 
-    for(i=0; lpszExtensions[i][0]; i++)
-      if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE;
+       for(i=0; lpszExtensions[i][0]; i++)
+         if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE;
 
-    return FALSE;
+       return FALSE;
 }
 
 /*************************************************************************
- *  PathIsExe        [SHELL32.43]
+ *  PathIsExe          [SHELL32.43]
  */
 BOOL WINAPI PathIsExeAW (LPCVOID path)
 {
-    if (SHELL_OsIsUnicode())
-      return PathIsExeW ((LPWSTR)path);
-    return PathIsExeA((LPSTR)path);
+       if (SHELL_OsIsUnicode())
+         return PathIsExeW (path);
+       return PathIsExeA(path);
 }
 
 /*************************************************************************
- * PathFileExists    [SHELL32.45]
+ * PathFileExists      [SHELL32.45]
  */
 BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath)
 {
-    if (SHELL_OsIsUnicode())
-      return PathFileExistsW ((LPWSTR)lpszPath);
-    return PathFileExistsA ((LPSTR)lpszPath);
+       if (SHELL_OsIsUnicode())
+         return PathFileExistsW (lpszPath);
+       return PathFileExistsA (lpszPath);
 }
 
 /*************************************************************************
- * PathIsSameRoot    [SHELL32.650]
+ * PathIsSameRoot      [SHELL32.650]
  */
 BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2)
 {
-    if (SHELL_OsIsUnicode())
-      return PathIsSameRootW((LPCWSTR)lpszPath1, (LPCWSTR)lpszPath2);
-    return PathIsSameRootA((LPCSTR)lpszPath1, (LPCSTR)lpszPath2);
+       if (SHELL_OsIsUnicode())
+         return PathIsSameRootW(lpszPath1, lpszPath2);
+       return PathIsSameRootA(lpszPath1, lpszPath2);
 }
 
 /*************************************************************************
- * IsLFNDriveA        [SHELL32.41]
+ * IsLFNDriveA         [SHELL32.41]
  */
-EXTERN_C BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath)
+BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath)
 {
-    DWORD    fnlen;
+    DWORD      fnlen;
 
     if (!GetVolumeInformationA(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
-    return FALSE;
+       return FALSE;
     return fnlen > 12;
 }
 
 /*************************************************************************
- * IsLFNDriveW        [SHELL32.42]
+ * IsLFNDriveW         [SHELL32.42]
  */
-EXTERN_C BOOL WINAPI IsLFNDriveW(LPCWSTR lpszPath)
+BOOL WINAPI IsLFNDriveW(LPCWSTR lpszPath)
 {
-    DWORD    fnlen;
+    DWORD      fnlen;
 
     if (!GetVolumeInformationW(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
-    return FALSE;
+       return FALSE;
     return fnlen > 12;
 }
 
 /*************************************************************************
- * IsLFNDrive        [SHELL32.119]
+ * IsLFNDrive          [SHELL32.119]
  */
-EXTERN_C BOOL WINAPI IsLFNDriveAW(LPCVOID lpszPath)
+BOOL WINAPI IsLFNDriveAW(LPCVOID lpszPath)
 {
-    if (SHELL_OsIsUnicode())
-      return IsLFNDriveW((LPCWSTR)lpszPath);
-    return IsLFNDriveA((LPCSTR)lpszPath);
+       if (SHELL_OsIsUnicode())
+         return IsLFNDriveW(lpszPath);
+       return IsLFNDriveA(lpszPath);
 }
 
 /*
-    ########## Creating Something Unique ##########
+       ########## Creating Something Unique ##########
 */
 /*************************************************************************
- * PathMakeUniqueNameA    [internal]
+ * PathMakeUniqueNameA [internal]
  */
 static BOOL PathMakeUniqueNameA(
-    LPSTR lpszBuffer,
-    DWORD dwBuffSize,
-    LPCSTR lpszShortName,
-    LPCSTR lpszLongName,
-    LPCSTR lpszPathName)
+       LPSTR lpszBuffer,
+       DWORD dwBuffSize,
+       LPCSTR lpszShortName,
+       LPCSTR lpszLongName,
+       LPCSTR lpszPathName)
 {
-    FIXME("%p %u %s %s %s stub\n",
-     lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
-     debugstr_a(lpszLongName), debugstr_a(lpszPathName));
-    return TRUE;
+       FIXME("%p %u %s %s %s stub\n",
+        lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
+        debugstr_a(lpszLongName), debugstr_a(lpszPathName));
+       return TRUE;
 }
 
 /*************************************************************************
- * PathMakeUniqueNameW    [internal]
+ * PathMakeUniqueNameW [internal]
  */
 static BOOL PathMakeUniqueNameW(
-    LPWSTR lpszBuffer,
-    DWORD dwBuffSize,
-    LPCWSTR lpszShortName,
-    LPCWSTR lpszLongName,
-    LPCWSTR lpszPathName)
+       LPWSTR lpszBuffer,
+       DWORD dwBuffSize,
+       LPCWSTR lpszShortName,
+       LPCWSTR lpszLongName,
+       LPCWSTR lpszPathName)
 {
-    FIXME("%p %u %s %s %s stub\n",
-     lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
-     debugstr_w(lpszLongName), debugstr_w(lpszPathName));
-    return TRUE;
+       FIXME("%p %u %s %s %s stub\n",
+        lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
+        debugstr_w(lpszLongName), debugstr_w(lpszPathName));
+       return TRUE;
 }
 
 /*************************************************************************
- * PathMakeUniqueName    [SHELL32.47]
+ * PathMakeUniqueName  [SHELL32.47]
  */
 BOOL WINAPI PathMakeUniqueNameAW(
-    LPVOID lpszBuffer,
-    DWORD dwBuffSize,
-    LPCVOID lpszShortName,
-    LPCVOID lpszLongName,
-    LPCVOID lpszPathName)
+       LPVOID lpszBuffer,
+       DWORD dwBuffSize,
+       LPCVOID lpszShortName,
+       LPCVOID lpszLongName,
+       LPCVOID lpszPathName)
 {
-    if (SHELL_OsIsUnicode())
-      return PathMakeUniqueNameW((LPWSTR)lpszBuffer, dwBuffSize, (LPCWSTR)lpszShortName, (LPCWSTR)lpszLongName, (LPCWSTR)lpszPathName);
-    return PathMakeUniqueNameA((LPSTR)lpszBuffer, dwBuffSize, (LPCSTR)lpszShortName, (LPCSTR)lpszLongName, (LPCSTR)lpszPathName);
+       if (SHELL_OsIsUnicode())
+         return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
+       return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
 }
 
 /*************************************************************************
  * PathYetAnotherMakeUniqueName [SHELL32.75]
- *
- * NOTES
- *     exported by ordinal
  */
-BOOL WINAPI PathYetAnotherMakeUniqueName(
-    LPWSTR lpszBuffer,
-    LPCWSTR lpszPathName,
-    LPCWSTR lpszShortName,
-    LPCWSTR lpszLongName)
+BOOL WINAPI PathYetAnotherMakeUniqueName(LPWSTR buffer, LPCWSTR path, LPCWSTR shortname, LPCWSTR longname)
 {
-    FIXME("(%p, %s, %s ,%s):stub.\n",
-          lpszBuffer, debugstr_w(lpszPathName), debugstr_w(lpszShortName), debugstr_w(lpszLongName));
+    WCHAR pathW[MAX_PATH], retW[MAX_PATH];
+    const WCHAR *file, *ext;
+    int i = 2;
+
+    TRACE("(%p, %s, %s, %s)\n", buffer, debugstr_w(path), debugstr_w(shortname), debugstr_w(longname));
+
+    file = longname ? longname : shortname;
+    PathCombineW(pathW, path, file);
+    strcpyW(retW, pathW);
+    PathRemoveExtensionW(pathW);
+
+    ext = PathFindExtensionW(file);
+
+    /* now try to make it unique */
+    while (PathFileExistsW(retW))
+    {
+        static const WCHAR fmtW[] = {'%','s',' ','(','%','d',')','%','s',0};
+
+        sprintfW(retW, fmtW, pathW, i, ext);
+        i++;
+    }
+
+    strcpyW(buffer, retW);
+    TRACE("ret - %s\n", debugstr_w(buffer));
+
     return TRUE;
 }
 
-
 /*
-    ########## cleaning and resolving paths ##########
+       ########## cleaning and resolving paths ##########
  */
 
 /*************************************************************************
- * PathCleanupSpec    [SHELL32.171]
+ * PathCleanupSpec     [SHELL32.171]
  *
  * lpszFile is changed in place.
  */
@@ -350,7 +408,7 @@ int WINAPI PathCleanupSpec( LPCWSTR lpszPathW, LPWSTR lpszFileW )
         TRACE("Cleanup %s\n",debugstr_w(lpszFileW));
 
         if (lpszPathW)
-            length = wcslen(lpszPathW);
+            length = strlenW(lpszPathW);
 
         while (*p)
         {
@@ -407,132 +465,120 @@ int WINAPI PathCleanupSpec( LPCWSTR lpszPathW, LPWSTR lpszFileW )
 }
 
 /*************************************************************************
- * PathQualifyA        [SHELL32]
+ * PathQualifyA                [SHELL32]
  */
 static BOOL PathQualifyA(LPCSTR pszPath)
 {
-    FIXME("%s\n",pszPath);
-    return 0;
+       FIXME("%s\n",pszPath);
+       return FALSE;
 }
 
 /*************************************************************************
- * PathQualifyW        [SHELL32]
+ * PathQualifyW                [SHELL32]
  */
 static BOOL PathQualifyW(LPCWSTR pszPath)
 {
-    FIXME("%s\n",debugstr_w(pszPath));
-    return 0;
+       FIXME("%s\n",debugstr_w(pszPath));
+       return FALSE;
 }
 
 /*************************************************************************
- * PathQualify    [SHELL32.49]
+ * PathQualify [SHELL32.49]
  */
 BOOL WINAPI PathQualifyAW(LPCVOID pszPath)
 {
-    if (SHELL_OsIsUnicode())
-      return PathQualifyW((LPCWSTR)pszPath);
-    return PathQualifyA((LPCSTR)pszPath);
+       if (SHELL_OsIsUnicode())
+         return PathQualifyW(pszPath);
+       return PathQualifyA(pszPath);
 }
 
-/*************************************************************************
- * PathResolveA [SHELL32.51]
- */
-static BOOL PathResolveA(
-    LPSTR lpszPath,
-    LPCSTR *alpszPaths,
-    DWORD dwFlags)
+static BOOL PathResolveA(LPSTR path, LPCSTR *paths, DWORD flags)
 {
-    FIXME("(%s,%p,0x%08x),stub!\n",
-      lpszPath, *alpszPaths, dwFlags);
-    return 0;
+    FIXME("(%s,%p,0x%08x),stub!\n", debugstr_a(path), paths, flags);
+    return FALSE;
 }
 
-/*************************************************************************
- * PathResolveW [SHELL32]
- */
-static BOOL PathResolveW(
-    LPWSTR lpszPath,
-    LPCWSTR *alpszPaths,
-    DWORD dwFlags)
+static BOOL PathResolveW(LPWSTR path, LPCWSTR *paths, DWORD flags)
 {
-    FIXME("(%s,%p,0x%08x),stub!\n",
-      debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
-    return 0;
+    FIXME("(%s,%p,0x%08x),stub!\n", debugstr_w(path), paths, flags);
+    return FALSE;
 }
 
 /*************************************************************************
  * PathResolve [SHELL32.51]
  */
-BOOL WINAPI PathResolveAW(
-    LPVOID lpszPath,
-    LPCVOID *alpszPaths,
-    DWORD dwFlags)
+BOOL WINAPI PathResolveAW(LPVOID path, LPCVOID *paths, DWORD flags)
 {
     if (SHELL_OsIsUnicode())
-      return PathResolveW((LPWSTR)lpszPath, (LPCWSTR *)alpszPaths, dwFlags);
-    return PathResolveA((LPSTR)lpszPath, (LPCSTR *)alpszPaths, dwFlags);
+        return PathResolveW(path, (LPCWSTR*)paths, flags);
+    else
+        return PathResolveA(path, (LPCSTR*)paths, flags);
 }
 
 /*************************************************************************
-*    PathProcessCommandA    [SHELL32.653]
+*      PathProcessCommandA
 */
 static LONG PathProcessCommandA (
-    LPCSTR lpszPath,
-    LPSTR lpszBuff,
-    DWORD dwBuffSize,
-    DWORD dwFlags)
+       LPCSTR lpszPath,
+       LPSTR lpszBuff,
+       DWORD dwBuffSize,
+       DWORD dwFlags)
 {
-    FIXME("%s %p 0x%04x 0x%04x stub\n",
-    lpszPath, lpszBuff, dwBuffSize, dwFlags);
-    if(!lpszPath) return -1;
-    if(lpszBuff) strcpy(lpszBuff, lpszPath);
-    return strlen(lpszPath);
+       FIXME("%s %p 0x%04x 0x%04x stub\n",
+       lpszPath, lpszBuff, dwBuffSize, dwFlags);
+       if(!lpszPath) return -1;
+       if(lpszBuff) strcpy(lpszBuff, lpszPath);
+       return strlen(lpszPath);
 }
 
 /*************************************************************************
-*    PathProcessCommandW
+*      PathProcessCommandW
 */
 static LONG PathProcessCommandW (
-    LPCWSTR lpszPath,
-    LPWSTR lpszBuff,
-    DWORD dwBuffSize,
-    DWORD dwFlags)
+       LPCWSTR lpszPath,
+       LPWSTR lpszBuff,
+       DWORD dwBuffSize,
+       DWORD dwFlags)
 {
-    FIXME("(%s, %p, 0x%04x, 0x%04x) stub\n",
-    debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
-    if(!lpszPath) return -1;
-    if(lpszBuff) wcscpy(lpszBuff, lpszPath);
-    return wcslen(lpszPath);
+       FIXME("(%s, %p, 0x%04x, 0x%04x) stub\n",
+       debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
+       if(!lpszPath) return -1;
+       if(lpszBuff) strcpyW(lpszBuff, lpszPath);
+       return strlenW(lpszPath);
 }
 
 /*************************************************************************
-*    PathProcessCommand (SHELL32.653)
+*      PathProcessCommand (SHELL32.653)
 */
 LONG WINAPI PathProcessCommandAW (
-    LPCVOID lpszPath,
-    LPVOID lpszBuff,
-    DWORD dwBuffSize,
-    DWORD dwFlags)
+       LPCVOID lpszPath,
+       LPVOID lpszBuff,
+       DWORD dwBuffSize,
+       DWORD dwFlags)
 {
-    if (SHELL_OsIsUnicode())
-      return PathProcessCommandW((LPCWSTR)lpszPath, (LPWSTR)lpszBuff, dwBuffSize, dwFlags);
-    return PathProcessCommandA((LPCSTR)lpszPath, (LPSTR)lpszBuff, dwBuffSize, dwFlags);
+       if (SHELL_OsIsUnicode())
+         return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags);
+       return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags);
 }
 
 /*
-    ########## special ##########
+       ########## special ##########
 */
 
 static const WCHAR szCurrentVersion[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0'};
 static const WCHAR Administrative_ToolsW[] = {'A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'};
 static const WCHAR AppDataW[] = {'A','p','p','D','a','t','a','\0'};
+static const WCHAR AppData_LocalLowW[] = {'A','p','p','D','a','t','a','\\','L','o','c','a','l','L','o','w','\0'};
+static const WCHAR Application_DataW[] = {'A','p','p','l','i','c','a','t','i','o','n',' ','D','a','t','a','\0'};
 static const WCHAR CacheW[] = {'C','a','c','h','e','\0'};
 static const WCHAR CD_BurningW[] = {'C','D',' ','B','u','r','n','i','n','g','\0'};
 static const WCHAR Common_Administrative_ToolsW[] = {'C','o','m','m','o','n',' ','A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'};
 static const WCHAR Common_AppDataW[] = {'C','o','m','m','o','n',' ','A','p','p','D','a','t','a','\0'};
 static const WCHAR Common_DesktopW[] = {'C','o','m','m','o','n',' ','D','e','s','k','t','o','p','\0'};
 static const WCHAR Common_DocumentsW[] = {'C','o','m','m','o','n',' ','D','o','c','u','m','e','n','t','s','\0'};
+static const WCHAR Common_FavoritesW[] = {'C','o','m','m','o','n',' ','F','a','v','o','r','i','t','e','s','\0'};
 static const WCHAR CommonFilesDirW[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r','\0'};
+static const WCHAR CommonFilesDirX86W[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r',' ','(','x','8','6',')','\0'};
 static const WCHAR CommonMusicW[] = {'C','o','m','m','o','n','M','u','s','i','c','\0'};
 static const WCHAR CommonPicturesW[] = {'C','o','m','m','o','n','P','i','c','t','u','r','e','s','\0'};
 static const WCHAR Common_ProgramsW[] = {'C','o','m','m','o','n',' ','P','r','o','g','r','a','m','s','\0'};
@@ -540,44 +586,73 @@ static const WCHAR Common_StartUpW[] = {'C','o','m','m','o','n',' ','S','t','a',
 static const WCHAR Common_Start_MenuW[] = {'C','o','m','m','o','n',' ','S','t','a','r','t',' ','M','e','n','u','\0'};
 static const WCHAR Common_TemplatesW[] = {'C','o','m','m','o','n',' ','T','e','m','p','l','a','t','e','s','\0'};
 static const WCHAR CommonVideoW[] = {'C','o','m','m','o','n','V','i','d','e','o','\0'};
+static const WCHAR ContactsW[] = {'C','o','n','t','a','c','t','s','\0'};
 static const WCHAR CookiesW[] = {'C','o','o','k','i','e','s','\0'};
 static const WCHAR DesktopW[] = {'D','e','s','k','t','o','p','\0'};
+static const WCHAR DocumentsW[] = {'D','o','c','u','m','e','n','t','s','\0'};
+static const WCHAR DownloadsW[] = {'D','o','w','n','l','o','a','d','s','\0'};
 static const WCHAR FavoritesW[] = {'F','a','v','o','r','i','t','e','s','\0'};
 static const WCHAR FontsW[] = {'F','o','n','t','s','\0'};
 static const WCHAR HistoryW[] = {'H','i','s','t','o','r','y','\0'};
+static const WCHAR LinksW[] = {'L','i','n','k','s','\0'};
 static const WCHAR Local_AppDataW[] = {'L','o','c','a','l',' ','A','p','p','D','a','t','a','\0'};
+static const WCHAR Local_Settings_Application_DataW[] = {'L','o','c','a','l',' ','S','e','t','t','i','n','g','s','\\','A','p','p','l','i','c','a','t','i','o','n',' ','D','a','t','a','\0'};
+static const WCHAR Local_Settings_CD_BurningW[] = {'L','o','c','a','l',' ','S','e','t','t','i','n','g','s','\\','A','p','p','l','i','c','a','t','i','o','n',' ','D','a','t','a','\\','M','i','c','r','o','s','o','f','t','\\','C','D',' ','B','u','r','n','i','n','g','\0'};
+static const WCHAR Local_Settings_HistoryW[] = {'L','o','c','a','l',' ','S','e','t','t','i','n','g','s','\\','H','i','s','t','o','r','y','\0'};
+static const WCHAR Local_Settings_Temporary_Internet_FilesW[] = {'L','o','c','a','l',' ','S','e','t','t','i','n','g','s','\\','T','e','m','p','o','r','a','r','y',' ','I','n','t','e','r','n','e','t',' ','F','i','l','e','s','\0'};
+static const WCHAR Microsoft_Windows_GameExplorerW[] = {'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','G','a','m','e','E','x','p','l','o','r','e','r','\0'};
+static const WCHAR Microsoft_Windows_LibrariesW[] = {'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','L','i','b','r','a','r','i','e','s','\0'};
+static const WCHAR Microsoft_Windows_RingtonesW[] = {'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','R','i','n','g','t','o','n','e','s','\0'};
+static const WCHAR MusicW[] = {'M','u','s','i','c','\0'};
+static const WCHAR Music_PlaylistsW[] = {'M','u','s','i','c','\\','P','l','a','y','l','i','s','t','s','\0'};
+static const WCHAR Music_Sample_MusicW[] = {'M','u','s','i','c','\\','S','a','m','p','l','e',' ','M','u','s','i','c','\0'};
+static const WCHAR Music_Sample_PlaylistsW[] = {'M','u','s','i','c','\\','S','a','m','p','l','e',' ','P','l','a','y','l','i','s','t','s','\0'};
+static const WCHAR My_DocumentsW[] = {'M','y',' ','D','o','c','u','m','e','n','t','s','\0'};
 static const WCHAR My_MusicW[] = {'M','y',' ','M','u','s','i','c','\0'};
 static const WCHAR My_PicturesW[] = {'M','y',' ','P','i','c','t','u','r','e','s','\0'};
 static const WCHAR My_VideoW[] = {'M','y',' ','V','i','d','e','o','\0'};
 static const WCHAR NetHoodW[] = {'N','e','t','H','o','o','d','\0'};
+static const WCHAR OEM_LinksW[] = {'O','E','M',' ','L','i','n','k','s','\0'};
 static const WCHAR PersonalW[] = {'P','e','r','s','o','n','a','l','\0'};
+static const WCHAR PicturesW[] = {'P','i','c','t','u','r','e','s','\0'};
+static const WCHAR Pictures_Sample_PicturesW[] = {'P','i','c','t','u','r','e','s','\\','S','a','m','p','l','e',' ','P','i','c','t','u','r','e','s','\0'};
+static const WCHAR Pictures_Slide_ShowsW[] = {'P','i','c','t','u','r','e','s','\\','S','l','i','d','e',' ','S','h','o','w','s','\0'};
 static const WCHAR PrintHoodW[] = {'P','r','i','n','t','H','o','o','d','\0'};
+static const WCHAR Program_FilesW[] = {'P','r','o','g','r','a','m',' ','F','i','l','e','s','\0'};
+static const WCHAR Program_Files_Common_FilesW[] = {'P','r','o','g','r','a','m',' ','F','i','l','e','s','\\','C','o','m','m','o','n',' ','F','i','l','e','s','\0'};
+static const WCHAR Program_Files_x86W[] = {'P','r','o','g','r','a','m',' ','F','i','l','e','s',' ','(','x','8','6',')','\0'};
+static const WCHAR Program_Files_x86_Common_FilesW[] = {'P','r','o','g','r','a','m',' ','F','i','l','e','s',' ','(','x','8','6',')','\\','C','o','m','m','o','n',' ','F','i','l','e','s','\0'};
 static const WCHAR ProgramFilesDirW[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r','\0'};
+static const WCHAR ProgramFilesDirX86W[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r',' ','(','x','8','6',')','\0'};
 static const WCHAR ProgramsW[] = {'P','r','o','g','r','a','m','s','\0'};
 static const WCHAR RecentW[] = {'R','e','c','e','n','t','\0'};
 static const WCHAR ResourcesW[] = {'R','e','s','o','u','r','c','e','s','\0'};
+static const WCHAR Saved_GamesW[] = {'S','a','v','e','d',' ','G','a','m','e','s','\0'};
+static const WCHAR SearchesW[] = {'S','e','a','r','c','h','e','s','\0'};
 static const WCHAR SendToW[] = {'S','e','n','d','T','o','\0'};
 static const WCHAR StartUpW[] = {'S','t','a','r','t','U','p','\0'};
 static const WCHAR Start_MenuW[] = {'S','t','a','r','t',' ','M','e','n','u','\0'};
+static const WCHAR Start_Menu_ProgramsW[] = {'S','t','a','r','t',' ','M','e','n','u','\\','P','r','o','g','r','a','m','s','\0'};
+static const WCHAR Start_Menu_Admin_ToolsW[] = {'S','t','a','r','t',' ','M','e','n','u','\\','P','r','o','g','r','a','m','s','\\','A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'};
+static const WCHAR Start_Menu_StartupW[] = {'S','t','a','r','t',' ','M','e','n','u','\\','P','r','o','g','r','a','m','s','\\','S','t','a','r','t','U','p','\0'};
 static const WCHAR TemplatesW[] = {'T','e','m','p','l','a','t','e','s','\0'};
+static const WCHAR UsersW[] = {'U','s','e','r','s','\0'};
+static const WCHAR UsersPublicW[] = {'U','s','e','r','s','\\','P','u','b','l','i','c','\0'};
+static const WCHAR VideosW[] = {'V','i','d','e','o','s','\0'};
+static const WCHAR Videos_Sample_VideosW[] = {'V','i','d','e','o','s','\\','S','a','m','p','l','e',' ','V','i','d','e','o','s','\0'};
 static const WCHAR DefaultW[] = {'.','D','e','f','a','u','l','t','\0'};
 static const WCHAR AllUsersProfileW[] = {'%','A','L','L','U','S','E','R','S','P','R','O','F','I','L','E','%','\0'};
 static const WCHAR UserProfileW[] = {'%','U','S','E','R','P','R','O','F','I','L','E','%','\0'};
 static const WCHAR SystemDriveW[] = {'%','S','y','s','t','e','m','D','r','i','v','e','%','\0'};
-static const WCHAR szSHFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'};
-static const WCHAR szSHUserFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','U','s','e','r',' ','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'};
-
-#if 0
 static const WCHAR ProfileListW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','P','r','o','f','i','l','e','L','i','s','t',0};
 static const WCHAR ProfilesDirectoryW[] = {'P','r','o','f','i','l','e','s','D','i','r','e','c','t','o','r','y',0};
 static const WCHAR AllUsersProfileValueW[] = {'A','l','l','U','s','e','r','s','P','r','o','f','i','l','e','\0'};
-static const WCHAR szDefaultProfileDirW[] = {'p','r','o','f','i','l','e','s','\0'};
-static const WCHAR AllUsersW[] = {'A','l','l',' ','U','s','e','r','s','\0'};
-#endif
-
-/* This defaults to L"Documents and Settings" on Windows 2000/XP, but we're
- * acting more Windows 9x-like for now.
- */
+static const WCHAR szSHFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'};
+static const WCHAR szSHUserFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','U','s','e','r',' ','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'};
+static const WCHAR szDefaultProfileDirW[] = {'u','s','e','r','s',0};
+static const WCHAR szKnownFolderDescriptions[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','F','o','l','d','e','r','D','e','s','c','r','i','p','t','i','o','n','s','\0'};
+static const WCHAR szKnownFolderRedirections[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','U','s','e','r',' ','S','h','e','l','l',' ','F','o','l','d','e','r','s',0};
+static const WCHAR AllUsersW[] = {'P','u','b','l','i','c',0};
 
 typedef enum _CSIDL_Type {
     CSIDL_Type_User,
@@ -587,10 +662,19 @@ typedef enum _CSIDL_Type {
     CSIDL_Type_NonExistent,
     CSIDL_Type_WindowsPath,
     CSIDL_Type_SystemPath,
+    CSIDL_Type_SystemX86Path,
 } CSIDL_Type;
 
+#define CSIDL_CONTACTS         0x0043
+#define CSIDL_DOWNLOADS        0x0047
+#define CSIDL_LINKS            0x004d
+#define CSIDL_APPDATA_LOCALLOW 0x004e
+#define CSIDL_SAVED_GAMES      0x0062
+#define CSIDL_SEARCHES         0x0063
+
 typedef struct
 {
+    const KNOWNFOLDERID *id;
     CSIDL_Type type;
     LPCWSTR    szValueName;
     LPCWSTR    szDefaultPath; /* fallback string or resource ID */
@@ -599,322 +683,699 @@ typedef struct
 static const CSIDL_DATA CSIDL_Data[] =
 {
     { /* 0x00 - CSIDL_DESKTOP */
+        &FOLDERID_Desktop,
         CSIDL_Type_User,
         DesktopW,
         MAKEINTRESOURCEW(IDS_DESKTOPDIRECTORY)
     },
     { /* 0x01 - CSIDL_INTERNET */
+        &FOLDERID_InternetFolder,
         CSIDL_Type_Disallowed,
         NULL,
         NULL
     },
     { /* 0x02 - CSIDL_PROGRAMS */
+        &FOLDERID_Programs,
         CSIDL_Type_User,
         ProgramsW,
-        MAKEINTRESOURCEW(IDS_PROGRAMS)
+        Start_Menu_ProgramsW
     },
     { /* 0x03 - CSIDL_CONTROLS (.CPL files) */
+        &FOLDERID_ControlPanelFolder,
         CSIDL_Type_SystemPath,
         NULL,
         NULL
     },
     { /* 0x04 - CSIDL_PRINTERS */
+        &FOLDERID_PrintersFolder,
         CSIDL_Type_SystemPath,
         NULL,
         NULL
     },
     { /* 0x05 - CSIDL_PERSONAL */
+        &FOLDERID_Documents,
         CSIDL_Type_User,
         PersonalW,
         MAKEINTRESOURCEW(IDS_PERSONAL)
     },
     { /* 0x06 - CSIDL_FAVORITES */
+        &FOLDERID_Favorites,
         CSIDL_Type_User,
         FavoritesW,
-        MAKEINTRESOURCEW(IDS_FAVORITES)
+        FavoritesW
     },
     { /* 0x07 - CSIDL_STARTUP */
+        &FOLDERID_Startup,
         CSIDL_Type_User,
         StartUpW,
-        MAKEINTRESOURCEW(IDS_STARTUP)
+        Start_Menu_StartupW
     },
     { /* 0x08 - CSIDL_RECENT */
+        &FOLDERID_Recent,
         CSIDL_Type_User,
         RecentW,
-        MAKEINTRESOURCEW(IDS_RECENT)
+        RecentW
     },
     { /* 0x09 - CSIDL_SENDTO */
+        &FOLDERID_SendTo,
         CSIDL_Type_User,
         SendToW,
-        MAKEINTRESOURCEW(IDS_SENDTO)
+        SendToW
     },
     { /* 0x0a - CSIDL_BITBUCKET - Recycle Bin */
+        &FOLDERID_RecycleBinFolder,
         CSIDL_Type_Disallowed,
         NULL,
         NULL,
     },
     { /* 0x0b - CSIDL_STARTMENU */
+        &FOLDERID_StartMenu,
         CSIDL_Type_User,
         Start_MenuW,
-        MAKEINTRESOURCEW(IDS_STARTMENU)
+        Start_MenuW
     },
     { /* 0x0c - CSIDL_MYDOCUMENTS */
+        &GUID_NULL,
         CSIDL_Type_Disallowed, /* matches WinXP--can't get its path */
         NULL,
         NULL
     },
     { /* 0x0d - CSIDL_MYMUSIC */
+        &FOLDERID_Music,
         CSIDL_Type_User,
         My_MusicW,
         MAKEINTRESOURCEW(IDS_MYMUSIC)
     },
     { /* 0x0e - CSIDL_MYVIDEO */
+        &FOLDERID_Videos,
         CSIDL_Type_User,
         My_VideoW,
         MAKEINTRESOURCEW(IDS_MYVIDEO)
     },
     { /* 0x0f - unassigned */
+        &GUID_NULL,
         CSIDL_Type_Disallowed,
         NULL,
         NULL,
     },
     { /* 0x10 - CSIDL_DESKTOPDIRECTORY */
+        &FOLDERID_Desktop,
         CSIDL_Type_User,
         DesktopW,
         MAKEINTRESOURCEW(IDS_DESKTOPDIRECTORY)
     },
     { /* 0x11 - CSIDL_DRIVES */
+        &FOLDERID_ComputerFolder,
         CSIDL_Type_Disallowed,
         NULL,
         NULL,
     },
     { /* 0x12 - CSIDL_NETWORK */
+        &FOLDERID_NetworkFolder,
         CSIDL_Type_Disallowed,
         NULL,
         NULL,
     },
     { /* 0x13 - CSIDL_NETHOOD */
+        &FOLDERID_NetHood,
         CSIDL_Type_User,
         NetHoodW,
-        MAKEINTRESOURCEW(IDS_NETHOOD)
+        NetHoodW
     },
     { /* 0x14 - CSIDL_FONTS */
+        &FOLDERID_Fonts,
         CSIDL_Type_WindowsPath,
         FontsW,
         FontsW
     },
     { /* 0x15 - CSIDL_TEMPLATES */
+        &FOLDERID_Templates,
         CSIDL_Type_User,
         TemplatesW,
-        MAKEINTRESOURCEW(IDS_TEMPLATES)
+        TemplatesW
     },
     { /* 0x16 - CSIDL_COMMON_STARTMENU */
+        &FOLDERID_CommonStartMenu,
         CSIDL_Type_AllUsers,
         Common_Start_MenuW,
-        MAKEINTRESOURCEW(IDS_STARTMENU)
+        Start_MenuW
     },
     { /* 0x17 - CSIDL_COMMON_PROGRAMS */
+        &FOLDERID_CommonPrograms,
         CSIDL_Type_AllUsers,
         Common_ProgramsW,
-        MAKEINTRESOURCEW(IDS_PROGRAMS)
+        Start_Menu_ProgramsW
     },
     { /* 0x18 - CSIDL_COMMON_STARTUP */
+        &FOLDERID_CommonStartup,
         CSIDL_Type_AllUsers,
         Common_StartUpW,
-        MAKEINTRESOURCEW(IDS_STARTUP)
+        Start_Menu_StartupW
     },
     { /* 0x19 - CSIDL_COMMON_DESKTOPDIRECTORY */
+        &FOLDERID_PublicDesktop,
         CSIDL_Type_AllUsers,
         Common_DesktopW,
-        MAKEINTRESOURCEW(IDS_DESKTOP)
+        MAKEINTRESOURCEW(IDS_DESKTOPDIRECTORY)
     },
     { /* 0x1a - CSIDL_APPDATA */
+        &FOLDERID_RoamingAppData,
         CSIDL_Type_User,
         AppDataW,
-        MAKEINTRESOURCEW(IDS_APPDATA)
+        Application_DataW
     },
     { /* 0x1b - CSIDL_PRINTHOOD */
+        &FOLDERID_PrintHood,
         CSIDL_Type_User,
         PrintHoodW,
-        MAKEINTRESOURCEW(IDS_PRINTHOOD)
+        PrintHoodW
     },
     { /* 0x1c - CSIDL_LOCAL_APPDATA */
+        &FOLDERID_LocalAppData,
         CSIDL_Type_User,
         Local_AppDataW,
-        MAKEINTRESOURCEW(IDS_LOCAL_APPDATA)
+        Local_Settings_Application_DataW
     },
     { /* 0x1d - CSIDL_ALTSTARTUP */
+        &GUID_NULL,
         CSIDL_Type_NonExistent,
         NULL,
         NULL
     },
     { /* 0x1e - CSIDL_COMMON_ALTSTARTUP */
+        &GUID_NULL,
         CSIDL_Type_NonExistent,
         NULL,
         NULL
     },
     { /* 0x1f - CSIDL_COMMON_FAVORITES */
+        &FOLDERID_Favorites,
         CSIDL_Type_AllUsers,
-        FavoritesW,
-        MAKEINTRESOURCEW(IDS_FAVORITES)
+        Common_FavoritesW,
+        FavoritesW
     },
     { /* 0x20 - CSIDL_INTERNET_CACHE */
+        &FOLDERID_InternetCache,
         CSIDL_Type_User,
         CacheW,
-        MAKEINTRESOURCEW(IDS_INTERNET_CACHE)
+        Local_Settings_Temporary_Internet_FilesW
     },
     { /* 0x21 - CSIDL_COOKIES */
+        &FOLDERID_Cookies,
         CSIDL_Type_User,
         CookiesW,
-        MAKEINTRESOURCEW(IDS_COOKIES)
+        CookiesW
     },
     { /* 0x22 - CSIDL_HISTORY */
+        &FOLDERID_History,
         CSIDL_Type_User,
         HistoryW,
-        MAKEINTRESOURCEW(IDS_HISTORY)
+        Local_Settings_HistoryW
     },
     { /* 0x23 - CSIDL_COMMON_APPDATA */
+        &FOLDERID_ProgramData,
         CSIDL_Type_AllUsers,
         Common_AppDataW,
-        MAKEINTRESOURCEW(IDS_APPDATA)
+        Application_DataW
     },
     { /* 0x24 - CSIDL_WINDOWS */
+        &FOLDERID_Windows,
         CSIDL_Type_WindowsPath,
         NULL,
         NULL
     },
     { /* 0x25 - CSIDL_SYSTEM */
+        &FOLDERID_System,
         CSIDL_Type_SystemPath,
         NULL,
         NULL
     },
     { /* 0x26 - CSIDL_PROGRAM_FILES */
+        &FOLDERID_ProgramFiles,
         CSIDL_Type_CurrVer,
         ProgramFilesDirW,
-        MAKEINTRESOURCEW(IDS_PROGRAM_FILES)
+        Program_FilesW
     },
     { /* 0x27 - CSIDL_MYPICTURES */
+        &FOLDERID_Pictures,
         CSIDL_Type_User,
         My_PicturesW,
         MAKEINTRESOURCEW(IDS_MYPICTURES)
     },
     { /* 0x28 - CSIDL_PROFILE */
+        &FOLDERID_Profile,
         CSIDL_Type_User,
         NULL,
         NULL
     },
     { /* 0x29 - CSIDL_SYSTEMX86 */
-        CSIDL_Type_NonExistent,
+        &FOLDERID_SystemX86,
+        CSIDL_Type_SystemX86Path,
         NULL,
         NULL
     },
     { /* 0x2a - CSIDL_PROGRAM_FILESX86 */
-        CSIDL_Type_NonExistent,
-        NULL,
-        NULL
+        &FOLDERID_ProgramFilesX86,
+        CSIDL_Type_CurrVer,
+        ProgramFilesDirX86W,
+        Program_Files_x86W
     },
     { /* 0x2b - CSIDL_PROGRAM_FILES_COMMON */
+        &FOLDERID_ProgramFilesCommon,
         CSIDL_Type_CurrVer,
         CommonFilesDirW,
-        MAKEINTRESOURCEW(IDS_PROGRAM_FILES_COMMON)
+        Program_Files_Common_FilesW
     },
     { /* 0x2c - CSIDL_PROGRAM_FILES_COMMONX86 */
-        CSIDL_Type_NonExistent,
-        NULL,
-        NULL
+        &FOLDERID_ProgramFilesCommonX86,
+        CSIDL_Type_CurrVer,
+        CommonFilesDirX86W,
+        Program_Files_x86_Common_FilesW
     },
     { /* 0x2d - CSIDL_COMMON_TEMPLATES */
+        &FOLDERID_CommonTemplates,
         CSIDL_Type_AllUsers,
         Common_TemplatesW,
-        MAKEINTRESOURCEW(IDS_TEMPLATES)
+        TemplatesW
     },
     { /* 0x2e - CSIDL_COMMON_DOCUMENTS */
+        &FOLDERID_PublicDocuments,
         CSIDL_Type_AllUsers,
         Common_DocumentsW,
-        MAKEINTRESOURCEW(IDS_COMMON_DOCUMENTS)
+        DocumentsW
     },
     { /* 0x2f - CSIDL_COMMON_ADMINTOOLS */
+        &FOLDERID_CommonAdminTools,
         CSIDL_Type_AllUsers,
         Common_Administrative_ToolsW,
-        MAKEINTRESOURCEW(IDS_ADMINTOOLS)
+        Start_Menu_Admin_ToolsW
     },
     { /* 0x30 - CSIDL_ADMINTOOLS */
+        &FOLDERID_AdminTools,
         CSIDL_Type_User,
         Administrative_ToolsW,
-        MAKEINTRESOURCEW(IDS_ADMINTOOLS)
+        Start_Menu_Admin_ToolsW
     },
     { /* 0x31 - CSIDL_CONNECTIONS */
+        &FOLDERID_ConnectionsFolder,
         CSIDL_Type_Disallowed,
         NULL,
         NULL
     },
     { /* 0x32 - unassigned */
+        &GUID_NULL,
         CSIDL_Type_Disallowed,
         NULL,
         NULL
     },
     { /* 0x33 - unassigned */
+        &GUID_NULL,
         CSIDL_Type_Disallowed,
         NULL,
         NULL
     },
     { /* 0x34 - unassigned */
+        &GUID_NULL,
         CSIDL_Type_Disallowed,
         NULL,
         NULL
     },
     { /* 0x35 - CSIDL_COMMON_MUSIC */
+        &FOLDERID_PublicMusic,
         CSIDL_Type_AllUsers,
         CommonMusicW,
-        MAKEINTRESOURCEW(IDS_COMMON_MUSIC)
+        MusicW
     },
     { /* 0x36 - CSIDL_COMMON_PICTURES */
+        &FOLDERID_PublicPictures,
         CSIDL_Type_AllUsers,
         CommonPicturesW,
-        MAKEINTRESOURCEW(IDS_COMMON_PICTURES)
+        PicturesW
     },
     { /* 0x37 - CSIDL_COMMON_VIDEO */
+        &FOLDERID_PublicVideos,
         CSIDL_Type_AllUsers,
         CommonVideoW,
-        MAKEINTRESOURCEW(IDS_COMMON_VIDEO)
+        VideosW
     },
     { /* 0x38 - CSIDL_RESOURCES */
+        &FOLDERID_ResourceDir,
         CSIDL_Type_WindowsPath,
         NULL,
         ResourcesW
     },
     { /* 0x39 - CSIDL_RESOURCES_LOCALIZED */
+        &FOLDERID_LocalizedResourcesDir,
         CSIDL_Type_NonExistent,
         NULL,
         NULL
     },
     { /* 0x3a - CSIDL_COMMON_OEM_LINKS */
-        CSIDL_Type_NonExistent,
+        &FOLDERID_CommonOEMLinks,
+        CSIDL_Type_AllUsers,
         NULL,
-        NULL
+        OEM_LinksW
     },
     { /* 0x3b - CSIDL_CDBURN_AREA */
+        &FOLDERID_CDBurning,
         CSIDL_Type_User,
         CD_BurningW,
-        MAKEINTRESOURCEW(IDS_CDBURN_AREA)
+        Local_Settings_CD_BurningW
     },
     { /* 0x3c unassigned */
+        &GUID_NULL,
         CSIDL_Type_Disallowed,
         NULL,
         NULL
     },
     { /* 0x3d - CSIDL_COMPUTERSNEARME */
+        &GUID_NULL,
         CSIDL_Type_Disallowed, /* FIXME */
         NULL,
         NULL
     },
     { /* 0x3e - CSIDL_PROFILES */
+        &GUID_NULL,
         CSIDL_Type_Disallowed, /* oddly, this matches WinXP */
         NULL,
         NULL
+    },
+    { /* 0x3f */
+        &FOLDERID_AddNewPrograms,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x40 */
+        &FOLDERID_AppUpdates,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x41 */
+        &FOLDERID_ChangeRemovePrograms,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x42 */
+        &FOLDERID_ConflictFolder,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x43 - CSIDL_CONTACTS */
+        &FOLDERID_Contacts,
+        CSIDL_Type_User,
+        NULL,
+        ContactsW
+    },
+    { /* 0x44 */
+        &FOLDERID_DeviceMetadataStore,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x45 */
+        &GUID_NULL,
+        CSIDL_Type_User,
+        NULL,
+        DocumentsW
+    },
+    { /* 0x46 */
+        &FOLDERID_DocumentsLibrary,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x47 - CSIDL_DOWNLOADS */
+        &FOLDERID_Downloads,
+        CSIDL_Type_User,
+        NULL,
+        DownloadsW
+    },
+    { /* 0x48 */
+        &FOLDERID_Games,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x49 */
+        &FOLDERID_GameTasks,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x4a */
+        &FOLDERID_HomeGroup,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x4b */
+        &FOLDERID_ImplicitAppShortcuts,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x4c */
+        &FOLDERID_Libraries,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x4d - CSIDL_LINKS */
+        &FOLDERID_Links,
+        CSIDL_Type_User,
+        NULL,
+        LinksW
+    },
+    { /* 0x4e - CSIDL_APPDATA_LOCALLOW */
+        &FOLDERID_LocalAppDataLow,
+        CSIDL_Type_User,
+        NULL,
+        AppData_LocalLowW
+    },
+    { /* 0x4f */
+        &FOLDERID_MusicLibrary,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x50 */
+        &FOLDERID_OriginalImages,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x51 */
+        &FOLDERID_PhotoAlbums,
+        CSIDL_Type_User,
+        NULL,
+        Pictures_Slide_ShowsW
+    },
+    { /* 0x52 */
+        &FOLDERID_PicturesLibrary,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x53 */
+        &FOLDERID_Playlists,
+        CSIDL_Type_User,
+        NULL,
+        Music_PlaylistsW
+    },
+    { /* 0x54 */
+        &FOLDERID_ProgramFilesX64,
+        CSIDL_Type_NonExistent,
+        NULL,
+        NULL
+    },
+    { /* 0x55 */
+        &FOLDERID_ProgramFilesCommonX64,
+        CSIDL_Type_NonExistent,
+        NULL,
+        NULL
+    },
+    { /* 0x56 */
+        &FOLDERID_Public,
+        CSIDL_Type_CurrVer, /* FIXME */
+        NULL,
+        UsersPublicW
+    },
+    { /* 0x57 */
+        &FOLDERID_PublicDownloads,
+        CSIDL_Type_AllUsers,
+        NULL,
+        DownloadsW
+    },
+    { /* 0x58 */
+        &FOLDERID_PublicGameTasks,
+        CSIDL_Type_AllUsers,
+        NULL,
+        Microsoft_Windows_GameExplorerW
+    },
+    { /* 0x59 */
+        &FOLDERID_PublicLibraries,
+        CSIDL_Type_AllUsers,
+        NULL,
+        Microsoft_Windows_LibrariesW
+    },
+    { /* 0x5a */
+        &FOLDERID_PublicRingtones,
+        CSIDL_Type_AllUsers,
+        NULL,
+        Microsoft_Windows_RingtonesW
+    },
+    { /* 0x5b */
+        &FOLDERID_QuickLaunch,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x5c */
+        &FOLDERID_RecordedTVLibrary,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x5d */
+        &FOLDERID_Ringtones,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x5e */
+        &FOLDERID_SampleMusic,
+        CSIDL_Type_AllUsers,
+        NULL,
+        Music_Sample_MusicW
+    },
+    { /* 0x5f */
+        &FOLDERID_SamplePictures,
+        CSIDL_Type_AllUsers,
+        NULL,
+        Pictures_Sample_PicturesW
+    },
+    { /* 0x60 */
+        &FOLDERID_SamplePlaylists,
+        CSIDL_Type_AllUsers,
+        NULL,
+        Music_Sample_PlaylistsW
+    },
+    { /* 0x61 */
+        &FOLDERID_SampleVideos,
+        CSIDL_Type_AllUsers,
+        NULL,
+        Videos_Sample_VideosW
+    },
+    { /* 0x62 - CSIDL_SAVED_GAMES */
+        &FOLDERID_SavedGames,
+        CSIDL_Type_User,
+        NULL,
+        Saved_GamesW
+    },
+    { /* 0x63 - CSIDL_SEARCHES */
+        &FOLDERID_SavedSearches,
+        CSIDL_Type_User,
+        NULL,
+        SearchesW
+    },
+    { /* 0x64 */
+        &FOLDERID_SEARCH_CSC,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x65 */
+        &FOLDERID_SEARCH_MAPI,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x66 */
+        &FOLDERID_SearchHome,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x67 */
+        &FOLDERID_SidebarDefaultParts,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x68 */
+        &FOLDERID_SidebarParts,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x69 */
+        &FOLDERID_SyncManagerFolder,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x6a */
+        &FOLDERID_SyncResultsFolder,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x6b */
+        &FOLDERID_SyncSetupFolder,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x6c */
+        &FOLDERID_UserPinned,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x6d */
+        &FOLDERID_UserProfiles,
+        CSIDL_Type_CurrVer,
+        UsersW,
+        UsersW
+    },
+    { /* 0x6e */
+        &FOLDERID_UserProgramFiles,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x6f */
+        &FOLDERID_UserProgramFilesCommon,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
+    },
+    { /* 0x70 */
+        &FOLDERID_UsersFiles,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x71 */
+        &FOLDERID_UsersLibraries,
+        CSIDL_Type_Disallowed,
+        NULL,
+        NULL
+    },
+    { /* 0x72 */
+        &FOLDERID_VideosLibrary,
+        CSIDL_Type_Disallowed, /* FIXME */
+        NULL,
+        NULL
     }
 };
 
+static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest);
+
 /* Gets the value named value from the registry key
  * rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
  * (or from rootKey\userPrefix\... if userPrefix is not NULL) into path, which
@@ -930,7 +1391,7 @@ static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix,
     HRESULT hr;
     WCHAR shellFolderPath[MAX_PATH], userShellFolderPath[MAX_PATH];
     LPCWSTR pShellFolderPath, pUserShellFolderPath;
-    DWORD dwDisp, dwType, dwPathLen;
+    DWORD dwType, dwPathLen = MAX_PATH;
     HKEY userShellFolderKey, shellFolderKey;
 
     TRACE("%p,%s,%s,%p\n",rootKey, debugstr_w(userPrefix), debugstr_w(value),
@@ -938,13 +1399,13 @@ static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix,
 
     if (userPrefix)
     {
-        wcscpy(shellFolderPath, userPrefix);
+        strcpyW(shellFolderPath, userPrefix);
         PathAddBackslashW(shellFolderPath);
-        wcscat(shellFolderPath, szSHFolders);
+        strcatW(shellFolderPath, szSHFolders);
         pShellFolderPath = shellFolderPath;
-        wcscpy(userShellFolderPath, userPrefix);
+        strcpyW(userShellFolderPath, userPrefix);
         PathAddBackslashW(userShellFolderPath);
-        wcscat(userShellFolderPath, szSHUserFolders);
+        strcatW(userShellFolderPath, szSHUserFolders);
         pUserShellFolderPath = userShellFolderPath;
     }
     else
@@ -953,14 +1414,12 @@ static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix,
         pShellFolderPath = szSHFolders;
     }
 
-    if (RegCreateKeyExW(rootKey, pShellFolderPath, 0, NULL, 0, KEY_SET_VALUE,
-     NULL, &shellFolderKey, &dwDisp))
+    if (RegCreateKeyW(rootKey, pShellFolderPath, &shellFolderKey))
     {
         TRACE("Failed to create %s\n", debugstr_w(pShellFolderPath));
         return E_FAIL;
     }
-    if (RegCreateKeyExW(rootKey, pUserShellFolderPath, 0, NULL, 0,
-     KEY_QUERY_VALUE, NULL, &userShellFolderKey, &dwDisp))
+    if (RegCreateKeyW(rootKey, pUserShellFolderPath, &userShellFolderKey))
     {
         TRACE("Failed to create %s\n",
          debugstr_w(pUserShellFolderPath));
@@ -968,25 +1427,21 @@ static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix,
         return E_FAIL;
     }
 
-    dwPathLen = MAX_PATH * sizeof(WCHAR);
-
     if (!RegQueryValueExW(userShellFolderKey, value, NULL, &dwType,
      (LPBYTE)path, &dwPathLen) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
     {
         LONG ret;
 
-        dwPathLen /= sizeof(WCHAR);
-
-        path[dwPathLen] = '\0';
+        path[dwPathLen / sizeof(WCHAR)] = '\0';
         if (dwType == REG_EXPAND_SZ && path[0] == '%')
         {
             WCHAR szTemp[MAX_PATH];
 
-            dwPathLen = ExpandEnvironmentStringsW(path, szTemp, MAX_PATH);
-            lstrcpynW(path, szTemp, dwPathLen);
+            _SHExpandEnvironmentStrings(path, szTemp);
+            lstrcpynW(path, szTemp, MAX_PATH);
         }
-
-        ret = RegSetValueExW(shellFolderKey, value, 0, REG_SZ, (LPBYTE)path, dwPathLen * sizeof(WCHAR));
+        ret = RegSetValueExW(shellFolderKey, value, 0, REG_SZ, (LPBYTE)path,
+         (strlenW(path) + 1) * sizeof(WCHAR));
         if (ret != ERROR_SUCCESS)
             hr = HRESULT_FROM_WIN32(ret);
         else
@@ -994,13 +1449,33 @@ static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix,
     }
     else
         hr = E_FAIL;
-
     RegCloseKey(shellFolderKey);
     RegCloseKey(userShellFolderKey);
     TRACE("returning 0x%08x\n", hr);
     return hr;
 }
 
+BOOL _SHGetUserProfileDirectoryW(HANDLE hToken, LPWSTR szPath, LPDWORD lpcchPath)
+{
+    BOOL result;
+    if (!hToken)
+    {
+        OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
+        result = GetUserProfileDirectoryW(hToken, szPath, lpcchPath);
+        CloseHandle(hToken);
+    }
+    else if ((INT) hToken == -1)
+    {
+        result = GetDefaultUserProfileDirectoryW(szPath, lpcchPath);
+    }
+    else
+    {
+        result = GetUserProfileDirectoryW(hToken, szPath, lpcchPath);
+    }
+    DbgPrint("_SHGetUserProfileDirectoryW returning %S\n", szPath);
+    return result;
+}
+
 /* Gets a 'semi-expanded' default value of the CSIDL with index folder into
  * pszPath, based on the entries in CSIDL_Data.  By semi-expanded, I mean:
  * - The entry's szDefaultPath may be either a string value or an integer
@@ -1015,13 +1490,11 @@ static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix,
  *   CSIDL_Type_CurrVer:  %SystemDrive%
  *   (Others might make sense too, but as yet are unneeded.)
  */
-static HRESULT _SHGetDefaultValue(BYTE folder, LPWSTR pszPath)
+static HRESULT _SHGetDefaultValue(HANDLE hToken, BYTE folder, LPWSTR pszPath)
 {
-    DWORD dwSize;
+    DWORD cchSize;
     HRESULT hr;
-    HKEY hKey;
     WCHAR resourcePath[MAX_PATH];
-    LPCWSTR pDefaultPath = NULL;
 
     TRACE("0x%02x,%p\n", folder, pszPath);
 
@@ -1030,60 +1503,58 @@ static HRESULT _SHGetDefaultValue(BYTE folder, LPWSTR pszPath)
     if (!pszPath)
         return E_INVALIDARG;
 
-
-    if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
+    switch (folder)
     {
-        /* FIXME assume MAX_PATH size */
-        dwSize = MAX_PATH * sizeof(WCHAR);
-        if (RegQueryValueExW(hKey, CSIDL_Data[folder].szValueName, NULL, NULL, (LPBYTE)pszPath, &dwSize) == ERROR_SUCCESS)
-        {
-            RegCloseKey(hKey);
-            return S_OK;
-        }
-        RegCloseKey(hKey);
+    case CSIDL_PROGRAM_FILES:
+        if (IsWow64())
+            folder = CSIDL_PROGRAM_FILESX86;
+        break;
+    case CSIDL_PROGRAM_FILES_COMMON:
+        if (IsWow64())
+            folder = CSIDL_PROGRAM_FILESX86;
+        break;
     }
 
-    if (CSIDL_Data[folder].szDefaultPath &&
-     IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath))
-    {
-        if (LoadStringW(shell32_hInstance,
-         LOWORD(CSIDL_Data[folder].szDefaultPath), resourcePath, MAX_PATH))
-        {
-            hr = S_OK;
-            pDefaultPath = resourcePath;
-        }
-        else
-        {
-            FIXME("(%d,%s), LoadString failed, missing translation?\n", folder,
-             debugstr_w(pszPath));
-            hr = E_FAIL;
-        }
-    }
-    else
+    switch (CSIDL_Data[folder].type)
     {
-        hr = S_OK;
-        pDefaultPath = CSIDL_Data[folder].szDefaultPath;
+    case CSIDL_Type_User:
+        cchSize = MAX_PATH;
+        if (!_SHGetUserProfileDirectoryW(hToken, pszPath, &cchSize))
+            return HRESULT_FROM_WIN32(GetLastError());
+        break;
+    case CSIDL_Type_AllUsers:
+        cchSize = MAX_PATH;
+        if (!GetAllUsersProfileDirectoryW(pszPath, &cchSize))
+            return HRESULT_FROM_WIN32(GetLastError());
+        break;
+    case CSIDL_Type_CurrVer:
+        strcpyW(pszPath, SystemDriveW);
+        break;
+    default:
+        ; /* no corresponding env. var, do nothing */
     }
-    if (SUCCEEDED(hr))
+
+    if (CSIDL_Data[folder].szDefaultPath)
     {
-        switch (CSIDL_Data[folder].type)
+        if (IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath))
         {
-            case CSIDL_Type_User:
-                wcscpy(pszPath, UserProfileW);
-                break;
-            case CSIDL_Type_AllUsers:
-                wcscpy(pszPath, AllUsersProfileW);
-                break;
-            case CSIDL_Type_CurrVer:
-                wcscpy(pszPath, SystemDriveW);
-                break;
-            default:
-                ; /* no corresponding env. var, do nothing */
+            if (LoadStringW(shell32_hInstance,
+                LOWORD(CSIDL_Data[folder].szDefaultPath), resourcePath, MAX_PATH))
+            {
+                hr = S_OK;
+                PathAppendW(pszPath, resourcePath);
+            }
+            else
+            {
+                FIXME("(%d,%s), LoadString failed, missing translation?\n", folder,
+                      debugstr_w(pszPath));
+                hr = E_FAIL;
+            }
         }
-        if (pDefaultPath)
+        else
         {
-            PathAddBackslashW(pszPath);
-            wcscat(pszPath, pDefaultPath);
+            hr = S_OK;
+            PathAppendW(pszPath, CSIDL_Data[folder].szDefaultPath);
         }
     }
     TRACE("returning 0x%08x\n", hr);
@@ -1111,14 +1582,12 @@ static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder,
         return E_INVALIDARG;
 
     if (dwFlags & SHGFP_TYPE_DEFAULT)
-        hr = _SHGetDefaultValue(folder, pszPath);
+        hr = _SHGetDefaultValue(NULL, folder, pszPath);
     else
     {
         HKEY hKey;
-        DWORD dwDisp;
 
-        if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szCurrentVersion, 0,
-         NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisp))
+        if (RegCreateKeyW(HKEY_LOCAL_MACHINE, szCurrentVersion, &hKey))
             hr = E_FAIL;
         else
         {
@@ -1128,10 +1597,24 @@ static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder,
              &dwType, (LPBYTE)pszPath, &dwPathLen) ||
              (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
             {
-                hr = _SHGetDefaultValue(folder, pszPath);
+                hr = _SHGetDefaultValue(NULL, folder, pszPath);
                 dwType = REG_EXPAND_SZ;
-                RegSetValueExW(hKey, CSIDL_Data[folder].szValueName, 0, dwType,
-                 (LPBYTE)pszPath, (wcslen(pszPath)+1)*sizeof(WCHAR));
+                switch (folder)
+                {
+                case CSIDL_PROGRAM_FILESX86:
+                case CSIDL_PROGRAM_FILES_COMMONX86:
+                    /* these two should never be set on 32-bit setups */
+                    if (!is_win64)
+                    {
+                        BOOL is_wow64;
+                        IsWow64Process( GetCurrentProcess(), &is_wow64 );
+                        if (!is_wow64) break;
+                    }
+                    /* fall through */
+                default:
+                    RegSetValueExW(hKey, CSIDL_Data[folder].szValueName, 0, dwType,
+                                   (LPBYTE)pszPath, (strlenW(pszPath)+1)*sizeof(WCHAR));
+                }
             }
             else
             {
@@ -1145,6 +1628,39 @@ static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder,
     return hr;
 }
 
+static LPWSTR _GetUserSidStringFromToken(HANDLE Token)
+{
+    char InfoBuffer[64];
+    PTOKEN_USER UserInfo;
+    DWORD InfoSize;
+    LPWSTR SidStr;
+
+    UserInfo = (PTOKEN_USER) InfoBuffer;
+    if (! GetTokenInformation(Token, TokenUser, InfoBuffer, sizeof(InfoBuffer),
+                              &InfoSize))
+    {
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+            return NULL;
+        UserInfo = HeapAlloc(GetProcessHeap(), 0, InfoSize);
+        if (UserInfo == NULL)
+            return NULL;
+        if (! GetTokenInformation(Token, TokenUser, UserInfo, InfoSize,
+                                  &InfoSize))
+        {
+            HeapFree(GetProcessHeap(), 0, UserInfo);
+            return NULL;
+        }
+    }
+
+    if (! ConvertSidToStringSidW(UserInfo->User.Sid, &SidStr))
+        SidStr = NULL;
+
+    if (UserInfo != (PTOKEN_USER) InfoBuffer)
+        HeapFree(GetProcessHeap(), 0, UserInfo);
+
+    return SidStr;
+}
+
 /* Gets the user's path (unexpanded) for the CSIDL with index folder:
  * If SHGFP_TYPE_DEFAULT is set, calls _SHGetDefaultValue for it.  Otherwise
  * calls _SHGetUserShellFolderPath for it.  Where it looks depends on hToken:
@@ -1156,86 +1672,63 @@ static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder,
 static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags, BYTE folder,
  LPWSTR pszPath)
 {
+    const WCHAR *szValueName;
+    WCHAR buffer[40];
     HRESULT hr;
 
     TRACE("%p,0x%08x,0x%02x,%p\n", hToken, dwFlags, folder, pszPath);
 
     if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0]))
         return E_INVALIDARG;
-
     if (CSIDL_Data[folder].type != CSIDL_Type_User)
         return E_INVALIDARG;
-
     if (!pszPath)
         return E_INVALIDARG;
 
     if (dwFlags & SHGFP_TYPE_DEFAULT)
     {
-        if (hToken != NULL && hToken != (HANDLE)-1)
-        {
-             FIXME("unsupported for user other than current or default\n");
-             return E_FAIL;
-        }
-        hr = _SHGetDefaultValue(folder, pszPath);
+        hr = _SHGetDefaultValue(hToken, folder, pszPath);
     }
     else
     {
-        LPWSTR userPrefix;
+        LPCWSTR userPrefix = NULL;
         HKEY hRootKey;
 
         if (hToken == (HANDLE)-1)
         {
-            /* Get the folder of the default user */
             hRootKey = HKEY_USERS;
-            userPrefix = (LPWSTR)DefaultW;
+            userPrefix = DefaultW;
         }
-        else if(!hToken)
-        {
-            /* Get the folder of the current user */
+        else if (hToken == NULL)
             hRootKey = HKEY_CURRENT_USER;
-            userPrefix = NULL;
-        }
         else
         {
-            /* Get the folder of the specified user */
-            DWORD InfoLength;
-            PTOKEN_USER UserInfo;
-
             hRootKey = HKEY_USERS;
-
-            GetTokenInformation(hToken, TokenUser, NULL, 0, &InfoLength);
-            UserInfo = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, InfoLength);
-
-            if(!GetTokenInformation(hToken, TokenUser, UserInfo, InfoLength, &InfoLength))
+            userPrefix = _GetUserSidStringFromToken(hToken);
+            if (userPrefix == NULL)
             {
-                WARN("GetTokenInformation failed for %x!\n", hToken);
-                HeapFree(GetProcessHeap(), 0, UserInfo);
-                return E_FAIL;
-            }
-
-            if(!ConvertSidToStringSidW(UserInfo->User.Sid, &userPrefix))
-            {
-                WARN("ConvertSidToStringSidW failed for %x!\n", hToken);
-                HeapFree(GetProcessHeap(), 0, UserInfo);
-                return E_FAIL;
+                hr = E_FAIL;
+                goto error;
             }
-
-            HeapFree(GetProcessHeap(), 0, UserInfo);
         }
 
-        hr = _SHGetUserShellFolderPath(hRootKey, userPrefix, CSIDL_Data[folder].szValueName, pszPath);
-
-        /* Free the memory allocated by ConvertSidToStringSidW */
-        if(hToken && hToken != (HANDLE)-1)
-            LocalFree(userPrefix);
+        /* For CSIDL_Type_User we also use the GUID if no szValueName is provided */
+        szValueName = CSIDL_Data[folder].szValueName;
+        if (!szValueName)
+        {
+            StringFromGUID2( CSIDL_Data[folder].id, buffer, 39 );
+            szValueName = &buffer[0];
+        }
 
+        hr = _SHGetUserShellFolderPath(hRootKey, userPrefix, szValueName, pszPath);
         if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE)
-            hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, CSIDL_Data[folder].szValueName, pszPath);
-
+            hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, szValueName, pszPath);
         if (FAILED(hr))
-            hr = _SHGetDefaultValue(folder, pszPath);
+            hr = _SHGetDefaultValue(hToken, folder, pszPath);
+        if (userPrefix != NULL && userPrefix != DefaultW)
+            LocalFree((HLOCAL) userPrefix);
     }
-
+error:
     TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
     return hr;
 }
@@ -1260,22 +1753,181 @@ static HRESULT _SHGetAllUsersProfilePath(DWORD dwFlags, BYTE folder,
         return E_INVALIDARG;
 
     if (dwFlags & SHGFP_TYPE_DEFAULT)
-        hr = _SHGetDefaultValue(folder, pszPath);
+        hr = _SHGetDefaultValue(NULL, folder, pszPath);
     else
     {
         hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL,
          CSIDL_Data[folder].szValueName, pszPath);
         if (FAILED(hr))
-            hr = _SHGetDefaultValue(folder, pszPath);
+            hr = _SHGetDefaultValue(NULL, folder, pszPath);
     }
     TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
     return hr;
 }
 
+static HRESULT _SHOpenProfilesKey(PHKEY pKey)
+{
+    LONG lRet;
+    DWORD disp;
+
+    lRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, ProfileListW, 0, NULL, 0,
+     KEY_ALL_ACCESS, NULL, pKey, &disp);
+    return HRESULT_FROM_WIN32(lRet);
+}
+
+/* Reads the value named szValueName from the key profilesKey (assumed to be
+ * opened by _SHOpenProfilesKey) into szValue, which is assumed to be MAX_PATH
+ * WCHARs in length.  If it doesn't exist, returns szDefault (and saves
+ * szDefault to the registry).
+ */
+static HRESULT _SHGetProfilesValue(HKEY profilesKey, LPCWSTR szValueName,
+ LPWSTR szValue, LPCWSTR szDefault)
+{
+    HRESULT hr;
+    DWORD type, dwPathLen = MAX_PATH * sizeof(WCHAR);
+    LONG lRet;
+
+    TRACE("%p,%s,%p,%s\n", profilesKey, debugstr_w(szValueName), szValue,
+     debugstr_w(szDefault));
+    lRet = RegQueryValueExW(profilesKey, szValueName, NULL, &type,
+     (LPBYTE)szValue, &dwPathLen);
+    if (!lRet && (type == REG_SZ || type == REG_EXPAND_SZ) && dwPathLen
+     && *szValue)
+    {
+        dwPathLen /= sizeof(WCHAR);
+        szValue[dwPathLen] = '\0';
+        hr = S_OK;
+    }
+    else
+    {
+        /* Missing or invalid value, set a default */
+        lstrcpynW(szValue, szDefault, MAX_PATH);
+        TRACE("Setting missing value %s to %s\n", debugstr_w(szValueName),
+                                                  debugstr_w(szValue));
+        lRet = RegSetValueExW(profilesKey, szValueName, 0, REG_EXPAND_SZ,
+                              (LPBYTE)szValue,
+                              (strlenW(szValue) + 1) * sizeof(WCHAR));
+        if (lRet)
+            hr = HRESULT_FROM_WIN32(lRet);
+        else
+            hr = S_OK;
+    }
+    TRACE("returning 0x%08x (output value is %s)\n", hr, debugstr_w(szValue));
+    return hr;
+}
+
+/* Attempts to expand environment variables from szSrc into szDest, which is
+ * assumed to be MAX_PATH characters in length.  Before referring to the
+ * environment, handles a few variables directly, because the environment
+ * variables may not be set when this is called (as during Wine's installation
+ * when default values are being written to the registry).
+ * The directly handled environment variables, and their source, are:
+ * - ALLUSERSPROFILE, USERPROFILE: reads from the registry
+ * - SystemDrive: uses GetSystemDirectoryW and uses the drive portion of its
+ *   path
+ * If one of the directly handled environment variables is expanded, only
+ * expands a single variable, and only in the beginning of szSrc.
+ */
+static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest)
+{
+    HRESULT hr;
+    WCHAR szTemp[MAX_PATH], szProfilesPrefix[MAX_PATH] = { 0 };
+    HKEY key = NULL;
+
+    TRACE("%s, %p\n", debugstr_w(szSrc), szDest);
+
+    if (!szSrc || !szDest) return E_INVALIDARG;
+
+    /* short-circuit if there's nothing to expand */
+    if (szSrc[0] != '%')
+    {
+        strcpyW(szDest, szSrc);
+        hr = S_OK;
+        goto end;
+    }
+    /* Get the profile prefix, we'll probably be needing it */
+    hr = _SHOpenProfilesKey(&key);
+    if (SUCCEEDED(hr))
+    {
+        WCHAR def_val[MAX_PATH];
+
+        /* get the system drive */
+        GetSystemDirectoryW(def_val, MAX_PATH);
+        if (def_val[1] == ':') strcpyW( def_val + 3, szDefaultProfileDirW );
+        else FIXME("non-drive system paths unsupported\n");
+
+        hr = _SHGetProfilesValue(key, ProfilesDirectoryW, szProfilesPrefix, def_val );
+    }
+
+    *szDest = 0;
+    strcpyW(szTemp, szSrc);
+    while (SUCCEEDED(hr) && szTemp[0] == '%')
+    {
+        if (!strncmpiW(szTemp, AllUsersProfileW, strlenW(AllUsersProfileW)))
+        {
+            WCHAR szAllUsers[MAX_PATH];
+
+            strcpyW(szDest, szProfilesPrefix);
+            hr = _SHGetProfilesValue(key, AllUsersProfileValueW,
+             szAllUsers, AllUsersW);
+            PathAppendW(szDest, szAllUsers);
+            PathAppendW(szDest, szTemp + strlenW(AllUsersProfileW));
+        }
+        else if (!strncmpiW(szTemp, UserProfileW, strlenW(UserProfileW)))
+        {
+            WCHAR userName[MAX_PATH];
+            DWORD userLen = MAX_PATH;
+
+            strcpyW(szDest, szProfilesPrefix);
+            GetUserNameW(userName, &userLen);
+            PathAppendW(szDest, userName);
+            PathAppendW(szDest, szTemp + strlenW(UserProfileW));
+        }
+        else if (!strncmpiW(szTemp, SystemDriveW, strlenW(SystemDriveW)))
+        {
+            GetSystemDirectoryW(szDest, MAX_PATH);
+            if (szDest[1] != ':')
+            {
+                FIXME("non-drive system paths unsupported\n");
+                hr = E_FAIL;
+            }
+            else
+            {
+                strcpyW(szDest + 3, szTemp + strlenW(SystemDriveW) + 1);
+                hr = S_OK;
+            }
+        }
+        else
+        {
+            DWORD ret = ExpandEnvironmentStringsW(szSrc, szDest, MAX_PATH);
+
+            if (ret > MAX_PATH)
+                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+            else if (ret == 0)
+                hr = HRESULT_FROM_WIN32(GetLastError());
+            else
+                hr = S_OK;
+        }
+        if (SUCCEEDED(hr) && szDest[0] == '%')
+            strcpyW(szTemp, szDest);
+        else
+        {
+            /* terminate loop */
+            szTemp[0] = '\0';
+        }
+    }
+end:
+    if (key)
+        RegCloseKey(key);
+    TRACE("returning 0x%08x (input was %s, output is %s)\n", hr,
+     debugstr_w(szSrc), debugstr_w(szDest));
+    return hr;
+}
+
 /*************************************************************************
- * SHGetFolderPathW            [SHELL32.@]
+ * SHGetFolderPathW                    [SHELL32.@]
  *
- * Convert nFolder to path.
+ * Convert nFolder to path.  
  *
  * RETURNS
  *  Success: S_OK
@@ -1293,11 +1945,11 @@ static HRESULT _SHGetAllUsersProfilePath(DWORD dwFlags, BYTE folder,
  * Furthermore, the HKCU paths take precedence over the HKLM paths.
  */
 HRESULT WINAPI SHGetFolderPathW(
-    HWND hwndOwner,    /* [I] owner window */
-    int nFolder,       /* [I] CSIDL identifying the folder */
-    HANDLE hToken,     /* [I] access token */
-    DWORD dwFlags,     /* [I] which path to return */
-    LPWSTR pszPath)    /* [O] converted path */
+       HWND hwndOwner,    /* [I] owner window */
+       int nFolder,       /* [I] CSIDL identifying the folder */
+       HANDLE hToken,     /* [I] access token */
+       DWORD dwFlags,     /* [I] which path to return */
+       LPWSTR pszPath)    /* [O] converted path */
 {
     HRESULT hr =  SHGetFolderPathAndSubDirW(hwndOwner, nFolder, hToken, dwFlags, NULL, pszPath);
     if(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
@@ -1306,12 +1958,12 @@ HRESULT WINAPI SHGetFolderPathW(
 }
 
 HRESULT WINAPI SHGetFolderPathAndSubDirA(
-    HWND hwndOwner,    /* [I] owner window */
-    int nFolder,       /* [I] CSIDL identifying the folder */
-    HANDLE hToken,     /* [I] access token */
-    DWORD dwFlags,     /* [I] which path to return */
-    LPCSTR pszSubPath, /* [I] sub directory of the specified folder */
-    LPSTR pszPath)     /* [O] converted path */
+       HWND hwndOwner,    /* [I] owner window */
+       int nFolder,       /* [I] CSIDL identifying the folder */
+       HANDLE hToken,     /* [I] access token */
+       DWORD dwFlags,     /* [I] which path to return */
+       LPCSTR pszSubPath, /* [I] sub directory of the specified folder */
+       LPSTR pszPath)     /* [O] converted path */
 {
     int length;
     HRESULT hr = S_OK;
@@ -1320,7 +1972,7 @@ HRESULT WINAPI SHGetFolderPathAndSubDirA(
     TRACE("%08x,%08x,%s\n",nFolder, dwFlags, debugstr_w(pszSubPathW));
 
     if(pszPath) {
-        pszPathW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
+        pszPathW = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
         if(!pszPathW) {
             hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
             goto cleanup;
@@ -1334,7 +1986,7 @@ HRESULT WINAPI SHGetFolderPathAndSubDirA(
      */
     if (pszSubPath && pszSubPath[0]) {
         length = MultiByteToWideChar(CP_ACP, 0, pszSubPath, -1, NULL, 0);
-        pszSubPathW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, length * sizeof(WCHAR));
+        pszSubPathW = HeapAlloc(GetProcessHeap(), 0, length * sizeof(WCHAR));
         if(!pszSubPathW) {
             hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
             goto cleanup;
@@ -1353,20 +2005,23 @@ cleanup:
     return hr;
 }
 
+/*************************************************************************
+ * SHGetFolderPathAndSubDirW           [SHELL32.@]
+ */
 HRESULT WINAPI SHGetFolderPathAndSubDirW(
-    HWND hwndOwner,    /* [I] owner window */
-    int nFolder,       /* [I] CSIDL identifying the folder */
-    HANDLE hToken,     /* [I] access token */
-    DWORD dwFlags,     /* [I] which path to return */
-    LPCWSTR pszSubPath,/* [I] sub directory of the specified folder */
-    LPWSTR pszPath)    /* [O] converted path */
+       HWND hwndOwner,    /* [I] owner window */
+       int nFolder,       /* [I] CSIDL identifying the folder */
+       HANDLE hToken,     /* [I] access token */
+       DWORD dwFlags,     /* [I] which path to return */
+       LPCWSTR pszSubPath,/* [I] sub directory of the specified folder */
+       LPWSTR pszPath)    /* [O] converted path */
 {
     HRESULT    hr;
     WCHAR      szBuildPath[MAX_PATH], szTemp[MAX_PATH];
-    DWORD      folder = nFolder & CSIDL_FOLDER_MASK; //FIXME
+    DWORD      folder = nFolder & CSIDL_FOLDER_MASK;
     CSIDL_Type type;
     int        ret;
-
+    
     TRACE("%p,%p,nFolder=0x%04x,%s\n", hwndOwner,pszPath,nFolder,debugstr_w(pszSubPath));
 
     /* Windows always NULL-terminates the resulting path regardless of success
@@ -1396,7 +2051,7 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
              *CSIDL_Data[folder].szDefaultPath)
             {
                 PathAddBackslashW(szTemp);
-                wcscat(szTemp, CSIDL_Data[folder].szDefaultPath);
+                strcatW(szTemp, CSIDL_Data[folder].szDefaultPath);
             }
             hr = S_OK;
             break;
@@ -1407,7 +2062,18 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
              *CSIDL_Data[folder].szDefaultPath)
             {
                 PathAddBackslashW(szTemp);
-                wcscat(szTemp, CSIDL_Data[folder].szDefaultPath);
+                strcatW(szTemp, CSIDL_Data[folder].szDefaultPath);
+            }
+            hr = S_OK;
+            break;
+        case CSIDL_Type_SystemX86Path:
+            if (!GetSystemWow64DirectoryW(szTemp, MAX_PATH)) GetSystemDirectoryW(szTemp, MAX_PATH);
+            if (CSIDL_Data[folder].szDefaultPath &&
+             !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) &&
+             *CSIDL_Data[folder].szDefaultPath)
+            {
+                PathAddBackslashW(szTemp);
+                strcatW(szTemp, CSIDL_Data[folder].szDefaultPath);
             }
             hr = S_OK;
             break;
@@ -1428,27 +2094,16 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
 
     /* Expand environment strings if necessary */
     if (*szTemp == '%')
-    {
-        DWORD ExpandRet = ExpandEnvironmentStringsW(szTemp, szBuildPath, MAX_PATH);
-
-        if (ExpandRet > MAX_PATH)
-            hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
-        else if (ExpandRet == 0)
-            hr = HRESULT_FROM_WIN32(GetLastError());
-        else
-            hr = S_OK;
-    }
+        hr = _SHExpandEnvironmentStrings(szTemp, szBuildPath);
     else
-    {
-        wcscpy(szBuildPath, szTemp);
-    }
+        strcpyW(szBuildPath, szTemp);
 
     if (FAILED(hr)) goto end;
 
     if(pszSubPath) {
-        /* make sure the new path does not exceed th bufferlength
-         * rememebr to backslash and the termination */
-        if(MAX_PATH < (wcslen(szBuildPath) + wcslen(pszSubPath) + 2)) {
+        /* make sure the new path does not exceed the buffer length
+         * and remember to backslash and terminate it */
+        if(MAX_PATH < (lstrlenW(szBuildPath) + lstrlenW(pszSubPath) + 2)) {
             hr = HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
             goto end;
         }
@@ -1457,7 +2112,7 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
     }
     /* Copy the path if it's available before we might return */
     if (SUCCEEDED(hr) && pszPath)
-        wcscpy(pszPath, szBuildPath);
+        strcpyW(pszPath, szBuildPath);
 
     /* if we don't care about existing directories we are ready */
     if(nFolder & CSIDL_FLAG_DONT_VERIFY) goto end;
@@ -1477,7 +2132,7 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
     ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, NULL);
     if (ret && ret != ERROR_ALREADY_EXISTS)
     {
-        WARN("Failed to create directory %s.\n", debugstr_w(szBuildPath));
+        ERR("Failed to create directory %s.\n", debugstr_w(szBuildPath));
         hr = E_FAIL;
         goto end;
     }
@@ -1489,16 +2144,16 @@ end:
 }
 
 /*************************************************************************
- * SHGetFolderPathA            [SHELL32.@]
+ * SHGetFolderPathA                    [SHELL32.@]
  *
  * See SHGetFolderPathW.
  */
 HRESULT WINAPI SHGetFolderPathA(
-    HWND hwndOwner,
-    int nFolder,
-    HANDLE hToken,
-    DWORD dwFlags,
-    LPSTR pszPath)
+       HWND hwndOwner,
+       int nFolder,
+       HANDLE hToken,
+       DWORD dwFlags,
+       LPSTR pszPath)
 {
     WCHAR szTemp[MAX_PATH];
     HRESULT hr;
@@ -1527,31 +2182,40 @@ static HRESULT _SHRegisterFolders(HKEY hRootKey, HANDLE hToken,
  LPCWSTR szUserShellFolderPath, LPCWSTR szShellFolderPath, const UINT folders[],
  UINT foldersLen)
 {
+    const WCHAR *szValueName;
+    WCHAR buffer[40];
     UINT i;
     WCHAR path[MAX_PATH];
     HRESULT hr = S_OK;
     HKEY hUserKey = NULL, hKey = NULL;
-    DWORD dwDisp, dwType, dwPathLen;
+    DWORD dwType, dwPathLen;
     LONG ret;
 
     TRACE("%p,%p,%s,%p,%u\n", hRootKey, hToken,
      debugstr_w(szUserShellFolderPath), folders, foldersLen);
 
-    ret = RegCreateKeyExW(hRootKey, szUserShellFolderPath, 0, NULL, 0,
-     KEY_ALL_ACCESS, NULL, &hUserKey, &dwDisp);
+    ret = RegCreateKeyW(hRootKey, szUserShellFolderPath, &hUserKey);
     if (ret)
         hr = HRESULT_FROM_WIN32(ret);
     else
     {
-        ret = RegCreateKeyExW(hRootKey, szShellFolderPath, 0, NULL, 0,
-         KEY_ALL_ACCESS, NULL, &hKey, &dwDisp);
+        ret = RegCreateKeyW(hRootKey, szShellFolderPath, &hKey);
         if (ret)
             hr = HRESULT_FROM_WIN32(ret);
     }
     for (i = 0; SUCCEEDED(hr) && i < foldersLen; i++)
     {
         dwPathLen = MAX_PATH * sizeof(WCHAR);
-        if (RegQueryValueExW(hUserKey, CSIDL_Data[folders[i]].szValueName, NULL,
+
+        /* For CSIDL_Type_User we also use the GUID if no szValueName is provided */
+        szValueName = CSIDL_Data[folders[i]].szValueName;
+        if (!szValueName && CSIDL_Data[folders[i]].type == CSIDL_Type_User)
+        {
+            StringFromGUID2( CSIDL_Data[folders[i]].id, buffer, 39 );
+            szValueName = &buffer[0];
+        }
+
+        if (RegQueryValueExW(hUserKey, szValueName, NULL,
          &dwType, (LPBYTE)path, &dwPathLen) || (dwType != REG_SZ &&
          dwType != REG_EXPAND_SZ))
         {
@@ -1562,27 +2226,31 @@ static HRESULT _SHRegisterFolders(HKEY hRootKey, HANDLE hToken,
             else if (CSIDL_Data[folders[i]].type == CSIDL_Type_AllUsers)
                 _SHGetAllUsersProfilePath(SHGFP_TYPE_DEFAULT, folders[i], path);
             else if (CSIDL_Data[folders[i]].type == CSIDL_Type_WindowsPath)
+            {
                 GetWindowsDirectoryW(path, MAX_PATH);
+                if (CSIDL_Data[folders[i]].szDefaultPath &&
+                    !IS_INTRESOURCE(CSIDL_Data[folders[i]].szDefaultPath))
+                {
+                    PathAddBackslashW(path);
+                    strcatW(path, CSIDL_Data[folders[i]].szDefaultPath);
+                }
+            }
             else
                 hr = E_FAIL;
             if (*path)
             {
-                ret = RegSetValueExW(hUserKey,
-                 CSIDL_Data[folders[i]].szValueName, 0, REG_EXPAND_SZ,
-                 (LPBYTE)path, (wcslen(path) + 1) * sizeof(WCHAR));
+                ret = RegSetValueExW(hUserKey, szValueName, 0, REG_EXPAND_SZ,
+                 (LPBYTE)path, (strlenW(path) + 1) * sizeof(WCHAR));
                 if (ret)
                     hr = HRESULT_FROM_WIN32(ret);
                 else
                 {
-                    // Don't fail if folder can't be created
-                    if (SUCCEEDED(SHGetFolderPathW(NULL, folders[i] | CSIDL_FLAG_CREATE,
-                        hToken, SHGFP_TYPE_DEFAULT, path)))
-                    {
-                        ret = RegSetValueExW(hKey, CSIDL_Data[folders[i]].szValueName, 0, REG_SZ,
-                              (LPBYTE)path, (wcslen(path) + 1) * sizeof(WCHAR));
-                        if (ret)
-                            hr = HRESULT_FROM_WIN32(ret);
-                    }
+                    hr = SHGetFolderPathW(NULL, folders[i] | CSIDL_FLAG_CREATE,
+                     hToken, SHGFP_TYPE_DEFAULT, path);
+                    ret = RegSetValueExW(hKey, szValueName, 0, REG_SZ,
+                     (LPBYTE)path, (strlenW(path) + 1) * sizeof(WCHAR));
+                    if (ret)
+                        hr = HRESULT_FROM_WIN32(ret);
                 }
             }
         }
@@ -1618,7 +2286,14 @@ static HRESULT _SHRegisterUserShellFolders(BOOL bDefault)
      CSIDL_COOKIES,
      CSIDL_HISTORY,
      CSIDL_MYPICTURES,
-     CSIDL_FONTS
+     CSIDL_FONTS,
+     CSIDL_ADMINTOOLS,
+     CSIDL_CONTACTS,
+     CSIDL_DOWNLOADS,
+     CSIDL_LINKS,
+     CSIDL_APPDATA_LOCALLOW,
+     CSIDL_SAVED_GAMES,
+     CSIDL_SEARCHES
     };
     WCHAR userShellFolderPath[MAX_PATH], shellFolderPath[MAX_PATH];
     LPCWSTR pUserShellFolderPath, pShellFolderPath;
@@ -1631,13 +2306,13 @@ static HRESULT _SHRegisterUserShellFolders(BOOL bDefault)
     {
         hToken = (HANDLE)-1;
         hRootKey = HKEY_USERS;
-        wcscpy(userShellFolderPath, DefaultW);
+        strcpyW(userShellFolderPath, DefaultW);
         PathAddBackslashW(userShellFolderPath);
-        wcscat(userShellFolderPath, szSHUserFolders);
+        strcatW(userShellFolderPath, szSHUserFolders);
         pUserShellFolderPath = userShellFolderPath;
-        wcscpy(shellFolderPath, DefaultW);
+        strcpyW(shellFolderPath, DefaultW);
         PathAddBackslashW(shellFolderPath);
-        wcscat(shellFolderPath, szSHFolders);
+        strcatW(shellFolderPath, szSHFolders);
         pShellFolderPath = shellFolderPath;
     }
     else
@@ -1665,6 +2340,10 @@ static HRESULT _SHRegisterCommonShellFolders(void)
      CSIDL_COMMON_APPDATA,
      CSIDL_COMMON_TEMPLATES,
      CSIDL_COMMON_DOCUMENTS,
+     CSIDL_COMMON_ADMINTOOLS,
+     CSIDL_COMMON_MUSIC,
+     CSIDL_COMMON_PICTURES,
+     CSIDL_COMMON_VIDEO,
     };
     HRESULT hr;
 
@@ -1678,7 +2357,7 @@ static HRESULT _SHRegisterCommonShellFolders(void)
 /* Register the default values in the registry, as some apps seem to depend
  * on their presence.  The set registered was taken from Windows XP.
  */
-EXTERN_C HRESULT SHELL_RegisterShellFolders(void)
+HRESULT SHELL_RegisterShellFolders(void)
 {
     HRESULT hr;
 
@@ -1694,34 +2373,26 @@ EXTERN_C HRESULT SHELL_RegisterShellFolders(void)
  * SHGetSpecialFolderPathA [SHELL32.@]
  */
 BOOL WINAPI SHGetSpecialFolderPathA (
-    HWND hwndOwner,
-    LPSTR szPath,
-    int nFolder,
-    BOOL bCreate)
+       HWND hwndOwner,
+       LPSTR szPath,
+       int nFolder,
+       BOOL bCreate)
 {
-    return (SHGetFolderPathA(
-        hwndOwner,
-        nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0),
-        NULL,
-        0,
-        szPath)) == S_OK ? TRUE : FALSE;
+    return SHGetFolderPathA(hwndOwner, nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0), NULL, 0,
+                            szPath) == S_OK;
 }
 
 /*************************************************************************
  * SHGetSpecialFolderPathW
  */
 BOOL WINAPI SHGetSpecialFolderPathW (
-    HWND hwndOwner,
-    LPWSTR szPath,
-    int nFolder,
-    BOOL bCreate)
+       HWND hwndOwner,
+       LPWSTR szPath,
+       int nFolder,
+       BOOL bCreate)
 {
-    return (SHGetFolderPathW(
-        hwndOwner,
-        nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0),
-        NULL,
-        0,
-        szPath)) == S_OK ? TRUE : FALSE;
+    return SHGetFolderPathW(hwndOwner, nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0), NULL, 0,
+                            szPath) == S_OK;
 }
 
 /*************************************************************************
@@ -1747,17 +2418,17 @@ BOOL WINAPI SHGetSpecialFolderPathW (
  *  virtual folders that are handled here.
  */
 HRESULT WINAPI SHGetFolderLocation(
-    HWND hwndOwner,
-    int nFolder,
-    HANDLE hToken,
-    DWORD dwReserved,
-    LPITEMIDLIST *ppidl)
+       HWND hwndOwner,
+       int nFolder,
+       HANDLE hToken,
+       DWORD dwReserved,
+       LPITEMIDLIST *ppidl)
 {
     HRESULT hr = E_INVALIDARG;
 
     TRACE("%p 0x%08x %p 0x%08x %p\n",
      hwndOwner, nFolder, hToken, dwReserved, ppidl);
-
+    
     if (!ppidl)
         return E_INVALIDARG;
     if (dwReserved)
@@ -1765,7 +2436,7 @@ HRESULT WINAPI SHGetFolderLocation(
 
     /* The virtual folders' locations are not user-dependent */
     *ppidl = NULL;
-    switch (nFolder)
+    switch (nFolder & CSIDL_FOLDER_MASK)
     {
         case CSIDL_DESKTOP:
             *ppidl = _ILCreateDesktop();
@@ -1829,16 +2500,16 @@ HRESULT WINAPI SHGetFolderLocation(
 }
 
 /*************************************************************************
- * SHGetSpecialFolderLocation        [SHELL32.@]
+ * SHGetSpecialFolderLocation          [SHELL32.@]
  *
  * NOTES
  *   In NT5, SHGetSpecialFolderLocation needs the <winntdir>/Recent
  *   directory.
  */
 HRESULT WINAPI SHGetSpecialFolderLocation(
-    HWND hwndOwner,
-    INT nFolder,
-    LPITEMIDLIST * ppidl)
+       HWND hwndOwner,
+       INT nFolder,
+       LPITEMIDLIST * ppidl)
 {
     HRESULT hr = E_INVALIDARG;