[RPCRT4_WINETEST] Sync with Wine Staging 4.0. CORE-15682
[reactos.git] / modules / rostests / winetests / rpcrt4 / server.c
index 96cea2c..2a66a38 100644 (file)
@@ -313,7 +313,7 @@ void __cdecl s_get_number_array(int x[20], int *n)
 {
   int c[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
   memcpy(x, c, sizeof(c));
-  *n = sizeof(c)/sizeof(c[0]);
+  *n = ARRAY_SIZE(c);
 }
 
 int __cdecl s_sum_cs(cs_t *cs)
@@ -861,6 +861,16 @@ void __cdecl s_ip_test(ipu_t *a)
     ok(hr == S_OK, "got %#x\n", hr);
 }
 
+int __cdecl s_sum_ptr_array(int *a[2])
+{
+    return *a[0] + *a[1];
+}
+
+int __cdecl s_sum_array_ptr(int (*a)[2])
+{
+    return (*a)[0] + (*a)[1];
+}
+
 static void
 make_cmdline(char buffer[MAX_PATH], const char *test)
 {
@@ -1388,6 +1398,7 @@ array_tests(void)
   pints_t api[5];
   numbers_struct_t *ns;
   refpint_t rpi[5];
+  int i0 = 1, i1 = 2, *ptr_array[2] = {&i0, &i1}, array[2] = {3, 4};
 
   if (!old_windows_version)
   {
@@ -1518,6 +1529,9 @@ array_tests(void)
   pi[4] = -4; rpi[4] = &pi[4];
   ok(sum_complex_array(5, rpi) == 1, "RPC sum_complex_array\n");
   HeapFree(GetProcessHeap(), 0, pi);
+
+  ok(sum_ptr_array(ptr_array) == 3, "RPC sum_ptr_array\n");
+  ok(sum_array_ptr(&array) == 7, "RPC sum_array_ptr\n");
 }
 
 void __cdecl s_authinfo_test(unsigned int protseq, int secure)
@@ -1959,6 +1973,118 @@ static void test_server_listening(void)
     ok(status == RPC_S_OK, "RpcStringFree\n");
 }
 
