diff --git a/dlls/urlmon/tests/uri.c b/dlls/urlmon/tests/uri.c index 775b4f62f95..c069d84cf5e 100644 --- a/dlls/urlmon/tests/uri.c +++ b/dlls/urlmon/tests/uri.c @@ -9067,6 +9067,96 @@ static void test_IUriBuilder_Misc(void) { if(uri) IUri_Release(uri); } +static void test_IUriBuilderFactory(void) { + HRESULT hr; + IUri *uri; + IUriBuilderFactory *factory; + IUriBuilder *builder; + + hr = pCreateUri(http_urlW, 0, 0, &uri); + ok(SUCCEEDED(hr), "Error: CreateUri returned 0x%08x.\n", hr); + if(SUCCEEDED(hr)) { + factory = NULL; + hr = IUri_QueryInterface(uri, &IID_IUriBuilderFactory, (void**)&factory); + ok(hr == S_OK, "Error: Expected S_OK, but got 0x%08x.\n", hr); + ok(factory != NULL, "Error: Expected 'factory' to not be NULL.\n"); + + if(SUCCEEDED(hr)) { + builder = (void*) 0xdeadbeef; + hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 10, 0, &builder); + ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n", + hr, E_INVALIDARG); + ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder); + + builder = (void*) 0xdeadbeef; + hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 10, &builder); + ok(hr == E_INVALIDARG, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n", + hr, E_INVALIDARG); + ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder); + + hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, NULL); + ok(hr == E_POINTER, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n", + hr, E_POINTER); + + builder = NULL; + hr = IUriBuilderFactory_CreateInitializedIUriBuilder(factory, 0, 0, &builder); + ok(hr == S_OK, "Error: CreateInitializedIUriBuilder returned 0x%08x, expected 0x%08x.\n", + hr, S_OK); + if(SUCCEEDED(hr)) { + IUri *tmp = (void*) 0xdeadbeef; + LPCWSTR result; + DWORD result_len; + + /* Seems microsoft had a bit of mixup naming this function. It + * returns an uninitialized IUriBuilder. + */ + hr = IUriBuilder_GetIUri(builder, &tmp); + ok(hr == S_OK, "Error: GetIUri returned 0x%08x, expected 0x%08x.\n", + hr, S_OK); + ok(!tmp, "Error: Expected 'tmp' to be NULL, but was %p instead.\n", tmp); + + hr = IUriBuilder_GetHost(builder, &result_len, &result); + ok(hr == S_FALSE, "Error: GetHost returned 0x%08x, expected 0x%08x.\n", + hr, S_FALSE); + } + if(builder) IUriBuilder_Release(builder); + + builder = (void*) 0xdeadbeef; + hr = IUriBuilderFactory_CreateIUriBuilder(factory, 10, 0, &builder); + ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", + hr, E_INVALIDARG); + ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder); + + builder = (void*) 0xdeadbeef; + hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 10, &builder); + ok(hr == E_INVALIDARG, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", + hr, E_INVALIDARG); + ok(!builder, "Error: Expected 'builder' to be NULL, but was %p.\n", builder); + + hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, NULL); + ok(hr == E_POINTER, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", + hr, E_POINTER); + + builder = NULL; + hr = IUriBuilderFactory_CreateIUriBuilder(factory, 0, 0, &builder); + ok(hr == S_OK, "Error: CreateIUriBuilder returned 0x%08x, expected 0x%08x.\n", + hr, S_OK); + if(SUCCEEDED(hr)) { + IUri *tmp = NULL; + + hr = IUriBuilder_GetIUri(builder, &tmp); + ok(hr == S_OK, "Error: GetIUri return 0x%08x, expected 0x%08x.\n", + hr, S_OK); + ok(tmp == uri, "Error: Expected tmp to be %p, but was %p.\n", uri, tmp); + if(uri) IUri_Release(uri); + } + if(builder) IUriBuilder_Release(builder); + } + if(factory) IUriBuilderFactory_Release(factory); + } + if(uri) IUri_Release(uri); +} + static void test_CoInternetCombineIUri(void) { HRESULT hr; IUri *base, *relative, *result; @@ -9718,6 +9808,9 @@ START_TEST(uri) { trace("test IUriBuilder miscellaneous...\n"); test_IUriBuilder_Misc(); + trace("test IUriBuilderFactory...\n"); + test_IUriBuilderFactory(); + trace("test CoInternetCombineIUri...\n"); test_CoInternetCombineIUri(); diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c index a273358bc0b..1cccfe3273e 100644 --- a/dlls/urlmon/uri.c +++ b/dlls/urlmon/uri.c @@ -48,7 +48,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); static const IID IID_IUriObj = {0x4b364760,0x9f51,0x11df,{0x98,0x1c,0x08,0x00,0x20,0x0c,0x9a,0x66}}; typedef struct { - IUri IUri_iface; + IUri IUri_iface; + IUriBuilderFactory IUriBuilderFactory_iface; + LONG ref; BSTR raw_uri; @@ -4122,6 +4124,13 @@ static inline Uri* impl_from_IUri(IUri *iface) return CONTAINING_RECORD(iface, Uri, IUri_iface); } +static inline void destory_uri_obj(Uri *This) +{ + SysFreeString(This->raw_uri); + heap_free(This->canon_uri); + heap_free(This); +} + static HRESULT WINAPI Uri_QueryInterface(IUri *iface, REFIID riid, void **ppv) { Uri *This = impl_from_IUri(iface); @@ -4132,6 +4141,9 @@ static HRESULT WINAPI Uri_QueryInterface(IUri *iface, REFIID riid, void **ppv) }else if(IsEqualGUID(&IID_IUri, riid)) { TRACE("(%p)->(IID_IUri %p)\n", This, ppv); *ppv = &This->IUri_iface; + }else if(IsEqualGUID(&IID_IUriBuilderFactory, riid)) { + TRACE("(%p)->(IID_IUriBuilderFactory %p)\n", This, riid); + *ppv = &This->IUriBuilderFactory_iface; }else if(IsEqualGUID(&IID_IUriObj, riid)) { TRACE("(%p)->(IID_IUriObj %p)\n", This, ppv); *ppv = This; @@ -4163,11 +4175,8 @@ static ULONG WINAPI Uri_Release(IUri *iface) TRACE("(%p) ref=%d\n", This, ref); - if(!ref) { - SysFreeString(This->raw_uri); - heap_free(This->canon_uri); - heap_free(This); - } + if(!ref) + destory_uri_obj(This); return ref; } @@ -4947,10 +4956,108 @@ static const IUriVtbl UriVtbl = { Uri_IsEqual }; +static inline Uri* impl_from_IUriBuilderFactory(IUriBuilderFactory *iface) +{ + return CONTAINING_RECORD(iface, Uri, IUriBuilderFactory_iface); +} + +static HRESULT WINAPI UriBuilderFactory_QueryInterface(IUriBuilderFactory *iface, REFIID riid, void **ppv) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = &This->IUriBuilderFactory_iface; + }else if(IsEqualGUID(&IID_IUriBuilderFactory, riid)) { + TRACE("(%p)->(IID_IUriBuilderFactory %p)\n", This, ppv); + *ppv = &This->IUriBuilderFactory_iface; + }else if(IsEqualGUID(&IID_IUri, riid)) { + TRACE("(%p)->(IID_IUri %p)\n", This, ppv); + *ppv = &This->IUri_iface; + }else { + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI UriBuilderFactory_AddRef(IUriBuilderFactory *iface) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI UriBuilderFactory_Release(IUriBuilderFactory *iface) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) + destory_uri_obj(This); + + return ref; +} + +static HRESULT WINAPI UriBuilderFactory_CreateInitializedIUriBuilder(IUriBuilderFactory *iface, + DWORD dwFlags, + DWORD_PTR dwReserved, + IUriBuilder **ppIUriBuilder) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + TRACE("(%p)->(%08x %08x %p)\n", This, dwFlags, (DWORD)dwReserved, ppIUriBuilder); + + if(!ppIUriBuilder) + return E_POINTER; + + if(dwFlags || dwReserved) { + *ppIUriBuilder = NULL; + return E_INVALIDARG; + } + + return CreateIUriBuilder(NULL, 0, 0, ppIUriBuilder); +} + +static HRESULT WINAPI UriBuilderFactory_CreateIUriBuilder(IUriBuilderFactory *iface, + DWORD dwFlags, + DWORD_PTR dwReserved, + IUriBuilder **ppIUriBuilder) +{ + Uri *This = impl_from_IUriBuilderFactory(iface); + TRACE("(%p)->(%08x %08x %p)\n", This, dwFlags, (DWORD)dwReserved, ppIUriBuilder); + + if(!ppIUriBuilder) + return E_POINTER; + + if(dwFlags || dwReserved) { + *ppIUriBuilder = NULL; + return E_INVALIDARG; + } + + return CreateIUriBuilder(&This->IUri_iface, 0, 0, ppIUriBuilder); +} + +static const IUriBuilderFactoryVtbl UriBuilderFactoryVtbl = { + UriBuilderFactory_QueryInterface, + UriBuilderFactory_AddRef, + UriBuilderFactory_Release, + UriBuilderFactory_CreateInitializedIUriBuilder, + UriBuilderFactory_CreateIUriBuilder +}; + static Uri* create_uri_obj(void) { Uri *ret = heap_alloc_zero(sizeof(Uri)); if(ret) { ret->IUri_iface.lpVtbl = &UriVtbl; + ret->IUriBuilderFactory_iface.lpVtbl = &UriBuilderFactoryVtbl; ret->ref = 1; }