ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

shellpath.cpp
Go to the documentation of this file.
00001 /*
00002  * Path Functions
00003  *
00004  * Copyright 1998, 1999, 2000 Juergen Schmied
00005  * Copyright 2004 Juan Lang
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  *
00021  * NOTES:
00022  *
00023  * Many of these functions are in SHLWAPI.DLL also
00024  *
00025  */
00026 
00027 #include <precomp.h>
00028 
00029 WINE_DEFAULT_DEBUG_CHANNEL(shell);
00030 
00031 /*
00032     ########## Combining and Constructing paths ##########
00033 */
00034 
00035 /*************************************************************************
00036  * PathAppend        [SHELL32.36]
00037  */
00038 BOOL WINAPI PathAppendAW(
00039     LPVOID lpszPath1,
00040     LPCVOID lpszPath2)
00041 {
00042     if (SHELL_OsIsUnicode())
00043       return PathAppendW((LPWSTR)lpszPath1, (LPCWSTR)lpszPath2);
00044     return PathAppendA((LPSTR)lpszPath1, (LPCSTR)lpszPath2);
00045 }
00046 
00047 /*************************************************************************
00048  * PathBuildRoot        [SHELL32.30]
00049  */
00050 LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive)
00051 {
00052     if(SHELL_OsIsUnicode())
00053       return PathBuildRootW((LPWSTR)lpszPath, drive);
00054     return PathBuildRootA((LPSTR)lpszPath, drive);
00055 }
00056 
00057 /*************************************************************************
00058  * PathGetExtensionA        [internal]
00059  *
00060  * NOTES
00061  *  exported by ordinal
00062  *  return value points to the first char after the dot
00063  */
00064 static LPSTR PathGetExtensionA(LPCSTR lpszPath)
00065 {
00066     TRACE("(%s)\n",lpszPath);
00067 
00068     lpszPath = PathFindExtensionA(lpszPath);
00069     return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
00070 }
00071 
00072 /*************************************************************************
00073  * PathGetExtensionW        [internal]
00074  */
00075 static LPWSTR PathGetExtensionW(LPCWSTR lpszPath)
00076 {
00077     TRACE("(%s)\n",debugstr_w(lpszPath));
00078 
00079     lpszPath = PathFindExtensionW(lpszPath);
00080     return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
00081 }
00082 
00083 /*************************************************************************
00084  * SHPathGetExtension        [SHELL32.158]
00085  */
00086 EXTERN_C LPVOID WINAPI SHPathGetExtensionW(LPCWSTR lpszPath, DWORD void1, DWORD void2)
00087 {
00088     return PathGetExtensionW(lpszPath);
00089 }
00090 
00091 /*************************************************************************
00092  * PathRemoveFileSpec [SHELL32.35]
00093  */
00094 BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath)
00095 {
00096     if (SHELL_OsIsUnicode())
00097       return PathRemoveFileSpecW((LPWSTR)lpszPath);
00098     return PathRemoveFileSpecA((LPSTR)lpszPath);
00099 }
00100 
00101 /*
00102     Path Manipulations
00103 */
00104 
00105 /*************************************************************************
00106  * PathGetShortPathA [internal]
00107  */
00108 static void PathGetShortPathA(LPSTR pszPath)
00109 {
00110     CHAR path[MAX_PATH];
00111 
00112     TRACE("%s\n", pszPath);
00113 
00114     if (GetShortPathNameA(pszPath, path, MAX_PATH))
00115     {
00116       lstrcpyA(pszPath, path);
00117     }
00118 }
00119 
00120 /*************************************************************************
00121  * PathGetShortPathW [internal]
00122  */
00123 static void PathGetShortPathW(LPWSTR pszPath)
00124 {
00125     WCHAR path[MAX_PATH];
00126 
00127     TRACE("%s\n", debugstr_w(pszPath));
00128 
00129     if (GetShortPathNameW(pszPath, path, MAX_PATH))
00130     {
00131       wcscpy(pszPath, path);
00132     }
00133 }
00134 
00135 /*************************************************************************
00136  * PathGetShortPath [SHELL32.92]
00137  */
00138 EXTERN_C VOID WINAPI PathGetShortPathAW(LPVOID pszPath)
00139 {
00140     if(SHELL_OsIsUnicode())
00141       PathGetShortPathW((LPWSTR)pszPath);
00142     PathGetShortPathA((LPSTR)pszPath);
00143 }
00144 
00145 /*
00146     ########## Path Testing ##########
00147 */
00148 
00149 /*************************************************************************
00150  * PathIsRoot        [SHELL32.29]
00151  */
00152 BOOL WINAPI PathIsRootAW(LPCVOID lpszPath)
00153 {
00154     if (SHELL_OsIsUnicode())
00155       return PathIsRootW((LPWSTR)lpszPath);
00156     return PathIsRootA((LPSTR)lpszPath);
00157 }
00158 
00159 /*************************************************************************
00160  *  PathIsExeA        [internal]
00161  */
00162 static BOOL PathIsExeA (LPCSTR lpszPath)
00163 {
00164     LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
00165         int i;
00166         static const char * const lpszExtensions[] =
00167             {"exe", "com", "pif", "cmd", "bat", "scf", "scr", NULL };
00168 
00169     TRACE("path=%s\n",lpszPath);
00170 
00171     for(i=0; lpszExtensions[i]; i++)
00172       if (!lstrcmpiA(lpszExtension,lpszExtensions[i])) return TRUE;
00173 
00174     return FALSE;
00175 }
00176 
00177 /*************************************************************************
00178  *  PathIsExeW        [internal]
00179  */
00180 BOOL PathIsExeW (LPCWSTR lpszPath)
00181 {
00182     LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
00183         int i;
00184         static const WCHAR lpszExtensions[][4] =
00185             {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','f','\0'},
00186              {'c','m','d','\0'}, {'b','a','t','\0'}, {'s','c','f','\0'},
00187              {'s','c','r','\0'}, {'\0'} };
00188 
00189     TRACE("path=%s\n",debugstr_w(lpszPath));
00190 
00191     for(i=0; lpszExtensions[i][0]; i++)
00192       if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE;
00193 
00194     return FALSE;
00195 }
00196 
00197 /*************************************************************************
00198  *  PathIsExe        [SHELL32.43]
00199  */
00200 BOOL WINAPI PathIsExeAW (LPCVOID path)
00201 {
00202     if (SHELL_OsIsUnicode())
00203       return PathIsExeW ((LPWSTR)path);
00204     return PathIsExeA((LPSTR)path);
00205 }
00206 
00207 /*************************************************************************
00208  * PathFileExists    [SHELL32.45]
00209  */
00210 BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath)
00211 {
00212     if (SHELL_OsIsUnicode())
00213       return PathFileExistsW ((LPWSTR)lpszPath);
00214     return PathFileExistsA ((LPSTR)lpszPath);
00215 }
00216 
00217 /*************************************************************************
00218  * PathIsSameRoot    [SHELL32.650]
00219  */
00220 BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2)
00221 {
00222     if (SHELL_OsIsUnicode())
00223       return PathIsSameRootW((LPCWSTR)lpszPath1, (LPCWSTR)lpszPath2);
00224     return PathIsSameRootA((LPCSTR)lpszPath1, (LPCSTR)lpszPath2);
00225 }
00226 
00227 /*************************************************************************
00228  * IsLFNDriveA        [SHELL32.41]
00229  */
00230 EXTERN_C BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath)
00231 {
00232     DWORD    fnlen;
00233 
00234     if (!GetVolumeInformationA(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
00235     return FALSE;
00236     return fnlen > 12;
00237 }
00238 
00239 /*************************************************************************
00240  * IsLFNDriveW        [SHELL32.42]
00241  */
00242 EXTERN_C BOOL WINAPI IsLFNDriveW(LPCWSTR lpszPath)
00243 {
00244     DWORD    fnlen;
00245 
00246     if (!GetVolumeInformationW(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
00247     return FALSE;
00248     return fnlen > 12;
00249 }
00250 
00251 /*************************************************************************
00252  * IsLFNDrive        [SHELL32.119]
00253  */
00254 EXTERN_C BOOL WINAPI IsLFNDriveAW(LPCVOID lpszPath)
00255 {
00256     if (SHELL_OsIsUnicode())
00257       return IsLFNDriveW((LPCWSTR)lpszPath);
00258     return IsLFNDriveA((LPCSTR)lpszPath);
00259 }
00260 
00261 /*
00262     ########## Creating Something Unique ##########
00263 */
00264 /*************************************************************************
00265  * PathMakeUniqueNameA    [internal]
00266  */
00267 static BOOL PathMakeUniqueNameA(
00268     LPSTR lpszBuffer,
00269     DWORD dwBuffSize,
00270     LPCSTR lpszShortName,
00271     LPCSTR lpszLongName,
00272     LPCSTR lpszPathName)
00273 {
00274     FIXME("%p %u %s %s %s stub\n",
00275      lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
00276      debugstr_a(lpszLongName), debugstr_a(lpszPathName));
00277     return TRUE;
00278 }
00279 
00280 /*************************************************************************
00281  * PathMakeUniqueNameW    [internal]
00282  */
00283 static BOOL PathMakeUniqueNameW(
00284     LPWSTR lpszBuffer,
00285     DWORD dwBuffSize,
00286     LPCWSTR lpszShortName,
00287     LPCWSTR lpszLongName,
00288     LPCWSTR lpszPathName)
00289 {
00290     FIXME("%p %u %s %s %s stub\n",
00291      lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
00292      debugstr_w(lpszLongName), debugstr_w(lpszPathName));
00293     return TRUE;
00294 }
00295 
00296 /*************************************************************************
00297  * PathMakeUniqueName    [SHELL32.47]
00298  */
00299 BOOL WINAPI PathMakeUniqueNameAW(
00300     LPVOID lpszBuffer,
00301     DWORD dwBuffSize,
00302     LPCVOID lpszShortName,
00303     LPCVOID lpszLongName,
00304     LPCVOID lpszPathName)
00305 {
00306     if (SHELL_OsIsUnicode())
00307       return PathMakeUniqueNameW((LPWSTR)lpszBuffer, dwBuffSize, (LPCWSTR)lpszShortName, (LPCWSTR)lpszLongName, (LPCWSTR)lpszPathName);
00308     return PathMakeUniqueNameA((LPSTR)lpszBuffer, dwBuffSize, (LPCSTR)lpszShortName, (LPCSTR)lpszLongName, (LPCSTR)lpszPathName);
00309 }
00310 
00311 /*************************************************************************
00312  * PathYetAnotherMakeUniqueName [SHELL32.75]
00313  *
00314  * NOTES
00315  *     exported by ordinal
00316  */
00317 BOOL WINAPI PathYetAnotherMakeUniqueName(
00318     LPWSTR lpszBuffer,
00319     LPCWSTR lpszPathName,
00320     LPCWSTR lpszShortName,
00321     LPCWSTR lpszLongName)
00322 {
00323     FIXME("(%p, %s, %s ,%s):stub.\n",
00324           lpszBuffer, debugstr_w(lpszPathName), debugstr_w(lpszShortName), debugstr_w(lpszLongName));
00325     return TRUE;
00326 }
00327 
00328 
00329 /*
00330     ########## cleaning and resolving paths ##########
00331  */
00332 
00333 /*************************************************************************
00334  * PathCleanupSpec    [SHELL32.171]
00335  *
00336  * lpszFile is changed in place.
00337  */
00338 int WINAPI PathCleanupSpec( LPCWSTR lpszPathW, LPWSTR lpszFileW )
00339 {
00340     int i = 0;
00341     DWORD rc = 0;
00342     int length = 0;
00343 
00344     if (SHELL_OsIsUnicode())
00345     {
00346         LPWSTR p = lpszFileW;
00347 
00348         TRACE("Cleanup %s\n",debugstr_w(lpszFileW));
00349 
00350         if (lpszPathW)
00351             length = wcslen(lpszPathW);
00352 
00353         while (*p)
00354         {
00355             int gct = PathGetCharTypeW(*p);
00356             if (gct == GCT_INVALID || gct == GCT_WILD || gct == GCT_SEPARATOR)
00357             {
00358                 lpszFileW[i]='-';
00359                 rc |= PCS_REPLACEDCHAR;
00360             }
00361             else
00362                 lpszFileW[i]=*p;
00363             i++;
00364             p++;
00365             if (length + i == MAX_PATH)
00366             {
00367                 rc |= PCS_FATAL | PCS_PATHTOOLONG;
00368                 break;
00369             }
00370         }
00371         lpszFileW[i]=0;
00372     }
00373     else
00374     {
00375         LPSTR lpszFileA = (LPSTR)lpszFileW;
00376         LPCSTR lpszPathA = (LPCSTR)lpszPathW;
00377         LPSTR p = lpszFileA;
00378 
00379         TRACE("Cleanup %s\n",debugstr_a(lpszFileA));
00380 
00381         if (lpszPathA)
00382             length = strlen(lpszPathA);
00383 
00384         while (*p)
00385         {
00386             int gct = PathGetCharTypeA(*p);
00387             if (gct == GCT_INVALID || gct == GCT_WILD || gct == GCT_SEPARATOR)
00388             {
00389                 lpszFileA[i]='-';
00390                 rc |= PCS_REPLACEDCHAR;
00391             }
00392             else
00393                 lpszFileA[i]=*p;
00394             i++;
00395             p++;
00396             if (length + i == MAX_PATH)
00397             {
00398                 rc |= PCS_FATAL | PCS_PATHTOOLONG;
00399                 break;
00400             }
00401         }
00402         lpszFileA[i]=0;
00403     }
00404     return rc;
00405 }
00406 
00407 /*************************************************************************
00408  * PathQualifyA        [SHELL32]
00409  */
00410 static BOOL PathQualifyA(LPCSTR pszPath)
00411 {
00412     FIXME("%s\n",pszPath);
00413     return 0;
00414 }
00415 
00416 /*************************************************************************
00417  * PathQualifyW        [SHELL32]
00418  */
00419 static BOOL PathQualifyW(LPCWSTR pszPath)
00420 {
00421     FIXME("%s\n",debugstr_w(pszPath));
00422     return 0;
00423 }
00424 
00425 /*************************************************************************
00426  * PathQualify    [SHELL32.49]
00427  */
00428 BOOL WINAPI PathQualifyAW(LPCVOID pszPath)
00429 {
00430     if (SHELL_OsIsUnicode())
00431       return PathQualifyW((LPCWSTR)pszPath);
00432     return PathQualifyA((LPCSTR)pszPath);
00433 }
00434 
00435 /*************************************************************************
00436  * PathResolveA [SHELL32.51]
00437  */
00438 static BOOL PathResolveA(
00439     LPSTR lpszPath,
00440     LPCSTR *alpszPaths,
00441     DWORD dwFlags)
00442 {
00443     FIXME("(%s,%p,0x%08x),stub!\n",
00444       lpszPath, *alpszPaths, dwFlags);
00445     return 0;
00446 }
00447 
00448 /*************************************************************************
00449  * PathResolveW [SHELL32]
00450  */
00451 static BOOL PathResolveW(
00452     LPWSTR lpszPath,
00453     LPCWSTR *alpszPaths,
00454     DWORD dwFlags)
00455 {
00456     FIXME("(%s,%p,0x%08x),stub!\n",
00457       debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
00458     return 0;
00459 }
00460 
00461 /*************************************************************************
00462  * PathResolve [SHELL32.51]
00463  */
00464 BOOL WINAPI PathResolveAW(
00465     LPVOID lpszPath,
00466     LPCVOID *alpszPaths,
00467     DWORD dwFlags)
00468 {
00469     if (SHELL_OsIsUnicode())
00470       return PathResolveW((LPWSTR)lpszPath, (LPCWSTR *)alpszPaths, dwFlags);
00471     return PathResolveA((LPSTR)lpszPath, (LPCSTR *)alpszPaths, dwFlags);
00472 }
00473 
00474 /*************************************************************************
00475 *    PathProcessCommandA    [SHELL32.653]
00476 */
00477 static LONG PathProcessCommandA (
00478     LPCSTR lpszPath,
00479     LPSTR lpszBuff,
00480     DWORD dwBuffSize,
00481     DWORD dwFlags)
00482 {
00483     FIXME("%s %p 0x%04x 0x%04x stub\n",
00484     lpszPath, lpszBuff, dwBuffSize, dwFlags);
00485     if(!lpszPath) return -1;
00486     if(lpszBuff) strcpy(lpszBuff, lpszPath);
00487     return strlen(lpszPath);
00488 }
00489 
00490 /*************************************************************************
00491 *    PathProcessCommandW
00492 */
00493 static LONG PathProcessCommandW (
00494     LPCWSTR lpszPath,
00495     LPWSTR lpszBuff,
00496     DWORD dwBuffSize,
00497     DWORD dwFlags)
00498 {
00499     FIXME("(%s, %p, 0x%04x, 0x%04x) stub\n",
00500     debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
00501     if(!lpszPath) return -1;
00502     if(lpszBuff) wcscpy(lpszBuff, lpszPath);
00503     return wcslen(lpszPath);
00504 }
00505 
00506 /*************************************************************************
00507 *    PathProcessCommand (SHELL32.653)
00508 */
00509 LONG WINAPI PathProcessCommandAW (
00510     LPCVOID lpszPath,
00511     LPVOID lpszBuff,
00512     DWORD dwBuffSize,
00513     DWORD dwFlags)
00514 {
00515     if (SHELL_OsIsUnicode())
00516       return PathProcessCommandW((LPCWSTR)lpszPath, (LPWSTR)lpszBuff, dwBuffSize, dwFlags);
00517     return PathProcessCommandA((LPCSTR)lpszPath, (LPSTR)lpszBuff, dwBuffSize, dwFlags);
00518 }
00519 
00520 /*
00521     ########## special ##########
00522 */
00523 
00524 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'};
00525 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'};
00526 static const WCHAR AppDataW[] = {'A','p','p','D','a','t','a','\0'};
00527 static const WCHAR CacheW[] = {'C','a','c','h','e','\0'};
00528 static const WCHAR CD_BurningW[] = {'C','D',' ','B','u','r','n','i','n','g','\0'};
00529 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'};
00530 static const WCHAR Common_AppDataW[] = {'C','o','m','m','o','n',' ','A','p','p','D','a','t','a','\0'};
00531 static const WCHAR Common_DesktopW[] = {'C','o','m','m','o','n',' ','D','e','s','k','t','o','p','\0'};
00532 static const WCHAR Common_DocumentsW[] = {'C','o','m','m','o','n',' ','D','o','c','u','m','e','n','t','s','\0'};
00533 static const WCHAR CommonFilesDirW[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r','\0'};
00534 static const WCHAR CommonMusicW[] = {'C','o','m','m','o','n','M','u','s','i','c','\0'};
00535 static const WCHAR CommonPicturesW[] = {'C','o','m','m','o','n','P','i','c','t','u','r','e','s','\0'};
00536 static const WCHAR Common_ProgramsW[] = {'C','o','m','m','o','n',' ','P','r','o','g','r','a','m','s','\0'};
00537 static const WCHAR Common_StartUpW[] = {'C','o','m','m','o','n',' ','S','t','a','r','t','U','p','\0'};
00538 static const WCHAR Common_Start_MenuW[] = {'C','o','m','m','o','n',' ','S','t','a','r','t',' ','M','e','n','u','\0'};
00539 static const WCHAR Common_TemplatesW[] = {'C','o','m','m','o','n',' ','T','e','m','p','l','a','t','e','s','\0'};
00540 static const WCHAR CommonVideoW[] = {'C','o','m','m','o','n','V','i','d','e','o','\0'};
00541 static const WCHAR CookiesW[] = {'C','o','o','k','i','e','s','\0'};
00542 static const WCHAR DesktopW[] = {'D','e','s','k','t','o','p','\0'};
00543 static const WCHAR FavoritesW[] = {'F','a','v','o','r','i','t','e','s','\0'};
00544 static const WCHAR FontsW[] = {'F','o','n','t','s','\0'};
00545 static const WCHAR HistoryW[] = {'H','i','s','t','o','r','y','\0'};
00546 static const WCHAR Local_AppDataW[] = {'L','o','c','a','l',' ','A','p','p','D','a','t','a','\0'};
00547 static const WCHAR My_MusicW[] = {'M','y',' ','M','u','s','i','c','\0'};
00548 static const WCHAR My_PicturesW[] = {'M','y',' ','P','i','c','t','u','r','e','s','\0'};
00549 static const WCHAR My_VideoW[] = {'M','y',' ','V','i','d','e','o','\0'};
00550 static const WCHAR NetHoodW[] = {'N','e','t','H','o','o','d','\0'};
00551 static const WCHAR PersonalW[] = {'P','e','r','s','o','n','a','l','\0'};
00552 static const WCHAR PrintHoodW[] = {'P','r','i','n','t','H','o','o','d','\0'};
00553 static const WCHAR ProgramFilesDirW[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r','\0'};
00554 static const WCHAR ProgramsW[] = {'P','r','o','g','r','a','m','s','\0'};
00555 static const WCHAR RecentW[] = {'R','e','c','e','n','t','\0'};
00556 static const WCHAR ResourcesW[] = {'R','e','s','o','u','r','c','e','s','\0'};
00557 static const WCHAR SendToW[] = {'S','e','n','d','T','o','\0'};
00558 static const WCHAR StartUpW[] = {'S','t','a','r','t','U','p','\0'};
00559 static const WCHAR Start_MenuW[] = {'S','t','a','r','t',' ','M','e','n','u','\0'};
00560 static const WCHAR TemplatesW[] = {'T','e','m','p','l','a','t','e','s','\0'};
00561 static const WCHAR DefaultW[] = {'.','D','e','f','a','u','l','t','\0'};
00562 static const WCHAR AllUsersProfileW[] = {'%','A','L','L','U','S','E','R','S','P','R','O','F','I','L','E','%','\0'};
00563 static const WCHAR UserProfileW[] = {'%','U','S','E','R','P','R','O','F','I','L','E','%','\0'};
00564 static const WCHAR SystemDriveW[] = {'%','S','y','s','t','e','m','D','r','i','v','e','%','\0'};
00565 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};
00566 static const WCHAR ProfilesDirectoryW[] = {'P','r','o','f','i','l','e','s','D','i','r','e','c','t','o','r','y',0};
00567 static const WCHAR AllUsersProfileValueW[] = {'A','l','l','U','s','e','r','s','P','r','o','f','i','l','e','\0'};
00568 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'};
00569 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'};
00570 /* This defaults to L"Documents and Settings" on Windows 2000/XP, but we're
00571  * acting more Windows 9x-like for now.
00572  */
00573 static const WCHAR szDefaultProfileDirW[] = {'p','r','o','f','i','l','e','s','\0'};
00574 static const WCHAR AllUsersW[] = {'A','l','l',' ','U','s','e','r','s','\0'};
00575 
00576 typedef enum _CSIDL_Type {
00577     CSIDL_Type_User,
00578     CSIDL_Type_AllUsers,
00579     CSIDL_Type_CurrVer,
00580     CSIDL_Type_Disallowed,
00581     CSIDL_Type_NonExistent,
00582     CSIDL_Type_WindowsPath,
00583     CSIDL_Type_SystemPath,
00584 } CSIDL_Type;
00585 
00586 typedef struct
00587 {
00588     CSIDL_Type type;
00589     LPCWSTR    szValueName;
00590     LPCWSTR    szDefaultPath; /* fallback string or resource ID */
00591 } CSIDL_DATA;
00592 
00593 static const CSIDL_DATA CSIDL_Data[] =
00594 {
00595     { /* 0x00 - CSIDL_DESKTOP */
00596         CSIDL_Type_User,
00597         DesktopW,
00598         MAKEINTRESOURCEW(IDS_DESKTOPDIRECTORY)
00599     },
00600     { /* 0x01 - CSIDL_INTERNET */
00601         CSIDL_Type_Disallowed,
00602         NULL,
00603         NULL
00604     },
00605     { /* 0x02 - CSIDL_PROGRAMS */
00606         CSIDL_Type_User,
00607         ProgramsW,
00608         MAKEINTRESOURCEW(IDS_PROGRAMS)
00609     },
00610     { /* 0x03 - CSIDL_CONTROLS (.CPL files) */
00611         CSIDL_Type_SystemPath,
00612         NULL,
00613         NULL
00614     },
00615     { /* 0x04 - CSIDL_PRINTERS */
00616         CSIDL_Type_SystemPath,
00617         NULL,
00618         NULL
00619     },
00620     { /* 0x05 - CSIDL_PERSONAL */
00621         CSIDL_Type_User,
00622         PersonalW,
00623         MAKEINTRESOURCEW(IDS_PERSONAL)
00624     },
00625     { /* 0x06 - CSIDL_FAVORITES */
00626         CSIDL_Type_User,
00627         FavoritesW,
00628         MAKEINTRESOURCEW(IDS_FAVORITES)
00629     },
00630     { /* 0x07 - CSIDL_STARTUP */
00631         CSIDL_Type_User,
00632         StartUpW,
00633         MAKEINTRESOURCEW(IDS_STARTUP)
00634     },
00635     { /* 0x08 - CSIDL_RECENT */
00636         CSIDL_Type_User,
00637         RecentW,
00638         MAKEINTRESOURCEW(IDS_RECENT)
00639     },
00640     { /* 0x09 - CSIDL_SENDTO */
00641         CSIDL_Type_User,
00642         SendToW,
00643         MAKEINTRESOURCEW(IDS_SENDTO)
00644     },
00645     { /* 0x0a - CSIDL_BITBUCKET - Recycle Bin */
00646         CSIDL_Type_Disallowed,
00647         NULL,
00648         NULL,
00649     },
00650     { /* 0x0b - CSIDL_STARTMENU */
00651         CSIDL_Type_User,
00652         Start_MenuW,
00653         MAKEINTRESOURCEW(IDS_STARTMENU)
00654     },
00655     { /* 0x0c - CSIDL_MYDOCUMENTS */
00656         CSIDL_Type_Disallowed, /* matches WinXP--can't get its path */
00657         NULL,
00658         NULL
00659     },
00660     { /* 0x0d - CSIDL_MYMUSIC */
00661         CSIDL_Type_User,
00662         My_MusicW,
00663         MAKEINTRESOURCEW(IDS_MYMUSIC)
00664     },
00665     { /* 0x0e - CSIDL_MYVIDEO */
00666         CSIDL_Type_User,
00667         My_VideoW,
00668         MAKEINTRESOURCEW(IDS_MYVIDEO)
00669     },
00670     { /* 0x0f - unassigned */
00671         CSIDL_Type_Disallowed,
00672         NULL,
00673         NULL,
00674     },
00675     { /* 0x10 - CSIDL_DESKTOPDIRECTORY */
00676         CSIDL_Type_User,
00677         DesktopW,
00678         MAKEINTRESOURCEW(IDS_DESKTOPDIRECTORY)
00679     },
00680     { /* 0x11 - CSIDL_DRIVES */
00681         CSIDL_Type_Disallowed,
00682         NULL,
00683         NULL,
00684     },
00685     { /* 0x12 - CSIDL_NETWORK */
00686         CSIDL_Type_Disallowed,
00687         NULL,
00688         NULL,
00689     },
00690     { /* 0x13 - CSIDL_NETHOOD */
00691         CSIDL_Type_User,
00692         NetHoodW,
00693         MAKEINTRESOURCEW(IDS_NETHOOD)
00694     },
00695     { /* 0x14 - CSIDL_FONTS */
00696         CSIDL_Type_WindowsPath,
00697         FontsW,
00698         FontsW
00699     },
00700     { /* 0x15 - CSIDL_TEMPLATES */
00701         CSIDL_Type_User,
00702         TemplatesW,
00703         MAKEINTRESOURCEW(IDS_TEMPLATES)
00704     },
00705     { /* 0x16 - CSIDL_COMMON_STARTMENU */
00706         CSIDL_Type_AllUsers,
00707         Common_Start_MenuW,
00708         MAKEINTRESOURCEW(IDS_STARTMENU)
00709     },
00710     { /* 0x17 - CSIDL_COMMON_PROGRAMS */
00711         CSIDL_Type_AllUsers,
00712         Common_ProgramsW,
00713         MAKEINTRESOURCEW(IDS_PROGRAMS)
00714     },
00715     { /* 0x18 - CSIDL_COMMON_STARTUP */
00716         CSIDL_Type_AllUsers,
00717         Common_StartUpW,
00718         MAKEINTRESOURCEW(IDS_STARTUP)
00719     },
00720     { /* 0x19 - CSIDL_COMMON_DESKTOPDIRECTORY */
00721         CSIDL_Type_AllUsers,
00722         Common_DesktopW,
00723         MAKEINTRESOURCEW(IDS_DESKTOP)
00724     },
00725     { /* 0x1a - CSIDL_APPDATA */
00726         CSIDL_Type_User,
00727         AppDataW,
00728         MAKEINTRESOURCEW(IDS_APPDATA)
00729     },
00730     { /* 0x1b - CSIDL_PRINTHOOD */
00731         CSIDL_Type_User,
00732         PrintHoodW,
00733         MAKEINTRESOURCEW(IDS_PRINTHOOD)
00734     },
00735     { /* 0x1c - CSIDL_LOCAL_APPDATA */
00736         CSIDL_Type_User,
00737         Local_AppDataW,
00738         MAKEINTRESOURCEW(IDS_LOCAL_APPDATA)
00739     },
00740     { /* 0x1d - CSIDL_ALTSTARTUP */
00741         CSIDL_Type_NonExistent,
00742         NULL,
00743         NULL
00744     },
00745     { /* 0x1e - CSIDL_COMMON_ALTSTARTUP */
00746         CSIDL_Type_NonExistent,
00747         NULL,
00748         NULL
00749     },
00750     { /* 0x1f - CSIDL_COMMON_FAVORITES */
00751         CSIDL_Type_AllUsers,
00752         FavoritesW,
00753         MAKEINTRESOURCEW(IDS_FAVORITES)
00754     },
00755     { /* 0x20 - CSIDL_INTERNET_CACHE */
00756         CSIDL_Type_User,
00757         CacheW,
00758         MAKEINTRESOURCEW(IDS_INTERNET_CACHE)
00759     },
00760     { /* 0x21 - CSIDL_COOKIES */
00761         CSIDL_Type_User,
00762         CookiesW,
00763         MAKEINTRESOURCEW(IDS_COOKIES)
00764     },
00765     { /* 0x22 - CSIDL_HISTORY */
00766         CSIDL_Type_User,
00767         HistoryW,
00768         MAKEINTRESOURCEW(IDS_HISTORY)
00769     },
00770     { /* 0x23 - CSIDL_COMMON_APPDATA */
00771         CSIDL_Type_AllUsers,
00772         Common_AppDataW,
00773         MAKEINTRESOURCEW(IDS_APPDATA)
00774     },
00775     { /* 0x24 - CSIDL_WINDOWS */
00776         CSIDL_Type_WindowsPath,
00777         NULL,
00778         NULL
00779     },
00780     { /* 0x25 - CSIDL_SYSTEM */
00781         CSIDL_Type_SystemPath,
00782         NULL,
00783         NULL
00784     },
00785     { /* 0x26 - CSIDL_PROGRAM_FILES */
00786         CSIDL_Type_CurrVer,
00787         ProgramFilesDirW,
00788         MAKEINTRESOURCEW(IDS_PROGRAM_FILES)
00789     },
00790     { /* 0x27 - CSIDL_MYPICTURES */
00791         CSIDL_Type_User,
00792         My_PicturesW,
00793         MAKEINTRESOURCEW(IDS_MYPICTURES)
00794     },
00795     { /* 0x28 - CSIDL_PROFILE */
00796         CSIDL_Type_User,
00797         NULL,
00798         NULL
00799     },
00800     { /* 0x29 - CSIDL_SYSTEMX86 */
00801         CSIDL_Type_NonExistent,
00802         NULL,
00803         NULL
00804     },
00805     { /* 0x2a - CSIDL_PROGRAM_FILESX86 */
00806         CSIDL_Type_NonExistent,
00807         NULL,
00808         NULL
00809     },
00810     { /* 0x2b - CSIDL_PROGRAM_FILES_COMMON */
00811         CSIDL_Type_CurrVer,
00812         CommonFilesDirW,
00813         MAKEINTRESOURCEW(IDS_PROGRAM_FILES_COMMON)
00814     },
00815     { /* 0x2c - CSIDL_PROGRAM_FILES_COMMONX86 */
00816         CSIDL_Type_NonExistent,
00817         NULL,
00818         NULL
00819     },
00820     { /* 0x2d - CSIDL_COMMON_TEMPLATES */
00821         CSIDL_Type_AllUsers,
00822         Common_TemplatesW,
00823         MAKEINTRESOURCEW(IDS_TEMPLATES)
00824     },
00825     { /* 0x2e - CSIDL_COMMON_DOCUMENTS */
00826         CSIDL_Type_AllUsers,
00827         Common_DocumentsW,
00828         MAKEINTRESOURCEW(IDS_COMMON_DOCUMENTS)
00829     },
00830     { /* 0x2f - CSIDL_COMMON_ADMINTOOLS */
00831         CSIDL_Type_AllUsers,
00832         Common_Administrative_ToolsW,
00833         MAKEINTRESOURCEW(IDS_ADMINTOOLS)
00834     },
00835     { /* 0x30 - CSIDL_ADMINTOOLS */
00836         CSIDL_Type_User,
00837         Administrative_ToolsW,
00838         MAKEINTRESOURCEW(IDS_ADMINTOOLS)
00839     },
00840     { /* 0x31 - CSIDL_CONNECTIONS */
00841         CSIDL_Type_Disallowed,
00842         NULL,
00843         NULL
00844     },
00845     { /* 0x32 - unassigned */
00846         CSIDL_Type_Disallowed,
00847         NULL,
00848         NULL
00849     },
00850     { /* 0x33 - unassigned */
00851         CSIDL_Type_Disallowed,
00852         NULL,
00853         NULL
00854     },
00855     { /* 0x34 - unassigned */
00856         CSIDL_Type_Disallowed,
00857         NULL,
00858         NULL
00859     },
00860     { /* 0x35 - CSIDL_COMMON_MUSIC */
00861         CSIDL_Type_AllUsers,
00862         CommonMusicW,
00863         MAKEINTRESOURCEW(IDS_COMMON_MUSIC)
00864     },
00865     { /* 0x36 - CSIDL_COMMON_PICTURES */
00866         CSIDL_Type_AllUsers,
00867         CommonPicturesW,
00868         MAKEINTRESOURCEW(IDS_COMMON_PICTURES)
00869     },
00870     { /* 0x37 - CSIDL_COMMON_VIDEO */
00871         CSIDL_Type_AllUsers,
00872         CommonVideoW,
00873         MAKEINTRESOURCEW(IDS_COMMON_VIDEO)
00874     },
00875     { /* 0x38 - CSIDL_RESOURCES */
00876         CSIDL_Type_WindowsPath,
00877         NULL,
00878         ResourcesW
00879     },
00880     { /* 0x39 - CSIDL_RESOURCES_LOCALIZED */
00881         CSIDL_Type_NonExistent,
00882         NULL,
00883         NULL
00884     },
00885     { /* 0x3a - CSIDL_COMMON_OEM_LINKS */
00886         CSIDL_Type_NonExistent,
00887         NULL,
00888         NULL
00889     },
00890     { /* 0x3b - CSIDL_CDBURN_AREA */
00891         CSIDL_Type_User,
00892         CD_BurningW,
00893         MAKEINTRESOURCEW(IDS_CDBURN_AREA)
00894     },
00895     { /* 0x3c unassigned */
00896         CSIDL_Type_Disallowed,
00897         NULL,
00898         NULL
00899     },
00900     { /* 0x3d - CSIDL_COMPUTERSNEARME */
00901         CSIDL_Type_Disallowed, /* FIXME */
00902         NULL,
00903         NULL
00904     },
00905     { /* 0x3e - CSIDL_PROFILES */
00906         CSIDL_Type_Disallowed, /* oddly, this matches WinXP */
00907         NULL,
00908         NULL
00909     }
00910 };
00911 
00912 /* Gets the value named value from the registry key
00913  * rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
00914  * (or from rootKey\userPrefix\... if userPrefix is not NULL) into path, which
00915  * is assumed to be MAX_PATH WCHARs in length.
00916  * If it exists, expands the value and writes the expanded value to
00917  * rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
00918  * Returns successful error code if the value was retrieved from the registry,
00919  * and a failure otherwise.
00920  */
00921 static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix,
00922  LPCWSTR value, LPWSTR path)
00923 {
00924     HRESULT hr;
00925     WCHAR shellFolderPath[MAX_PATH], userShellFolderPath[MAX_PATH];
00926     LPCWSTR pShellFolderPath, pUserShellFolderPath;
00927     DWORD dwDisp, dwType, dwPathLen;
00928     HKEY userShellFolderKey, shellFolderKey;
00929 
00930     TRACE("%p,%s,%s,%p\n",rootKey, debugstr_w(userPrefix), debugstr_w(value),
00931      path);
00932 
00933     if (userPrefix)
00934     {
00935         wcscpy(shellFolderPath, userPrefix);
00936         PathAddBackslashW(shellFolderPath);
00937         wcscat(shellFolderPath, szSHFolders);
00938         pShellFolderPath = shellFolderPath;
00939         wcscpy(userShellFolderPath, userPrefix);
00940         PathAddBackslashW(userShellFolderPath);
00941         wcscat(userShellFolderPath, szSHUserFolders);
00942         pUserShellFolderPath = userShellFolderPath;
00943     }
00944     else
00945     {
00946         pUserShellFolderPath = szSHUserFolders;
00947         pShellFolderPath = szSHFolders;
00948     }
00949 
00950     if (RegCreateKeyExW(rootKey, pShellFolderPath, 0, NULL, 0, KEY_SET_VALUE,
00951      NULL, &shellFolderKey, &dwDisp))
00952     {
00953         TRACE("Failed to create %s\n", debugstr_w(pShellFolderPath));
00954         return E_FAIL;
00955     }
00956     if (RegCreateKeyExW(rootKey, pUserShellFolderPath, 0, NULL, 0,
00957      KEY_QUERY_VALUE, NULL, &userShellFolderKey, &dwDisp))
00958     {
00959         TRACE("Failed to create %s\n",
00960          debugstr_w(pUserShellFolderPath));
00961         RegCloseKey(shellFolderKey);
00962         return E_FAIL;
00963     }
00964 
00965     dwPathLen = MAX_PATH * sizeof(WCHAR);
00966 
00967     if (!RegQueryValueExW(userShellFolderKey, value, NULL, &dwType,
00968      (LPBYTE)path, &dwPathLen) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
00969     {
00970         LONG ret;
00971 
00972         dwPathLen /= sizeof(WCHAR);
00973 
00974         path[dwPathLen] = '\0';
00975         if (dwType == REG_EXPAND_SZ && path[0] == '%')
00976         {
00977             WCHAR szTemp[MAX_PATH];
00978 
00979             dwPathLen = ExpandEnvironmentStringsW(path, szTemp, MAX_PATH);
00980             lstrcpynW(path, szTemp, dwPathLen);
00981         }
00982 
00983         ret = RegSetValueExW(shellFolderKey, value, 0, REG_SZ, (LPBYTE)path, dwPathLen * sizeof(WCHAR));
00984         if (ret != ERROR_SUCCESS)
00985             hr = HRESULT_FROM_WIN32(ret);
00986         else
00987             hr = S_OK;
00988     }
00989     else
00990         hr = E_FAIL;
00991 
00992     RegCloseKey(shellFolderKey);
00993     RegCloseKey(userShellFolderKey);
00994     TRACE("returning 0x%08x\n", hr);
00995     return hr;
00996 }
00997 
00998 /* Gets a 'semi-expanded' default value of the CSIDL with index folder into
00999  * pszPath, based on the entries in CSIDL_Data.  By semi-expanded, I mean:
01000  * - The entry's szDefaultPath may be either a string value or an integer
01001  *   resource identifier.  In the latter case, the string value of the resource
01002  *   is written.
01003  * - Depending on the entry's type, the path may begin with an (unexpanded)
01004  *   environment variable name.  The caller is responsible for expanding
01005  *   environment strings if so desired.
01006  *   The types that are prepended with environment variables are:
01007  *   CSIDL_Type_User:     %USERPROFILE%
01008  *   CSIDL_Type_AllUsers: %ALLUSERSPROFILE%
01009  *   CSIDL_Type_CurrVer:  %SystemDrive%
01010  *   (Others might make sense too, but as yet are unneeded.)
01011  */
01012 static HRESULT _SHGetDefaultValue(BYTE folder, LPWSTR pszPath)
01013 {
01014     DWORD dwSize;
01015     HRESULT hr;
01016     HKEY hKey;
01017     WCHAR resourcePath[MAX_PATH];
01018     LPCWSTR pDefaultPath = NULL;
01019 
01020     TRACE("0x%02x,%p\n", folder, pszPath);
01021 
01022     if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0]))
01023         return E_INVALIDARG;
01024     if (!pszPath)
01025         return E_INVALIDARG;
01026 
01027 
01028     if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
01029     {
01030         /* FIXME assume MAX_PATH size */
01031         dwSize = MAX_PATH * sizeof(WCHAR);
01032         if (RegQueryValueExW(hKey, CSIDL_Data[folder].szValueName, NULL, NULL, (LPBYTE)pszPath, &dwSize) == ERROR_SUCCESS)
01033         {
01034             RegCloseKey(hKey);
01035             return S_OK;
01036         }
01037         RegCloseKey(hKey);
01038     }
01039 
01040     if (CSIDL_Data[folder].szDefaultPath &&
01041      IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath))
01042     {
01043         if (LoadStringW(shell32_hInstance,
01044          LOWORD(CSIDL_Data[folder].szDefaultPath), resourcePath, MAX_PATH))
01045         {
01046             hr = S_OK;
01047             pDefaultPath = resourcePath;
01048         }
01049         else
01050         {
01051             FIXME("(%d,%s), LoadString failed, missing translation?\n", folder,
01052              debugstr_w(pszPath));
01053             hr = E_FAIL;
01054         }
01055     }
01056     else
01057     {
01058         hr = S_OK;
01059         pDefaultPath = CSIDL_Data[folder].szDefaultPath;
01060     }
01061     if (SUCCEEDED(hr))
01062     {
01063         switch (CSIDL_Data[folder].type)
01064         {
01065             case CSIDL_Type_User:
01066                 wcscpy(pszPath, UserProfileW);
01067                 break;
01068             case CSIDL_Type_AllUsers:
01069                 wcscpy(pszPath, AllUsersProfileW);
01070                 break;
01071             case CSIDL_Type_CurrVer:
01072                 wcscpy(pszPath, SystemDriveW);
01073                 break;
01074             default:
01075                 ; /* no corresponding env. var, do nothing */
01076         }
01077         if (pDefaultPath)
01078         {
01079             PathAddBackslashW(pszPath);
01080             wcscat(pszPath, pDefaultPath);
01081         }
01082     }
01083     TRACE("returning 0x%08x\n", hr);
01084     return hr;
01085 }
01086 
01087 /* Gets the (unexpanded) value of the folder with index folder into pszPath.
01088  * The folder's type is assumed to be CSIDL_Type_CurrVer.  Its default value
01089  * can be overridden in the HKLM\\szCurrentVersion key.
01090  * If dwFlags has SHGFP_TYPE_DEFAULT set or if the value isn't overridden in
01091  * the registry, uses _SHGetDefaultValue to get the value.
01092  */
01093 static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder,
01094  LPWSTR pszPath)
01095 {
01096     HRESULT hr;
01097 
01098     TRACE("0x%08x,0x%02x,%p\n", dwFlags, folder, pszPath);
01099 
01100     if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0]))
01101         return E_INVALIDARG;
01102     if (CSIDL_Data[folder].type != CSIDL_Type_CurrVer)
01103         return E_INVALIDARG;
01104     if (!pszPath)
01105         return E_INVALIDARG;
01106 
01107     if (dwFlags & SHGFP_TYPE_DEFAULT)
01108         hr = _SHGetDefaultValue(folder, pszPath);
01109     else
01110     {
01111         HKEY hKey;
01112         DWORD dwDisp;
01113 
01114         if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szCurrentVersion, 0,
01115          NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisp))
01116             hr = E_FAIL;
01117         else
01118         {
01119             DWORD dwType, dwPathLen = MAX_PATH * sizeof(WCHAR);
01120 
01121             if (RegQueryValueExW(hKey, CSIDL_Data[folder].szValueName, NULL,
01122              &dwType, (LPBYTE)pszPath, &dwPathLen) ||
01123              (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
01124             {
01125                 hr = _SHGetDefaultValue(folder, pszPath);
01126                 dwType = REG_EXPAND_SZ;
01127                 RegSetValueExW(hKey, CSIDL_Data[folder].szValueName, 0, dwType,
01128                  (LPBYTE)pszPath, (wcslen(pszPath)+1)*sizeof(WCHAR));
01129             }
01130             else
01131             {
01132                 pszPath[dwPathLen / sizeof(WCHAR)] = '\0';
01133                 hr = S_OK;
01134             }
01135             RegCloseKey(hKey);
01136         }
01137     }
01138     TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
01139     return hr;
01140 }
01141 
01142 /* Gets the user's path (unexpanded) for the CSIDL with index folder:
01143  * If SHGFP_TYPE_DEFAULT is set, calls _SHGetDefaultValue for it.  Otherwise
01144  * calls _SHGetUserShellFolderPath for it.  Where it looks depends on hToken:
01145  * - if hToken is -1, looks in HKEY_USERS\.Default
01146  * - otherwise looks first in HKEY_CURRENT_USER, followed by HKEY_LOCAL_MACHINE
01147  *   if HKEY_CURRENT_USER doesn't contain any entries.  If both fail, finally
01148  *   calls _SHGetDefaultValue for it.
01149  */
01150 static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags, BYTE folder,
01151  LPWSTR pszPath)
01152 {
01153     HRESULT hr;
01154 
01155     TRACE("%p,0x%08x,0x%02x,%p\n", hToken, dwFlags, folder, pszPath);
01156 
01157     if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0]))
01158         return E_INVALIDARG;
01159 
01160     if (CSIDL_Data[folder].type != CSIDL_Type_User)
01161         return E_INVALIDARG;
01162 
01163     if (!pszPath)
01164         return E_INVALIDARG;
01165 
01166     if (dwFlags & SHGFP_TYPE_DEFAULT)
01167     {
01168         hr = _SHGetDefaultValue(folder, pszPath);
01169     }
01170     else
01171     {
01172         LPWSTR userPrefix;
01173         HKEY hRootKey;
01174 
01175         if (hToken == (HANDLE)-1)
01176         {
01177             /* Get the folder of the default user */
01178             hRootKey = HKEY_USERS;
01179             userPrefix = (LPWSTR)DefaultW;
01180         }
01181         else if(!hToken)
01182         {
01183             /* Get the folder of the current user */
01184             hRootKey = HKEY_CURRENT_USER;
01185             userPrefix = NULL;
01186         }
01187         else
01188         {
01189             /* Get the folder of the specified user */
01190             DWORD InfoLength;
01191             PTOKEN_USER UserInfo;
01192 
01193             hRootKey = HKEY_USERS;
01194 
01195             GetTokenInformation(hToken, TokenUser, NULL, 0, &InfoLength);
01196             UserInfo = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, InfoLength);
01197 
01198             if(!GetTokenInformation(hToken, TokenUser, UserInfo, InfoLength, &InfoLength))
01199             {
01200                 WARN("GetTokenInformation failed for %x!\n", hToken);
01201                 HeapFree(GetProcessHeap(), 0, UserInfo);
01202                 return E_FAIL;
01203             }
01204 
01205             if(!ConvertSidToStringSidW(UserInfo->User.Sid, &userPrefix))
01206             {
01207                 WARN("ConvertSidToStringSidW failed for %x!\n", hToken);
01208                 HeapFree(GetProcessHeap(), 0, UserInfo);
01209                 return E_FAIL;
01210             }
01211 
01212             HeapFree(GetProcessHeap(), 0, UserInfo);
01213         }
01214 
01215         hr = _SHGetUserShellFolderPath(hRootKey, userPrefix, CSIDL_Data[folder].szValueName, pszPath);
01216 
01217         /* Free the memory allocated by ConvertSidToStringSidW */
01218         if(hToken && hToken != (HANDLE)-1)
01219             LocalFree(userPrefix);
01220 
01221         if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE)
01222             hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, CSIDL_Data[folder].szValueName, pszPath);
01223 
01224         if (FAILED(hr))
01225             hr = _SHGetDefaultValue(folder, pszPath);
01226     }
01227 
01228     TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
01229     return hr;
01230 }
01231 
01232 /* Gets the (unexpanded) path for the CSIDL with index folder.  If dwFlags has
01233  * SHGFP_TYPE_DEFAULT set, calls _SHGetDefaultValue.  Otherwise calls
01234  * _SHGetUserShellFolderPath for it, looking only in HKEY_LOCAL_MACHINE.
01235  * If this fails, falls back to _SHGetDefaultValue.
01236  */
01237 static HRESULT _SHGetAllUsersProfilePath(DWORD dwFlags, BYTE folder,
01238  LPWSTR pszPath)
01239 {
01240     HRESULT hr;
01241 
01242     TRACE("0x%08x,0x%02x,%p\n", dwFlags, folder, pszPath);
01243 
01244     if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0]))
01245         return E_INVALIDARG;
01246     if (CSIDL_Data[folder].type != CSIDL_Type_AllUsers)
01247         return E_INVALIDARG;
01248     if (!pszPath)
01249         return E_INVALIDARG;
01250 
01251     if (dwFlags & SHGFP_TYPE_DEFAULT)
01252         hr = _SHGetDefaultValue(folder, pszPath);
01253     else
01254     {
01255         hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL,
01256          CSIDL_Data[folder].szValueName, pszPath);
01257         if (FAILED(hr))
01258             hr = _SHGetDefaultValue(folder, pszPath);
01259     }
01260     TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
01261     return hr;
01262 }
01263 
01264 /*************************************************************************
01265  * SHGetFolderPathW            [SHELL32.@]
01266  *
01267  * Convert nFolder to path.
01268  *
01269  * RETURNS
01270  *  Success: S_OK
01271  *  Failure: standard HRESULT error codes.
01272  *
01273  * NOTES
01274  * Most values can be overridden in either
01275  * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
01276  * or in the same location in HKLM.
01277  * The "Shell Folders" registry key was used in NT4 and earlier systems.
01278  * Beginning with Windows 2000, the "User Shell Folders" key is used, so
01279  * changes made to it are made to the former key too.  This synchronization is
01280  * done on-demand: not until someone requests the value of one of these paths
01281  * (by calling one of the SHGet functions) is the value synchronized.
01282  * Furthermore, the HKCU paths take precedence over the HKLM paths.
01283  */
01284 HRESULT WINAPI SHGetFolderPathW(
01285     HWND hwndOwner,    /* [I] owner window */
01286     int nFolder,       /* [I] CSIDL identifying the folder */
01287     HANDLE hToken,     /* [I] access token */
01288     DWORD dwFlags,     /* [I] which path to return */
01289     LPWSTR pszPath)    /* [O] converted path */
01290 {
01291     HRESULT hr =  SHGetFolderPathAndSubDirW(hwndOwner, nFolder, hToken, dwFlags, NULL, pszPath);
01292     if(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
01293         hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
01294     return hr;
01295 }
01296 
01297 HRESULT WINAPI SHGetFolderPathAndSubDirA(
01298     HWND hwndOwner,    /* [I] owner window */
01299     int nFolder,       /* [I] CSIDL identifying the folder */
01300     HANDLE hToken,     /* [I] access token */
01301     DWORD dwFlags,     /* [I] which path to return */
01302     LPCSTR pszSubPath, /* [I] sub directory of the specified folder */
01303     LPSTR pszPath)     /* [O] converted path */
01304 {
01305     int length;
01306     HRESULT hr = S_OK;
01307     LPWSTR pszSubPathW = NULL;
01308     LPWSTR pszPathW = NULL;
01309     TRACE("%08x,%08x,%s\n",nFolder, dwFlags, debugstr_w(pszSubPathW));
01310 
01311     if(pszPath) {
01312         pszPathW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
01313         if(!pszPathW) {
01314             hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
01315             goto cleanup;
01316         }
01317     }
01318     TRACE("%08x,%08x,%s\n",nFolder, dwFlags, debugstr_w(pszSubPathW));
01319 
01320     /* SHGetFolderPathAndSubDirW does not distinguish if pszSubPath isn't
01321      * set (null), or an empty string.therefore call it without the parameter set
01322      * if pszSubPath is an empty string
01323      */
01324     if (pszSubPath && pszSubPath[0]) {
01325         length = MultiByteToWideChar(CP_ACP, 0, pszSubPath, -1, NULL, 0);
01326         pszSubPathW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, length * sizeof(WCHAR));
01327         if(!pszSubPathW) {
01328             hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
01329             goto cleanup;
01330         }
01331         MultiByteToWideChar(CP_ACP, 0, pszSubPath, -1, pszSubPathW, length);
01332     }
01333 
01334     hr = SHGetFolderPathAndSubDirW(hwndOwner, nFolder, hToken, dwFlags, pszSubPathW, pszPathW);
01335 
01336     if (SUCCEEDED(hr) && pszPath)
01337         WideCharToMultiByte(CP_ACP, 0, pszPathW, -1, pszPath, MAX_PATH, NULL, NULL);
01338 
01339 cleanup:
01340     HeapFree(GetProcessHeap(), 0, pszPathW);
01341     HeapFree(GetProcessHeap(), 0, pszSubPathW);
01342     return hr;
01343 }
01344 
01345 HRESULT WINAPI SHGetFolderPathAndSubDirW(
01346     HWND hwndOwner,    /* [I] owner window */
01347     int nFolder,       /* [I] CSIDL identifying the folder */
01348     HANDLE hToken,     /* [I] access token */
01349     DWORD dwFlags,     /* [I] which path to return */
01350     LPCWSTR pszSubPath,/* [I] sub directory of the specified folder */
01351     LPWSTR pszPath)    /* [O] converted path */
01352 {
01353     HRESULT    hr;
01354     WCHAR      szBuildPath[MAX_PATH], szTemp[MAX_PATH];
01355     DWORD      folder = nFolder & CSIDL_FOLDER_MASK; //FIXME
01356     CSIDL_Type type;
01357     int        ret;
01358 
01359     TRACE("%p,%p,nFolder=0x%04x,%s\n", hwndOwner,pszPath,nFolder,debugstr_w(pszSubPath));
01360 
01361     /* Windows always NULL-terminates the resulting path regardless of success
01362      * or failure, so do so first
01363      */
01364     if (pszPath)
01365         *pszPath = '\0';
01366 
01367     if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0]))
01368         return E_INVALIDARG;
01369     if ((SHGFP_TYPE_CURRENT != dwFlags) && (SHGFP_TYPE_DEFAULT != dwFlags))
01370         return E_INVALIDARG;
01371     szTemp[0] = 0;
01372     type = CSIDL_Data[folder].type;
01373     switch (type)
01374     {
01375         case CSIDL_Type_Disallowed:
01376             hr = E_INVALIDARG;
01377             break;
01378         case CSIDL_Type_NonExistent:
01379             hr = S_FALSE;
01380             break;
01381         case CSIDL_Type_WindowsPath:
01382             GetWindowsDirectoryW(szTemp, MAX_PATH);
01383             if (CSIDL_Data[folder].szDefaultPath &&
01384              !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) &&
01385              *CSIDL_Data[folder].szDefaultPath)
01386             {
01387                 PathAddBackslashW(szTemp);
01388                 wcscat(szTemp, CSIDL_Data[folder].szDefaultPath);
01389             }
01390             hr = S_OK;
01391             break;
01392         case CSIDL_Type_SystemPath:
01393             GetSystemDirectoryW(szTemp, MAX_PATH);
01394             if (CSIDL_Data[folder].szDefaultPath &&
01395              !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) &&
01396              *CSIDL_Data[folder].szDefaultPath)
01397             {
01398                 PathAddBackslashW(szTemp);
01399                 wcscat(szTemp, CSIDL_Data[folder].szDefaultPath);
01400             }
01401             hr = S_OK;
01402             break;
01403         case CSIDL_Type_CurrVer:
01404             hr = _SHGetCurrentVersionPath(dwFlags, folder, szTemp);
01405             break;
01406         case CSIDL_Type_User:
01407             hr = _SHGetUserProfilePath(hToken, dwFlags, folder, szTemp);
01408             break;
01409         case CSIDL_Type_AllUsers:
01410             hr = _SHGetAllUsersProfilePath(dwFlags, folder, szTemp);
01411             break;
01412         default:
01413             FIXME("bogus type %d, please fix\n", type);
01414             hr = E_INVALIDARG;
01415             break;
01416     }
01417 
01418     /* Expand environment strings if necessary */
01419     if (*szTemp == '%')
01420     {
01421         DWORD ExpandRet = ExpandEnvironmentStringsW(szTemp, szBuildPath, MAX_PATH);
01422 
01423         if (ExpandRet > MAX_PATH)
01424             hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
01425         else if (ExpandRet == 0)
01426             hr = HRESULT_FROM_WIN32(GetLastError());
01427         else
01428             hr = S_OK;
01429     }
01430     else
01431     {
01432         wcscpy(szBuildPath, szTemp);
01433     }
01434 
01435     if (FAILED(hr)) goto end;
01436 
01437     if(pszSubPath) {
01438         /* make sure the new path does not exceed th bufferlength
01439          * rememebr to backslash and the termination */
01440         if(MAX_PATH < (wcslen(szBuildPath) + wcslen(pszSubPath) + 2)) {
01441             hr = HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
01442             goto end;
01443         }
01444         PathAppendW(szBuildPath, pszSubPath);
01445         PathRemoveBackslashW(szBuildPath);
01446     }
01447     /* Copy the path if it's available before we might return */
01448     if (SUCCEEDED(hr) && pszPath)
01449         wcscpy(pszPath, szBuildPath);
01450 
01451     /* if we don't care about existing directories we are ready */
01452     if(nFolder & CSIDL_FLAG_DONT_VERIFY) goto end;
01453 
01454     if (PathFileExistsW(szBuildPath)) goto end;
01455 
01456     /* not existing but we are not allowed to create it.  The return value
01457      * is verified against shell32 version 6.0.
01458      */
01459     if (!(nFolder & CSIDL_FLAG_CREATE))
01460     {
01461         hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
01462         goto end;
01463     }
01464 
01465     /* create directory/directories */
01466     ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, NULL);
01467     if (ret && ret != ERROR_ALREADY_EXISTS)
01468     {
01469         WARN("Failed to create directory %s.\n", debugstr_w(szBuildPath));
01470         hr = E_FAIL;
01471         goto end;
01472     }
01473 
01474     TRACE("Created missing system directory %s\n", debugstr_w(szBuildPath));
01475 end:
01476     TRACE("returning 0x%08x (final path is %s)\n", hr, debugstr_w(szBuildPath));
01477     return hr;
01478 }
01479 
01480 /*************************************************************************
01481  * SHGetFolderPathA            [SHELL32.@]
01482  *
01483  * See SHGetFolderPathW.
01484  */
01485 HRESULT WINAPI SHGetFolderPathA(
01486     HWND hwndOwner,
01487     int nFolder,
01488     HANDLE hToken,
01489     DWORD dwFlags,
01490     LPSTR pszPath)
01491 {
01492     WCHAR szTemp[MAX_PATH];
01493     HRESULT hr;
01494 
01495     TRACE("%p,%p,nFolder=0x%04x\n",hwndOwner,pszPath,nFolder);
01496 
01497     if (pszPath)
01498         *pszPath = '\0';
01499     hr = SHGetFolderPathW(hwndOwner, nFolder, hToken, dwFlags, szTemp);
01500     if (SUCCEEDED(hr) && pszPath)
01501         WideCharToMultiByte(CP_ACP, 0, szTemp, -1, pszPath, MAX_PATH, NULL,
01502          NULL);
01503 
01504     return hr;
01505 }
01506 
01507 /* For each folder in folders, if its value has not been set in the registry,
01508  * calls _SHGetUserProfilePath or _SHGetAllUsersProfilePath (depending on the
01509  * folder's type) to get the unexpanded value first.
01510  * Writes the unexpanded value to User Shell Folders, and queries it with
01511  * SHGetFolderPathW to force the creation of the directory if it doesn't
01512  * already exist.  SHGetFolderPathW also returns the expanded value, which
01513  * this then writes to Shell Folders.
01514  */
01515 static HRESULT _SHRegisterFolders(HKEY hRootKey, HANDLE hToken,
01516  LPCWSTR szUserShellFolderPath, LPCWSTR szShellFolderPath, const UINT folders[],
01517  UINT foldersLen)
01518 {
01519     UINT i;
01520     WCHAR path[MAX_PATH];
01521     HRESULT hr = S_OK;
01522     HKEY hUserKey = NULL, hKey = NULL;
01523     DWORD dwDisp, dwType, dwPathLen;
01524     LONG ret;
01525 
01526     TRACE("%p,%p,%s,%p,%u\n", hRootKey, hToken,
01527      debugstr_w(szUserShellFolderPath), folders, foldersLen);
01528 
01529     ret = RegCreateKeyExW(hRootKey, szUserShellFolderPath, 0, NULL, 0,
01530      KEY_ALL_ACCESS, NULL, &hUserKey, &dwDisp);
01531     if (ret)
01532         hr = HRESULT_FROM_WIN32(ret);
01533     else
01534     {
01535         ret = RegCreateKeyExW(hRootKey, szShellFolderPath, 0, NULL, 0,
01536          KEY_ALL_ACCESS, NULL, &hKey, &dwDisp);
01537         if (ret)
01538             hr = HRESULT_FROM_WIN32(ret);
01539     }
01540     for (i = 0; SUCCEEDED(hr) && i < foldersLen; i++)
01541     {
01542         dwPathLen = MAX_PATH * sizeof(WCHAR);
01543         if (RegQueryValueExW(hUserKey, CSIDL_Data[folders[i]].szValueName, NULL,
01544          &dwType, (LPBYTE)path, &dwPathLen) || (dwType != REG_SZ &&
01545          dwType != REG_EXPAND_SZ))
01546         {
01547             *path = '\0';
01548             if (CSIDL_Data[folders[i]].type == CSIDL_Type_User)
01549                 _SHGetUserProfilePath(hToken, SHGFP_TYPE_DEFAULT, folders[i],
01550                  path);
01551             else if (CSIDL_Data[folders[i]].type == CSIDL_Type_AllUsers)
01552                 _SHGetAllUsersProfilePath(SHGFP_TYPE_DEFAULT, folders[i], path);
01553             else if (CSIDL_Data[folders[i]].type == CSIDL_Type_WindowsPath)
01554                 GetWindowsDirectoryW(path, MAX_PATH);
01555             else
01556                 hr = E_FAIL;
01557             if (*path)
01558             {
01559                 ret = RegSetValueExW(hUserKey,
01560                  CSIDL_Data[folders[i]].szValueName, 0, REG_EXPAND_SZ,
01561                  (LPBYTE)path, (wcslen(path) + 1) * sizeof(WCHAR));
01562                 if (ret)
01563                     hr = HRESULT_FROM_WIN32(ret);
01564                 else
01565                 {
01566                     // Don't fail if folder can't be created
01567                     if (SUCCEEDED(SHGetFolderPathW(NULL, folders[i] | CSIDL_FLAG_CREATE,
01568                         hToken, SHGFP_TYPE_DEFAULT, path)))
01569                     {
01570                         ret = RegSetValueExW(hKey, CSIDL_Data[folders[i]].szValueName, 0, REG_SZ,
01571                               (LPBYTE)path, (wcslen(path) + 1) * sizeof(WCHAR));
01572                         if (ret)
01573                             hr = HRESULT_FROM_WIN32(ret);
01574                     }
01575                 }
01576             }
01577         }
01578     }
01579     if (hUserKey)
01580         RegCloseKey(hUserKey);
01581     if (hKey)
01582         RegCloseKey(hKey);
01583 
01584     TRACE("returning 0x%08x\n", hr);
01585     return hr;
01586 }
01587 
01588 static HRESULT _SHRegisterUserShellFolders(BOOL bDefault)
01589 {
01590     static const UINT folders[] = {
01591      CSIDL_PROGRAMS,
01592      CSIDL_PERSONAL,
01593      CSIDL_FAVORITES,
01594      CSIDL_APPDATA,
01595      CSIDL_STARTUP,
01596      CSIDL_RECENT,
01597      CSIDL_SENDTO,
01598      CSIDL_STARTMENU,
01599      CSIDL_MYMUSIC,
01600      CSIDL_MYVIDEO,
01601      CSIDL_DESKTOPDIRECTORY,
01602      CSIDL_NETHOOD,
01603      CSIDL_TEMPLATES,
01604      CSIDL_PRINTHOOD,
01605      CSIDL_LOCAL_APPDATA,
01606      CSIDL_INTERNET_CACHE,
01607      CSIDL_COOKIES,
01608      CSIDL_HISTORY,
01609      CSIDL_MYPICTURES,
01610      CSIDL_FONTS
01611     };
01612     WCHAR userShellFolderPath[MAX_PATH], shellFolderPath[MAX_PATH];
01613     LPCWSTR pUserShellFolderPath, pShellFolderPath;
01614     HRESULT hr = S_OK;
01615     HKEY hRootKey;
01616     HANDLE hToken;
01617 
01618     TRACE("%s\n", bDefault ? "TRUE" : "FALSE");
01619     if (bDefault)
01620     {
01621         hToken = (HANDLE)-1;
01622         hRootKey = HKEY_USERS;
01623         wcscpy(userShellFolderPath, DefaultW);
01624         PathAddBackslashW(userShellFolderPath);
01625         wcscat(userShellFolderPath, szSHUserFolders);
01626         pUserShellFolderPath = userShellFolderPath;
01627         wcscpy(shellFolderPath, DefaultW);
01628         PathAddBackslashW(shellFolderPath);
01629         wcscat(shellFolderPath, szSHFolders);
01630         pShellFolderPath = shellFolderPath;
01631     }
01632     else
01633     {
01634         hToken = NULL;
01635         hRootKey = HKEY_CURRENT_USER;
01636         pUserShellFolderPath = szSHUserFolders;
01637         pShellFolderPath = szSHFolders;
01638     }
01639 
01640     hr = _SHRegisterFolders(hRootKey, hToken, pUserShellFolderPath,
01641      pShellFolderPath, folders, sizeof(folders) / sizeof(folders[0]));
01642     TRACE("returning 0x%08x\n", hr);
01643     return hr;
01644 }
01645 
01646 static HRESULT _SHRegisterCommonShellFolders(void)
01647 {
01648     static const UINT folders[] = {
01649      CSIDL_COMMON_STARTMENU,
01650      CSIDL_COMMON_PROGRAMS,
01651      CSIDL_COMMON_STARTUP,
01652      CSIDL_COMMON_DESKTOPDIRECTORY,
01653      CSIDL_COMMON_FAVORITES,
01654      CSIDL_COMMON_APPDATA,
01655      CSIDL_COMMON_TEMPLATES,
01656      CSIDL_COMMON_DOCUMENTS,
01657     };
01658     HRESULT hr;
01659 
01660     TRACE("\n");
01661     hr = _SHRegisterFolders(HKEY_LOCAL_MACHINE, NULL, szSHUserFolders,
01662      szSHFolders, folders, sizeof(folders) / sizeof(folders[0]));
01663     TRACE("returning 0x%08x\n", hr);
01664     return hr;
01665 }
01666 
01667 /* Register the default values in the registry, as some apps seem to depend
01668  * on their presence.  The set registered was taken from Windows XP.
01669  */
01670 EXTERN_C HRESULT SHELL_RegisterShellFolders(void)
01671 {
01672     HRESULT hr;
01673 
01674     hr = _SHRegisterUserShellFolders(TRUE);
01675     if (SUCCEEDED(hr))
01676         hr = _SHRegisterUserShellFolders(FALSE);
01677     if (SUCCEEDED(hr))
01678         hr = _SHRegisterCommonShellFolders();
01679     return hr;
01680 }
01681 
01682 /*************************************************************************
01683  * SHGetSpecialFolderPathA [SHELL32.@]
01684  */
01685 BOOL WINAPI SHGetSpecialFolderPathA (
01686     HWND hwndOwner,
01687     LPSTR szPath,
01688     int nFolder,
01689     BOOL bCreate)
01690 {
01691     return (SHGetFolderPathA(
01692         hwndOwner,
01693         nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0),
01694         NULL,
01695         0,
01696         szPath)) == S_OK ? TRUE : FALSE;
01697 }
01698 
01699 /*************************************************************************
01700  * SHGetSpecialFolderPathW
01701  */
01702 BOOL WINAPI SHGetSpecialFolderPathW (
01703     HWND hwndOwner,
01704     LPWSTR szPath,
01705     int nFolder,
01706     BOOL bCreate)
01707 {
01708     return (SHGetFolderPathW(
01709         hwndOwner,
01710         nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0),
01711         NULL,
01712         0,
01713         szPath)) == S_OK ? TRUE : FALSE;
01714 }
01715 
01716 /*************************************************************************
01717  * SHGetFolderLocation [SHELL32.@]
01718  *
01719  * Gets the folder locations from the registry and creates a pidl.
01720  *
01721  * PARAMS
01722  *   hwndOwner  [I]
01723  *   nFolder    [I] CSIDL_xxxxx
01724  *   hToken     [I] token representing user, or NULL for current user, or -1 for
01725  *                  default user
01726  *   dwReserved [I] must be zero
01727  *   ppidl      [O] PIDL of a special folder
01728  *
01729  * RETURNS
01730  *  Success: S_OK
01731  *  Failure: Standard OLE-defined error result, S_FALSE or E_INVALIDARG
01732  *
01733  * NOTES
01734  *  Creates missing reg keys and directories.
01735  *  Mostly forwards to SHGetFolderPathW, but a few values of nFolder return
01736  *  virtual folders that are handled here.
01737  */
01738 HRESULT WINAPI SHGetFolderLocation(
01739     HWND hwndOwner,
01740     int nFolder,
01741     HANDLE hToken,
01742     DWORD dwReserved,
01743     LPITEMIDLIST *ppidl)
01744 {
01745     HRESULT hr = E_INVALIDARG;
01746 
01747     TRACE("%p 0x%08x %p 0x%08x %p\n",
01748      hwndOwner, nFolder, hToken, dwReserved, ppidl);
01749 
01750     if (!ppidl)
01751         return E_INVALIDARG;
01752     if (dwReserved)
01753         return E_INVALIDARG;
01754 
01755     /* The virtual folders' locations are not user-dependent */
01756     *ppidl = NULL;
01757     switch (nFolder)
01758     {
01759         case CSIDL_DESKTOP:
01760             *ppidl = _ILCreateDesktop();
01761             break;
01762 
01763         case CSIDL_PERSONAL:
01764             *ppidl = _ILCreateMyDocuments();
01765             break;
01766 
01767         case CSIDL_INTERNET:
01768             *ppidl = _ILCreateIExplore();
01769             break;
01770 
01771         case CSIDL_CONTROLS:
01772             *ppidl = _ILCreateControlPanel();
01773             break;
01774 
01775         case CSIDL_PRINTERS:
01776             *ppidl = _ILCreatePrinters();
01777             break;
01778 
01779         case CSIDL_BITBUCKET:
01780             *ppidl = _ILCreateBitBucket();
01781             break;
01782 
01783         case CSIDL_DRIVES:
01784             *ppidl = _ILCreateMyComputer();
01785             break;
01786 
01787         case CSIDL_NETWORK:
01788             *ppidl = _ILCreateNetwork();
01789             break;
01790 
01791         default:
01792         {
01793             WCHAR szPath[MAX_PATH];
01794 
01795             hr = SHGetFolderPathW(hwndOwner, nFolder, hToken,
01796              SHGFP_TYPE_CURRENT, szPath);
01797             if (SUCCEEDED(hr))
01798             {
01799                 DWORD attributes=0;
01800 
01801                 TRACE("Value=%s\n", debugstr_w(szPath));
01802                 hr = SHILCreateFromPathW(szPath, ppidl, &attributes);
01803             }
01804             else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
01805             {
01806                 /* unlike SHGetFolderPath, SHGetFolderLocation in shell32
01807                  * version 6.0 returns E_FAIL for nonexistent paths
01808                  */
01809                 hr = E_FAIL;
01810             }
01811         }
01812     }
01813     if(*ppidl)
01814         hr = NOERROR;
01815 
01816     TRACE("-- (new pidl %p)\n",*ppidl);
01817     return hr;
01818 }
01819 
01820 /*************************************************************************
01821  * SHGetSpecialFolderLocation        [SHELL32.@]
01822  *
01823  * NOTES
01824  *   In NT5, SHGetSpecialFolderLocation needs the <winntdir>/Recent
01825  *   directory.
01826  */
01827 HRESULT WINAPI SHGetSpecialFolderLocation(
01828     HWND hwndOwner,
01829     INT nFolder,
01830     LPITEMIDLIST * ppidl)
01831 {
01832     HRESULT hr = E_INVALIDARG;
01833 
01834     TRACE("(%p,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
01835 
01836     if (!ppidl)
01837         return E_INVALIDARG;
01838 
01839     hr = SHGetFolderLocation(hwndOwner, nFolder, NULL, 0, ppidl);
01840     return hr;
01841 }

Generated on Sun May 27 2012 04:26:26 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.