[RFC PATCH 3/4] winevulkan: Add support for named video resources.

Derek Lesho dlesho at codeweavers.com
Mon May 3 11:46:56 CDT 2021


Beyond whether this approach is acceptable, one thing I'd appreciate feedback
on is a better name for the wine driver.  winevideo.sys seems too generic
and winevideoresource.sys seems too verbose.
---
 configure.ac                          |   1 +
 dlls/ntoskrnl.exe/ntoskrnl.c          |  57 +++++-
 dlls/ntoskrnl.exe/ntoskrnl.exe.spec   |   2 +
 dlls/vulkan-1/tests/vulkan.c          |   9 +-
 dlls/winevideo.sys/Makefile.in        |   6 +
 dlls/winevideo.sys/winevideo.c        | 284 ++++++++++++++++++++++++++
 dlls/winevideo.sys/winevideo.sys.spec |   1 +
 dlls/winevulkan/vulkan.c              |  82 +++++++-
 include/ddk/wdm.h                     |   1 +
 loader/wine.inf.in                    |  13 ++
 10 files changed, 443 insertions(+), 13 deletions(-)
 create mode 100644 dlls/winevideo.sys/Makefile.in
 create mode 100644 dlls/winevideo.sys/winevideo.c
 create mode 100644 dlls/winevideo.sys/winevideo.sys.spec

diff --git a/configure.ac b/configure.ac
index 46bbb8a70f8..0071eeb0dd3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3823,6 +3823,7 @@ WINE_CONFIG_MAKEFILE(dlls/wineps16.drv16,enable_win16)
 WINE_CONFIG_MAKEFILE(dlls/winepulse.drv)
 WINE_CONFIG_MAKEFILE(dlls/wineqtdecoder)
 WINE_CONFIG_MAKEFILE(dlls/wineusb.sys)
+WINE_CONFIG_MAKEFILE(dlls/winevideo.sys)
 WINE_CONFIG_MAKEFILE(dlls/winevulkan)
 WINE_CONFIG_MAKEFILE(dlls/winex11.drv)
 WINE_CONFIG_MAKEFILE(dlls/wing.dll16,enable_win16)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 5b84c626547..5156f3d3ab1 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -138,6 +138,10 @@ static HANDLE get_device_manager(void)
 struct object_header
 {
     LONG ref;
+    /* only blocks object from being freed, not released */
+    LONG weak_ref;
+    /* an additional ref used to indicate whether server is done w/ obj */
+    BOOL in_server;
     POBJECT_TYPE type;
 };
 
@@ -166,6 +170,7 @@ void *alloc_kernel_object( POBJECT_TYPE type, HANDLE handle, SIZE_T size, LONG r
         }
         SERVER_END_REQ;
         if (status) FIXME( "set_object_reference failed: %#x\n", status );
+        else header->in_server = TRUE;
     }
 
     header->ref = ref;
