-- v3: 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. win32u: Use array indexes for d3dkmt handles.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 89 +++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 39 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 13f05f2d069..c91ed0309ef 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -69,80 +69,91 @@ struct d3dkmt_vidpn_source static pthread_mutex_t d3dkmt_lock = PTHREAD_MUTEX_INITIALIZER; static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); /* VidPN source information list */
-static struct d3dkmt_object **objects; -static unsigned int object_count, object_capacity, last_index; +static struct d3dkmt_object **objects, **objects_end, **objects_next;
-/* 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 ) +#define D3DKMT_HANDLE_BIT 0x40000000 + +static D3DKMT_HANDLE index_to_handle( int index ) { - unsigned int begin = 0, end = object_count, mid; + return (index << 6) | D3DKMT_HANDLE_BIT; +}
- while (begin < end) - { - mid = begin + (end - begin) / 2; - if (objects[mid]->local < local) begin = mid + 1; - else end = mid; - } +static int handle_to_index( D3DKMT_HANDLE handle ) +{ + return (handle & ~0xc0000000) >> 6; +} + +static NTSTATUS init_handle_table(void) +{ + if (!(objects = calloc( 1024, sizeof(*objects) ))) return STATUS_NO_MEMORY; + objects_end = objects + 1024; + objects_next = objects; + return STATUS_SUCCESS; +} + +static struct d3dkmt_object **grow_handle_table(void) +{ + size_t old_capacity = objects_end - objects, max_capacity = handle_to_index( D3DKMT_HANDLE_BIT - 1 ); + unsigned int new_capacity = old_capacity * 3 / 2; + struct d3dkmt_object **tmp; + + if (new_capacity > max_capacity) new_capacity = max_capacity; + if (new_capacity <= old_capacity) return NULL; /* exhausted handle capacity */ + + if (!(tmp = realloc( objects, new_capacity * sizeof(*objects) ))) return NULL; + memset( tmp + old_capacity, 0, (new_capacity - old_capacity) * sizeof(*tmp) ); + + objects = tmp; + objects_end = tmp + new_capacity; + objects_next = tmp + old_capacity;
- return begin; + return objects_next; }
/* allocate a d3dkmt object with a local handle */ static NTSTATUS alloc_object_handle( struct d3dkmt_object *object ) { - D3DKMT_HANDLE handle = 0; - unsigned int index; + struct d3dkmt_object **entry;
pthread_mutex_lock( &d3dkmt_lock ); + if (!objects && init_handle_table()) goto done;
- if (object_count >= object_capacity) + for (entry = objects_next; entry < objects_end; entry++) if (!*entry) break; + if (entry == objects_end) { - 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; + for (entry = objects; entry < objects_next; entry++) if (!*entry) break; + if (entry == objects_next && !(entry = grow_handle_table())) goto done; }
- last_index += 0x40; - handle = object->local = (last_index & ~0xc0000000) | 0x40000000; - index = object_handle_lower_bound( object->local ); - if (index < object_count) memmove( objects + index + 1, objects, (object_count - index) * sizeof(*objects) ); - objects[index] = object; - object_count++; + object->local = index_to_handle( entry - objects ); + objects_next = entry + 1; + *entry = object;
done: pthread_mutex_unlock( &d3dkmt_lock ); - return handle ? STATUS_SUCCESS : STATUS_NO_MEMORY; + return object->local ? STATUS_SUCCESS : STATUS_NO_MEMORY; }
/* free a d3dkmt local object handle */ static void free_object_handle( struct d3dkmt_object *object ) { - unsigned int index; + unsigned int index = handle_to_index( object->local );
pthread_mutex_lock( &d3dkmt_lock ); - index = object_handle_lower_bound( object->local ); - assert( index < object_count && objects[index] == object ); - object_count--; + assert( objects + index < objects_end && objects[index] == object ); + objects[index] = NULL; object->local = 0; - memmove( objects + index, objects + index + 1, (object_count - index) * sizeof(*objects) ); pthread_mutex_unlock( &d3dkmt_lock ); }
/* return a pointer to a d3dkmt object from its local handle */ static void *get_d3dkmt_object( D3DKMT_HANDLE local, enum d3dkmt_type type ) { + unsigned int index = handle_to_index( local ); struct d3dkmt_object *object; - unsigned int index;
pthread_mutex_lock( &d3dkmt_lock ); - index = object_handle_lower_bound( local ); - if (index >= object_count) object = NULL; + if (objects + index >= objects_end) object = NULL; else object = objects[index]; pthread_mutex_unlock( &d3dkmt_lock );
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 c91ed0309ef..24129f1cd20 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 @@ -172,9 +166,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 ); }
@@ -841,8 +859,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; }
/****************************************************************************** @@ -850,8 +883,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; }
/****************************************************************************** @@ -859,8 +902,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 | 90 +++++++++++++++++++++++++++++++++++++- server/protocol.def | 2 + tools/make_requests | 1 + 5 files changed, 103 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 24129f1cd20..cd3df745866 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 */ };
@@ -177,6 +179,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; @@ -184,13 +188,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 ); @@ -869,7 +873,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..84d53e31c72 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,93 @@ static const struct object_ops d3dkmt_object_ops = d3dkmt_object_destroy, /* destroy */ };
+static struct d3dkmt_object **objects, **objects_end, **objects_next; + +#define D3DKMT_HANDLE_BIT 0x40000000 + +static d3dkmt_handle_t index_to_handle( int index ) +{ + return (index << 6) | D3DKMT_HANDLE_BIT | 2; +} + +static int handle_to_index( d3dkmt_handle_t handle ) +{ + return (handle & ~0xc000003f) >> 6; +} + +static NTSTATUS init_handle_table(void) +{ + if (!(objects = calloc( 1024, sizeof(*objects) ))) return STATUS_NO_MEMORY; + objects_end = objects + 1024; + objects_next = objects; + return STATUS_SUCCESS; +} + +static struct d3dkmt_object **grow_handle_table(void) +{ + size_t old_capacity = objects_end - objects, max_capacity = handle_to_index( D3DKMT_HANDLE_BIT - 1 ); + unsigned int new_capacity = old_capacity * 3 / 2; + struct d3dkmt_object **tmp; + + if (new_capacity > max_capacity) new_capacity = max_capacity; + if (new_capacity <= old_capacity) return NULL; /* exhausted handle capacity */ + + if (!(tmp = realloc( objects, new_capacity * sizeof(*objects) ))) return NULL; + memset( tmp + old_capacity, 0, (new_capacity - old_capacity) * sizeof(*tmp) ); + + objects = tmp; + objects_end = tmp + new_capacity; + objects_next = tmp + old_capacity; + + return objects_next; +} + +/* allocate a d3dkmt object with a global handle */ +static NTSTATUS alloc_object_handle( struct d3dkmt_object *object ) +{ + struct d3dkmt_object **entry; + + if (!objects && init_handle_table()) goto done; + + for (entry = objects_next; entry < objects_end; entry++) if (!*entry) break; + if (entry == objects_end) + { + for (entry = objects; entry < objects_next; entry++) if (!*entry) break; + if (entry == objects_next && !(entry = grow_handle_table())) goto done; + } + + object->global = index_to_handle( entry - objects ); + objects_next = entry + 1; + *entry = object; + +done: + return object->global ? STATUS_SUCCESS : STATUS_NO_MEMORY; +} + +/* free a d3dkmt global object handle */ +static void free_object_handle( struct d3dkmt_object *object ) +{ + unsigned int index = handle_to_index( object->global ); + + assert( objects + index < objects_end && objects[index] == object ); + objects[index] = NULL; + object->global = 0; +} + 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 +166,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 +186,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 cd3df745866..063b3341073 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -950,8 +950,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; }
/****************************************************************************** @@ -959,8 +983,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; }
/****************************************************************************** @@ -1004,6 +1043,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 063b3341073..3b51ddbb7b2 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 */ @@ -772,8 +778,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; }
/****************************************************************************** @@ -781,8 +843,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 ); }
/****************************************************************************** @@ -790,8 +851,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; }
/****************************************************************************** @@ -799,8 +889,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 3b51ddbb7b2..d7a6aec2032 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -174,14 +174,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 ); @@ -810,7 +810,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; @@ -970,7 +971,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; @@ -1065,7 +1068,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 84d53e31c72..e19a006494a 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 ); @@ -159,17 +161,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 ); @@ -184,7 +188,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 | 39 ++++++++++++++++++++++++++++++++++++ server/protocol.def | 8 ++++++++ 4 files changed, 92 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index d7a6aec2032..e4a6bc81035 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -75,6 +75,11 @@ static struct d3dkmt_object **objects, **objects_end, **objects_next;
#define D3DKMT_HANDLE_BIT 0x40000000
+static BOOL is_d3dkmt_global( D3DKMT_HANDLE handle ) +{ + return (handle & 0xc0000000) && (handle & 0x3f) == 2; +} + static D3DKMT_HANDLE index_to_handle( int index ) { return (index << 6) | D3DKMT_HANDLE_BIT; @@ -198,6 +203,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 ); @@ -944,8 +967,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 e19a006494a..8ba6599001e 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -147,6 +147,19 @@ static void free_object_handle( struct d3dkmt_object *object ) object->global = 0; }
+/* return a pointer to a d3dkmt object from its global handle */ +static void *get_d3dkmt_object( d3dkmt_handle_t global, enum d3dkmt_type type ) +{ + unsigned int index = handle_to_index( global ); + struct d3dkmt_object *object; + + if (objects + index >= objects_end) object = NULL; + else object = objects[index]; + + if (!object || object->global != global || (type != -1 && object->type != type)) return NULL; + return object; +} + static void d3dkmt_object_dump( struct object *obj, int verbose ) { struct d3dkmt_object *object = (struct d3dkmt_object *)obj; @@ -183,6 +196,19 @@ 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; + + if (!(object = get_d3dkmt_object( global, type ))) + { + set_error( STATUS_INVALID_PARAMETER ); + return NULL; + } + return grab_object( object ); +} + /* create a global d3dkmt object */ DECL_HANDLER(d3dkmt_object_create) { @@ -193,3 +219,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
v3: Use a linear lookup for handle allocation while keeping the monotonic allocation until table is reallocated. This should also fix the incorrect handle reuse when index wraps around.
Alexandre Julliard (@julliard) commented about server/d3dkmt.c:
- if (new_capacity > max_capacity) new_capacity = max_capacity;
- if (new_capacity <= old_capacity) return NULL; /* exhausted handle capacity */
- if (!(tmp = realloc( objects, new_capacity * sizeof(*objects) ))) return NULL;
- memset( tmp + old_capacity, 0, (new_capacity - old_capacity) * sizeof(*tmp) );
- objects = tmp;
- objects_end = tmp + new_capacity;
- objects_next = tmp + old_capacity;
- return objects_next;
+}
+/* allocate a d3dkmt object with a global handle */ +static NTSTATUS alloc_object_handle( struct d3dkmt_object *object ) +{
It's not useful to return NTSTATUS from these functions if you are not making use of it.
You should either return an error code (as unsigned int rather than NTSTATUS) and propagate it properly, or even better, use set_error() and then return a success/failure boolean.