* Deleting tasks & folders requires elevated privileges on Windows 7. * Document SchRpcGetTaskInfo() calls that crash on Windows. * Use a winetest context in the rpcapi loops. * Use wide character string literals in rpcapi.c. * Use __HRESULT_FROM_WIN32() to initialize constants.
From: Francois Gouget fgouget@codeweavers.com
It is a macro and thus constant unlike HRESULT_FROM_WIN32(). --- dlls/schedsvc/tests/rpcapi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/schedsvc/tests/rpcapi.c b/dlls/schedsvc/tests/rpcapi.c index 41182bb4fbe..84302f89141 100644 --- a/dlls/schedsvc/tests/rpcapi.c +++ b/dlls/schedsvc/tests/rpcapi.c @@ -65,7 +65,7 @@ START_TEST(rpcapi) { { 0, S_OK }, { TASK_CREATE, S_OK }, - { TASK_UPDATE, 0x80070002 /* HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) */ }, + { TASK_UPDATE, __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) }, { TASK_CREATE | TASK_UPDATE, S_OK } }; static const struct @@ -73,8 +73,8 @@ START_TEST(rpcapi) DWORD flags, hr; } open_existing_task[] = { - { 0, 0x800700b7 /* HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) */ }, - { TASK_CREATE, 0x800700b7 /* HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) */ }, + { 0, __HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) }, + { TASK_CREATE, __HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) }, { TASK_UPDATE, S_OK }, { TASK_CREATE | TASK_UPDATE, S_OK } };
From: Francois Gouget fgouget@codeweavers.com
--- dlls/schedsvc/tests/rpcapi.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/dlls/schedsvc/tests/rpcapi.c b/dlls/schedsvc/tests/rpcapi.c index 84302f89141..cf160108c05 100644 --- a/dlls/schedsvc/tests/rpcapi.c +++ b/dlls/schedsvc/tests/rpcapi.c @@ -42,8 +42,8 @@ static LONG CALLBACK rpc_exception_filter(EXCEPTION_POINTERS *ptrs) START_TEST(rpcapi) { static unsigned char ncalrpc[] = "ncalrpc"; - static const char xml1[] = - "<?xml version=\"1.0\"?>\n" + static const WCHAR* xml1 = + L"<?xml version=\"1.0\"?>\n" "<Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task%5C%22%3E%5Cn" " <RegistrationInfo>\n" " <Description>"Task1"</Description>\n" @@ -78,7 +78,7 @@ START_TEST(rpcapi) { TASK_UPDATE, S_OK }, { TASK_CREATE | TASK_UPDATE, S_OK } }; - WCHAR xmlW[sizeof(xml1)], *xml; + WCHAR *xml; HRESULT hr; DWORD version, start_index, count, i, enumed, enabled, state; WCHAR *path; @@ -146,11 +146,9 @@ START_TEST(rpcapi) hr = SchRpcCreateFolder(L"\Wine", NULL, 0); ok(hr == S_OK, "expected S_OK, got %#lx\n", hr);
- MultiByteToWideChar(CP_ACP, 0, xml1, -1, xmlW, ARRAY_SIZE(xmlW)); - path = NULL; info = NULL; - hr = SchRpcRegisterTask(L"Wine", xmlW, TASK_VALIDATE_ONLY, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); + hr = SchRpcRegisterTask(L"Wine", xml1, TASK_VALIDATE_ONLY, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == S_OK, "expected S_OK, got %#lx\n", hr); ok(!path, "expected NULL, path %p\n", path); ok(!info, "expected NULL, info %p\n", info); @@ -159,7 +157,7 @@ START_TEST(rpcapi) { path = NULL; info = NULL; - hr = SchRpcRegisterTask(L"\Wine\Task1", xmlW, create_new_task[i].flags, NULL, + hr = SchRpcRegisterTask(L"\Wine\Task1", xml1, create_new_task[i].flags, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == create_new_task[i].hr, "%lu: expected %#lx, got %#lx\n", i, create_new_task[i].hr, hr);
@@ -174,21 +172,21 @@ START_TEST(rpcapi)
path = NULL; info = NULL; - hr = SchRpcRegisterTask(L"\Wine\Task1", xmlW, TASK_VALIDATE_ONLY, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); + hr = SchRpcRegisterTask(L"\Wine\Task1", xml1, TASK_VALIDATE_ONLY, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == S_OK, "expected S_OK, got %#lx\n", hr); ok(!path, "expected NULL, path %p\n", path); ok(!info, "expected NULL, info %p\n", info);
path = NULL; info = NULL; - hr = SchRpcRegisterTask(NULL, xmlW, TASK_VALIDATE_ONLY, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); + hr = SchRpcRegisterTask(NULL, xml1, TASK_VALIDATE_ONLY, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == S_OK, "expected S_OK, got %#lx\n", hr); ok(!path, "expected NULL, path %p\n", path); ok(!info, "expected NULL, info %p\n", info);
path = NULL; info = NULL; - hr = SchRpcRegisterTask(L"Wine\Folder1\Task1", xmlW, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); + hr = SchRpcRegisterTask(L"Wine\Folder1\Task1", xml1, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == S_OK, "expected S_OK, got %#lx\n", hr); ok(!lstrcmpW(path, L"\Wine\Folder1\Task1") /* win7 */ || !lstrcmpW(path, L"Wine\Folder1\Task1") /* vista */, "expected \Wine\Folder1\Task1, task actual path %s\n", wine_dbgstr_w(path)); @@ -199,7 +197,7 @@ START_TEST(rpcapi) { path = NULL; info = NULL; - hr = SchRpcRegisterTask(L"Wine\Folder1\Task1", xmlW, open_existing_task[i].flags, NULL, + hr = SchRpcRegisterTask(L"Wine\Folder1\Task1", xml1, open_existing_task[i].flags, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == open_existing_task[i].hr, "%lu: expected %#lx, got %#lx\n", i, open_existing_task[i].hr, hr); if (hr == S_OK) @@ -216,7 +214,7 @@ START_TEST(rpcapi)
path = NULL; info = NULL; - hr = SchRpcRegisterTask(L"Wine\Folder1\Task1", xmlW, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); + hr = SchRpcRegisterTask(L"Wine\Folder1\Task1", xml1, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS), "expected ERROR_ALREADY_EXISTS, got %#lx\n", hr); ok(!path, "expected NULL, path %p\n", path); ok(!info, "expected NULL, info %p\n", info); @@ -358,7 +356,7 @@ START_TEST(rpcapi)
path = NULL; info = NULL; - hr = SchRpcRegisterTask(L"Wine\Task1", xmlW, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); + hr = SchRpcRegisterTask(L"Wine\Task1", xml1, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == S_OK, "expected S_OK, got %#lx\n", hr); ok(!lstrcmpW(path, L"\Wine\Task1") /* win7 */ || !lstrcmpW(path, L"Wine\Task1") /* vista */, "expected \Wine\Task1, task actual path %s\n", wine_dbgstr_w(path)); @@ -367,7 +365,7 @@ START_TEST(rpcapi)
path = NULL; info = NULL; - hr = SchRpcRegisterTask(L"\Wine\Task2", xmlW, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); + hr = SchRpcRegisterTask(L"\Wine\Task2", xml1, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == S_OK, "expected S_OK, got %#lx\n", hr); ok(!lstrcmpW(path, L"\Wine\Task2"), "expected \Wine\Task2, task actual path %s\n", wine_dbgstr_w(path)); ok(!info, "expected NULL, info %p\n", info); @@ -449,7 +447,7 @@ START_TEST(rpcapi)
path = NULL; info = NULL; - hr = SchRpcRegisterTask(L"Wine\Task3", xmlW, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); + hr = SchRpcRegisterTask(L"Wine\Task3", xml1, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == S_OK, "expected S_OK, got %#lx\n", hr); ok(!lstrcmpW(path, L"\Wine\Task3") /* win7 */ || !lstrcmpW(path, L"Wine\Task3") /* vista */, "expected \Wine\Task3, task actual path %s\n", wine_dbgstr_w(path)); @@ -515,7 +513,7 @@ START_TEST(rpcapi)
path = NULL; info = NULL; - hr = SchRpcRegisterTask(NULL, xmlW, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); + hr = SchRpcRegisterTask(NULL, xml1, TASK_CREATE, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); ok(hr == S_OK || hr == E_ACCESSDENIED, "expected S_OK, got %#lx\n", hr); if (hr != E_ACCESSDENIED) {
From: Francois Gouget fgouget@codeweavers.com
--- dlls/schedsvc/tests/rpcapi.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/schedsvc/tests/rpcapi.c b/dlls/schedsvc/tests/rpcapi.c index cf160108c05..0142b1af88a 100644 --- a/dlls/schedsvc/tests/rpcapi.c +++ b/dlls/schedsvc/tests/rpcapi.c @@ -155,6 +155,7 @@ START_TEST(rpcapi)
for (i = 0; i < ARRAY_SIZE(create_new_task); i++) { + winetest_push_context("%lu", i); path = NULL; info = NULL; hr = SchRpcRegisterTask(L"\Wine\Task1", xml1, create_new_task[i].flags, NULL, @@ -168,6 +169,7 @@ START_TEST(rpcapi) ok(!info, "expected NULL, info %p\n", info); MIDL_user_free(path); } + winetest_pop_context(); }
path = NULL; @@ -195,11 +197,12 @@ START_TEST(rpcapi)
for (i = 0; i < ARRAY_SIZE(open_existing_task); i++) { + winetest_push_context("%lu", i); path = NULL; info = NULL; hr = SchRpcRegisterTask(L"Wine\Folder1\Task1", xml1, open_existing_task[i].flags, NULL, TASK_LOGON_NONE, 0, NULL, &path, &info); - ok(hr == open_existing_task[i].hr, "%lu: expected %#lx, got %#lx\n", i, open_existing_task[i].hr, hr); + ok(hr == open_existing_task[i].hr, "expected %#lx, got %#lx\n", open_existing_task[i].hr, hr); if (hr == S_OK) { ok(!lstrcmpW(path, L"\Wine\Folder1\Task1") /* win7 */ || @@ -208,8 +211,9 @@ START_TEST(rpcapi) MIDL_user_free(path); } else - ok(!path, "%lu: expected NULL, path %p\n", i, path); - ok(!info, "%lu: expected NULL, info %p\n", i, info); + ok(!path, "expected NULL, path %p\n", path); + ok(!info, "expected NULL, info %p\n", info); + winetest_pop_context(); }
path = NULL;
From: Francois Gouget fgouget@codeweavers.com
Not just Windows 7 but all versions up to Windows 11. --- And fittingly they all crash in Wine too. --- dlls/schedsvc/tests/rpcapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/schedsvc/tests/rpcapi.c b/dlls/schedsvc/tests/rpcapi.c index 0142b1af88a..b8742c1fd58 100644 --- a/dlls/schedsvc/tests/rpcapi.c +++ b/dlls/schedsvc/tests/rpcapi.c @@ -471,7 +471,7 @@ START_TEST(rpcapi) MIDL_user_free(names[0]); MIDL_user_free(names);
- if (0) /* crashes under win7 */ + if (0) /* each of these crashes on Windows 7 to 11 */ { hr = SchRpcGetTaskInfo(NULL, 0, NULL, NULL); hr = SchRpcGetTaskInfo(L"Task1", 0, NULL, NULL);
From: Francois Gouget fgouget@codeweavers.com
This means skipping any test that requires creating a folder as the test would be unable to clean up after itself.
Wine-Bug: https://bugs.winehq.org//show_bug.cgi?id=53128 Wine-Bug: https://bugs.winehq.org//show_bug.cgi?id=54109 --- dlls/schedsvc/tests/Makefile.in | 2 +- dlls/schedsvc/tests/rpcapi.c | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/dlls/schedsvc/tests/Makefile.in b/dlls/schedsvc/tests/Makefile.in index b8e7448bb76..62f41d4744f 100644 --- a/dlls/schedsvc/tests/Makefile.in +++ b/dlls/schedsvc/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = schedsvc.dll -IMPORTS = rpcrt4 ole32 +IMPORTS = advapi32 rpcrt4 ole32
C_SRCS = \ atsvcapi.c \ diff --git a/dlls/schedsvc/tests/rpcapi.c b/dlls/schedsvc/tests/rpcapi.c index b8742c1fd58..d9e2a75eb7b 100644 --- a/dlls/schedsvc/tests/rpcapi.c +++ b/dlls/schedsvc/tests/rpcapi.c @@ -18,6 +18,7 @@
#include <stdio.h> #include <windows.h> +#include "winternl.h" #include <ole2.h> #include <rpcdce.h> #include <taskschd.h> @@ -25,6 +26,37 @@
#include "wine/test.h"
+static BOOL is_process_elevated(void) +{ + HANDLE token; + if (OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &token )) + { + TOKEN_ELEVATION_TYPE type; + DWORD size; + BOOL ret; + + ret = GetTokenInformation( token, TokenElevationType, &type, sizeof(type), &size ); + CloseHandle( token ); + return (ret && type == TokenElevationTypeFull); + } + return FALSE; +} + +static BOOL check_win_version(int min_major, int min_minor) +{ + HMODULE hntdll = GetModuleHandleA("ntdll.dll"); + NTSTATUS (WINAPI *pRtlGetVersion)(RTL_OSVERSIONINFOEXW *); + RTL_OSVERSIONINFOEXW rtlver; + + rtlver.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); + pRtlGetVersion = (void *)GetProcAddress(hntdll, "RtlGetVersion"); + pRtlGetVersion(&rtlver); + return rtlver.dwMajorVersion > min_major || + (rtlver.dwMajorVersion == min_major && + rtlver.dwMinorVersion >= min_minor); +} +#define is_win8_plus() check_win_version(6, 2) + extern handle_t schrpc_handle;
static LONG CALLBACK rpc_exception_filter(EXCEPTION_POINTERS *ptrs) @@ -143,6 +175,12 @@ START_TEST(rpcapi) hr = SchRpcDelete(L"", 0); ok(hr == E_ACCESSDENIED /* win7 */ || hr == E_INVALIDARG /* vista */, "expected E_ACCESSDENIED, got %#lx\n", hr);
+ if (!is_process_elevated() && !is_win8_plus()) + { + win_skip("Skipping because deleting anything requires elevated privileges on Windows 7\n"); + return; + } + hr = SchRpcCreateFolder(L"\Wine", NULL, 0); ok(hr == S_OK, "expected S_OK, got %#lx\n", hr);