From ef1042b0b195f19f5e83591070710f4a85fb3b04 Mon Sep 17 00:00:00 2001
From: Daniel Lehman <dlehman25@gmail.com>
Date: Sun, 29 Apr 2018 15:42:35 -0700
Subject: [PATCH] advapi32/tests: Add tests for REG_NOTIFY_THREAD_AGNOSTIC.

Signed-off-by: Daniel Lehman <dlehman@esri.com>
---
 dlls/advapi32/tests/registry.c | 81 ++++++++++++++++++++++++++++++++++
 include/winnt.h                |  1 +
 2 files changed, 82 insertions(+)

diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c
index 2f7566c3000..6d8f90add8a 100644
--- a/dlls/advapi32/tests/registry.c
+++ b/dlls/advapi32/tests/registry.c
@@ -3464,9 +3464,28 @@ static void test_RegOpenCurrentUser(void)
     RegCloseKey(key);
 }
 
+struct notify_data {
+    HKEY key;
+    DWORD flags;
+    HANDLE event;
+};
+
+static DWORD WINAPI notify_change_thread(void *arg)
+{
+    struct notify_data *data = arg;
+    LONG ret;
+
+    ret = RegNotifyChangeKeyValue(data->key, TRUE,
+            REG_NOTIFY_CHANGE_NAME|data->flags, data->event, TRUE);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+    return 0;
+}
+
 static void test_RegNotifyChangeKeyValue(void)
 {
+    struct notify_data data;
     HKEY key, subkey;
+    HANDLE thread;
     HANDLE event;
     DWORD dwret;
     LONG ret;
@@ -3486,6 +3505,68 @@ static void test_RegNotifyChangeKeyValue(void)
     dwret = WaitForSingleObject(event, 0);
     ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
 
+    RegDeleteKeyA(key, "SubKey");
+    RegCloseKey(key);
+
+    /* test same thread with REG_NOTIFY_THREAD_AGNOSTIC */
+    ret = RegOpenKeyA(hkey_main, "TestKey", &key);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+    ret = RegNotifyChangeKeyValue(key, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_THREAD_AGNOSTIC,
+            event, TRUE);
+    if (ret == ERROR_INVALID_PARAMETER)
+    {
+        win_skip("REG_NOTIFY_THREAD_AGNOSTIC is not supported\n");
+        RegCloseKey(key);
+        CloseHandle(event);
+        return;
+    }
+
+    ret = RegCreateKeyA(key, "SubKey", &subkey);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+    dwret = WaitForSingleObject(event, 0);
+    ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
+
+    RegDeleteKeyA(key, "SubKey");
+    RegCloseKey(key);
+
+    /* test different thread without REG_NOTIFY_THREAD_AGNOSTIC */
+    ret = RegOpenKeyA(hkey_main, "TestKey", &key);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+
+    data.key = key;
+    data.flags = 0;
+    data.event = event;
+    thread = CreateThread(NULL, 0, notify_change_thread, &data, 0, NULL);
+    WaitForSingleObject(thread, INFINITE);
+    CloseHandle(thread);
+
+    /* the thread exiting causes event to signal on Windows
+       this is worked around on Windows using REG_NOTIFY_THREAD_AGNOSTIC
+       Wine already behaves as if the flag is set */
+    dwret = WaitForSingleObject(event, 0);
+    todo_wine
+    ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
+    RegCloseKey(key);
+
+    /* test different thread with REG_NOTIFY_THREAD_AGNOSTIC */
+    ret = RegOpenKeyA(hkey_main, "TestKey", &key);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+
+    data.flags = REG_NOTIFY_THREAD_AGNOSTIC;
+    thread = CreateThread(NULL, 0, notify_change_thread, &data, 0, NULL);
+    WaitForSingleObject(thread, INFINITE);
+    CloseHandle(thread);
+
+    dwret = WaitForSingleObject(event, 0);
+    ok(dwret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", dwret);
+
+    ret = RegCreateKeyA(key, "SubKey", &subkey);
+    ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
+
+    dwret = WaitForSingleObject(event, 0);
+    ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
+
+    RegDeleteKeyA(key, "SubKey");
     RegDeleteKeyA(key, "");
     RegCloseKey(key);
     CloseHandle(event);
diff --git a/include/winnt.h b/include/winnt.h
index 16d96d8b9df..ba10be772d9 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -5368,6 +5368,7 @@ typedef struct _TAPE_GET_MEDIA_PARAMETERS {
 #define REG_NOTIFY_CHANGE_ATTRIBUTES 0x02
 #define REG_NOTIFY_CHANGE_LAST_SET   0x04
 #define REG_NOTIFY_CHANGE_SECURITY   0x08
+#define REG_NOTIFY_THREAD_AGNOSTIC   0x10000000
 
 #define KEY_QUERY_VALUE		0x00000001
 #define KEY_SET_VALUE		0x00000002
-- 
2.17.0

