[PATCH v2] dpnet: Implement IDirectPlay8Address GetURLW/A.

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Wed Aug 15 22:39:09 CDT 2018


Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
v2: Use sprintfW so user32 isn't required.
 - 
 dlls/dpnet/address.c       | 114 ++++++++++++++++++++++++++++++---
 dlls/dpnet/tests/address.c | 155 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 259 insertions(+), 10 deletions(-)

diff --git a/dlls/dpnet/address.c b/dlls/dpnet/address.c
index 0bfa2bc..a4c864e 100644
--- a/dlls/dpnet/address.c
+++ b/dlls/dpnet/address.c
@@ -47,6 +47,22 @@ static char *heap_strdupA( const char *str )
     return ret;
 }
 
+static inline WCHAR *heap_strdupAtoW(const char *str)
+{
+    LPWSTR ret = NULL;
+
+    if(str) {
+        DWORD len;
+
+        len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+        ret = heap_alloc(len*sizeof(WCHAR));
+        if(ret)
+            MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
+    }
+
+    return ret;
+}
+
 static BOOL add_component(IDirectPlay8AddressImpl *This, struct component *item)
 {
     if(This->comp_count == This->comp_array_size)
@@ -258,20 +274,98 @@ static HRESULT WINAPI IDirectPlay8AddressImpl_Clear(IDirectPlay8Address *iface)
   return DPN_OK; 
 }
 
-static HRESULT WINAPI IDirectPlay8AddressImpl_GetURLW(IDirectPlay8Address *iface, WCHAR *pwszURL,
-        DWORD *pdwNumChars)
+static HRESULT WINAPI IDirectPlay8AddressImpl_GetURLW(IDirectPlay8Address *iface, WCHAR *url, DWORD *length)
 {
-  IDirectPlay8AddressImpl *This = impl_from_IDirectPlay8Address(iface);
-  TRACE("(%p): stub\n", This);
-  return DPN_OK; 
+    IDirectPlay8AddressImpl *This = impl_from_IDirectPlay8Address(iface);
+    HRESULT hr = DPNERR_BUFFERTOOSMALL;
+    int i;
+    WCHAR buffer[1024] = {0};
+    const static WCHAR comma[] = {';',0};
+    const static WCHAR format_stringW[] = {'%', 's','=','%','s',0};
+    const static WCHAR format_dword[] = {'%', 's','=','%','d',0};
+    static const WCHAR format_guid[] = { '%', 's','=','%', '%','7','B',
+        '%','0','8','X','-','%','0','4','X','-','%','0','4','X','-','%','0','2',
+        'X','%','0','2','X','-',
+        '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%','0',
+        '2','X','%','0','2','X','%','%','7','D',0};
+
+    TRACE("(%p, %p, %p)\n", This, url, length);
+
+    if(!length || (!url && *length != 0))
+        return DPNERR_INVALIDPOINTER;
+
+    for(i=0; i < This->comp_count; i++)
+    {
+        int position = strlenW(buffer);
+        struct component *entry = This->components[i];
+
+        if(position)
+            lstrcatW(&buffer[position++], comma);
+
+        switch(entry->type)
+        {
+            case DPNA_DATATYPE_GUID:
+                sprintfW( &buffer[position], format_guid, entry->name, entry->data.guid.Data1, entry->data.guid.Data2, entry->data.guid.Data3,
+                      entry->data.guid.Data4[0], entry->data.guid.Data4[1], entry->data.guid.Data4[2], entry->data.guid.Data4[3],
+                      entry->data.guid.Data4[4], entry->data.guid.Data4[5], entry->data.guid.Data4[6], entry->data.guid.Data4[7] );
+                break;
+            case DPNA_DATATYPE_STRING:
+                sprintfW(&buffer[position], format_stringW, entry->name, entry->data.string);
+                break;
+            case DPNA_DATATYPE_DWORD:
+                sprintfW(&buffer[position], format_dword, entry->name, entry->data.value);
+                break;
+            case DPNA_DATATYPE_STRING_ANSI:
+            {
+                WCHAR *str = heap_strdupAtoW(entry->data.ansi);
+                sprintfW(&buffer[position], format_stringW, entry->name, str);
+                heap_free(str);
+                break;
+            }
+            case DPNA_DATATYPE_BINARY:
+            default:
+                FIXME("Unsupported type %d\n", entry->type);
+        }
+    }
+
+    if(url && *length >= lstrlenW(buffer) + lstrlenW(DPNA_HEADER) + 1)
+    {
+        lstrcpyW(url, DPNA_HEADER);
+        lstrcatW(url, buffer);
+        hr = DPN_OK;
+    }
+
+    *length = lstrlenW(buffer) + lstrlenW(DPNA_HEADER) + 1;
+
+    return hr;
 }
 
