Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenshellpath.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
1.7.6.1
|