Signed-off-by: Alistair Leslie-Hughes leslie_alistair@hotmail.com --- dlls/dpnet/address.c | 122 ++++++++++++++++++++++++++++++++--- dlls/dpnet/tests/address.c | 155 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+), 10 deletions(-)
diff --git a/dlls/dpnet/address.c b/dlls/dpnet/address.c index 0bfa2bc..55957ce 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,106 @@ 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}; + WCHAR data[1024]; + 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++) + { + struct component *entry = This->components[i]; + + if(i) + lstrcatW(buffer, comma); + + switch(entry->type) + { + case DPNA_DATATYPE_GUID: + sprintfW(data, 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(data, format_stringW, entry->name, entry->data.string); + break; + case DPNA_DATATYPE_DWORD: + sprintfW(data, format_dword, entry->name, entry->data.value); + break; + case DPNA_DATATYPE_STRING_ANSI: + { + WCHAR *str = heap_strdupAtoW(entry->data.ansi); + sprintfW(data, format_stringW, entry->name, str); + heap_free(str); + break; + } + case DPNA_DATATYPE_BINARY: + default: + FIXME("Unsupported type %d\n", entry->type); + } + + strcatW(buffer, data); + } + + 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); + if(size <= *length) + WideCharToMultiByte(CP_ACP, 0, buffer, -1, url, *length, NULL, NULL); + else + { + *length = size; + hr = DPNERR_BUFFERTOOSMALL; + } + } + 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(); }