+static HANDLE create_server_process(void)
+{
+    SECURITY_ATTRIBUTES sec_attr = { sizeof(sec_attr), NULL, TRUE };
+    HANDLE ready_event;
+    char cmdline[MAX_PATH];
+    PROCESS_INFORMATION info;
+    STARTUPINFOA startup;
+    DWORD ret;
+
+    memset(&startup, 0, sizeof startup);
+    startup.cb = sizeof startup;
+
+    ready_event = CreateEventW(&sec_attr, TRUE, FALSE, NULL);
+    ok(ready_event != NULL, "CreateEvent failed: %u\n", GetLastError());
+
+    sprintf(cmdline, "%s server run %lx", progname, (UINT_PTR)ready_event);
+    trace("running server process...\n");
+    ok(CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
+    ret = WaitForSingleObject(ready_event, 10000);
+    ok(WAIT_OBJECT_0 == ret, "WaitForSingleObject\n");
+
+    ok(CloseHandle(info.hThread), "CloseHandle\n");
+    ok(CloseHandle(ready_event), "CloseHandle\n");
+    return info.hProcess;
+}
+
+static void run_server(HANDLE ready_event)
+{
+    static unsigned char np[] = "ncacn_np";
+    static unsigned char pipe[] = PIPE "term_test";
+    RPC_STATUS status;
+    BOOL ret;
+
+    status = RpcServerUseProtseqEpA(np, 0, pipe, NULL);
+    ok(status == RPC_S_OK, "RpcServerUseProtseqEp(ncacn_np) failed with status %d\n", status);
+
+    status = RpcServerRegisterIf(s_IServer_v0_0_s_ifspec, NULL, NULL);
+    ok(status == RPC_S_OK, "RpcServerRegisterIf failed with status %d\n", status);
+
+    test_is_server_listening(NULL, RPC_S_NOT_LISTENING);
+    status = RpcServerListen(1, 20, TRUE);
+    ok(status == RPC_S_OK, "RpcServerListen failed with status %d\n", status);
+
+    stop_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    ok(stop_event != NULL, "CreateEvent failed with error %d\n", GetLastError());
+
+    ret = SetEvent(ready_event);
+    ok(ret, "SetEvent failed: %u\n", GetLastError());
+
+    ret = WaitForSingleObject(stop_event, 1000);
+    ok(WAIT_OBJECT_0 == ret, "WaitForSingleObject\n");
+
+    status = RpcMgmtWaitServerListen();
+    ok(status == RPC_S_OK, "RpcMgmtWaitServerListening failed with status %d\n", status);
+
+    CloseHandle(stop_event);
+    stop_event = NULL;
+}
+
+static DWORD WINAPI basic_tests_thread(void *arg)
+{
+    basic_tests();
+    return 0;
+}
+
+static void test_reconnect(void)
+{
+    static unsigned char np[] = "ncacn_np";
+    static unsigned char address_np[] = "\\\\.";
+    static unsigned char pipe[] = PIPE "term_test";
+    unsigned char *binding;
+    HANDLE threads[32];
+    HANDLE server_process;
+    unsigned i;
+    DWORD ret;
+
+    server_process = create_server_process();
+
+    ok(RPC_S_OK == RpcStringBindingComposeA(NULL, np, address_np, pipe, NULL, &binding), "RpcStringBindingCompose\n");
+    ok(RPC_S_OK == RpcBindingFromStringBindingA(binding, &IServer_IfHandle), "RpcBindingFromStringBinding\n");
+
+    for (i = 0; i < ARRAY_SIZE(threads); i++)
+    {
+        threads[i] = CreateThread(NULL, 0, basic_tests_thread, 0, 0, NULL);
+        ok(threads[i] != NULL, "CreateThread failed: %u\n", GetLastError());
+    }
+
+    for (i = 0; i < ARRAY_SIZE(threads); i++)
+    {
+        ret = WaitForSingleObject(threads[i], 10000);
+        ok(WAIT_OBJECT_0 == ret, "WaitForSingleObject\n");
+        CloseHandle(threads[i]);
+    }
+
+    stop();
+
+    winetest_wait_child_process(server_process);
+    ok(CloseHandle(server_process), "CloseHandle\n");
+
+    /* create new server, rpcrt4 will connect to it once sending to existing connection fails
+     * that current connection is broken. */
+    server_process = create_server_process();
+    basic_tests();
+    stop();
+
+    winetest_wait_child_process(server_process);
+    ok(CloseHandle(server_process), "CloseHandle\n");
+
+    ok(RPC_S_OK == RpcStringFreeA(&binding), "RpcStringFree\n");
+    ok(RPC_S_OK == RpcBindingFree(&IServer_IfHandle), "RpcBindingFree\n");
+}
+
 static BOOL is_process_elevated(void)
 {
     HANDLE token;
@@ -2085,16 +2211,10 @@ START_TEST(server)
   ULONG size = 0;
   int argc;
   char **argv;
-  BOOL firewall_enabled = is_firewall_enabled();
+  BOOL firewall_enabled = is_firewall_enabled(), firewall_disabled = FALSE;
 
   InitFunctionPointers();
 
-  if (firewall_enabled && !is_process_elevated())
-  {
-    trace("no privileges, skipping tests to avoid firewall dialog\n");
-    return;
-  }
-
   ok(!GetUserNameExA(NameSamCompatible, NULL, &size), "GetUserNameExA\n");
   domain_and_user = HeapAlloc(GetProcessHeap(), 0, size);
   ok(GetUserNameExA(NameSamCompatible, domain_and_user, &size), "GetUserNameExA\n");
@@ -2116,23 +2236,50 @@ START_TEST(server)
   }
   else if (argc == 4)
   {
-    test_server_listening();
+    if (!strcmp(argv[3], "listen"))
+    {
+      test_server_listening();
+    }
+    else if(!strcmp(argv[2], "run"))
+    {
+      UINT_PTR event;
+      sscanf(argv[3], "%lx", &event);
+      run_server((HANDLE)event);
+    }
   }
   else
   {
     if (firewall_enabled)
     {
-      HRESULT hr = set_firewall(APP_ADD);
-      if (hr != S_OK)
+      if (is_process_elevated())
       {
-        skip("can't authorize app in firewall %08x\n", hr);
-        HeapFree(GetProcessHeap(), 0, domain_and_user);
-        return;
+        HRESULT hr = set_firewall(APP_ADD);
+        if (hr == S_OK)
+        {
+          firewall_enabled = FALSE;
+          firewall_disabled = TRUE;
+        }
+        else
+        {
+          skip("can't authorize app in firewall %08x\n", hr);
+        }
+      }
+      else
+      {
+          trace("no privileges, skipping tests to avoid firewall dialog\n");
       }
     }
-    server();
+
+    if (!firewall_enabled) server();
+
+    /* Those tests cause occasional crashes on winxp and win2k3 */
+    if (GetProcAddress(GetModuleHandleA("rpcrt4.dll"), "RpcExceptionFilter"))
+        test_reconnect();
+    else
+        win_skip("Skipping reconnect tests on too old Windows version\n");
+
     run_client("test listen");
-    if (firewall_enabled) set_firewall(APP_REMOVE);
+    if (firewall_disabled) set_firewall(APP_REMOVE);
   }
 
   HeapFree(GetProcessHeap(), 0, domain_and_user);