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 ],