[v2 PATCH 1/5] mfplat: Implement DXGI device manager handle management.

Nikolay Sivov nsivov at codeweavers.com
Fri Oct 23 06:59:38 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mfplat/main.c         | 248 +++++++++++++++++++++++++++++++++----
 dlls/mfplat/tests/mfplat.c | 156 ++++++++++++++++++++++-
 include/mfapi.h            |   4 +
 3 files changed, 380 insertions(+), 28 deletions(-)

diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 452426d055f..68aa2cdaa2d 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -8556,12 +8556,29 @@ HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
     return S_OK;
 }
 
+enum dxgi_device_handle_flags
+{
+    DXGI_DEVICE_HANDLE_FLAG_OPEN = 0x1,
+    DXGI_DEVICE_HANDLE_FLAG_INVALID = 0x2,
+    DXGI_DEVICE_HANDLE_FLAG_LOCKED = 0x4,
+};
+
 struct dxgi_device_manager
 {
     IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
     LONG refcount;
     UINT token;
     IDXGIDevice *device;
+
+    unsigned int *handles;
+    size_t count;
+    size_t capacity;
+
+    unsigned int locks;
+    unsigned int locking_tid;
+
+    CRITICAL_SECTION cs;
+    CONDITION_VARIABLE lock;
 };
 
 static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
@@ -8569,6 +8586,14 @@ static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceM
     return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
 }
 
+static HRESULT dxgi_device_manager_get_handle_index(struct dxgi_device_manager *manager, HANDLE hdevice, size_t *idx)
+{
+    if (!hdevice || hdevice > ULongToHandle(manager->count))
+        return E_HANDLE;
+    *idx = (ULONG_PTR)hdevice - 1;
+    return S_OK;
+}
+
 static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
 {
     TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), obj);
@@ -8607,17 +8632,61 @@ static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
     {
         if (manager->device)
             IDXGIDevice_Release(manager->device);
+        DeleteCriticalSection(&manager->cs);
+        heap_free(manager->handles);
         heap_free(manager);
     }
 
     return refcount;
 }
 
-static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE device)
+static void dxgi_device_manager_lock_handle(struct dxgi_device_manager *manager, size_t idx)
 {
-    FIXME("(%p, %p): stub.\n", iface, device);
+    if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED)
+        return;
 
-    return E_NOTIMPL;
+    manager->handles[idx] |= DXGI_DEVICE_HANDLE_FLAG_LOCKED;
+    manager->locks++;
+}
+
+static void dxgi_device_manager_unlock_handle(struct dxgi_device_manager *manager, size_t idx)
+{
+    if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED))
+        return;
+
+    manager->handles[idx] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
+    if (!--manager->locks)
+        manager->locking_tid = 0;
+}
+
+static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE hdevice)
+{
+    struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+    HRESULT hr;
+    size_t idx;
+
+    TRACE("%p, %p.\n", iface, hdevice);
+
+    EnterCriticalSection(&manager->cs);
+
+    if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
+    {
+        if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN)
+        {
+            dxgi_device_manager_unlock_handle(manager, idx);
+            manager->handles[idx] = 0;
+            if (idx == manager->count - 1)
+                manager->count--;
+        }
+        else
+            hr = E_HANDLE;
+    }
+
+    LeaveCriticalSection(&manager->cs);
+
+    WakeAllConditionVariable(&manager->lock);
+
+    return hr;
 }
 
 static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE device,
