[PATCH 0/1] MR10661: Draft: scrrun: Implement folder stubs
Return a new IFolder for the parent directory of This->path, reusing the existing get_parent_folder_name() helper. Return a NULL IFolder (Nothing in VBScript) for root paths. This fixes VBScript expressions such as `folder.ParentFolder & "\sub"` that previously failed with error 445 ("Object doesn't support this action") because the getter was a stub returning E_NOTIMPL. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10661
From: Francis De Brabandere <francisdb@gmail.com> Return a new IFolder for the parent directory of This->path, reusing the existing get_parent_folder_name() helper. Return a NULL IFolder (Nothing in VBScript) for root paths. This fixes VBScript expressions such as `folder.ParentFolder & "\sub"` that previously failed with error 445 ("Object doesn't support this action") because the getter was a stub returning E_NOTIMPL. --- dlls/scrrun/filesystem.c | 79 +++++++++++++++++++++------------- dlls/scrrun/tests/filesystem.c | 45 +++++++++++++++++++ 2 files changed, 95 insertions(+), 29 deletions(-) diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c index ae6c583fd06..c24e39eb543 100644 --- a/dlls/scrrun/filesystem.c +++ b/dlls/scrrun/filesystem.c @@ -199,6 +199,33 @@ static HRESULT create_foldercoll_enum(struct foldercollection*, IUnknown**); static HRESULT create_filecoll_enum(struct filecollection*, IUnknown**); static HRESULT create_drivecoll_enum(struct drivecollection*, IUnknown**); +static inline DWORD get_parent_folder_name(const WCHAR *path, DWORD len) +{ + int i; + + if(!path) + return 0; + + for(i=len-1; i>=0; i--) + if(path[i]!='/' && path[i]!='\\') + break; + + for(; i>=0; i--) + if(path[i]=='/' || path[i]=='\\') + break; + + for(; i>=0; i--) + if(path[i]!='/' && path[i]!='\\') + break; + + if(i < 0) + return 0; + + if(path[i]==':' && i==1) + i++; + return i+1; +} + static inline BOOL is_dir_data(const WIN32_FIND_DATAW *data) { return (data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && @@ -2562,8 +2589,29 @@ static HRESULT WINAPI folder_get_Drive(IFolder *iface, IDrive **drive) static HRESULT WINAPI folder_get_ParentFolder(IFolder *iface, IFolder **parent) { struct folder *This = impl_from_IFolder(iface); - FIXME("(%p)->(%p): stub\n", This, parent); - return E_NOTIMPL; + WCHAR *parent_path; + DWORD len; + HRESULT hr; + + TRACE("(%p)->(%p)\n", This, parent); + + if(!parent) + return E_POINTER; + + *parent = NULL; + + len = get_parent_folder_name(This->path, lstrlenW(This->path)); + if(!len) + return S_OK; + + if(!(parent_path = malloc((len + 1) * sizeof(WCHAR)))) + return E_OUTOFMEMORY; + memcpy(parent_path, This->path, len * sizeof(WCHAR)); + parent_path[len] = 0; + + hr = create_folder(parent_path, parent); + free(parent_path); + return hr; } static HRESULT WINAPI folder_get_Attributes(IFolder *iface, FileAttribute *attr) @@ -3296,33 +3344,6 @@ static HRESULT WINAPI filesys_GetDriveName(IFileSystem3 *iface, BSTR path, BSTR return S_OK; } -static inline DWORD get_parent_folder_name(const WCHAR *path, DWORD len) -{ - int i; - - if(!path) - return 0; - - for(i=len-1; i>=0; i--) - if(path[i]!='/' && path[i]!='\\') - break; - - for(; i>=0; i--) - if(path[i]=='/' || path[i]=='\\') - break; - - for(; i>=0; i--) - if(path[i]!='/' && path[i]!='\\') - break; - - if(i < 0) - return 0; - - if(path[i]==':' && i==1) - i++; - return i+1; -} - static HRESULT WINAPI filesys_GetParentFolderName(IFileSystem3 *iface, BSTR Path, BSTR *pbstrResult) { diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c index 5edf11824e0..3911e910b4a 100644 --- a/dlls/scrrun/tests/filesystem.c +++ b/dlls/scrrun/tests/filesystem.c @@ -1032,6 +1032,50 @@ static void test_GetFolder(void) SetCurrentDirectoryW(prev_path); } +static void test_Folder_ParentFolder(void) +{ + WCHAR windir[MAX_PATH]; + IFolder *folder, *parent, *grandparent; + BSTR str, expected; + HRESULT hr; + + GetWindowsDirectoryW(windir, MAX_PATH); + str = SysAllocString(windir); + hr = IFileSystem3_GetFolder(fs3, str, &folder); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + SysFreeString(str); + + hr = IFolder_get_ParentFolder(folder, NULL); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + parent = (void*)0xdeadbeef; + hr = IFolder_get_ParentFolder(folder, &parent); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(parent != NULL && parent != (void*)0xdeadbeef, "got parent %p\n", parent); + + str = SysAllocString(windir); + hr = IFileSystem3_GetParentFolderName(fs3, str, &expected); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + SysFreeString(str); + + hr = IFolder_get_Path(parent, &str); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpiW(str, expected), "got %s, expected %s\n", + wine_dbgstr_w(str), wine_dbgstr_w(expected)); + SysFreeString(str); + SysFreeString(expected); + + IFolder_Release(folder); + + /* Root folder: ParentFolder returns NULL. */ + grandparent = (void*)0xdeadbeef; + hr = IFolder_get_ParentFolder(parent, &grandparent); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(grandparent == NULL, "got %p, expected NULL\n", grandparent); + + IFolder_Release(parent); +} + static void _test_clone(IEnumVARIANT *enumvar, BOOL position_inherited, LONG count, int line) { HRESULT hr; @@ -2955,6 +2999,7 @@ START_TEST(filesystem) test_CopyFolder(); test_BuildPath(); test_GetFolder(); + test_Folder_ParentFolder(); test_FolderCollection(); test_FileCollection(); test_DriveCollection(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10661
participants (2)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb)