shell32: Move retrieving folder path logic to SHGetKnownFolderPath().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2016-12-04 23:33:08 +03:00 committed by Alexandre Julliard
parent 064508c0dd
commit a0c259cf56
1 changed files with 115 additions and 26 deletions

View File

@ -4704,45 +4704,134 @@ static int csidl_from_id( const KNOWNFOLDERID *id )
/*************************************************************************
* SHGetKnownFolderPath [SHELL32.@]
*/
HRESULT WINAPI SHGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD flags, HANDLE token, PWSTR *path)
HRESULT WINAPI SHGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD flags, HANDLE token, WCHAR **ret_path)
{
HRESULT hr;
WCHAR folder[MAX_PATH];
int index = csidl_from_id( rfid );
WCHAR pathW[MAX_PATH], tempW[MAX_PATH];
HRESULT hr;
CSIDL_Type type;
int ret;
int folder = csidl_from_id(rfid), shgfp_flags;
TRACE("%s, 0x%08x, %p, %p\n", debugstr_guid(rfid), flags, token, path);
TRACE("%s, 0x%08x, %p, %p\n", debugstr_guid(rfid), flags, token, ret_path);
*path = NULL;
*ret_path = NULL;
if (index < 0)
if (folder < 0)
return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
if (flags & KF_FLAG_CREATE)
index |= CSIDL_FLAG_CREATE;
if (flags & KF_FLAG_DONT_VERIFY)
index |= CSIDL_FLAG_DONT_VERIFY;
if (flags & KF_FLAG_NO_ALIAS)
index |= CSIDL_FLAG_NO_ALIAS;
if (flags & KF_FLAG_INIT)
index |= CSIDL_FLAG_PER_USER_INIT;
if (flags & ~(KF_FLAG_CREATE|KF_FLAG_DONT_VERIFY|KF_FLAG_NO_ALIAS|KF_FLAG_INIT))
if (flags & ~(KF_FLAG_CREATE|KF_FLAG_DONT_VERIFY|KF_FLAG_NO_ALIAS|
KF_FLAG_INIT|KF_FLAG_DEFAULT_PATH))
{
FIXME("flags 0x%08x not supported\n", flags);
return E_INVALIDARG;
}
hr = SHGetFolderPathW( NULL, index, token, 0, folder );
if (SUCCEEDED(hr))
shgfp_flags = flags & KF_FLAG_DEFAULT_PATH ? SHGFP_TYPE_DEFAULT : SHGFP_TYPE_CURRENT;
type = CSIDL_Data[folder].type;
switch (type)
{
*path = CoTaskMemAlloc( (strlenW( folder ) + 1) * sizeof(WCHAR) );
if (!*path)
return E_OUTOFMEMORY;
strcpyW( *path, folder );
case CSIDL_Type_Disallowed:
hr = E_INVALIDARG;
break;
case CSIDL_Type_NonExistent:
hr = S_FALSE;
break;
case CSIDL_Type_WindowsPath:
GetWindowsDirectoryW(tempW, MAX_PATH);
if (CSIDL_Data[folder].szDefaultPath &&
!IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) &&
*CSIDL_Data[folder].szDefaultPath)
{
PathAddBackslashW(tempW);
strcatW(tempW, CSIDL_Data[folder].szDefaultPath);
}
hr = S_OK;
break;
case CSIDL_Type_SystemPath:
GetSystemDirectoryW(tempW, MAX_PATH);
if (CSIDL_Data[folder].szDefaultPath &&
!IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) &&
*CSIDL_Data[folder].szDefaultPath)
{
PathAddBackslashW(tempW);
strcatW(tempW, CSIDL_Data[folder].szDefaultPath);
}
hr = S_OK;
break;
case CSIDL_Type_SystemX86Path:
if (!GetSystemWow64DirectoryW(tempW, MAX_PATH)) GetSystemDirectoryW(tempW, MAX_PATH);
if (CSIDL_Data[folder].szDefaultPath &&
!IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) &&
*CSIDL_Data[folder].szDefaultPath)
{
PathAddBackslashW(tempW);
strcatW(tempW, CSIDL_Data[folder].szDefaultPath);
}
hr = S_OK;
break;
case CSIDL_Type_CurrVer:
hr = _SHGetCurrentVersionPath(shgfp_flags, folder, tempW);
break;
case CSIDL_Type_User:
hr = _SHGetUserProfilePath(token, shgfp_flags, folder, tempW);
break;
case CSIDL_Type_AllUsers:
hr = _SHGetAllUsersProfilePath(shgfp_flags, folder, tempW);
break;
default:
FIXME("bogus type %d, please fix\n", type);
hr = E_INVALIDARG;
break;
}
/* Expand environment strings if necessary */
if (*tempW == '%')
hr = _SHExpandEnvironmentStrings(tempW, pathW);
else
strcpyW(pathW, tempW);
if (FAILED(hr))
goto failed;
/* if we don't care about existing directories we are ready */
if (flags & KF_FLAG_DONT_VERIFY) goto done;
if (PathFileExistsW(pathW)) goto done;
/* Does not exist but we are not allowed to create it. The return value
* is verified against shell32 version 6.0.
*/
if (!(flags & KF_FLAG_CREATE))
{
hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
goto done;
}
/* create directory/directories */
ret = SHCreateDirectoryExW(NULL, pathW, NULL);
if (ret && ret != ERROR_ALREADY_EXISTS)
{
ERR("Failed to create directory %s.\n", debugstr_w(pathW));
hr = E_FAIL;
goto failed;
}
TRACE("Created missing system directory %s\n", debugstr_w(pathW));
done:
TRACE("Final path is %s, %#x\n", debugstr_w(pathW), hr);
*ret_path = CoTaskMemAlloc((strlenW(pathW) + 1) * sizeof(WCHAR));
if (!*ret_path)
return E_OUTOFMEMORY;
strcpyW(*ret_path, pathW);
return hr;
failed:
TRACE("Failed to get folder path, %#x.\n", hr);
return hr;
}