@@ -197,7 +202,8 @@ void WINAPI ObDereferenceObject( void *obj )
     {
         if (header->type->release)
         {
-            header->type->release( obj );
+            if (!header->weak_ref)
+                header->type->release( obj );
         }
         else
         {
@@ -227,6 +233,13 @@ void ObReferenceObject( void *obj )
 
     EnterCriticalSection( &obref_cs );
 
+    if (header->ref == 0 && !header->in_server)
+    {
+        ERR("Weak references may not be turned into strong references\n");
+        LeaveCriticalSection( &obref_cs );
+        return;
+    }
+
     ref = ++header->ref;
     TRACE( "(%p) ref=%u\n", obj, ref );
     if (ref == 1)
@@ -246,7 +259,37 @@ void ObReferenceObject( void *obj )
 ULONG WINAPI ObGetObjectPointerCount( void *object )
 {
     struct object_header *header = (struct object_header *)object - 1;
-    return header->ref;
+    return header->ref + header->in_server;
+}
+
+void CDECL wine_ob_weak_ref( void *object )
+{
+    struct object_header *header = (struct object_header *) object - 1;
+
+    EnterCriticalSection( &obref_cs );
+
+    header->weak_ref++;
+
+    LeaveCriticalSection( &obref_cs );
+}
+
+void CDECL wine_ob_weak_deref( void *object )
+{
+    struct object_header *header = (struct object_header *) object - 1;
+
+    EnterCriticalSection( &obref_cs );
+
+    header->weak_ref--;
+
+    if (!header->weak_ref && !header->ref && !header->in_server)
+    {
+        if (header->type->release)
+            header->type->release(object);
+        else
+            free_kernel_object(object);
+    }
+
+    LeaveCriticalSection( &obref_cs );
 }
 
 /***********************************************************************
@@ -814,8 +857,16 @@ static NTSTATUS dispatch_volume( struct dispatch_context *context )
 static NTSTATUS dispatch_free( struct dispatch_context *context )
 {
     void *obj = wine_server_get_ptr( context->params.free.obj );
+    struct object_header *header = (struct object_header *)obj - 1;
+
     TRACE( "freeing %p object\n", obj );
-    free_kernel_object( obj );
+
+    EnterCriticalSection(&obref_cs);
+    header->in_server = FALSE;
+    if (!header->weak_ref)
+        free_kernel_object( obj );
+    LeaveCriticalSection(&obref_cs);
+
     return STATUS_SUCCESS;
 }
 
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 6426bc3968a..318344fe90f 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1688,3 +1688,5 @@
 
 @ cdecl wine_ntoskrnl_main_loop(long)
 @ cdecl wine_enumerate_root_devices(wstr)
+@ cdecl wine_ob_weak_ref(ptr)
+@ cdecl wine_ob_weak_deref(ptr)
diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c
index c1350da70ee..53df0e9a8d6 100644
--- a/dlls/vulkan-1/tests/vulkan.c
+++ b/dlls/vulkan-1/tests/vulkan.c
@@ -579,13 +579,10 @@ static void test_external_memory(VkInstance vk_instance, VkPhysicalDevice vk_phy
         import_handle_info.name = L"wine_test_buffer_export_name";
 
         vr = vkAllocateMemory(vk_device, &alloc_info, NULL, &vk_memory_import);
-    todo_wine
         ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult %d.\n", vr);
-        if (vr == VK_SUCCESS)
-        {
-            ok(vk_memory_import != vk_memory, "Expected new memory object.\n");
-            vkFreeMemory(vk_device, vk_memory_import, NULL);
-        }
+        ok(vk_memory_import != vk_memory, "Expected new memory object.\n");
+
+        vkFreeMemory(vk_device, vk_memory_import, NULL);
         vkFreeMemory(vk_device, vk_memory, NULL);
         CloseHandle(nt_handle);
     }
diff --git a/dlls/winevideo.sys/Makefile.in b/dlls/winevideo.sys/Makefile.in
new file mode 100644
index 00000000000..ed185b9f071
--- /dev/null
+++ b/dlls/winevideo.sys/Makefile.in
@@ -0,0 +1,6 @@
+MODULE    = winevideo.sys
+IMPORTS   = ntoskrnl
+EXTRADLLFLAGS = -Wl,--subsystem,native -mno-cygwin
+
+C_SRCS = \
+	winevideo.c
diff --git a/dlls/winevideo.sys/winevideo.c b/dlls/winevideo.sys/winevideo.c
new file mode 100644
index 00000000000..04e171bea3f
--- /dev/null
+++ b/dlls/winevideo.sys/winevideo.c
@@ -0,0 +1,284 @@
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winternl.h"
+#include "winioctl.h"
+
+#include "ddk/wdm.h"
+
+#include "wine/debug.h"
+#include "wine/server.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winevideo);
+
+#define IOCTL_VIDEO_RESOURCE_CREATE           CTL_CODE(FILE_DEVICE_VIDEO, 0, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define IOCTL_VIDEO_RESOURCE_FIND_BY_NAME     CTL_CODE(FILE_DEVICE_VIDEO, 1, METHOD_BUFFERED, FILE_READ_ACCESS)
+
+struct video_resource
+{
+    void *object;
+    LPWSTR name;
+};
+
+static struct video_resource *video_resources;
+static unsigned int video_resources_size;
+
+extern void CDECL wine_ob_weak_ref( void *object );
+extern void CDECL wine_ob_weak_deref( void *object );
+
+/* TODO: If/when ntoskrnl gets support for referencing user handles directly, remove this function */
+static void *reference_client_handle(obj_handle_t handle)
+{
+    HANDLE client_process, kernel_handle;
+    OBJECT_ATTRIBUTES attr;
+    void *object = NULL;
+    CLIENT_ID cid;
+
+    attr.Length = sizeof(OBJECT_ATTRIBUTES);
+    attr.RootDirectory = 0;
+    attr.Attributes = OBJ_KERNEL_HANDLE;
+    attr.ObjectName = NULL;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    cid.UniqueProcess = PsGetCurrentProcessId();
+    cid.UniqueThread = 0;
+
+    if (NtOpenProcess(&client_process, PROCESS_ALL_ACCESS, &attr, &cid) != STATUS_SUCCESS)
+        return NULL;
+
+    if (NtDuplicateObject(client_process, wine_server_ptr_handle(handle), NtCurrentProcess(), &kernel_handle,
+                               0, OBJ_KERNEL_HANDLE, DUPLICATE_SAME_ACCESS) != STATUS_SUCCESS)
+    {
+        NtClose(client_process);
+        return NULL;
+    }
+
+    ObReferenceObjectByHandle(kernel_handle, 0, NULL, KernelMode, &object, NULL);
+
+    NtClose(client_process);
+    NtClose(kernel_handle);
+
+    return object;
+}
+
+struct resource_create_in
+{
+    obj_handle_t handle;
+    WCHAR name[1];
+};
+
+static NTSTATUS resource_create(void *buff, SIZE_T insize, SIZE_T outsize, IO_STATUS_BLOCK *iosb)
+{
+    struct resource_create_in *input = buff;
+    struct video_resource *resource = NULL;
+    int free_entry = -1;
+    unsigned int i;
+    void *object;
+    LPWSTR name;
+
+    if (insize < offsetof(struct resource_create_in, name))
+        return STATUS_INFO_LENGTH_MISMATCH;
+
+    if (insize < sizeof(*input))
+        name = NULL;
+    else if (input->name[ ((insize - offsetof(struct resource_create_in, name)) / sizeof(WCHAR)) - 1 ])
+        return STATUS_INVALID_PARAMETER;
+    else
+        name = &input->name[0];
+
+    if (!(object = reference_client_handle(input->handle)))
+        return STATUS_INVALID_HANDLE;
+
+    /* Find lowest free slot while checking for duplicate names */
+    for (i = video_resources_size - 1; i < video_resources_size; i--)
+    {
+        resource = &video_resources[i];
+        if (resource->object)
+        {
+            if (!ObGetObjectPointerCount(resource->object))
+            {
+                wine_ob_weak_deref(resource->object);
+                if (resource->name)
+                {
+                    ExFreePoolWithTag(resource->name, 0);
+                    resource->name = NULL;
+                }
+
+                free_entry = i;
+            }
+            else if (resource->object == object)
+            {
+                ObDereferenceObject(object);
+                return STATUS_INVALID_PARAMETER;
+            }
+            else if (resource->name && name && !wcscmp(name, resource->name))
+            {
+                ObDereferenceObject(object);
+                return STATUS_OBJECT_NAME_COLLISION;
+            }
+        }
+        else
+            free_entry = i;
+    }
+
+    if (free_entry == -1)
+    {
+        struct video_resource *new_resources =
+            ExAllocatePoolWithTag(NonPagedPool, sizeof(struct video_resource) * (video_resources_size + 1024), 0);
+
+        if (video_resources)
+        {
+            memcpy(new_resources, video_resources, video_resources_size * sizeof(struct video_resource));
+            ExFreePoolWithTag(video_resources, 0);
+        }
+
+        memset(&new_resources[video_resources_size], 0, 1024 * sizeof (struct video_resource));
+
+        video_resources = new_resources;
+        free_entry = video_resources_size;
+        video_resources_size += 1024;
+    }
+
+    resource = &video_resources[free_entry];
+
+    resource->object = object;
+    if (name)
+    {
+        resource->name = ExAllocatePoolWithTag(NonPagedPool, (wcslen(name) + 1) * sizeof(WCHAR), 0);
+        wcscpy(resource->name, name);
+    }
+
+    wine_ob_weak_ref(object);
+    ObDereferenceObject(object);
+
+    iosb->Information = 0;
+    return STATUS_SUCCESS;
+}
+
+/* TODO: If/when ntoskrnl gets support for opening user handles directly, remove this function */
+static obj_handle_t open_client_handle(void *object)
+{
+    HANDLE client_process, kernel_handle, handle = NULL;
+    OBJECT_ATTRIBUTES attr;
+    CLIENT_ID cid;
+
+    attr.Length = sizeof(OBJECT_ATTRIBUTES);
+    attr.RootDirectory = 0;
+    attr.Attributes = OBJ_KERNEL_HANDLE;
+    attr.ObjectName = NULL;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    cid.UniqueProcess = PsGetCurrentProcessId();
+    cid.UniqueThread = 0;
+
+    if (NtOpenProcess(&client_process, PROCESS_ALL_ACCESS, &attr, &cid) != STATUS_SUCCESS)
+        return 0;
+
+    if (ObOpenObjectByPointer(object, 0, NULL, GENERIC_ALL, NULL, KernelMode, &kernel_handle) != STATUS_SUCCESS)
+    {
+        NtClose(client_process);
+        return 0;
+    }
+
+    NtDuplicateObject(NtCurrentProcess(), kernel_handle, client_process, &handle,
+                        0, 0, DUPLICATE_SAME_ACCESS);
+
+    NtClose(client_process);
+    NtClose(kernel_handle);
+
+    return wine_server_obj_handle(handle);
+}
+
+static NTSTATUS find_resource_by_name(void *buff, SIZE_T insize, SIZE_T outsize, IO_STATUS_BLOCK *iosb)
+{
+    LPCWSTR name = buff;
+    obj_handle_t ret;
+    unsigned int i;
+
+    if (insize < sizeof(WCHAR))
+        return STATUS_INVALID_PARAMETER;
+    if (name[(insize / sizeof(WCHAR)) - 1])
+        return STATUS_INVALID_PARAMETER;
+
+    for (i = 0; i < video_resources_size; i++)
+    {
+        if (video_resources[i].name && !wcscmp(name, video_resources[i].name))
+        {
+            if (!ObGetObjectPointerCount(video_resources[i].object))
+                break;
+
+            if (!(ret = open_client_handle(video_resources[i].object)))
+                return STATUS_INTERNAL_ERROR;
+
+            if (outsize < sizeof(obj_handle_t))
+                return STATUS_INFO_LENGTH_MISMATCH;
+
+            iosb->Information = sizeof(obj_handle_t);
+            *(obj_handle_t *)buff = ret;
+
+            return STATUS_SUCCESS;
+        }
+    }
+
+    return STATUS_OBJECT_NAME_NOT_FOUND;
+}
+
+static NTSTATUS WINAPI winevideo_ioctl(DEVICE_OBJECT *device, IRP *irp)
+{
+    IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
+    NTSTATUS status;
+
+    TRACE( "ioctl %x insize %u outsize %u\n",
+           irpsp->Parameters.DeviceIoControl.IoControlCode,
+           irpsp->Parameters.DeviceIoControl.InputBufferLength,
+           irpsp->Parameters.DeviceIoControl.OutputBufferLength );
+
+    switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
+    {
+        case IOCTL_VIDEO_RESOURCE_CREATE:
+            status = resource_create( irp->AssociatedIrp.SystemBuffer,
+                                      irpsp->Parameters.DeviceIoControl.InputBufferLength,
+                                      irpsp->Parameters.DeviceIoControl.OutputBufferLength,
+                                      &irp->IoStatus );
+            break;
+        case IOCTL_VIDEO_RESOURCE_FIND_BY_NAME:
+            status = find_resource_by_name( irp->AssociatedIrp.SystemBuffer,
+                                            irpsp->Parameters.DeviceIoControl.InputBufferLength,
+                                            irpsp->Parameters.DeviceIoControl.OutputBufferLength,
+                                            &irp->IoStatus );
+            break;
+    default:
+        FIXME( "ioctl %x not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode );
+        status = STATUS_NOT_SUPPORTED;
+        break;
+    }
+
+    irp->IoStatus.u.Status = status;
+    IoCompleteRequest( irp, IO_NO_INCREMENT );
+    return status;
+}
+
+NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
+{
+    static const WCHAR device_nameW[] = L"\\Device\\WineVideoResourceManager";
+    static const WCHAR link_nameW[] = L"\\??\\WineVideoResourceManager";
+    UNICODE_STRING device_name, link_name;
+    DEVICE_OBJECT *device;
+    NTSTATUS status;
+
+    driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = winevideo_ioctl;
+
+    RtlInitUnicodeString(&device_name, device_nameW);
+    RtlInitUnicodeString(&link_name, link_nameW);
+
+    if ((status = IoCreateDevice(driver, 0, &device_name, 0, 0, FALSE, &device)))
+        return status;
+
+    return IoCreateSymbolicLink(&link_name, &device_name);
+}
diff --git a/dlls/winevideo.sys/winevideo.sys.spec b/dlls/winevideo.sys/winevideo.sys.spec
new file mode 100644
index 00000000000..76421d7e35b
--- /dev/null
+++ b/dlls/winevideo.sys/winevideo.sys.spec
@@ -0,0 +1 @@
+# nothing to export
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index e95860cb3fa..65f53aa679e 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -31,6 +31,7 @@
 #define WIN32_NO_STATUS
 #include "windef.h"
 #include "winbase.h"
+#include "winioctl.h"
 #include "winreg.h"
 #include "winuser.h"
 #include "winternl.h"
@@ -502,10 +503,33 @@ static void wine_vk_device_free(struct VkDevice_T *device)
     free(device);
 }
 
+static HANDLE winevideo_device;
+
 NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *driver, void *ptr_out)
 {
+    static const WCHAR manager_nameW[] = {'\\','?','?','\\','W','i','n','e','V','i','d','e','o','R','e','s','o','u','r','c','e','M','a','n','a','g','e','r',0};
+    UNICODE_STRING manager_name;
+    OBJECT_ATTRIBUTES attr;
+    IO_STATUS_BLOCK io;
+    NTSTATUS status;
+
     if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
 
+    RtlInitUnicodeString(&manager_name, manager_nameW);
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.Attributes = 0;
+    attr.ObjectName = &manager_name;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+
+    if ((status = NtCreateFile(&winevideo_device, GENERIC_READ | GENERIC_WRITE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0)))
+    {
+        ERR("Failed to load the wine video-resource manager, status %#x.\n", status);
+        winevideo_device = NULL;
+    }
+
     vk_funcs = driver;
     p_vkEnumerateInstanceVersion = vk_funcs->p_vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion");
     *(const struct unix_funcs **)ptr_out = &loader_funcs;
@@ -1958,18 +1982,68 @@ VkResult WINAPI wine_vkDebugMarkerSetObjectNameEXT(VkDevice device, const VkDebu
     return thunk_vkDebugMarkerSetObjectNameEXT(device, &wine_name_info);
 }
 
+#define IOCTL_VIDEO_RESOURCE_CREATE CTL_CODE(FILE_DEVICE_VIDEO, 0, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+
+struct resource_create_in
+{
+    obj_handle_t handle;
+    WCHAR name[1];
+};
+
 static HANDLE create_video_resource(int fd, LPCWSTR name)
 {
     HANDLE ret = INVALID_HANDLE_VALUE;
-
-    if (name)
-        FIXME("Naming video resources not supported.\n");
+    struct resource_create_in *inbuff;
+    IO_STATUS_BLOCK iosb;
+    NTSTATUS status;
+    DWORD in_size;
 
     wine_server_fd_to_handle(fd, GENERIC_ALL, 0, &ret);
 
+    if (ret != INVALID_HANDLE_VALUE && winevideo_device)
+    {
+        in_size = offsetof(struct resource_create_in, name) + (name ? (lstrlenW(name) + 1) * sizeof(WCHAR) : 0);
+        inbuff = malloc(in_size);
+        inbuff->handle = wine_server_obj_handle(ret);
+        if (name)
+            lstrcpyW(&inbuff->name[0], name);
+
+        if ((status = NtDeviceIoControlFile(winevideo_device, NULL, NULL, NULL, &iosb, IOCTL_VIDEO_RESOURCE_CREATE,
+                inbuff, in_size, NULL, 0)))
+            ERR("Failed to create video resource, status %#x.\n", status);
+
+        free(inbuff);
+    }
     return ret;
 }
 
+#define IOCTL_VIDEO_RESOURCE_FIND_BY_NAME CTL_CODE(FILE_DEVICE_VIDEO, 1, METHOD_BUFFERED, FILE_READ_ACCESS)
+
+static HANDLE open_video_resource_by_name(LPCWSTR name)
+{
+    obj_handle_t handle_out;
+    IO_STATUS_BLOCK iosb;
+    NTSTATUS status;
+
+    if (!winevideo_device)
+        return INVALID_HANDLE_VALUE;
+
+    if ((status = NtDeviceIoControlFile(winevideo_device, NULL, NULL, NULL, &iosb, IOCTL_VIDEO_RESOURCE_FIND_BY_NAME,
+            (PVOID) name, (lstrlenW(name) + 1) * sizeof(WCHAR), &handle_out, sizeof(handle_out))))
+    {
+        ERR("Failed to open video resource by name, status %#x.\n", status);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    if (iosb.Information < sizeof(handle_out))
+    {
+        ERR("Unexpected out size.\n");
+        return INVALID_HANDLE_VALUE;
+    }
+
+    return wine_server_ptr_handle(handle_out);
+}
+
 VkResult WINAPI wine_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *allocate_info,
     const VkAllocationCallbacks *allocator, VkDeviceMemory *memory_out)
 {
@@ -2061,7 +2135,7 @@ VkResult WINAPI wine_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInf
                 if (handle_import_info->handle)
                     NtDuplicateObject( NtCurrentProcess(), handle_import_info->handle, NtCurrentProcess(), &object->handle, 0, 0, DUPLICATE_SAME_ACCESS );
                 else if (handle_import_info->name)
-                    FIXME("Importing device memory by resource name not supported.\n");
+                    object->handle = open_video_resource_by_name( handle_import_info->name );
                 break;
             default:
                 WARN("Invalid handle type %08x passed in.\n", handle_import_info->handleType);
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index 1e7ce63f776..906f70b72e9 100644
--- a/include/ddk/wdm.h
+++ b/include/ddk/wdm.h
@@ -1803,6 +1803,7 @@ void    FASTCALL ObfReferenceObject(void*);
 void      WINAPI ObDereferenceObject(void*);
 USHORT    WINAPI ObGetFilterVersion(void);
 ULONG     WINAPI ObGetObjectPointerCount(void*);
+NTSTATUS  WINAPI ObOpenObjectByPointer(void*,ULONG,ACCESS_STATE*,ACCESS_MASK,POBJECT_TYPE,KPROCESSOR_MODE,HANDLE*);
 NTSTATUS  WINAPI ObRegisterCallbacks(POB_CALLBACK_REGISTRATION, void**);
 NTSTATUS  WINAPI ObReferenceObjectByHandle(HANDLE,ACCESS_MASK,POBJECT_TYPE,KPROCESSOR_MODE,PVOID*,POBJECT_HANDLE_INFORMATION);
 NTSTATUS  WINAPI ObReferenceObjectByName(UNICODE_STRING*,ULONG,ACCESS_STATE*,ACCESS_MASK,POBJECT_TYPE,KPROCESSOR_MODE,void*,void**);
diff --git a/loader/wine.inf.in b/loader/wine.inf.in
index 6ae4e96e37f..17b5db66f0d 100644
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -165,6 +165,7 @@ AddService=Schedule,0,TaskSchedulerService
 AddService=Winmgmt,0,WinmgmtService
 AddService=wuauserv,0,wuauService
 AddService=NDIS,0x800,NDISService
+AddService=WineVideoResources,0x800,WineVideoResourcesService
 
 [DefaultInstall.NT.Services]
 AddService=BITS,0,BITSService
@@ -184,6 +185,7 @@ AddService=Schedule,0,TaskSchedulerService
 AddService=Winmgmt,0,WinmgmtService
 AddService=wuauserv,0,wuauService
 AddService=NDIS,0x800,NDISService
+AddService=WineVideoResources,0x800,WineVideoResourcesService
 
 [DefaultInstall.ntamd64.Services]
 AddService=BITS,0,BITSService
@@ -203,6 +205,7 @@ AddService=Schedule,0,TaskSchedulerService
 AddService=Winmgmt,0,WinmgmtService
 AddService=wuauserv,0,wuauService
 AddService=NDIS,0x800,NDISService
+AddService=WineVideoResources,0x800,WineVideoResourcesService
 
 [DefaultInstall.ntarm64.Services]
 AddService=BITS,0,BITSService
@@ -222,6 +225,7 @@ AddService=Schedule,0,TaskSchedulerService
 AddService=Winmgmt,0,WinmgmtService
 AddService=wuauserv,0,wuauService
 AddService=NDIS,0x800,NDISService
+AddService=WineVideoResources,0x800,WineVideoResourcesService
 
 [Strings]
 MciExtStr="Software\Microsoft\Windows NT\CurrentVersion\MCI Extensions"
@@ -3799,6 +3803,15 @@ StartType=2
 ErrorControl=1
 LoadOrderGroup="System Bus Extender"
 
+[WineVideoResourcesService]
+Description="Video resource helper service"
+DisplayName="Wine Video Resources"
+ServiceBinary="%12%\winevideo.sys"
+ServiceType=1
+StartType=2
+ErrorControl=1
+LoadOrderGroup="System Bus Extender"
+
 [RpcSsService]
 Description="RPC service"
 DisplayName="Remote Procedure Call (RPC)"
-- 
2.31.1




More information about the wine-devel mailing list