[1/2] webservices: Implement WsDecodeUrl.

Hans Leidekker hans at codeweavers.com
Thu May 26 03:56:47 CDT 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/Makefile.in       |   1 +
 dlls/webservices/tests/Makefile.in |   1 +
 dlls/webservices/tests/url.c       | 194 +++++++++++++++++++++++++++++++++
 dlls/webservices/url.c             | 214 +++++++++++++++++++++++++++++++++++++
 dlls/webservices/webservices.spec  |   2 +-
 include/webservices.h              |  67 ++++++++++++
 6 files changed, 478 insertions(+), 1 deletion(-)
 create mode 100644 dlls/webservices/tests/url.c
 create mode 100644 dlls/webservices/url.c

diff --git a/dlls/webservices/Makefile.in b/dlls/webservices/Makefile.in
index 285368f..acb7d0e 100644
--- a/dlls/webservices/Makefile.in
+++ b/dlls/webservices/Makefile.in
@@ -7,4 +7,5 @@ C_SRCS = \
 	main.c \
 	proxy.c \
 	reader.c \
+	url.c \
 	writer.c
diff --git a/dlls/webservices/tests/Makefile.in b/dlls/webservices/tests/Makefile.in
index 66d82f8..c278a47 100644
--- a/dlls/webservices/tests/Makefile.in
+++ b/dlls/webservices/tests/Makefile.in
@@ -5,4 +5,5 @@ C_SRCS = \
 	channel.c \
 	proxy.c \
 	reader.c \
+	url.c \
 	writer.c
