mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 22:29:15 +01:00
[util] Fix COM private data bug when passing NULL interface
Fixes test failure in wine's DXGI tests.
This commit is contained in:
parent
6d999fad89
commit
96b9058fbf
@ -12,6 +12,7 @@ namespace dxvk {
|
|||||||
UINT size,
|
UINT size,
|
||||||
const void* data)
|
const void* data)
|
||||||
: m_guid(guid),
|
: m_guid(guid),
|
||||||
|
m_type(ComPrivateDataType::Data),
|
||||||
m_size(size),
|
m_size(size),
|
||||||
m_data(std::malloc(size)) {
|
m_data(std::malloc(size)) {
|
||||||
std::memcpy(m_data, data, size);
|
std::memcpy(m_data, data, size);
|
||||||
@ -22,8 +23,9 @@ namespace dxvk {
|
|||||||
REFGUID guid,
|
REFGUID guid,
|
||||||
const IUnknown* iface)
|
const IUnknown* iface)
|
||||||
: m_guid (guid),
|
: m_guid (guid),
|
||||||
|
m_type(ComPrivateDataType::Iface),
|
||||||
m_iface (const_cast<IUnknown*>(iface)) {
|
m_iface (const_cast<IUnknown*>(iface)) {
|
||||||
if (m_iface != nullptr)
|
if (m_iface)
|
||||||
m_iface->AddRef();
|
m_iface->AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,10 +37,12 @@ namespace dxvk {
|
|||||||
|
|
||||||
ComPrivateDataEntry::ComPrivateDataEntry(ComPrivateDataEntry&& other)
|
ComPrivateDataEntry::ComPrivateDataEntry(ComPrivateDataEntry&& other)
|
||||||
: m_guid (other.m_guid),
|
: m_guid (other.m_guid),
|
||||||
|
m_type (other.m_type),
|
||||||
m_size (other.m_size),
|
m_size (other.m_size),
|
||||||
m_data (other.m_data),
|
m_data (other.m_data),
|
||||||
m_iface (other.m_iface) {
|
m_iface (other.m_iface) {
|
||||||
other.m_guid = __uuidof(IUnknown);
|
other.m_guid = __uuidof(IUnknown);
|
||||||
|
other.m_type = ComPrivateDataType::None;
|
||||||
other.m_size = 0;
|
other.m_size = 0;
|
||||||
other.m_data = nullptr;
|
other.m_data = nullptr;
|
||||||
other.m_iface = nullptr;
|
other.m_iface = nullptr;
|
||||||
@ -48,11 +52,13 @@ namespace dxvk {
|
|||||||
ComPrivateDataEntry& ComPrivateDataEntry::operator = (ComPrivateDataEntry&& other) {
|
ComPrivateDataEntry& ComPrivateDataEntry::operator = (ComPrivateDataEntry&& other) {
|
||||||
this->destroy();
|
this->destroy();
|
||||||
this->m_guid = other.m_guid;
|
this->m_guid = other.m_guid;
|
||||||
|
this->m_type = other.m_type;
|
||||||
this->m_size = other.m_size;
|
this->m_size = other.m_size;
|
||||||
this->m_data = other.m_data;
|
this->m_data = other.m_data;
|
||||||
this->m_iface = other.m_iface;
|
this->m_iface = other.m_iface;
|
||||||
|
|
||||||
other.m_guid = __uuidof(IUnknown);
|
other.m_guid = __uuidof(IUnknown);
|
||||||
|
other.m_type = ComPrivateDataType::None;
|
||||||
other.m_size = 0;
|
other.m_size = 0;
|
||||||
other.m_data = nullptr;
|
other.m_data = nullptr;
|
||||||
other.m_iface = nullptr;
|
other.m_iface = nullptr;
|
||||||
@ -61,22 +67,24 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
HRESULT ComPrivateDataEntry::get(UINT& size, void* data) const {
|
HRESULT ComPrivateDataEntry::get(UINT& size, void* data) const {
|
||||||
const UINT minSize = m_iface != nullptr
|
UINT minSize = 0;
|
||||||
? sizeof(IUnknown*)
|
|
||||||
: m_size;
|
if (m_type == ComPrivateDataType::Iface) minSize = sizeof(IUnknown*);
|
||||||
|
if (m_type == ComPrivateDataType::Data) minSize = m_size;
|
||||||
|
|
||||||
if (data == nullptr) {
|
if (!data) {
|
||||||
size = minSize;
|
size = minSize;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HRESULT result = size < minSize
|
HRESULT result = size < minSize
|
||||||
? DXGI_ERROR_MORE_DATA
|
? DXGI_ERROR_MORE_DATA
|
||||||
: S_OK;
|
: S_OK;
|
||||||
|
|
||||||
if (size >= minSize) {
|
if (size >= minSize) {
|
||||||
if (m_iface != nullptr) {
|
if (m_type == ComPrivateDataType::Iface) {
|
||||||
m_iface->AddRef();
|
if (m_iface)
|
||||||
|
m_iface->AddRef();
|
||||||
std::memcpy(data, &m_iface, minSize);
|
std::memcpy(data, &m_iface, minSize);
|
||||||
} else {
|
} else {
|
||||||
std::memcpy(data, m_data, minSize);
|
std::memcpy(data, m_data, minSize);
|
||||||
@ -89,9 +97,9 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void ComPrivateDataEntry::destroy() {
|
void ComPrivateDataEntry::destroy() {
|
||||||
if (m_data != nullptr)
|
if (m_data)
|
||||||
std::free(m_data);
|
std::free(m_data);
|
||||||
if (m_iface != nullptr)
|
if (m_iface)
|
||||||
m_iface->Release();
|
m_iface->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +108,7 @@ namespace dxvk {
|
|||||||
REFGUID guid,
|
REFGUID guid,
|
||||||
UINT size,
|
UINT size,
|
||||||
const void* data) {
|
const void* data) {
|
||||||
if (data == nullptr) {
|
if (!data) {
|
||||||
for (auto it = m_entries.begin(); it != m_entries.end(); ++it) {
|
for (auto it = m_entries.begin(); it != m_entries.end(); ++it) {
|
||||||
if (it->hasGuid(guid)) {
|
if (it->hasGuid(guid)) {
|
||||||
m_entries.erase(it);
|
m_entries.erase(it);
|
||||||
@ -126,12 +134,12 @@ namespace dxvk {
|
|||||||
REFGUID guid,
|
REFGUID guid,
|
||||||
UINT* size,
|
UINT* size,
|
||||||
void* data) {
|
void* data) {
|
||||||
if (size == nullptr)
|
if (!size)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
auto entry = this->findEntry(guid);
|
auto entry = this->findEntry(guid);
|
||||||
|
|
||||||
if (entry == nullptr) {
|
if (!entry) {
|
||||||
*size = 0;
|
*size = 0;
|
||||||
return DXGI_ERROR_NOT_FOUND;
|
return DXGI_ERROR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
@ -154,7 +162,7 @@ namespace dxvk {
|
|||||||
ComPrivateDataEntry srcEntry = std::move(entry);
|
ComPrivateDataEntry srcEntry = std::move(entry);
|
||||||
ComPrivateDataEntry* dstEntry = this->findEntry(srcEntry.guid());
|
ComPrivateDataEntry* dstEntry = this->findEntry(srcEntry.guid());
|
||||||
|
|
||||||
if (dstEntry != nullptr)
|
if (dstEntry)
|
||||||
*dstEntry = std::move(srcEntry);
|
*dstEntry = std::move(srcEntry);
|
||||||
else
|
else
|
||||||
m_entries.push_back(std::move(srcEntry));
|
m_entries.push_back(std::move(srcEntry));
|
||||||
|
@ -6,6 +6,15 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief COM private data entry type
|
||||||
|
*/
|
||||||
|
enum ComPrivateDataType {
|
||||||
|
None,
|
||||||
|
Data,
|
||||||
|
Iface,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Data entry for private storage
|
* \brief Data entry for private storage
|
||||||
* Stores a single private storage item.
|
* Stores a single private storage item.
|
||||||
@ -58,10 +67,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
GUID m_guid = __uuidof(IUnknown);
|
GUID m_guid = __uuidof(IUnknown);
|
||||||
UINT m_size = 0;
|
ComPrivateDataType m_type = ComPrivateDataType::None;
|
||||||
void* m_data = nullptr;
|
UINT m_size = 0;
|
||||||
IUnknown* m_iface = nullptr;
|
void* m_data = nullptr;
|
||||||
|
IUnknown* m_iface = nullptr;
|
||||||
|
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user