[PATCH 1/2] shell32: Move retrieving folder path logic to SHGetKnownFolderPath()
Nikolay Sivov
nsivov at codeweavers.com
Sun Dec 4 14:33:08 CST 2016
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
This will need a couple of patches more to finish transition to newer API internally.
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 aa2742d..1fa5f23 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;
}
--
2.10.2
More information about the wine-patches
mailing list