* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#define _WIN32_WINNT 0x500
+#define _WIN32_WINNT 0x502
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
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)
{
DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
HMODULE kernel32;
DWORD r;
- int i;
- HANDLE event[2], maxevents[MAXIMUM_WAIT_OBJECTS], semaphore[2], file;
+ HANDLE event[2], semaphore[2], file;
kernel32 = GetModuleHandle("kernel32");
pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
CloseHandle(event[0]);
CloseHandle(event[1]);
- /* create the maximum number of events and make sure
- * we can wait on that many */
- for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
- {
- maxevents[i] = CreateEvent(NULL, 1, 1, NULL);
- ok( maxevents[i] != 0, "should create enough events\n");
- }
- r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
- ok( r != WAIT_FAILED && r != WAIT_TIMEOUT, "should succeed\n");
-
- for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
- if (maxevents[i]) CloseHandle(maxevents[i]);
-
/* semaphores */
semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
BOOL ret;
HANDLE hCreated;
HANDLE hOpened;
+ int i;
+ DWORD failed = 0;
+ SetLastError(0xdeadbeef);
+ hOpened = OpenMutex(0, FALSE, "WineTestMutex");
+ ok(hOpened == NULL, "OpenMutex succeeded\n");
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
- wait_ret = WaitForSingleObject(hCreated, INFINITE);
- ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
- /* yes, opening with just READ_CONTROL access allows us to successfully
- * call ReleaseMutex */
- hOpened = OpenMutex(READ_CONTROL, FALSE, "WineTestMutex");
+ SetLastError(0xdeadbeef);
+ hOpened = OpenMutex(0, FALSE, "WineTestMutex");
+todo_wine
+ ok(hOpened == NULL, "OpenMutex succeeded\n");
+todo_wine
+ ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex");
+ ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
+ wait_ret = WaitForSingleObject(hOpened, INFINITE);
+ ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
+ CloseHandle(hOpened);
+
+ for(i=0; i < 31; i++)
+ {
+ wait_ret = WaitForSingleObject(hCreated, INFINITE);
+ ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
+ }
+
+ SetLastError(0xdeadbeef);
+ hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
- ret = ReleaseMutex(hOpened);
- todo_wine ok(ret, "ReleaseMutex failed with error %d\n", GetLastError());
+ wait_ret = WaitForSingleObject(hOpened, INFINITE);
+ ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
+ CloseHandle(hOpened);
+
+ for (i = 0; i < 32; i++)
+ {
+ SetLastError(0xdeadbeef);
+ hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
+ if(hOpened != NULL)
+ {
+ SetLastError(0xdeadbeef);
+ ret = ReleaseMutex(hOpened);
+ ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
+ CloseHandle(hOpened);
+ }
+ else
+ {
+ if ((1 << i) == ACCESS_SYSTEM_SECURITY)
+ todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i);
+ else
+ todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
+ ReleaseMutex(hCreated);
+ failed |=0x1 << i;
+ }
+ }
+
+todo_wine
+ ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
+
+ SetLastError(0xdeadbeef);
ret = ReleaseMutex(hCreated);
- todo_wine ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
+ ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
"ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
/* test case sensitivity */
SetLastError(0xdeadbeef);
hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
ok(!hOpened, "OpenMutex succeeded\n");
- ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
- GetLastError() == ERROR_INVALID_NAME, /* win9x */
- "wrong error %u\n", GetLastError());
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
ok(!hOpened, "OpenMutex succeeded\n");
- ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
- GetLastError() == ERROR_INVALID_NAME, /* win9x */
- "wrong error %u\n", GetLastError());
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
ACL acl;
+ DWORD ret;
+ BOOL val;
/* no sd */
handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
SetLastError(0xdeadbeef);
handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
ok( !handle2, "OpenEvent succeeded\n");
- ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
- GetLastError() == ERROR_INVALID_NAME, /* win9x */
- "wrong error %u\n", GetLastError());
+ 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 );
}
SetLastError(0xdeadbeef);
handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
ok( !handle2, "OpenSemaphore succeeded\n");
- ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
- GetLastError() == ERROR_INVALID_NAME, /* win9x */
- "wrong error %u\n", GetLastError());
+ ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
CloseHandle( handle );
}
GetLastError());
}
+static HANDLE modify_handle(HANDLE handle, DWORD modify)
+{
+ DWORD tmp = HandleToULong(handle);
+ tmp |= modify;
+ return ULongToHandle(tmp);
+}
+
+static void test_WaitForSingleObject(void)
+{
+ HANDLE signaled, nonsignaled, invalid;
+ DWORD ret;
+
+ signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
+ nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
+ invalid = (HANDLE) 0xdeadbee0;
+
+ /* invalid handle with different values for lower 2 bits */
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(invalid, 0);
+ ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
+ ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
+ ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
+ ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ /* valid handle with different values for lower 2 bits */
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(nonsignaled, 0);
+ ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
+ ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
+ ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
+ ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* valid handle with different values for lower 2 bits */
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(signaled, 0);
+ ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
+ ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
+ ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
+ ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ CloseHandle(signaled);
+ CloseHandle(nonsignaled);
+}
+
+static void test_WaitForMultipleObjects(void)
+{
+ DWORD r;
+ int i;
+ HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
+
+ /* create the maximum number of events and make sure
+ * we can wait on that many */
+ for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
+ {
+ maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
+ ok( maxevents[i] != 0, "should create enough events\n");
+ }
+
+ /* a manual-reset event remains signaled, an auto-reset event is cleared */
+ r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
+ ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
+ r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
+ ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
+ ok(ResetEvent(maxevents[0]), "ResetEvent\n");
+ for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
+ {
+ /* the lowest index is checked first and remaining events are untouched */
+ r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
+ ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
+ }
+
+ for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
+ if (maxevents[i]) CloseHandle(maxevents[i]);
+}
+
START_TEST(sync)
{
HMODULE hdll = GetModuleHandle("kernel32");
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();
test_waitable_timer();
test_iocp_callback();
test_timer_queue();
+ test_WaitForSingleObject();
+ test_WaitForMultipleObjects();
}