@@ -8628,57 +8697,180 @@ static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE device,
-                                                     REFIID riid, void **ppv, BOOL block)
+static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
+        REFIID riid, void **obj, BOOL block)
 {
-    FIXME("(%p, %p, %s, %p, %d): stub.\n", iface, device, wine_dbgstr_guid(riid), ppv, block);
+    struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+    HRESULT hr;
+    size_t idx;
 
-    return E_NOTIMPL;
+    TRACE("%p, %p, %s, %p, %d.\n", iface, hdevice, wine_dbgstr_guid(riid), obj, block);
+
+    EnterCriticalSection(&manager->cs);
+
+    if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
+    {
+        if (!manager->device)
+        {
+            hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
+        }
+        else if (manager->locking_tid == GetCurrentThreadId())
+        {
+            if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
+                dxgi_device_manager_lock_handle(manager, idx);
+        }
+        else if (manager->locking_tid && !block)
+        {
+            hr = MF_E_DXGI_VIDEO_DEVICE_LOCKED;
+        }
+        else
+        {
+            while (manager->locking_tid)
+            {
+                SleepConditionVariableCS(&manager->lock, &manager->cs, INFINITE);
+            }
+
+            if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
+            {
+                if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
+                    hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
+                else if (SUCCEEDED(hr = IDXGIDevice_QueryInterface(manager->device, riid, obj)))
+                {
+                    manager->locking_tid = GetCurrentThreadId();
+                    dxgi_device_manager_lock_handle(manager, idx);
+                }
+            }
+        }
+    }
+
+    LeaveCriticalSection(&manager->cs);
+
+    return hr;
 }
 
-static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *device)
+static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *hdevice)
 {
-    FIXME("(%p, %p): stub.\n", iface, device);
+    struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+    HRESULT hr = S_OK;
+    size_t i;
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, hdevice);
+
+    *hdevice = NULL;
+
+    EnterCriticalSection(&manager->cs);
+
+    if (!manager->device)
+        hr = MF_E_DXGI_DEVICE_NOT_INITIALIZED;
+    else
+    {
+        for (i = 0; i < manager->count; ++i)
+        {
+            if (!(manager->handles[i] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
+            {
+                manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_OPEN;
+                *hdevice = ULongToHandle(i + 1);
+                break;
+            }
+        }
+
+        if (mf_array_reserve((void **)&manager->handles, &manager->capacity, manager->count + 1,
+                sizeof(*manager->handles)))
+        {
+            *hdevice = ULongToHandle(manager->count + 1);
+            manager->handles[manager->count++] = DXGI_DEVICE_HANDLE_FLAG_OPEN;
+        }
+        else
+            hr = E_OUTOFMEMORY;
+    }
+
+    LeaveCriticalSection(&manager->cs);
+
+    return hr;
 }
 
 static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
 {
     struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
     IDXGIDevice *dxgi_device;
-    HRESULT hr;
+    size_t i;
 
-    TRACE("(%p, %p, %u).\n", iface, device, token);
+    TRACE("%p, %p, %u.\n", iface, device, token);
 
     if (!device || token != manager->token)
         return E_INVALIDARG;
 
-    hr = IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
-    if (SUCCEEDED(hr))
+    if (FAILED(IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device)))
+        return E_INVALIDARG;
+
+    EnterCriticalSection(&manager->cs);
+
+    if (manager->device)
     {
-        if (manager->device)
-            IDXGIDevice_Release(manager->device);
-        manager->device = dxgi_device;
+        for (i = 0; i < manager->count; ++i)
+        {
+            manager->handles[i] |= DXGI_DEVICE_HANDLE_FLAG_INVALID;
+            manager->handles[i] &= ~DXGI_DEVICE_HANDLE_FLAG_LOCKED;
+        }
+        manager->locking_tid = 0;
+        manager->locks = 0;
+        IDXGIDevice_Release(manager->device);
     }
-    else
-        hr = E_INVALIDARG;
+    manager->device = dxgi_device;
 
-    return hr;
+    LeaveCriticalSection(&manager->cs);
+
+    WakeAllConditionVariable(&manager->lock);
+
+    return S_OK;
 }
 
