Reactos
1/*
2 * PROJECT: ReactOS Automatic Testing Utility
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Class for managing all the configuration parameters
5 * COPYRIGHT: Copyright 2009-2011 Colin Finck (colin@reactos.org)
6 */
7
8#include "precomp.h"
9#include <versionhelpers.h>
10
11#define CONFIGURATION_FILENAME "rosautotest.ini"
12
13static void (WINAPI *pGetSystemInfo)(LPSYSTEM_INFO);
14static void(NTAPI *pRtlGetVersion)(RTL_OSVERSIONINFOEXW *);
15
16
17/**
18 * Constructs an empty CConfiguration object
19 */
20CConfiguration::CConfiguration()
21 : m_CrashRecovery(false),
22 m_IsInteractive(false),
23 m_PrintToConsole(true),
24 m_RepeatCount(1),
25 m_Shutdown(false),
26 m_Submit(false),
27 m_ListModules(false)
28{
29 WCHAR WindowsDirectory[MAX_PATH];
30 WCHAR Interactive[32];
31
32 /* Check if we are running under ReactOS from the SystemRoot directory */
33 if(!GetWindowsDirectoryW(WindowsDirectory, MAX_PATH))
34 FATAL("GetWindowsDirectoryW failed\n");
35
36 m_IsReactOS = !_wcsnicmp(&WindowsDirectory[3], L"reactos", 7);
37 m_IsReactOS = m_IsReactOS || IsReactOS();
38
39 if(GetEnvironmentVariableW(L"WINETEST_INTERACTIVE", Interactive, _countof(Interactive)))
40 m_IsInteractive = _wtoi(Interactive);
41}
42
43/**
44 * Parses the passed parameters and sets the appropriate configuration settings.
45 *
46 * @param argc
47 * The number of parameters (argc parameter of the wmain function)
48 *
49 * @param argv
50 * Pointer to a wchar_t array containing the parameters (argv parameter of the wmain function)
51 */
52void
53CConfiguration::ParseParameters(int argc, wchar_t* argv[])
54{
55 /* Parse the command line arguments */
56 for(int i = 1; i < argc; i++)
57 {
58 if(argv[i][0] == '-' || argv[i][0] == '/')
59 {
60 unsigned long tmp_RepeatCount;
61
62 switch(argv[i][1])
63 {
64 case 'c':
65 ++i;
66 if (i >= argc)
67 {
68 throw CInvalidParameterException();
69 }
70
71 m_Comment = UnicodeToAscii(argv[i]);
72 break;
73
74 case 'n':
75 m_PrintToConsole = false;
76 break;
77
78 case 'r':
79 m_CrashRecovery = true;
80 break;
81
82 case 's':
83 m_Shutdown = true;
84 break;
85
86 case 'w':
87 m_Submit = true;
88 break;
89
90 case 't':
91 ++i;
92 if (i >= argc)
93 {
94 throw CInvalidParameterException();
95 }
96
97 tmp_RepeatCount = wcstoul(argv[i], NULL, 10);
98
99 if (tmp_RepeatCount == 0 || tmp_RepeatCount > 10000)
100 {
101 throw CInvalidParameterException();
102 }
103
104 m_RepeatCount = tmp_RepeatCount;
105 break;
106
107 case 'l':
108 m_ListModules = true;
109 break;
110
111 default:
112 throw CInvalidParameterException();
113 }
114 }
115 else
116 {
117 /* Which parameter is this? */
118 if(m_Module.empty())
119 {
120 /* Copy the parameter */
121 m_Module = argv[i];
122 }
123 else if(m_Test.empty())
124 {
125 /* Copy the parameter converted to ASCII */
126 m_Test = UnicodeToAscii(argv[i]);
127 }
128 else
129 {
130 throw CInvalidParameterException();
131 }
132 }
133 }
134
135 /* The /r and /w options shouldn't be used in conjunction */
136 if(m_CrashRecovery && m_Submit)
137 throw CInvalidParameterException();
138}
139
140/**
141 * Gets information about the running system and sets the appropriate configuration settings.
142 */
143void
144CConfiguration::GetSystemInformation()
145{
146 char ProductType;
147 stringstream ss;
148 SYSTEM_INFO si;
149
150 /* Get the build from the define */
151 ss << "&revision=";
152 ss << KERNEL_VERSION_COMMIT_HASH;
153
154 ss << "&platform=";
155
156 if(m_IsReactOS)
157 {
158 ss << "reactos";
159 }
160 else
161 {
162 RTL_OSVERSIONINFOEXW rtlinfo = {0};
163 /* No, then use the info from GetVersionExW */
164 rtlinfo.dwOSVersionInfoSize = sizeof(rtlinfo);
165
166 if (!pRtlGetVersion)
167 {
168 HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
169 pRtlGetVersion = (decltype(pRtlGetVersion))GetProcAddress(hNtdll, "RtlGetVersion");
170 }
171
172 pRtlGetVersion(&rtlinfo);
173
174 if (rtlinfo.dwMajorVersion < 5)
175 EXCEPTION("Application requires at least Windows 2000!\n");
176
177 if (rtlinfo.wProductType == VER_NT_WORKSTATION)
178 ProductType = 'w';
179 else
180 ProductType = 's';
181
182 /* Print all necessary identification information into the Platform string */
183 ss << rtlinfo.dwMajorVersion << '.'
184 << rtlinfo.dwMinorVersion << '.'
185 << rtlinfo.dwBuildNumber << '.'
186 << rtlinfo.wServicePackMajor << '.'
187 << rtlinfo.wServicePackMinor << '.'
188 << ProductType << '.';
189 }
190
191 /* We also need to know about the processor architecture.
192 To retrieve this information accurately, check whether "GetNativeSystemInfo" is exported and use it then, otherwise fall back to "GetSystemInfo". */
193 if (!pGetSystemInfo)
194 {
195 HMODULE hKernel32 = GetModuleHandleW(L"KERNEL32.DLL");
196 pGetSystemInfo = (decltype(pGetSystemInfo))GetProcAddress(hKernel32, "GetNativeSystemInfo");
197
198 if (!pGetSystemInfo)
199 pGetSystemInfo = GetSystemInfo;
200 }
201
202 pGetSystemInfo(&si);
203 ss << si.wProcessorArchitecture;
204
205 m_SystemInfoRequestString = ss.str();
206}
207
208/**
209 * Reads additional configuration options from the INI file.
210 *
211 * ParseParameters should be called before this function to get the desired result.
212 */
213void
214CConfiguration::GetConfigurationFromFile()
215{
216 DWORD Length;
217 string Value;
218 WCHAR ConfigFile[MAX_PATH];
219
220 /* Most values are only needed if we're going to submit anything */
221 if(m_Submit)
222 {
223 /* Build the path to the configuration file from the application's path */
224 GetModuleFileNameW(NULL, ConfigFile, MAX_PATH);
225 Length = wcsrchr(ConfigFile, '\\') - ConfigFile + 1;
226 wcscpy(&ConfigFile[Length], TEXT(CONFIGURATION_FILENAME));
227
228 /* Check if it exists */
229 if(GetFileAttributesW(ConfigFile) == INVALID_FILE_ATTRIBUTES)
230 EXCEPTION("Missing \"" CONFIGURATION_FILENAME "\" configuration file!\n");
231
232 /* Get the user name */
233 m_AuthenticationRequestString = "&sourceid=";
234 Value = GetINIValue(L"Login", L"SourceID", ConfigFile);
235
236 if(Value.empty())
237 EXCEPTION("SourceID is missing in the configuration file\n");
238
239 m_AuthenticationRequestString += EscapeString(Value);
240
241 /* Get the password */
242 m_AuthenticationRequestString += "&password=";
243 Value = GetINIValue(L"Login", L"Password", ConfigFile);
244
245 if(Value.empty())
246 EXCEPTION("Password is missing in the configuration file\n");
247
248 m_AuthenticationRequestString += EscapeString(Value);
249
250 /* If we don't have any Comment string yet, try to find one in the INI file */
251 if(m_Comment.empty())
252 m_Comment = GetINIValue(L"Submission", L"Comment", ConfigFile);
253 }
254}