[PATCH 2/7] schedsvc/tests: Add ATSvc RPC API tests.

Dmitry Timoshkov dmitry at baikal.ru
Thu Apr 5 02:55:42 CDT 2018


Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/schedsvc/tests/Makefile.in |   2 +
 dlls/schedsvc/tests/atsvc.idl   |   3 +
 dlls/schedsvc/tests/atsvcapi.c  | 196 ++++++++++++++++++++++++++++++++++++++++
 include/lmat.h                  |  28 ++++++
 4 files changed, 229 insertions(+)
 create mode 100644 dlls/schedsvc/tests/atsvc.idl
 create mode 100644 dlls/schedsvc/tests/atsvcapi.c

diff --git a/dlls/schedsvc/tests/Makefile.in b/dlls/schedsvc/tests/Makefile.in
index cd56fde214..b8e7448bb7 100644
--- a/dlls/schedsvc/tests/Makefile.in
+++ b/dlls/schedsvc/tests/Makefile.in
@@ -2,7 +2,9 @@ TESTDLL   = schedsvc.dll
 IMPORTS   = rpcrt4 ole32
 
 C_SRCS = \
+	atsvcapi.c \
 	rpcapi.c
 
 IDL_SRCS = \
+	atsvc.idl \
 	schrpc.idl
