[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