Module: wine Branch: oldstable Commit: e5a36c4a3d48c941ff38421cc667a1e96e0c408f URL: http://source.winehq.org/git/wine.git/?a=commit;h=e5a36c4a3d48c941ff38421cc6...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Sun Dec 4 23:33:08 2016 +0300
shell32: Move retrieving folder path logic to SHGetKnownFolderPath().
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org (cherry picked from commit a0c259cf562b32268df86053a5e0785b1ad78cc1) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
dlls/shell32/shellpath.c | 137 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 113 insertions(+), 24 deletions(-)
diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c index cb79d6f..1c3ab59 100644 --- a/dlls/shell32/shellpath.c +++ b/dlls/shell32/shellpath.c @@ -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_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; + } + + shgfp_flags = flags & KF_FLAG_DEFAULT_PATH ? SHGFP_TYPE_DEFAULT : SHGFP_TYPE_CURRENT; + + type = CSIDL_Data[folder].type; + switch (type) + { + 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 (flags & KF_FLAG_DONT_VERIFY) - index |= CSIDL_FLAG_DONT_VERIFY; + if (FAILED(hr)) + goto failed;
- if (flags & KF_FLAG_NO_ALIAS) - index |= CSIDL_FLAG_NO_ALIAS; + /* if we don't care about existing directories we are ready */ + if (flags & KF_FLAG_DONT_VERIFY) goto done;
- if (flags & KF_FLAG_INIT) - index |= CSIDL_FLAG_PER_USER_INIT; + if (PathFileExistsW(pathW)) goto done;
- if (flags & ~(KF_FLAG_CREATE|KF_FLAG_DONT_VERIFY|KF_FLAG_NO_ALIAS|KF_FLAG_INIT)) + /* 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)) { - FIXME("flags 0x%08x not supported\n", flags); - return E_INVALIDARG; + hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); + goto done; }
- hr = SHGetFolderPathW( NULL, index, token, 0, folder ); - if (SUCCEEDED(hr)) + /* create directory/directories */ + ret = SHCreateDirectoryExW(NULL, pathW, NULL); + if (ret && ret != ERROR_ALREADY_EXISTS) { - *path = CoTaskMemAlloc( (strlenW( folder ) + 1) * sizeof(WCHAR) ); - if (!*path) - return E_OUTOFMEMORY; - strcpyW( *path, folder ); + 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; }