From: Rémi Bernon rbernon@codeweavers.com
When a process exits with an open handle, it loses its references on the object. --- dlls/win32u/tests/d3dkmt.c | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)
diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 167071f5b0c..9de2dc3d76a 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -67,6 +67,33 @@ static const char *debugstr_ok( const char *cond ) #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 run_in_process( a ) run_in_process_( __FILE__, __LINE__, a ) +static void run_in_process_( const char *file, int line, const char *args ) +{ + char cmdline[MAX_PATH * 2], test[MAX_PATH], *tmp, **argv; + STARTUPINFOA startup = {.cb = sizeof(STARTUPINFOA)}; + PROCESS_INFORMATION info = {0}; + const char *name; + DWORD ret; + int argc; + + name = file; + if ((tmp = strrchr( name, '\' ))) name = tmp; + if ((tmp = strrchr( name, '/' ))) name = tmp; + if ((tmp = strrchr( test, '.' ))) *tmp = 0; + strcpy( test, name ); + + argc = winetest_get_mainargs( &argv ); + sprintf( cmdline, "%s %s %s", argv[0], argc > 1 ? argv[1] : test, args ); + ret = CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info ); + ok_(file, line)( ret, "CreateProcessA failed, error %lu\n", GetLastError() ); + if (!ret) return; + + wait_child_process( info.hProcess ); + CloseHandle( info.hThread ); + CloseHandle( info.hProcess ); +} + #define check_d3dkmt_global( a ) check_d3dkmt_global_( __LINE__, a ) static void check_d3dkmt_global_( int line, UINT_PTR handle ) { @@ -1193,6 +1220,21 @@ static void test_D3DKMTQueryAdapterInfo(void) ok( status == STATUS_SUCCESS, "Got unexpected return code %#lx.\n", status ); }
+static void test_D3DKMTCreateSynchronizationObject_process( const char *arg ) +{ + D3DKMT_OPENSYNCHRONIZATIONOBJECT open = {0}; + D3DKMT_HANDLE global = atoi( arg ); + D3DKMT_HANDLE next_local = 0; + NTSTATUS status; + + open.hSharedHandle = global; + open.hSyncObject = 0x1eadbeed; + status = D3DKMTOpenSynchronizationObject( &open ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + todo_wine check_d3dkmt_local( open.hSyncObject, &next_local ); + /* leak the object */ +} + static void test_D3DKMTCreateSynchronizationObject( void ) { D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter = {0}; @@ -1204,6 +1246,7 @@ static void test_D3DKMTCreateSynchronizationObject( void ) D3DKMT_CREATEDEVICE create_device = {0}; D3DKMT_CLOSEADAPTER close_adapter = {0}; D3DKMT_HANDLE next_local = 0; + char buffer[256]; NTSTATUS status;
wcscpy( open_adapter.DeviceName, L"\\.\DISPLAY1" ); @@ -1426,6 +1469,25 @@ static void test_D3DKMTCreateSynchronizationObject( void ) todo_wine ok_nt( STATUS_SUCCESS, status );
+ create2.Info.Flags.NtSecuritySharing = 0; + 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 ); + + sprintf( buffer, "test_D3DKMTCreateSynchronizationObject %u", create2.Info.SharedHandle ); + run_in_process( buffer ); + + destroy.hSyncObject = create2.hSyncObject; + status = D3DKMTDestroySynchronizationObject( &destroy ); + todo_wine ok_nt( STATUS_SUCCESS, status ); + + open.hSharedHandle = create2.Info.SharedHandle; + status = D3DKMTOpenSynchronizationObject( &open ); + todo_wine ok_nt( STATUS_INVALID_PARAMETER, status ); + + destroy_device.hDevice = create_device.hDevice; status = D3DKMTDestroyDevice( &destroy_device ); ok_nt( STATUS_SUCCESS, status ); @@ -2606,9 +2668,16 @@ static void test_D3DKMTShareObjects( void )
START_TEST( d3dkmt ) { + char **argv; + int argc; + /* native win32u.dll fails if user32 is not loaded, so make sure it's fully initialized */ GetDesktopWindow();
+ argc = winetest_get_mainargs( &argv ); + if (argc > 3 && !strcmp( argv[2], "test_D3DKMTCreateSynchronizationObject" )) + return test_D3DKMTCreateSynchronizationObject_process( argv[3] ); + test_D3DKMTOpenAdapterFromGdiDisplayName(); test_D3DKMTOpenAdapterFromHdc(); test_D3DKMTEnumAdapters2();