-static HRESULT WINAPI IDirectPlay8AddressImpl_GetURLA(IDirectPlay8Address *iface, CHAR *pszURL,
-        DWORD *pdwNumChars)
+static HRESULT WINAPI IDirectPlay8AddressImpl_GetURLA(IDirectPlay8Address *iface, char *url, DWORD *length)
 {
-  IDirectPlay8AddressImpl *This = impl_from_IDirectPlay8Address(iface);
-  TRACE("(%p): stub\n", This);
-  return DPN_OK; 
+    IDirectPlay8AddressImpl *This = impl_from_IDirectPlay8Address(iface);
+    HRESULT hr;
+    WCHAR *buffer = NULL;
+
+    TRACE("(%p, %p %p)\n", This, url, length);
+
+    if(!length || (!url && *length != 0))
+        return DPNERR_INVALIDPOINTER;
+
+    if(url && *length)
+    {
+        url[0] = '\0';
+        buffer = heap_alloc(*length * sizeof(WCHAR));
+    }
+
+    hr = IDirectPlay8Address_GetURLW(iface, buffer, length);
+    if(hr == DPN_OK)
+    {
+        DWORD size;
+        size = WideCharToMultiByte(CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL);
+        WideCharToMultiByte(CP_ACP, 0, buffer, -1, url, size, NULL, NULL);
+    }
+    heap_free(buffer);
+    return hr;
 }
 
 static HRESULT WINAPI IDirectPlay8AddressImpl_GetSP(IDirectPlay8Address *iface, GUID *pguidSP)
diff --git a/dlls/dpnet/tests/address.c b/dlls/dpnet/tests/address.c
index a1dcdef..526f41f 100644
--- a/dlls/dpnet/tests/address.c
+++ b/dlls/dpnet/tests/address.c
@@ -305,6 +305,159 @@ static void address_setsp(void)
     }
 }
 
