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 3f32b0aef4b..ae1206e45c9 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -935,8 +935,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; }
/****************************************************************************** @@ -944,8 +968,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; }
/****************************************************************************** @@ -989,6 +1028,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, };
/****************************************************************/