1
0
mirror of https://github.com/solemnwarning/directplay-lite synced 2024-12-30 16:45:37 +01:00

Partial DirectPlay8Address implementation.

This commit is contained in:
Daniel Collins 2018-08-23 00:10:18 +01:00
parent 1c41ec3b76
commit b8364c5997
2 changed files with 360 additions and 15 deletions

View File

@ -2,6 +2,8 @@
#include <dplay8.h>
#include <objbase.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <windows.h>
#include "DirectPlay8Address.hpp"
@ -17,6 +19,41 @@ DirectPlay8Address::DirectPlay8Address(std::atomic<unsigned int> *global_refcoun
AddRef();
}
DirectPlay8Address::DirectPlay8Address(const DirectPlay8Address &src):
global_refcount(src.global_refcount),
local_refcount(0),
user_data(src.user_data)
{
replace_components(src.components);
AddRef();
}
DirectPlay8Address::~DirectPlay8Address()
{
clear_components();
}
void DirectPlay8Address::clear_components()
{
for(auto c = components.begin(); c != components.end(); ++c)
{
delete *c;
}
components.clear();
}
void DirectPlay8Address::replace_components(const std::vector<Component*> src)
{
clear_components();
components.reserve(src.size());
for(auto c = src.begin(); c != src.end(); ++c)
{
components.push_back((*c)->clone());
}
}
HRESULT DirectPlay8Address::QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == IID_IDirectPlay8Address || riid == IID_IUnknown)
@ -71,12 +108,16 @@ HRESULT DirectPlay8Address::BuildFromURLA(CHAR* pszSourceURL)
HRESULT DirectPlay8Address::Duplicate(PDIRECTPLAY8ADDRESS* ppdpaNewAddress)
{
UNIMPLEMENTED("DirectPlay8Address::Duplicate");
*ppdpaNewAddress = new DirectPlay8Address(*this);
return S_OK;
}
HRESULT DirectPlay8Address::SetEqual(PDIRECTPLAY8ADDRESS pdpaAddress)
{
UNIMPLEMENTED("DirectPlay8Address::SetEqual");
replace_components(((DirectPlay8Address*)(pdpaAddress))->components);
user_data = ((DirectPlay8Address*)(pdpaAddress))->user_data;
return S_OK;
}
HRESULT DirectPlay8Address::IsEqual(PDIRECTPLAY8ADDRESS pdpaAddress)
@ -86,7 +127,10 @@ HRESULT DirectPlay8Address::IsEqual(PDIRECTPLAY8ADDRESS pdpaAddress)
HRESULT DirectPlay8Address::Clear()
{
UNIMPLEMENTED("DirectPlay8Address::Clear");
clear_components();
user_data.clear();
return S_OK;
}
HRESULT DirectPlay8Address::GetURLW(WCHAR* pwszURL, PDWORD pdwNumChars)
@ -101,55 +145,292 @@ HRESULT DirectPlay8Address::GetURLA(CHAR* pszURL, PDWORD pdwNumChars)
HRESULT DirectPlay8Address::GetSP(GUID* pguidSP)
{
UNIMPLEMENTED("DirectPlay8Address::GetSP");
GUID buf;
DWORD buf_size = sizeof(buf);
DWORD type;
HRESULT res = GetComponentByName(DPNA_KEY_PROVIDER, &buf, &buf_size, &type);
if(res == S_OK && type == DPNA_DATATYPE_GUID)
{
*pguidSP = buf;
return S_OK;
}
else if(res == S_OK)
{
return DPNERR_GENERIC;
}
else{
return res;
}
}
HRESULT DirectPlay8Address::GetUserData(LPVOID pvUserData, PDWORD pdwBufferSize)
{
UNIMPLEMENTED("DirectPlay8Address::GetUserData");
if(user_data.empty())
{
return DPNERR_DOESNOTEXIST;
}
if(pvUserData != NULL && *pdwBufferSize >= user_data.size())
{
memcpy(pvUserData, user_data.data(), user_data.size());
*pdwBufferSize = user_data.size();
return S_OK;
}
else{
*pdwBufferSize = user_data.size();
return DPNERR_BUFFERTOOSMALL;
}
}
HRESULT DirectPlay8Address::SetSP(CONST GUID* CONST pguidSP)
{
UNIMPLEMENTED("DirectPlay8Address::SetSP");
return AddComponent(DPNA_KEY_PROVIDER, pguidSP, sizeof(*pguidSP), DPNA_DATATYPE_GUID);
}
HRESULT DirectPlay8Address::SetUserData(CONST void* CONST pvUserData, CONST DWORD dwDataSize)
{
UNIMPLEMENTED("DirectPlay8Address::SetUserData");
user_data.clear();
if(pvUserData != NULL && dwDataSize > 0)
{
user_data.insert(user_data.end(), (unsigned char*)(pvUserData),(unsigned char*)(pvUserData) + dwDataSize);
}
return S_OK;
}
HRESULT DirectPlay8Address::GetNumComponents(PDWORD pdwNumComponents)
{
UNIMPLEMENTED("DirectPlay8Address::GetNumComponents");
return components.size();
}
HRESULT DirectPlay8Address::GetComponentByName(CONST WCHAR* CONST pwszName, LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType)
{
UNIMPLEMENTED("DirectPlay8Address::GetComponentByName");
for(auto c = components.begin(); c != components.end(); ++c)
{
if((*c)->name == pwszName)
{
return (*c)->get_component(pvBuffer, pdwBufferSize, pdwDataType);
}
}
return DPNERR_DOESNOTEXIST;
}
HRESULT DirectPlay8Address::GetComponentByIndex(CONST DWORD dwComponentID, WCHAR* pwszName, PDWORD pdwNameLen, void* pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType)
{
UNIMPLEMENTED("DirectPlay8Address::GetComponentByIndex");
if(dwComponentID >= components.size())
{
return DPNERR_DOESNOTEXIST;
}
Component *c = components[dwComponentID];
HRESULT res = c->get_component(pvBuffer, pdwBufferSize, pdwDataType);
if(*pdwNameLen > c->name.length() && pwszName != NULL)
{
wcscpy(pwszName, c->name.c_str());
*pdwNameLen = c->name.length() + 1;
}
else{
*pdwNameLen = c->name.length() + 1;
res = DPNERR_BUFFERTOOSMALL;
}
return res;
}
HRESULT DirectPlay8Address::AddComponent(CONST WCHAR* CONST pwszName, CONST void* CONST lpvData, CONST DWORD dwDataSize, CONST DWORD dwDataType)
{
UNIMPLEMENTED("DirectPlay8Address::AddComponent");
auto existing_component = components.begin();
for(; existing_component != components.end(); ++existing_component)
{
if((*existing_component)->name == pwszName)
{
break;
}
}
Component *new_component;
switch(dwDataType)
{
case DPNA_DATATYPE_STRING:
new_component = new StringComponentW(pwszName, (const wchar_t*)(lpvData), dwDataSize);
break;
case DPNA_DATATYPE_STRING_ANSI:
new_component = new StringComponentA(pwszName, (const char*)(lpvData), dwDataSize);
break;
case DPNA_DATATYPE_DWORD:
if(dwDataSize != sizeof(DWORD))
{
return DPNERR_INVALIDPARAM;
}
new_component = new DWORDComponent(pwszName, *((DWORD*)(lpvData)));
break;
case DPNA_DATATYPE_GUID:
if(dwDataSize != sizeof(GUID))
{
return DPNERR_INVALIDPARAM;
}
new_component = new GUIDComponent(pwszName, *((GUID*)(lpvData)));
break;
default:
UNIMPLEMENTED("DirectPlay8Address::AddComponent() with dwDataType %u", (unsigned)(dwDataType));
}
if(existing_component != components.end())
{
delete *existing_component;
*existing_component = new_component;
}
else{
components.push_back(new_component);
}
return S_OK;
}
HRESULT DirectPlay8Address::GetDevice(GUID* pDevGuid)
{
UNIMPLEMENTED("DirectPlay8Address::GetDevice");
GUID buf;
DWORD buf_size = sizeof(buf);
DWORD type;
HRESULT res = GetComponentByName(DPNA_KEY_DEVICE, &buf, &buf_size, &type);
if(res == S_OK && type == DPNA_DATATYPE_GUID)
{
*pDevGuid = buf;
return S_OK;
}
else if(res == S_OK)
{
return DPNERR_GENERIC;
}
else{
return res;
}
}
HRESULT DirectPlay8Address::SetDevice(CONST GUID* CONST devGuid)
{
UNIMPLEMENTED("DirectPlay8Address::SetDevice");
return AddComponent(DPNA_KEY_DEVICE, devGuid, sizeof(*devGuid), DPNA_DATATYPE_GUID);
}
HRESULT DirectPlay8Address::BuildFromDirectPlay4Address(LPVOID pvAddress, DWORD dwDataSize)
{
UNIMPLEMENTED("DirectPlay8Address::BuildFromDirectPlay4Address");
}
DirectPlay8Address::Component::Component(const std::wstring &name, DWORD type):
name(name),
type(type) {}
DirectPlay8Address::Component::~Component() {}
DirectPlay8Address::StringComponentW::StringComponentW(const std::wstring &name, const wchar_t *lpvData, DWORD dwDataSize):
Component(name, DPNA_DATATYPE_STRING), value(lpvData, dwDataSize) {}
DirectPlay8Address::Component *DirectPlay8Address::StringComponentW::clone()
{
return new DirectPlay8Address::StringComponentW(name, value.data(), value.length());
}
HRESULT DirectPlay8Address::StringComponentW::get_component(LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType)
{
*pdwDataType = DPNA_DATATYPE_STRING;
if(*pdwBufferSize > value.length() && pvBuffer != NULL)
{
wcscpy((wchar_t*)(pvBuffer), value.c_str());
*pdwBufferSize = value.length() + 1;
return S_OK;
}
else{
*pdwBufferSize = value.length() + 1;
return DPNERR_BUFFERTOOSMALL;
}
}
DirectPlay8Address::StringComponentA::StringComponentA(const std::wstring &name, const char *lpvData, DWORD dwDataSize):
Component(name, DPNA_DATATYPE_STRING_ANSI), value(lpvData, dwDataSize) {}
HRESULT DirectPlay8Address::StringComponentA::get_component(LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType)
{
*pdwDataType = DPNA_DATATYPE_STRING_ANSI;
if(*pdwBufferSize > value.length() && pvBuffer != NULL)
{
strcpy((char*)(pvBuffer), value.c_str());
*pdwBufferSize = value.length() + 1;
return S_OK;
}
else{
*pdwBufferSize = value.length() + 1;
return DPNERR_BUFFERTOOSMALL;
}
}
DirectPlay8Address::Component *DirectPlay8Address::StringComponentA::clone()
{
return new DirectPlay8Address::StringComponentA(name, value.data(), value.length());
}
DirectPlay8Address::DWORDComponent::DWORDComponent(const std::wstring &name, DWORD value):
Component(name, DPNA_DATATYPE_DWORD), value(value) {}
DirectPlay8Address::Component *DirectPlay8Address::DWORDComponent::clone()
{
return new DirectPlay8Address::DWORDComponent(name, value);
}
HRESULT DirectPlay8Address::DWORDComponent::get_component(LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType)
{
*pdwDataType = DPNA_DATATYPE_DWORD;
if(*pdwBufferSize >= sizeof(DWORD) && pvBuffer != NULL)
{
*((DWORD*)(pvBuffer)) = value;
*pdwBufferSize = sizeof(DWORD);
return S_OK;
}
else{
*pdwBufferSize = sizeof(DWORD);
return DPNERR_BUFFERTOOSMALL;
}
}
DirectPlay8Address::GUIDComponent::GUIDComponent(const std::wstring &name, GUID value):
Component(name, DPNA_DATATYPE_GUID), value(value) {}
DirectPlay8Address::Component *DirectPlay8Address::GUIDComponent::clone()
{
return new DirectPlay8Address::GUIDComponent(name, value);
}
HRESULT DirectPlay8Address::GUIDComponent::get_component(LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType)
{
*pdwDataType = DPNA_DATATYPE_GUID;
if(*pdwBufferSize >= sizeof(GUID) && pvBuffer != NULL)
{
*((GUID*)(pvBuffer)) = value;
*pdwBufferSize = sizeof(GUID);
return S_OK;
}
else{
*pdwBufferSize = sizeof(GUID);
return DPNERR_BUFFERTOOSMALL;
}
}