diff --git a/dlls/schedsvc/tests/atsvc.idl b/dlls/schedsvc/tests/atsvc.idl
new file mode 100644
index 0000000000..61bc163a57
--- /dev/null
+++ b/dlls/schedsvc/tests/atsvc.idl
@@ -0,0 +1,3 @@
+#pragma makedep client
+
+#include "wine/atsvc.idl"
diff --git a/dlls/schedsvc/tests/atsvcapi.c b/dlls/schedsvc/tests/atsvcapi.c
new file mode 100644
index 0000000000..d429232913
--- /dev/null
+++ b/dlls/schedsvc/tests/atsvcapi.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2018 Dmitry Timoshkov
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdio.h>
+#include <windows.h>
+#include <ole2.h>
+#include <rpcdce.h>
+#include <mstask.h>
+#include "atsvc.h"
+
+#include "wine/test.h"
+
+/* lmat.h defines those, but other types in that file conflict
+ * with generated atsvc.h typedefs.
+ */
+#define JOB_ADD_CURRENT_DATE 0x08
+#define JOB_NONINTERACTIVE   0x10
+
+extern handle_t rpc_handle;
+
+static int test_failures, test_skipped;
+
+static LONG CALLBACK rpc_exception_filter(EXCEPTION_POINTERS *ptrs)
+{
+    if (test_skipped)
+        skip("Can't connect to ATSvc service: %#x\n", ptrs->ExceptionRecord->ExceptionCode);
+
+    if (winetest_debug)
+    {
+        fprintf(stdout, "%04x:atsvcapi: 1 tests executed (0 marked as todo, %d %s), %d skipped.\n",
+                GetCurrentProcessId(), test_failures, test_failures != 1 ? "failures" : "failure", test_skipped);
+        fflush(stdout);
+    }
+    ExitProcess(test_failures);
+}
+
+START_TEST(atsvcapi)
+{
+    static unsigned char ncalrpc[] = "ncalrpc";
+    static WCHAR task1W[] = { 'T','a','s','k','1','.','e','x','e',0 };
+    HRESULT hr;
+    unsigned char *binding_str;
+    WCHAR server_name[MAX_COMPUTERNAME_LENGTH + 1];
+    PTOP_LEVEL_EXCEPTION_FILTER old_exception_filter;
+    AT_ENUM_CONTAINER container;
+    AT_INFO info;
+    DWORD ret, i, total, start_index, jobid, try, try_count;
+    BOOL found;
+
+    total = MAX_COMPUTERNAME_LENGTH + 1;
+    SetLastError(0xdeadbeef);
+    ret = GetComputerNameW(server_name, &total);
+    ok(ret, "GetComputerName error %u\n", GetLastError());
+
+    hr = RpcStringBindingComposeA(NULL, ncalrpc, NULL, NULL, NULL, &binding_str);
+    ok(hr == RPC_S_OK, "RpcStringBindingCompose error %#x\n", hr);
+    hr = RpcBindingFromStringBindingA(binding_str, &rpc_handle);
+    ok(hr == RPC_S_OK, "RpcBindingFromStringBinding error %#x\n", hr);
+    hr = RpcStringFreeA(&binding_str);
+    ok(hr == RPC_S_OK, "RpcStringFree error %#x\n", hr);
+
+    /* widl generated RpcTryExcept/RpcExcept can't catch raised exceptions */
+    old_exception_filter = SetUnhandledExceptionFilter(rpc_exception_filter);
+
+    /* If the first call fails that's probably because the service is not running */
+    test_failures = 0;
+    test_skipped = 1;
+
+    memset(&info, 0, sizeof(info));
+    info.Flags = JOB_ADD_CURRENT_DATE | JOB_NONINTERACTIVE;
+    info.Command = task1W;
+    jobid = 0;
+    ret = NetrJobAdd(server_name, &info, &jobid);
+    if (ret == ERROR_ACCESS_DENIED)
+    {
+        win_skip("NetrJobAdd: Access denied, skipping the tests\n");
+        goto skip_tests;
+    }
+todo_wine
+    ok(ret == ERROR_SUCCESS || broken(ret == ERROR_NOT_SUPPORTED) /* Win8+ */, "NetrJobAdd error %u\n", ret);
+    if (ret == ERROR_NOT_SUPPORTED)
+    {
+        /* FIXME: use win_skip() when todo_wine above is removed */
+        skip("NetrJobAdd is not supported on this platform\n");
+        goto skip_tests;
+    }
+    ok(jobid != 0, "jobid should not be 0\n");
+
+    /* From now on: if the call fails that's a failure */
+    test_failures = 1;
+    test_skipped = 0;
+
+    try_count = 5;
+
+    for (try = 1; try <= try_count; try++)
+    {
+        container.EntriesRead = 0;
+        container.Buffer = NULL;
+        total = start_index = 0;
+        ret = NetrJobEnum(server_name, &container, 1, &total, &start_index);
+        if (ret == ERROR_ACCESS_DENIED)
+        {
+            win_skip("NetrJobEnum: Access denied, skipping the tests\n");
+            goto skip_tests_delete;
+        }
+        ok(ret == ERROR_SUCCESS, "NetrJobEnum error %u (%#x)\n", ret, ret);
+        ok(total != 0, "total %u\n", total);
+        ok(start_index == 0, "start_index %u\n", start_index);
+        ok(container.Buffer != NULL, "Buffer %p\n", container.Buffer);
+        ok(container.EntriesRead != 0, "EntriesRead %u\n", container.EntriesRead);
+
+        found = FALSE;
+
+        for (i = 0; i < container.EntriesRead; i++)
+        {
+            AT_INFO *info2;
+
+            trace("%u: jobid %u, command %s\n", i, container.Buffer[i].JobId, wine_dbgstr_w(container.Buffer[i].Command));
+
+            if (container.Buffer[i].JobId == jobid ||
+                !lstrcmpW(container.Buffer[i].Command, task1W))
+            {
+                found = TRUE;
+                trace("found %u: jobid %u, command %s\n", i, container.Buffer[i].JobId, wine_dbgstr_w(container.Buffer[i].Command));
+            }
+
+            info2 = NULL;
+            ret = NetrJobGetInfo(server_name, container.Buffer[i].JobId, &info2);
+            ok(ret == ERROR_SUCCESS, "NetrJobGetInfo error %u\n", ret);
+
+            ok(container.Buffer[i].JobTime == info2->JobTime, "%u != %u\n", (UINT)container.Buffer[i].JobTime, (UINT)info2->JobTime);
+            ok(container.Buffer[i].DaysOfMonth == info2->DaysOfMonth, "%u != %u\n", container.Buffer[i].DaysOfMonth, info2->DaysOfMonth);
+            ok(container.Buffer[i].DaysOfWeek == info2->DaysOfWeek, "%u != %u\n", container.Buffer[i].DaysOfWeek, info2->DaysOfWeek);
+            ok(container.Buffer[i].Flags == info2->Flags, "%#x != %#x\n", container.Buffer[i].Flags, info2->Flags);
+            ok(!lstrcmpW(container.Buffer[i].Command, info2->Command), "%s != %s\n", wine_dbgstr_w(container.Buffer[i].Command), wine_dbgstr_w(info2->Command));
+
+            MIDL_user_free(container.Buffer[i].Command);
+            MIDL_user_free(info2->Command);
+            MIDL_user_free(info2);
+        }
+
+        if (found)
+            break;
+    }
+
+    MIDL_user_free(container.Buffer);
+
+    ok(found, "just added jobid %u should be found\n", jobid);
+
+skip_tests_delete:
+    ret = NetrJobDel(server_name, jobid, jobid);
+    ok(ret == ERROR_SUCCESS, "NetrJobDel error %u\n", ret);
+
+skip_tests:
+    SetUnhandledExceptionFilter(old_exception_filter);
+
+    hr = RpcBindingFree(&rpc_handle);
+    ok(hr == RPC_S_OK, "RpcBindingFree error %#x\n", hr);
+}
+
+DECLSPEC_HIDDEN handle_t __RPC_USER ATSVC_HANDLE_bind(ATSVC_HANDLE str)
+{
+    static unsigned char ncalrpc[] = "ncalrpc";
+    unsigned char *binding_str;
+    handle_t rpc_handle;
+    HRESULT hr;
+
+    hr = RpcStringBindingComposeA(NULL, ncalrpc, NULL, NULL, NULL, &binding_str);
+    ok(hr == RPC_S_OK, "RpcStringBindingCompose error %#x\n", hr);
+
+    hr = RpcBindingFromStringBindingA(binding_str, &rpc_handle);
+    ok(hr == RPC_S_OK, "RpcBindingFromStringBinding error %#x\n", hr);
+
+    RpcStringFreeA(&binding_str);
+    return rpc_handle;
+}
+
+DECLSPEC_HIDDEN void __RPC_USER ATSVC_HANDLE_unbind(ATSVC_HANDLE ServerName, handle_t rpc_handle)
+{
+    RpcBindingFree(&rpc_handle);
+}
diff --git a/include/lmat.h b/include/lmat.h
index da9691a668..0fa574f41a 100644
--- a/include/lmat.h
+++ b/include/lmat.h
@@ -25,6 +25,34 @@
 extern "C" {
 #endif
 
+#define JOB_RUN_PERIODICALLY 0x01
+#define JOB_EXEC_ERROR       0x02
+#define JOB_RUNS_TODAY       0x04
+#define JOB_ADD_CURRENT_DATE 0x08
+#define JOB_NONINTERACTIVE   0x10
+
+#define JOB_INPUT_FLAGS (JOB_RUN_PERIODICALLY | JOB_ADD_CURRENT_DATE | JOB_NONINTERACTIVE)
+#define JOB_OUTPUT_FLAGS (JOB_RUN_PERIODICALLY | JOB_EXEC_ERROR | JOB_RUNS_TODAY | JOB_NONINTERACTIVE)
+
+typedef struct _AT_INFO
+{
+    DWORD_PTR JobTime;
+    DWORD DaysOfMonth;
+    UCHAR DaysOfWeek;
+    UCHAR Flags;
+    LPWSTR Command;
+} AT_INFO, *PAT_INFO, *LPAT_INFO;
+
+typedef struct _AT_ENUM
+{
+    DWORD JobId;
+    DWORD_PTR JobTime;
+    DWORD DaysOfMonth;
+    UCHAR DaysOfWeek;
+    UCHAR Flags;
+    LPWSTR Command;
+} AT_ENUM, *PAT_ENUM, *LPAT_ENUM;
+
 NET_API_STATUS WINAPI NetScheduleJobAdd(LPCWSTR,LPBYTE,LPDWORD);
 NET_API_STATUS WINAPI NetScheduleJobDel(LPCWSTR,DWORD,DWORD);
 NET_API_STATUS WINAPI NetScheduleJobEnum(LPCWSTR,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD);
-- 
2.16.3




More information about the wine-devel mailing list