+static void address_urlW(void)
+{
+    HRESULT hr;
+    IDirectPlay8Address *localaddr = NULL;
+    static const WCHAR urlW1[] = {'x','-','d','i','r','e','c','t','p','l','a','y',':','/','p','r','o','v','i','d','e','r',
+                                  '=','%','7','B','E','B','F','E','7','B','A','0','-','6','2','8','D','-','1','1','D','2',
+                                  '-','A','E','0','F','-','0','0','6','0','9','7','B','0','1','4','1','1','%','7','D',0 };
+    static const WCHAR urlW2[] = {'x','-','d','i','r','e','c','t','p','l','a','y',':','/','p','r','o','v','i','d','e','r',
+                                  '=','%','7','B','E','B','F','E','7','B','A','0','-','6','2','8','D','-','1','1','D','2',
+                                  '-','A','E','0','F','-','0','0','6','0','9','7','B','0','1','4','1','1','%','7','D',
+                                  ';','p','o','r','t','=','4','3','2','1',0 };
+    static const WCHAR urlW3[] = {'x','-','d','i','r','e','c','t','p','l','a','y',':','/','p','r','o','v','i','d','e','r',
+                                  '=','%','7','B','E','B','F','E','7','B','A','0','-','6','2','8','D','-','1','1','D','2',
+                                  '-','A','E','0','F','-','0','0','6','0','9','7','B','0','1','4','1','1','%','7','D',
+                                  ';','p','o','r','t','=','4','3','2','1',';','h','o','s','t','n','a','m','e','=','l',
+                                  'o','c','a','l','h','o','s','t', 0 };
+
+    hr = CoCreateInstance( &CLSID_DirectPlay8Address, NULL, CLSCTX_ALL, &IID_IDirectPlay8Address, (LPVOID*)&localaddr);
+    ok(hr == S_OK, "Failed to create IDirectPlay8Address object\n");
+    if(SUCCEEDED(hr))
+    {
+        WCHAR *buffer = NULL;
+        DWORD bufflen = 0, bufflen2;
+        DWORD port = 4321;
+
+        hr = IDirectPlay8Address_SetSP(localaddr, &CLSID_DP8SP_TCPIP);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        hr = IDirectPlay8Address_GetURLW(localaddr, buffer, NULL);
+        ok(hr == DPNERR_INVALIDPOINTER, "got 0x%08x\n", hr);
+
+        bufflen = 10;
+        hr = IDirectPlay8Address_GetURLW(localaddr, NULL, &bufflen);
+        ok(hr == DPNERR_INVALIDPOINTER, "got 0x%08x\n", hr);
+
+        bufflen = 0;
+        hr = IDirectPlay8Address_GetURLW(localaddr, NULL, &bufflen);
+        ok(bufflen == 66, "got %d\n", bufflen);
+        ok(hr == DPNERR_BUFFERTOOSMALL, "got 0x%08x\n", hr);
+        buffer =  HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufflen * sizeof(WCHAR));
+
+        hr = IDirectPlay8Address_GetURLW(localaddr, buffer, &bufflen);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpW(urlW1, buffer), "got %s\n", wine_dbgstr_w(buffer));
+        HeapFree(GetProcessHeap(), 0, buffer);
+
+        hr = IDirectPlay8Address_AddComponent(localaddr, DPNA_KEY_PORT, &port, sizeof(DWORD), DPNA_DATATYPE_DWORD);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        bufflen = 0;
+        hr = IDirectPlay8Address_GetURLW(localaddr, NULL, &bufflen);
+        ok(hr == DPNERR_BUFFERTOOSMALL, "got 0x%08x\n", hr);
+        buffer =  HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufflen * sizeof(WCHAR));
+
+        bufflen2 = bufflen/2;
+        hr = IDirectPlay8Address_GetURLW(localaddr, buffer, &bufflen2);
+        ok(hr == DPNERR_BUFFERTOOSMALL, "got 0x%08x\n", hr);
+        ok(!lstrlenW(buffer), "wrong length\n");
+
+        hr = IDirectPlay8Address_GetURLW(localaddr, buffer, &bufflen);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpW(urlW2, buffer), "got %s\n", wine_dbgstr_w(buffer));
+        HeapFree(GetProcessHeap(), 0, buffer);
+
+        hr = IDirectPlay8Address_AddComponent(localaddr, DPNA_KEY_HOSTNAME, &localhost, sizeof(localhost), DPNA_DATATYPE_STRING);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        bufflen = 0;
+        hr = IDirectPlay8Address_GetURLW(localaddr, NULL, &bufflen);
+        ok(hr == DPNERR_BUFFERTOOSMALL, "got 0x%08x\n", hr);
+        buffer =  HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufflen * sizeof(WCHAR));
+
+        hr = IDirectPlay8Address_GetURLW(localaddr, buffer, &bufflen);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpW(urlW3, buffer), "got %s\n", wine_dbgstr_w(buffer));
+        HeapFree(GetProcessHeap(), 0, buffer);
+
+        IDirectPlay8Address_Release(localaddr);
+    }
+}
+
+static void address_urlA(void)
+{
+    HRESULT hr;
+    IDirectPlay8Address *localaddr = NULL;
+    static const char urlA1[] = "x-directplay:/provider=%7BEBFE7BA0-628D-11D2-AE0F-006097B01411%7D";
+    static const char urlA2[] = "x-directplay:/provider=%7BEBFE7BA0-628D-11D2-AE0F-006097B01411%7D;port=4321";
+    static const char urlA3[] = "x-directplay:/provider=%7BEBFE7BA0-628D-11D2-AE0F-006097B01411%7D;port=4321;hostname=localhost";
+    static const char localhostA[] = "localhost";
+
+    hr = CoCreateInstance( &CLSID_DirectPlay8Address, NULL, CLSCTX_ALL, &IID_IDirectPlay8Address, (LPVOID*)&localaddr);
+    ok(hr == S_OK, "Failed to create IDirectPlay8Address object\n");
+    if(SUCCEEDED(hr))
+    {
+        char *buffer = NULL;
+        DWORD bufflen = 0, bufflen2;
+        DWORD port = 4321;
+
+        hr = IDirectPlay8Address_SetSP(localaddr, &CLSID_DP8SP_TCPIP);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        hr = IDirectPlay8Address_GetURLA(localaddr, buffer, NULL);
+        ok(hr == DPNERR_INVALIDPOINTER, "got 0x%08x\n", hr);
+
+        bufflen = 10;
+        hr = IDirectPlay8Address_GetURLA(localaddr, NULL, &bufflen);
+        ok(hr == DPNERR_INVALIDPOINTER, "got 0x%08x\n", hr);
+
+        bufflen = 0;
+        hr = IDirectPlay8Address_GetURLA(localaddr, NULL, &bufflen);
+        ok(hr == DPNERR_BUFFERTOOSMALL, "got 0x%08x\n", hr);
+        buffer =  HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufflen);
+
+        bufflen2 = bufflen/2;
+        hr = IDirectPlay8Address_GetURLA(localaddr, buffer, &bufflen2);
+        ok(hr == DPNERR_BUFFERTOOSMALL, "got 0x%08x\n", hr);
+        ok(!strlen(buffer), "wrong length\n");
+
+        hr = IDirectPlay8Address_GetURLA(localaddr, buffer, &bufflen);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpA(urlA1, buffer), "got %s\n", buffer);
+        HeapFree(GetProcessHeap(), 0, buffer);
+
+        hr = IDirectPlay8Address_AddComponent(localaddr, DPNA_KEY_PORT, &port, sizeof(DWORD), DPNA_DATATYPE_DWORD);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        bufflen = 0;
+        hr = IDirectPlay8Address_GetURLA(localaddr, NULL, &bufflen);
+        ok(hr == DPNERR_BUFFERTOOSMALL, "got 0x%08x\n", hr);
+        buffer =  HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufflen);
+
+        hr = IDirectPlay8Address_GetURLA(localaddr, buffer, &bufflen);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpA(urlA2, buffer), "got %s\n", buffer);
+        HeapFree(GetProcessHeap(), 0, buffer);
+
+        hr = IDirectPlay8Address_AddComponent(localaddr, DPNA_KEY_HOSTNAME, &localhostA, sizeof(localhostA), DPNA_DATATYPE_STRING_ANSI);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        bufflen = 0;
+        hr = IDirectPlay8Address_GetURLA(localaddr, NULL, &bufflen);
+        ok(hr == DPNERR_BUFFERTOOSMALL, "got 0x%08x\n", hr);
+        buffer =  HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufflen);
+
+        hr = IDirectPlay8Address_GetURLA(localaddr, buffer, &bufflen);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(!lstrcmpA(urlA3, buffer), "got %s\n", buffer);
+        HeapFree(GetProcessHeap(), 0, buffer);
+
+        IDirectPlay8Address_Release(localaddr);
+    }
+}
+
 static void address_duplicate(void)
 {
     HRESULT hr;
@@ -382,6 +535,8 @@ START_TEST(address)
     address_addcomponents();
     address_setsp();
     address_duplicate();
+    address_urlW();
+    address_urlA();
 
     CoUninitialize();
 }
-- 
1.9.1




More information about the wine-devel mailing list