[PATCH v7 0/1] MR10193: dlls/comdlg32:Add the implementation of IServiceProvider_fnQueryService to obtain IFolderView2
An application adds a new button using IFileDialogCustomize_AddPushButton. The application obtains IServiceProvider_iface through QueryInterface using the parameter IFileDialogCustomize_iface of the callback function IFileDialogControlEvents_OnButtonClicked, and then uses IServiceProvider_iface to pass IID_IFolderView and IID_IFolderView2 through IServiceProvider_fnQueryService to obtain IFolderView2. After that, it obtains the selected files and folders through IFolderView2_GetSelection. Currently, the implementation of obtaining IFolderView2 through IServiceProvider_fnQueryService is missing and needs to be added. -- v7: dlls/comdlg32:Add the implementation of IServiceProvider_fnQueryService to obtain IFolderView2 https://gitlab.winehq.org/wine/wine/-/merge_requests/10193
From: panhui <panhui@uniontech.com> --- dlls/comdlg32/itemdlg.c | 4 + dlls/comdlg32/tests/itemdlg.c | 353 ++++++++++++++++++++++++++++++++++ 2 files changed, 357 insertions(+) diff --git a/dlls/comdlg32/itemdlg.c b/dlls/comdlg32/itemdlg.c index 830d88bb661..c12ae22e1c7 100644 --- a/dlls/comdlg32/itemdlg.c +++ b/dlls/comdlg32/itemdlg.c @@ -3602,6 +3602,10 @@ static HRESULT WINAPI IServiceProvider_fnQueryService(IServiceProvider *iface, hr = IExplorerBrowser_QueryInterface(This->peb, riid, ppv); else if(IsEqualGUID(guidService, &SID_SExplorerBrowserFrame)) hr = IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppv); + else if((IsEqualIID(riid, &IID_IFolderView) || IsEqualIID(riid, &IID_IFolderView2)) && This->peb) + { + hr = IExplorerBrowser_GetCurrentView(This->peb, riid, ppv); + } else FIXME("Interface %s requested from unknown service %s\n", debugstr_guid(riid), debugstr_guid(guidService)); diff --git a/dlls/comdlg32/tests/itemdlg.c b/dlls/comdlg32/tests/itemdlg.c index e31ce3592c3..6d4d5314770 100644 --- a/dlls/comdlg32/tests/itemdlg.c +++ b/dlls/comdlg32/tests/itemdlg.c @@ -356,6 +356,8 @@ static BOOL test_instantiation(void) IUnknown *punk, *unk2; HRESULT hr; LONG ref; + IFolderView *pfv; + IFolderView2 *pfv2; /* Instantiate FileOpenDialog */ hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, @@ -414,6 +416,13 @@ static BOOL test_instantiation(void) ok(hr == E_NOTIMPL || broken(hr == E_FAIL), "got 0x%08lx (expected E_NOTIMPL)\n", hr); if(SUCCEEDED(hr)) IUnknown_Release(punk); + hr = IServiceProvider_QueryService(psp, &IID_IFolderView, &IID_IFolderView, (void**)&pfv); + ok(hr == E_NOTIMPL || broken(hr == E_FAIL), "got 0x%08lx (expected E_NOTIMPL)\n", hr); + if(SUCCEEDED(hr)) IFolderView_Release(pfv); + hr = IServiceProvider_QueryService(psp, &IID_IFolderView, &IID_IFolderView2, (void**)&pfv2); + ok(hr == E_NOTIMPL || broken(hr == E_FAIL), "got 0x%08lx (expected E_NOTIMPL)\n", hr); + if(SUCCEEDED(hr)) IFolderView2_Release(pfv2); + IServiceProvider_Release(psp); } @@ -2557,6 +2566,349 @@ static void test_double_show(void) IFileDialog_Release(pfd); } +typedef struct { + IFileDialogEvents IFileDialogEvents_iface; + IFileDialogControlEvents IFileDialogControlEvents_iface; + LONG ref; + LPCWSTR button_text; + DWORD button_id; + BOOL button_clicked; + BOOL test_passed; + IFileDialog *pfd; +} ITestEventsImpl; + +static inline ITestEventsImpl *test_impl_from_IFileDialogEvents(IFileDialogEvents *iface) +{ + return CONTAINING_RECORD(iface, ITestEventsImpl, IFileDialogEvents_iface); +} + +static HRESULT WINAPI test_events_QueryInterface(IFileDialogEvents *iface, REFIID riid, void **ppv) +{ + ITestEventsImpl *This = test_impl_from_IFileDialogEvents(iface); + + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IFileDialogEvents)) + { + *ppv = &This->IFileDialogEvents_iface; + } + else if (IsEqualIID(riid, &IID_IFileDialogControlEvents)) { + *ppv = &This->IFileDialogControlEvents_iface; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI test_events_AddRef(IFileDialogEvents *iface) +{ + ITestEventsImpl *This = test_impl_from_IFileDialogEvents(iface); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI test_events_Release(IFileDialogEvents *iface) +{ + ITestEventsImpl *This = test_impl_from_IFileDialogEvents(iface); + LONG ref = InterlockedDecrement(&This->ref); + if (!ref) free(This); + return ref; +} + +static HRESULT WINAPI test_events_OnFileOk(IFileDialogEvents *iface, IFileDialog *pfd) +{ + return S_OK; +} +static HRESULT WINAPI test_events_OnFolderChanging(IFileDialogEvents *iface, IFileDialog *pfd, IShellItem *psi) +{ + return S_OK; +} +static HRESULT WINAPI test_events_OnSelectionChange(IFileDialogEvents *iface, IFileDialog *pfd) +{ + return S_OK; +} +static HRESULT WINAPI test_events_OnShareViolation(IFileDialogEvents *iface, IFileDialog *pfd, + IShellItem *psi, FDE_SHAREVIOLATION_RESPONSE *resp) +{ + return S_OK; +} +static HRESULT WINAPI test_events_OnTypeChange(IFileDialogEvents *iface, IFileDialog *pfd) +{ + return S_OK; +} +static HRESULT WINAPI test_events_OnOverwrite(IFileDialogEvents *iface, IFileDialog *pfd, + IShellItem *psi, FDE_OVERWRITE_RESPONSE *resp) +{ + return S_OK; +} + +static LRESULT CALLBACK test_control_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + +static HRESULT WINAPI test_events_OnFolderChange(IFileDialogEvents *iface, IFileDialog *pfd) +{ + ITestEventsImpl *This = test_impl_from_IFileDialogEvents(iface); + HWND hwnd; + WNDPROC oldproc; + + hwnd = get_hwnd_from_ifiledialog(pfd); + ok(hwnd != NULL, "Failed to get dialog window\n"); + + if (GetPropA(hwnd, "TEST_THIS")) return S_OK; + + IFileDialogEvents_AddRef(iface); + + oldproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC); + SetPropA(hwnd, "OLD_PROC", (HANDLE)oldproc); + SetPropA(hwnd, "TEST_THIS", (HANDLE)This); + SetPropA(hwnd, "IFD", (HANDLE)pfd); + SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)test_control_wndproc); + + PostMessageW(hwnd, WM_APP + 1, 0, 0); + + return S_OK; +} + +static const IFileDialogEventsVtbl test_events_vtbl = { + test_events_QueryInterface, + test_events_AddRef, + test_events_Release, + test_events_OnFileOk, + test_events_OnFolderChanging, + test_events_OnFolderChange, + test_events_OnSelectionChange, + test_events_OnShareViolation, + test_events_OnTypeChange, + test_events_OnOverwrite +}; + +static inline ITestEventsImpl *test_impl_from_IFileDialogControlEvents(IFileDialogControlEvents *iface) +{ + return CONTAINING_RECORD(iface, ITestEventsImpl, IFileDialogControlEvents_iface); +} + +static HRESULT WINAPI test_control_QueryInterface(IFileDialogControlEvents *iface, REFIID riid, void **ppv) +{ + ITestEventsImpl *This = test_impl_from_IFileDialogControlEvents(iface); + return IFileDialogEvents_QueryInterface(&This->IFileDialogEvents_iface, riid, ppv); +} + +static ULONG WINAPI test_control_AddRef(IFileDialogControlEvents *iface) +{ + ITestEventsImpl *This = test_impl_from_IFileDialogControlEvents(iface); + return IFileDialogEvents_AddRef(&This->IFileDialogEvents_iface); +} + +static ULONG WINAPI test_control_Release(IFileDialogControlEvents *iface) +{ + ITestEventsImpl *This = test_impl_from_IFileDialogControlEvents(iface); + return IFileDialogEvents_Release(&This->IFileDialogEvents_iface); +} + +static HRESULT WINAPI test_control_OnItemSelected(IFileDialogControlEvents *iface, + IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI test_control_OnButtonClicked(IFileDialogControlEvents *iface, + IFileDialogCustomize *pfdc, DWORD dwIDCtl) +{ + ITestEventsImpl *This = test_impl_from_IFileDialogControlEvents(iface); + IServiceProvider *psp; + IFolderView2 *pfv2; + IShellItemArray *psia; + HRESULT hr; + IFileDialog *pfd; + + ok(dwIDCtl == This->button_id, "Expected button ID %lu, got %lu\n", This->button_id, dwIDCtl); + + hr = IFileDialogCustomize_QueryInterface(pfdc, &IID_IServiceProvider, (void**)&psp); + ok(hr == S_OK, "QI for IServiceProvider failed: 0x%08lx\n", hr); + if (FAILED(hr)) + { + return S_OK; + } + + hr = IServiceProvider_QueryService(psp, &IID_IFolderView, &IID_IFolderView2, (void**)&pfv2); + ok(hr == S_OK, "QueryService for IFolderView2 failed: 0x%08lx\n", hr); + if (SUCCEEDED(hr)) + { + psia = NULL; + hr = IFolderView2_GetSelection(pfv2, TRUE, &psia); + if (hr == E_NOTIMPL) + todo_wine ok(0, "IFolderView2_GetSelection(TRUE) not implemented\n"); + else + ok(hr == S_OK, "GetSelection(TRUE) returned 0x%08lx, expected S_OK\n", hr); + + if (hr == S_OK) + { + ok(psia != NULL, "psia should not be NULL when hr == S_OK\n"); + if (psia) + { + DWORD count; + hr = IShellItemArray_GetCount(psia, &count); + ok(hr == S_OK, "GetCount failed: 0x%08lx\n", hr); + ok(count == 1, "Expected 1 item (the current folder), got %lu\n", count); + IShellItemArray_Release(psia); + } + } + IFolderView2_Release(pfv2); + } + IServiceProvider_Release(psp); + + This->test_passed = TRUE; + This->button_clicked = TRUE; + + hr = IFileDialogCustomize_QueryInterface(pfdc, &IID_IFileDialog, (void**)&pfd); + ok(hr == S_OK, "QI for IFileDialog failed: 0x%08lx\n", hr); + if (SUCCEEDED(hr)) + { + hr = IFileDialog_Close(pfd, S_FALSE); + ok(hr == S_OK, "Close failed: 0x%08lx\n", hr); + IFileDialog_Release(pfd); + } + + return S_OK; +} + +static HRESULT WINAPI test_control_OnCheckButtonToggled(IFileDialogControlEvents *iface, + IFileDialogCustomize *pfdc, + DWORD dwIDCtl, BOOL bChecked) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI test_control_OnControlActivating(IFileDialogControlEvents *iface, + IFileDialogCustomize *pfdc, + DWORD dwIDCtl) +{ + return E_NOTIMPL; +} + +static const IFileDialogControlEventsVtbl test_control_vtbl = { + test_control_QueryInterface, + test_control_AddRef, + test_control_Release, + test_control_OnItemSelected, + test_control_OnButtonClicked, + test_control_OnCheckButtonToggled, + test_control_OnControlActivating +}; + +static LRESULT CALLBACK test_control_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + WNDPROC oldproc; + switch (msg) + { + case WM_APP + 1: + SetTimer(hwnd, 1000, 100, NULL); + return 0; + + case WM_TIMER: + if (wparam == 1000) + { + ITestEventsImpl *This = (ITestEventsImpl*)GetPropA(hwnd, "TEST_THIS"); + if (This) + { + HWND btn = find_window(hwnd, L"Button", This->button_text); + if (btn) + { + SendMessageW(btn, BM_CLICK, 0, 0); + } + else + { + trace("Button not found!\n"); + } + } + KillTimer(hwnd, 1000); + oldproc = (WNDPROC)GetPropA(hwnd, "OLD_PROC"); + if (oldproc) + { + SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)oldproc); + RemovePropA(hwnd, "OLD_PROC"); + RemovePropA(hwnd, "TEST_THIS"); + RemovePropA(hwnd, "IFD"); + } + + if (This) + IFileDialogEvents_Release(&This->IFileDialogEvents_iface); + + return 0; + } + break; + } + oldproc = (WNDPROC)GetPropA(hwnd, "OLD_PROC"); + if (oldproc) + return CallWindowProcW(oldproc, hwnd, msg, wparam, lparam); + return DefWindowProcW(hwnd, msg, wparam, lparam); +} + +static void test_control_events_selection(void) +{ + IFileDialog *pfd; + IFileDialogCustomize *pfdc; + ITestEventsImpl *events; + IFileDialogEvents *pEvents; + DWORD cookie; + HRESULT hr; + static const WCHAR button_text[] = L"testButton"; + DWORD button_id = 1001; + + hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, + &IID_IFileDialog, (void**)&pfd); + ok(hr == S_OK, "CoCreateInstance failed: 0x%08lx\n", hr); + if (FAILED(hr)) return; + + hr = IFileDialog_QueryInterface(pfd, &IID_IFileDialogCustomize, (void**)&pfdc); + ok(hr == S_OK, "QI for IFileDialogCustomize failed: 0x%08lx\n", hr); + if (FAILED(hr)) + { + IFileDialog_Release(pfd); + return; + } + + hr = IFileDialogCustomize_AddPushButton(pfdc, button_id, button_text); + ok(hr == S_OK, "AddPushButton failed: 0x%08lx\n", hr); + + events = calloc(1, sizeof(*events)); + events->IFileDialogEvents_iface.lpVtbl = &test_events_vtbl; + events->IFileDialogControlEvents_iface.lpVtbl = &test_control_vtbl; + events->ref = 1; + events->button_text = button_text; + events->button_id = button_id; + events->pfd = pfd; + pEvents = &events->IFileDialogEvents_iface; + + hr = IFileDialog_Advise(pfd, pEvents, &cookie); + ok(hr == S_OK, "Advise failed: 0x%08lx\n", hr); + + { + IShellItem *psi; + WCHAR path[MAX_PATH]; + GetCurrentDirectoryW(MAX_PATH, path); + hr = pSHCreateItemFromParsingName(path, NULL, &IID_IShellItem, (void**)&psi); + if (SUCCEEDED(hr)) + { + IFileDialog_SetFolder(pfd, psi); + IShellItem_Release(psi); + } + } + + hr = IFileDialog_Show(pfd, NULL); + ok(hr == S_FALSE || hr == HRESULT_FROM_WIN32(ERROR_CANCELLED), + "Show returned 0x%08lx (expected S_FALSE or ERROR_CANCELLED)\n", hr); + + ok(events->button_clicked, "Button was not clicked\n"); + ok(events->test_passed, "Test in OnButtonClicked failed\n"); + + IFileDialog_Unadvise(pfd, cookie); + IFileDialogCustomize_Release(pfdc); + IFileDialog_Release(pfd); + IFileDialogEvents_Release(pEvents); +} + START_TEST(itemdlg) { OleInitialize(NULL); @@ -2583,6 +2935,7 @@ START_TEST(itemdlg) test_overwrite(); test_customize_remove_from_empty_combobox(); test_double_show(); + test_control_events_selection(); } else skip("Skipping all Item Dialog tests.\n"); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10193
participants (2)
-
pan hui (@panhui) -
panhui