-static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE device)
+static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice)
 {
-    FIXME("(%p, %p): stub.\n", iface, device);
+    struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+    HRESULT hr;
+    size_t idx;
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, hdevice);
+
+    EnterCriticalSection(&manager->cs);
+
+    if (SUCCEEDED(hr = dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
+    {
+        if (manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_INVALID)
+            hr = MF_E_DXGI_NEW_VIDEO_DEVICE;
+        else if (!(manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_OPEN))
+            hr = E_HANDLE;
+    }
+
+    LeaveCriticalSection(&manager->cs);
+
+    return hr;
 }
 
-static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE device, BOOL state)
+static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE hdevice,
+         BOOL savestate)
 {
-    FIXME("(%p, %p, %d): stub.\n", iface, device, state);
+    struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+    HRESULT hr = E_FAIL;
+    size_t idx;
 
-    return E_NOTIMPL;
+    TRACE("%p, %p, %d.\n", iface, hdevice, savestate);
+
+    EnterCriticalSection(&manager->cs);
+
+    if (SUCCEEDED(dxgi_device_manager_get_handle_index(manager, hdevice, &idx)))
+    {
+        hr = manager->handles[idx] & DXGI_DEVICE_HANDLE_FLAG_LOCKED ? S_OK : E_INVALIDARG;
+        if (SUCCEEDED(hr))
+            dxgi_device_manager_unlock_handle(manager, idx);
+    }
+
+    LeaveCriticalSection(&manager->cs);
+
+    WakeAllConditionVariable(&manager->lock);
+
+    return hr;
 }
 
 static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
@@ -8699,7 +8891,7 @@ HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **man
 {
     struct dxgi_device_manager *object;
 
-    TRACE("(%p, %p).\n", token, manager);
+    TRACE("%p, %p.\n", token, manager);
 
     if (!token || !manager)
         return E_POINTER;
@@ -8712,6 +8904,8 @@ HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **man
     object->refcount = 1;
     object->token = GetTickCount();
     object->device = NULL;
+    InitializeCriticalSection(&object->cs);
+    InitializeConditionVariable(&object->lock);
 
     TRACE("Created device manager: %p, token: %u.\n", object, object->token);
 
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index a5388840bc5..17371a0e1c0 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -4497,10 +4497,38 @@ if (0)
     ok(!refcount, "Unexpected refcount %u.\n", refcount);
 }
 
+struct test_thread_param
+{
+    IMFDXGIDeviceManager *manager;
+    HANDLE handle;
+    BOOL lock;
+};
+
+static DWORD WINAPI test_device_manager_thread(void *arg)
+{
+    struct test_thread_param *param = arg;
+    ID3D11Device *device;
+    HRESULT hr;
+
+    if (param->lock)
+    {
+        hr = IMFDXGIDeviceManager_LockDevice(param->manager, param->handle, &IID_ID3D11Device,
+                (void **)&device, FALSE);
+        if (SUCCEEDED(hr))
+            ID3D11Device_Release(device);
+    }
+    else
+        hr = IMFDXGIDeviceManager_UnlockDevice(param->manager, param->handle, FALSE);
+
+    return hr;
+}
+
 static void test_dxgi_device_manager(void)
 {
     IMFDXGIDeviceManager *manager, *manager2;
-    ID3D11Device *d3d11_dev, *d3d11_dev2;
+    ID3D11Device *device, *d3d11_dev, *d3d11_dev2;
+    struct test_thread_param param;
+    HANDLE handle1, handle, thread;
     UINT token, token2;
     HRESULT hr;
 
@@ -4532,6 +4560,12 @@ static void test_dxgi_device_manager(void)
     ok(manager != manager2, "got wrong pointer: %p.\n", manager2);
     EXPECT_REF(manager, 1);
 
+    hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle);
+    ok(hr == MF_E_DXGI_DEVICE_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, 0);
+    ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr);
+
     hr = pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
                            NULL, 0, D3D11_SDK_VERSION, &d3d11_dev, NULL, NULL);
     ok(hr == S_OK, "D3D11CreateDevice failed: %#x.\n", hr);
@@ -4569,6 +4603,126 @@ static void test_dxgi_device_manager(void)
     EXPECT_REF(d3d11_dev2, 2);
     EXPECT_REF(d3d11_dev, 1);
 