diff --git a/dlls/webservices/tests/url.c b/dlls/webservices/tests/url.c
new file mode 100644
index 0000000..45b6745
--- /dev/null
+++ b/dlls/webservices/tests/url.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2016 Hans Leidekker for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdio.h>
+#include "windows.h"
+#include "webservices.h"
+#include "wine/test.h"
+
+static void test_WsDecodeUrl(void)
+{
+    static WCHAR url1[] = {'h','t','t','p',':','/','/','h','o','s','t',0};
+    static WCHAR url2[] = {'h','t','t','p','s',':','/','/','h','o','s','t',0};
+    static WCHAR url3[] = {'h','t','t','p',':','/','/','h','o','s','t',':','8','0',0};
+    static WCHAR url4[] = {'h','t','t','p','s',':','/','/','h','o','s','t',':','8','0',0};
+    static WCHAR url5[] = {'h','t','t','p',':','/','/','h','o','s','t','/','p','a','t','h',0};
+    static WCHAR url6[] = {'h','t','t','p',':','/','/','h','o','s','t','/','p','a','t','h','?',
+                           'q','u','e','r','y',0};
+    static WCHAR url7[] = {'h','t','t','p',':','/','/','h','o','s','t','/','p','a','t','h','?',
+                           'q','u','e','r','y','#','f','r','a','g',0};
+    static WCHAR url8[] = {'H','T','T','P',':','/','/','h','o','s','t',0};
+    static WCHAR url9[] = {'h','t','t','q',':','/','/','h','o','s','t',0};
+    static WCHAR url10[] = {'h','t','t','p',':',0};
+    static WCHAR url11[] = {'h','t','t','p',0};
+    static WCHAR url12[] = {'n','e','t','.','t','c','p',':','/','/','h','o','s','t',0};
+    static WCHAR url13[] = {'s','o','a','p','.','u','d','p',':','/','/','h','o','s','t',0};
+    static WCHAR url14[] = {'n','e','t','.','p','i','p','e',':','/','/','h','o','s','t',0};
+    static WCHAR url15[] = {'h','t','t','p',':','/','h','o','s','t',0};
+    static WCHAR url16[] = {'h','t','t','p',':','h','o','s','t',0};
+    static WCHAR url17[] = {'h','t','t','p',':','/','/','/','h','o','s','t',0};
+    static WCHAR url18[] = {'h','t','t','p',':','/','/','h','o','s','t','/',0};
+    static WCHAR url19[] = {'h','t','t','p',':','/','/','h','o','s','t',':','/',0};
+    static WCHAR url20[] = {'h','t','t','p',':','/','/','h','o','s','t',':','6','5','5','3','6',0};
+    static WCHAR url21[] = {'h','t','t','p',':','/','/','h','o','s','t','?','q','u','e','r','y',0};
+    static WCHAR url22[] = {'h','t','t','p',':','/','/','h','o','s','t','#','f','r','a','g',0};
+    static WCHAR url23[] = {'h','t','t','p',':','/','/','h','o','s','t','%','2','0','2',0};
+    static WCHAR url24[] = {'h','t','t','p',':','/','/','h','o','s','t','/','p','a','t','h',
+                            '%','2','0','2',0};
+    static WCHAR url25[] = {'h','t','t','p',':','/','/','h','o','s','t','?','q','u','e','r','y',
+                            '%','2','0','2',0};
+    static WCHAR url26[] = {'h','t','t','p',':','/','/','h','o','s','t','#','f','r','a','g',
+                            '%','2','0','2',0};
+    static WCHAR host2[] = {'h','o','s','t',' ','2'};
+    static WCHAR path2[] = {'/','p','a','t','h',' ','2'};
+    static WCHAR query2[] = {'q','u','e','r','y',' ','2'};
+    static WCHAR frag2[] = {'f','r','a','g',' ','2'};
+    static const struct
+    {
+        WCHAR              *str;
+        HRESULT             hr;
+        WS_URL_SCHEME_TYPE  scheme;
+        WCHAR              *host;
+        ULONG               host_len;
+        USHORT              port;
+        WCHAR              *port_str;
+        ULONG               port_len;
+        WCHAR              *path;
+        ULONG               path_len;
+        WCHAR              *query;
+        ULONG               query_len;
+        WCHAR              *fragment;
+        ULONG               fragment_len;
+    }
+    tests[] =
+    {
+        { url1, S_OK, WS_URL_HTTP_SCHEME_TYPE, url1 + 7, 4, 80 },
+        { url2, S_OK, WS_URL_HTTPS_SCHEME_TYPE, url2 + 8, 4, 443 },
+        { url3, S_OK, WS_URL_HTTP_SCHEME_TYPE, url3 + 7, 4, 80, url3 + 12, 2 },
+        { url4, S_OK, WS_URL_HTTPS_SCHEME_TYPE, url4 + 8, 4, 80, url4 + 13, 2 },
+        { url5, S_OK, WS_URL_HTTP_SCHEME_TYPE, url5 + 7, 4, 80, NULL, 0, url5 + 11, 5 },
+        { url6, S_OK, WS_URL_HTTP_SCHEME_TYPE, url5 + 7, 4, 80, NULL, 0, url6 + 11, 5, url6 + 17, 5 },
+        { url7, S_OK, WS_URL_HTTP_SCHEME_TYPE, url5 + 7, 4, 80, NULL, 0, url7 + 11, 5, url7 + 17, 5,
+          url7 + 23, 4 },
+        { url8, S_OK, WS_URL_HTTP_SCHEME_TYPE, url1 + 7, 4, 80 },
+        { url9, WS_E_INVALID_FORMAT },
+        { url10, WS_E_INVALID_FORMAT },
+        { url11, WS_E_INVALID_FORMAT },
+        { url12, S_OK, WS_URL_NETTCP_SCHEME_TYPE, url12 + 10, 4, 808 },
+        { url13, S_OK, WS_URL_SOAPUDP_SCHEME_TYPE, url13 + 11, 4, 65535 },
+        { url14, S_OK, WS_URL_NETPIPE_SCHEME_TYPE, url14 + 11, 4, 65535 },
+        { url15, WS_E_INVALID_FORMAT },
+        { url16, WS_E_INVALID_FORMAT },
+        { url17, WS_E_INVALID_FORMAT },
+        { url18, S_OK, WS_URL_HTTP_SCHEME_TYPE, url18 + 7, 4, 80, NULL, 0, url18 + 11, 1 },
+        { url19, S_OK, WS_URL_HTTP_SCHEME_TYPE, url19 + 7, 4, 80, NULL, 0, url19 + 12, 1 },
+        { url20, WS_E_INVALID_FORMAT },
+        { url21, S_OK, WS_URL_HTTP_SCHEME_TYPE, url21 + 7, 4, 80, NULL, 0, NULL, 0, url21 + 12, 5 },
+        { url22, S_OK, WS_URL_HTTP_SCHEME_TYPE, url22 + 7, 4, 80, NULL, 0, NULL, 0, NULL, 0,
+          url22 + 12, 4  },
+        { url23, S_OK, WS_URL_HTTP_SCHEME_TYPE, host2, 6, 80 },
+        { url24, S_OK, WS_URL_HTTP_SCHEME_TYPE, url24 + 7, 4, 80, NULL, 0, path2, 7 },
+        { url25, S_OK, WS_URL_HTTP_SCHEME_TYPE, url24 + 7, 4, 80, NULL, 0, NULL, 0, query2, 7 },
+        { url26, S_OK, WS_URL_HTTP_SCHEME_TYPE, url24 + 7, 4, 80, NULL, 0, NULL, 0, NULL, 0, frag2, 6 },
+    };
+    WS_HEAP *heap;
+    WS_STRING str;
+    WS_HTTP_URL *url;
+    HRESULT hr;
+    UINT i;
+
+    hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsDecodeUrl( NULL, 0, heap, (WS_URL **)&url, NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+    str.chars  = NULL;
+    str.length = 0;
+    hr = WsDecodeUrl( &str, 0, heap, (WS_URL **)&url, NULL );
+    ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
+
+    str.chars  = url1;
+    str.length = lstrlenW( url1 );
+    hr = WsDecodeUrl( &str, 0, NULL, (WS_URL **)&url, NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+    for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+    {
+        static const WCHAR netpipe[] = {'n','e','t','.','p','i','p','e'};
+
+        str.length = lstrlenW( tests[i].str );
+        str.chars  = tests[i].str;
+        url = NULL;
+        hr = WsDecodeUrl( &str, 0, heap, (WS_URL **)&url, NULL );
+        ok( hr == tests[i].hr ||
+            broken(hr == WS_E_INVALID_FORMAT && str.length >= 8 && !memcmp(netpipe, str.chars, 8)),
+            "%u: got %08x\n", i, hr );
+        if (hr != S_OK) continue;
+
+        ok( url->url.scheme == tests[i].scheme, "%u: got %u\n", i, url->url.scheme );
+        ok( url->port == tests[i].port, "%u: got %u\n", i, url->port );
+
+        if (tests[i].host)
+        {
+            ok( url->host.length == tests[i].host_len, "%u: got %u\n", i, url->host.length );
+            ok( !memcmp( url->host.chars, tests[i].host, url->host.length * sizeof(WCHAR) ),
+                "%u: got %s\n", i, wine_dbgstr_wn(url->host.chars, url->host.length) );
+        }
+        else ok( !url->host.length, "%u: got %u\n", i, url->host.length );
+
+        if (tests[i].port_str)
+        {
+            ok( url->portAsString.length == tests[i].port_len, "%u: got %u\n", i, url->portAsString.length );
+            ok( !memcmp( url->portAsString.chars, tests[i].port_str, url->portAsString.length * sizeof(WCHAR) ),
+                "%u: got %s\n", i, wine_dbgstr_wn(url->portAsString.chars, url->portAsString.length) );
+        }
+        else ok( !url->portAsString.length, "%u: got %u\n", i, url->portAsString.length );
+
+        if (tests[i].path)
+        {
+            ok( url->path.length == tests[i].path_len, "%u: got %u\n", i, url->path.length );
+            ok( !memcmp( url->path.chars, tests[i].path, url->path.length * sizeof(WCHAR) ),
+                "%u: got %s\n", i, wine_dbgstr_wn(url->path.chars, url->path.length) );
+        }
+        else ok( !url->path.length, "%u: got %u\n", i, url->path.length );
+
+        if (tests[i].query)
+        {
+            ok( url->query.length == tests[i].query_len, "%u: got %u\n", i, url->query.length );
+            ok( !memcmp( url->query.chars, tests[i].query, url->query.length * sizeof(WCHAR) ),
+                "%u: got %s\n", i, wine_dbgstr_wn(url->query.chars, url->query.length) );
+        }
+        else ok( !url->query.length, "%u: got %u\n", i, url->query.length );
+
+        if (tests[i].fragment)
+        {
+            ok( url->fragment.length == tests[i].fragment_len, "%u: got %u\n", i, url->fragment.length );
+            ok( !memcmp( url->fragment.chars, tests[i].fragment, url->fragment.length * sizeof(WCHAR) ),
+                "%u: got %s\n", i, wine_dbgstr_wn(url->fragment.chars, url->fragment.length) );
+        }
+        else ok( !url->fragment.length, "%u: got %u\n", i, url->fragment.length );
+    }
+
+    WsFreeHeap( heap );
+}
+
+START_TEST(url)
+{
+    test_WsDecodeUrl();
+}
diff --git a/dlls/webservices/url.c b/dlls/webservices/url.c
new file mode 100644
index 0000000..8884fd1
--- /dev/null
+++ b/dlls/webservices/url.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2016 Hans Leidekker for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "webservices.h"
+
+#include "wine/debug.h"
+#include "wine/list.h"
+#include "wine/unicode.h"
+#include "webservices_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(webservices);
+
+static const WCHAR http[] = {'h','t','t','p'};
+static const WCHAR https[] = {'h','t','t','p','s'};
+static const WCHAR nettcp[] = {'n','e','t','.','t','c','p'};
+static const WCHAR soapudp[] = {'s','o','a','p','.','u','d','p'};
+static const WCHAR netpipe[] = {'n','e','t','.','p','i','p','e'};
+
+static WS_URL_SCHEME_TYPE scheme_type( const WCHAR *str, ULONG len )
+{
+    if (len == sizeof(http)/sizeof(http[0]) && !memicmpW( str, http, sizeof(http)/sizeof(http[0]) ))
+        return WS_URL_HTTP_SCHEME_TYPE;
+
+    if (len == sizeof(https)/sizeof(https[0]) && !memicmpW( str, https, sizeof(https)/sizeof(https[0]) ))
+        return WS_URL_HTTPS_SCHEME_TYPE;
+
+    if (len == sizeof(nettcp)/sizeof(nettcp[0]) && !memicmpW( str, nettcp, sizeof(nettcp)/sizeof(nettcp[0]) ))
+        return WS_URL_NETTCP_SCHEME_TYPE;
+
+    if (len == sizeof(soapudp)/sizeof(soapudp[0]) && !memicmpW( str, soapudp, sizeof(soapudp)/sizeof(soapudp[0]) ))
+        return WS_URL_SOAPUDP_SCHEME_TYPE;
+
+    if (len == sizeof(netpipe)/sizeof(netpipe[0]) && !memicmpW( str, netpipe, sizeof(netpipe)/sizeof(netpipe[0]) ))
+        return WS_URL_NETPIPE_SCHEME_TYPE;
+
+    return ~0u;
+}
+
+static USHORT default_port( WS_URL_SCHEME_TYPE scheme )
+{
+    switch (scheme)
+    {
+    case WS_URL_HTTP_SCHEME_TYPE:    return 80;
+    case WS_URL_HTTPS_SCHEME_TYPE:   return 443;
+    case WS_URL_NETTCP_SCHEME_TYPE:  return 808;
+    case WS_URL_SOAPUDP_SCHEME_TYPE:
+    case WS_URL_NETPIPE_SCHEME_TYPE: return 65535;
+    default:
+        ERR( "unhandled scheme %u\n", scheme );
+        return 0;
+    }
+}
+
+static WCHAR *url_decode( WCHAR *str, ULONG len, WS_HEAP *heap, ULONG *ret_len )
+{
+    WCHAR *p = str, *q, *ret;
+    BOOL decode = FALSE;
+    ULONG i, val;
+
+    *ret_len = len;
+    for (i = 0; i < len; i++, p++)
+    {
+        if ((len - i) < 3) break;
+        if (p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] ))
+        {
+            decode = TRUE;
+            *ret_len -= 2;
+        }
+    }
+    if (!decode) return str;
+
+    if (!(q = ret = ws_alloc( heap, *ret_len * sizeof(WCHAR) ))) return NULL;
+    p = str;
+    while (len)
+    {
+        if (len >= 3 && p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] ))
+        {
+            if (p[1] >= '0' && p[1] <= '9') val = (p[1] - '0') * 16;
+            else if (p[1] >= 'a' && p[1] <= 'f') val = (p[1] - 'a') * 16;
+            else val = (p[1] - 'A') * 16;
+
+            if (p[2] >= '0' && p[2] <= '9') val += p[2] - '0';
+            else if (p[1] >= 'a' && p[1] <= 'f') val += p[2] - 'a';
+            else val += p[1] - 'A';
+
+            *q++ = val;
+            p += 3;
+            len -= 3;
+        }
+        else
+        {
+            *q++ = *p++;
+            len -= 1;
+        }
+    }
+
+    return ret;
+}
+
+/**************************************************************************
+ *          WsDecodeUrl		[webservices.@]
+ */
+HRESULT WINAPI WsDecodeUrl( const WS_STRING *str, ULONG flags, WS_HEAP *heap, WS_URL **ret,
+                            WS_ERROR *error )
+{
+    HRESULT hr = WS_E_QUOTA_EXCEEDED;
+    WCHAR *p, *q, *decoded = NULL;
+    WS_HTTP_URL *url = NULL;
+    ULONG len, port = 0;
+
+    TRACE( "%s %08x %p %p %p\n", str ? debugstr_wn(str->chars, str->length) : "null", flags,
+           heap, ret, error );
+    if (error) FIXME( "ignoring error parameter\n" );
+
+    if (!str || !heap) return E_INVALIDARG;
+    if (!str->length) return WS_E_INVALID_FORMAT;
+    if (flags)
+    {
+        FIXME( "unimplemented flags %08x\n", flags );
+        return E_NOTIMPL;
+    }
+    if (!(decoded = url_decode( str->chars, str->length, heap, &len )) ||
+        !(url = ws_alloc( heap, sizeof(*url) ))) goto error;
+
+    hr = WS_E_INVALID_FORMAT;
+
+    p = q = decoded;
+    while (len && *q != ':') { q++; len--; };
+    if (*q != ':') goto error;
+    if ((url->url.scheme = scheme_type( p, q - p )) == ~0u) goto error;
+
+    if (!--len || *++q != '/') goto error;
+    if (!--len || *++q != '/') goto error;
+
+    p = ++q; len--;
+    while (len && *q != '/' && *q != ':' && *q != '?' && *q != '#') { q++; len--; };
+    if (q == p) goto error;
+    url->host.length = q - p;
+    url->host.chars  = p;
+
+    if (len && *q == ':')
+    {
+        p = ++q; len--;
+        while (len && isdigitW( *q ))
+        {
+            if ((port = port * 10 + *q - '0') > 65535) goto error;
+            q++; len--;
+        };
+        url->port = port;
+        url->portAsString.length = q - p;
+        url->portAsString.chars  = p;
+    }
+    if (!port)
+    {
+        url->port = default_port( url->url.scheme );
+        url->portAsString.length = 0;
+        url->portAsString.chars  = NULL;
+    }
+
+    if (len && *q == '/')
+    {
+        p = q;
+        while (len && *q != '?') { q++; len--; };
+        url->path.length = q - p;
+        url->path.chars  = p;
+    }
+    else url->path.length = 0;
+
+    if (len && *q == '?')
+    {
+        p = ++q; len--;
+        while (len && *q != '#') { q++; len--; };
+        url->query.length = q - p;
+        url->query.chars  = p;
+    }
+    else url->query.length = 0;
+
+    if (len && *q == '#')
+    {
+        p = ++q; len--;
+        while (len && *q != '#') { q++; len--; };
+        url->fragment.length = q - p;
+        url->fragment.chars  = p;
+    }
+    else url->fragment.length = 0;
+
+    *ret = (WS_URL *)url;
+    return S_OK;
+
+error:
+    if (decoded != str->chars) ws_free( heap, decoded );
+    ws_free( heap, url );
+    return hr;
+}
diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec
index 22cfe95..55e19ca 100644
--- a/dlls/webservices/webservices.spec
+++ b/dlls/webservices/webservices.spec
@@ -38,7 +38,7 @@
 @ stdcall WsCreateXmlBuffer(ptr ptr long ptr ptr)
 @ stub WsCreateXmlSecurityToken
 @ stdcall WsDateTimeToFileTime(ptr ptr ptr)
