Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- -v2: Test for QueryService setting ppv to NULL upon failure.
--- dlls/oleacc/tests/main.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/dlls/oleacc/tests/main.c b/dlls/oleacc/tests/main.c index 5522867b085..ba7ac3cc3ac 100644 --- a/dlls/oleacc/tests/main.c +++ b/dlls/oleacc/tests/main.c @@ -27,6 +27,7 @@ #include <ole2.h> #include <commctrl.h> #include <oleacc.h> +#include <servprov.h>
#define DEFINE_EXPECT(func) \ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE @@ -1409,6 +1410,32 @@ static LRESULT WINAPI test_query_class(HWND hwnd, UINT msg, WPARAM wparam, LPARA return 0; }
+#define check_acc_proxy_service( acc ) \ + check_acc_proxy_service_( (acc), __LINE__) +static void check_acc_proxy_service_(IAccessible *acc, int line) +{ + IServiceProvider *service = NULL; + IUnknown *unk = NULL; + HRESULT hr; + + hr = IAccessible_QueryInterface(acc, &IID_IServiceProvider, (void **)&service); + todo_wine ok(hr == S_OK, "got %#lx\n", hr); + if (SUCCEEDED(hr)) + { + hr = IServiceProvider_QueryService(service, &IIS_IsOleaccProxy, &IID_IUnknown, (void **)&unk); + ok(hr == S_OK, "got %#lx\n", hr); + ok(!!unk, "unk == NULL\n"); + ok(iface_cmp(unk, (IUnknown*)acc), "unk != acc\n"); + IUnknown_Release(unk); + + unk = (IUnknown*)0xdeadbeef; + hr = IServiceProvider_QueryService(service, &IID_IUnknown, &IID_IUnknown, (void **)&unk); + ok(hr == E_INVALIDARG, "got %#lx\n", hr); + ok(!unk, "unk != NULL\n"); + IServiceProvider_Release(service); + } +} + static void test_CreateStdAccessibleObject_classes(void) { static const struct { @@ -1463,6 +1490,7 @@ static void test_CreateStdAccessibleObject_classes(void) ok(hr == S_OK, "CreateStdAccessibleObject failed %lx\n", hr); if (tests[i].client) CHECK_CALLED(winproc_GETOBJECT); + check_acc_proxy_service(acc); IAccessible_Release(acc);
if (tests[i].window) @@ -1471,6 +1499,7 @@ static void test_CreateStdAccessibleObject_classes(void) ok(hr == S_OK, "CreateStdAccessibleObject failed %lx\n", hr); if (tests[i].window) CHECK_CALLED(winproc_GETOBJECT); + check_acc_proxy_service(acc); IAccessible_Release(acc);
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)win_proc);
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- -v2: Set ppv to NULL upon failure in QueryService.
--- dlls/oleacc/client.c | 48 ++++++++++++++++++++++++++++++++++++ dlls/oleacc/oleacc_private.h | 1 + dlls/oleacc/tests/main.c | 26 +++++++++---------- dlls/oleacc/window.c | 48 ++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 14 deletions(-)
diff --git a/dlls/oleacc/client.c b/dlls/oleacc/client.c index 20993109d28..8a8fd3d240d 100644 --- a/dlls/oleacc/client.c +++ b/dlls/oleacc/client.c @@ -32,6 +32,7 @@ typedef struct { IAccessible IAccessible_iface; IOleWindow IOleWindow_iface; IEnumVARIANT IEnumVARIANT_iface; + IServiceProvider IServiceProvider_iface;
LONG ref;
@@ -114,6 +115,8 @@ static HRESULT WINAPI Client_QueryInterface(IAccessible *iface, REFIID riid, voi *ppv = &This->IOleWindow_iface; }else if(IsEqualIID(riid, &IID_IEnumVARIANT)) { *ppv = &This->IEnumVARIANT_iface; + }else if(IsEqualIID(riid, &IID_IServiceProvider)) { + *ppv = &This->IServiceProvider_iface; }else { WARN("no interface: %s\n", debugstr_guid(riid)); *ppv = NULL; @@ -703,6 +706,50 @@ static const IEnumVARIANTVtbl ClientEnumVARIANTVtbl = { Client_EnumVARIANT_Clone };
+static inline Client* impl_from_Client_ServiceProvider(IServiceProvider *iface) +{ + return CONTAINING_RECORD(iface, Client, IServiceProvider_iface); +} + +static HRESULT WINAPI Client_ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + Client *This = impl_from_Client_ServiceProvider(iface); + return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv); +} + +static ULONG WINAPI Client_ServiceProvider_AddRef(IServiceProvider *iface) +{ + Client *This = impl_from_Client_ServiceProvider(iface); + return IAccessible_AddRef(&This->IAccessible_iface); +} + +static ULONG WINAPI Client_ServiceProvider_Release(IServiceProvider *iface) +{ + Client *This = impl_from_Client_ServiceProvider(iface); + return IAccessible_Release(&This->IAccessible_iface); +} + +static HRESULT WINAPI Client_ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guid_service, + REFIID riid, void **ppv) +{ + Client *This = impl_from_Client_ServiceProvider(iface); + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guid_service), debugstr_guid(riid), ppv); + + *ppv = NULL; + if (IsEqualIID(guid_service, &IIS_IsOleaccProxy)) + return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv); + + return E_INVALIDARG; +} + +static const IServiceProviderVtbl ClientServiceProviderVtbl = { + Client_ServiceProvider_QueryInterface, + Client_ServiceProvider_AddRef, + Client_ServiceProvider_Release, + Client_ServiceProvider_QueryService +}; + static void edit_init(Client *client) { client->role = ROLE_SYSTEM_TEXT; @@ -872,6 +919,7 @@ HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj) client->IAccessible_iface.lpVtbl = &ClientVtbl; client->IOleWindow_iface.lpVtbl = &ClientOleWindowVtbl; client->IEnumVARIANT_iface.lpVtbl = &ClientEnumVARIANTVtbl; + client->IServiceProvider_iface.lpVtbl = &ClientServiceProviderVtbl; client->ref = 1; client->hwnd = hwnd; client->enum_pos = 0; diff --git a/dlls/oleacc/oleacc_private.h b/dlls/oleacc/oleacc_private.h index a01fc3615fe..c91b1465a79 100644 --- a/dlls/oleacc/oleacc_private.h +++ b/dlls/oleacc/oleacc_private.h @@ -17,6 +17,7 @@ */
#include "oleacc_classes.h" +#include "servprov.h"
struct win_class_data { const WCHAR *name; diff --git a/dlls/oleacc/tests/main.c b/dlls/oleacc/tests/main.c index ba7ac3cc3ac..7854764ec08 100644 --- a/dlls/oleacc/tests/main.c +++ b/dlls/oleacc/tests/main.c @@ -1419,21 +1419,19 @@ static void check_acc_proxy_service_(IAccessible *acc, int line) HRESULT hr;
hr = IAccessible_QueryInterface(acc, &IID_IServiceProvider, (void **)&service); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); - if (SUCCEEDED(hr)) - { - hr = IServiceProvider_QueryService(service, &IIS_IsOleaccProxy, &IID_IUnknown, (void **)&unk); - ok(hr == S_OK, "got %#lx\n", hr); - ok(!!unk, "unk == NULL\n"); - ok(iface_cmp(unk, (IUnknown*)acc), "unk != acc\n"); - IUnknown_Release(unk); + ok(hr == S_OK, "got %#lx\n", hr);
- unk = (IUnknown*)0xdeadbeef; - hr = IServiceProvider_QueryService(service, &IID_IUnknown, &IID_IUnknown, (void **)&unk); - ok(hr == E_INVALIDARG, "got %#lx\n", hr); - ok(!unk, "unk != NULL\n"); - IServiceProvider_Release(service); - } + hr = IServiceProvider_QueryService(service, &IIS_IsOleaccProxy, &IID_IUnknown, (void **)&unk); + ok(hr == S_OK, "got %#lx\n", hr); + ok(!!unk, "unk == NULL\n"); + ok(iface_cmp(unk, (IUnknown*)acc), "unk != acc\n"); + IUnknown_Release(unk); + + unk = (IUnknown*)0xdeadbeef; + hr = IServiceProvider_QueryService(service, &IID_IUnknown, &IID_IUnknown, (void **)&unk); + ok(hr == E_INVALIDARG, "got %#lx\n", hr); + ok(!unk, "unk != NULL\n"); + IServiceProvider_Release(service); }
static void test_CreateStdAccessibleObject_classes(void) diff --git a/dlls/oleacc/window.c b/dlls/oleacc/window.c index 470bfd5b362..6a7aa3d0318 100644 --- a/dlls/oleacc/window.c +++ b/dlls/oleacc/window.c @@ -30,6 +30,7 @@ typedef struct { IAccessible IAccessible_iface; IOleWindow IOleWindow_iface; IEnumVARIANT IEnumVARIANT_iface; + IServiceProvider IServiceProvider_iface;
LONG ref;
@@ -55,6 +56,8 @@ static HRESULT WINAPI Window_QueryInterface(IAccessible *iface, REFIID riid, voi *ppv = &This->IOleWindow_iface; }else if(IsEqualIID(riid, &IID_IEnumVARIANT)) { *ppv = &This->IEnumVARIANT_iface; + }else if(IsEqualIID(riid, &IID_IServiceProvider)) { + *ppv = &This->IServiceProvider_iface; }else { WARN("no interface: %s\n", debugstr_guid(riid)); *ppv = NULL; @@ -444,6 +447,50 @@ static const IEnumVARIANTVtbl WindowEnumVARIANTVtbl = { Window_EnumVARIANT_Clone };
+static inline Window* impl_from_Window_ServiceProvider(IServiceProvider *iface) +{ + return CONTAINING_RECORD(iface, Window, IServiceProvider_iface); +} + +static HRESULT WINAPI Window_ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + Window *This = impl_from_Window_ServiceProvider(iface); + return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv); +} + +static ULONG WINAPI Window_ServiceProvider_AddRef(IServiceProvider *iface) +{ + Window *This = impl_from_Window_ServiceProvider(iface); + return IAccessible_AddRef(&This->IAccessible_iface); +} + +static ULONG WINAPI Window_ServiceProvider_Release(IServiceProvider *iface) +{ + Window *This = impl_from_Window_ServiceProvider(iface); + return IAccessible_Release(&This->IAccessible_iface); +} + +static HRESULT WINAPI Window_ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guid_service, + REFIID riid, void **ppv) +{ + Window *This = impl_from_Window_ServiceProvider(iface); + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guid_service), debugstr_guid(riid), ppv); + + *ppv = NULL; + if (IsEqualIID(guid_service, &IIS_IsOleaccProxy)) + return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv); + + return E_INVALIDARG; +} + +static const IServiceProviderVtbl WindowServiceProviderVtbl = { + Window_ServiceProvider_QueryInterface, + Window_ServiceProvider_AddRef, + Window_ServiceProvider_Release, + Window_ServiceProvider_QueryService +}; + static const struct win_class_data classes[] = { {WC_LISTBOXW, 0x10000, TRUE}, {L"#32768", 0x10001, TRUE}, /* menu */ @@ -467,6 +514,7 @@ HRESULT create_window_object(HWND hwnd, const IID *iid, void **obj) window->IAccessible_iface.lpVtbl = &WindowVtbl; window->IOleWindow_iface.lpVtbl = &WindowOleWindowVtbl; window->IEnumVARIANT_iface.lpVtbl = &WindowEnumVARIANTVtbl; + window->IServiceProvider_iface.lpVtbl = &WindowServiceProviderVtbl; window->ref = 1; window->hwnd = hwnd;
Signed-off-by: Piotr Caban piotr@codeweavers.com