Fix build.
[reactos.git] / rostests / rosautotest / main.c
1 /*
2 * PROJECT: ReactOS Automatic Testing Utility
3 * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
4 * PURPOSE: Main implementation file
5 * COPYRIGHT: Copyright 2008-2009 Colin Finck <colin@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 typedef void (WINAPI *GETSYSINFO)(LPSYSTEM_INFO);
11
12 APP_OPTIONS AppOptions = {0};
13 HANDLE hProcessHeap;
14 PCHAR AuthenticationRequestString = NULL;
15 PCHAR SystemInfoRequestString = NULL;
16
17 /**
18 * Gets a value from a specified INI file and returns it converted to ASCII.
19 *
20 * @param AppName
21 * The INI section to look in (lpAppName parameter passed to GetPrivateProfileStringW)
22 *
23 * @param KeyName
24 * The key to look for in the specified section (lpKeyName parameter passed to GetPrivateProfileStringW)
25 *
26 * @param FileName
27 * The path to the INI file
28 *
29 * @param ReturnedValue
30 * Pointer to a CHAR pointer, which will receive the read and converted value.
31 * The caller needs to HeapFree that value manually.
32 *
33 * @return
34 * Returns the string length of the read value (in characters) or zero if we didn't get any value.
35 */
36 static DWORD
37 IntGetINIValueA(PCWCH AppName, PCWCH KeyName, PCWCH FileName, char** ReturnedValue)
38 {
39 DWORD Length;
40 WCHAR Buffer[2048];
41
42 /* Load the value into a temporary Unicode buffer */
43 Length = GetPrivateProfileStringW(AppName, KeyName, NULL, Buffer, sizeof(Buffer) / sizeof(WCHAR), FileName);
44
45 if(!Length)
46 return 0;
47
48 /* Convert the string to ANSI charset */
49 *ReturnedValue = HeapAlloc(hProcessHeap, 0, Length + 1);
50 WideCharToMultiByte(CP_ACP, 0, Buffer, Length + 1, *ReturnedValue, Length + 1, NULL, NULL);
51
52 return Length;
53 }
54
55 /**
56 * Gets the username and password from the "rosautotest.ini" file if the user enabled submitting the results to the web service.
57 * The "rosautotest.ini" file should look like this:
58 *
59 * [Login]
60 * UserName=TestMan
61 * Password=TestPassword
62 */
63 static BOOL
64 IntGetConfigurationValues()
65 {
66 const CHAR PasswordProp[] = "&password=";
67 const CHAR UserNameProp[] = "&username=";
68
69 BOOL ReturnValue = FALSE;
70 DWORD DataLength;
71 DWORD Length;
72 PCHAR Password = NULL;
73 PCHAR UserName = NULL;
74 WCHAR ConfigFile[MAX_PATH];
75
76 /* Most values are only needed if we're going to submit */
77 if(AppOptions.Submit)
78 {
79 /* Build the path to the configuration file from the application's path */
80 GetModuleFileNameW(NULL, ConfigFile, MAX_PATH);
81 Length = wcsrchr(ConfigFile, '\\') - ConfigFile;
82 wcscpy(&ConfigFile[Length], L"\\rosautotest.ini");
83
84 /* Check if it exists */
85 if(GetFileAttributesW(ConfigFile) == INVALID_FILE_ATTRIBUTES)
86 {
87 StringOut("Missing \"rosautotest.ini\" configuration file!\n");
88 goto Cleanup;
89 }
90
91 /* Get the required length of the authentication request string */
92 DataLength = sizeof(UserNameProp) - 1;
93 Length = IntGetINIValueA(L"Login", L"UserName", ConfigFile, &UserName);
94
95 if(!Length)
96 {
97 StringOut("UserName is missing in the configuration file\n");
98 goto Cleanup;
99 }
100
101 /* Some characters might need to be escaped and an escaped character takes 3 bytes */
102 DataLength += 3 * Length;
103
104 DataLength += sizeof(PasswordProp) - 1;
105 Length = IntGetINIValueA(L"Login", L"Password", ConfigFile, &Password);
106
107 if(!Length)
108 {
109 StringOut("Password is missing in the configuration file\n");
110 goto Cleanup;
111 }
112
113 DataLength += 3 * Length;
114
115 /* Build the string */
116 AuthenticationRequestString = HeapAlloc(hProcessHeap, 0, DataLength + 1);
117
118 strcpy(AuthenticationRequestString, UserNameProp);
119 EscapeString(&AuthenticationRequestString[strlen(AuthenticationRequestString)], UserName);
120
121 strcat(AuthenticationRequestString, PasswordProp);
122 EscapeString(&AuthenticationRequestString[strlen(AuthenticationRequestString)], Password);
123
124 /* If we don't have any Comment string yet, try to find one in the INI file */
125 if(!AppOptions.Comment)
126 IntGetINIValueA(L"Submission", L"Comment", ConfigFile, &AppOptions.Comment);
127 }
128
129 ReturnValue = TRUE;
130
131 Cleanup:
132 if(UserName)
133 HeapFree(hProcessHeap, 0, UserName);
134
135 if(Password)
136 HeapFree(hProcessHeap, 0, Password);
137
138 return ReturnValue;
139 }
140
141 /**
142 * Determines on which platform we're running on.
143 * Prepares the appropriate request strings needed if we want to submit test results to the web service.
144 */
145 static BOOL
146 IntGetBuildAndPlatform()
147 {
148 const CHAR PlatformProp[] = "&platform=";
149 const CHAR RevisionProp[] = "&revision=";
150
151 CHAR BuildNo[BUILDNO_LENGTH];
152 CHAR Platform[PLATFORM_LENGTH];
153 CHAR PlatformArchitecture[3];
154 CHAR ProductType;
155 DWORD DataLength;
156 GETSYSINFO GetSysInfo;
157 HANDLE hKernel32;
158 OSVERSIONINFOEXW os;
159 SYSTEM_INFO si;
160 WCHAR WindowsDirectory[MAX_PATH];
161
162 /* Get the build from the define */
163 _ultoa(KERNEL_VERSION_BUILD_HEX, BuildNo, 10);
164
165 /* Check if we are running under ReactOS from the SystemRoot directory */
166 GetWindowsDirectoryW(WindowsDirectory, MAX_PATH);
167
168 if(!_wcsnicmp(&WindowsDirectory[3], L"reactos", 7))
169 {
170 /* Yes, we are most-probably under ReactOS */
171 strcpy(Platform, "reactos");
172 }
173 else
174 {
175 /* No, then use the info from GetVersionExW */
176 os.dwOSVersionInfoSize = sizeof(os);
177
178 if(!GetVersionExW((LPOSVERSIONINFOW)&os))
179 {
180 StringOut("GetVersionExW failed\n");
181 return FALSE;
182 }
183
184 if(os.dwMajorVersion < 5)
185 {
186 StringOut("Application requires at least Windows 2000!\n");
187 return FALSE;
188 }
189
190 if(os.wProductType == VER_NT_WORKSTATION)
191 ProductType = 'w';
192 else
193 ProductType = 's';
194
195 /* Print all necessary identification information into the Platform string */
196 sprintf(Platform, "%lu.%lu.%lu.%u.%u.%c", os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber, os.wServicePackMajor, os.wServicePackMinor, ProductType);
197 }
198
199 /* We also need to know about the processor architecture.
200 To retrieve this information accurately, check whether "GetNativeSystemInfo" is exported and use it then, otherwise fall back to "GetSystemInfo". */
201 hKernel32 = GetModuleHandleW(L"KERNEL32.DLL");
202 GetSysInfo = (GETSYSINFO)GetProcAddress(hKernel32, "GetNativeSystemInfo");
203
204 if(!GetSysInfo)
205 GetSysInfo = (GETSYSINFO)GetProcAddress(hKernel32, "GetSystemInfo");
206
207 GetSysInfo(&si);
208
209 PlatformArchitecture[0] = '.';
210 _ultoa(si.wProcessorArchitecture, &PlatformArchitecture[1], 10);
211 PlatformArchitecture[2] = 0;
212 strcat(Platform, PlatformArchitecture);
213
214 /* Get the required length of the system info request string */
215 DataLength = sizeof(RevisionProp) - 1;
216 DataLength += strlen(BuildNo);
217 DataLength += sizeof(PlatformProp) - 1;
218 DataLength += strlen(Platform);
219
220 /* Now build the string */
221 SystemInfoRequestString = HeapAlloc(hProcessHeap, 0, DataLength + 1);
222 strcpy(SystemInfoRequestString, RevisionProp);
223 strcat(SystemInfoRequestString, BuildNo);
224 strcat(SystemInfoRequestString, PlatformProp);
225 strcat(SystemInfoRequestString, Platform);
226
227 return TRUE;
228 }
229
230 /**
231 * Prints the application usage.
232 */
233 static VOID
234 IntPrintUsage()
235 {
236 printf("rosautotest - ReactOS Automatic Testing Utility\n");
237 printf("Usage: rosautotest [options] [module] [test]\n");
238 printf(" options:\n");
239 printf(" /? - Shows this help\n");
240 printf(" /c <comment> - Specifies the comment to be submitted to the Web Service.\n");
241 printf(" Skips the comment set in the configuration file (if any).\n");
242 printf(" Only has an effect when /w is also used.\n");
243 printf(" /s - Shut down the system after finishing the tests\n");
244 printf(" /w - Submit the results to the webservice\n");
245 printf(" Requires a \"rosautotest.ini\" with valid login data.\n");
246 printf("\n");
247 printf(" module:\n");
248 printf(" The module to be tested (i.e. \"advapi32\")\n");
249 printf(" If this parameter is specified without any test parameter,\n");
250 printf(" all tests of the specified module are run.\n");
251 printf("\n");
252 printf(" test:\n");
253 printf(" The test to be run. Needs to be a test of the specified module.\n");
254 }
255
256 /**
257 * Main entry point
258 */
259 int
260 wmain(int argc, wchar_t* argv[])
261 {
262 int ReturnValue = 0;
263 size_t Length;
264 UINT i;
265
266 hProcessHeap = GetProcessHeap();
267
268 /* Parse the command line arguments */
269 for(i = 1; i < (UINT)argc; i++)
270 {
271 if(argv[i][0] == '-' || argv[i][0] == '/')
272 {
273 switch(argv[i][1])
274 {
275 case 'c':
276 ++i;
277
278 /* Copy the parameter converted to ASCII */
279 Length = WideCharToMultiByte(CP_ACP, 0, argv[i], -1, NULL, 0, NULL, NULL);
280 AppOptions.Comment = HeapAlloc(hProcessHeap, 0, Length);
281 WideCharToMultiByte(CP_ACP, 0, argv[i], -1, AppOptions.Comment, Length, NULL, NULL);
282
283 break;
284
285 case 's':
286 AppOptions.Shutdown = TRUE;
287 break;
288
289 case 'w':
290 AppOptions.Submit = TRUE;
291 break;
292
293 default:
294 ReturnValue = 1;
295 /* Fall through */
296
297 case '?':
298 IntPrintUsage();
299 goto Cleanup;
300 }
301 }
302 else
303 {
304 /* Which parameter is this? */
305 if(!AppOptions.Module)
306 {
307 /* Copy the parameter */
308 Length = (wcslen(argv[i]) + 1) * sizeof(WCHAR);
309 AppOptions.Module = HeapAlloc(hProcessHeap, 0, Length);
310 memcpy(AppOptions.Module, argv[i], Length);
311 }
312 else if(!AppOptions.Test)
313 {
314 /* Copy the parameter converted to ASCII */
315 Length = WideCharToMultiByte(CP_ACP, 0, argv[i], -1, NULL, 0, NULL, NULL);
316 AppOptions.Test = HeapAlloc(hProcessHeap, 0, Length);
317 WideCharToMultiByte(CP_ACP, 0, argv[i], -1, AppOptions.Test, Length, NULL, NULL);
318 }
319 else
320 {
321 ReturnValue = 1;
322 IntPrintUsage();
323 goto Cleanup;
324 }
325 }
326 }
327
328 if(!IntGetConfigurationValues() || !IntGetBuildAndPlatform() || !RunWineTests())
329 {
330 ReturnValue = 1;
331 goto Cleanup;
332 }
333
334 /* For sysreg */
335 OutputDebugStringA("SYSREG_CHECKPOINT:THIRDBOOT_COMPLETE\n");
336
337 Cleanup:
338 if(AppOptions.Comment)
339 HeapFree(hProcessHeap, 0, AppOptions.Comment);
340
341 if(AppOptions.Module)
342 HeapFree(hProcessHeap, 0, AppOptions.Module);
343
344 if(AppOptions.Test)
345 HeapFree(hProcessHeap, 0, AppOptions.Test);
346
347 if(AuthenticationRequestString)
348 HeapFree(hProcessHeap, 0, AuthenticationRequestString);
349
350 if(SystemInfoRequestString)
351 HeapFree(hProcessHeap, 0, SystemInfoRequestString);
352
353 /* Shut down the system if requested */
354 if(AppOptions.Shutdown && !ShutdownSystem())
355 ReturnValue = 1;
356
357 return ReturnValue;
358 }