-@ stub WsDecodeUrl
+@ stdcall WsDecodeUrl(ptr long ptr ptr ptr)
 @ stub WsEncodeUrl
 @ stub WsEndReaderCanonicalization
 @ stub WsEndWriterCanonicalization
diff --git a/include/webservices.h b/include/webservices.h
index 62e1182..d9fc9d1 100644
--- a/include/webservices.h
+++ b/include/webservices.h
@@ -59,6 +59,12 @@ typedef struct _WS_CALL_PROPERTY WS_CALL_PROPERTY;
 typedef struct _WS_DOUBLE_DESCRIPTION WS_DOUBLE_DESCRIPTION;
 typedef struct _WS_DATETIME WS_DATETIME;
 typedef struct _WS_DATETIME_DESCRIPTION WS_DATETIME_DESCRIPTION;
+typedef struct _WS_URL WS_URL;
+typedef struct _WS_HTTP_URL WS_HTTP_URL;
+typedef struct _WS_HTTPS_URL WS_HTTPS_URL;
+typedef struct _WS_NETTCP_URL WS_NETTCP_URL;
+typedef struct _WS_SOAPUDP_URL WS_SOAPUDP_URL;
+typedef struct _WS_NETPIPE_URL WS_NETPIPE_URL;
 
 struct _WS_STRUCT_DESCRIPTION;
 struct _WS_XML_STRING;
