-- v5: win32u/tests: Test D3DKMT objects NT handle sharing. win32u/tests: Test D3DKMT allocation object creation. win32u/tests: Test D3DKMT keyed mutex object creation. win32u/tests: Test D3DKMT synchronization object creation. win32u: Stub NtGdiDdDDIOpenNtHandleFromName.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/gdi32/gdi32.spec | 1 + dlls/win32u/d3dkmt.c | 9 +++++++++ dlls/win32u/main.c | 5 +++++ dlls/win32u/win32syscalls.h | 5 ++--- dlls/win32u/win32u.spec | 2 +- dlls/wow64win/gdi.c | 19 +++++++++++++++++++ include/ddk/d3dkmthk.h | 8 ++++++++ include/ntgdi.h | 1 + 8 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec index 28dab037a74..ae097e607ba 100644 --- a/dlls/gdi32/gdi32.spec +++ b/dlls/gdi32/gdi32.spec @@ -126,6 +126,7 @@ @ stdcall D3DKMTOpenKeyedMutex(ptr) win32u.NtGdiDdDDIOpenKeyedMutex @ stdcall D3DKMTOpenKeyedMutex2(ptr) win32u.NtGdiDdDDIOpenKeyedMutex2 @ stdcall D3DKMTOpenKeyedMutexFromNtHandle(ptr) win32u.NtGdiDdDDIOpenKeyedMutexFromNtHandle +@ stdcall D3DKMTOpenNtHandleFromName(ptr) win32u.NtGdiDdDDIOpenNtHandleFromName @ stdcall D3DKMTOpenResource(ptr) win32u.NtGdiDdDDIOpenResource @ stdcall D3DKMTOpenResource2(ptr) win32u.NtGdiDdDDIOpenResource2 @ stdcall D3DKMTOpenResourceFromNtHandle(ptr) win32u.NtGdiDdDDIOpenResourceFromNtHandle diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index cdad56d1448..13f05f2d069 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -797,6 +797,15 @@ NTSTATUS WINAPI NtGdiDdDDIOpenResourceFromNtHandle( D3DKMT_OPENRESOURCEFROMNTHAN return STATUS_NOT_IMPLEMENTED; }
+/****************************************************************************** + * NtGdiDdDDIOpenNtHandleFromName (win32u.@) + */ +NTSTATUS WINAPI NtGdiDdDDIOpenNtHandleFromName( D3DKMT_OPENNTHANDLEFROMNAME *params ) +{ + FIXME( "params %p stub!\n", params ); + return STATUS_NOT_IMPLEMENTED; +} + /****************************************************************************** * NtGdiDdDDIQueryResourceInfo (win32u.@) */ diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c index 53b9d25143b..103c0d4ed9a 100644 --- a/dlls/win32u/main.c +++ b/dlls/win32u/main.c @@ -341,6 +341,11 @@ NTSTATUS SYSCALL_API NtGdiDdDDIOpenKeyedMutexFromNtHandle( D3DKMT_OPENKEYEDMUTEX SYSCALL_FUNC( NtGdiDdDDIOpenKeyedMutexFromNtHandle ); }
+NTSTATUS SYSCALL_API NtGdiDdDDIOpenNtHandleFromName( D3DKMT_OPENNTHANDLEFROMNAME *desc ) +{ + SYSCALL_FUNC( NtGdiDdDDIOpenNtHandleFromName ); +} + NTSTATUS SYSCALL_API NtGdiDdDDIOpenResource( D3DKMT_OPENRESOURCE *desc ) { SYSCALL_FUNC( NtGdiDdDDIOpenResource ); diff --git a/dlls/win32u/win32syscalls.h b/dlls/win32u/win32syscalls.h index 6fe9b47087c..f37eae3551b 100644 --- a/dlls/win32u/win32syscalls.h +++ b/dlls/win32u/win32syscalls.h @@ -307,7 +307,7 @@ SYSCALL_ENTRY( 0x112f, NtGdiDdDDIOpenKeyedMutex, 4 ) \ SYSCALL_ENTRY( 0x1130, NtGdiDdDDIOpenKeyedMutex2, 4 ) \ SYSCALL_ENTRY( 0x1131, NtGdiDdDDIOpenKeyedMutexFromNtHandle, 4 ) \ - SYSCALL_ENTRY( 0x1132, NtGdiDdDDIOpenNtHandleFromName, 0 ) \ + SYSCALL_ENTRY( 0x1132, NtGdiDdDDIOpenNtHandleFromName, 4 ) \ SYSCALL_ENTRY( 0x1133, NtGdiDdDDIOpenProtectedSessionFromNtHandle, 0 ) \ SYSCALL_ENTRY( 0x1134, NtGdiDdDDIOpenResource, 4 ) \ SYSCALL_ENTRY( 0x1135, NtGdiDdDDIOpenResource2, 4 ) \ @@ -1849,7 +1849,7 @@ SYSCALL_ENTRY( 0x112f, NtGdiDdDDIOpenKeyedMutex, 8 ) \ SYSCALL_ENTRY( 0x1130, NtGdiDdDDIOpenKeyedMutex2, 8 ) \ SYSCALL_ENTRY( 0x1131, NtGdiDdDDIOpenKeyedMutexFromNtHandle, 8 ) \ - SYSCALL_ENTRY( 0x1132, NtGdiDdDDIOpenNtHandleFromName, 0 ) \ + SYSCALL_ENTRY( 0x1132, NtGdiDdDDIOpenNtHandleFromName, 8 ) \ SYSCALL_ENTRY( 0x1133, NtGdiDdDDIOpenProtectedSessionFromNtHandle, 0 ) \ SYSCALL_ENTRY( 0x1134, NtGdiDdDDIOpenResource, 8 ) \ SYSCALL_ENTRY( 0x1135, NtGdiDdDDIOpenResource2, 8 ) \ @@ -3337,7 +3337,6 @@ SYSCALL_STUB( NtGdiDdDDINetDispStopMiracastDisplayDevice ) \ SYSCALL_STUB( NtGdiDdDDIOfferAllocations ) \ SYSCALL_STUB( NtGdiDdDDIOpenBundleObjectNtHandleFromName ) \ - SYSCALL_STUB( NtGdiDdDDIOpenNtHandleFromName ) \ SYSCALL_STUB( NtGdiDdDDIOpenProtectedSessionFromNtHandle ) \ SYSCALL_STUB( NtGdiDdDDIOpenSwapChain ) \ SYSCALL_STUB( NtGdiDdDDIOutputDuplGetFrameInfo ) \ diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index adc5f2f19b5..2273c1fbb4d 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -305,7 +305,7 @@ @ stdcall -syscall NtGdiDdDDIOpenKeyedMutex(ptr) @ stdcall -syscall NtGdiDdDDIOpenKeyedMutex2(ptr) @ stdcall -syscall NtGdiDdDDIOpenKeyedMutexFromNtHandle(ptr) -@ stub -syscall NtGdiDdDDIOpenNtHandleFromName +@ stdcall -syscall NtGdiDdDDIOpenNtHandleFromName(ptr) @ stub -syscall NtGdiDdDDIOpenProtectedSessionFromNtHandle @ stdcall -syscall NtGdiDdDDIOpenResource(ptr) @ stdcall -syscall NtGdiDdDDIOpenResource2(ptr) diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c index 8ec1e2e0d98..cec41199086 100644 --- a/dlls/wow64win/gdi.c +++ b/dlls/wow64win/gdi.c @@ -977,6 +977,25 @@ NTSTATUS WINAPI wow64_NtGdiDdDDIOpenKeyedMutexFromNtHandle( UINT *args ) return status; }
+NTSTATUS WINAPI wow64_NtGdiDdDDIOpenNtHandleFromName( UINT *args ) +{ + struct + { + DWORD dwDesiredAccess; + ULONG pObjAttrib; + ULONG hNtHandle; + } *desc32 = get_ptr( &args ); + D3DKMT_OPENNTHANDLEFROMNAME desc; + struct object_attr64 attr; + NTSTATUS status; + + desc.dwDesiredAccess = desc32->dwDesiredAccess; + desc.pObjAttrib = objattr_32to64( &attr, UlongToPtr( desc32->pObjAttrib ) ); + status = NtGdiDdDDIOpenNtHandleFromName( &desc ); + desc32->hNtHandle = HandleToUlong( desc.hNtHandle ); + return status; +} + NTSTATUS WINAPI wow64_NtGdiDdDDIOpenResource( UINT *args ) { struct diff --git a/include/ddk/d3dkmthk.h b/include/ddk/d3dkmthk.h index de12ef4a527..0cac5c7beaf 100644 --- a/include/ddk/d3dkmthk.h +++ b/include/ddk/d3dkmthk.h @@ -876,6 +876,13 @@ typedef struct _D3DKMT_OPENKEYEDMUTEXFROMNTHANDLE UINT PrivateRuntimeDataSize; } D3DKMT_OPENKEYEDMUTEXFROMNTHANDLE;
+typedef struct _D3DKMT_OPENNTHANDLEFROMNAME +{ + DWORD dwDesiredAccess; + OBJECT_ATTRIBUTES *pObjAttrib; + HANDLE hNtHandle; +} D3DKMT_OPENNTHANDLEFROMNAME; + typedef ULONGLONG D3DGPU_VIRTUAL_ADDRESS;
#ifndef D3DDDI_SYNCHRONIZATIONOBJECT_FLAGS_EXT @@ -1312,6 +1319,7 @@ NTSTATUS WINAPI D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID * desc ); NTSTATUS WINAPI D3DKMTOpenKeyedMutex( D3DKMT_OPENKEYEDMUTEX *params ); NTSTATUS WINAPI D3DKMTOpenKeyedMutex2( D3DKMT_OPENKEYEDMUTEX2 *params ); NTSTATUS WINAPI D3DKMTOpenKeyedMutexFromNtHandle( D3DKMT_OPENKEYEDMUTEXFROMNTHANDLE *params ); +NTSTATUS WINAPI D3DKMTOpenNtHandleFromName( D3DKMT_OPENNTHANDLEFROMNAME *params ); NTSTATUS WINAPI D3DKMTOpenResource( D3DKMT_OPENRESOURCE *params ); NTSTATUS WINAPI D3DKMTOpenResource2( D3DKMT_OPENRESOURCE *params ); NTSTATUS WINAPI D3DKMTOpenResourceFromNtHandle( D3DKMT_OPENRESOURCEFROMNTHANDLE *params ); diff --git a/include/ntgdi.h b/include/ntgdi.h index 81fa1eff14a..f073cf5ac61 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -540,6 +540,7 @@ W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUI W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutex( D3DKMT_OPENKEYEDMUTEX *params ); W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutex2( D3DKMT_OPENKEYEDMUTEX2 *params ); W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenKeyedMutexFromNtHandle( D3DKMT_OPENKEYEDMUTEXFROMNTHANDLE *params ); +W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenNtHandleFromName( D3DKMT_OPENNTHANDLEFROMNAME *params ); W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenResource( D3DKMT_OPENRESOURCE *params ); W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenResource2( D3DKMT_OPENRESOURCE *params ); W32KAPI NTSTATUS WINAPI NtGdiDdDDIOpenResourceFromNtHandle( D3DKMT_OPENRESOURCEFROMNTHANDLE *params );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/d3dkmt.c | 271 +++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+)
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 2f174da8841..001a9d85b98 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -41,6 +41,35 @@ static const WCHAR display1W[] = L"\\.\DISPLAY1";
DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
+static const char *debugstr_ok( const char *cond ) +{ + int c, n = 0; + /* skip possible casts */ + while ((c = *cond++)) + { + if (c == '(') n++; + if (!n) break; + if (c == ')') n--; + } + if (!strchr( cond - 1, '(' )) return wine_dbg_sprintf( "got %s", cond - 1 ); + return wine_dbg_sprintf( "%.*s returned", (int)strcspn( cond - 1, "( " ), cond - 1 ); +} + +#define ok_ex( r, op, e, t, f, ... ) \ + do \ + { \ + t v = (r); \ + ok( v op (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \ + } while (0) +#define ok_nt( e, r ) ok_ex( r, ==, e, NTSTATUS, "%#lx" ) + +#define check_d3dkmt_global( a ) check_d3dkmt_global_( __LINE__, a ) +static void check_d3dkmt_global_( int line, UINT_PTR handle ) +{ + ok_( __FILE__, line )( handle & 0xc0000000, "got %#Ix\n", handle ); + ok_( __FILE__, line )( (handle & 0x3f) == 2, "got %#Ix\n", handle ); +} + #define check_d3dkmt_local( a, b ) check_d3dkmt_local_( __LINE__, a, b ) static void check_d3dkmt_local_( int line, D3DKMT_HANDLE handle, D3DKMT_HANDLE *next_local ) { @@ -1116,6 +1145,247 @@ static void test_D3DKMTQueryAdapterInfo(void) ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); }
+static void test_D3DKMTCreateSynchronizationObject( void ) +{ + D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter = {0}; + D3DKMT_DESTROYSYNCHRONIZATIONOBJECT destroy = {0}; + D3DKMT_CREATESYNCHRONIZATIONOBJECT2 create2 = {0}; + D3DKMT_CREATESYNCHRONIZATIONOBJECT create = {0}; + D3DKMT_OPENSYNCHRONIZATIONOBJECT open = {0}; + D3DKMT_DESTROYDEVICE destroy_device = {0}; + D3DKMT_CREATEDEVICE create_device = {0}; + D3DKMT_CLOSEADAPTER close_adapter = {0}; + D3DKMT_HANDLE next_local = 0; + NTSTATUS status; + + wcscpy( open_adapter.DeviceName, L"\\.\DISPLAY1" ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open_adapter.hAdapter, &next_local ); + create_device.hAdapter = open_adapter.hAdapter; + status = D3DKMTCreateDevice( &create_device ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create_device.hDevice, &next_local ); + + /* D3DKMTCreateSynchronizationObject creates a local D3DKMT_HANDLE */ + status = D3DKMTCreateSynchronizationObject( NULL ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + status = D3DKMTCreateSynchronizationObject( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.hDevice = create_device.hDevice; + status = D3DKMTCreateSynchronizationObject( &create ); + todo_wine 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 ); + 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 ); + 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 ); + + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + /* destroying multiple times fails */ + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + destroy.hSyncObject = create.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine 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 ); + destroy.hSyncObject = create.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + create.Info.Type = D3DDDI_FENCE; + status = D3DKMTCreateSynchronizationObject( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + + /* D3DKMTCreateSynchronizationObject2 can create local D3DKMT_HANDLE */ + status = D3DKMTCreateSynchronizationObject2( NULL ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + status = D3DKMTCreateSynchronizationObject2( &create2 ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create2.hDevice = create_device.hDevice; + status = D3DKMTCreateSynchronizationObject2( &create2 ); + todo_wine 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 ); + 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 ); + + destroy.hSyncObject = create2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine 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 ); + destroy.hSyncObject = create2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine 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 ); + destroy.hSyncObject = create2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + create2.Info.Type = D3DDDI_CPU_NOTIFICATION; + status = D3DKMTCreateSynchronizationObject2( &create2 ); + todo_wine 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 ); + destroy.hSyncObject = create2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine 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 ); + } + + + 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 ); + 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 ); + + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine 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 ); + + + /* D3DKMTOpenSynchronizationObject creates a new local D3DKMT_HANDLE */ + open.hSharedHandle = 0x1eadbeed; + status = D3DKMTOpenSynchronizationObject( &open ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + open.hSharedHandle = 0; + status = D3DKMTOpenSynchronizationObject( &open ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + open.hSyncObject = create2.hSyncObject; + status = D3DKMTOpenSynchronizationObject( &open ); + todo_wine 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 ); + + destroy.hSyncObject = open.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + /* destroying multiple times fails */ + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine 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 ); + + destroy.hSyncObject = open.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + destroy.hSyncObject = create2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine 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 ); + + + /* NtSecuritySharing requires Shared, doesn't creates a global handle */ + create2.Info.Flags.Shared = 0; + create2.Info.Flags.NtSecuritySharing = 1; + status = D3DKMTCreateSynchronizationObject2( &create2 ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + if (broken( !status )) + { + check_d3dkmt_local( create2.hSyncObject, &next_local ); + destroy.hSyncObject = create2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + ok_nt( STATUS_SUCCESS, status ); + } + + create2.Info.Flags.Shared = 1; + 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( 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 ); + + + destroy_device.hDevice = create_device.hDevice; + status = D3DKMTDestroyDevice( &destroy_device ); + ok_nt( STATUS_SUCCESS, status ); + close_adapter.hAdapter = open_adapter.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter ); + ok_nt( STATUS_SUCCESS, status ); +} + START_TEST( d3dkmt ) { /* native win32u.dll fails if user32 is not loaded, so make sure it's fully initialized */ @@ -1134,4 +1404,5 @@ START_TEST( d3dkmt ) test_D3DKMTQueryAdapterInfo(); test_D3DKMTQueryVideoMemoryInfo(); test_gpu_device_properties(); + test_D3DKMTCreateSynchronizationObject(); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/d3dkmt.c | 174 +++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+)
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 001a9d85b98..dc6c7fbe914 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -61,6 +61,8 @@ static const char *debugstr_ok( const char *cond ) t v = (r); \ ok( v op (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \ } while (0) +#define ok_x4( r, op, e ) ok_ex( r, op, e, UINT, "%#x" ) +#define ok_u1( r, op, e ) ok_ex( r, op, e, unsigned char, "%u" ) #define ok_nt( e, r ) ok_ex( r, ==, e, NTSTATUS, "%#lx" )
#define check_d3dkmt_global( a ) check_d3dkmt_global_( __LINE__, a ) @@ -1386,6 +1388,177 @@ static void test_D3DKMTCreateSynchronizationObject( void ) ok_nt( STATUS_SUCCESS, status ); }
+static void test_D3DKMTCreateKeyedMutex( void ) +{ + D3DKMT_DESTROYKEYEDMUTEX destroy = {0}; + D3DKMT_CREATEKEYEDMUTEX2 create2 = {0}; + D3DKMT_CREATEKEYEDMUTEX create = {0}; + D3DKMT_OPENKEYEDMUTEX2 open2 = {0}; + D3DKMT_OPENKEYEDMUTEX open = {0}; + char runtime_data[] = {1, 2, 3, 4, 5, 6}, buffer[64]; + D3DKMT_HANDLE next_local = 0; + NTSTATUS status; + + status = D3DKMTCreateKeyedMutex( NULL ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.hKeyedMutex = create.hSharedHandle = 0x1eadbeed; + status = D3DKMTCreateKeyedMutex( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine check_d3dkmt_local( create.hKeyedMutex, &next_local ); + todo_wine check_d3dkmt_global( create.hSharedHandle ); + + status = D3DKMTOpenKeyedMutex( &open ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + open.hKeyedMutex = create.hKeyedMutex; + status = D3DKMTOpenKeyedMutex( &open ); + todo_wine 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 ); + + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + if (0) + { + /* 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 ); + } + + destroy.hKeyedMutex = open.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + /* destroying multiple times fails */ + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + destroy.hKeyedMutex = create.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + /* the global D3DKMT_HANDLE is destroyed with last reference */ + status = D3DKMTOpenKeyedMutex( &open ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + + status = D3DKMTCreateKeyedMutex2( NULL ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create2.hKeyedMutex = create2.hSharedHandle = 0x1eadbeed; + status = D3DKMTCreateKeyedMutex2( &create2 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + todo_wine check_d3dkmt_global( create2.hSharedHandle ); + destroy.hKeyedMutex = create2.hKeyedMutex; + + create2.hKeyedMutex = create2.hSharedHandle = 0x1eadbeed; + status = D3DKMTCreateKeyedMutex2( &create2 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + todo_wine check_d3dkmt_global( create2.hSharedHandle ); + + status = D3DKMTOpenKeyedMutex2( &open2 ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + open2.hKeyedMutex = create2.hKeyedMutex; + status = D3DKMTOpenKeyedMutex2( &open2 ); + todo_wine 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 ); + + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + destroy.hKeyedMutex = create2.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + destroy.hKeyedMutex = open2.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + /* PrivateRuntimeDataSize must be 0 if no buffer is provided */ + + status = D3DKMTCreateKeyedMutex2( &create2 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + todo_wine check_d3dkmt_global( create2.hSharedHandle ); + + open2.hKeyedMutex = 0x1eadbeed; + open2.hSharedHandle = create2.hSharedHandle; + open2.PrivateRuntimeDataSize = sizeof(buffer); + status = D3DKMTOpenKeyedMutex2( &open2 ); + todo_wine 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 ); + ok_x4( open2.PrivateRuntimeDataSize, ==, sizeof(buffer) ); + + destroy.hKeyedMutex = open2.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + destroy.hKeyedMutex = create2.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + create2.PrivateRuntimeDataSize = sizeof(runtime_data); + create2.pPrivateRuntimeData = runtime_data; + status = D3DKMTCreateKeyedMutex2( &create2 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + todo_wine check_d3dkmt_global( create2.hSharedHandle ); + + open2.hKeyedMutex = 0x1eadbeed; + open2.hSharedHandle = create2.hSharedHandle; + 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 ); + ok_x4( open2.PrivateRuntimeDataSize, ==, 0 ); + + open2.PrivateRuntimeDataSize = sizeof(buffer); + status = D3DKMTOpenKeyedMutex2( &open2 ); + todo_wine 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 ); + 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 ); + ok_x4( open2.PrivateRuntimeDataSize, ==, sizeof(runtime_data) ); + ok_u1( buffer[0], ==, 0xcd ); + + destroy.hKeyedMutex = open2.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + destroy.hKeyedMutex = create2.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + /* doesn't return a global D3DKMT_HANDLE with NtSecuritySharing = 1 */ + create2.Flags.NtSecuritySharing = 1; + create2.hKeyedMutex = create2.hSharedHandle = 0x1eadbeed; + status = D3DKMTCreateKeyedMutex2( &create2 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine check_d3dkmt_local( create2.hKeyedMutex, &next_local ); + todo_wine ok_x4( create2.hSharedHandle, ==, 0 ); + + destroy.hKeyedMutex = create2.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); +} + START_TEST( d3dkmt ) { /* native win32u.dll fails if user32 is not loaded, so make sure it's fully initialized */ @@ -1405,4 +1578,5 @@ START_TEST( d3dkmt ) test_D3DKMTQueryVideoMemoryInfo(); test_gpu_device_properties(); test_D3DKMTCreateSynchronizationObject(); + test_D3DKMTCreateKeyedMutex(); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/d3dkmt.c | 436 +++++++++++++++++++++++++++++++++++++ 1 file changed, 436 insertions(+)
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index dc6c7fbe914..14a2d33e5d8 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -61,8 +61,10 @@ static const char *debugstr_ok( const char *cond ) t v = (r); \ ok( v op (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \ } while (0) +#define ok_u4( r, op, e ) ok_ex( r, op, e, UINT, "%u" ) #define ok_x4( r, op, e ) ok_ex( r, op, e, UINT, "%#x" ) #define ok_u1( r, op, e ) ok_ex( r, op, e, unsigned char, "%u" ) +#define ok_ptr( r, op, e ) ok_ex( r, op, e, const void *, "%p" ) #define ok_nt( e, r ) ok_ex( r, ==, e, NTSTATUS, "%#lx" )
#define check_d3dkmt_global( a ) check_d3dkmt_global_( __LINE__, a ) @@ -1559,6 +1561,439 @@ static void test_D3DKMTCreateKeyedMutex( void ) todo_wine ok_nt( STATUS_SUCCESS, status ); }
+static void test_D3DKMTCreateAllocation( void ) +{ + OBJECT_ATTRIBUTES attr = {.Length = sizeof(attr)}; + D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter = {0}; + D3DKMT_CREATESTANDARDALLOCATION standard[2] = {0}; + D3DDDI_OPENALLOCATIONINFO2 open_alloc2 = {0}; + D3DDDI_OPENALLOCATIONINFO open_alloc = {0}; + D3DKMT_DESTROYDEVICE destroy_device = {0}; + D3DKMT_DESTROYALLOCATION2 destroy2 = {0}; + D3DKMT_CREATEDEVICE create_device = {0}; + D3DKMT_CLOSEADAPTER close_adapter = {0}; + D3DDDI_ALLOCATIONINFO2 allocs2[2] = {0}; + D3DKMT_DESTROYALLOCATION destroy = {0}; + D3DDDI_ALLOCATIONINFO allocs[2] = {0}; + D3DKMT_CREATEALLOCATION create = {0}; + D3DKMT_QUERYRESOURCEINFO query = {0}; + D3DKMT_OPENRESOURCE open = {0}; + const char expect_alloc_data[] = {1, 2, 3, 4, 5, 6}; + const char expect_runtime_data[] = {7, 8, 9, 10}; + char driver_data[0x1000], resource_data[0x100], runtime_data[0x100]; + char alloc_data[0x400], alloc2_data[0x400]; + D3DKMT_HANDLE next_local = 0; + NTSTATUS status; + + /* static NTSTATUS (WINAPI *D3DKMTOpenResourceFromNtHandle)( D3DKMT_OPENRESOURCEFROMNTHANDLE *params ); */ + /* static NTSTATUS (WINAPI *D3DKMTQueryResourceInfoFromNtHandle)( D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE *params ); */ + + if (0) /* crashes */ + status = D3DKMTCreateAllocation( NULL ); + + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + wcscpy( open_adapter.DeviceName, L"\\.\DISPLAY1" ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open_adapter.hAdapter, &next_local ); + create_device.hAdapter = open_adapter.hAdapter; + status = D3DKMTCreateDevice( &create_device ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create_device.hDevice, &next_local ); + + + allocs[0].pSystemMem = allocs2[0].pSystemMem = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE ); + allocs[1].pSystemMem = allocs2[1].pSystemMem = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE ); + standard[0].Type = D3DKMT_STANDARDALLOCATIONTYPE_EXISTINGHEAP; + standard[0].ExistingHeapData.Size = 0x10000; + standard[1].Type = D3DKMT_STANDARDALLOCATIONTYPE_EXISTINGHEAP; + standard[1].ExistingHeapData.Size = 0x10000; + + + create.hDevice = create_device.hDevice; + create.Flags.ExistingSysMem = 1; + create.Flags.StandardAllocation = 1; + create.pStandardAllocation = standard; + create.NumAllocations = 1; + create.pAllocationInfo = allocs; + allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; + create.hPrivateRuntimeResourceHandle = (HANDLE)0xdeadbeef; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_x4( create.hResource, ==, 0 ); + todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + ok_ptr( create.hPrivateRuntimeResourceHandle, ==, (HANDLE)0xdeadbeef ); + + destroy.hDevice = create_device.hDevice; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + destroy.AllocationCount = 1; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + destroy.phAllocationList = &allocs[0].hAllocation; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + /* allocation has already been destroyed */ + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + + /* D3DKMTCreateAllocation2 also works with the same parameters, with extra alloc info */ + create.pAllocationInfo2 = allocs2; + allocs2[0].hAllocation = create.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation2( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_x4( create.hResource, ==, 0 ); + todo_wine check_d3dkmt_local( allocs2[0].hAllocation, &next_local ); + ok_x4( create.PrivateRuntimeDataSize, ==, 0 ); + ok_x4( create.PrivateDriverDataSize, ==, 0 ); + ok_x4( allocs2[0].PrivateDriverDataSize, ==, 0 ); + create.pAllocationInfo = allocs; + + destroy.phAllocationList = &allocs2[0].hAllocation; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + destroy.phAllocationList = &allocs[0].hAllocation; + + + /* D3DKMTDestroyAllocation2 works as well */ + allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_x4( create.hResource, ==, 0 ); + todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + + destroy2.hDevice = create_device.hDevice; + destroy2.AllocationCount = 1; + destroy2.phAllocationList = &allocs[0].hAllocation; + status = D3DKMTDestroyAllocation2( &destroy2 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + /* alloc PrivateDriverDataSize can be set */ + allocs[0].pPrivateDriverData = (char *)expect_alloc_data; + allocs[0].PrivateDriverDataSize = sizeof(expect_alloc_data); + allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_x4( create.hResource, ==, 0 ); + todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + /* PrivateRuntimeDataSize can be set */ + create.pPrivateRuntimeData = expect_runtime_data; + create.PrivateRuntimeDataSize = sizeof(expect_runtime_data); + allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + ok_x4( create.hResource, ==, 0 ); + todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + /* PrivateDriverDataSize must be 0 for standard allocations */ + create.PrivateDriverDataSize = 64; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.PrivateDriverDataSize = 0; + + /* device handle is required */ + create.hDevice = 0; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.hDevice = create_device.hDevice; + + /* hResource must be valid or 0 */ + create.hResource = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_HANDLE, status ); + create.hResource = 0; + + /* NumAllocations is required */ + create.NumAllocations = 0; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.NumAllocations = 1; + + /* standard.Type must be set */ + standard[0].Type = 0; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + standard[0].Type = D3DKMT_STANDARDALLOCATIONTYPE_EXISTINGHEAP; + + /* pSystemMem must be set */ + allocs[0].pSystemMem = 0; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + allocs[0].pSystemMem = allocs2[0].pSystemMem; + + /* creating multiple allocations doesn't work */ + create.NumAllocations = 2; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.NumAllocations = 1; + + /* ExistingHeapData.Size must be page aligned */ + standard[0].ExistingHeapData.Size = 0x1100; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + standard[0].ExistingHeapData.Size = 0x10000; + + /* specific flags are required for standard allocations */ + create.Flags.ExistingSysMem = 0; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.Flags.ExistingSysMem = 1; + create.Flags.StandardAllocation = 0; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.Flags.StandardAllocation = 1; + + /* CreateShared doesn't work without CreateResource */ + create.Flags.CreateShared = 1; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.Flags.CreateShared = 0; + + + /* test creating a resource with the allocations */ + create.Flags.CreateResource = 1; + allocs[0].hAllocation = create.hGlobalShare = create.hResource = 0x1eadbeed; + create.hPrivateRuntimeResourceHandle = (HANDLE)0xdeadbeef; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_HANDLE, status ); + create.hResource = 0; /* hResource must be set to 0, even with CreateResource */ + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + todo_wine check_d3dkmt_local( create.hResource, &next_local ); + todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + ok_ptr( create.hPrivateRuntimeResourceHandle, ==, (HANDLE)0xdeadbeef ); + + /* destroying the allocation doesn't destroys the resource */ + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + destroy.hResource = create.hResource; + destroy.AllocationCount = 0; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + destroy.AllocationCount = 1; + create.hResource = 0; + + + create.Flags.CreateResource = 1; + allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + todo_wine check_d3dkmt_local( create.hResource, &next_local ); + todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + + /* cannot create allocations with an existing resource */ + create.Flags.CreateResource = 0; + create.pAllocationInfo = &allocs[1]; + allocs[1].hAllocation = create.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.pAllocationInfo = &allocs[0]; + + /* destroying resource destroys its allocations */ + destroy.hResource = create.hResource; + destroy.AllocationCount = 0; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + destroy.hResource = 0; + destroy.AllocationCount = 1; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.hResource = 0; + + + /* cannot create a resource without allocations */ + create.Flags.CreateResource = 1; + create.NumAllocations = 0; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + create.NumAllocations = 1; + + /* destroy resource at once from here */ + destroy.AllocationCount = 0; + + + allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + todo_wine check_d3dkmt_local( create.hResource, &next_local ); + todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + + /* D3DKMTQueryResourceInfo requires a global handle */ + query.hDevice = create_device.hDevice; + query.hGlobalShare = create.hResource; + status = D3DKMTQueryResourceInfo( &query ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + /* D3DKMTOpenResource requires a global handle */ + open.hDevice = create_device.hDevice; + open.hGlobalShare = create.hResource; + status = D3DKMTOpenResource( &open ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + destroy.hResource = create.hResource; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + create.hResource = 0; + + + /* test creating global shared resource */ + create.Flags.CreateShared = 1; + allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine check_d3dkmt_global( create.hGlobalShare ); + todo_wine check_d3dkmt_local( create.hResource, &next_local ); + todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + + /* D3DKMTQueryResourceInfo works with global handle */ + memset( runtime_data, 0xcd, sizeof(runtime_data) ); + query.hDevice = create_device.hDevice; + query.hGlobalShare = create.hGlobalShare; + query.pPrivateRuntimeData = runtime_data; + query.PrivateRuntimeDataSize = sizeof(runtime_data); + status = D3DKMTQueryResourceInfo( &query ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( query.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + todo_wine ok_x4( query.TotalPrivateDriverDataSize, >, 0 ); + ok_x4( query.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); + ok_x4( query.ResourcePrivateDriverDataSize, ==, 0 ); + todo_wine ok_u4( query.NumAllocations, ==, 1 ); + /* runtime data doesn't get updated ? */ + ok_u1( runtime_data[0], ==, 0xcd ); + + /* D3DKMTOpenResource works with a global handle */ + memset( runtime_data, 0xcd, sizeof(runtime_data) ); + memset( driver_data, 0xcd, sizeof(driver_data) ); + memset( resource_data, 0xcd, sizeof(resource_data) ); + memset( alloc_data, 0xcd, sizeof(alloc_data) ); + open.hDevice = create_device.hDevice; + open.hGlobalShare = create.hGlobalShare; + open.pPrivateRuntimeData = runtime_data; + open.PrivateRuntimeDataSize = query.PrivateRuntimeDataSize; + open.pTotalPrivateDriverDataBuffer = driver_data; + open.TotalPrivateDriverDataBufferSize = sizeof(driver_data); + open.pResourcePrivateDriverData = resource_data; + open.ResourcePrivateDriverDataSize = query.ResourcePrivateDriverDataSize; + open.NumAllocations = 1; + open.pOpenAllocationInfo = &open_alloc; + open_alloc.pPrivateDriverData = alloc_data; + open_alloc.PrivateDriverDataSize = sizeof(alloc_data); + open.hResource = 0x1eadbeed; + status = D3DKMTOpenResource( &open ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_x4( open.hGlobalShare, ==, create.hGlobalShare ); + todo_wine check_d3dkmt_local( open.hResource, &next_local ); + todo_wine ok_x4( open.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + ok_x4( open.TotalPrivateDriverDataBufferSize, >, 0 ); + todo_wine 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] ); + 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 ); + open.hResource = 0; + + /* NumAllocations must be set */ + open.NumAllocations = 0; + status = D3DKMTOpenResource( &open ); + todo_wine 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 ); + open.PrivateRuntimeDataSize -= 1; + open.ResourcePrivateDriverDataSize += 1; + status = D3DKMTOpenResource( &open ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + open.ResourcePrivateDriverDataSize -= 1; + + /* D3DKMTOpenResource2 works as well */ + open.pOpenAllocationInfo2 = &open_alloc2; + open_alloc2.pPrivateDriverData = alloc2_data; + open_alloc2.PrivateDriverDataSize = sizeof(alloc2_data); + open_alloc2.hAllocation = 0x1eadbeed; + status = D3DKMTOpenResource2( &open ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + ok_x4( open.hGlobalShare, ==, create.hGlobalShare ); + todo_wine check_d3dkmt_local( open.hResource, &next_local ); + todo_wine ok_x4( open.PrivateRuntimeDataSize, ==, sizeof(expect_runtime_data) ); + ok_x4( open.TotalPrivateDriverDataBufferSize, >, 0 ); + todo_wine 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 ); + ok_x4( open_alloc2.PrivateDriverDataSize, >, 0 ); + todo_wine ok_x4( open_alloc2.PrivateDriverDataSize, <, sizeof(alloc_data) ); + open.pOpenAllocationInfo = &open_alloc; + + destroy.hResource = open.hResource; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + open.hResource = 0; + + destroy.hResource = create.hResource; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + create.hResource = 0; + + + /* test creating nt shared resource */ + create.Flags.NtSecuritySharing = 1; + create.Flags.CreateShared = 1; + allocs[0].hAllocation = create.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create.hGlobalShare, ==, 0 ); + todo_wine check_d3dkmt_local( create.hResource, &next_local ); + todo_wine check_d3dkmt_local( allocs[0].hAllocation, &next_local ); + + destroy.hResource = create.hResource; + status = D3DKMTDestroyAllocation( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + create.hResource = 0; + + + VirtualFree( (void *)allocs[0].pSystemMem, 0, MEM_RELEASE ); + VirtualFree( (void *)allocs[1].pSystemMem, 0, MEM_RELEASE ); + + + destroy_device.hDevice = create_device.hDevice; + D3DKMTDestroyDevice( &destroy_device ); + close_adapter.hAdapter = open_adapter.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter ); + ok_nt( STATUS_SUCCESS, status ); +} + START_TEST( d3dkmt ) { /* native win32u.dll fails if user32 is not loaded, so make sure it's fully initialized */ @@ -1579,4 +2014,5 @@ START_TEST( d3dkmt ) test_gpu_device_properties(); test_D3DKMTCreateSynchronizationObject(); test_D3DKMTCreateKeyedMutex(); + test_D3DKMTCreateAllocation(); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/d3dkmt.c | 610 +++++++++++++++++++++++++++++++++++++ 1 file changed, 610 insertions(+)
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 14a2d33e5d8..ac1146b8870 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -83,6 +83,50 @@ static void check_d3dkmt_local_( int line, D3DKMT_HANDLE handle, D3DKMT_HANDLE * if (next_local) *next_local = handle + 0x40; }
+static BOOL compare_unicode_string( const UNICODE_STRING *string, const WCHAR *expect ) +{ + return string->Length == wcslen( expect ) * sizeof(WCHAR) && + !wcsnicmp( string->Buffer, expect, string->Length / sizeof(WCHAR) ); +} + +#define check_object_type( a, b ) _check_object_type( __LINE__, a, b ) +static void _check_object_type( unsigned line, HANDLE handle, const WCHAR *expected_name ) +{ + char buffer[1024]; + OBJECT_TYPE_INFORMATION *type = (OBJECT_TYPE_INFORMATION *)buffer; + UNICODE_STRING expect; + ULONG len = 0; + NTSTATUS status; + + RtlInitUnicodeString( &expect, expected_name ); + + memset( buffer, 0, sizeof(buffer) ); + status = NtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len ); + ok_(__FILE__, line)( status == STATUS_SUCCESS, "NtQueryObject failed %lx\n", status ); + ok_(__FILE__, line)( len > sizeof(UNICODE_STRING), "unexpected len %lu\n", len ); + ok_(__FILE__, line)( len >= sizeof(*type) + type->TypeName.Length, "unexpected len %lu\n", len ); + ok_(__FILE__, line)( compare_unicode_string( &type->TypeName, expected_name ), + "wrong name %s\n", debugstr_w( type->TypeName.Buffer ) ); +} + +#define check_object_name( a, b ) _check_object_name( __LINE__, a, b ) +static void _check_object_name( unsigned line, HANDLE handle, const WCHAR *expected_name ) +{ + char buffer[1024]; + UNICODE_STRING *str = (UNICODE_STRING *)buffer, expect; + ULONG len = 0; + NTSTATUS status; + + RtlInitUnicodeString( &expect, expected_name ); + + memset( buffer, 0, sizeof(buffer) ); + status = NtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len ); + ok_(__FILE__, line)( status == STATUS_SUCCESS, "NtQueryObject failed %lx\n", status ); + ok_(__FILE__, line)( len >= sizeof(OBJECT_NAME_INFORMATION) + str->Length, "unexpected len %lu\n", len ); + ok_(__FILE__, line)( compare_unicode_string( str, expected_name ), "got %s, expected %s\n", + debugstr_w(str->Buffer), debugstr_w(expected_name) ); +} + static BOOL get_primary_adapter_name( WCHAR *name ) { DISPLAY_DEVICEW dd; @@ -1994,6 +2038,571 @@ static void test_D3DKMTCreateAllocation( void ) ok_nt( STATUS_SUCCESS, status ); }
+static void test_D3DKMTShareObjects( void ) +{ + OBJECT_ATTRIBUTES attr = {.Length = sizeof(attr)}; + UNICODE_STRING name = RTL_CONSTANT_STRING( L"\BaseNamedObjects\__WineTest_D3DKMT" ); + UNICODE_STRING name2 = RTL_CONSTANT_STRING( L"\BaseNamedObjects\__WineTest_D3DKMT_2" ); + UNICODE_STRING name_lower = RTL_CONSTANT_STRING( L"\BaseNamedObjects\__winetest_d3dkmt" ); + UNICODE_STRING name_invalid = RTL_CONSTANT_STRING( L"\BaseNamedObjects\__winetest_invalid" ); + D3DKMT_OPENSYNCOBJECTNTHANDLEFROMNAME open_sync_name = {0}; + D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter = {0}; + D3DKMT_CREATESYNCHRONIZATIONOBJECT2 create_sync2 = {0}; + D3DKMT_DESTROYSYNCHRONIZATIONOBJECT destroy_sync = {0}; + D3DKMT_CREATESYNCHRONIZATIONOBJECT create_sync = {0}; + D3DKMT_OPENNTHANDLEFROMNAME open_resource_name = {0}; + D3DKMT_OPENSYNCOBJECTFROMNTHANDLE2 open_sync2 = {0}; + D3DKMT_OPENSYNCOBJECTFROMNTHANDLE open_sync = {0}; + D3DKMT_DESTROYKEYEDMUTEX destroy_mutex = {0}; + D3DKMT_CREATEKEYEDMUTEX2 create_mutex2 = {0}; + D3DKMT_CREATEKEYEDMUTEX create_mutex = {0}; + D3DKMT_DESTROYDEVICE destroy_device = {0}; + D3DKMT_CREATEDEVICE create_device = {0}; + D3DKMT_CLOSEADAPTER close_adapter = {0}; + + D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE query_resource = {0}; + D3DKMT_OPENRESOURCEFROMNTHANDLE open_resource = {0}; + D3DKMT_CREATESTANDARDALLOCATION standard = {0}; + D3DKMT_DESTROYALLOCATION destroy_alloc = {0}; + D3DDDI_OPENALLOCATIONINFO2 open_alloc = {0}; + D3DKMT_CREATEALLOCATION create_alloc = {0}; + D3DDDI_ALLOCATIONINFO alloc = {0}; + char expect_runtime_data[] = {9, 8, 7, 6}; + char expect_mutex_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + char expect_alloc_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + char driver_data[0x1000], runtime_data[0x100]; + char alloc_data[0x400], mutex_data[0x100]; + D3DKMT_HANDLE objects[4], next_local = 0; + + NTSTATUS status; + HANDLE handle; + + wcscpy( open_adapter.DeviceName, L"\\.\DISPLAY1" ); + status = D3DKMTOpenAdapterFromGdiDisplayName( &open_adapter ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( open_adapter.hAdapter, &next_local ); + create_device.hAdapter = open_adapter.hAdapter; + status = D3DKMTCreateDevice( &create_device ); + ok_nt( STATUS_SUCCESS, status ); + check_d3dkmt_local( create_device.hDevice, &next_local ); + + + /* D3DKMTShareObjects doesn't work with D3DKMTCreateSynchronizationObject created objects */ + create_sync.hDevice = create_device.hDevice; + create_sync.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; + create_sync.hSyncObject = 0x1eadbeed; + status = D3DKMTCreateSynchronizationObject( &create_sync ); + todo_wine 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 ); + + /* 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 ); + 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 ); + + create_sync2.Info.Flags.Shared = 1; + status = D3DKMTCreateSynchronizationObject2( &create_sync2 ); + todo_wine 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 ); + + /* D3DKMTShareObjects requires NtSecuritySharing (which requires Shared = 1) */ + create_sync2.Info.Flags.NtSecuritySharing = 1; + status = D3DKMTCreateSynchronizationObject2( &create_sync2 ); + todo_wine 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 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + /* handle isn't a D3DKMT_HANDLE */ + todo_wine 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 ); + + /* cannot destroy the handle */ + destroy_sync.hSyncObject = (UINT_PTR)handle; + status = D3DKMTDestroySynchronizationObject( &destroy_sync ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + destroy_sync.hSyncObject = create_sync2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy_sync ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + /* the sync object can be opened from the NT handle */ + status = D3DKMTOpenSyncObjectFromNtHandle( &open_sync ); + todo_wine 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 ); + + /* 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 ); + + destroy_sync.hSyncObject = open_sync.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy_sync ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + status = D3DKMTOpenSyncObjectFromNtHandle2( &open_sync2 ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + open_sync2.hNtHandle = open_sync.hNtHandle; + status = D3DKMTOpenSyncObjectFromNtHandle2( &open_sync2 ); + todo_wine 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 ); + + /* objects opened with Shared/NtSecuritySharing flags don't seem to matter */ + ok_x4( open_sync2.Flags.Shared, ==, 0 ); + ok_x4( open_sync2.Flags.NtSecuritySharing, ==, 0 ); + 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 ); + CloseHandle( handle ); + + destroy_sync.hSyncObject = open_sync2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy_sync ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + status = D3DKMTOpenSyncObjectNtHandleFromName( &open_sync_name ); + todo_wine 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 ); + 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 ); + open_sync_name.dwDesiredAccess = STANDARD_RIGHTS_WRITE; + status = D3DKMTOpenSyncObjectNtHandleFromName( &open_sync_name ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + ok( !((UINT_PTR)open_sync_name.hNtHandle & 0xc0000000), "got %p\n", open_sync_name.hNtHandle ); + + + CloseHandle( open_sync2.hNtHandle ); + + status = D3DKMTOpenSyncObjectFromNtHandle2( &open_sync2 ); + todo_wine ok_nt( STATUS_INVALID_HANDLE, status ); + 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 ); + + CloseHandle( open_sync_name.hNtHandle ); + + + /* cannot open the object anymore after all the NT handles have been closed */ + 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 ); + + /* 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 ); + + /* 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 ); + + CloseHandle( open_sync_name.hNtHandle ); + CloseHandle( handle ); + + destroy_sync.hSyncObject = open_sync2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy_sync ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + /* D3DKMTShareObjects doesn't work with keyed mutex objects alone */ + status = D3DKMTCreateKeyedMutex( &create_mutex ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + status = D3DKMTShareObjects( 1, &create_mutex.hKeyedMutex, &attr, STANDARD_RIGHTS_WRITE, &handle ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + status = D3DKMTShareObjects( 1, &create_mutex.hSharedHandle, &attr, STANDARD_RIGHTS_WRITE, &handle ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + destroy_mutex.hKeyedMutex = create_mutex.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + create_mutex2.Flags.NtSecuritySharing = 1; + status = D3DKMTCreateKeyedMutex2( &create_mutex2 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + status = D3DKMTShareObjects( 1, &create_mutex2.hKeyedMutex, &attr, STANDARD_RIGHTS_WRITE, &handle ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + destroy_mutex.hKeyedMutex = create_mutex2.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + + /* NtSecuritySharing = 1 is required for D3DKMTShareObjects */ + + alloc.pSystemMem = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE ); + standard.Type = D3DKMT_STANDARDALLOCATIONTYPE_EXISTINGHEAP; + standard.ExistingHeapData.Size = 0x10000; + create_alloc.hDevice = create_device.hDevice; + create_alloc.Flags.ExistingSysMem = 1; + create_alloc.Flags.StandardAllocation = 1; + create_alloc.Flags.CreateResource = 1; + create_alloc.pStandardAllocation = &standard; + create_alloc.NumAllocations = 1; + create_alloc.pAllocationInfo = &alloc; + create_alloc.pPrivateRuntimeData = expect_runtime_data; + create_alloc.PrivateRuntimeDataSize = sizeof(expect_runtime_data); + create_alloc.hPrivateRuntimeResourceHandle = (HANDLE)0xdeadbeef; + alloc.pPrivateDriverData = expect_alloc_data; + alloc.PrivateDriverDataSize = sizeof(expect_alloc_data); + alloc.hAllocation = create_alloc.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create_alloc ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create_alloc.hGlobalShare, ==, 0 ); + todo_wine check_d3dkmt_local( create_alloc.hResource, NULL ); + todo_wine check_d3dkmt_local( alloc.hAllocation, NULL ); + + status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); + todo_wine 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 ); + + destroy_alloc.hDevice = create_device.hDevice; + destroy_alloc.hResource = create_alloc.hResource; + status = D3DKMTDestroyAllocation( &destroy_alloc ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + create_alloc.hResource = 0; + + + create_alloc.Flags.CreateShared = 1; + alloc.hAllocation = create_alloc.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create_alloc ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine check_d3dkmt_global( create_alloc.hGlobalShare ); + todo_wine check_d3dkmt_local( create_alloc.hResource, NULL ); + todo_wine check_d3dkmt_local( alloc.hAllocation, NULL ); + + status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); + todo_wine 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 ); + + destroy_alloc.hResource = create_alloc.hResource; + status = D3DKMTDestroyAllocation( &destroy_alloc ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + create_alloc.hResource = 0; + + + create_alloc.Flags.NtSecuritySharing = 1; + alloc.hAllocation = create_alloc.hGlobalShare = 0x1eadbeed; + status = D3DKMTCreateAllocation( &create_alloc ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine ok_x4( create_alloc.hGlobalShare, ==, 0 ); + todo_wine check_d3dkmt_local( create_alloc.hResource, NULL ); + todo_wine check_d3dkmt_local( alloc.hAllocation, NULL ); + + /* can only share resources, not allocations */ + status = D3DKMTShareObjects( 1, &alloc.hAllocation, &attr, STANDARD_RIGHTS_READ, &handle ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + status = D3DKMTShareObjects( 1, &create_alloc.hResource, &attr, STANDARD_RIGHTS_READ, &handle ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + todo_wine check_object_type( handle, L"DxgkSharedResource" ); + todo_wine check_object_name( handle, name.Buffer ); + + + status = D3DKMTOpenNtHandleFromName( &open_resource_name ); + todo_wine 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 ); + 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 ); + open_resource_name.dwDesiredAccess = GENERIC_ALL; + status = D3DKMTOpenNtHandleFromName( &open_resource_name ); + todo_wine 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; + query_resource.hNtHandle = open_resource_name.hNtHandle; + query_resource.PrivateRuntimeDataSize = 0xdeadbeef; + query_resource.TotalPrivateDriverDataSize = 0xdeadbeef; + 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 ); + + 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_u1( runtime_data[0], ==, 0xcd ); + + CloseHandle( open_resource_name.hNtHandle ); + + + memset( runtime_data, 0xcd, sizeof(runtime_data) ); + memset( driver_data, 0xcd, sizeof(driver_data) ); + open_resource.hDevice = create_device.hDevice; + open_resource.hNtHandle = handle; + open_resource.hResource = open_resource.hKeyedMutex = open_resource.hSyncObject = 0x1eadbeed; + open_resource.NumAllocations = 1; + open_resource.pOpenAllocationInfo2 = &open_alloc; + open_alloc.hAllocation = 0x1eadbeed; + open_resource.pPrivateRuntimeData = runtime_data; + open_resource.PrivateRuntimeDataSize = query_resource.PrivateRuntimeDataSize; + open_resource.pTotalPrivateDriverDataBuffer = driver_data; + open_resource.TotalPrivateDriverDataBufferSize = query_resource.TotalPrivateDriverDataSize; + 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.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 ); + ok_x4( open_resource.KeyedMutexPrivateRuntimeDataSize, ==, 0 ); + todo_wine 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) ); + todo_wine 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; + status = D3DKMTDestroyAllocation( &destroy_alloc ); + todo_wine 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 ); + open_resource.pOpenAllocationInfo2 = &open_alloc; + + open_resource.NumAllocations = 0; + status = D3DKMTOpenResourceFromNtHandle( &open_resource ); + todo_wine 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 ); + open_resource.pPrivateRuntimeData = runtime_data; + + open_resource.PrivateRuntimeDataSize += 1; + status = D3DKMTOpenResourceFromNtHandle( &open_resource ); + todo_wine 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 ); + open_resource.pTotalPrivateDriverDataBuffer = driver_data; + + open_resource.TotalPrivateDriverDataBufferSize -= 1; + status = D3DKMTOpenResourceFromNtHandle( &open_resource ); + todo_wine ok_nt( STATUS_NO_MEMORY, status ); + open_resource.TotalPrivateDriverDataBufferSize = query_resource.TotalPrivateDriverDataSize; + + memset( &open_resource, 0, sizeof(open_resource) ); + CloseHandle( handle ); + + /* with combined objects only resource/mutex/sync order and combination works */ + + create_sync2.hDevice = create_device.hDevice; + create_sync2.Info.Type = D3DDDI_SYNCHRONIZATION_MUTEX; + status = D3DKMTCreateSynchronizationObject2( &create_sync2 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + handle = (HANDLE)0xdeadbeef; + + create_mutex2.Flags.NtSecuritySharing = 1; + create_mutex2.PrivateRuntimeDataSize = sizeof(expect_mutex_data); + create_mutex2.pPrivateRuntimeData = expect_mutex_data; + status = D3DKMTCreateKeyedMutex2( &create_mutex2 ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + objects[0] = create_alloc.hResource; + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + 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 ); + + objects[0] = create_alloc.hResource; + objects[1] = create_mutex2.hKeyedMutex; + objects[2] = create_sync2.hSyncObject; + handle = (HANDLE)0xdeadbeef; + status = D3DKMTShareObjects( 3, objects, &attr, STANDARD_RIGHTS_ALL, &handle ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + todo_wine check_object_type( handle, L"DxgkSharedResource" ); + todo_wine check_object_name( handle, name.Buffer ); + + destroy_mutex.hKeyedMutex = create_mutex2.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + create_mutex2.hKeyedMutex = 0; + + destroy_sync.hSyncObject = create_sync2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy_sync ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + create_sync2.hSyncObject = 0; + + destroy_alloc.hResource = create_alloc.hResource; + status = D3DKMTDestroyAllocation( &destroy_alloc ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + create_alloc.hResource = 0; + + + query_resource.hDevice = create_device.hDevice; + query_resource.hNtHandle = handle; + query_resource.PrivateRuntimeDataSize = 0xdeadbeef; + query_resource.TotalPrivateDriverDataSize = 0xdeadbeef; + 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 ); + + 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_u1( runtime_data[0], ==, 0xcd ); + + memset( runtime_data, 0xcd, sizeof(runtime_data) ); + memset( driver_data, 0xcd, sizeof(driver_data) ); + memset( mutex_data, 0xcd, sizeof(mutex_data) ); + open_resource.hDevice = create_device.hDevice; + open_resource.hNtHandle = handle; + open_resource.hResource = open_resource.hKeyedMutex = open_resource.hSyncObject = 0x1eadbeed; + open_resource.NumAllocations = 1; + open_resource.pOpenAllocationInfo2 = &open_alloc; + open_alloc.hAllocation = 0x1eadbeed; + open_resource.pPrivateRuntimeData = runtime_data; + open_resource.PrivateRuntimeDataSize = query_resource.PrivateRuntimeDataSize; + open_resource.pTotalPrivateDriverDataBuffer = driver_data; + open_resource.TotalPrivateDriverDataBufferSize = query_resource.TotalPrivateDriverDataSize; + open_resource.pKeyedMutexPrivateRuntimeData = mutex_data; + open_resource.KeyedMutexPrivateRuntimeDataSize = sizeof(expect_mutex_data); + 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.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 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 ); + 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 ); + open_resource.hResource = 0; + + destroy_mutex.hKeyedMutex = open_resource.hKeyedMutex; + status = D3DKMTDestroyKeyedMutex( &destroy_mutex ); + todo_wine 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 ); + open_resource.hSyncObject = 0; + + memset( &open_resource, 0, sizeof(open_resource) ); + CloseHandle( handle ); + + + VirtualFree( (void *)alloc.pSystemMem, 0, MEM_RELEASE ); + + destroy_device.hDevice = create_device.hDevice; + status = D3DKMTDestroyDevice( &destroy_device ); + ok_nt( STATUS_SUCCESS, status ); + close_adapter.hAdapter = open_adapter.hAdapter; + status = D3DKMTCloseAdapter( &close_adapter ); + ok_nt( STATUS_SUCCESS, status ); +} + START_TEST( d3dkmt ) { /* native win32u.dll fails if user32 is not loaded, so make sure it's fully initialized */ @@ -2015,4 +2624,5 @@ START_TEST( d3dkmt ) test_D3DKMTCreateSynchronizationObject(); test_D3DKMTCreateKeyedMutex(); test_D3DKMTCreateAllocation(); + test_D3DKMTShareObjects(); }
Added a missing stub message, is there something else I missed about this? It's pretty much only tests for how shared resource functions are supposed to work.
I'm getting a bunch of test failures here, please rebase to make sure it runs the tests.