diff --git a/dlls/hlink/tests/hlink.c b/dlls/hlink/tests/hlink.c index 52b5c57f9e6..ccbbd889d5c 100644 --- a/dlls/hlink/tests/hlink.c +++ b/dlls/hlink/tests/hlink.c @@ -81,9 +81,16 @@ DEFINE_EXPECT(HT_GetFriendlyName); DEFINE_EXPECT(HLF_UpdateHlink); +DEFINE_EXPECT(BindStatusCallback_GetBindInfo); +DEFINE_EXPECT(BindStatusCallback_OnObjectAvailable); +DEFINE_EXPECT(BindStatusCallback_OnStartBinding); +DEFINE_EXPECT(BindStatusCallback_OnStopBinding); + DEFINE_GUID(CLSID_IdentityUnmarshal,0x0000001b,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); DEFINE_GUID(IID_IHlinkHistory,0x79eac9c8,0xbaf9,0x11ce,0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b); +static IHlinkTarget HlinkTarget; + static const WCHAR winehq_urlW[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g', '/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0}; @@ -757,21 +764,25 @@ static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *ifa return E_NOINTERFACE; } +static LONG bind_callback_refs = 1; + static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface) { - return 2; + return ++bind_callback_refs; } static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface) { - return 1; + return --bind_callback_refs; } -static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, - IBinding *pib) +static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, + DWORD reserved, IBinding *binding) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + CHECK_EXPECT(BindStatusCallback_OnStartBinding); + + ok(!binding, "binding = %p\n", binding); + return S_OK; } static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) @@ -793,15 +804,20 @@ static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, return E_NOTIMPL; } -static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError) +static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hr, const WCHAR *error) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + CHECK_EXPECT(BindStatusCallback_OnStopBinding); + + ok(hr == S_OK, "got hr %#x\n", hr); + ok(!error, "got error %s\n", wine_dbgstr_w(error)); + + return 0xdeadbeef; } -static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo) +static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *bind_flags, BINDINFO *bind_info) { - ok(0, "unexpected call\n"); + CHECK_EXPECT(BindStatusCallback_GetBindInfo); + return E_NOTIMPL; } @@ -812,10 +828,14 @@ static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *if return E_NOTIMPL; } -static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk) +static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID iid, IUnknown *out) { - ok(0, "unexpected call\n"); - return E_NOTIMPL; + CHECK_EXPECT(BindStatusCallback_OnObjectAvailable); + + ok(IsEqualGUID(iid, &IID_IUnknown), "iid = %s\n", wine_dbgstr_guid(iid)); + ok(out == (IUnknown *)&HlinkTarget, "out = %p\n", out); + + return 0xdeadbeef; } static IBindStatusCallbackVtbl BindStatusCallbackVtbl = { @@ -853,14 +873,16 @@ static HRESULT WINAPI HlinkBrowseContext_QueryInterface( return E_NOINTERFACE; } +static LONG browse_ctx_refs = 1; + static ULONG WINAPI HlinkBrowseContext_AddRef(IHlinkBrowseContext *iface) { - return 2; + return ++browse_ctx_refs; } static ULONG WINAPI HlinkBrowseContext_Release(IHlinkBrowseContext *iface) { - return 1; + return --browse_ctx_refs; } static HRESULT WINAPI HlinkBrowseContext_Register(IHlinkBrowseContext *iface, @@ -1125,9 +1147,16 @@ static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSiz return E_NOTIMPL; } +static BOOL async_bind; +static IBindStatusCallback *async_bind_callback; + static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, void **ppv) { + static WCHAR bscb_holderW[] = {'_','B','S','C','B','_','H','o','l','d','e','r','_',0}; + IUnknown *bind_callback_holder; + HRESULT hr; + CHECK_EXPECT(BindToObject); ok(pbc != _bctx, "pbc != _bctx\n"); @@ -1136,6 +1165,17 @@ static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoni ok(ppv != NULL, "ppv == NULL\n"); ok(*ppv == NULL, "*ppv = %p\n", *ppv); + if (async_bind) + { + hr = IBindCtx_GetObjectParam(pbc, bscb_holderW, &bind_callback_holder); + ok(hr == S_OK, "Failed to get IBindStatusCallback holder, hr %#x.\n", hr); + hr = IUnknown_QueryInterface(bind_callback_holder, &IID_IBindStatusCallback, + (void **)&async_bind_callback); + ok(hr == S_OK, "Failed to get IBindStatusCallback interface, hr %#x.\n", hr); + IUnknown_Release(bind_callback_holder); + return MK_S_ASYNCHRONOUS; + } + *ppv = &HlinkTarget; return S_OK; } @@ -2188,6 +2228,8 @@ static void test_StdHlink(void) static void test_Hlink_Navigate(void) { + BINDINFO bind_info = {sizeof(BINDINFO)}; + DWORD bind_flags; IHlink *hlink; IBindCtx *pbc; HRESULT hres; @@ -2301,6 +2343,179 @@ if (0) { /* these currently open a browser window on wine */ else skip("interactive IHlink_Navigate tests\n"); + /* test binding callback */ + SET_EXPECT(IsSystemMoniker); + SET_EXPECT(GetDisplayName); + SET_EXPECT(BindStatusCallback_GetBindInfo); + SET_EXPECT(HBC_GetObject); + SET_EXPECT(Reduce); + SET_EXPECT(BindToObject); + SET_EXPECT(BindStatusCallback_OnStartBinding); + SET_EXPECT(BindStatusCallback_OnObjectAvailable); + SET_EXPECT(HT_QueryInterface_IHlinkTarget); + SET_EXPECT(HT_GetBrowseContext); + SET_EXPECT(HT_SetBrowseContext); + SET_EXPECT(HBC_QueryInterface_IHlinkHistory); + SET_EXPECT(HT_Navigate); + SET_EXPECT(HT_GetFriendlyName); + SET_EXPECT(BindStatusCallback_OnStopBinding); + hres = IHlink_Navigate(hlink, 0, pbc, &BindStatusCallback, &HlinkBrowseContext); + ok(hres == S_OK, "Navigate failed: %#x\n", hres); + CHECK_CALLED(IsSystemMoniker); + CHECK_CALLED(GetDisplayName); + CHECK_CALLED(HBC_GetObject); +todo_wine + CHECK_CALLED(BindStatusCallback_GetBindInfo); +todo_wine + CHECK_CALLED(Reduce); + CHECK_CALLED(BindToObject); +todo_wine { + CHECK_CALLED(BindStatusCallback_OnStartBinding); + CHECK_CALLED(BindStatusCallback_OnObjectAvailable); +} + CHECK_CALLED(HT_QueryInterface_IHlinkTarget); +todo_wine + CHECK_CALLED(HT_GetBrowseContext); + CHECK_CALLED(HT_SetBrowseContext); +todo_wine + CHECK_CALLED(HBC_QueryInterface_IHlinkHistory); + CHECK_CALLED(HT_Navigate); +todo_wine + CHECK_CALLED(HT_GetFriendlyName); +todo_wine + CHECK_CALLED(BindStatusCallback_OnStopBinding); + + ok(bind_callback_refs == 1, "Got unexpected refcount %d.\n", bind_callback_refs); + ok(browse_ctx_refs == 1, "Got unexpected refcount %d.\n", browse_ctx_refs); + + /* test asynchronous binding */ + async_bind = TRUE; + SET_EXPECT(IsSystemMoniker); + SET_EXPECT(GetDisplayName); + SET_EXPECT(HBC_GetObject); + SET_EXPECT(Reduce); + SET_EXPECT(BindToObject); + hres = IHlink_Navigate(hlink, 0, pbc, NULL, &HlinkBrowseContext); + ok(hres == MK_S_ASYNCHRONOUS, "Navigate failed: %#x\n", hres); + CHECK_CALLED(IsSystemMoniker); + CHECK_CALLED(GetDisplayName); + CHECK_CALLED(HBC_GetObject); +todo_wine + CHECK_CALLED(Reduce); + CHECK_CALLED(BindToObject); + + ok(browse_ctx_refs > 1, "Got unexpected refcount %d.\n", browse_ctx_refs); + + hres = IHlink_Navigate(hlink, 0, pbc, NULL, &HlinkBrowseContext); + ok(hres == E_UNEXPECTED, "Got hr %#x.\n", hres); + + hres = IBindStatusCallback_GetBindInfo(async_bind_callback, &bind_flags, &bind_info); + ok(hres == S_OK, "Got hr %#x.\n", hres); + + hres = IBindStatusCallback_OnStartBinding(async_bind_callback, 0, NULL); + ok(hres == S_OK, "Got hr %#x.\n", hres); + + SET_EXPECT(HT_QueryInterface_IHlinkTarget); + SET_EXPECT(HT_GetBrowseContext); + SET_EXPECT(HT_SetBrowseContext); + SET_EXPECT(HBC_QueryInterface_IHlinkHistory); + SET_EXPECT(HT_Navigate); + SET_EXPECT(HT_GetFriendlyName); + hres = IBindStatusCallback_OnObjectAvailable(async_bind_callback, &IID_IUnknown, + (IUnknown *)&HlinkTarget); + ok(hres == S_OK, "Got hr %#x.\n", hres); + CHECK_CALLED(HT_QueryInterface_IHlinkTarget); +todo_wine + CHECK_CALLED(HT_GetBrowseContext); + CHECK_CALLED(HT_SetBrowseContext); +todo_wine + CHECK_CALLED(HBC_QueryInterface_IHlinkHistory); + CHECK_CALLED(HT_Navigate); +todo_wine + CHECK_CALLED(HT_GetFriendlyName); + + hres = IHlink_Navigate(hlink, 0, pbc, NULL, &HlinkBrowseContext); + ok(hres == E_UNEXPECTED, "Got hr %#x.\n", hres); + + ok(browse_ctx_refs > 1, "Got unexpected refcount %d.\n", browse_ctx_refs); + + hres = IBindStatusCallback_OnStopBinding(async_bind_callback, S_OK, NULL); + ok(hres == S_OK, "Got hr %#x.\n", hres); + + ok(browse_ctx_refs == 1, "Got unexpected refcount %d.\n", browse_ctx_refs); + + IBindStatusCallback_Release(async_bind_callback); + + SET_EXPECT(IsSystemMoniker); + SET_EXPECT(GetDisplayName); + SET_EXPECT(BindStatusCallback_GetBindInfo); + SET_EXPECT(HBC_GetObject); + SET_EXPECT(Reduce); + SET_EXPECT(BindToObject); + hres = IHlink_Navigate(hlink, 0, pbc, &BindStatusCallback, &HlinkBrowseContext); + ok(hres == MK_S_ASYNCHRONOUS, "Navigate failed: %#x\n", hres); + CHECK_CALLED(IsSystemMoniker); + CHECK_CALLED(GetDisplayName); +todo_wine + CHECK_CALLED(BindStatusCallback_GetBindInfo); + CHECK_CALLED(HBC_GetObject); +todo_wine + CHECK_CALLED(Reduce); + CHECK_CALLED(BindToObject); + + ok(bind_callback_refs > 1, "Got unexpected refcount %d.\n", bind_callback_refs); + ok(browse_ctx_refs > 1, "Got unexpected refcount %d.\n", browse_ctx_refs); + + hres = IHlink_Navigate(hlink, 0, pbc, NULL, &HlinkBrowseContext); + ok(hres == E_UNEXPECTED, "Got hr %#x.\n", hres); + + SET_EXPECT(BindStatusCallback_GetBindInfo); + hres = IBindStatusCallback_GetBindInfo(async_bind_callback, &bind_flags, &bind_info); + ok(hres == E_NOTIMPL, "Got hr %#x.\n", hres); + CHECK_CALLED(BindStatusCallback_GetBindInfo); + + SET_EXPECT(BindStatusCallback_OnStartBinding); + hres = IBindStatusCallback_OnStartBinding(async_bind_callback, 0, NULL); + ok(hres == S_OK, "Got hr %#x.\n", hres); + CHECK_CALLED(BindStatusCallback_OnStartBinding); + + SET_EXPECT(BindStatusCallback_OnObjectAvailable); + SET_EXPECT(HT_QueryInterface_IHlinkTarget); + SET_EXPECT(HT_GetBrowseContext); + SET_EXPECT(HT_SetBrowseContext); + SET_EXPECT(HBC_QueryInterface_IHlinkHistory); + SET_EXPECT(HT_Navigate); + SET_EXPECT(HT_GetFriendlyName); + hres = IBindStatusCallback_OnObjectAvailable(async_bind_callback, &IID_IUnknown, + (IUnknown *)&HlinkTarget); + ok(hres == S_OK, "Got hr %#x.\n", hres); + CHECK_CALLED(BindStatusCallback_OnObjectAvailable); + CHECK_CALLED(HT_QueryInterface_IHlinkTarget); +todo_wine + CHECK_CALLED(HT_GetBrowseContext); + CHECK_CALLED(HT_SetBrowseContext); +todo_wine + CHECK_CALLED(HBC_QueryInterface_IHlinkHistory); + CHECK_CALLED(HT_Navigate); +todo_wine + CHECK_CALLED(HT_GetFriendlyName); + + hres = IHlink_Navigate(hlink, 0, pbc, NULL, &HlinkBrowseContext); + ok(hres == E_UNEXPECTED, "Got hr %#x.\n", hres); + + ok(bind_callback_refs > 1, "Got unexpected refcount %d.\n", bind_callback_refs); + ok(browse_ctx_refs > 1, "Got unexpected refcount %d.\n", browse_ctx_refs); + + SET_EXPECT(BindStatusCallback_OnStopBinding); + hres = IBindStatusCallback_OnStopBinding(async_bind_callback, S_OK, NULL); + ok(hres == S_OK, "Got hr %#x.\n", hres); + CHECK_CALLED(BindStatusCallback_OnStopBinding); + + ok(bind_callback_refs == 1, "Got unexpected refcount %d.\n", bind_callback_refs); + ok(browse_ctx_refs == 1, "Got unexpected refcount %d.\n", browse_ctx_refs); + + IBindStatusCallback_Release(async_bind_callback); + IHlink_Release(hlink); IBindCtx_Release(pbc); _bctx = NULL;