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