@@ -1007,12 +1013,71 @@ struct _WS_DATETIME_DESCRIPTION {
     WS_DATETIME maxValue;
 };
 
+typedef enum {
+    WS_URL_HTTP_SCHEME_TYPE,
+    WS_URL_HTTPS_SCHEME_TYPE,
+    WS_URL_NETTCP_SCHEME_TYPE,
+    WS_URL_SOAPUDP_SCHEME_TYPE,
+    WS_URL_NETPIPE_SCHEME_TYPE
+} WS_URL_SCHEME_TYPE;
+
+enum {
+    WS_URL_FLAGS_ALLOW_HOST_WILDCARDS   = 0x1,
+    WS_URL_FLAGS_NO_PATH_COLLAPSE       = 0x2,
+    WS_URL_FLAGS_ZERO_TERMINATE         = 0x4
+};
+
+struct _WS_URL {
+    WS_URL_SCHEME_TYPE scheme;
+};
+
+struct _WS_HTTP_URL {
+    WS_URL url;
+    WS_STRING host;
+    USHORT port;
+    WS_STRING portAsString;
+    WS_STRING path;
+    WS_STRING query;
+    WS_STRING fragment;
+};
+
+struct _WS_HTTPS_URL {
+    WS_URL url;
+    WS_STRING host;
+    USHORT port;
+    WS_STRING portAsString;
+    WS_STRING path;
+    WS_STRING query;
+    WS_STRING fragment;
+};
+
+struct _WS_SOAPUDP_URL {
+    WS_URL url;
+    WS_STRING host;
+    USHORT port;
+    WS_STRING portAsString;
+    WS_STRING path;
+    WS_STRING query;
+    WS_STRING fragment;
+};
+
+struct _WS_NETPIPE_URL {
+    WS_URL url;
+    WS_STRING host;
+    USHORT port;
+    WS_STRING portAsString;
+    WS_STRING path;
+    WS_STRING query;
+    WS_STRING fragment;
+};
+
 HRESULT WINAPI WsAlloc(WS_HEAP*, SIZE_T, void**, WS_ERROR*);
 HRESULT WINAPI WsCall(WS_SERVICE_PROXY*, const WS_OPERATION_DESCRIPTION*, const void**,
                       WS_HEAP*, const WS_CALL_PROPERTY*, const ULONG, const WS_ASYNC_CONTEXT*,
                       WS_ERROR*);
 HRESULT WINAPI WsCloseChannel(WS_CHANNEL*, const WS_ASYNC_CONTEXT*, WS_ERROR*);
 HRESULT WINAPI WsCloseServiceProxy(WS_SERVICE_PROXY*, const WS_ASYNC_CONTEXT*, WS_ERROR*);
