Stefan Leichter : shell32: Implement SHGetFolderPathAndSubDirA/W.

Alexandre Julliard julliard at winehq.org
Mon Apr 21 07:46:37 CDT 2008


Module: wine
Branch: master
Commit: a629a4199e388dbab941a38914ff6106b02e420a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a629a4199e388dbab941a38914ff6106b02e420a

Author: Stefan Leichter <Stefan.Leichter at camline.com>
Date:   Thu Apr 17 23:31:05 2008 +0200

shell32: Implement SHGetFolderPathAndSubDirA/W.

---

 dlls/shell32/shell32.spec |    2 +
 dlls/shell32/shellpath.c  |   86 ++++++++++++++++++++++++++++++++++++++++++--
 include/shlobj.h          |    3 ++
 3 files changed, 87 insertions(+), 4 deletions(-)

diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec
index 6c0d7d8..e054db3 100644
--- a/dlls/shell32/shell32.spec
+++ b/dlls/shell32/shell32.spec
@@ -344,6 +344,8 @@
 @ stdcall SHGetFileInfoW(ptr long ptr long long)
 @ stdcall SHGetFolderLocation(long long long long ptr)
 @ stdcall SHGetFolderPathA(long long long long ptr)
+@ stdcall SHGetFolderPathAndSubDirA(long long long long str ptr)
+@ stdcall SHGetFolderPathAndSubDirW(long long long long wstr ptr)
 @ stdcall SHGetFolderPathW(long long long long ptr)
 @ stub SHGetFreeDiskSpace
 @ stub SHGetIconOverlayIndexA
diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c
index c4ae688..abbaf19 100644
--- a/dlls/shell32/shellpath.c
+++ b/dlls/shell32/shellpath.c
@@ -1675,21 +1675,88 @@ HRESULT WINAPI SHGetFolderPathW(
 	DWORD dwFlags,     /* [I] which path to return */
 	LPWSTR pszPath)    /* [O] converted path */
 {
+    HRESULT hr =  SHGetFolderPathAndSubDirW(hwndOwner, nFolder, hToken, dwFlags, NULL, pszPath);
+    if(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
+        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+    return hr;
+}
+
+HRESULT WINAPI SHGetFolderPathAndSubDirA(
+	HWND hwndOwner,    /* [I] owner window */
+	int nFolder,       /* [I] CSIDL identifying the folder */
+	HANDLE hToken,     /* [I] access token */
+	DWORD dwFlags,     /* [I] which path to return */
+	LPCSTR pszSubPath, /* [I] sub directory of the specified folder */
+	LPSTR pszPath)     /* [O] converted path */
+{
+    int length;
+    HRESULT hr = S_OK;
+    LPWSTR pszSubPathW = NULL;
+    LPWSTR pszPathW = NULL;
+    TRACE("%08x,%08x,%s\n",nFolder, dwFlags, debugstr_w(pszSubPathW));
+
+    if(pszPath) {
+        pszPathW = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
+        if(!pszPathW) {
+            hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
+            WARN("Failed to allocate %u bytes of memory\n", MAX_PATH * sizeof(WCHAR));
+            goto cleanup;
+        }
+    }
+    TRACE("%08x,%08x,%s\n",nFolder, dwFlags, debugstr_w(pszSubPathW));
+
+    /* SHGetFolderPathAndSubDirW does not distinguish if pszSubPath isn't
+     * set (null), or an empty string.therefore call it without the parameter set
+     * if pszSubPath is an empty string
+     */
+    if (pszSubPath && pszSubPath[0]) {
+        length = MultiByteToWideChar(CP_ACP, 0, pszSubPath, -1, NULL, 0);
+        pszSubPathW = HeapAlloc(GetProcessHeap(), 0, length * sizeof(WCHAR));
+        if(!pszSubPathW) {
+            hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
+            WARN("Failed to allocate %u bytes of memory\n", length * sizeof(WCHAR));
+            goto cleanup;
+        }
+        MultiByteToWideChar(CP_ACP, 0, pszSubPath, -1, pszSubPathW, length);
+    }
+
+    hr = SHGetFolderPathAndSubDirW(hwndOwner, nFolder, hToken, dwFlags, pszSubPathW, pszPathW);
+
+    if (SUCCEEDED(hr) && pszPath)
+        WideCharToMultiByte(CP_ACP, 0, pszPathW, -1, pszPath, MAX_PATH, NULL, NULL);
+
+cleanup:
+    HeapFree(GetProcessHeap(), 0, pszPathW);
+    HeapFree(GetProcessHeap(), 0, pszSubPathW);
+    return hr;
+}
+
+HRESULT WINAPI SHGetFolderPathAndSubDirW(
+	HWND hwndOwner,    /* [I] owner window */
+	int nFolder,       /* [I] CSIDL identifying the folder */
+	HANDLE hToken,     /* [I] access token */
+	DWORD dwFlags,     /* [I] which path to return */
+	LPCWSTR pszSubPath,/* [I] sub directory of the specified folder */
+	LPWSTR pszPath)    /* [O] converted path */
+{
     HRESULT    hr;
     WCHAR      szBuildPath[MAX_PATH], szTemp[MAX_PATH];
     DWORD      folder = nFolder & CSIDL_FOLDER_MASK;
     CSIDL_Type type;
     int        ret;
     
-    TRACE("%p,%p,nFolder=0x%04x\n", hwndOwner,pszPath,nFolder);
+    TRACE("%p,%p,nFolder=0x%04x,%s\n", hwndOwner,pszPath,nFolder,debugstr_w(pszSubPath));
 
     /* Windows always NULL-terminates the resulting path regardless of success
      * or failure, so do so first
      */
     if (pszPath)
         *pszPath = '\0';
+
     if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0]))
         return E_INVALIDARG;
