Thomas Mullaly : urlmon: Implemented IUriBuilder_{Get/Set}Fragment.

Alexandre Julliard julliard at winehq.org
Mon Sep 6 13:53:12 CDT 2010


Module: wine
Branch: master
Commit: 6aa90a2dceb388d1b46bfc7700d219afd7bd42f5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6aa90a2dceb388d1b46bfc7700d219afd7bd42f5

Author: Thomas Mullaly <thomas.mullaly at gmail.com>
Date:   Sun Aug 29 17:10:10 2010 -0400

urlmon: Implemented IUriBuilder_{Get/Set}Fragment.

---

 dlls/urlmon/tests/uri.c |   22 ++++++++-
 dlls/urlmon/uri.c       |  122 +++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 121 insertions(+), 23 deletions(-)

diff --git a/dlls/urlmon/tests/uri.c b/dlls/urlmon/tests/uri.c
index 9206ce0..1ce6dfa 100644
--- a/dlls/urlmon/tests/uri.c
+++ b/dlls/urlmon/tests/uri.c
@@ -4266,7 +4266,7 @@ typedef struct _uri_builder_test {
 static const uri_builder_test uri_builder_tests[] = {
     {   "http://google.com/",0,S_OK,FALSE,
         {
-            {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,TRUE},
+            {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
             {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,TRUE},
             {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,TRUE},
             {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,TRUE}
@@ -4295,6 +4295,24 @@ static const uri_builder_test uri_builder_tests[] = {
         "http://[::192.2.3.4]/",0,S_OK,TRUE,
         "http://[::192.2.3.4]/",0,S_OK,TRUE,
         "http://[::192.2.3.4]/",0,0,0,S_OK,TRUE
+    },
+    {   "http://google.com/",0,S_OK,FALSE,
+        {
+            {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}
+        },
+        {FALSE},
+        "http://google.com/#Frag",0,S_OK,TRUE,
+        "http://google.com/#Frag",0,S_OK,TRUE,
+        "http://google.com/#Frag",0,0,0,S_OK,TRUE
+    },
+    {   "http://google.com/",0,S_OK,FALSE,
+        {
+            {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE},
+        },
+        {FALSE},
+        "http://google.com/#",0,S_OK,TRUE,
+        "http://google.com/#",0,S_OK,TRUE,
+        "http://google.com/#",0,0,0,S_OK,TRUE
     }
 };
 
@@ -5819,7 +5837,7 @@ static void test_IUriBuilder_CreateInvalidArgs(void) {
             if(uri) IUri_Release(uri);
 
             hr = IUriBuilder_SetFragment(builder, NULL);
-            todo_wine { ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK); }
+            ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK);
 
             /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */
             uri = (void*) 0xdeadbeef;
diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c
index 4377548..c6b496b 100644
--- a/dlls/urlmon/uri.c
+++ b/dlls/urlmon/uri.c
@@ -77,7 +77,11 @@ typedef struct {
     const IUriBuilderVtbl  *lpIUriBuilderVtbl;
     LONG ref;
 
-    IUri *uri;
+    Uri *uri;
+    DWORD modified_props;
+
+    WCHAR   *fragment;
+    DWORD   fragment_len;
 } UriBuilder;
 
 typedef struct {
@@ -3243,6 +3247,76 @@ static HRESULT canonicalize_uri(const parse_data *data, Uri *uri, DWORD flags) {
     return S_OK;
 }
 
+static HRESULT get_builder_component(LPWSTR *component, DWORD *component_len,
+                                     LPCWSTR source, DWORD source_len,
+                                     LPCWSTR *output, DWORD *output_len)
+{
+    if(!output_len) {
+        if(output)
+            *output = NULL;
+        return E_POINTER;
+    }
+
+    if(!output) {
+        *output_len = 0;
+        return E_POINTER;
+    }
+
+    if(!(*component) && source) {
+        /* Allocate 'component', and copy the contents from 'source'
+         * into the new allocation.
+         */
+        *component = heap_alloc((source_len+1)*sizeof(WCHAR));
+        if(!(*component))
+            return E_OUTOFMEMORY;
+
+        memcpy(*component, source, source_len*sizeof(WCHAR));
+        (*component)[source_len] = '\0';
+        *component_len = source_len;
+    }
+
+    *output = *component;
+    *output_len = *component_len;
+    return *output ? S_OK : S_FALSE;
+}
+
+/* Allocates 'component' and copies the string from 'new_value' into 'component'.
+ * If 'prefix' is set and 'new_value' isn't NULL, then it checks if 'new_value'
+ * starts with 'prefix'. If it doesn't then 'prefix' is prepended to 'component'.
+ */
+static HRESULT set_builder_component(LPWSTR *component, DWORD *component_len, LPCWSTR new_value,
+                                     WCHAR prefix)
+{
+    if(*component)
+        heap_free(*component);
+
+    if(!new_value) {
+        *component = NULL;
+        *component_len = 0;
+    } else {
+        BOOL add_prefix = FALSE;
+        DWORD len = lstrlenW(new_value);
+        DWORD pos = 0;
+
+        if(prefix && *new_value != prefix) {
+            add_prefix = TRUE;
+            *component = heap_alloc((len+2)*sizeof(WCHAR));
+        } else
+            *component = heap_alloc((len+1)*sizeof(WCHAR));
+
+        if(!(*component))
+            return E_OUTOFMEMORY;
+
+        if(add_prefix)
+            (*component)[pos++] = prefix;
+
+        memcpy(*component+pos, new_value, (len+1)*sizeof(WCHAR));
+        *component_len = len+pos;
+    }
+
+    return S_OK;
+}
+
 #define URI(x)         ((IUri*)  &(x)->lpIUriVtbl)
 #define URIBUILDER(x)  ((IUriBuilder*)  &(x)->lpIUriBuilderVtbl)
 
@@ -4234,7 +4308,8 @@ static ULONG WINAPI UriBuilder_Release(IUriBuilder *iface)
     TRACE("(%p) ref=%d\n", This, ref);
 
     if(!ref) {
-        if(This->uri) IUri_Release(This->uri);
+        if(This->uri) IUri_Release(URI(This->uri));
+        heap_free(This->fragment);
         heap_free(This);
     }
 
@@ -4353,19 +4428,11 @@ static HRESULT WINAPI UriBuilder_GetFragment(IUriBuilder *iface, DWORD *pcchFrag
     UriBuilder *This = URIBUILDER_THIS(iface);
     TRACE("(%p)->(%p %p)\n", This, pcchFragment, ppwzFragment);
 
-    if(!pcchFragment) {
-        if(ppwzFragment)
-            *ppwzFragment = NULL;
-        return E_POINTER;
-    }
-
-    if(!ppwzFragment) {
-        *pcchFragment = 0;
-        return E_POINTER;
-    }
-
-    FIXME("(%p)->(%p %p)\n", This, pcchFragment, ppwzFragment);
-    return E_NOTIMPL;
+    if(!This->uri || This->uri->fragment_start == -1 || This->modified_props & Uri_HAS_FRAGMENT)
+        return get_builder_component(&This->fragment, &This->fragment_len, NULL, 0, ppwzFragment, pcchFragment);
+    else
+        return get_builder_component(&This->fragment, &This->fragment_len, This->uri->canon_uri+This->uri->fragment_start,
+                                     This->uri->fragment_len, ppwzFragment, pcchFragment);
 }
 
 static HRESULT WINAPI UriBuilder_GetHost(IUriBuilder *iface, DWORD *pcchHost, LPCWSTR *ppwzHost)
@@ -4511,8 +4578,10 @@ static HRESULT WINAPI UriBuilder_GetUserName(IUriBuilder *iface, DWORD *pcchUser
 static HRESULT WINAPI UriBuilder_SetFragment(IUriBuilder *iface, LPCWSTR pwzNewValue)
 {
     UriBuilder *This = URIBUILDER_THIS(iface);
-    FIXME("(%p)->(%s)\n", This, debugstr_w(pwzNewValue));
-    return E_NOTIMPL;
+    TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue));
+
+    This->modified_props |= Uri_HAS_FRAGMENT;
+    return set_builder_component(&This->fragment, &This->fragment_len, pwzNewValue, '#');
 }
 
 static HRESULT WINAPI UriBuilder_SetHost(IUriBuilder *iface, LPCWSTR pwzNewValue)
@@ -4626,16 +4695,27 @@ HRESULT WINAPI CreateIUriBuilder(IUri *pIUri, DWORD dwFlags, DWORD_PTR dwReserve
     if(!ppIUriBuilder)
         return E_POINTER;
 
-    ret = heap_alloc(sizeof(UriBuilder));
+    ret = heap_alloc_zero(sizeof(UriBuilder));
     if(!ret)
         return E_OUTOFMEMORY;
 
     ret->lpIUriBuilderVtbl = &UriBuilderVtbl;
     ret->ref = 1;
 
-    ret->uri = pIUri;
-    if(pIUri)
-        IUri_AddRef(pIUri);
+    if(pIUri) {
+        Uri *uri;
+
+        if((uri = get_uri_obj(pIUri))) {
+            IUri_AddRef(pIUri);
+            ret->uri = uri;
+        } else {
+            heap_free(ret);
+            *ppIUriBuilder = NULL;
+            FIXME("(%p %x %x %p): Unknown IUri types not supported yet.\n", pIUri, dwFlags,
+                (DWORD)dwReserved, ppIUriBuilder);
+            return E_NOTIMPL;
+        }
+    }
 
     *ppIUriBuilder = URIBUILDER(ret);
     return S_OK;




More information about the wine-cvs mailing list