-- v2: win32u: Implement NtGdiDdDDIQueryResourceInfo. win32u: Pass D3DKMT object runtime data to wineserver. win32u: Implement creation of D3DKMT resource objects. win32u: Implement creation of D3DKMT sync objects. server: Allocate global D3DKMT handles for objects. server: Create server-side global D3DKMT objects.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 78 ++++++++++++++++++++++----- dlls/win32u/tests/d3dkmt.c | 63 ++++++++++++---------- dlls/wow64win/gdi.c | 3 ++ server/Makefile.in | 1 + server/d3dkmt.c | 105 +++++++++++++++++++++++++++++++++++++ server/protocol.def | 17 ++++++ 6 files changed, 224 insertions(+), 43 deletions(-) create mode 100644 server/d3dkmt.c
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 13f05f2d069..3c905b5cb20 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -31,19 +31,13 @@ #include "win32u_private.h" #include "ntuser_private.h"
-WINE_DEFAULT_DEBUG_CHANNEL(vulkan); - -enum d3dkmt_type -{ - D3DKMT_ADAPTER = 1, - D3DKMT_DEVICE = 2, - D3DKMT_SOURCE = 3, -}; +WINE_DEFAULT_DEBUG_CHANNEL(d3dkmt);
struct d3dkmt_object { enum d3dkmt_type type; /* object type */ D3DKMT_HANDLE local; /* object local handle */ + HANDLE handle; /* process-private handle of server object */ };
struct d3dkmt_adapter @@ -161,9 +155,33 @@ static NTSTATUS d3dkmt_object_alloc( UINT size, enum d3dkmt_type type, void **ob return STATUS_SUCCESS; }
+/* create a global D3DKMT object, either with a global handle or later shareable */ +static NTSTATUS d3dkmt_object_create( struct d3dkmt_object *obj, BOOL shared ) +{ + NTSTATUS status; + + SERVER_START_REQ( d3dkmt_object_create ) + { + req->type = obj->type; + if (!(status = wine_server_call( req ))) + { + obj->handle = wine_server_ptr_handle( reply->handle ); + } + } + SERVER_END_REQ; + + if (!status) status = alloc_object_handle( obj ); + + if (status) WARN( "Failed to create global resource for %p, status %#x\n", obj, status ); + else TRACE( "Created global resource for %p/%#x\n", obj, obj->local ); + return status; +} + static void d3dkmt_object_free( struct d3dkmt_object *object ) { + TRACE( "object %p/%#x\n", object, object->local ); if (object->local) free_object_handle( object ); + if (object->handle) NtClose( object->handle ); free( object ); }
@@ -830,8 +848,23 @@ NTSTATUS WINAPI NtGdiDdDDIQueryResourceInfoFromNtHandle( D3DKMT_QUERYRESOURCEINF */ NTSTATUS WINAPI NtGdiDdDDICreateKeyedMutex2( D3DKMT_CREATEKEYEDMUTEX2 *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *mutex; + NTSTATUS status; + + FIXME( "params %p semi-stub!\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + + if ((status = d3dkmt_object_alloc( sizeof(*mutex), D3DKMT_MUTEX, (void **)&mutex ))) return status; + if ((status = d3dkmt_object_create( mutex, params->Flags.NtSecuritySharing ))) goto failed; + + params->hSharedHandle = 0; + params->hKeyedMutex = mutex->local; + return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( mutex ); + return status; }
/****************************************************************************** @@ -839,8 +872,18 @@ NTSTATUS WINAPI NtGdiDdDDICreateKeyedMutex2( D3DKMT_CREATEKEYEDMUTEX2 *params ) */ NTSTATUS WINAPI NtGdiDdDDICreateKeyedMutex( D3DKMT_CREATEKEYEDMUTEX *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + D3DKMT_CREATEKEYEDMUTEX2 params2 = {0}; + NTSTATUS status; + + TRACE( "params %p\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + + params2.InitialValue = params->InitialValue; + status = NtGdiDdDDICreateKeyedMutex2( ¶ms2 ); + params->hSharedHandle = params2.hSharedHandle; + params->hKeyedMutex = params2.hKeyedMutex; + return status; }
/****************************************************************************** @@ -848,8 +891,15 @@ NTSTATUS WINAPI NtGdiDdDDICreateKeyedMutex( D3DKMT_CREATEKEYEDMUTEX *params ) */ NTSTATUS WINAPI NtGdiDdDDIDestroyKeyedMutex( const D3DKMT_DESTROYKEYEDMUTEX *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *mutex; + + TRACE( "params %p\n", params ); + + if (!(mutex = get_d3dkmt_object( params->hKeyedMutex, D3DKMT_MUTEX ))) + return STATUS_INVALID_PARAMETER; + d3dkmt_object_free( mutex ); + + return STATUS_SUCCESS; }
/****************************************************************************** diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 167071f5b0c..bdf39a1d83a 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -1446,11 +1446,11 @@ static void test_D3DKMTCreateKeyedMutex( void ) NTSTATUS status;
status = D3DKMTCreateKeyedMutex( NULL ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.hKeyedMutex = create.hSharedHandle = 0x1eadbeed; status = D3DKMTCreateKeyedMutex( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create.hKeyedMutex, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create.hKeyedMutex, &next_local ); todo_wine check_d3dkmt_global( create.hSharedHandle );
status = D3DKMTOpenKeyedMutex( &open ); @@ -1463,9 +1463,10 @@ static void test_D3DKMTCreateKeyedMutex( void ) status = D3DKMTOpenKeyedMutex( &open ); todo_wine ok_nt( STATUS_SUCCESS, status ); todo_wine check_d3dkmt_local( open.hKeyedMutex, &next_local ); + next_local = 0;
status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
if (0) { @@ -1480,11 +1481,11 @@ static void test_D3DKMTCreateKeyedMutex( void ) todo_wine ok_nt( STATUS_SUCCESS, status ); /* destroying multiple times fails */ status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
destroy.hKeyedMutex = create.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* the global D3DKMT_HANDLE is destroyed with last reference */ status = D3DKMTOpenKeyedMutex( &open ); @@ -1492,18 +1493,18 @@ static void test_D3DKMTCreateKeyedMutex( void )
status = D3DKMTCreateKeyedMutex2( NULL ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create2.hKeyedMutex = create2.hSharedHandle = 0x1eadbeed; status = D3DKMTCreateKeyedMutex2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hKeyedMutex, &next_local ); todo_wine check_d3dkmt_global( create2.hSharedHandle ); destroy.hKeyedMutex = create2.hKeyedMutex;
create2.hKeyedMutex = create2.hSharedHandle = 0x1eadbeed; status = D3DKMTCreateKeyedMutex2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hKeyedMutex, &next_local ); todo_wine check_d3dkmt_global( create2.hSharedHandle );
status = D3DKMTOpenKeyedMutex2( &open2 ); @@ -1516,12 +1517,13 @@ static void test_D3DKMTCreateKeyedMutex( void ) status = D3DKMTOpenKeyedMutex2( &open2 ); todo_wine ok_nt( STATUS_SUCCESS, status ); todo_wine check_d3dkmt_local( open2.hKeyedMutex, &next_local ); + next_local = 0;
status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); destroy.hKeyedMutex = create2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); destroy.hKeyedMutex = open2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); todo_wine ok_nt( STATUS_SUCCESS, status ); @@ -1530,8 +1532,8 @@ static void test_D3DKMTCreateKeyedMutex( void ) /* PrivateRuntimeDataSize must be 0 if no buffer is provided */
status = D3DKMTCreateKeyedMutex2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hKeyedMutex, &next_local ); todo_wine check_d3dkmt_global( create2.hSharedHandle );
open2.hKeyedMutex = 0x1eadbeed; @@ -1543,6 +1545,7 @@ static void test_D3DKMTCreateKeyedMutex( void ) status = D3DKMTOpenKeyedMutex2( &open2 ); todo_wine ok_nt( STATUS_SUCCESS, status ); todo_wine check_d3dkmt_local( open2.hKeyedMutex, &next_local ); + next_local = 0; ok_x4( open2.PrivateRuntimeDataSize, ==, sizeof(buffer) );
destroy.hKeyedMutex = open2.hKeyedMutex; @@ -1550,14 +1553,14 @@ static void test_D3DKMTCreateKeyedMutex( void ) todo_wine ok_nt( STATUS_SUCCESS, status ); destroy.hKeyedMutex = create2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
create2.PrivateRuntimeDataSize = sizeof(runtime_data); create2.pPrivateRuntimeData = runtime_data; status = D3DKMTCreateKeyedMutex2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hKeyedMutex, &next_local ); todo_wine check_d3dkmt_global( create2.hSharedHandle );
open2.hKeyedMutex = 0x1eadbeed; @@ -1567,6 +1570,7 @@ static void test_D3DKMTCreateKeyedMutex( void ) status = D3DKMTOpenKeyedMutex2( &open2 ); todo_wine ok_nt( STATUS_SUCCESS, status ); todo_wine check_d3dkmt_local( open2.hKeyedMutex, &next_local ); + next_local = 0; ok_x4( open2.PrivateRuntimeDataSize, ==, 0 );
open2.PrivateRuntimeDataSize = sizeof(buffer); @@ -1581,6 +1585,7 @@ static void test_D3DKMTCreateKeyedMutex( void ) status = D3DKMTOpenKeyedMutex2( &open2 ); todo_wine ok_nt( STATUS_SUCCESS, status ); todo_wine check_d3dkmt_local( open2.hKeyedMutex, &next_local ); + next_local = 0; ok_x4( open2.PrivateRuntimeDataSize, ==, sizeof(runtime_data) ); ok_u1( buffer[0], ==, 0xcd );
@@ -1589,20 +1594,20 @@ static void test_D3DKMTCreateKeyedMutex( void ) todo_wine ok_nt( STATUS_SUCCESS, status ); destroy.hKeyedMutex = create2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* doesn't return a global D3DKMT_HANDLE with NtSecuritySharing = 1 */ create2.Flags.NtSecuritySharing = 1; create2.hKeyedMutex = create2.hSharedHandle = 0x1eadbeed; status = D3DKMTCreateKeyedMutex2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); - todo_wine ok_x4( create2.hSharedHandle, ==, 0 ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + ok_x4( create2.hSharedHandle, ==, 0 );
destroy.hKeyedMutex = create2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); }
static void test_D3DKMTCreateAllocation( void ) @@ -2251,23 +2256,23 @@ static void test_D3DKMTShareObjects( void )
/* D3DKMTShareObjects doesn't work with keyed mutex objects alone */ status = D3DKMTCreateKeyedMutex( &create_mutex ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); status = D3DKMTShareObjects( 1, &create_mutex.hKeyedMutex, &attr, STANDARD_RIGHTS_WRITE, &handle ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); status = D3DKMTShareObjects( 1, &create_mutex.hSharedHandle, &attr, STANDARD_RIGHTS_WRITE, &handle ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); destroy_mutex.hKeyedMutex = create_mutex.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
create_mutex2.Flags.NtSecuritySharing = 1; status = D3DKMTCreateKeyedMutex2( &create_mutex2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); status = D3DKMTShareObjects( 1, &create_mutex2.hKeyedMutex, &attr, STANDARD_RIGHTS_WRITE, &handle ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); destroy_mutex.hKeyedMutex = create_mutex2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* NtSecuritySharing = 1 is required for D3DKMTShareObjects */ @@ -2462,7 +2467,7 @@ static void test_D3DKMTShareObjects( void ) create_mutex2.PrivateRuntimeDataSize = sizeof(expect_mutex_data); create_mutex2.pPrivateRuntimeData = expect_mutex_data; status = D3DKMTCreateKeyedMutex2( &create_mutex2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
objects[0] = create_alloc.hResource; objects[1] = create_alloc.hResource; @@ -2510,7 +2515,7 @@ static void test_D3DKMTShareObjects( void )
destroy_mutex.hKeyedMutex = create_mutex2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); create_mutex2.hKeyedMutex = 0;
destroy_sync.hSyncObject = create_sync2.hSyncObject; diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c index 30c4a5b6d62..f8e3056c932 100644 --- a/dlls/wow64win/gdi.c +++ b/dlls/wow64win/gdi.c @@ -726,6 +726,8 @@ NTSTATUS WINAPI wow64_NtGdiDdDDICreateKeyedMutex2( UINT *args ) D3DKMT_CREATEKEYEDMUTEX2 desc; NTSTATUS status;
+ if (!desc32) return STATUS_INVALID_PARAMETER; + desc.InitialValue = desc32->InitialValue; desc.hSharedHandle = desc32->hSharedHandle; desc.hKeyedMutex = desc32->hKeyedMutex; @@ -734,6 +736,7 @@ NTSTATUS WINAPI wow64_NtGdiDdDDICreateKeyedMutex2( UINT *args ) desc.Flags = desc32->Flags; status = NtGdiDdDDICreateKeyedMutex2( &desc ); desc32->hKeyedMutex = desc.hKeyedMutex; + desc32->hSharedHandle = desc.hSharedHandle; return status; }
diff --git a/server/Makefile.in b/server/Makefile.in index 57250fd0332..d3d50b9aa5a 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -8,6 +8,7 @@ SOURCES = \ clipboard.c \ completion.c \ console.c \ + d3dkmt.c \ debugger.c \ device.c \ directory.c \ diff --git a/server/d3dkmt.c b/server/d3dkmt.c new file mode 100644 index 00000000000..64301548784 --- /dev/null +++ b/server/d3dkmt.c @@ -0,0 +1,105 @@ +/* + * Server-side D3DKMT resource management + * + * Copyright 2025 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include <assert.h> +#include <stdarg.h> +#include <stdio.h> + +#include <unistd.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" +#include "ddk/wdm.h" + +#include "file.h" +#include "handle.h" +#include "request.h" +#include "security.h" + +struct d3dkmt_object +{ + struct object obj; /* object header */ + enum d3dkmt_type type; /* object type */ +}; + +static void d3dkmt_object_dump( struct object *obj, int verbose ); +static void d3dkmt_object_destroy( struct object *obj ); + +static const struct object_ops d3dkmt_object_ops = +{ + sizeof(struct d3dkmt_object), /* size */ + &no_type, /* type */ + d3dkmt_object_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ + default_map_access, /* map_access */ + default_get_sd, /* get_sd */ + default_set_sd, /* set_sd */ + no_get_full_name, /* get_full_name */ + no_lookup_name, /* lookup_name */ + no_link_name, /* link_name */ + NULL, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ + no_close_handle, /* close_handle */ + d3dkmt_object_destroy, /* destroy */ +}; + +static void d3dkmt_object_dump( struct object *obj, int verbose ) +{ + struct d3dkmt_object *object = (struct d3dkmt_object *)obj; + assert( obj->ops == &d3dkmt_object_ops ); + + fprintf( stderr, "type=%#x\n", object->type ); +} + +static void d3dkmt_object_destroy( struct object *obj ) +{ + assert( obj->ops == &d3dkmt_object_ops ); +} + +static struct d3dkmt_object *d3dkmt_object_create( enum d3dkmt_type type ) +{ + struct d3dkmt_object *object; + + if (!(object = alloc_object( &d3dkmt_object_ops ))) return NULL; + object->type = type; + + return object; +} + +/* create a global d3dkmt object */ +DECL_HANDLER(d3dkmt_object_create) +{ + struct d3dkmt_object *object; + + if (!(object = d3dkmt_object_create( req->type ))) return; + reply->handle = alloc_handle( current->process, object, STANDARD_RIGHTS_ALL, OBJ_INHERIT ); + release_object( object ); +} diff --git a/server/protocol.def b/server/protocol.def index 59c6436fa88..6ab783a7c5d 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -968,6 +968,14 @@ union udp_endpoint } ipv6; };
+enum d3dkmt_type +{ + D3DKMT_ADAPTER = 1, + D3DKMT_DEVICE = 2, + D3DKMT_SOURCE = 3, + D3DKMT_MUTEX = 4, +}; + /****************************************************************/ /* shared session mapping structures */
@@ -4137,3 +4145,12 @@ enum inproc_sync_type int type; /* inproc sync type */ unsigned int access; /* handle access rights */ @END + + +/* Create a global d3dkmt object */ +@REQ(d3dkmt_object_create) + unsigned int type; /* d3dkmt object type */ +@REPLY + obj_handle_t handle; /* process-private handle */ +@END +
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 10 +++-- dlls/win32u/tests/d3dkmt.c | 10 ++--- server/d3dkmt.c | 75 +++++++++++++++++++++++++++++++++++++- server/protocol.def | 2 + tools/make_requests | 1 + 5 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 3c905b5cb20..720bd5716fc 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -37,6 +37,8 @@ struct d3dkmt_object { enum d3dkmt_type type; /* object type */ D3DKMT_HANDLE local; /* object local handle */ + D3DKMT_HANDLE global; /* object global handle if any */ + BOOL shared; /* object is shared using nt handles */ HANDLE handle; /* process-private handle of server object */ };
@@ -166,6 +168,8 @@ static NTSTATUS d3dkmt_object_create( struct d3dkmt_object *obj, BOOL shared ) if (!(status = wine_server_call( req ))) { obj->handle = wine_server_ptr_handle( reply->handle ); + obj->global = reply->global; + obj->shared = shared; } } SERVER_END_REQ; @@ -173,13 +177,13 @@ static NTSTATUS d3dkmt_object_create( struct d3dkmt_object *obj, BOOL shared ) if (!status) status = alloc_object_handle( obj );
if (status) WARN( "Failed to create global resource for %p, status %#x\n", obj, status ); - else TRACE( "Created global resource for %p/%#x\n", obj, obj->local ); + else TRACE( "Created global resource %#x for %p/%#x\n", obj->global, obj, obj->local ); return status; }
static void d3dkmt_object_free( struct d3dkmt_object *object ) { - TRACE( "object %p/%#x\n", object, object->local ); + TRACE( "object %p/%#x, global %#x\n", object, object->local, object->global ); if (object->local) free_object_handle( object ); if (object->handle) NtClose( object->handle ); free( object ); @@ -858,7 +862,7 @@ NTSTATUS WINAPI NtGdiDdDDICreateKeyedMutex2( D3DKMT_CREATEKEYEDMUTEX2 *params ) if ((status = d3dkmt_object_alloc( sizeof(*mutex), D3DKMT_MUTEX, (void **)&mutex ))) return status; if ((status = d3dkmt_object_create( mutex, params->Flags.NtSecuritySharing ))) goto failed;
- params->hSharedHandle = 0; + params->hSharedHandle = mutex->shared ? 0 : mutex->global; params->hKeyedMutex = mutex->local; return STATUS_SUCCESS;
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index bdf39a1d83a..143faa6b41a 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -1451,7 +1451,7 @@ static void test_D3DKMTCreateKeyedMutex( void ) status = D3DKMTCreateKeyedMutex( &create ); ok_nt( STATUS_SUCCESS, status ); check_d3dkmt_local( create.hKeyedMutex, &next_local ); - todo_wine check_d3dkmt_global( create.hSharedHandle ); + check_d3dkmt_global( create.hSharedHandle );
status = D3DKMTOpenKeyedMutex( &open ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); @@ -1498,14 +1498,14 @@ static void test_D3DKMTCreateKeyedMutex( void ) status = D3DKMTCreateKeyedMutex2( &create2 ); ok_nt( STATUS_SUCCESS, status ); check_d3dkmt_local( create2.hKeyedMutex, &next_local ); - todo_wine check_d3dkmt_global( create2.hSharedHandle ); + check_d3dkmt_global( create2.hSharedHandle ); destroy.hKeyedMutex = create2.hKeyedMutex;
create2.hKeyedMutex = create2.hSharedHandle = 0x1eadbeed; status = D3DKMTCreateKeyedMutex2( &create2 ); ok_nt( STATUS_SUCCESS, status ); check_d3dkmt_local( create2.hKeyedMutex, &next_local ); - todo_wine check_d3dkmt_global( create2.hSharedHandle ); + check_d3dkmt_global( create2.hSharedHandle );
status = D3DKMTOpenKeyedMutex2( &open2 ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); @@ -1534,7 +1534,7 @@ static void test_D3DKMTCreateKeyedMutex( void ) status = D3DKMTCreateKeyedMutex2( &create2 ); ok_nt( STATUS_SUCCESS, status ); check_d3dkmt_local( create2.hKeyedMutex, &next_local ); - todo_wine check_d3dkmt_global( create2.hSharedHandle ); + check_d3dkmt_global( create2.hSharedHandle );
open2.hKeyedMutex = 0x1eadbeed; open2.hSharedHandle = create2.hSharedHandle; @@ -1561,7 +1561,7 @@ static void test_D3DKMTCreateKeyedMutex( void ) status = D3DKMTCreateKeyedMutex2( &create2 ); ok_nt( STATUS_SUCCESS, status ); check_d3dkmt_local( create2.hKeyedMutex, &next_local ); - todo_wine check_d3dkmt_global( create2.hSharedHandle ); + check_d3dkmt_global( create2.hSharedHandle );
open2.hKeyedMutex = 0x1eadbeed; open2.hSharedHandle = create2.hSharedHandle; diff --git a/server/d3dkmt.c b/server/d3dkmt.c index 64301548784..0249afca1a1 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -41,6 +41,7 @@ struct d3dkmt_object { struct object obj; /* object header */ enum d3dkmt_type type; /* object type */ + d3dkmt_handle_t global; /* object global handle */ };
static void d3dkmt_object_dump( struct object *obj, int verbose ); @@ -71,17 +72,78 @@ static const struct object_ops d3dkmt_object_ops = d3dkmt_object_destroy, /* destroy */ };
+static struct d3dkmt_object **objects; +static unsigned int object_count, object_capacity, next_index; + +/* return the position of the first object which handle is not less than + * the given global handle. */ +static unsigned int object_handle_lower_bound( d3dkmt_handle_t global ) +{ + unsigned int begin = 0, end = object_count, mid; + + while (begin < end) + { + mid = begin + (end - begin) / 2; + if (objects[mid]->global < global) begin = mid + 1; + else end = mid; + } + + return begin; +} + +/* allocate a d3dkmt object with a global handle */ +static d3dkmt_handle_t alloc_object_handle( struct d3dkmt_object *object ) +{ + d3dkmt_handle_t handle = 0; + unsigned int index; + + if (object_count >= object_capacity) + { + unsigned int capacity = max( 32, object_capacity * 3 / 2 ); + struct d3dkmt_object **tmp; + assert( capacity > object_capacity ); + + if (capacity >= 0xffff) goto done; + if (!(tmp = realloc( objects, capacity * sizeof(*objects) ))) goto done; + object_capacity = capacity; + objects = tmp; + } + + handle = object->global = ((next_index++ << 6) & ~0xc000003f) | 0x40000002; + index = object_handle_lower_bound( object->global ); + memmove( objects + index + 1, objects, (object_count - index) * sizeof(*objects) ); + objects[index] = object; + object_count++; + +done: + return handle; +} + +/* free a d3dkmt global object handle */ +static void free_object_handle( struct d3dkmt_object *object ) +{ + unsigned int index; + + index = object_handle_lower_bound( object->global ); + assert( index < object_count && objects[index] == object ); + object_count--; + memmove( objects + index, objects + index + 1, (object_count - index) * sizeof(*objects) ); +} + static void d3dkmt_object_dump( struct object *obj, int verbose ) { struct d3dkmt_object *object = (struct d3dkmt_object *)obj; assert( obj->ops == &d3dkmt_object_ops );
- fprintf( stderr, "type=%#x\n", object->type ); + fprintf( stderr, "type=%#x global=%#x\n", object->type, object->global ); }
static void d3dkmt_object_destroy( struct object *obj ) { + struct d3dkmt_object *object = (struct d3dkmt_object *)obj; assert( obj->ops == &d3dkmt_object_ops ); + + if (object->global) free_object_handle( object ); }
static struct d3dkmt_object *d3dkmt_object_create( enum d3dkmt_type type ) @@ -89,7 +151,15 @@ static struct d3dkmt_object *d3dkmt_object_create( enum d3dkmt_type type ) struct d3dkmt_object *object;
if (!(object = alloc_object( &d3dkmt_object_ops ))) return NULL; - object->type = type; + object->type = type; + object->global = 0; + + if (!alloc_object_handle( object )) + { + release_object( object ); + set_error( STATUS_NO_MEMORY ); + return NULL; + }
return object; } @@ -101,5 +171,6 @@ DECL_HANDLER(d3dkmt_object_create)
if (!(object = d3dkmt_object_create( req->type ))) return; reply->handle = alloc_handle( current->process, object, STANDARD_RIGHTS_ALL, OBJ_INHERIT ); + reply->global = object->global; release_object( object ); } diff --git a/server/protocol.def b/server/protocol.def index 6ab783a7c5d..9437caa53b5 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -34,6 +34,7 @@
typedef unsigned int obj_handle_t; typedef unsigned int user_handle_t; +typedef unsigned int d3dkmt_handle_t; typedef unsigned int atom_t; typedef unsigned int process_id_t; typedef unsigned int thread_id_t; @@ -4151,6 +4152,7 @@ enum inproc_sync_type @REQ(d3dkmt_object_create) unsigned int type; /* d3dkmt object type */ @REPLY + d3dkmt_handle_t global; /* global d3dkmt handle */ obj_handle_t handle; /* process-private handle */ @END
diff --git a/tools/make_requests b/tools/make_requests index f87664c9690..17e425537b5 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -34,6 +34,7 @@ my %formats = "atom_t" => [ 4, 4, "%04x" ], "process_id_t" => [ 4, 4, "%04x" ], "thread_id_t" => [ 4, 4, "%04x" ], + "d3dkmt_handle_t"=>[ 4, 4, "%08x" ], "unsigned __int64" => [ 8, 8, "&uint64" ], "timeout_t" => [ 8, 8 ], "abstime_t" => [ 8, 8 ],
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 58 +++++++++++++++-- dlls/win32u/tests/d3dkmt.c | 128 ++++++++++++++++++------------------- dlls/wow64win/gdi.c | 1 + server/protocol.def | 1 + 4 files changed, 117 insertions(+), 71 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 720bd5716fc..495d42aa0b7 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -939,8 +939,32 @@ NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutexFromNtHandle( D3DKMT_OPENKEYEDMUTEXFROMN */ NTSTATUS WINAPI NtGdiDdDDICreateSynchronizationObject2( D3DKMT_CREATESYNCHRONIZATIONOBJECT2 *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *device, *sync; + NTSTATUS status; + + FIXME( "params %p semi-stub!\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + if (!(device = get_d3dkmt_object( params->hDevice, D3DKMT_DEVICE ))) return STATUS_INVALID_PARAMETER; + + if (params->Info.Type < D3DDDI_SYNCHRONIZATION_MUTEX || params->Info.Type > D3DDDI_MONITORED_FENCE) + return STATUS_INVALID_PARAMETER; + + if (params->Info.Type == D3DDDI_CPU_NOTIFICATION && !params->Info.CPUNotification.Event) return STATUS_INVALID_HANDLE; + if (params->Info.Flags.NtSecuritySharing && !params->Info.Flags.Shared) return STATUS_INVALID_PARAMETER; + + if ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) return status; + if (!params->Info.Flags.Shared) status = alloc_object_handle( sync ); + else status = d3dkmt_object_create( sync, params->Info.Flags.NtSecuritySharing ); + if (status) goto failed; + + if (params->Info.Flags.Shared) params->Info.SharedHandle = sync->shared ? 0 : sync->global; + params->hSyncObject = sync->local; + return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( sync ); + return status; }
/****************************************************************************** @@ -948,8 +972,23 @@ NTSTATUS WINAPI NtGdiDdDDICreateSynchronizationObject2( D3DKMT_CREATESYNCHRONIZA */ NTSTATUS WINAPI NtGdiDdDDICreateSynchronizationObject( D3DKMT_CREATESYNCHRONIZATIONOBJECT *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + D3DKMT_CREATESYNCHRONIZATIONOBJECT2 params2 = {0}; + NTSTATUS status; + + TRACE( "params %p\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + + if (params->Info.Type != D3DDDI_SYNCHRONIZATION_MUTEX && params->Info.Type != D3DDDI_SEMAPHORE) + return STATUS_INVALID_PARAMETER; + + params2.hDevice = params->hDevice; + params2.Info.Type = params->Info.Type; + params2.Info.Flags.Shared = 1; + memcpy( ¶ms2.Info.Reserved, ¶ms->Info.Reserved, sizeof(params->Info.Reserved) ); + status = NtGdiDdDDICreateSynchronizationObject2( ¶ms2 ); + params->hSyncObject = params2.hSyncObject; + return status; }
/****************************************************************************** @@ -993,6 +1032,13 @@ NTSTATUS WINAPI NtGdiDdDDIOpenSynchronizationObject( D3DKMT_OPENSYNCHRONIZATIONO */ NTSTATUS WINAPI NtGdiDdDDIDestroySynchronizationObject( const D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *sync; + + TRACE( "params %p\n", params ); + + if (!(sync = get_d3dkmt_object( params->hSyncObject, D3DKMT_SYNC ))) + return STATUS_INVALID_PARAMETER; + d3dkmt_object_free( sync ); + + return STATUS_SUCCESS; } diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 143faa6b41a..210df1571f2 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -1217,145 +1217,142 @@ static void test_D3DKMTCreateSynchronizationObject( void )
/* D3DKMTCreateSynchronizationObject creates a local D3DKMT_HANDLE */ status = D3DKMTCreateSynchronizationObject( NULL ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); status = D3DKMTCreateSynchronizationObject( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.hDevice = create_device.hDevice; status = D3DKMTCreateSynchronizationObject( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.hDevice = 0; create.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; status = D3DKMTCreateSynchronizationObject( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.hDevice = create_device.hDevice; create.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; create.hSyncObject = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create.hSyncObject, &next_local ); destroy.hSyncObject = create.hSyncObject;
/* local handles are monotonically increasing */ create.hSyncObject = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create.hSyncObject, &next_local );
status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); /* destroying multiple times fails */ status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
destroy.hSyncObject = create.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
create.Info.Type = D3DDDI_SEMAPHORE; create.hSyncObject = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create.hSyncObject, &next_local ); destroy.hSyncObject = create.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
create.Info.Type = D3DDDI_FENCE; status = D3DKMTCreateSynchronizationObject( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
/* D3DKMTCreateSynchronizationObject2 can create local D3DKMT_HANDLE */ status = D3DKMTCreateSynchronizationObject2( NULL ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create2.hDevice = create_device.hDevice; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create2.hDevice = 0; create2.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create2.hDevice = create_device.hDevice; create2.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; create2.hSyncObject = create2.Info.SharedHandle = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hSyncObject, &next_local );
destroy.hSyncObject = create2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
create2.Info.Type = D3DDDI_SEMAPHORE; create2.hSyncObject = create2.Info.SharedHandle = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hSyncObject, &next_local ); destroy.hSyncObject = create2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
create2.Info.Type = D3DDDI_FENCE; create2.hSyncObject = create2.Info.SharedHandle = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hSyncObject, &next_local ); destroy.hSyncObject = create2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
create2.Info.Type = D3DDDI_CPU_NOTIFICATION; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_INVALID_HANDLE, status ); + ok_nt( STATUS_INVALID_HANDLE, status ); create2.Info.CPUNotification.Event = CreateEventW( NULL, FALSE, FALSE, NULL ); create2.hSyncObject = create2.Info.SharedHandle = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hSyncObject, &next_local ); destroy.hSyncObject = create2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); CloseHandle( create2.Info.CPUNotification.Event ); create2.Info.CPUNotification.Event = NULL;
create2.Info.Type = D3DDDI_MONITORED_FENCE; create2.hSyncObject = create2.Info.SharedHandle = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - if (status == STATUS_SUCCESS) - { - todo_wine check_d3dkmt_local( create2.hSyncObject, &next_local ); - destroy.hSyncObject = create2.hSyncObject; - status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - } + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hSyncObject, &next_local ); + destroy.hSyncObject = create2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + ok_nt( STATUS_SUCCESS, status );
create2.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; create2.Info.Flags.Shared = 1; create2.hSyncObject = create2.Info.SharedHandle = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hSyncObject, &next_local ); - todo_wine check_d3dkmt_global( create2.Info.SharedHandle ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hSyncObject, &next_local ); + check_d3dkmt_global( create2.Info.SharedHandle ); destroy.hSyncObject = create2.hSyncObject;
create2.hSyncObject = create2.Info.SharedHandle = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hSyncObject, &next_local ); - todo_wine check_d3dkmt_global( create2.Info.SharedHandle ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hSyncObject, &next_local ); + check_d3dkmt_global( create2.Info.SharedHandle );
status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* cannot destroy the global D3DKMT_HANDLE */ destroy.hSyncObject = create2.Info.SharedHandle; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
/* D3DKMTOpenSynchronizationObject creates a new local D3DKMT_HANDLE */ @@ -1379,13 +1376,14 @@ static void test_D3DKMTCreateSynchronizationObject( void ) todo_wine ok_nt( STATUS_SUCCESS, status ); /* destroying multiple times fails */ status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
/* the D3DKMT object can still be opened */ open.hSyncObject = 0x1eadbeed; status = D3DKMTOpenSynchronizationObject( &open ); todo_wine ok_nt( STATUS_SUCCESS, status ); todo_wine check_d3dkmt_local( open.hSyncObject, &next_local ); + next_local = 0;
destroy.hSyncObject = open.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); @@ -1393,7 +1391,7 @@ static void test_D3DKMTCreateSynchronizationObject( void )
destroy.hSyncObject = create2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); /* the global D3DKMT_HANDLE is destroyed with last reference */ status = D3DKMTOpenSynchronizationObject( &open ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); @@ -1403,7 +1401,7 @@ static void test_D3DKMTCreateSynchronizationObject( void ) create2.Info.Flags.Shared = 0; create2.Info.Flags.NtSecuritySharing = 1; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); if (broken( !status )) { check_d3dkmt_local( create2.hSyncObject, &next_local ); @@ -1416,14 +1414,14 @@ static void test_D3DKMTCreateSynchronizationObject( void ) create2.Info.Flags.NtSecuritySharing = 1; create2.hSyncObject = create2.Info.SharedHandle = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject2( &create2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( create2.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create2.hSyncObject, &next_local ); ok( create2.Info.SharedHandle == 0x1eadbeed || !create2.Info.SharedHandle, "got Info.SharedHandle %#x\n", create2.Info.SharedHandle );
destroy.hSyncObject = create2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
destroy_device.hDevice = create_device.hDevice; @@ -2098,43 +2096,43 @@ static void test_D3DKMTShareObjects( void ) create_sync.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; create_sync.hSyncObject = 0x1eadbeed; status = D3DKMTCreateSynchronizationObject( &create_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); handle = (HANDLE)0xdeadbeef; status = D3DKMTShareObjects( 1, &create_sync.hSyncObject, &attr, STANDARD_RIGHTS_WRITE, &handle ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); if (broken( !status )) CloseHandle( handle ); destroy_sync.hSyncObject = create_sync.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* D3DKMTShareObjects doesn't work with Shared = 1/0 alone */ create_sync2.hDevice = create_device.hDevice; create_sync2.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; status = D3DKMTCreateSynchronizationObject2( &create_sync2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); handle = (HANDLE)0xdeadbeef; status = D3DKMTShareObjects( 1, &create_sync2.hSyncObject, &attr, STANDARD_RIGHTS_WRITE, &handle ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); if (broken( !status )) CloseHandle( handle ); destroy_sync.hSyncObject = create_sync2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
create_sync2.Info.Flags.Shared = 1; status = D3DKMTCreateSynchronizationObject2( &create_sync2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); handle = (HANDLE)0xdeadbeef; status = D3DKMTShareObjects( 1, &create_sync2.hSyncObject, &attr, STANDARD_RIGHTS_WRITE, &handle ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); if (broken( !status )) CloseHandle( handle ); destroy_sync.hSyncObject = create_sync2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* D3DKMTShareObjects requires NtSecuritySharing (which requires Shared = 1) */ create_sync2.Info.Flags.NtSecuritySharing = 1; status = D3DKMTCreateSynchronizationObject2( &create_sync2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); InitializeObjectAttributes( &attr, &name, 0, 0, NULL ); handle = (HANDLE)0xdeadbeef; status = D3DKMTShareObjects( 1, &create_sync2.hSyncObject, &attr, STANDARD_RIGHTS_WRITE, &handle ); @@ -2148,11 +2146,11 @@ static void test_D3DKMTShareObjects( void ) /* cannot destroy the handle */ destroy_sync.hSyncObject = (UINT_PTR)handle; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
destroy_sync.hSyncObject = create_sync2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* the sync object can be opened from the NT handle */ @@ -2460,7 +2458,7 @@ static void test_D3DKMTShareObjects( void ) create_sync2.hDevice = create_device.hDevice; create_sync2.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; status = D3DKMTCreateSynchronizationObject2( &create_sync2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); handle = (HANDLE)0xdeadbeef;
create_mutex2.Flags.NtSecuritySharing = 1; @@ -2520,7 +2518,7 @@ static void test_D3DKMTShareObjects( void )
destroy_sync.hSyncObject = create_sync2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); create_sync2.hSyncObject = 0;
destroy_alloc.hResource = create_alloc.hResource; diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c index f8e3056c932..cfa67e82ebb 100644 --- a/dlls/wow64win/gdi.c +++ b/dlls/wow64win/gdi.c @@ -750,6 +750,7 @@ NTSTATUS WINAPI wow64_NtGdiDdDDICreateSynchronizationObject2( UINT *args ) { D3DKMT_CREATESYNCHRONIZATIONOBJECT2 *desc = get_ptr( &args );
+ if (!desc) return STATUS_INVALID_PARAMETER; if (desc->Info.Type == D3DDDI_CPU_NOTIFICATION) { ULONG event = HandleToUlong( desc->Info.CPUNotification.Event ); diff --git a/server/protocol.def b/server/protocol.def index 9437caa53b5..8605c940d6b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -975,6 +975,7 @@ enum d3dkmt_type D3DKMT_DEVICE = 2, D3DKMT_SOURCE = 3, D3DKMT_MUTEX = 4, + D3DKMT_SYNC = 5, };
/****************************************************************/
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 115 ++++++++++++++++++++++++-- dlls/win32u/tests/d3dkmt.c | 165 +++++++++++++++++++------------------ dlls/wow64win/gdi.c | 11 ++- server/protocol.def | 2 + 4 files changed, 200 insertions(+), 93 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 495d42aa0b7..64d71fc45a1 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -42,6 +42,12 @@ struct d3dkmt_object HANDLE handle; /* process-private handle of server object */ };
+struct d3dkmt_resource +{ + struct d3dkmt_object obj; + D3DKMT_HANDLE allocation; +}; + struct d3dkmt_adapter { struct d3dkmt_object obj; /* object header */ @@ -761,8 +767,64 @@ NTSTATUS WINAPI NtGdiDdDDIShareObjects( UINT count, const D3DKMT_HANDLE *handles */ NTSTATUS WINAPI NtGdiDdDDICreateAllocation2( D3DKMT_CREATEALLOCATION *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + D3DKMT_CREATESTANDARDALLOCATION *standard; + struct d3dkmt_resource *resource = NULL; + D3DDDI_ALLOCATIONINFO *alloc_info; + struct d3dkmt_object *allocation; + struct d3dkmt_device *device; + NTSTATUS status; + + FIXME( "params %p semi-stub!\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + if (!(device = get_d3dkmt_object( params->hDevice, D3DKMT_DEVICE ))) return STATUS_INVALID_PARAMETER; + + if (!params->Flags.StandardAllocation) return STATUS_INVALID_PARAMETER; + if (params->PrivateDriverDataSize) return STATUS_INVALID_PARAMETER; + + if (params->NumAllocations != 1) return STATUS_INVALID_PARAMETER; + if (!(alloc_info = params->pAllocationInfo)) return STATUS_INVALID_PARAMETER; + + if (!(standard = params->pStandardAllocation)) return STATUS_INVALID_PARAMETER; + if (standard->Type != D3DKMT_STANDARDALLOCATIONTYPE_EXISTINGHEAP) return STATUS_INVALID_PARAMETER; + if (standard->ExistingHeapData.Size & 0xfff) return STATUS_INVALID_PARAMETER; + if (!params->Flags.ExistingSysMem) return STATUS_INVALID_PARAMETER; + if (!alloc_info->pSystemMem) return STATUS_INVALID_PARAMETER; + + if (params->Flags.CreateResource) + { + if (params->hResource && !(resource = get_d3dkmt_object( params->hResource, D3DKMT_RESOURCE ))) + return STATUS_INVALID_HANDLE; + if ((status = d3dkmt_object_alloc( sizeof(*resource), D3DKMT_RESOURCE, (void **)&resource ))) return status; + if ((status = d3dkmt_object_alloc( sizeof(*allocation), D3DKMT_ALLOCATION, (void **)&allocation ))) goto failed; + + if (!params->Flags.CreateShared) status = alloc_object_handle( &resource->obj ); + else status = d3dkmt_object_create( &resource->obj, params->Flags.NtSecuritySharing ); + if (status) goto failed; + + params->hGlobalShare = resource->obj.shared ? 0 : resource->obj.global; + params->hResource = resource->obj.local; + } + else + { + if (params->Flags.CreateShared) return STATUS_INVALID_PARAMETER; + if (params->hResource) + { + resource = get_d3dkmt_object( params->hResource, D3DKMT_RESOURCE ); + return resource ? STATUS_INVALID_PARAMETER : STATUS_INVALID_HANDLE; + } + if ((status = d3dkmt_object_alloc( sizeof(*allocation), D3DKMT_ALLOCATION, (void **)&allocation ))) return status; + params->hGlobalShare = 0; + } + + if ((status = alloc_object_handle( allocation ))) goto failed; + if (resource) resource->allocation = allocation->local; + alloc_info->hAllocation = allocation->local; + return STATUS_SUCCESS; + +failed: + if (resource) d3dkmt_object_free( &resource->obj ); + return status; }
/****************************************************************************** @@ -770,8 +832,7 @@ NTSTATUS WINAPI NtGdiDdDDICreateAllocation2( D3DKMT_CREATEALLOCATION *params ) */ NTSTATUS WINAPI NtGdiDdDDICreateAllocation( D3DKMT_CREATEALLOCATION *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + return NtGdiDdDDICreateAllocation2( params ); }
/****************************************************************************** @@ -779,8 +840,37 @@ NTSTATUS WINAPI NtGdiDdDDICreateAllocation( D3DKMT_CREATEALLOCATION *params ) */ NTSTATUS WINAPI NtGdiDdDDIDestroyAllocation2( const D3DKMT_DESTROYALLOCATION2 *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *device, *allocation; + D3DKMT_HANDLE alloc_handle = 0; + UINT i; + + TRACE( "params %p\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + if (!(device = get_d3dkmt_object( params->hDevice, D3DKMT_DEVICE ))) return STATUS_INVALID_PARAMETER; + + if (params->AllocationCount && !params->phAllocationList) return STATUS_INVALID_PARAMETER; + + if (params->hResource) + { + struct d3dkmt_resource *resource; + if (!(resource = get_d3dkmt_object( params->hResource, D3DKMT_RESOURCE ))) + return STATUS_INVALID_PARAMETER; + alloc_handle = resource->allocation; + d3dkmt_object_free( &resource->obj ); + } + + for (i = 0; i < params->AllocationCount; i++) + { + if (!(allocation = get_d3dkmt_object( params->phAllocationList[i], D3DKMT_ALLOCATION ))) + return STATUS_INVALID_PARAMETER; + d3dkmt_object_free( allocation ); + } + + if (alloc_handle && (allocation = get_d3dkmt_object( alloc_handle, D3DKMT_ALLOCATION ))) + d3dkmt_object_free( allocation ); + + return STATUS_SUCCESS; }
/****************************************************************************** @@ -788,8 +878,17 @@ NTSTATUS WINAPI NtGdiDdDDIDestroyAllocation2( const D3DKMT_DESTROYALLOCATION2 *p */ NTSTATUS WINAPI NtGdiDdDDIDestroyAllocation( const D3DKMT_DESTROYALLOCATION *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + D3DKMT_DESTROYALLOCATION2 params2 = {0}; + + TRACE( "params %p\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + + params2.hDevice = params->hDevice; + params2.hResource = params->hResource; + params2.phAllocationList = params->phAllocationList; + params2.AllocationCount = params->AllocationCount; + return NtGdiDdDDIDestroyAllocation2( ¶ms2 ); }
/****************************************************************************** diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 210df1571f2..45f56f29a0b 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -1639,7 +1639,7 @@ static void test_D3DKMTCreateAllocation( void ) status = D3DKMTCreateAllocation( NULL );
status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
wcscpy( open_adapter.DeviceName, L"\\.\DISPLAY1" ); status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter ); @@ -1668,34 +1668,34 @@ static void test_D3DKMTCreateAllocation( void ) allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; create.hPrivateRuntimeResourceHandle = (HANDLE)0xdeadbeef; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create.hGlobalShare, ==, 0 ); ok_x4( create.hResource, ==, 0 ); - todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + check_d3dkmt_local( allocs[0].hAllocation, &next_local ); ok_ptr( create.hPrivateRuntimeResourceHandle, ==, (HANDLE)0xdeadbeef );
destroy.hDevice = create_device.hDevice; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); destroy.AllocationCount = 1; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); destroy.phAllocationList = &allocs[0].hAllocation; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); /* allocation has already been destroyed */ status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
/* D3DKMTCreateAllocation2 also works with the same parameters, with extra alloc info */ create.pAllocationInfo2 = allocs2; allocs2[0].hAllocation = create.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation2( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create.hGlobalShare, ==, 0 ); ok_x4( create.hResource, ==, 0 ); - todo_wine check_d3dkmt_local( allocs2[0].hAllocation, &next_local ); + check_d3dkmt_local( allocs2[0].hAllocation, &next_local ); ok_x4( create.PrivateRuntimeDataSize, ==, 0 ); ok_x4( create.PrivateDriverDataSize, ==, 0 ); ok_x4( allocs2[0].PrivateDriverDataSize, ==, 0 ); @@ -1703,23 +1703,23 @@ static void test_D3DKMTCreateAllocation( void )
destroy.phAllocationList = &allocs2[0].hAllocation; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); destroy.phAllocationList = &allocs[0].hAllocation;
/* D3DKMTDestroyAllocation2 works as well */ allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create.hGlobalShare, ==, 0 ); ok_x4( create.hResource, ==, 0 ); - todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + check_d3dkmt_local( allocs[0].hAllocation, &next_local );
destroy2.hDevice = create_device.hDevice; destroy2.AllocationCount = 1; destroy2.phAllocationList = &allocs[0].hAllocation; status = D3DKMTDestroyAllocation2( &destroy2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* alloc PrivateDriverDataSize can be set */ @@ -1727,88 +1727,88 @@ static void test_D3DKMTCreateAllocation( void ) allocs[0].PrivateDriverDataSize = sizeof(expect_alloc_data); allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create.hGlobalShare, ==, 0 ); ok_x4( create.hResource, ==, 0 ); - todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + check_d3dkmt_local( allocs[0].hAllocation, &next_local ); status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* PrivateRuntimeDataSize can be set */ create.pPrivateRuntimeData = expect_runtime_data; create.PrivateRuntimeDataSize = sizeof(expect_runtime_data); allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create.hGlobalShare, ==, 0 ); ok_x4( create.hResource, ==, 0 ); - todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + check_d3dkmt_local( allocs[0].hAllocation, &next_local ); status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* PrivateDriverDataSize must be 0 for standard allocations */ create.PrivateDriverDataSize = 64; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.PrivateDriverDataSize = 0;
/* device handle is required */ create.hDevice = 0; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.hDevice = create_device.hDevice;
/* hResource must be valid or 0 */ create.hResource = 0x1eadbeed; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_HANDLE, status ); + ok_nt( STATUS_INVALID_HANDLE, status ); create.hResource = 0;
/* NumAllocations is required */ create.NumAllocations = 0; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.NumAllocations = 1;
/* standard.Type must be set */ standard[0].Type = 0; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); standard[0].Type = D3DKMT_STANDARDALLOCATIONTYPE_EXISTINGHEAP;
/* pSystemMem must be set */ allocs[0].pSystemMem = 0; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); allocs[0].pSystemMem = allocs2[0].pSystemMem;
/* creating multiple allocations doesn't work */ create.NumAllocations = 2; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.NumAllocations = 1;
/* ExistingHeapData.Size must be page aligned */ standard[0].ExistingHeapData.Size = 0x1100; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); standard[0].ExistingHeapData.Size = 0x10000;
/* specific flags are required for standard allocations */ create.Flags.ExistingSysMem = 0; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.Flags.ExistingSysMem = 1; create.Flags.StandardAllocation = 0; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.Flags.StandardAllocation = 1;
/* CreateShared doesn't work without CreateResource */ create.Flags.CreateShared = 1; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.Flags.CreateShared = 0;
@@ -1817,24 +1817,24 @@ static void test_D3DKMTCreateAllocation( void ) allocs[0].hAllocation = create.hGlobalShare = create.hResource = 0x1eadbeed; create.hPrivateRuntimeResourceHandle = (HANDLE)0xdeadbeef; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_HANDLE, status ); + ok_nt( STATUS_INVALID_HANDLE, status ); create.hResource = 0; /* hResource must be set to 0, even with CreateResource */ status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create.hGlobalShare, ==, 0 ); - todo_wine check_d3dkmt_local( create.hResource, &next_local ); - todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create.hGlobalShare, ==, 0 ); + check_d3dkmt_local( create.hResource, &next_local ); + check_d3dkmt_local( allocs[0].hAllocation, &next_local ); ok_ptr( create.hPrivateRuntimeResourceHandle, ==, (HANDLE)0xdeadbeef );
/* destroying the allocation doesn't destroys the resource */ status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); destroy.hResource = create.hResource; destroy.AllocationCount = 0; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); destroy.AllocationCount = 1; create.hResource = 0;
@@ -1842,28 +1842,28 @@ static void test_D3DKMTCreateAllocation( void ) create.Flags.CreateResource = 1; allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create.hGlobalShare, ==, 0 ); - todo_wine check_d3dkmt_local( create.hResource, &next_local ); - todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create.hGlobalShare, ==, 0 ); + check_d3dkmt_local( create.hResource, &next_local ); + check_d3dkmt_local( allocs[0].hAllocation, &next_local );
/* cannot create allocations with an existing resource */ create.Flags.CreateResource = 0; create.pAllocationInfo = &allocs[1]; allocs[1].hAllocation = create.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.pAllocationInfo = &allocs[0];
/* destroying resource destroys its allocations */ destroy.hResource = create.hResource; destroy.AllocationCount = 0; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); destroy.hResource = 0; destroy.AllocationCount = 1; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.hResource = 0;
@@ -1871,7 +1871,7 @@ static void test_D3DKMTCreateAllocation( void ) create.Flags.CreateResource = 1; create.NumAllocations = 0; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); create.NumAllocations = 1;
/* destroy resource at once from here */ @@ -1880,10 +1880,10 @@ static void test_D3DKMTCreateAllocation( void )
allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create.hGlobalShare, ==, 0 ); - todo_wine check_d3dkmt_local( create.hResource, &next_local ); - todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create.hGlobalShare, ==, 0 ); + check_d3dkmt_local( create.hResource, &next_local ); + check_d3dkmt_local( allocs[0].hAllocation, &next_local );
/* D3DKMTQueryResourceInfo requires a global handle */ query.hDevice = create_device.hDevice; @@ -1899,7 +1899,7 @@ static void test_D3DKMTCreateAllocation( void )
destroy.hResource = create.hResource; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); create.hResource = 0;
@@ -1907,10 +1907,10 @@ static void test_D3DKMTCreateAllocation( void ) create.Flags.CreateShared = 1; allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_global( create.hGlobalShare ); - todo_wine check_d3dkmt_local( create.hResource, &next_local ); - todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_global( create.hGlobalShare ); + check_d3dkmt_local( create.hResource, &next_local ); + check_d3dkmt_local( allocs[0].hAllocation, &next_local );
/* D3DKMTQueryResourceInfo works with global handle */ memset( runtime_data, 0xcd, sizeof(runtime_data) ); @@ -2000,18 +2000,19 @@ static void test_D3DKMTCreateAllocation( void ) ok_x4( open.ResourcePrivateDriverDataSize, ==, 0 ); ok_u4( open.NumAllocations, ==, 1 ); todo_wine check_d3dkmt_local( open_alloc2.hAllocation, &next_local ); + next_local = 0; ok_x4( open_alloc2.PrivateDriverDataSize, >, 0 ); todo_wine ok_x4( open_alloc2.PrivateDriverDataSize, <, sizeof(alloc_data) ); open.pOpenAllocationInfo = &open_alloc;
destroy.hResource = open.hResource; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); open.hResource = 0;
destroy.hResource = create.hResource; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); create.hResource = 0;
@@ -2020,14 +2021,14 @@ static void test_D3DKMTCreateAllocation( void ) create.Flags.CreateShared = 1; allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create.hGlobalShare, ==, 0 ); - todo_wine check_d3dkmt_local( create.hResource, &next_local ); - todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create.hGlobalShare, ==, 0 ); + check_d3dkmt_local( create.hResource, &next_local ); + check_d3dkmt_local( allocs[0].hAllocation, &next_local );
destroy.hResource = create.hResource; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); create.hResource = 0;
@@ -2292,10 +2293,10 @@ static void test_D3DKMTShareObjects( void ) alloc.PrivateDriverDataSize = sizeof(expect_alloc_data); alloc.hAllocation = create_alloc.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create_alloc ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create_alloc.hGlobalShare, ==, 0 ); - todo_wine check_d3dkmt_local( create_alloc.hResource, NULL ); - todo_wine check_d3dkmt_local( alloc.hAllocation, NULL ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create_alloc.hGlobalShare, ==, 0 ); + check_d3dkmt_local( create_alloc.hResource, NULL ); + check_d3dkmt_local( alloc.hAllocation, NULL );
status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); @@ -2305,17 +2306,17 @@ static void test_D3DKMTShareObjects( void ) destroy_alloc.hDevice = create_device.hDevice; destroy_alloc.hResource = create_alloc.hResource; status = D3DKMTDestroyAllocation( &destroy_alloc ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); create_alloc.hResource = 0;
create_alloc.Flags.CreateShared = 1; alloc.hAllocation = create_alloc.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create_alloc ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_global( create_alloc.hGlobalShare ); - todo_wine check_d3dkmt_local( create_alloc.hResource, NULL ); - todo_wine check_d3dkmt_local( alloc.hAllocation, NULL ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_global( create_alloc.hGlobalShare ); + check_d3dkmt_local( create_alloc.hResource, NULL ); + check_d3dkmt_local( alloc.hAllocation, NULL );
status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); @@ -2324,17 +2325,17 @@ static void test_D3DKMTShareObjects( void )
destroy_alloc.hResource = create_alloc.hResource; status = D3DKMTDestroyAllocation( &destroy_alloc ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); create_alloc.hResource = 0;
create_alloc.Flags.NtSecuritySharing = 1; alloc.hAllocation = create_alloc.hGlobalShare = 0x1eadbeed; status = D3DKMTCreateAllocation( &create_alloc ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( create_alloc.hGlobalShare, ==, 0 ); - todo_wine check_d3dkmt_local( create_alloc.hResource, NULL ); - todo_wine check_d3dkmt_local( alloc.hAllocation, NULL ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( create_alloc.hGlobalShare, ==, 0 ); + check_d3dkmt_local( create_alloc.hResource, NULL ); + check_d3dkmt_local( alloc.hAllocation, NULL );
/* can only share resources, not allocations */ status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); @@ -2523,7 +2524,7 @@ static void test_D3DKMTShareObjects( void )
destroy_alloc.hResource = create_alloc.hResource; status = D3DKMTDestroyAllocation( &destroy_alloc ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); create_alloc.hResource = 0;
diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c index cfa67e82ebb..bf5705f52a6 100644 --- a/dlls/wow64win/gdi.c +++ b/dlls/wow64win/gdi.c @@ -497,16 +497,16 @@ NTSTATUS WINAPI wow64_NtGdiDdDDICreateAllocation( UINT *args ) standard.Flags = standard32->Flags;
desc.pStandardAllocation = &standard; - desc.PrivateDriverDataSize = sizeof(standard); + desc.PrivateDriverDataSize = desc32->PrivateDriverDataSize; } desc.NumAllocations = desc32->NumAllocations; + allocs32 = UlongToPtr( desc32->pAllocationInfo ); desc.pAllocationInfo = NULL; if (desc32->pAllocationInfo && desc32->NumAllocations) { if (!(desc.pAllocationInfo = Wow64AllocateTemp( desc32->NumAllocations + sizeof(*desc.pAllocationInfo) ))) return STATUS_NO_MEMORY;
- allocs32 = UlongToPtr( desc32->pAllocationInfo ); for (i = 0; i < desc32->NumAllocations; i++) { desc.pAllocationInfo[i].hAllocation = allocs32->hAllocation; @@ -523,6 +523,8 @@ NTSTATUS WINAPI wow64_NtGdiDdDDICreateAllocation( UINT *args ) status = NtGdiDdDDICreateAllocation( &desc ); desc32->hResource = desc.hResource; desc32->hGlobalShare = desc.hGlobalShare; + for (i = 0; desc32->pAllocationInfo && i < desc32->NumAllocations; i++) + allocs32->hAllocation = desc.pAllocationInfo[i].hAllocation; return status; }
@@ -607,13 +609,13 @@ NTSTATUS WINAPI wow64_NtGdiDdDDICreateAllocation2( UINT *args ) desc.PrivateDriverDataSize = sizeof(standard); } desc.NumAllocations = desc32->NumAllocations; + allocs32 = UlongToPtr( desc32->pAllocationInfo2 ); desc.pAllocationInfo2 = NULL; if (desc32->pAllocationInfo2 && desc32->NumAllocations) { if (!(desc.pAllocationInfo2 = Wow64AllocateTemp( desc32->NumAllocations + sizeof(*desc.pAllocationInfo2) ))) return STATUS_NO_MEMORY;
- allocs32 = UlongToPtr( desc32->pAllocationInfo2 ); for (i = 0; i < desc32->NumAllocations; i++) { desc.pAllocationInfo2[i].hAllocation = allocs32->hAllocation; @@ -632,7 +634,10 @@ NTSTATUS WINAPI wow64_NtGdiDdDDICreateAllocation2( UINT *args ) desc32->hResource = desc.hResource; desc32->hGlobalShare = desc.hGlobalShare; for (i = 0; desc32->pAllocationInfo2 && i < desc32->NumAllocations; i++) + { + allocs32->hAllocation = desc.pAllocationInfo2[i].hAllocation; allocs32->GpuVirtualAddress = desc.pAllocationInfo2[i].GpuVirtualAddress; + } return status; }
diff --git a/server/protocol.def b/server/protocol.def index 8605c940d6b..e22b34ee3d2 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -976,6 +976,8 @@ enum d3dkmt_type D3DKMT_SOURCE = 3, D3DKMT_MUTEX = 4, D3DKMT_SYNC = 5, + D3DKMT_RESOURCE = 6, + D3DKMT_ALLOCATION = 7, };
/****************************************************************/
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 13 ++++++++----- dlls/wow64win/gdi.c | 2 +- server/d3dkmt.c | 14 +++++++++----- server/protocol.def | 1 + 4 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 64d71fc45a1..4ef8bc8fcab 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -163,14 +163,14 @@ static NTSTATUS d3dkmt_object_alloc( UINT size, enum d3dkmt_type type, void **ob return STATUS_SUCCESS; }
-/* create a global D3DKMT object, either with a global handle or later shareable */ -static NTSTATUS d3dkmt_object_create( struct d3dkmt_object *obj, BOOL shared ) +static NTSTATUS d3dkmt_object_create( struct d3dkmt_object *obj, BOOL shared, const void *runtime, UINT runtime_size ) { NTSTATUS status;
SERVER_START_REQ( d3dkmt_object_create ) { req->type = obj->type; + if (runtime_size) wine_server_add_data( req, runtime, runtime_size ); if (!(status = wine_server_call( req ))) { obj->handle = wine_server_ptr_handle( reply->handle ); @@ -799,7 +799,8 @@ NTSTATUS WINAPI NtGdiDdDDICreateAllocation2( D3DKMT_CREATEALLOCATION *params ) if ((status = d3dkmt_object_alloc( sizeof(*allocation), D3DKMT_ALLOCATION, (void **)&allocation ))) goto failed;
if (!params->Flags.CreateShared) status = alloc_object_handle( &resource->obj ); - else status = d3dkmt_object_create( &resource->obj, params->Flags.NtSecuritySharing ); + else status = d3dkmt_object_create( &resource->obj, params->Flags.NtSecuritySharing, + params->pPrivateRuntimeData, params->PrivateRuntimeDataSize ); if (status) goto failed;
params->hGlobalShare = resource->obj.shared ? 0 : resource->obj.global; @@ -959,7 +960,9 @@ NTSTATUS WINAPI NtGdiDdDDICreateKeyedMutex2( D3DKMT_CREATEKEYEDMUTEX2 *params ) if (!params) return STATUS_INVALID_PARAMETER;
if ((status = d3dkmt_object_alloc( sizeof(*mutex), D3DKMT_MUTEX, (void **)&mutex ))) return status; - if ((status = d3dkmt_object_create( mutex, params->Flags.NtSecuritySharing ))) goto failed; + if ((status = d3dkmt_object_create( mutex, params->Flags.NtSecuritySharing, + params->pPrivateRuntimeData, params->PrivateRuntimeDataSize ))) + goto failed;
params->hSharedHandle = mutex->shared ? 0 : mutex->global; params->hKeyedMutex = mutex->local; @@ -1054,7 +1057,7 @@ NTSTATUS WINAPI NtGdiDdDDICreateSynchronizationObject2( D3DKMT_CREATESYNCHRONIZA
if ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) return status; if (!params->Info.Flags.Shared) status = alloc_object_handle( sync ); - else status = d3dkmt_object_create( sync, params->Info.Flags.NtSecuritySharing ); + else status = d3dkmt_object_create( sync, params->Info.Flags.NtSecuritySharing, NULL, 0 ); if (status) goto failed;
if (params->Info.Flags.Shared) params->Info.SharedHandle = sync->shared ? 0 : sync->global; diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c index bf5705f52a6..40dbd811e01 100644 --- a/dlls/wow64win/gdi.c +++ b/dlls/wow64win/gdi.c @@ -606,7 +606,7 @@ NTSTATUS WINAPI wow64_NtGdiDdDDICreateAllocation2( UINT *args ) standard.Flags = standard32->Flags;
desc.pStandardAllocation = &standard; - desc.PrivateDriverDataSize = sizeof(standard); + desc.PrivateDriverDataSize = desc32->PrivateDriverDataSize; } desc.NumAllocations = desc32->NumAllocations; allocs32 = UlongToPtr( desc32->pAllocationInfo2 ); diff --git a/server/d3dkmt.c b/server/d3dkmt.c index 0249afca1a1..fb50ffb59c0 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -42,6 +42,8 @@ struct d3dkmt_object struct object obj; /* object header */ enum d3dkmt_type type; /* object type */ d3dkmt_handle_t global; /* object global handle */ + char *runtime; /* client runtime data */ + mem_size_t runtime_size; /* size of client runtime data */ };
static void d3dkmt_object_dump( struct object *obj, int verbose ); @@ -144,17 +146,19 @@ static void d3dkmt_object_destroy( struct object *obj ) assert( obj->ops == &d3dkmt_object_ops );
if (object->global) free_object_handle( object ); + free( object->runtime ); }
-static struct d3dkmt_object *d3dkmt_object_create( enum d3dkmt_type type ) +static struct d3dkmt_object *d3dkmt_object_create( enum d3dkmt_type type, mem_size_t runtime_size, const void *runtime ) { struct d3dkmt_object *object;
if (!(object = alloc_object( &d3dkmt_object_ops ))) return NULL; - object->type = type; - object->global = 0; + object->type = type; + object->global = 0; + object->runtime_size = runtime_size;
- if (!alloc_object_handle( object )) + if (!(object->runtime = memdup( runtime, runtime_size )) || !alloc_object_handle( object )) { release_object( object ); set_error( STATUS_NO_MEMORY ); @@ -169,7 +173,7 @@ DECL_HANDLER(d3dkmt_object_create) { struct d3dkmt_object *object;
- if (!(object = d3dkmt_object_create( req->type ))) return; + if (!(object = d3dkmt_object_create( req->type, get_req_data_size(), get_req_data() ))) return; reply->handle = alloc_handle( current->process, object, STANDARD_RIGHTS_ALL, OBJ_INHERIT ); reply->global = object->global; release_object( object ); diff --git a/server/protocol.def b/server/protocol.def index e22b34ee3d2..6d5980cc43f 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4154,6 +4154,7 @@ enum inproc_sync_type /* Create a global d3dkmt object */ @REQ(d3dkmt_object_create) unsigned int type; /* d3dkmt object type */ + VARARG(runtime,bytes); /* client runtime data */ @REPLY d3dkmt_handle_t global; /* global d3dkmt handle */ obj_handle_t handle; /* process-private handle */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 41 ++++++++++++++++++++++++++++++++++++-- dlls/win32u/tests/d3dkmt.c | 12 +++++------ server/d3dkmt.c | 31 ++++++++++++++++++++++++++++ server/protocol.def | 8 ++++++++ 4 files changed, 84 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 4ef8bc8fcab..b9f4cd9b153 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -74,6 +74,11 @@ static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); / static struct d3dkmt_object **objects; static unsigned int object_count, object_capacity, last_index;
+static BOOL is_d3dkmt_global( D3DKMT_HANDLE handle ) +{ + return (handle & 0xc0000000) && (handle & 0x3f) == 2; +} + /* return the position of the first object which handle is not less than * the given local handle, d3dkmt_lock must be held. */ static unsigned int object_handle_lower_bound( D3DKMT_HANDLE local ) @@ -187,6 +192,24 @@ static NTSTATUS d3dkmt_object_create( struct d3dkmt_object *obj, BOOL shared, co return status; }
+static NTSTATUS d3dkmt_object_query( enum d3dkmt_type type, D3DKMT_HANDLE global, UINT *runtime_size ) +{ + NTSTATUS status; + + SERVER_START_REQ( d3dkmt_object_query ) + { + req->type = type; + req->global = global; + status = wine_server_call( req ); + *runtime_size = reply->runtime_size; + } + SERVER_END_REQ; + + if (status) WARN( "Failed to query resource %#x, status %#x\n", global, status ); + else TRACE( "Found resource %#x with runtime size %#x\n", global, *runtime_size ); + return status; +} + static void d3dkmt_object_free( struct d3dkmt_object *object ) { TRACE( "object %p/%#x, global %#x\n", object, object->local, object->global ); @@ -933,8 +956,22 @@ NTSTATUS WINAPI NtGdiDdDDIOpenNtHandleFromName( D3DKMT_OPENNTHANDLEFROMNAME *par */ NTSTATUS WINAPI NtGdiDdDDIQueryResourceInfo( D3DKMT_QUERYRESOURCEINFO *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *device; + NTSTATUS status; + + TRACE( "params %p\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + if (!(device = get_d3dkmt_object( params->hDevice, D3DKMT_DEVICE ))) return STATUS_INVALID_PARAMETER; + if (!is_d3dkmt_global( params->hGlobalShare )) return STATUS_INVALID_PARAMETER; + + if ((status = d3dkmt_object_query( D3DKMT_RESOURCE, params->hGlobalShare, ¶ms->PrivateRuntimeDataSize ))) + return status; + + params->TotalPrivateDriverDataSize = 0; + params->ResourcePrivateDriverDataSize = 0; + params->NumAllocations = 1; + return STATUS_SUCCESS; }
/****************************************************************************** diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 45f56f29a0b..f79bbcccecf 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -1889,7 +1889,7 @@ static void test_D3DKMTCreateAllocation( void ) query.hDevice = create_device.hDevice; query.hGlobalShare = create.hResource; status = D3DKMTQueryResourceInfo( &query ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
/* D3DKMTOpenResource requires a global handle */ open.hDevice = create_device.hDevice; @@ -1920,12 +1920,12 @@ static void test_D3DKMTCreateAllocation( void ) query.PrivateRuntimeDataSize = sizeof(runtime_data); query.ResourcePrivateDriverDataSize = 0; status = D3DKMTQueryResourceInfo( &query ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( query.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( query.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); todo_wine ok_x4( query.TotalPrivateDriverDataSize, >, 0 ); ok_x4( query.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); ok_x4( query.ResourcePrivateDriverDataSize, ==, 0 ); - todo_wine ok_u4( query.NumAllocations, ==, 1 ); + ok_u4( query.NumAllocations, ==, 1 ); /* runtime data doesn't get updated ? */ ok_u1( runtime_data[0], ==, 0xcd );
@@ -1951,7 +1951,7 @@ static void test_D3DKMTCreateAllocation( void ) todo_wine ok_nt( STATUS_SUCCESS, status ); ok_x4( open.hGlobalShare, ==, create.hGlobalShare ); todo_wine check_d3dkmt_local( open.hResource, &next_local ); - todo_wine ok_x4( open.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + ok_x4( open.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); ok_x4( open.TotalPrivateDriverDataBufferSize, >, 0 ); todo_wine ok_x4( open.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); ok_x4( open.ResourcePrivateDriverDataSize, ==, 0 ); @@ -1994,7 +1994,7 @@ static void test_D3DKMTCreateAllocation( void ) todo_wine ok_nt( STATUS_SUCCESS, status ); ok_x4( open.hGlobalShare, ==, create.hGlobalShare ); todo_wine check_d3dkmt_local( open.hResource, &next_local ); - todo_wine ok_x4( open.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + ok_x4( open.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); ok_x4( open.TotalPrivateDriverDataBufferSize, >, 0 ); todo_wine ok_x4( open.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); ok_x4( open.ResourcePrivateDriverDataSize, ==, 0 ); diff --git a/server/d3dkmt.c b/server/d3dkmt.c index fb50ffb59c0..525a37e3e76 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -168,6 +168,24 @@ static struct d3dkmt_object *d3dkmt_object_create( enum d3dkmt_type type, mem_si return object; }
+/* return a pointer to a d3dkmt object from its global handle */ +static void *d3dkmt_object_open( d3dkmt_handle_t global, enum d3dkmt_type type ) +{ + struct d3dkmt_object *object; + unsigned int index; + + index = object_handle_lower_bound( global ); + if (index >= object_count) object = NULL; + else object = objects[index]; + + if (!object || object->global != global || object->type != type) + { + set_error( STATUS_INVALID_PARAMETER ); + return NULL; + } + return grab_object( object ); +} + /* create a global d3dkmt object */ DECL_HANDLER(d3dkmt_object_create) { @@ -178,3 +196,16 @@ DECL_HANDLER(d3dkmt_object_create) reply->global = object->global; release_object( object ); } + +/* query a global d3dkmt object */ +DECL_HANDLER(d3dkmt_object_query) +{ + struct d3dkmt_object *object; + + if (!req->global) return; + object = d3dkmt_object_open( req->global, req->type ); + if (!object) return; + + reply->runtime_size = object->runtime_size; + release_object( object ); +} diff --git a/server/protocol.def b/server/protocol.def index 6d5980cc43f..d68513ef3a7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4160,3 +4160,11 @@ enum inproc_sync_type obj_handle_t handle; /* process-private handle */ @END
+ +/* Query a global d3dkmt object */ +@REQ(d3dkmt_object_query) + unsigned int type; /* d3dkmt object type */ + d3dkmt_handle_t global; /* global d3dkmt handle */ +@REPLY + mem_size_t runtime_size; /* size of client runtime data */ +@END
v2: Add some trace messages.