View File

@ -4,16 +4,80 @@
#include <atomic>
#include <dplay8.h>
#include <objbase.h>
#include <string>
#include <vector>
class DirectPlay8Address: public IDirectPlay8Address
{
private:
class Component
{
public:
const std::wstring name;
const DWORD type;
virtual ~Component();
virtual Component *clone() = 0;
virtual HRESULT get_component(LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType) = 0;
protected:
Component(const std::wstring &name, DWORD type);
};
class StringComponentW: public Component
{
public:
const std::wstring value;
StringComponentW(const std::wstring &name, const wchar_t *lpvData, DWORD dwDataSize);
virtual Component *clone();
virtual HRESULT get_component(LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType);
};
class StringComponentA: public Component
{
public:
const std::string value;
StringComponentA(const std::wstring &name, const char *lpvData, DWORD dwDataSize);
virtual Component *clone();
virtual HRESULT get_component(LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType);
};
class DWORDComponent: public Component
{
public:
const DWORD value;
DWORDComponent(const std::wstring &name, DWORD value);
virtual Component *clone();
virtual HRESULT get_component(LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType);
};
class GUIDComponent: public Component
{
public:
const GUID value;
GUIDComponent(const std::wstring &name, GUID value);
virtual Component *clone();
virtual HRESULT get_component(LPVOID pvBuffer, PDWORD pdwBufferSize, PDWORD pdwDataType);
};
std::atomic<unsigned int> * const global_refcount;
ULONG local_refcount;
std::vector<Component*> components;
std::vector<unsigned char> user_data;
void clear_components();
void replace_components(const std::vector<Component*> src);
public:
DirectPlay8Address(std::atomic<unsigned int> *global_refcount);
virtual ~DirectPlay8Address() {}
DirectPlay8Address(const DirectPlay8Address &src);
virtual ~DirectPlay8Address();
/* IUnknown */
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override;