diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index acbfab06761..08ea8cc9a96 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -2179,21 +2179,63 @@ BOOL WINAPI BindIoCompletionCallback( HANDLE FileHandle, LPOVERLAPPED_COMPLETION /*********************************************************************** * CreateMemoryResourceNotification (KERNEL32.@) */ -HANDLE WINAPI CreateMemoryResourceNotification(MEMORY_RESOURCE_NOTIFICATION_TYPE nt) +HANDLE WINAPI CreateMemoryResourceNotification(MEMORY_RESOURCE_NOTIFICATION_TYPE type) { - FIXME("(%d) stub\n", nt); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return NULL; + static const WCHAR lowmemW[] = + {'\\','K','e','r','n','e','l','O','b','j','e','c','t','s', + '\\','L','o','w','M','e','m','o','r','y','C','o','n','d','i','t','i','o','n',0}; + static const WCHAR highmemW[] = + {'\\','K','e','r','n','e','l','O','b','j','e','c','t','s', + '\\','H','i','g','h','M','e','m','o','r','y','C','o','n','d','i','t','i','o','n',0}; + HANDLE ret; + UNICODE_STRING nameW; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + + switch (type) + { + case LowMemoryResourceNotification: + RtlInitUnicodeString( &nameW, lowmemW ); + break; + case HighMemoryResourceNotification: + RtlInitUnicodeString( &nameW, highmemW ); + break; + default: + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + status = NtOpenEvent( &ret, EVENT_ALL_ACCESS, &attr ); + if (status != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError(status) ); + return 0; + } + return ret; } /*********************************************************************** * QueryMemoryResourceNotification (KERNEL32.@) */ -BOOL WINAPI QueryMemoryResourceNotification(HANDLE rnh, PBOOL rs) +BOOL WINAPI QueryMemoryResourceNotification(HANDLE handle, PBOOL state) { - FIXME("(%p, %p) stub\n", rnh, rs); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + switch (WaitForSingleObject( handle, 0 )) + { + case WAIT_OBJECT_0: + *state = TRUE; + return TRUE; + case WAIT_TIMEOUT: + *state = FALSE; + return TRUE; + } + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; } #ifdef __i386__ diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index 07bc2ca9976..3965458e5c6 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -35,6 +35,8 @@ static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR); static BOOL (WINAPI *pDeleteTimerQueueEx)(HANDLE, HANDLE); static BOOL (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE); static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR); +static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE); +static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL); static void test_signalandwait(void) { @@ -300,6 +302,8 @@ static void test_event(void) SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; ACL acl; + DWORD ret; + BOOL val; /* no sd */ handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); @@ -360,6 +364,39 @@ static void test_event(void) ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); CloseHandle( handle ); + + /* resource notifications are events too */ + + if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification) + { + trace( "memory resource notifications not supported\n" ); + return; + } + handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 ); + ok( !handle, "CreateMemoryResourceNotification succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); + ret = pQueryMemoryResourceNotification( handle, &val ); + ok( !ret, "QueryMemoryResourceNotification succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); + + handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification ); + ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() ); + ret = WaitForSingleObject( handle, 10 ); + ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret ); + + val = ~0; + ret = pQueryMemoryResourceNotification( handle, &val ); + ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() ); + ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); + ret = CloseHandle( handle ); + ok( ret, "CloseHandle failed err %u\n", GetLastError() ); + + handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); + val = ~0; + ret = pQueryMemoryResourceNotification( handle, &val ); + ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() ); + ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); + CloseHandle( handle ); } static void test_semaphore(void) @@ -1074,6 +1111,8 @@ START_TEST(sync) pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx"); pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer"); pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA"); + pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification"); + pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification"); test_signalandwait(); test_mutex(); diff --git a/include/winbase.h b/include/winbase.h index 6ec92302285..492c63b7e5d 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2021,6 +2021,7 @@ WINBASEAPI BOOL WINAPI QueryFullProcessImageNameA(HANDLE,DWORD,LPSTR,PDWO WINBASEAPI BOOL WINAPI QueryFullProcessImageNameW(HANDLE,DWORD,LPWSTR,PDWORD); #define QueryFullProcessImageName WINELIB_NAME_AW(QueryFullProcessImageName) WINBASEAPI BOOL WINAPI QueryInformationJobObject(HANDLE,JOBOBJECTINFOCLASS,LPVOID,DWORD,DWORD*); +WINBASEAPI BOOL WINAPI QueryMemoryResourceNotification(HANDLE,PBOOL); WINBASEAPI BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER*); WINBASEAPI BOOL WINAPI QueryPerformanceFrequency(LARGE_INTEGER*); WINBASEAPI DWORD WINAPI QueueUserAPC(PAPCFUNC,HANDLE,ULONG_PTR);