mirror of
https://github.com/reactos/reactos.git
synced 2024-09-01 00:03:39 +00:00
![Mark Jansen](/assets/img/avatar_default.png)
- Add a missing file - Add convenience targets for MSVC_IDE - Remove whitespace at the end of the lines
413 lines
19 KiB
C
413 lines
19 KiB
C
/*
|
|
* PROJECT: ReactOS api tests
|
|
* LICENSE: GPLv2+ - See COPYING in the top level directory
|
|
* PURPOSE: Test for RtlDosApplyFileIsolationRedirection_Ustr
|
|
* PROGRAMMER: Giannis Adamopoulos
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#define ok_eq_hex(value, expected) ok((value) == (expected), #value " = 0x%lx, expected 0x%lx\n", value, expected)
|
|
#define ok_eq_pointer(value, expected) ok((value) == (expected), #value " = %p, expected %p\n", value, expected)
|
|
|
|
#define EXPECT_IN_SAME_DIR (WCHAR*)0xdead
|
|
|
|
UNICODE_STRING DotDll = RTL_CONSTANT_STRING(L".DLL");
|
|
|
|
struct test_data
|
|
{
|
|
int testline;
|
|
NTSTATUS ExpectedStatus;
|
|
WCHAR* Param;
|
|
WCHAR* ExpectedSubString;
|
|
};
|
|
|
|
struct test_data Tests[] =
|
|
{
|
|
/* Not redirected file */
|
|
{__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"somefilesomefile", NULL},
|
|
{__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"ntdll.dll", NULL},
|
|
/* Files redirected with sxs */
|
|
{__LINE__, STATUS_SUCCESS, L"GDIPLUS", L"\\winsxs\\x86_microsoft.windows.gdiplus_6595b64144ccf1df_1."},
|
|
{__LINE__, STATUS_SUCCESS, L"GDIPLUS.DLL", L"\\winsxs\\x86_microsoft.windows.gdiplus_6595b64144ccf1df_1."},
|
|
{__LINE__, STATUS_SUCCESS, L"COMCTL32.DLL", L"\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82"},
|
|
{__LINE__, STATUS_SUCCESS, L"comctl32.DLL", L"\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82"},
|
|
{__LINE__, STATUS_SUCCESS, L"c:\\windows\\system32\\comctl32.DLL", L"\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82"},
|
|
/* Files not redirected with sxs */
|
|
{__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"MSVCR90.DLL", NULL},
|
|
{__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"c:\\windows\\system32\\MSVCR90.DLL", NULL},
|
|
/* Files defined in the manifest, one exists, one doesn't */
|
|
{__LINE__, STATUS_SUCCESS, L"deptest.dll", EXPECT_IN_SAME_DIR},
|
|
{__LINE__, STATUS_SUCCESS, L"adllfile.dll", EXPECT_IN_SAME_DIR},
|
|
/* A file that exists in the same dir but isn't mentioned in the manifest */
|
|
{__LINE__, STATUS_SUCCESS, L"fil1.txt", EXPECT_IN_SAME_DIR},
|
|
/* This is a weird case; the source doesn't exist but does get redirected */
|
|
{__LINE__, STATUS_SUCCESS, L"c:\\windows\\system32\\gdiplus.DLL", L"\\winsxs\\x86_microsoft.windows.gdiplus_6595b64144ccf1df_1."},
|
|
/* But redirecting gdiplus from a different directory doesn't work */
|
|
{__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"c:\\GDIPLUS.DLL", NULL},
|
|
{__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"c:\\comctl32.DLL", NULL},
|
|
/* Redirection based on .local */
|
|
{__LINE__, STATUS_SUCCESS, L"test", EXPECT_IN_SAME_DIR},
|
|
{__LINE__, STATUS_SUCCESS, L"test.dll", EXPECT_IN_SAME_DIR},
|
|
{__LINE__, STATUS_SUCCESS, L"c:\\test.dll", EXPECT_IN_SAME_DIR},
|
|
/* known dlls are also covered */
|
|
{__LINE__, STATUS_SUCCESS, L"shell32", EXPECT_IN_SAME_DIR},
|
|
{__LINE__, STATUS_SUCCESS, L"shell32.dll", EXPECT_IN_SAME_DIR},
|
|
{__LINE__, STATUS_SUCCESS, L"c:\\shell32.dll", EXPECT_IN_SAME_DIR}
|
|
};
|
|
|
|
HANDLE _CreateActCtxFromFile(LPCWSTR FileName, int line)
|
|
{
|
|
ACTCTXW ActCtx = {sizeof(ACTCTX)};
|
|
HANDLE h;
|
|
WCHAR buffer[MAX_PATH] , *separator;
|
|
|
|
ok (GetModuleFileNameW(NULL, buffer, MAX_PATH), "GetModuleFileName failed\n");
|
|
separator = wcsrchr(buffer, L'\\');
|
|
if (separator)
|
|
wcscpy(separator + 1, FileName);
|
|
|
|
ActCtx.lpSource = buffer;
|
|
|
|
SetLastError(0xdeaddead);
|
|
h = CreateActCtxW(&ActCtx);
|
|
ok_(__FILE__, line)(h != INVALID_HANDLE_VALUE, "CreateActCtx failed for %S\n", FileName);
|
|
// In win10 last error is unchanged and in win2k3 it is ERROR_BAD_EXE_FORMAT
|
|
ok_(__FILE__, line)(GetLastError() == ERROR_BAD_EXE_FORMAT || GetLastError() == 0xdeaddead, "Wrong last error %lu\n", GetLastError());
|
|
|
|
return h;
|
|
}
|
|
|
|
void TestRedirection(void)
|
|
{
|
|
WCHAR SystemDir[MAX_PATH];
|
|
WCHAR TestPath[MAX_PATH];
|
|
WCHAR ParameterBuffer[MAX_PATH];
|
|
WCHAR* separator;
|
|
NTSTATUS Status;
|
|
int i;
|
|
|
|
GetSystemDirectoryW(SystemDir, MAX_PATH);
|
|
GetModuleFileNameW(NULL, TestPath, MAX_PATH);
|
|
separator = wcsrchr(TestPath, L'\\');
|
|
separator++;
|
|
*separator = 0;
|
|
|
|
for (i = 0; i < _countof(Tests); i ++)
|
|
{
|
|
UNICODE_STRING OriginalName, DynamicString;
|
|
PUNICODE_STRING StringUsed = NULL;
|
|
|
|
if (memcmp(Tests[i].Param, L"c:\\windows\\system32", 38) == 0)
|
|
{
|
|
wcscpy(ParameterBuffer, SystemDir);
|
|
wcscat(ParameterBuffer, &Tests[i].Param[19]);
|
|
}
|
|
else
|
|
{
|
|
wcscpy(ParameterBuffer, Tests[i].Param);
|
|
}
|
|
|
|
RtlInitUnicodeString(&OriginalName, ParameterBuffer);
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&OriginalName,
|
|
&DotDll,
|
|
NULL,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status == Tests[i].ExpectedStatus, "%d: Status 0x%lx, expected 0x%lx\n", Tests[i].testline, Status, Tests[i].ExpectedStatus);
|
|
|
|
if(Tests[i].ExpectedSubString && DynamicString.Buffer == NULL)
|
|
{
|
|
ok(0, "%d: Expected a returned string\n", Tests[i].testline);
|
|
}
|
|
|
|
if (Tests[i].ExpectedSubString && DynamicString.Buffer != NULL)
|
|
{
|
|
if (Tests[i].ExpectedSubString == EXPECT_IN_SAME_DIR)
|
|
{
|
|
ok(wcsstr(DynamicString.Buffer, TestPath) != 0, "%d: Expected string %S in %S\n", Tests[i].testline, TestPath, DynamicString.Buffer);
|
|
}
|
|
else
|
|
{
|
|
RtlDowncaseUnicodeString(&DynamicString, &DynamicString, FALSE);
|
|
ok(wcsstr(DynamicString.Buffer, Tests[i].ExpectedSubString) != 0, "%d: Expected string %S in %S\n", Tests[i].testline, Tests[i].ExpectedSubString, DynamicString.Buffer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TestBuffers()
|
|
{
|
|
UNICODE_STRING Param, DynamicString, StaticString;
|
|
PUNICODE_STRING StringUsed = NULL;
|
|
NTSTATUS Status;
|
|
WCHAR buffer[MAX_PATH];
|
|
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_INVALID_PARAMETER, "0x%lx\n", Status);
|
|
|
|
RtlInitEmptyUnicodeString(&Param, NULL, 0);
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
NULL,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%lx\n", Status);
|
|
|
|
/* Tests for NULL termination of OriginalName */
|
|
Param.MaximumLength = Param.Length = 12 * sizeof(WCHAR);
|
|
Param.Buffer = L"comctl32.dllcrapcrap";
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
NULL,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SUCCESS, "\n");
|
|
|
|
/* Tests for the Extension parameter */
|
|
RtlInitUnicodeString(&Param, L"comctl32.dll");
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
NULL,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SUCCESS, "\n");
|
|
|
|
RtlInitUnicodeString(&Param, L"comctl32");
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
NULL,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%lx\n", Status);
|
|
|
|
RtlInitUnicodeString(&Param, L"comctl32");
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
&DotDll,
|
|
NULL,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SUCCESS, "\n");
|
|
|
|
/* Tests for the DynamicString parameter */
|
|
RtlInitUnicodeString(&Param, L"comctl32.dll");
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
NULL,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SUCCESS, "\n");
|
|
ok(DynamicString.Length >0 , "\n");
|
|
ok(DynamicString.MaximumLength == DynamicString.Length + sizeof(WCHAR) , "\n");
|
|
if (DynamicString.Buffer && DynamicString.Length)
|
|
ok(wcslen(DynamicString.Buffer) * sizeof(WCHAR) == DynamicString.Length, "got %d and %d\n", wcslen(DynamicString.Buffer) * sizeof(WCHAR) , DynamicString.Length);
|
|
else
|
|
ok(DynamicString.Buffer != NULL, "Expected non NULL buffer\n");
|
|
ok(StringUsed == &DynamicString, "\n");
|
|
|
|
/* Tests for the StaticString parameter */
|
|
wcscpy(buffer, L"comctl32.dll");
|
|
StaticString.Buffer = buffer;
|
|
StaticString.Length = sizeof(L"comctl32.dll");
|
|
StaticString.MaximumLength = sizeof(buffer);
|
|
Param = StaticString;
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
&StaticString,
|
|
NULL,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%lx\n", Status);
|
|
|
|
wcscpy(buffer, L"comctl32.dll");
|
|
StaticString.Buffer = buffer;
|
|
StaticString.Length = sizeof(L"comctl32.dll");
|
|
StaticString.MaximumLength = sizeof(buffer);
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&StaticString,
|
|
NULL,
|
|
&StaticString,
|
|
NULL,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%lx\n", Status);
|
|
|
|
RtlInitUnicodeString(&Param, L"comctl32.dll");
|
|
RtlInitEmptyUnicodeString(&StaticString, buffer, sizeof(buffer));
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
&StaticString,
|
|
NULL,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SUCCESS, "\n");
|
|
ok(StaticString.Length >0 , "\n");
|
|
ok(StaticString.MaximumLength == sizeof(buffer) , "\n");
|
|
if (StaticString.Buffer && StaticString.Length)
|
|
ok(wcslen(StaticString.Buffer) * sizeof(WCHAR) == StaticString.Length, "got %d and %d\n", wcslen(StaticString.Buffer) * sizeof(WCHAR) , StaticString.Length);
|
|
else
|
|
ok(StaticString.Length != 0, "Expected non 0 lenght\n");
|
|
ok(StringUsed == &StaticString, "\n");
|
|
|
|
RtlInitEmptyUnicodeString(&StaticString, buffer, 5 * sizeof(WCHAR));
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
&StaticString,
|
|
NULL,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status == STATUS_BUFFER_TOO_SMALL, "0x%lx\n", Status);
|
|
|
|
RtlInitUnicodeString(&Param, L"comctl32.dll");
|
|
RtlInitEmptyUnicodeString(&StaticString, buffer, sizeof(buffer));
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
&StaticString,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SUCCESS, "\n");
|
|
ok(StaticString.Length >0 , "\n");
|
|
ok(StaticString.MaximumLength == sizeof(buffer) , "\n");
|
|
if (StaticString.Buffer && StaticString.Length)
|
|
ok(wcslen(StaticString.Buffer) * sizeof(WCHAR) == StaticString.Length, "got %d and %d\n", wcslen(StaticString.Buffer) * sizeof(WCHAR) , StaticString.Length);
|
|
else
|
|
ok(StaticString.Length != 0, "Expected non 0 lenght\n");
|
|
ok(DynamicString.Buffer == NULL, "\n");
|
|
ok(DynamicString.Length == 0, "\n");
|
|
ok(DynamicString.MaximumLength == 0, "\n");
|
|
ok(StringUsed == &StaticString, "\n");
|
|
|
|
/* Test a small buffer and a dynamic buffer */
|
|
RtlInitUnicodeString(&Param, L"comctl32.dll");
|
|
RtlInitEmptyUnicodeString(&StaticString, buffer, 5 * sizeof(WCHAR));
|
|
RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
|
|
StaticString.Buffer[0] = 1;
|
|
Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
&Param,
|
|
NULL,
|
|
&StaticString,
|
|
&DynamicString,
|
|
&StringUsed,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
ok(Status ==STATUS_SUCCESS, "\n");
|
|
ok(StaticString.Buffer == buffer, "\n");
|
|
ok(StaticString.Length == 0 , "%d\n", StaticString.Length);
|
|
ok(StaticString.Buffer[0] == 0, "\n");
|
|
ok(StaticString.MaximumLength == 5 * sizeof(WCHAR) , "%d\n", StaticString.MaximumLength);
|
|
ok(DynamicString.Length >0 , "\n");
|
|
ok(DynamicString.MaximumLength == DynamicString.Length + sizeof(WCHAR) , "\n");
|
|
if (DynamicString.Buffer && DynamicString.Length)
|
|
ok(wcslen(DynamicString.Buffer) * sizeof(WCHAR) == DynamicString.Length, "got %d and %d\n", wcslen(DynamicString.Buffer) * sizeof(WCHAR) , DynamicString.Length);
|
|
else
|
|
ok(DynamicString.Length != 0, "Expected non 0 lenght\n");
|
|
|
|
ok(StringUsed == &DynamicString, "\n");
|
|
}
|
|
|
|
START_TEST(RtlDosApplyFileIsolationRedirection_Ustr)
|
|
{
|
|
int argc;
|
|
char **test_argv;
|
|
argc = winetest_get_mainargs( &test_argv );
|
|
if (argc >= 3)
|
|
{
|
|
HANDLE h = _CreateActCtxFromFile(L"ntdlltest.manifest", __LINE__);
|
|
BOOL bactivated = FALSE;
|
|
ULONG_PTR cookie;
|
|
|
|
if (h != INVALID_HANDLE_VALUE)
|
|
bactivated = ActivateActCtx(h, &cookie);
|
|
|
|
TestRedirection();
|
|
TestBuffers();
|
|
|
|
if (bactivated)
|
|
DeactivateActCtx(0, cookie);
|
|
}
|
|
else
|
|
{
|
|
WCHAR TestPath[MAX_PATH];
|
|
WCHAR* separator;
|
|
STARTUPINFOW si = { sizeof(si) };
|
|
PROCESS_INFORMATION pi;
|
|
BOOL created;
|
|
|
|
GetModuleFileNameW(NULL, TestPath, MAX_PATH);
|
|
separator = wcsrchr(TestPath, L'\\');
|
|
separator++;
|
|
wcscpy(separator, L"testdata\\ntdll_apitest.exe RtlDosApplyFileIsolationRedirection_Ustr DoTest");
|
|
|
|
created = CreateProcessW(NULL, TestPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
|
|
ok(created, "Expected CreateProcess to succeed\n");
|
|
if (created)
|
|
{
|
|
winetest_wait_child_process(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
}
|
|
}
|
|
}
|