+    if ((SHGFP_TYPE_CURRENT != dwFlags) && (SHGFP_TYPE_DEFAULT != dwFlags))
+        return E_INVALIDARG;
     szTemp[0] = 0;
     type = CSIDL_Data[folder].type;
     switch (type)
@@ -1742,12 +1809,23 @@ HRESULT WINAPI SHGetFolderPathW(
         hr = _SHExpandEnvironmentStrings(szTemp, szBuildPath);
     else
         strcpyW(szBuildPath, szTemp);
+
+    if (FAILED(hr)) goto end;
+
+    if(pszSubPath) {
+        /* make sure the new path does not exceed th bufferlength
+         * rememebr to backslash and the termination */
+        if(MAX_PATH < (lstrlenW(szBuildPath) + lstrlenW(pszSubPath) + 2)) {
+            hr = HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
+            goto end;
+        }
+        PathAppendW(szBuildPath, pszSubPath);
+        PathRemoveBackslashW(szBuildPath);
+    }
     /* Copy the path if it's available before we might return */
     if (SUCCEEDED(hr) && pszPath)
         strcpyW(pszPath, szBuildPath);
 
-    if (FAILED(hr)) goto end;
-
     /* if we don't care about existing directories we are ready */
     if(nFolder & CSIDL_FLAG_DONT_VERIFY) goto end;
 
@@ -1758,7 +1836,7 @@ HRESULT WINAPI SHGetFolderPathW(
      */
     if (!(nFolder & CSIDL_FLAG_CREATE))
     {
-        hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+        hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
         goto end;
     }
 
diff --git a/include/shlobj.h b/include/shlobj.h
index 8dbccb7..159e85a 100644
--- a/include/shlobj.h
+++ b/include/shlobj.h
@@ -54,6 +54,9 @@ DWORD        WINAPI SHFormatDrive(HWND,UINT,UINT,UINT);
 void         WINAPI SHFree(LPVOID);
 BOOL         WINAPI GetFileNameFromBrowse(HWND,LPSTR,DWORD,LPCSTR,LPCSTR,LPCSTR,LPCSTR);
 HRESULT      WINAPI SHGetInstanceExplorer(IUnknown**);
+HRESULT      WINAPI SHGetFolderPathAndSubDirA(HWND,int,HANDLE,DWORD,LPCSTR,LPSTR);
+HRESULT      WINAPI SHGetFolderPathAndSubDirW(HWND,int,HANDLE,DWORD,LPCWSTR,LPWSTR);
+#define             SHGetFolderPathAndSubDir WINELIB_NAME_AW(SHGetFolderPathAndSubDir);
 BOOL         WINAPI SHGetPathFromIDListA(LPCITEMIDLIST,LPSTR);
 BOOL         WINAPI SHGetPathFromIDListW(LPCITEMIDLIST,LPWSTR);
 #define             SHGetPathFromIDList WINELIB_NAME_AW(SHGetPathFromIDList)




More information about the wine-cvs mailing list