summaryrefslogtreecommitdiffstats
path: root/toolkit/xre/test/win
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/xre/test/win')
-rw-r--r--toolkit/xre/test/win/Makefile.in14
-rw-r--r--toolkit/xre/test/win/TestDllInterceptor.cpp237
-rw-r--r--toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp265
-rw-r--r--toolkit/xre/test/win/TestXREMakeCommandLineWin.ini94
-rw-r--r--toolkit/xre/test/win/moz.build30
5 files changed, 640 insertions, 0 deletions
diff --git a/toolkit/xre/test/win/Makefile.in b/toolkit/xre/test/win/Makefile.in
new file mode 100644
index 000000000..331a8a4fd
--- /dev/null
+++ b/toolkit/xre/test/win/Makefile.in
@@ -0,0 +1,14 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+MOZ_WINCONSOLE = 1
+
+include $(topsrcdir)/config/rules.mk
+
+libs:: TestXREMakeCommandLineWin.ini
+ $(INSTALL) $^ $(FINAL_TARGET)/
+
+check::
+ @echo 'Running TestXREMakeCommandLineWin tests'
+ @$(RUN_TEST_PROGRAM) $(FINAL_TARGET)/TestXREMakeCommandLineWin.exe
diff --git a/toolkit/xre/test/win/TestDllInterceptor.cpp b/toolkit/xre/test/win/TestDllInterceptor.cpp
new file mode 100644
index 000000000..dff71817f
--- /dev/null
+++ b/toolkit/xre/test/win/TestDllInterceptor.cpp
@@ -0,0 +1,237 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if _WIN32_WINNT < 0x0600
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#endif
+
+#include <shlobj.h>
+#include <stdio.h>
+
+#include "mozilla/WindowsVersion.h"
+#include "nsWindowsDllInterceptor.h"
+#include "nsWindowsHelpers.h"
+
+using namespace mozilla;
+
+struct payload {
+ UINT64 a;
+ UINT64 b;
+ UINT64 c;
+
+ bool operator==(const payload &other) const {
+ return (a == other.a &&
+ b == other.b &&
+ c == other.c);
+ }
+};
+
+extern "C" __declspec(dllexport) __declspec(noinline) payload rotatePayload(payload p) {
+ UINT64 tmp = p.a;
+ p.a = p.b;
+ p.b = p.c;
+ p.c = tmp;
+ return p;
+}
+
+static bool patched_func_called = false;
+
+static payload (*orig_rotatePayload)(payload);
+
+static payload
+patched_rotatePayload(payload p)
+{
+ patched_func_called = true;
+ return orig_rotatePayload(p);
+}
+
+bool TestHook(const char *dll, const char *func)
+{
+ void *orig_func;
+ bool successful = false;
+ {
+ WindowsDllInterceptor TestIntercept;
+ TestIntercept.Init(dll);
+ successful = TestIntercept.AddHook(func, 0, &orig_func);
+ }
+
+ if (successful) {
+ printf("TEST-PASS | WindowsDllInterceptor | Could hook %s from %s\n", func, dll);
+ return true;
+ } else {
+ printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to hook %s from %s\n", func, dll);
+ return false;
+ }
+}
+
+bool TestDetour(const char *dll, const char *func)
+{
+ void *orig_func;
+ bool successful = false;
+ {
+ WindowsDllInterceptor TestIntercept;
+ TestIntercept.Init(dll);
+ successful = TestIntercept.AddDetour(func, 0, &orig_func);
+ }
+
+ if (successful) {
+ printf("TEST-PASS | WindowsDllInterceptor | Could detour %s from %s\n", func, dll);
+ return true;
+ } else {
+ printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to detour %s from %s\n", func, dll);
+ return false;
+ }
+}
+
+bool MaybeTestHook(const bool cond, const char* dll, const char* func)
+{
+ if (!cond) {
+ return true;
+ }
+
+ return TestHook(dll, func);
+}
+
+bool ShouldTestTipTsf()
+{
+#if defined(_M_X64)
+ return false;
+#else
+ if (!IsWin8OrLater()) {
+ return false;
+ }
+
+ nsModuleHandle shell32(LoadLibraryW(L"shell32.dll"));
+ if (!shell32) {
+ return true;
+ }
+
+ auto pSHGetKnownFolderPath = reinterpret_cast<decltype(&SHGetKnownFolderPath)>(GetProcAddress(shell32, "SHGetKnownFolderPath"));
+ if (!pSHGetKnownFolderPath) {
+ return true;
+ }
+
+ PWSTR commonFilesPath = nullptr;
+ if (FAILED(pSHGetKnownFolderPath(FOLDERID_ProgramFilesCommon, 0, nullptr,
+ &commonFilesPath))) {
+ return true;
+ }
+
+ wchar_t fullPath[MAX_PATH + 1] = {};
+ wcscpy(fullPath, commonFilesPath);
+ wcscat(fullPath, L"\\Microsoft Shared\\Ink\\tiptsf.dll");
+ CoTaskMemFree(commonFilesPath);
+
+ if (!LoadLibraryW(fullPath)) {
+ return false;
+ }
+
+ // Leak the module so that it's loaded for the interceptor test
+ return true;
+#endif
+}
+
+int main()
+{
+ payload initial = { 0x12345678, 0xfc4e9d31, 0x87654321 };
+ payload p0, p1;
+ ZeroMemory(&p0, sizeof(p0));
+ ZeroMemory(&p1, sizeof(p1));
+
+ p0 = rotatePayload(initial);
+
+ {
+ WindowsDllInterceptor ExeIntercept;
+ ExeIntercept.Init("TestDllInterceptor.exe");
+ if (ExeIntercept.AddHook("rotatePayload", reinterpret_cast<intptr_t>(patched_rotatePayload), (void**) &orig_rotatePayload)) {
+ printf("TEST-PASS | WindowsDllInterceptor | Hook added\n");
+ } else {
+ printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to add hook\n");
+ return 1;
+ }
+
+ p1 = rotatePayload(initial);
+
+ if (patched_func_called) {
+ printf("TEST-PASS | WindowsDllInterceptor | Hook called\n");
+ } else {
+ printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Hook was not called\n");
+ return 1;
+ }
+
+ if (p0 == p1) {
+ printf("TEST-PASS | WindowsDllInterceptor | Hook works properly\n");
+ } else {
+ printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Hook didn't return the right information\n");
+ return 1;
+ }
+ }
+
+ patched_func_called = false;
+ ZeroMemory(&p1, sizeof(p1));
+
+ p1 = rotatePayload(initial);
+
+ if (!patched_func_called) {
+ printf("TEST-PASS | WindowsDllInterceptor | Hook was not called after unregistration\n");
+ } else {
+ printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Hook was still called after unregistration\n");
+ return 1;
+ }
+
+ if (p0 == p1) {
+ printf("TEST-PASS | WindowsDllInterceptor | Original function worked properly\n");
+ } else {
+ printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Original function didn't return the right information\n");
+ return 1;
+ }
+
+ if (TestHook("user32.dll", "GetWindowInfo") &&
+#ifdef _WIN64
+ TestHook("user32.dll", "SetWindowLongPtrA") &&
+ TestHook("user32.dll", "SetWindowLongPtrW") &&
+#else
+ TestHook("user32.dll", "SetWindowLongA") &&
+ TestHook("user32.dll", "SetWindowLongW") &&
+#endif
+ TestHook("user32.dll", "TrackPopupMenu") &&
+#ifdef _M_IX86
+ // We keep this test to hook complex code on x86. (Bug 850957)
+ TestHook("ntdll.dll", "NtFlushBuffersFile") &&
+#endif
+ TestHook("ntdll.dll", "NtCreateFile") &&
+ TestHook("ntdll.dll", "NtReadFile") &&
+ TestHook("ntdll.dll", "NtReadFileScatter") &&
+ TestHook("ntdll.dll", "NtWriteFile") &&
+ TestHook("ntdll.dll", "NtWriteFileGather") &&
+ TestHook("ntdll.dll", "NtQueryFullAttributesFile") &&
+ // Bug 733892: toolkit/crashreporter/nsExceptionHandler.cpp
+ TestHook("kernel32.dll", "SetUnhandledExceptionFilter") &&
+#ifdef _M_IX86
+ // Bug 670967: xpcom/base/AvailableMemoryTracker.cpp
+ TestHook("kernel32.dll", "VirtualAlloc") &&
+ TestHook("kernel32.dll", "MapViewOfFile") &&
+ TestHook("gdi32.dll", "CreateDIBSection") &&
+ TestHook("kernel32.dll", "CreateFileW") &&
+#endif
+ TestDetour("user32.dll", "CreateWindowExW") &&
+ TestHook("user32.dll", "InSendMessageEx") &&
+ TestHook("imm32.dll", "ImmGetContext") &&
+ TestHook("imm32.dll", "ImmGetCompositionStringW") &&
+ TestHook("imm32.dll", "ImmSetCandidateWindow") &&
+#ifdef _M_X64
+ TestHook("user32.dll", "GetKeyState") &&
+#endif
+ MaybeTestHook(ShouldTestTipTsf(), "tiptsf.dll", "ProcessCaretEvents") &&
+#ifdef _M_IX86
+ TestHook("user32.dll", "SendMessageTimeoutW") &&
+#endif
+ TestDetour("ntdll.dll", "LdrLoadDll")) {
+ printf("TEST-PASS | WindowsDllInterceptor | all checks passed\n");
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp b/toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp
new file mode 100644
index 000000000..00d786aa2
--- /dev/null
+++ b/toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+// Support for _setmode
+#include <fcntl.h>
+#include <io.h>
+
+#include "nsWindowsRestart.cpp"
+
+// CommandLineToArgvW may return different values for argv[0] since it contains
+// the path to the binary that was executed so we prepend an argument that is
+// quoted with a space to prevent argv[1] being appended to argv[0].
+#define DUMMY_ARG1 L"\"arg 1\" "
+
+#ifndef MAXPATHLEN
+# ifdef PATH_MAX
+# define MAXPATHLEN PATH_MAX
+# elif defined(MAX_PATH)
+# define MAXPATHLEN MAX_PATH
+# elif defined(_MAX_PATH)
+# define MAXPATHLEN _MAX_PATH
+# elif defined(CCHMAXPATH)
+# define MAXPATHLEN CCHMAXPATH
+# else
+# define MAXPATHLEN 1024
+# endif
+#endif
+
+#define TEST_NAME L"XRE MakeCommandLine"
+#define MAX_TESTS 100
+
+// Verbose output can be enabled by defining VERBOSE 1
+#define VERBOSE 0
+
+// Compares compareCmdLine with the output of MakeCommandLine. This is
+// accomplished by converting inCmdLine to an argument list with
+// CommandLineToArgvW and converting it back to a command line with
+// MakeCommandLine.
+static int
+verifyCmdLineCreation(wchar_t *inCmdLine,
+ wchar_t *compareCmdLine,
+ bool passes, int testNum)
+{
+ int rv = 0;
+ int i;
+ int inArgc;
+ int outArgc;
+ bool isEqual;
+
+ // When debugging with command lines containing Unicode characters greater
+ // than 255 you can set the mode for stdout to Unicode so the console will
+ // receive the correct characters though it won't display them properly unless
+ // the console's font has been set to one that can display the characters. You
+ // can also redirect the console output to a file that has been saved as Unicode
+ // to view the characters.
+// _setmode(_fileno(stdout), _O_WTEXT);
+
+ // Prepend an additional argument to the command line. CommandLineToArgvW
+ // handles argv[0] differently than other arguments since argv[0] is the path
+ // to the binary being executed and MakeCommandLine only handles argv[1] and
+ // larger.
+ wchar_t *inCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(inCmdLine) + 1) * sizeof(wchar_t));
+ wcscpy(inCmdLineNew, DUMMY_ARG1);
+ wcscat(inCmdLineNew, inCmdLine);
+ LPWSTR *inArgv = CommandLineToArgvW(inCmdLineNew, &inArgc);
+
+ wchar_t *outCmdLine = MakeCommandLine(inArgc - 1, inArgv + 1);
+ wchar_t *outCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(outCmdLine) + 1) * sizeof(wchar_t));
+ wcscpy(outCmdLineNew, DUMMY_ARG1);
+ wcscat(outCmdLineNew, outCmdLine);
+ LPWSTR *outArgv = CommandLineToArgvW(outCmdLineNew, &outArgc);
+
+ if (VERBOSE) {
+ wprintf(L"\n");
+ wprintf(L"Verbose Output\n");
+ wprintf(L"--------------\n");
+ wprintf(L"Input command line : >%s<\n", inCmdLine);
+ wprintf(L"MakeComandLine output: >%s<\n", outCmdLine);
+ wprintf(L"Expected command line: >%s<\n", compareCmdLine);
+
+ wprintf(L"input argc : %d\n", inArgc - 1);
+ wprintf(L"output argc: %d\n", outArgc - 1);
+
+ for (i = 1; i < inArgc; ++i) {
+ wprintf(L"input argv[%d] : >%s<\n", i - 1, inArgv[i]);
+ }
+
+ for (i = 1; i < outArgc; ++i) {
+ wprintf(L"output argv[%d]: >%s<\n", i - 1, outArgv[i]);
+ }
+ wprintf(L"\n");
+ }
+
+ isEqual = (inArgc == outArgc);
+ if (!isEqual) {
+ wprintf(L"TEST-%s-FAIL | %s | ARGC Comparison (check %2d)\n",
+ passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum);
+ if (passes) {
+ rv = 1;
+ }
+ LocalFree(inArgv);
+ LocalFree(outArgv);
+ free(inCmdLineNew);
+ free(outCmdLineNew);
+ free(outCmdLine);
+ return rv;
+ }
+
+ for (i = 1; i < inArgc; ++i) {
+ isEqual = (wcscmp(inArgv[i], outArgv[i]) == 0);
+ if (!isEqual) {
+ wprintf(L"TEST-%s-FAIL | %s | ARGV Comparison (check %2d)\n",
+ passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum);
+ if (passes) {
+ rv = 1;
+ }
+ LocalFree(inArgv);
+ LocalFree(outArgv);
+ free(inCmdLineNew);
+ free(outCmdLineNew);
+ free(outCmdLine);
+ return rv;
+ }
+ }
+
+ isEqual = (wcscmp(outCmdLine, compareCmdLine) == 0);
+ if (!isEqual) {
+ wprintf(L"TEST-%s-FAIL | %s | Command Line Comparison (check %2d)\n",
+ passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum);
+ if (passes) {
+ rv = 1;
+ }
+ LocalFree(inArgv);
+ LocalFree(outArgv);
+ free(inCmdLineNew);
+ free(outCmdLineNew);
+ free(outCmdLine);
+ return rv;
+ }
+
+ if (rv == 0) {
+ if (passes) {
+ wprintf(L"TEST-PASS | %s | check %2d\n", TEST_NAME, testNum);
+ } else {
+ wprintf(L"TEST-UNEXPECTED-PASS | %s | check %2d\n", TEST_NAME, testNum);
+ rv = 1;
+ }
+ }
+
+ LocalFree(inArgv);
+ LocalFree(outArgv);
+ free(inCmdLineNew);
+ free(outCmdLineNew);
+ free(outCmdLine);
+ return rv;
+}
+
+int wmain(int argc, wchar_t *argv[])
+{
+ int i;
+ int rv = 0;
+
+ if (argc > 1 && (_wcsicmp(argv[1], L"-check-one") != 0 || argc != 3)) {
+ fwprintf(stderr, L"Displays and validates output from MakeCommandLine.\n\n");
+ fwprintf(stderr, L"Usage: %s -check-one <test number>\n\n", argv[0]);
+ fwprintf(stderr, L" <test number>\tSpecifies the test number to run from the\n");
+ fwprintf(stderr, L"\t\tTestXREMakeCommandLineWin.ini file.\n");
+ return 255;
+ }
+
+ wchar_t inifile[MAXPATHLEN];
+ if (!::GetModuleFileNameW(0, inifile, MAXPATHLEN)) {
+ wprintf(L"TEST-UNEXPECTED-FAIL | %s | GetModuleFileNameW\n", TEST_NAME);
+ return 2;
+ }
+
+ WCHAR *slash = wcsrchr(inifile, '\\');
+ if (!slash) {
+ wprintf(L"TEST-UNEXPECTED-FAIL | %s | wcsrchr\n", TEST_NAME);
+ return 3;
+ }
+
+ wcscpy(slash + 1, L"TestXREMakeCommandLineWin.ini\0");
+
+ for (i = 0; i < MAX_TESTS; ++i) {
+ wchar_t sInputVal[MAXPATHLEN];
+ wchar_t sOutputVal[MAXPATHLEN];
+ wchar_t sPassesVal[MAXPATHLEN];
+ wchar_t sInputKey[MAXPATHLEN];
+ wchar_t sOutputKey[MAXPATHLEN];
+ wchar_t sPassesKey[MAXPATHLEN];
+
+ if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) {
+ i = _wtoi(argv[2]);
+ }
+
+ _snwprintf(sInputKey, MAXPATHLEN, L"input_%d", i);
+ _snwprintf(sOutputKey, MAXPATHLEN, L"output_%d", i);
+ _snwprintf(sPassesKey, MAXPATHLEN, L"passes_%d", i);
+
+ if (!GetPrivateProfileStringW(L"MakeCommandLineTests", sInputKey, nullptr,
+ sInputVal, MAXPATHLEN, inifile)) {
+ if (i == 0 || (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0)) {
+ wprintf(L"TEST-UNEXPECTED-FAIL | %s | see following explanation:\n", TEST_NAME);
+ wprintf(L"ERROR: Either the TestXREMakeCommandLineWin.ini file doesn't exist\n");
+ if (argc > 1 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) {
+ wprintf(L"ERROR: or the test is not defined in the MakeCommandLineTests section.\n");
+ } else {
+ wprintf(L"ERROR: or it has no tests defined in the MakeCommandLineTests section.\n");
+ }
+ wprintf(L"ERROR: File: %s\n", inifile);
+ return 4;
+ }
+ break;
+ }
+
+ GetPrivateProfileStringW(L"MakeCommandLineTests", sOutputKey, nullptr,
+ sOutputVal, MAXPATHLEN, inifile);
+ GetPrivateProfileStringW(L"MakeCommandLineTests", sPassesKey, nullptr,
+ sPassesVal, MAXPATHLEN, inifile);
+
+ rv |= verifyCmdLineCreation(sInputVal, sOutputVal,
+ (_wcsicmp(sPassesVal, L"false") == 0) ? FALSE : TRUE,
+ i);
+
+ if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0) {
+ break;
+ }
+ }
+
+ if (rv == 0) {
+ wprintf(L"TEST-PASS | %s | all checks passed\n", TEST_NAME);
+ } else {
+ wprintf(L"TEST-UNEXPECTED-FAIL | %s | some checks failed\n", TEST_NAME);
+ }
+
+ return rv;
+}
+
+#ifdef __MINGW32__
+
+/* MingW currently does not implement a wide version of the
+ startup routines. Workaround is to implement something like
+ it ourselves. See bug 411826 */
+
+#include <shellapi.h>
+
+int main(int argc, char **argv)
+{
+ LPWSTR commandLine = GetCommandLineW();
+ int argcw = 0;
+ LPWSTR *argvw = CommandLineToArgvW(commandLine, &argcw);
+ if (!argvw)
+ return 127;
+
+ int result = wmain(argcw, argvw);
+ LocalFree(argvw);
+ return result;
+}
+#endif /* __MINGW32__ */
diff --git a/toolkit/xre/test/win/TestXREMakeCommandLineWin.ini b/toolkit/xre/test/win/TestXREMakeCommandLineWin.ini
new file mode 100644
index 000000000..dbb529d1b
--- /dev/null
+++ b/toolkit/xre/test/win/TestXREMakeCommandLineWin.ini
@@ -0,0 +1,94 @@
+; A typical MakeCommandLine test will contain an input and an output name value
+; pair. The value for input_xx is the input command line and the value for
+; output_xx is the expected output command line.
+;
+; A test that is known to fail can be added as follows. If the passes_xx name
+; value pair doesn't exist it defaults to true.
+; input_99=yabadaba
+; output_99=doo
+; passes_99=false
+;
+; If a value starts and ends with single or double quotation marks then it must
+; be enclosed in single or double quotation marks due to GetPrivateProfileString
+; discarding the outmost quotation marks. See GetPrivateProfileString on MSDN
+; for more information.
+; http://msdn.microsoft.com/en-us/library/ms724353.aspx
+
+[MakeCommandLineTests]
+input_0=a:\
+output_0=a:\
+
+input_1=""a:\""
+output_1=a:\"
+
+input_2=""a:\b c""
+output_2=""a:\b c""
+
+input_3=""a:\b c\""
+output_3=""a:\b c\"""
+
+input_4=""a:\b c\d e""
+output_4=""a:\b c\d e""
+
+input_5=""a:\b c\d e\""
+output_5=""a:\b c\d e\"""
+
+input_6=""a:\\""
+output_6=a:\
+
+input_7="a:\" "b:\c d"
+output_7=a:\" "b:\c d"
+
+input_8="a "b:\" "c:\d e""
+output_8="a "b:\" c:\d" e"
+
+input_9="abc" d e
+output_9=abc d e
+
+input_10="a b c" d e
+output_10="a b c" d e
+
+input_11=a\\\b d"e f"g h
+output_11=a\\\b "de fg" h
+
+input_12=a b
+output_12=a b
+
+input_13=""a b""
+output_13=""a b""
+
+input_14=a\\\"b c d
+output_14=a\\\"b c d
+
+input_15=a\\\"b c"
+output_15=a\\\"b c
+
+input_16=""a\\\b c"
+output_16=""a\\\b c""
+
+input_17=\"a
+output_17=\"a
+
+input_18=\\"a
+output_18=\a
+
+input_19=\\"\\\\"a
+output_19=\\\a
+
+input_20=\\"\\\\\"a
+output_20=\\\\\\\"a
+
+input_21="a\\\"b c\" d e
+output_21=""a\\\"b c\" d e""
+
+input_22=a\\\\\"b c" d e"
+output_22=a\\\\\"b "c d e"
+
+input_23=a:\b c\アルファ オメガ\d
+output_23=a:\b c\アルファ オメガ\d
+
+input_24=a:\b "c\アルファ オメガ\d"
+output_24=a:\b "c\アルファ オメガ\d"
+
+input_25=アルファ オメガ
+output_25=アルファ オメガ
diff --git a/toolkit/xre/test/win/moz.build b/toolkit/xre/test/win/moz.build
new file mode 100644
index 000000000..51ad0bcb3
--- /dev/null
+++ b/toolkit/xre/test/win/moz.build
@@ -0,0 +1,30 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SimplePrograms([
+ 'TestXREMakeCommandLineWin',
+])
+
+CppUnitTests([
+ 'TestDllInterceptor',
+])
+
+DEFINES['NS_NO_XPCOM'] = True
+
+LOCAL_INCLUDES += [
+ '/config',
+ '/toolkit/xre',
+]
+
+DISABLE_STL_WRAPPING = True
+USE_STATIC_LIBS = True
+
+OS_LIBS += [
+ 'comctl32',
+ 'ole32',
+ 'shell32',
+ 'ws2_32',
+]