From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 160 ++++++++++++++++++++++++++++++++++--- dlls/win32u/tests/d3dkmt.c | 121 +++++++++++++--------------- dlls/wow64win/gdi.c | 13 ++- server/d3dkmt.c | 26 ++++++ server/protocol.def | 12 +++ 5 files changed, 254 insertions(+), 78 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index e073c11a832..f21a7728581 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -202,6 +202,30 @@ static NTSTATUS d3dkmt_object_create( struct d3dkmt_object *object, BOOL shared, return status; }
+static NTSTATUS d3dkmt_object_open( struct d3dkmt_object *obj, D3DKMT_HANDLE global, + void *runtime, UINT *runtime_size ) +{ + NTSTATUS status; + + SERVER_START_REQ( d3dkmt_object_open ) + { + req->type = obj->type; + req->global = global; + if (runtime) wine_server_set_reply( req, runtime, *runtime_size ); + status = wine_server_call( req ); + obj->handle = wine_server_ptr_handle( reply->handle ); + obj->global = reply->global; + obj->shared = !global; + *runtime_size = reply->runtime_size; + } + SERVER_END_REQ; + if (!status) status = alloc_object_handle( obj ); + + if (status) WARN( "Failed to open global object %#x, status %#x\n", global, status ); + else TRACE( "Opened global object %#x as %p/%#x\n", global, obj, obj->local ); + return status; +} + static NTSTATUS d3dkmt_object_query( enum d3dkmt_type type, D3DKMT_HANDLE global, UINT *runtime_size ) { NTSTATUS status; @@ -215,8 +239,8 @@ static NTSTATUS d3dkmt_object_query( enum d3dkmt_type type, D3DKMT_HANDLE global } SERVER_END_REQ;
- if (status) WARN( "Failed to query object %#x, status %#x\n", global, status ); - else TRACE( "Found object %#x with runtime size %#x\n", global, *runtime_size ); + if (status) WARN( "Failed to query global object %#x, status %#x\n", global, status ); + else TRACE( "Found global object %#x with runtime size %#x\n", global, *runtime_size ); return status; }
@@ -930,8 +954,42 @@ NTSTATUS WINAPI NtGdiDdDDIDestroyAllocation( const D3DKMT_DESTROYALLOCATION *par */ NTSTATUS WINAPI NtGdiDdDDIOpenResource( D3DKMT_OPENRESOURCE *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *device, *allocation; + D3DDDI_OPENALLOCATIONINFO *alloc_info; + struct d3dkmt_resource *resource; + UINT runtime_size; + 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 (params->ResourcePrivateDriverDataSize) return STATUS_INVALID_PARAMETER; + + if (!params->NumAllocations) return STATUS_INVALID_PARAMETER; + if (!(alloc_info = params->pOpenAllocationInfo)) return STATUS_INVALID_PARAMETER; + + 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; + + runtime_size = params->PrivateRuntimeDataSize; + if ((status = d3dkmt_object_open( &resource->obj, params->hGlobalShare, params->pPrivateRuntimeData, &runtime_size ))) goto failed; + + if ((status = alloc_object_handle( allocation ))) goto failed; + resource->allocation = allocation->local; + alloc_info->hAllocation = allocation->local; + alloc_info->PrivateDriverDataSize = 0; + + params->hResource = resource->obj.local; + params->PrivateRuntimeDataSize = runtime_size; + params->TotalPrivateDriverDataBufferSize = 0; + params->ResourcePrivateDriverDataSize = 0; + return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( &resource->obj ); + return status; }
/****************************************************************************** @@ -939,8 +997,42 @@ NTSTATUS WINAPI NtGdiDdDDIOpenResource( D3DKMT_OPENRESOURCE *params ) */ NTSTATUS WINAPI NtGdiDdDDIOpenResource2( D3DKMT_OPENRESOURCE *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *device, *allocation; + D3DDDI_OPENALLOCATIONINFO2 *alloc_info; + struct d3dkmt_resource *resource; + UINT runtime_size; + 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 (params->ResourcePrivateDriverDataSize) return STATUS_INVALID_PARAMETER; + + if (!params->NumAllocations) return STATUS_INVALID_PARAMETER; + if (!(alloc_info = params->pOpenAllocationInfo2)) return STATUS_INVALID_PARAMETER; + + 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; + + runtime_size = params->PrivateRuntimeDataSize; + if ((status = d3dkmt_object_open( &resource->obj, params->hGlobalShare, params->pPrivateRuntimeData, &runtime_size ))) goto failed; + + if ((status = alloc_object_handle( allocation ))) goto failed; + resource->allocation = allocation->local; + alloc_info->hAllocation = allocation->local; + alloc_info->PrivateDriverDataSize = 0; + + params->hResource = resource->obj.local; + params->PrivateRuntimeDataSize = runtime_size; + params->TotalPrivateDriverDataBufferSize = 0; + params->ResourcePrivateDriverDataSize = 0; + return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( &resource->obj ); + return status; }
/****************************************************************************** @@ -1060,8 +1152,27 @@ NTSTATUS WINAPI NtGdiDdDDIDestroyKeyedMutex( const D3DKMT_DESTROYKEYEDMUTEX *par */ NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutex2( D3DKMT_OPENKEYEDMUTEX2 *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *mutex; + UINT runtime_size; + NTSTATUS status; + + TRACE( "params %p\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + if (!is_d3dkmt_global( params->hSharedHandle )) return STATUS_INVALID_PARAMETER; + if (params->PrivateRuntimeDataSize && !params->pPrivateRuntimeData) return STATUS_INVALID_PARAMETER; + + if ((status = d3dkmt_object_alloc( sizeof(*mutex), D3DKMT_MUTEX, (void **)&mutex ))) return status; + + runtime_size = params->PrivateRuntimeDataSize; + if ((status = d3dkmt_object_open( mutex, params->hSharedHandle, params->pPrivateRuntimeData, &runtime_size ))) goto failed; + + params->hKeyedMutex = mutex->local; + return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( mutex ); + return status; }
/****************************************************************************** @@ -1069,8 +1180,17 @@ NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutex2( D3DKMT_OPENKEYEDMUTEX2 *params ) */ NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutex( D3DKMT_OPENKEYEDMUTEX *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + D3DKMT_OPENKEYEDMUTEX2 params2 = {0}; + NTSTATUS status; + + TRACE( "params %p\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + + params2.hSharedHandle = params->hSharedHandle; + status = NtGdiDdDDIOpenKeyedMutex2( ¶ms2 ); + params->hKeyedMutex = params2.hKeyedMutex; + return status; }
/****************************************************************************** @@ -1172,8 +1292,24 @@ NTSTATUS WINAPI NtGdiDdDDIOpenSyncObjectNtHandleFromName( D3DKMT_OPENSYNCOBJECTN */ NTSTATUS WINAPI NtGdiDdDDIOpenSynchronizationObject( D3DKMT_OPENSYNCHRONIZATIONOBJECT *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *sync; + NTSTATUS status; + UINT dummy = 0; + + TRACE( "params %p\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + if (!is_d3dkmt_global( params->hSharedHandle )) return STATUS_INVALID_PARAMETER; + + if ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) return status; + if ((status = d3dkmt_object_open( sync, params->hSharedHandle, NULL, &dummy ))) goto failed; + + params->hSyncObject = sync->local; + return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( sync ); + return status; }
/****************************************************************************** diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index b6080dbe604..83ed9f0dfd0 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -1230,8 +1230,8 @@ static void test_D3DKMTCreateSynchronizationObject_process( const char *arg ) open.hSharedHandle = global; open.hSyncObject = 0x1eadbeed; status = D3DKMTOpenSynchronizationObject( &open ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open.hSyncObject, &next_local ); /* leak the object */ }
@@ -1401,22 +1401,22 @@ static void test_D3DKMTCreateSynchronizationObject( void ) /* D3DKMTOpenSynchronizationObject creates a new local D3DKMT_HANDLE */ open.hSharedHandle = 0x1eadbeed; status = D3DKMTOpenSynchronizationObject( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open.hSharedHandle = 0; status = D3DKMTOpenSynchronizationObject( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open.hSyncObject = create2.hSyncObject; status = D3DKMTOpenSynchronizationObject( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open.hSyncObject = 0x1eadbeed; open.hSharedHandle = create2.Info.SharedHandle; status = D3DKMTOpenSynchronizationObject( &open ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open.hSyncObject, &next_local ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open.hSyncObject, &next_local );
destroy.hSyncObject = open.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); /* destroying multiple times fails */ status = D3DKMTDestroySynchronizationObject( &destroy ); ok_nt( STATUS_INVALID_PARAMETER, status ); @@ -1424,20 +1424,19 @@ static void test_D3DKMTCreateSynchronizationObject( void ) /* 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; + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open.hSyncObject, &next_local );
destroy.hSyncObject = open.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
destroy.hSyncObject = create2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy ); 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 ); + ok_nt( STATUS_INVALID_PARAMETER, status );
/* NtSecuritySharing requires Shared, doesn't creates a global handle */ @@ -1483,7 +1482,7 @@ static void test_D3DKMTCreateSynchronizationObject( void )
open.hSharedHandle = create2.Info.SharedHandle; status = D3DKMTOpenSynchronizationObject( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
destroy_device.hDevice = create_device.hDevice; @@ -1514,16 +1513,15 @@ static void test_D3DKMTCreateKeyedMutex( void ) check_d3dkmt_global( create.hSharedHandle );
status = D3DKMTOpenKeyedMutex( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open.hKeyedMutex = create.hKeyedMutex; status = D3DKMTOpenKeyedMutex( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open.hKeyedMutex = 0x1eadbeed; open.hSharedHandle = create.hSharedHandle; status = D3DKMTOpenKeyedMutex( &open ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open.hKeyedMutex, &next_local ); - next_local = 0; + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open.hKeyedMutex, &next_local );
status = D3DKMTDestroyKeyedMutex( &destroy ); ok_nt( STATUS_INVALID_PARAMETER, status ); @@ -1533,12 +1531,12 @@ static void test_D3DKMTCreateKeyedMutex( void ) /* older W10 lets you destroy the global D3DKMT_HANDLE, it causes random failures in the tests below */ destroy.hKeyedMutex = create.hSharedHandle; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); }
destroy.hKeyedMutex = open.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); /* destroying multiple times fails */ status = D3DKMTDestroyKeyedMutex( &destroy ); ok_nt( STATUS_INVALID_PARAMETER, status ); @@ -1549,7 +1547,7 @@ static void test_D3DKMTCreateKeyedMutex( void )
/* the global D3DKMT_HANDLE is destroyed with last reference */ status = D3DKMTOpenKeyedMutex( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
status = D3DKMTCreateKeyedMutex2( NULL ); @@ -1568,16 +1566,15 @@ static void test_D3DKMTCreateKeyedMutex( void ) check_d3dkmt_global( create2.hSharedHandle );
status = D3DKMTOpenKeyedMutex2( &open2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open2.hKeyedMutex = create2.hKeyedMutex; status = D3DKMTOpenKeyedMutex2( &open2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open2.hKeyedMutex = 0x1eadbeed; open2.hSharedHandle = create2.hSharedHandle; status = D3DKMTOpenKeyedMutex2( &open2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open2.hKeyedMutex, &next_local ); - next_local = 0; + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open2.hKeyedMutex, &next_local );
status = D3DKMTDestroyKeyedMutex( &destroy ); ok_nt( STATUS_SUCCESS, status ); @@ -1586,7 +1583,7 @@ static void test_D3DKMTCreateKeyedMutex( void ) ok_nt( STATUS_SUCCESS, status ); destroy.hKeyedMutex = open2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* PrivateRuntimeDataSize must be 0 if no buffer is provided */ @@ -1600,17 +1597,16 @@ static void test_D3DKMTCreateKeyedMutex( void ) open2.hSharedHandle = create2.hSharedHandle; open2.PrivateRuntimeDataSize = sizeof(buffer); status = D3DKMTOpenKeyedMutex2( &open2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open2.pPrivateRuntimeData = buffer; status = D3DKMTOpenKeyedMutex2( &open2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open2.hKeyedMutex, &next_local ); - next_local = 0; + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open2.hKeyedMutex, &next_local ); ok_x4( open2.PrivateRuntimeDataSize, ==, sizeof(buffer) );
destroy.hKeyedMutex = open2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); destroy.hKeyedMutex = create2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); ok_nt( STATUS_SUCCESS, status ); @@ -1628,30 +1624,28 @@ static void test_D3DKMTCreateKeyedMutex( void ) open2.PrivateRuntimeDataSize = 0; open2.pPrivateRuntimeData = NULL; status = D3DKMTOpenKeyedMutex2( &open2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open2.hKeyedMutex, &next_local ); - next_local = 0; + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open2.hKeyedMutex, &next_local ); ok_x4( open2.PrivateRuntimeDataSize, ==, 0 );
open2.PrivateRuntimeDataSize = sizeof(buffer); status = D3DKMTOpenKeyedMutex2( &open2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open2.PrivateRuntimeDataSize = sizeof(runtime_data) - 1; open2.pPrivateRuntimeData = buffer; status = D3DKMTOpenKeyedMutex2( &open2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open2.PrivateRuntimeDataSize = sizeof(runtime_data); memset( buffer, 0xcd, sizeof(buffer) ); status = D3DKMTOpenKeyedMutex2( &open2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open2.hKeyedMutex, &next_local ); - next_local = 0; + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open2.hKeyedMutex, &next_local ); ok_x4( open2.PrivateRuntimeDataSize, ==, sizeof(runtime_data) ); - ok_u1( buffer[0], ==, 0xcd ); + todo_wine ok_u1( buffer[0], ==, 0xcd );
destroy.hKeyedMutex = open2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); destroy.hKeyedMutex = create2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy ); ok_nt( STATUS_SUCCESS, status ); @@ -1957,7 +1951,7 @@ static void test_D3DKMTCreateAllocation( void ) open.hDevice = create_device.hDevice; open.hGlobalShare = create.hResource; status = D3DKMTOpenResource( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
destroy.hResource = create.hResource; status = D3DKMTDestroyAllocation( &destroy ); @@ -2010,41 +2004,41 @@ static void test_D3DKMTCreateAllocation( void ) open_alloc.PrivateDriverDataSize = sizeof(alloc_data); open.hResource = 0x1eadbeed; status = D3DKMTOpenResource( &open ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); ok_x4( open.hGlobalShare, ==, create.hGlobalShare ); - todo_wine check_d3dkmt_local( open.hResource, &next_local ); + check_d3dkmt_local( open.hResource, &next_local ); ok_x4( open.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); - ok_x4( open.TotalPrivateDriverDataBufferSize, >, 0 ); - todo_wine ok_x4( open.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); + todo_wine ok_x4( open.TotalPrivateDriverDataBufferSize, >, 0 ); + ok_x4( open.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); ok_x4( open.ResourcePrivateDriverDataSize, ==, 0 ); ok_u4( open.NumAllocations, ==, 1 ); - todo_wine check_d3dkmt_local( open_alloc.hAllocation, &next_local ); - ok_x4( open_alloc.PrivateDriverDataSize, >, 0 ); - todo_wine ok_x4( open_alloc.PrivateDriverDataSize, <, sizeof(alloc_data) ); - todo_wine ok( !memcmp( runtime_data, expect_runtime_data, sizeof(expect_runtime_data) ), "got data %#x\n", runtime_data[0] ); + check_d3dkmt_local( open_alloc.hAllocation, &next_local ); + todo_wine ok_x4( open_alloc.PrivateDriverDataSize, >, 0 ); + ok_x4( open_alloc.PrivateDriverDataSize, <, sizeof(alloc_data) ); + ok( !memcmp( runtime_data, expect_runtime_data, sizeof(expect_runtime_data) ), "got data %#x\n", runtime_data[0] ); todo_wine ok_u1( driver_data[0], !=, 0xcd ); ok_u1( resource_data[0], ==, 0xcd ); ok_u1( alloc_data[0], ==, 0xcd );
destroy.hResource = open.hResource; status = D3DKMTDestroyAllocation( &destroy ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); open.hResource = 0;
/* NumAllocations must be set */ open.NumAllocations = 0; status = D3DKMTOpenResource( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open.NumAllocations = 1;
/* buffer sizes must match exactly */ open.PrivateRuntimeDataSize += 1; status = D3DKMTOpenResource( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open.PrivateRuntimeDataSize -= 1; open.ResourcePrivateDriverDataSize += 1; status = D3DKMTOpenResource( &open ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open.ResourcePrivateDriverDataSize -= 1;
/* D3DKMTOpenResource2 works as well */ @@ -2053,18 +2047,17 @@ static void test_D3DKMTCreateAllocation( void ) open_alloc2.PrivateDriverDataSize = sizeof(alloc2_data); open_alloc2.hAllocation = 0x1eadbeed; status = D3DKMTOpenResource2( &open ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); ok_x4( open.hGlobalShare, ==, create.hGlobalShare ); - todo_wine check_d3dkmt_local( open.hResource, &next_local ); + check_d3dkmt_local( open.hResource, &next_local ); ok_x4( open.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); - ok_x4( open.TotalPrivateDriverDataBufferSize, >, 0 ); - todo_wine ok_x4( open.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); + todo_wine ok_x4( open.TotalPrivateDriverDataBufferSize, >, 0 ); + ok_x4( open.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); 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) ); + check_d3dkmt_local( open_alloc2.hAllocation, &next_local ); + todo_wine ok_x4( open_alloc2.PrivateDriverDataSize, >, 0 ); + ok_x4( open_alloc2.PrivateDriverDataSize, <, sizeof(alloc_data) ); open.pOpenAllocationInfo = &open_alloc;
destroy.hResource = open.hResource; diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c index 40dbd811e01..7b96e7d3a34 100644 --- a/dlls/wow64win/gdi.c +++ b/dlls/wow64win/gdi.c @@ -1049,13 +1049,13 @@ NTSTATUS WINAPI wow64_NtGdiDdDDIOpenResource( UINT *args ) desc.hDevice = desc32->hDevice; desc.hGlobalShare = desc32->hGlobalShare; desc.NumAllocations = desc32->NumAllocations; + allocs32 = UlongToPtr( desc32->pOpenAllocationInfo ); desc.pOpenAllocationInfo = NULL; if (desc32->pOpenAllocationInfo && desc32->NumAllocations) { if (!(desc.pOpenAllocationInfo = Wow64AllocateTemp( desc32->NumAllocations + sizeof(*desc.pOpenAllocationInfo) ))) return STATUS_NO_MEMORY;
- allocs32 = UlongToPtr( desc32->pOpenAllocationInfo ); for (i = 0; i < desc32->NumAllocations; i++) { desc.pOpenAllocationInfo[i].hAllocation = allocs32->hAllocation; @@ -1074,6 +1074,11 @@ NTSTATUS WINAPI wow64_NtGdiDdDDIOpenResource( UINT *args ) status = NtGdiDdDDIOpenResource( &desc ); desc32->TotalPrivateDriverDataBufferSize = desc.TotalPrivateDriverDataBufferSize; desc32->hResource = desc.hResource; + for (i = 0; desc32->pOpenAllocationInfo && i < desc32->NumAllocations; i++) + { + allocs32->hAllocation = desc.pOpenAllocationInfo[i].hAllocation; + allocs32->PrivateDriverDataSize = desc.pOpenAllocationInfo[i].PrivateDriverDataSize; + } return status; }
@@ -1108,13 +1113,13 @@ NTSTATUS WINAPI wow64_NtGdiDdDDIOpenResource2( UINT *args ) desc.hDevice = desc32->hDevice; desc.hGlobalShare = desc32->hGlobalShare; desc.NumAllocations = desc32->NumAllocations; + allocs32 = UlongToPtr( desc32->pOpenAllocationInfo2 ); desc.pOpenAllocationInfo2 = NULL; if (desc32->pOpenAllocationInfo2 && desc32->NumAllocations) { if (!(desc.pOpenAllocationInfo2 = Wow64AllocateTemp( desc32->NumAllocations + sizeof(*desc.pOpenAllocationInfo2) ))) return STATUS_NO_MEMORY;
- allocs32 = UlongToPtr( desc32->pOpenAllocationInfo2 ); for (i = 0; i < desc32->NumAllocations; i++) { desc.pOpenAllocationInfo2[i].hAllocation = allocs32->hAllocation; @@ -1135,7 +1140,11 @@ NTSTATUS WINAPI wow64_NtGdiDdDDIOpenResource2( UINT *args ) desc32->TotalPrivateDriverDataBufferSize = desc.TotalPrivateDriverDataBufferSize; desc32->hResource = desc.hResource; for (i = 0; desc32->pOpenAllocationInfo2 && i < desc32->NumAllocations; i++) + { + allocs32->hAllocation = desc.pOpenAllocationInfo2[i].hAllocation; + allocs32->PrivateDriverDataSize = desc.pOpenAllocationInfo2[i].PrivateDriverDataSize; allocs32->GpuVirtualAddress = desc.pOpenAllocationInfo2[i].GpuVirtualAddress; + } return status; }
diff --git a/server/d3dkmt.c b/server/d3dkmt.c index 599d037f0af..23f0e6d4a71 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -234,3 +234,29 @@ DECL_HANDLER(d3dkmt_object_query) reply->runtime_size = object->runtime_size; release_object( object ); } + +/* open a global d3dkmt object */ +DECL_HANDLER(d3dkmt_object_open) +{ + data_size_t runtime_size = get_reply_max_size(); + struct d3dkmt_object *object; + obj_handle_t handle; + + if (!req->global) return; + object = d3dkmt_object_open( req->global, req->type ); + if (!object) return; + + /* only resource objects require exact runtime buffer size match */ + if (object->type != D3DKMT_RESOURCE && runtime_size > object->runtime_size) runtime_size = object->runtime_size; + + if (runtime_size && object->runtime_size != runtime_size) set_error( STATUS_INVALID_PARAMETER ); + else if ((handle = alloc_handle( current->process, object, STANDARD_RIGHTS_ALL, OBJ_INHERIT ))) + { + reply->handle = handle; + reply->global = object->global; + reply->runtime_size = object->runtime_size; + if (runtime_size) set_reply_data( object->runtime, runtime_size ); + } + + release_object( object ); +} diff --git a/server/protocol.def b/server/protocol.def index c9c77b1cf17..6b1d1dd1cfb 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4170,3 +4170,15 @@ enum inproc_sync_type @REPLY data_size_t runtime_size; /* size of client runtime data */ @END + + +/* Open a global d3dkmt object */ +@REQ(d3dkmt_object_open) + unsigned int type; /* d3dkmt object type */ + d3dkmt_handle_t global; /* global d3dkmt handle */ +@REPLY + d3dkmt_handle_t global; /* global d3dkmt handle */ + obj_handle_t handle; /* internal handle of the server object */ + data_size_t runtime_size; /* size of client runtime data */ + VARARG(runtime,bytes); /* client runtime data */ +@END
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 131 ++++++++++++++++++++++++++++++++++++- dlls/win32u/tests/d3dkmt.c | 44 ++++++------- server/d3dkmt.c | 86 ++++++++++++++++++++++++ server/protocol.def | 10 +++ 4 files changed, 247 insertions(+), 24 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index f21a7728581..e47a95d9c85 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -252,6 +252,99 @@ static void d3dkmt_object_free( struct d3dkmt_object *object ) free( object ); }
+/* create a struct security_descriptor and contained information in one contiguous piece of memory */ +static unsigned int alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret, + data_size_t *ret_len ) +{ + unsigned int len = sizeof(**ret); + SID *owner = NULL, *group = NULL; + ACL *dacl = NULL, *sacl = NULL; + SECURITY_DESCRIPTOR *sd; + + *ret = NULL; + *ret_len = 0; + + if (!attr) return STATUS_SUCCESS; + + if (attr->Length != sizeof(*attr)) return STATUS_INVALID_PARAMETER; + + if ((sd = attr->SecurityDescriptor)) + { + len += sizeof(struct security_descriptor); + if (sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION; + if (sd->Control & SE_SELF_RELATIVE) + { + SECURITY_DESCRIPTOR_RELATIVE *rel = (SECURITY_DESCRIPTOR_RELATIVE *)sd; + if (rel->Owner) owner = (PSID)((BYTE *)rel + rel->Owner); + if (rel->Group) group = (PSID)((BYTE *)rel + rel->Group); + if ((sd->Control & SE_SACL_PRESENT) && rel->Sacl) sacl = (PSID)((BYTE *)rel + rel->Sacl); + if ((sd->Control & SE_DACL_PRESENT) && rel->Dacl) dacl = (PSID)((BYTE *)rel + rel->Dacl); + } + else + { + owner = sd->Owner; + group = sd->Group; + if (sd->Control & SE_SACL_PRESENT) sacl = sd->Sacl; + if (sd->Control & SE_DACL_PRESENT) dacl = sd->Dacl; + } + + if (owner) len += offsetof( SID, SubAuthority[owner->SubAuthorityCount] ); + if (group) len += offsetof( SID, SubAuthority[group->SubAuthorityCount] ); + if (sacl) len += sacl->AclSize; + if (dacl) len += dacl->AclSize; + + /* fix alignment for the Unicode name that follows the structure */ + len = (len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1); + } + + if (attr->ObjectName) + { + if ((ULONG_PTR)attr->ObjectName->Buffer & (sizeof(WCHAR) - 1)) return STATUS_DATATYPE_MISALIGNMENT; + if (attr->ObjectName->Length & (sizeof(WCHAR) - 1)) return STATUS_OBJECT_NAME_INVALID; + len += attr->ObjectName->Length; + } + else if (attr->RootDirectory) return STATUS_OBJECT_NAME_INVALID; + + len = (len + 3) & ~3; /* DWORD-align the entire structure */ + + if (!(*ret = calloc( len, 1 ))) return STATUS_NO_MEMORY; + + (*ret)->rootdir = wine_server_obj_handle( attr->RootDirectory ); + (*ret)->attributes = attr->Attributes; + + if (attr->SecurityDescriptor) + { + struct security_descriptor *descr = (struct security_descriptor *)(*ret + 1); + unsigned char *ptr = (unsigned char *)(descr + 1); + + descr->control = sd->Control & ~SE_SELF_RELATIVE; + if (owner) descr->owner_len = offsetof( SID, SubAuthority[owner->SubAuthorityCount] ); + if (group) descr->group_len = offsetof( SID, SubAuthority[group->SubAuthorityCount] ); + if (sacl) descr->sacl_len = sacl->AclSize; + if (dacl) descr->dacl_len = dacl->AclSize; + + memcpy( ptr, owner, descr->owner_len ); + ptr += descr->owner_len; + memcpy( ptr, group, descr->group_len ); + ptr += descr->group_len; + memcpy( ptr, sacl, descr->sacl_len ); + ptr += descr->sacl_len; + memcpy( ptr, dacl, descr->dacl_len ); + (*ret)->sd_len = (sizeof(*descr) + descr->owner_len + descr->group_len + descr->sacl_len + + descr->dacl_len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1); + } + + if (attr->ObjectName) + { + unsigned char *ptr = (unsigned char *)(*ret + 1) + (*ret)->sd_len; + (*ret)->name_len = attr->ObjectName->Length; + memcpy( ptr, attr->ObjectName->Buffer, (*ret)->name_len ); + } + + *ret_len = len; + return STATUS_SUCCESS; +} + static VkInstance d3dkmt_vk_instance; /* Vulkan instance for D3DKMT functions */ static PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryProperties2KHR; static PFN_vkGetPhysicalDeviceMemoryProperties pvkGetPhysicalDeviceMemoryProperties; @@ -815,8 +908,42 @@ void free_vulkan_gpu( struct vulkan_gpu *gpu ) NTSTATUS WINAPI NtGdiDdDDIShareObjects( UINT count, const D3DKMT_HANDLE *handles, OBJECT_ATTRIBUTES *attr, UINT access, HANDLE *handle ) { - FIXME( "count %u, handles %p, attr %p, access %#x, handle %p stub!\n", count, handles, attr, access, handle ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *object, *sync; + struct object_attributes *objattr; + data_size_t len; + NTSTATUS status; + + TRACE( "count %u, handles %p, attr %p, access %#x, handle %p\n", count, handles, attr, access, handle ); + + if (count == 1) + { + if (!(object = get_d3dkmt_object( handles[0], -1 )) || !object->shared) goto failed; + if (object->type == D3DKMT_SYNC) sync = object; + else goto failed; + } + else goto failed; + + if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status; + + SERVER_START_REQ( d3dkmt_share_objects ) + { + req->access = access | STANDARD_RIGHTS_ALL; + req->sync = sync->global; + wine_server_add_data( req, objattr, len ); + status = wine_server_call( req ); + *handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + free( objattr ); + + if (status) WARN( "Failed to share objects, status %#x\n", status ); + else TRACE( "Shared objects with handle %p\n", *handle ); + return status; + +failed: + WARN( "Unsupported object count / types / handles\n" ); + return STATUS_INVALID_PARAMETER; }
/****************************************************************************** diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 83ed9f0dfd0..56ac8f81b1e 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -2155,7 +2155,7 @@ static void test_D3DKMTShareObjects( void ) 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 ); + ok_nt( STATUS_INVALID_PARAMETER, status ); if (broken( !status )) CloseHandle( handle ); destroy_sync.hSyncObject = create_sync.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); @@ -2168,7 +2168,7 @@ static void test_D3DKMTShareObjects( void ) 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 ); + ok_nt( STATUS_INVALID_PARAMETER, status ); if (broken( !status )) CloseHandle( handle ); destroy_sync.hSyncObject = create_sync2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); @@ -2179,7 +2179,7 @@ static void test_D3DKMTShareObjects( void ) 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 ); + ok_nt( STATUS_INVALID_PARAMETER, status ); if (broken( !status )) CloseHandle( handle ); destroy_sync.hSyncObject = create_sync2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); @@ -2192,12 +2192,12 @@ static void test_D3DKMTShareObjects( void ) InitializeObjectAttributes( &attr, &name, 0, 0, NULL ); handle = (HANDLE)0xdeadbeef; status = D3DKMTShareObjects( 1, &create_sync2.hSyncObject, &attr, STANDARD_RIGHTS_WRITE, &handle ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); /* handle isn't a D3DKMT_HANDLE */ - todo_wine ok( !((UINT_PTR)handle & 0xc0000000), "got %p\n", handle ); + ok( !((UINT_PTR)handle & 0xc0000000), "got %p\n", handle );
- todo_wine check_object_type( handle, L"DxgkSharedSyncObject" ); - todo_wine check_object_name( handle, name.Buffer ); + check_object_type( handle, L"DxgkSharedSyncObject" ); + check_object_name( handle, name.Buffer );
/* cannot destroy the handle */ destroy_sync.hSyncObject = (UINT_PTR)handle; @@ -2221,7 +2221,7 @@ static void test_D3DKMTShareObjects( void ) /* objects opened with D3DKMTOpenSyncObjectFromNtHandle cannot be reshared */ InitializeObjectAttributes( &attr, &name, 0, 0, NULL ); status = D3DKMTShareObjects( 1, &create_sync2.hSyncObject, &attr, STANDARD_RIGHTS_WRITE, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
destroy_sync.hSyncObject = open_sync.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); @@ -2312,9 +2312,9 @@ static void test_D3DKMTShareObjects( void ) status = D3DKMTCreateKeyedMutex( &create_mutex ); ok_nt( STATUS_SUCCESS, status ); status = D3DKMTShareObjects( 1, &create_mutex.hKeyedMutex, &attr, STANDARD_RIGHTS_WRITE, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + 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 ); + ok_nt( STATUS_INVALID_PARAMETER, status ); destroy_mutex.hKeyedMutex = create_mutex.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); ok_nt( STATUS_SUCCESS, status ); @@ -2323,7 +2323,7 @@ static void test_D3DKMTShareObjects( void ) status = D3DKMTCreateKeyedMutex2( &create_mutex2 ); ok_nt( STATUS_SUCCESS, status ); status = D3DKMTShareObjects( 1, &create_mutex2.hKeyedMutex, &attr, STANDARD_RIGHTS_WRITE, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); destroy_mutex.hKeyedMutex = create_mutex2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); ok_nt( STATUS_SUCCESS, status ); @@ -2354,9 +2354,9 @@ static void test_D3DKMTShareObjects( void ) check_d3dkmt_local( alloc.hAllocation, NULL );
status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); status = D3DKMTShareObjects( 1, &create_alloc.hResource, &attr, STANDARD_RIGHTS_READ, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
destroy_alloc.hDevice = create_device.hDevice; destroy_alloc.hResource = create_alloc.hResource; @@ -2374,9 +2374,9 @@ static void test_D3DKMTShareObjects( void ) check_d3dkmt_local( alloc.hAllocation, NULL );
status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); status = D3DKMTShareObjects( 1, &create_alloc.hResource, &attr, STANDARD_RIGHTS_READ, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
destroy_alloc.hResource = create_alloc.hResource; status = D3DKMTDestroyAllocation( &destroy_alloc ); @@ -2394,7 +2394,7 @@ static void test_D3DKMTShareObjects( void )
/* can only share resources, not allocations */ status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); status = D3DKMTShareObjects( 1, &create_alloc.hResource, &attr, STANDARD_RIGHTS_READ, &handle ); todo_wine ok_nt( STATUS_SUCCESS, status );
@@ -2527,35 +2527,35 @@ static void test_D3DKMTShareObjects( void ) objects[1] = create_alloc.hResource; objects[2] = create_alloc.hResource; status = D3DKMTShareObjects( 3, objects, &attr, STANDARD_RIGHTS_ALL, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
objects[0] = create_alloc.hResource; objects[1] = create_mutex2.hKeyedMutex; status = D3DKMTShareObjects( 2, objects, &attr, STANDARD_RIGHTS_ALL, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
objects[0] = create_alloc.hResource; objects[1] = create_sync2.hSyncObject; status = D3DKMTShareObjects( 2, objects, &attr, STANDARD_RIGHTS_ALL, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
objects[0] = create_mutex2.hKeyedMutex; objects[1] = create_sync2.hSyncObject; status = D3DKMTShareObjects( 2, objects, &attr, STANDARD_RIGHTS_ALL, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
objects[0] = create_alloc.hResource; objects[1] = create_mutex2.hKeyedMutex; objects[2] = create_sync2.hSyncObject; objects[3] = create_sync2.hSyncObject; status = D3DKMTShareObjects( 4, objects, &attr, STANDARD_RIGHTS_ALL, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
objects[0] = create_alloc.hResource; objects[1] = create_sync2.hSyncObject; objects[2] = create_mutex2.hKeyedMutex; status = D3DKMTShareObjects( 3, objects, &attr, STANDARD_RIGHTS_ALL, &handle ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status );
objects[0] = create_alloc.hResource; objects[1] = create_mutex2.hKeyedMutex; diff --git a/server/d3dkmt.c b/server/d3dkmt.c index 23f0e6d4a71..95032ede3d1 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -72,6 +72,72 @@ static const struct object_ops d3dkmt_object_ops = d3dkmt_object_destroy, /* destroy */ };
+#define DXGK_SHARED_SYNC_QUERY_STATE 0x0001 +#define DXGK_SHARED_SYNC_MODIFY_STATE 0x0002 +#define DXGK_SHARED_SYNC_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) + +static const WCHAR dxgk_shared_sync_name[] = {'D','x','g','k','S','h','a','r','e','d','S','y','n','c','O','b','j','e','c','t'}; + +struct type_descr dxgk_shared_sync_type = +{ + { dxgk_shared_sync_name, sizeof(dxgk_shared_sync_name) }, /* name */ + DXGK_SHARED_SYNC_ALL_ACCESS, /* valid_access */ + { /* mapping */ + STANDARD_RIGHTS_READ | DXGK_SHARED_SYNC_QUERY_STATE, + STANDARD_RIGHTS_WRITE | DXGK_SHARED_SYNC_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, + DXGK_SHARED_SYNC_ALL_ACCESS, + }, +}; + +struct dxgk_shared_sync +{ + struct object obj; /* object header */ + struct object *sync; /* shared sync object */ +}; + +static void dxgk_shared_sync_dump( struct object *obj, int verbose ); +static void dxgk_shared_sync_destroy( struct object *obj ); + +static const struct object_ops dxgk_shared_sync_ops = +{ + sizeof(struct dxgk_shared_sync), /* size */ + &dxgk_shared_sync_type, /* type */ + dxgk_shared_sync_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 */ + default_get_full_name, /* get_full_name */ + no_lookup_name, /* lookup_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ + no_close_handle, /* close_handle */ + dxgk_shared_sync_destroy, /* destroy */ +}; + +static void dxgk_shared_sync_dump( struct object *obj, int verbose ) +{ + struct dxgk_shared_sync *shared = (struct dxgk_shared_sync *)obj; + assert( obj->ops == &dxgk_shared_sync_ops ); + fprintf( stderr, "sync=%p\n", shared->sync ); +} + +static void dxgk_shared_sync_destroy( struct object *obj ) +{ + struct dxgk_shared_sync *shared = (struct dxgk_shared_sync *)obj; + assert( obj->ops == &dxgk_shared_sync_ops ); + release_object( shared->sync ); +} + static struct d3dkmt_object **objects, **objects_end, **objects_next;
#define D3DKMT_HANDLE_BIT 0x40000000 @@ -260,3 +326,23 @@ DECL_HANDLER(d3dkmt_object_open)
release_object( object ); } + +/* share global d3dkmt objects together */ +DECL_HANDLER(d3dkmt_share_objects) +{ + struct object *sync = NULL; + const struct object_attributes *objattr; + const struct security_descriptor *sd; + struct dxgk_shared_sync *shared; + struct unicode_str name; + struct object *root; + + objattr = get_req_object_attributes( &sd, &name, &root ); + + if (!(sync = get_d3dkmt_object( req->sync, D3DKMT_SYNC ))) return; + + if (!(shared = create_named_object( root, &dxgk_shared_sync_ops, &name, objattr->attributes | OBJ_CASE_INSENSITIVE, NULL ))) return; + shared->sync = grab_object( sync ); + reply->handle = alloc_handle( current->process, shared, req->access, OBJ_INHERIT ); + release_object( shared ); +} diff --git a/server/protocol.def b/server/protocol.def index 6b1d1dd1cfb..819ea6e8311 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4182,3 +4182,13 @@ enum inproc_sync_type data_size_t runtime_size; /* size of client runtime data */ VARARG(runtime,bytes); /* client runtime data */ @END + + +/* Share d3dkmt objects together */ +@REQ(d3dkmt_share_objects) + d3dkmt_handle_t sync; /* sync global handle */ + unsigned int access; /* wanted access rights */ + VARARG(objattr,object_attributes); /* object attributes */ +@REPLY + obj_handle_t handle; /* shared object handle */ +@END
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 23 ++++++-- dlls/win32u/tests/d3dkmt.c | 12 ++--- server/d3dkmt.c | 108 ++++++++++++++++++++++++++++++++++--- server/protocol.def | 2 + 4 files changed, 129 insertions(+), 16 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index e47a95d9c85..2deefd7aada 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -908,7 +908,7 @@ void free_vulkan_gpu( struct vulkan_gpu *gpu ) NTSTATUS WINAPI NtGdiDdDDIShareObjects( UINT count, const D3DKMT_HANDLE *handles, OBJECT_ATTRIBUTES *attr, UINT access, HANDLE *handle ) { - struct d3dkmt_object *object, *sync; + struct d3dkmt_object *object, *resource = NULL, *sync = NULL, *mutex = NULL; struct object_attributes *objattr; data_size_t len; NTSTATUS status; @@ -918,9 +918,24 @@ NTSTATUS WINAPI NtGdiDdDDIShareObjects( UINT count, const D3DKMT_HANDLE *handles if (count == 1) { if (!(object = get_d3dkmt_object( handles[0], -1 )) || !object->shared) goto failed; - if (object->type == D3DKMT_SYNC) sync = object; + if (object->type == D3DKMT_RESOURCE) resource = object; + else if (object->type == D3DKMT_SYNC) sync = object; else goto failed; } + else if (count == 3) + { + if (!(object = get_d3dkmt_object( handles[0], -1 )) || !object->shared) goto failed; + if (object->type != D3DKMT_RESOURCE) goto failed; + resource = object; + + if (!(object = get_d3dkmt_object( handles[1], -1 )) || !object->shared) goto failed; + if (object->type != D3DKMT_MUTEX) goto failed; + mutex = object; + + if (!(object = get_d3dkmt_object( handles[2], -1 )) || !object->shared) goto failed; + if (object->type != D3DKMT_SYNC) goto failed; + sync = object; + } else goto failed;
if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status; @@ -928,7 +943,9 @@ NTSTATUS WINAPI NtGdiDdDDIShareObjects( UINT count, const D3DKMT_HANDLE *handles SERVER_START_REQ( d3dkmt_share_objects ) { req->access = access | STANDARD_RIGHTS_ALL; - req->sync = sync->global; + if (resource) req->resource = resource->global; + if (mutex) req->mutex = mutex->global; + if (sync) req->sync = sync->global; wine_server_add_data( req, objattr, len ); status = wine_server_call( req ); *handle = wine_server_ptr_handle( reply->handle ); diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 56ac8f81b1e..baa4b95355f 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -2396,10 +2396,10 @@ static void test_D3DKMTShareObjects( void ) status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); ok_nt( STATUS_INVALID_PARAMETER, status ); status = D3DKMTShareObjects( 1, &create_alloc.hResource, &attr, STANDARD_RIGHTS_READ, &handle ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
- todo_wine check_object_type( handle, L"DxgkSharedResource" ); - todo_wine check_object_name( handle, name.Buffer ); + check_object_type( handle, L"DxgkSharedResource" ); + check_object_name( handle, name.Buffer );
status = D3DKMTOpenNtHandleFromName( &open_resource_name ); @@ -2562,10 +2562,10 @@ static void test_D3DKMTShareObjects( void ) objects[2] = create_sync2.hSyncObject; handle = (HANDLE)0xdeadbeef; status = D3DKMTShareObjects( 3, objects, &attr, STANDARD_RIGHTS_ALL, &handle ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
- todo_wine check_object_type( handle, L"DxgkSharedResource" ); - todo_wine check_object_name( handle, name.Buffer ); + check_object_type( handle, L"DxgkSharedResource" ); + check_object_name( handle, name.Buffer );
destroy_mutex.hKeyedMutex = create_mutex2.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); diff --git a/server/d3dkmt.c b/server/d3dkmt.c index 95032ede3d1..0939cdecbb3 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -138,6 +138,76 @@ static void dxgk_shared_sync_destroy( struct object *obj ) release_object( shared->sync ); }
+#define DXGK_SHARED_RESOURCE_MODIFY_STATE 0x0001 +#define DXGK_SHARED_RESOURCE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x1) + +static const WCHAR dxgk_shared_resource_name[] = {'D','x','g','k','S','h','a','r','e','d','R','e','s','o','u','r','c','e'}; + +struct type_descr dxgk_shared_resource_type = +{ + { dxgk_shared_resource_name, sizeof(dxgk_shared_resource_name) }, /* name */ + DXGK_SHARED_RESOURCE_ALL_ACCESS, /* valid_access */ + { /* mapping */ + STANDARD_RIGHTS_READ, + STANDARD_RIGHTS_WRITE | DXGK_SHARED_RESOURCE_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE, + STANDARD_RIGHTS_REQUIRED | DXGK_SHARED_RESOURCE_MODIFY_STATE, + }, +}; + +struct dxgk_shared_resource +{ + struct object obj; /* object header */ + struct object *resource; /* shared resource object */ + struct object *mutex; /* shared keyed mutex object */ + struct object *sync; /* shared sync object */ +}; + +static void dxgk_shared_resource_dump( struct object *obj, int verbose ); +static void dxgk_shared_resource_destroy( struct object *obj ); + +static const struct object_ops dxgk_shared_resource_ops = +{ + sizeof(struct dxgk_shared_resource), /* size */ + &dxgk_shared_resource_type, /* type */ + dxgk_shared_resource_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 */ + default_get_full_name, /* get_full_name */ + no_lookup_name, /* lookup_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ + no_close_handle, /* close_handle */ + dxgk_shared_resource_destroy, /* destroy */ +}; + +static void dxgk_shared_resource_dump( struct object *obj, int verbose ) +{ + struct dxgk_shared_resource *shared = (struct dxgk_shared_resource *)obj; + assert( obj->ops == &dxgk_shared_resource_ops ); + fprintf( stderr, "resource=%p mutex=%p sync=%p\n", shared->resource, + shared->mutex, shared->sync ); +} + +static void dxgk_shared_resource_destroy( struct object *obj ) +{ + struct dxgk_shared_resource *shared = (struct dxgk_shared_resource *)obj; + assert( obj->ops == &dxgk_shared_resource_ops ); + release_object( shared->resource ); + if (shared->mutex) release_object( shared->mutex ); + if (shared->sync) release_object( shared->sync ); +} + static struct d3dkmt_object **objects, **objects_end, **objects_next;
#define D3DKMT_HANDLE_BIT 0x40000000 @@ -330,19 +400,43 @@ DECL_HANDLER(d3dkmt_object_open) /* share global d3dkmt objects together */ DECL_HANDLER(d3dkmt_share_objects) { - struct object *sync = NULL; + struct object *resource = NULL, *mutex = NULL, *sync = NULL; const struct object_attributes *objattr; const struct security_descriptor *sd; - struct dxgk_shared_sync *shared; struct unicode_str name; struct object *root;
objattr = get_req_object_attributes( &sd, &name, &root );
- if (!(sync = get_d3dkmt_object( req->sync, D3DKMT_SYNC ))) return; + if (req->resource) + { + struct dxgk_shared_resource *shared; + + if (!(resource = d3dkmt_object_open( req->resource, D3DKMT_RESOURCE ))) return; + if (req->mutex && !(mutex = d3dkmt_object_open( req->mutex, D3DKMT_MUTEX ))) goto done; + if (req->sync && !(sync = d3dkmt_object_open( req->sync, D3DKMT_SYNC ))) goto done; + + if (!(shared = create_named_object( root, &dxgk_shared_resource_ops, &name, objattr->attributes | OBJ_CASE_INSENSITIVE, NULL ))) goto done; + shared->resource = grab_object( resource ); + if ((shared->mutex = mutex)) grab_object( mutex ); + if ((shared->sync = sync)) grab_object( sync ); + reply->handle = alloc_handle( current->process, shared, req->access, OBJ_INHERIT ); + release_object( shared ); + } + else + { + struct dxgk_shared_sync *shared; + + if (!(sync = d3dkmt_object_open( req->sync, D3DKMT_SYNC ))) return;
- if (!(shared = create_named_object( root, &dxgk_shared_sync_ops, &name, objattr->attributes | OBJ_CASE_INSENSITIVE, NULL ))) return; - shared->sync = grab_object( sync ); - reply->handle = alloc_handle( current->process, shared, req->access, OBJ_INHERIT ); - release_object( shared ); + if (!(shared = create_named_object( root, &dxgk_shared_sync_ops, &name, objattr->attributes | OBJ_CASE_INSENSITIVE, NULL ))) goto done; + shared->sync = grab_object( sync ); + reply->handle = alloc_handle( current->process, shared, req->access, OBJ_INHERIT ); + release_object( shared ); + } + +done: + if (resource) release_object( resource ); + if (mutex) release_object( mutex ); + if (sync) release_object( sync ); } diff --git a/server/protocol.def b/server/protocol.def index 819ea6e8311..2e9c4d6ea27 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4186,6 +4186,8 @@ enum inproc_sync_type
/* Share d3dkmt objects together */ @REQ(d3dkmt_share_objects) + d3dkmt_handle_t resource; /* resource global handle */ + d3dkmt_handle_t mutex; /* mutex global handle */ d3dkmt_handle_t sync; /* sync global handle */ unsigned int access; /* wanted access rights */ VARARG(objattr,object_attributes); /* object attributes */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 25 +++++++++++++++++++------ dlls/win32u/tests/d3dkmt.c | 22 +++++++++++----------- server/d3dkmt.c | 34 ++++++++++++++++++++++++++++++++-- server/protocol.def | 3 ++- 4 files changed, 64 insertions(+), 20 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 2deefd7aada..3536d8732e1 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -226,7 +226,8 @@ static NTSTATUS d3dkmt_object_open( struct d3dkmt_object *obj, D3DKMT_HANDLE glo return status; }
-static NTSTATUS d3dkmt_object_query( enum d3dkmt_type type, D3DKMT_HANDLE global, UINT *runtime_size ) +static NTSTATUS d3dkmt_object_query( enum d3dkmt_type type, D3DKMT_HANDLE global, HANDLE handle, + UINT *runtime_size ) { NTSTATUS status;
@@ -234,13 +235,14 @@ static NTSTATUS d3dkmt_object_query( enum d3dkmt_type type, D3DKMT_HANDLE global { req->type = type; req->global = global; + req->handle = wine_server_obj_handle( handle ); status = wine_server_call( req ); *runtime_size = reply->runtime_size; } SERVER_END_REQ;
- if (status) WARN( "Failed to query global object %#x, status %#x\n", global, status ); - else TRACE( "Found global object %#x with runtime size %#x\n", global, *runtime_size ); + if (status) WARN( "Failed to query global object %#x/%p, status %#x\n", global, handle, status ); + else TRACE( "Found global object %#x/%p with runtime size %#x\n", global, handle, *runtime_size ); return status; }
@@ -1211,7 +1213,8 @@ NTSTATUS WINAPI NtGdiDdDDIQueryResourceInfo( D3DKMT_QUERYRESOURCEINFO *params ) 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 ))) + if ((status = d3dkmt_object_query( D3DKMT_RESOURCE, params->hGlobalShare, NULL, + ¶ms->PrivateRuntimeDataSize ))) return status;
params->TotalPrivateDriverDataSize = 0; @@ -1225,8 +1228,18 @@ NTSTATUS WINAPI NtGdiDdDDIQueryResourceInfo( D3DKMT_QUERYRESOURCEINFO *params ) */ NTSTATUS WINAPI NtGdiDdDDIQueryResourceInfoFromNtHandle( D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS status; + + TRACE( "params %p\n", params ); + + if ((status = d3dkmt_object_query( D3DKMT_RESOURCE, 0, params->hNtHandle, + ¶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 baa4b95355f..ececd663449 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -2590,19 +2590,19 @@ static void test_D3DKMTShareObjects( void ) query_resource.ResourcePrivateDriverDataSize = 0xdeadbeef; query_resource.NumAllocations = 0xdeadbeef; status = D3DKMTQueryResourceInfoFromNtHandle( &query_resource ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( query_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); - ok_x4( query_resource.TotalPrivateDriverDataSize, >, 0 ); - todo_wine ok_x4( query_resource.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); - todo_wine ok_x4( query_resource.ResourcePrivateDriverDataSize, ==, 0 ); - todo_wine ok_u4( query_resource.NumAllocations, ==, 1 ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( query_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + todo_wine ok_x4( query_resource.TotalPrivateDriverDataSize, >, 0 ); + ok_x4( query_resource.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); + ok_x4( query_resource.ResourcePrivateDriverDataSize, ==, 0 ); + ok_u4( query_resource.NumAllocations, ==, 1 );
memset( runtime_data, 0xcd, sizeof(runtime_data) ); query_resource.pPrivateRuntimeData = runtime_data; query_resource.PrivateRuntimeDataSize = sizeof(runtime_data); status = D3DKMTQueryResourceInfoFromNtHandle( &query_resource ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( query_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( query_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); ok_u1( runtime_data[0], ==, 0xcd );
memset( runtime_data, 0xcd, sizeof(runtime_data) ); @@ -2623,10 +2623,10 @@ static void test_D3DKMTShareObjects( void ) status = D3DKMTOpenResourceFromNtHandle( &open_resource ); todo_wine ok_nt( STATUS_SUCCESS, status ); ok_u4( open_resource.NumAllocations, ==, 1 ); - todo_wine ok_x4( open_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + ok_x4( open_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); ok_x4( open_resource.ResourcePrivateDriverDataSize, ==, 0 ); - ok_x4( open_resource.TotalPrivateDriverDataBufferSize, >, 0 ); - todo_wine ok_x4( open_resource.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); + todo_wine ok_x4( open_resource.TotalPrivateDriverDataBufferSize, >, 0 ); + ok_x4( open_resource.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); todo_wine check_d3dkmt_local( open_resource.hResource, NULL ); todo_wine check_d3dkmt_local( open_resource.hKeyedMutex, NULL ); ok_x4( open_resource.KeyedMutexPrivateRuntimeDataSize, ==, sizeof(expect_mutex_data) ); diff --git a/server/d3dkmt.c b/server/d3dkmt.c index 0939cdecbb3..ce81521a2ff 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -347,6 +347,36 @@ static void *d3dkmt_object_open( d3dkmt_handle_t global, enum d3dkmt_type type ) return grab_object( object ); }
+static struct d3dkmt_object *d3dkmt_object_open_shared( obj_handle_t handle, enum d3dkmt_type type ) +{ + struct object *obj, *ret = NULL; + + if ((obj = get_handle_obj( current->process, handle, 0, &dxgk_shared_resource_ops ))) + { + struct dxgk_shared_resource *shared = (struct dxgk_shared_resource *)obj; + if (type == D3DKMT_RESOURCE) ret = grab_object( shared->resource ); + else if (type == D3DKMT_MUTEX && shared->mutex) ret = grab_object( shared->mutex ); + else if (type == D3DKMT_SYNC && shared->sync) ret = grab_object( shared->sync ); + release_object( obj ); + if (!ret) set_error( STATUS_INVALID_PARAMETER ); + return (struct d3dkmt_object *)ret; + } + + if (type != D3DKMT_SYNC) return NULL; + + /* try again looking for a shared sync if client asked for a sync object */ + set_error( STATUS_SUCCESS ); + + if ((obj = get_handle_obj( current->process, handle, 0, &dxgk_shared_sync_ops ))) + { + struct dxgk_shared_sync *shared = (struct dxgk_shared_sync *)obj; + ret = grab_object( shared->sync ); + release_object( obj ); + } + + return (struct d3dkmt_object *)ret; +} + /* create a global d3dkmt object */ DECL_HANDLER(d3dkmt_object_create) { @@ -363,8 +393,8 @@ DECL_HANDLER(d3dkmt_object_query) { struct d3dkmt_object *object;
- if (!req->global) return; - object = d3dkmt_object_open( req->global, req->type ); + if (req->global) object = d3dkmt_object_open( req->global, req->type ); + else object = d3dkmt_object_open_shared( req->handle, req->type ); if (!object) return;
reply->runtime_size = object->runtime_size; diff --git a/server/protocol.def b/server/protocol.def index 2e9c4d6ea27..036e35cdf68 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4163,10 +4163,11 @@ enum inproc_sync_type @END
-/* Query a global d3dkmt object */ +/* Query a global/shared d3dkmt object */ @REQ(d3dkmt_object_query) unsigned int type; /* d3dkmt object type */ d3dkmt_handle_t global; /* global d3dkmt handle */ + obj_handle_t handle; /* shared object handle */ @REPLY data_size_t runtime_size; /* size of client runtime data */ @END
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 121 ++++++++++++++++++++++++++++++++----- dlls/win32u/tests/d3dkmt.c | 62 +++++++++---------- dlls/wow64win/gdi.c | 8 ++- server/d3dkmt.c | 4 +- server/protocol.def | 3 +- 5 files changed, 148 insertions(+), 50 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 3536d8732e1..665a7b36175 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -202,7 +202,7 @@ static NTSTATUS d3dkmt_object_create( struct d3dkmt_object *object, BOOL shared, return status; }
-static NTSTATUS d3dkmt_object_open( struct d3dkmt_object *obj, D3DKMT_HANDLE global, +static NTSTATUS d3dkmt_object_open( struct d3dkmt_object *obj, D3DKMT_HANDLE global, HANDLE handle, void *runtime, UINT *runtime_size ) { NTSTATUS status; @@ -211,6 +211,7 @@ static NTSTATUS d3dkmt_object_open( struct d3dkmt_object *obj, D3DKMT_HANDLE glo { req->type = obj->type; req->global = global; + req->handle = wine_server_obj_handle( handle ); if (runtime) wine_server_set_reply( req, runtime, *runtime_size ); status = wine_server_call( req ); obj->handle = wine_server_ptr_handle( reply->handle ); @@ -221,8 +222,8 @@ static NTSTATUS d3dkmt_object_open( struct d3dkmt_object *obj, D3DKMT_HANDLE glo SERVER_END_REQ; if (!status) status = alloc_object_handle( obj );
- if (status) WARN( "Failed to open global object %#x, status %#x\n", global, status ); - else TRACE( "Opened global object %#x as %p/%#x\n", global, obj, obj->local ); + if (status) WARN( "Failed to open global object %#x/%p, status %#x\n", global, handle, status ); + else TRACE( "Opened global object %#x/%p as %p/%#x\n", global, handle, obj, obj->local ); return status; }
@@ -1120,7 +1121,7 @@ NTSTATUS WINAPI NtGdiDdDDIOpenResource( D3DKMT_OPENRESOURCE *params ) if ((status = d3dkmt_object_alloc( sizeof(*allocation), D3DKMT_ALLOCATION, (void **)&allocation ))) goto failed;
runtime_size = params->PrivateRuntimeDataSize; - if ((status = d3dkmt_object_open( &resource->obj, params->hGlobalShare, params->pPrivateRuntimeData, &runtime_size ))) goto failed; + if ((status = d3dkmt_object_open( &resource->obj, params->hGlobalShare, NULL, params->pPrivateRuntimeData, &runtime_size ))) goto failed;
if ((status = alloc_object_handle( allocation ))) goto failed; resource->allocation = allocation->local; @@ -1163,7 +1164,7 @@ NTSTATUS WINAPI NtGdiDdDDIOpenResource2( D3DKMT_OPENRESOURCE *params ) if ((status = d3dkmt_object_alloc( sizeof(*allocation), D3DKMT_ALLOCATION, (void **)&allocation ))) goto failed;
runtime_size = params->PrivateRuntimeDataSize; - if ((status = d3dkmt_object_open( &resource->obj, params->hGlobalShare, params->pPrivateRuntimeData, &runtime_size ))) goto failed; + if ((status = d3dkmt_object_open( &resource->obj, params->hGlobalShare, NULL, params->pPrivateRuntimeData, &runtime_size ))) goto failed;
if ((status = alloc_object_handle( allocation ))) goto failed; resource->allocation = allocation->local; @@ -1186,8 +1187,51 @@ failed: */ NTSTATUS WINAPI NtGdiDdDDIOpenResourceFromNtHandle( D3DKMT_OPENRESOURCEFROMNTHANDLE *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *mutex = NULL, *sync = NULL; + struct d3dkmt_resource *resource = NULL; + NTSTATUS status; + UINT dummy = 0; + + FIXME( "params %p semi-stub!\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + if (!params->pPrivateRuntimeData) return STATUS_INVALID_PARAMETER; + if (!params->pTotalPrivateDriverDataBuffer) return STATUS_INVALID_PARAMETER; + if (!params->pOpenAllocationInfo2) return STATUS_INVALID_PARAMETER; + if (!params->NumAllocations) return STATUS_INVALID_PARAMETER; + + if ((status = d3dkmt_object_alloc( sizeof(*resource), D3DKMT_RESOURCE, (void **)&resource ))) return status; + if ((status = d3dkmt_object_alloc( sizeof(*mutex), D3DKMT_MUTEX, (void **)&mutex ))) goto failed; + if ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) goto failed; + + if ((status = d3dkmt_object_open( &resource->obj, 0, params->hNtHandle, params->pPrivateRuntimeData, + ¶ms->PrivateRuntimeDataSize ))) + goto failed; + + if (d3dkmt_object_open( mutex, 0, params->hNtHandle, params->pKeyedMutexPrivateRuntimeData, ¶ms->KeyedMutexPrivateRuntimeDataSize )) + { + d3dkmt_object_free( mutex ); + mutex = NULL; + } + + if (d3dkmt_object_open( sync, 0, params->hNtHandle, NULL, &dummy )) + { + d3dkmt_object_free( sync ); + sync = NULL; + } + + params->hResource = resource->obj.local; + params->hKeyedMutex = mutex ? mutex->local : 0; + params->hSyncObject = sync ? sync->local : 0; + params->TotalPrivateDriverDataBufferSize = 0; + params->ResourcePrivateDriverDataSize = 0; + return STATUS_SUCCESS; + +failed: + if (sync) d3dkmt_object_free( sync ); + if (mutex) d3dkmt_object_free( mutex ); + if (resource) d3dkmt_object_free( &resource->obj ); + return status; }
/****************************************************************************** @@ -1322,7 +1366,7 @@ NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutex2( D3DKMT_OPENKEYEDMUTEX2 *params ) if ((status = d3dkmt_object_alloc( sizeof(*mutex), D3DKMT_MUTEX, (void **)&mutex ))) return status;
runtime_size = params->PrivateRuntimeDataSize; - if ((status = d3dkmt_object_open( mutex, params->hSharedHandle, params->pPrivateRuntimeData, &runtime_size ))) goto failed; + if ((status = d3dkmt_object_open( mutex, params->hSharedHandle, NULL, params->pPrivateRuntimeData, &runtime_size ))) goto failed;
params->hKeyedMutex = mutex->local; return STATUS_SUCCESS; @@ -1355,8 +1399,22 @@ NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutex( D3DKMT_OPENKEYEDMUTEX *params ) */ NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutexFromNtHandle( D3DKMT_OPENKEYEDMUTEXFROMNTHANDLE *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 ((status = d3dkmt_object_alloc( sizeof(*mutex), D3DKMT_MUTEX, (void **)&mutex ))) return status; + if ((status = d3dkmt_object_open( mutex, 0, params->hNtHandle, params->pPrivateRuntimeData, + ¶ms->PrivateRuntimeDataSize ))) + goto failed; + + params->hKeyedMutex = mutex->local; + return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( mutex ); + return status; }
@@ -1422,8 +1480,26 @@ NTSTATUS WINAPI NtGdiDdDDICreateSynchronizationObject( D3DKMT_CREATESYNCHRONIZAT */ NTSTATUS WINAPI NtGdiDdDDIOpenSyncObjectFromNtHandle2( D3DKMT_OPENSYNCOBJECTFROMNTHANDLE2 *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *sync, *device; + NTSTATUS status; + UINT dummy = 0; + + 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 ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) return status; + if ((status = d3dkmt_object_open( sync, 0, params->hNtHandle, NULL, &dummy ))) goto failed; + + params->hSyncObject = sync->local; + params->MonitoredFence.FenceValueCPUVirtualAddress = 0; + params->MonitoredFence.FenceValueGPUVirtualAddress = 0; + return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( sync ); + return status; }
/****************************************************************************** @@ -1431,8 +1507,23 @@ NTSTATUS WINAPI NtGdiDdDDIOpenSyncObjectFromNtHandle2( D3DKMT_OPENSYNCOBJECTFROM */ NTSTATUS WINAPI NtGdiDdDDIOpenSyncObjectFromNtHandle( D3DKMT_OPENSYNCOBJECTFROMNTHANDLE *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + struct d3dkmt_object *sync; + NTSTATUS status; + UINT dummy = 0; + + FIXME( "params %p semi-stub!\n", params ); + + if (!params) return STATUS_INVALID_PARAMETER; + + if ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) return status; + if ((status = d3dkmt_object_open( sync, 0, params->hNtHandle, NULL, &dummy ))) goto failed; + + params->hSyncObject = sync->local; + return STATUS_SUCCESS; + +failed: + d3dkmt_object_free( sync ); + return status; }
/****************************************************************************** @@ -1459,7 +1550,7 @@ NTSTATUS WINAPI NtGdiDdDDIOpenSynchronizationObject( D3DKMT_OPENSYNCHRONIZATIONO if (!is_d3dkmt_global( params->hSharedHandle )) return STATUS_INVALID_PARAMETER;
if ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) return status; - if ((status = d3dkmt_object_open( sync, params->hSharedHandle, NULL, &dummy ))) goto failed; + if ((status = d3dkmt_object_open( sync, params->hSharedHandle, NULL, NULL, &dummy ))) goto failed;
params->hSyncObject = sync->local; return STATUS_SUCCESS; diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index ececd663449..4a7578f2588 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -2211,12 +2211,12 @@ static void test_D3DKMTShareObjects( void )
/* the sync object can be opened from the NT handle */ status = D3DKMTOpenSyncObjectFromNtHandle( &open_sync ); - todo_wine ok_nt( STATUS_INVALID_HANDLE, status ); + ok_nt( STATUS_INVALID_HANDLE, status ); open_sync.hNtHandle = handle; open_sync.hSyncObject = 0x1eadbeed; status = D3DKMTOpenSyncObjectFromNtHandle( &open_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open_sync.hSyncObject, NULL ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open_sync.hSyncObject, NULL );
/* objects opened with D3DKMTOpenSyncObjectFromNtHandle cannot be reshared */ InitializeObjectAttributes( &attr, &name, 0, 0, NULL ); @@ -2225,19 +2225,19 @@ static void test_D3DKMTShareObjects( void )
destroy_sync.hSyncObject = open_sync.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
status = D3DKMTOpenSyncObjectFromNtHandle2( &open_sync2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open_sync2.hNtHandle = open_sync.hNtHandle; status = D3DKMTOpenSyncObjectFromNtHandle2( &open_sync2 ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open_sync2.hDevice = create_device.hDevice; open_sync2.hSyncObject = 0x1eadbeed; status = D3DKMTOpenSyncObjectFromNtHandle2( &open_sync2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open_sync2.hSyncObject, NULL ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open_sync2.hSyncObject, NULL );
/* objects opened with Shared/NtSecuritySharing flags don't seem to matter */ ok_x4( open_sync2.Flags.Shared, ==, 0 ); @@ -2245,12 +2245,12 @@ static void test_D3DKMTShareObjects( void ) InitializeObjectAttributes( &attr, &name2, 0, 0, NULL ); handle = (HANDLE)0xdeadbeef; status = D3DKMTShareObjects( 1, &open_sync2.hSyncObject, &attr, STANDARD_RIGHTS_READ, &handle ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); CloseHandle( handle );
destroy_sync.hSyncObject = open_sync2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
status = D3DKMTOpenSyncObjectNtHandleFromName( &open_sync_name ); @@ -2272,7 +2272,7 @@ static void test_D3DKMTShareObjects( void ) CloseHandle( open_sync2.hNtHandle );
status = D3DKMTOpenSyncObjectFromNtHandle2( &open_sync2 ); - todo_wine ok_nt( STATUS_INVALID_HANDLE, status ); + ok_nt( STATUS_INVALID_HANDLE, status ); open_sync2.hNtHandle = open_sync_name.hNtHandle; open_sync2.hSyncObject = 0x1eadbeed; status = D3DKMTOpenSyncObjectFromNtHandle2( &open_sync2 ); @@ -2455,16 +2455,16 @@ static void test_D3DKMTShareObjects( void ) open_resource.pTotalPrivateDriverDataBuffer = driver_data; open_resource.TotalPrivateDriverDataBufferSize = query_resource.TotalPrivateDriverDataSize; status = D3DKMTOpenResourceFromNtHandle( &open_resource ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); ok_u4( open_resource.NumAllocations, ==, 1 ); - todo_wine ok_x4( open_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + ok_x4( open_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); ok_x4( open_resource.ResourcePrivateDriverDataSize, ==, 0 ); - ok_x4( open_resource.TotalPrivateDriverDataBufferSize, >, 0 ); - todo_wine ok_x4( open_resource.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); - todo_wine check_d3dkmt_local( open_resource.hResource, NULL ); - todo_wine ok_x4( open_resource.hKeyedMutex, ==, 0 ); + todo_wine ok_x4( open_resource.TotalPrivateDriverDataBufferSize, >, 0 ); + ok_x4( open_resource.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); + check_d3dkmt_local( open_resource.hResource, NULL ); + ok_x4( open_resource.hKeyedMutex, ==, 0 ); ok_x4( open_resource.KeyedMutexPrivateRuntimeDataSize, ==, 0 ); - todo_wine ok_x4( open_resource.hSyncObject, ==, 0 ); + ok_x4( open_resource.hSyncObject, ==, 0 ); todo_wine check_d3dkmt_local( open_alloc.hAllocation, NULL ); todo_wine ok_x4( open_alloc.PrivateDriverDataSize, >, 0 ); ok_x4( open_alloc.PrivateDriverDataSize, <, sizeof(alloc_data) ); @@ -2473,32 +2473,32 @@ static void test_D3DKMTShareObjects( void )
destroy_alloc.hResource = open_resource.hResource; status = D3DKMTDestroyAllocation( &destroy_alloc ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); open_resource.hResource = 0;
open_resource.pOpenAllocationInfo2 = NULL; status = D3DKMTOpenResourceFromNtHandle( &open_resource ); - todo_wine ok( status == STATUS_INVALID_PARAMETER || broken(status == STATUS_ACCESS_VIOLATION) /* win32 */, "got %#lx\n", status ); + ok( status == STATUS_INVALID_PARAMETER || broken(status == STATUS_ACCESS_VIOLATION) /* win32 */, "got %#lx\n", status ); open_resource.pOpenAllocationInfo2 = &open_alloc;
open_resource.NumAllocations = 0; status = D3DKMTOpenResourceFromNtHandle( &open_resource ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open_resource.NumAllocations = 1;
open_resource.pPrivateRuntimeData = NULL; status = D3DKMTOpenResourceFromNtHandle( &open_resource ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open_resource.pPrivateRuntimeData = runtime_data;
open_resource.PrivateRuntimeDataSize += 1; status = D3DKMTOpenResourceFromNtHandle( &open_resource ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open_resource.PrivateRuntimeDataSize = query_resource.PrivateRuntimeDataSize;
open_resource.pTotalPrivateDriverDataBuffer = NULL; status = D3DKMTOpenResourceFromNtHandle( &open_resource ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); open_resource.pTotalPrivateDriverDataBuffer = driver_data;
open_resource.TotalPrivateDriverDataBufferSize -= 1; @@ -2621,32 +2621,32 @@ static void test_D3DKMTShareObjects( void ) open_resource.pKeyedMutexPrivateRuntimeData = mutex_data; open_resource.KeyedMutexPrivateRuntimeDataSize = sizeof(expect_mutex_data); status = D3DKMTOpenResourceFromNtHandle( &open_resource ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); ok_u4( open_resource.NumAllocations, ==, 1 ); ok_x4( open_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); ok_x4( open_resource.ResourcePrivateDriverDataSize, ==, 0 ); todo_wine ok_x4( open_resource.TotalPrivateDriverDataBufferSize, >, 0 ); ok_x4( open_resource.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); - todo_wine check_d3dkmt_local( open_resource.hResource, NULL ); - todo_wine check_d3dkmt_local( open_resource.hKeyedMutex, NULL ); + check_d3dkmt_local( open_resource.hResource, NULL ); + check_d3dkmt_local( open_resource.hKeyedMutex, NULL ); ok_x4( open_resource.KeyedMutexPrivateRuntimeDataSize, ==, sizeof(expect_mutex_data) ); - todo_wine check_d3dkmt_local( open_resource.hSyncObject, NULL ); + check_d3dkmt_local( open_resource.hSyncObject, NULL ); todo_wine check_d3dkmt_local( open_alloc.hAllocation, NULL ); todo_wine ok_x4( open_alloc.PrivateDriverDataSize, >, 0 );
destroy_alloc.hResource = open_resource.hResource; status = D3DKMTDestroyAllocation( &destroy_alloc ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); open_resource.hResource = 0;
destroy_mutex.hKeyedMutex = open_resource.hKeyedMutex; status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); open_resource.hKeyedMutex = 0;
destroy_sync.hSyncObject = open_resource.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); open_resource.hSyncObject = 0;
memset( &open_resource, 0, sizeof(open_resource) ); diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c index 7b96e7d3a34..a03dd4e4990 100644 --- a/dlls/wow64win/gdi.c +++ b/dlls/wow64win/gdi.c @@ -1183,13 +1183,13 @@ NTSTATUS WINAPI wow64_NtGdiDdDDIOpenResourceFromNtHandle( UINT *args ) desc.hDevice = desc32->hDevice; desc.hNtHandle = UlongToHandle( desc32->hNtHandle ); desc.NumAllocations = desc32->NumAllocations; + allocs32 = UlongToPtr( desc32->pOpenAllocationInfo2 ); desc.pOpenAllocationInfo2 = NULL; if (desc32->pOpenAllocationInfo2 && desc32->NumAllocations) { if (!(desc.pOpenAllocationInfo2 = Wow64AllocateTemp( desc32->NumAllocations + sizeof(*desc.pOpenAllocationInfo2) ))) return STATUS_NO_MEMORY;
- allocs32 = UlongToPtr( desc32->pOpenAllocationInfo2 ); for (i = 0; i < desc32->NumAllocations; i++) { desc.pOpenAllocationInfo2[i].hAllocation = allocs32->hAllocation; @@ -1211,12 +1211,18 @@ NTSTATUS WINAPI wow64_NtGdiDdDDIOpenResourceFromNtHandle( UINT *args ) desc.hSyncObject = desc32->hSyncObject;
status = NtGdiDdDDIOpenResourceFromNtHandle( &desc ); + desc32->PrivateRuntimeDataSize = desc.PrivateRuntimeDataSize; + desc32->ResourcePrivateDriverDataSize = desc.ResourcePrivateDriverDataSize; desc32->TotalPrivateDriverDataBufferSize = desc.TotalPrivateDriverDataBufferSize; desc32->hResource = desc.hResource; desc32->hKeyedMutex = desc.hKeyedMutex; desc32->hSyncObject = desc.hSyncObject; for (i = 0; desc32->pOpenAllocationInfo2 && i < desc32->NumAllocations; i++) + { + allocs32->hAllocation = desc.pOpenAllocationInfo2[i].hAllocation; + allocs32->PrivateDriverDataSize = desc.pOpenAllocationInfo2[i].PrivateDriverDataSize; allocs32->GpuVirtualAddress = desc.pOpenAllocationInfo2[i].GpuVirtualAddress; + } return status; }
diff --git a/server/d3dkmt.c b/server/d3dkmt.c index ce81521a2ff..4cc4f3ad0bd 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -408,8 +408,8 @@ DECL_HANDLER(d3dkmt_object_open) struct d3dkmt_object *object; obj_handle_t handle;
- if (!req->global) return; - object = d3dkmt_object_open( req->global, req->type ); + if (req->global) object = d3dkmt_object_open( req->global, req->type ); + else object = d3dkmt_object_open_shared( req->handle, req->type ); if (!object) return;
/* only resource objects require exact runtime buffer size match */ diff --git a/server/protocol.def b/server/protocol.def index 036e35cdf68..29f05cf1273 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4173,10 +4173,11 @@ enum inproc_sync_type @END
-/* Open a global d3dkmt object */ +/* Open a global/shared d3dkmt object */ @REQ(d3dkmt_object_open) unsigned int type; /* d3dkmt object type */ d3dkmt_handle_t global; /* global d3dkmt handle */ + obj_handle_t handle; /* shared object handle */ @REPLY d3dkmt_handle_t global; /* global d3dkmt handle */ obj_handle_t handle; /* internal handle of the server object */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 64 +++++++++++++++++++++++++++++++++++--- dlls/win32u/tests/d3dkmt.c | 46 +++++++++++++-------------- server/d3dkmt.c | 21 +++++++++++++ server/protocol.def | 12 +++++++ 4 files changed, 116 insertions(+), 27 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 665a7b36175..3afdcabfcf8 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -407,6 +407,20 @@ static BOOL d3dkmt_use_vulkan(void) return !!d3dkmt_vk_instance; }
+static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *attr ) +{ + if (!attr || attr->Length != sizeof(*attr)) return STATUS_INVALID_PARAMETER; + + if (attr->ObjectName) + { + if ((ULONG_PTR)attr->ObjectName->Buffer & (sizeof(WCHAR) - 1)) return STATUS_DATATYPE_MISALIGNMENT; + if (attr->ObjectName->Length & (sizeof(WCHAR) - 1)) return STATUS_OBJECT_NAME_INVALID; + } + else if (attr->RootDirectory) return STATUS_OBJECT_NAME_INVALID; + + return STATUS_SUCCESS; +} + /****************************************************************************** * NtGdiDdDDIOpenAdapterFromHdc (win32u.@) */ @@ -1234,15 +1248,37 @@ failed: return status; }
+ /****************************************************************************** * NtGdiDdDDIOpenNtHandleFromName (win32u.@) */ NTSTATUS WINAPI NtGdiDdDDIOpenNtHandleFromName( D3DKMT_OPENNTHANDLEFROMNAME *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + OBJECT_ATTRIBUTES *attr = params->pObjAttrib; + DWORD access = params->dwDesiredAccess; + NTSTATUS status; + + TRACE( "params %p\n", params ); + + params->hNtHandle = 0; + if ((status = validate_open_object_attributes( attr ))) return status; + + SERVER_START_REQ( d3dkmt_object_open_name ) + { + req->type = D3DKMT_RESOURCE; + req->access = access; + req->attributes = attr->Attributes; + req->rootdir = wine_server_obj_handle( attr->RootDirectory ); + if (attr->ObjectName) wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length ); + status = wine_server_call( req ); + params->hNtHandle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + return status; }
+ /****************************************************************************** * NtGdiDdDDIQueryResourceInfo (win32u.@) */ @@ -1531,8 +1567,28 @@ failed: */ NTSTATUS WINAPI NtGdiDdDDIOpenSyncObjectNtHandleFromName( D3DKMT_OPENSYNCOBJECTNTHANDLEFROMNAME *params ) { - FIXME( "params %p stub!\n", params ); - return STATUS_NOT_IMPLEMENTED; + OBJECT_ATTRIBUTES *attr = params->pObjAttrib; + DWORD access = params->dwDesiredAccess; + NTSTATUS status; + + TRACE( "params %p\n", params ); + + params->hNtHandle = 0; + if ((status = validate_open_object_attributes( attr ))) return status; + + SERVER_START_REQ( d3dkmt_object_open_name ) + { + req->type = D3DKMT_SYNC; + req->access = access; + req->attributes = attr->Attributes; + req->rootdir = wine_server_obj_handle( attr->RootDirectory ); + if (attr->ObjectName) wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length ); + status = wine_server_call( req ); + params->hNtHandle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + return status; }
/****************************************************************************** diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 4a7578f2588..5385c25a9d0 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -2254,18 +2254,18 @@ static void test_D3DKMTShareObjects( void )
status = D3DKMTOpenSyncObjectNtHandleFromName( &open_sync_name ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); InitializeObjectAttributes( &attr, &name_invalid, 0, 0, NULL ); open_sync_name.pObjAttrib = &attr; status = D3DKMTOpenSyncObjectNtHandleFromName( &open_sync_name ); - todo_wine ok_nt( STATUS_OBJECT_NAME_NOT_FOUND, status ); + ok_nt( STATUS_OBJECT_NAME_NOT_FOUND, status ); InitializeObjectAttributes( &attr, &name_lower, 0, 0, NULL ); open_sync_name.pObjAttrib = &attr; status = D3DKMTOpenSyncObjectNtHandleFromName( &open_sync_name ); - todo_wine ok_nt( STATUS_ACCESS_DENIED, status ); + ok_nt( STATUS_ACCESS_DENIED, status ); open_sync_name.dwDesiredAccess = STANDARD_RIGHTS_WRITE; status = D3DKMTOpenSyncObjectNtHandleFromName( &open_sync_name ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); ok( !((UINT_PTR)open_sync_name.hNtHandle & 0xc0000000), "got %p\n", open_sync_name.hNtHandle );
@@ -2276,8 +2276,8 @@ static void test_D3DKMTShareObjects( void ) open_sync2.hNtHandle = open_sync_name.hNtHandle; open_sync2.hSyncObject = 0x1eadbeed; status = D3DKMTOpenSyncObjectFromNtHandle2( &open_sync2 ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine check_d3dkmt_local( open_sync2.hSyncObject, NULL ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open_sync2.hSyncObject, NULL );
CloseHandle( open_sync_name.hNtHandle );
@@ -2286,26 +2286,26 @@ static void test_D3DKMTShareObjects( void ) InitializeObjectAttributes( &attr, &name_lower, 0, 0, NULL ); open_sync_name.pObjAttrib = &attr; status = D3DKMTOpenSyncObjectNtHandleFromName( &open_sync_name ); - todo_wine ok_nt( STATUS_OBJECT_NAME_NOT_FOUND, status ); + ok_nt( STATUS_OBJECT_NAME_NOT_FOUND, status );
/* but object still exists and can be re-shared */ InitializeObjectAttributes( &attr, &name, 0, 0, NULL ); handle = (HANDLE)0xdeadbeef; status = D3DKMTShareObjects( 1, &open_sync2.hSyncObject, &attr, STANDARD_RIGHTS_READ, &handle ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* can be opened again by name */ open_sync_name.pObjAttrib = &attr; open_sync_name.dwDesiredAccess = STANDARD_RIGHTS_READ; status = D3DKMTOpenSyncObjectNtHandleFromName( &open_sync_name ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
CloseHandle( open_sync_name.hNtHandle ); CloseHandle( handle );
destroy_sync.hSyncObject = open_sync2.hSyncObject; status = D3DKMTDestroySynchronizationObject( &destroy_sync ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status );
/* D3DKMTShareObjects doesn't work with keyed mutex objects alone */ @@ -2403,18 +2403,18 @@ static void test_D3DKMTShareObjects( void )
status = D3DKMTOpenNtHandleFromName( &open_resource_name ); - todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + ok_nt( STATUS_INVALID_PARAMETER, status ); InitializeObjectAttributes( &attr, &name_invalid, 0, 0, NULL ); open_resource_name.pObjAttrib = &attr; status = D3DKMTOpenNtHandleFromName( &open_resource_name ); - todo_wine ok_nt( STATUS_OBJECT_NAME_NOT_FOUND, status ); + ok_nt( STATUS_OBJECT_NAME_NOT_FOUND, status ); InitializeObjectAttributes( &attr, &name_lower, 0, 0, NULL ); open_resource_name.pObjAttrib = &attr; status = D3DKMTOpenNtHandleFromName( &open_resource_name ); - todo_wine ok_nt( STATUS_ACCESS_DENIED, status ); + ok_nt( STATUS_ACCESS_DENIED, status ); open_resource_name.dwDesiredAccess = GENERIC_ALL; status = D3DKMTOpenNtHandleFromName( &open_resource_name ); - todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_nt( STATUS_SUCCESS, status ); ok( !((UINT_PTR)open_resource_name.hNtHandle & 0xc0000000), "got %p\n", open_resource_name.hNtHandle );
query_resource.hDevice = create_device.hDevice; @@ -2424,19 +2424,19 @@ static void test_D3DKMTShareObjects( void ) query_resource.ResourcePrivateDriverDataSize = 0xdeadbeef; query_resource.NumAllocations = 0xdeadbeef; status = D3DKMTQueryResourceInfoFromNtHandle( &query_resource ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( query_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); - ok_x4( query_resource.TotalPrivateDriverDataSize, >, 0 ); - todo_wine ok_x4( query_resource.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); - todo_wine ok_x4( query_resource.ResourcePrivateDriverDataSize, ==, 0 ); - todo_wine ok_u4( query_resource.NumAllocations, ==, 1 ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( query_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + todo_wine ok_x4( query_resource.TotalPrivateDriverDataSize, >, 0 ); + ok_x4( query_resource.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); + ok_x4( query_resource.ResourcePrivateDriverDataSize, ==, 0 ); + ok_u4( query_resource.NumAllocations, ==, 1 );
memset( runtime_data, 0xcd, sizeof(runtime_data) ); query_resource.pPrivateRuntimeData = runtime_data; query_resource.PrivateRuntimeDataSize = 0; /* sizeof(runtime_data); */ status = D3DKMTQueryResourceInfoFromNtHandle( &query_resource ); - todo_wine ok_nt( STATUS_SUCCESS, status ); - todo_wine ok_x4( query_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + ok_nt( STATUS_SUCCESS, status ); + ok_x4( query_resource.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); ok_u1( runtime_data[0], ==, 0xcd );
CloseHandle( open_resource_name.hNtHandle ); @@ -2468,7 +2468,7 @@ static void test_D3DKMTShareObjects( void ) todo_wine check_d3dkmt_local( open_alloc.hAllocation, NULL ); todo_wine ok_x4( open_alloc.PrivateDriverDataSize, >, 0 ); ok_x4( open_alloc.PrivateDriverDataSize, <, sizeof(alloc_data) ); - todo_wine ok( !memcmp( runtime_data, expect_runtime_data, sizeof(expect_runtime_data) ), "got data %#x\n", runtime_data[0] ); + ok( !memcmp( runtime_data, expect_runtime_data, sizeof(expect_runtime_data) ), "got data %#x\n", runtime_data[0] ); todo_wine ok_u1( driver_data[0], !=, 0xcd );
destroy_alloc.hResource = open_resource.hResource; diff --git a/server/d3dkmt.c b/server/d3dkmt.c index 4cc4f3ad0bd..8dba86df97d 100644 --- a/server/d3dkmt.c +++ b/server/d3dkmt.c @@ -470,3 +470,24 @@ done: if (mutex) release_object( mutex ); if (sync) release_object( sync ); } + +/* open a shared d3dkmt object from its name */ +DECL_HANDLER(d3dkmt_object_open_name) +{ + struct unicode_str name = get_req_unicode_str(); + + switch (req->type) + { + case D3DKMT_SYNC: + reply->handle = open_object( current->process, req->rootdir, req->access, &dxgk_shared_sync_ops, + &name, req->attributes | OBJ_CASE_INSENSITIVE ); + break; + case D3DKMT_RESOURCE: + reply->handle = open_object( current->process, req->rootdir, req->access, &dxgk_shared_resource_ops, + &name, req->attributes | OBJ_CASE_INSENSITIVE ); + break; + default: + set_error( STATUS_INVALID_PARAMETER ); + break; + } +} diff --git a/server/protocol.def b/server/protocol.def index 29f05cf1273..6013cbf8841 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4196,3 +4196,15 @@ enum inproc_sync_type @REPLY obj_handle_t handle; /* shared object handle */ @END + + +/* Open a shared d3dkmt object from a name */ +@REQ(d3dkmt_object_open_name) + unsigned int type; /* d3dkmt object type */ + unsigned int access; /* wanted access rights */ + unsigned int attributes; /* object attributes */ + obj_handle_t rootdir; /* root directory */ + VARARG(name,unicode_str); /* object name */ +@REPLY + obj_handle_t handle; /* shared object handle */ +@END