+    handle = NULL;
+    hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(!!handle, "Unexpected handle value %p.\n", handle);
+
+    handle1 = NULL;
+    hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle1);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(handle != handle1, "Unexpected handle.\n");
+
+    hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    /* Already closed. */
+    hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle);
+    ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr);
+
+    handle = NULL;
+    hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle1);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_TestDevice(manager, handle1);
+    ok(hr == E_HANDLE, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_LockDevice(manager, handle, &IID_ID3D11Device, (void **)&device, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(device == d3d11_dev2, "Unexpected device pointer.\n");
+    ID3D11Device_Release(device);
+
+    hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle, FALSE);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_UnlockDevice(manager, UlongToHandle(100), FALSE);
+    ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
+
+    /* Locked with one handle, unlock with another. */
+    hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle1);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_LockDevice(manager, handle, &IID_ID3D11Device, (void **)&device, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle1, FALSE);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    ID3D11Device_Release(device);
+
+    /* Closing unlocks the device. */
+    hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_LockDevice(manager, handle1, &IID_ID3D11Device, (void **)&device, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ID3D11Device_Release(device);
+
+    hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle1);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    /* Open two handles. */
+    hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_OpenDeviceHandle(manager, &handle1);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_LockDevice(manager, handle, &IID_ID3D11Device, (void **)&device, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ID3D11Device_Release(device);
+
+    hr = IMFDXGIDeviceManager_LockDevice(manager, handle1, &IID_ID3D11Device, (void **)&device, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ID3D11Device_Release(device);
+
+    hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle, FALSE);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    param.manager = manager;
+    param.handle = handle;
+    param.lock = TRUE;
+    thread = CreateThread(NULL, 0, test_device_manager_thread, &param, 0, NULL);
+    ok(!WaitForSingleObject(thread, 1000), "Wait for a test thread failed.\n");
+    GetExitCodeThread(thread, (DWORD *)&hr);
+    ok(hr == MF_E_DXGI_VIDEO_DEVICE_LOCKED, "Unexpected hr %#x.\n", hr);
+    CloseHandle(thread);
+
+    hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle1, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_UnlockDevice(manager, handle1, FALSE);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    /* Lock on main thread, unlock on another. */
+    hr = IMFDXGIDeviceManager_LockDevice(manager, handle, &IID_ID3D11Device, (void **)&device, FALSE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ID3D11Device_Release(device);
+
+    param.manager = manager;
+    param.handle = handle;
+    param.lock = FALSE;
+    thread = CreateThread(NULL, 0, test_device_manager_thread, &param, 0, NULL);
+    ok(!WaitForSingleObject(thread, 1000), "Wait for a test thread failed.\n");
+    GetExitCodeThread(thread, (DWORD *)&hr);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    CloseHandle(thread);
+
+    hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle1);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFDXGIDeviceManager_CloseDeviceHandle(manager, handle);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
     IMFDXGIDeviceManager_Release(manager);
     EXPECT_REF(d3d11_dev2, 1);
     ID3D11Device_Release(d3d11_dev);
diff --git a/include/mfapi.h b/include/mfapi.h
index 499c77ab337..25fced1c7d6 100644
--- a/include/mfapi.h
+++ b/include/mfapi.h
@@ -482,6 +482,10 @@ typedef enum
 #define MFSESSIONCAP_RATE_REVERSE          0x00000020
 #define MFSESSIONCAP_DOES_NOT_USE_NETWORK  0x00000040
 
+#define MF_E_DXGI_DEVICE_NOT_INITIALIZED   ((HRESULT)0x80041000)
+#define MF_E_DXGI_NEW_VIDEO_DEVICE         ((HRESULT)0x80041001)
+#define MF_E_DXGI_VIDEO_DEVICE_LOCKED      ((HRESULT)0x80041002)
+
 HRESULT WINAPI MFAddPeriodicCallback(MFPERIODICCALLBACK callback, IUnknown *context, DWORD *key);
 HRESULT WINAPI MFAllocateSerialWorkQueue(DWORD target_queue, DWORD *queue);
 HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue);
-- 
2.28.0




More information about the wine-devel mailing list