1 /*
2  * PROJECT:     ReactOS Automatic Testing Utility
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Main implementation file
5  * COPYRIGHT:   Copyright 2008-2009 Colin Finck (colin@reactos.org)
6  */
7 
8 #include "precomp.h"
9 #include <cstdio>
10 #include <ndk/setypes.h>
11 #include <ndk/exfuncs.h>
12 
13 CConfiguration Configuration;
14 
15 /**
16  * Prints the application usage.
17  */
18 static void
19 IntPrintUsage()
20 {
21     cout << "rosautotest - ReactOS Automatic Testing Utility" << endl
22          << "Usage: rosautotest [options] [module] [test]" << endl
23          << "  options:" << endl
24          << "    /?           - Shows this help." << endl
25          << "    /c <comment> - Specifies the comment to be submitted to the Web Service." << endl
26          << "                   Skips the comment set in the configuration file (if any)." << endl
27          << "                   Only has an effect when /w is also used." << endl
28          << "    /n           - Do not print test output to console" << endl
29          << "    /r           - Maintain information to resume from ReactOS crashes" << endl
30          << "                   Can only be run under ReactOS and relies on sysreg2," << endl
31          << "                   so incompatible with /w" << endl
32          << "    /s           - Shut down the system after finishing the tests." << endl
33          << "    /t <num>     - Repeat the test <num> times (1-10000)" << endl
34          << "    /w           - Submit the results to the webservice." << endl
35          << "                   Requires a \"rosautotest.ini\" with valid login data." << endl
36          << "                   Incompatible with the /r option." << endl
37          << "    /l           - List all modules that would run." << endl
38          << endl
39          << "  module:" << endl
40          << "    The module to be tested (i.e. \"advapi32\")" << endl
41          << "    If this parameter is specified without any test parameter," << endl
42          << "    all tests of the specified module are run." << endl
43          << endl
44          << "  test:" << endl
45          << "    The test to be run. Needs to be a test of the specified module." << endl;
46 }
47 
48 static
49 VOID
50 SetNtGlobalFlags()
51 {
52     ULONG NtGlobalFlags = 0;
53     BOOLEAN PrivilegeEnabled;
54     NTSTATUS Status;
55 
56     /* Enable SeDebugPrivilege */
57     Status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &PrivilegeEnabled);
58     if (!NT_SUCCESS(Status))
59     {
60         DbgPrint("Failed to enable SeDebugPrivilege: 0x%08lx\n", Status);
61         return;
62     }
63 
64     /* Get current NtGlobalFlags */
65     Status = NtQuerySystemInformation(SystemFlagsInformation, &NtGlobalFlags, sizeof(NtGlobalFlags), NULL);
66     if (!NT_SUCCESS(Status))
67     {
68         DbgPrint("Failed to get NtGlobalFlags: 0x%08lx\n", Status);
69         return;
70     }
71 
72     /* Disable debug prompts */
73     NtGlobalFlags |= FLG_DISABLE_DEBUG_PROMPTS;
74 
75     /* Set new NtGlobalFlags */
76     Status = NtSetSystemInformation(SystemFlagsInformation, &NtGlobalFlags, sizeof(NtGlobalFlags));
77     if (!NT_SUCCESS(Status))
78     {
79         DbgPrint("Failed to set NtGlobalFlags: 0x%08lx\n", Status);
80     }
81 }
82 
83 /**
84  * Main entry point
85  */
86 extern "C" int
87 wmain(int argc, wchar_t* argv[])
88 {
89     int ReturnValue = 1;
90 
91     SetNtGlobalFlags();
92 
93     try
94     {
95         stringstream ss;
96 
97         /* Set up the configuration */
98         Configuration.ParseParameters(argc, argv);
99         Configuration.GetSystemInformation();
100         Configuration.GetConfigurationFromFile();
101 
102         ss << endl
103            << endl
104            << "[ROSAUTOTEST] System uptime " << setprecision(2) << fixed;
105         ss << ((float)GetTickCount()/1000) << " seconds" << endl;
106         StringOut(ss.str());
107 
108         /* Report tests startup */
109         InitLogs();
110         ReportEventW(hLog,
111                       EVENTLOG_INFORMATION_TYPE,
112                       0,
113                       MSG_TESTS_STARTED,
114                       NULL,
115                       0,
116                       0,
117                       NULL,
118                       NULL);
119 
120         if (Configuration.GetRepeatCount() > 1)
121         {
122             stringstream ss1;
123 
124             ss1 << "[ROSAUTOTEST] The test will be repeated " << Configuration.GetRepeatCount() << " times" << endl;
125             StringOut(ss1.str());
126         }
127 
128         /* Run the tests */
129         for (unsigned long i = 0; i < Configuration.GetRepeatCount(); i++)
130         {
131             CWineTest WineTest;
132 
133             if (Configuration.GetRepeatCount() > 1)
134             {
135                 stringstream ss;
136                 ss << "[ROSAUTOTEST] Running attempt #" << i+1 << endl;
137                 StringOut(ss.str());
138             }
139             WineTest.Run();
140         }
141 
142         /* For sysreg2 */
143         DbgPrint("SYSREG_CHECKPOINT:THIRDBOOT_COMPLETE\n");
144 
145         ReturnValue = 0;
146     }
147     catch(CInvalidParameterException)
148     {
149         IntPrintUsage();
150     }
151     catch(CSimpleException& e)
152     {
153         stringstream ss;
154 
155         // e.GetMessage() must include ending '\n'.
156         ss << "[ROSAUTOTEST] " << e.GetMessage();
157         StringOut(ss.str());
158     }
159     catch(CFatalException& e)
160     {
161         stringstream ss;
162 
163         // e.GetMessage() must include ending '\n'.
164         ss << "An exception occured in rosautotest." << endl
165            << "Message: " << e.GetMessage()
166            << "File: " << e.GetFile() << endl
167            << "Line: " << e.GetLine() << endl
168            << "Last Win32 Error: " << GetLastError() << endl;
169         StringOut(ss.str());
170     }
171 
172     /* For sysreg2 to notice if rosautotest itself failed */
173     if(ReturnValue == 1)
174         DbgPrint("SYSREG_ROSAUTOTEST_FAILURE\n");
175 
176     /* Report successful end of tests */
177     ReportEventW(hLog,
178                   EVENTLOG_SUCCESS,
179                   0,
180                   MSG_TESTS_SUCCESSFUL,
181                   NULL,
182                   0,
183                   0,
184                   NULL,
185                   NULL);
186     FreeLogs();
187 
188     /* Shut down the system if requested, also in case of an exception above */
189     if(Configuration.DoShutdown() && !ShutdownSystem())
190         ReturnValue = 1;
191 
192     return ReturnValue;
193 }
194