+HRESULT WINAPI WsCombineUrl(const WS_STRING*, const WS_STRING*, ULONG, WS_HEAP*, WS_STRING*, WS_ERROR*);
 HRESULT WINAPI WsCreateChannel(WS_CHANNEL_TYPE, WS_CHANNEL_BINDING, const WS_CHANNEL_PROPERTY*,
                                ULONG, const WS_SECURITY_DESCRIPTION*, WS_CHANNEL**, WS_ERROR*);
 HRESULT WINAPI WsCreateError(const WS_ERROR_PROPERTY*, ULONG, WS_ERROR**);
@@ -1034,6 +1099,8 @@ HRESULT WINAPI WsCreateWriter(const WS_XML_WRITER_PROPERTY*, ULONG, WS_XML_WRITE
 HRESULT WINAPI WsCreateXmlBuffer(WS_HEAP*, const WS_XML_BUFFER_PROPERTY*, ULONG, WS_XML_BUFFER**,
                                  WS_ERROR*);
 HRESULT WINAPI WsDateTimeToFileTime(const WS_DATETIME*, FILETIME*, WS_ERROR*);
+HRESULT WINAPI WsDecodeUrl(const WS_STRING*, ULONG, WS_HEAP*, WS_URL**, WS_ERROR*);
+HRESULT WINAPI WsEncodeUrl(const WS_URL*, ULONG, WS_HEAP*, WS_STRING*, WS_ERROR*);
 HRESULT WINAPI WsFileTimeToDateTime(const FILETIME*, WS_DATETIME*, WS_ERROR*);
 HRESULT WINAPI WsFillReader(WS_XML_READER*, ULONG, const WS_ASYNC_CONTEXT*, WS_ERROR*);
 HRESULT WINAPI WsFindAttribute(WS_XML_READER*, const WS_XML_STRING*, const WS_XML_STRING*, BOOL,
-- 
2.8.1




More information about the wine-patches mailing list