main.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496
  1. /*
  2. * Wine Conformance Test EXE
  3. *
  4. * Copyright 2003, 2004 Jakob Eriksson (for Solid Form Sweden AB)
  5. * Copyright 2003 Dimitrie O. Paun
  6. * Copyright 2003 Ferenc Wagner
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  21. *
  22. * This program is dedicated to Anna Lindh,
  23. * Swedish Minister of Foreign Affairs.
  24. * Anna was murdered September 11, 2003.
  25. *
  26. */
  27. #define COBJMACROS
  28. #include <stdio.h>
  29. #include <assert.h>
  30. #include <windows.h>
  31. #include <commctrl.h>
  32. #include <winternl.h>
  33. #include <mshtml.h>
  34. #include "winetest.h"
  35. #include "resource.h"
  36. /* Don't submit the results if more than SKIP_LIMIT tests have been skipped */
  37. #define SKIP_LIMIT 10
  38. /* Don't submit the results if more than FAILURES_LIMIT tests have failed */
  39. #define FAILURES_LIMIT 50
  40. struct wine_test
  41. {
  42. char *name;
  43. int subtest_count;
  44. char **subtests;
  45. char *exename;
  46. char *maindllpath;
  47. };
  48. char *tag = NULL;
  49. char *description = NULL;
  50. char *url = NULL;
  51. char *email = NULL;
  52. BOOL aborting = FALSE;
  53. static struct wine_test *wine_tests;
  54. static int nr_of_files, nr_of_tests, nr_of_skips;
  55. static int nr_native_dlls;
  56. static const char whitespace[] = " \t\r\n";
  57. static const char testexe[] = "_test.exe";
  58. static char build_id[64];
  59. static BOOL is_wow64;
  60. static int failures;
  61. /* filters for running only specific tests */
  62. static char *filters[64];
  63. static unsigned int nb_filters = 0;
  64. static BOOL exclude_tests = FALSE;
  65. /* Needed to check for .NET dlls */
  66. static HMODULE hmscoree;
  67. static HRESULT (WINAPI *pLoadLibraryShim)(LPCWSTR, LPCWSTR, LPVOID, HMODULE *);
  68. /* For SxS DLLs e.g. msvcr90 */
  69. static HANDLE (WINAPI *pCreateActCtxA)(PACTCTXA);
  70. static BOOL (WINAPI *pActivateActCtx)(HANDLE, ULONG_PTR *);
  71. static BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
  72. static void (WINAPI *pReleaseActCtx)(HANDLE);
  73. /* To store the current PATH setting (related to .NET only provided dlls) */
  74. static char *curpath;
  75. /* check if test is being filtered out */
  76. static BOOL test_filtered_out( LPCSTR module, LPCSTR testname )
  77. {
  78. char *p, dllname[MAX_PATH];
  79. unsigned int i, len;
  80. strcpy( dllname, module );
  81. CharLowerA( dllname );
  82. p = strstr( dllname, testexe );
  83. if (p) *p = 0;
  84. len = strlen(dllname);
  85. if (!nb_filters) return exclude_tests;
  86. for (i = 0; i < nb_filters; i++)
  87. {
  88. if (!strncmp( dllname, filters[i], len ))
  89. {
  90. if (!filters[i][len]) return exclude_tests;
  91. if (filters[i][len] != ':') continue;
  92. if (testname && !strcmp( testname, &filters[i][len+1] )) return exclude_tests;
  93. if (!testname && !exclude_tests) return FALSE;
  94. }
  95. }
  96. return !exclude_tests;
  97. }
  98. static char * get_file_version(char * file_name)
  99. {
  100. static char version[32];
  101. DWORD size;
  102. DWORD handle;
  103. size = GetFileVersionInfoSizeA(file_name, &handle);
  104. if (size) {
  105. char * data = heap_alloc(size);
  106. if (data) {
  107. if (GetFileVersionInfoA(file_name, handle, size, data)) {
  108. static const char backslash[] = "\\";
  109. VS_FIXEDFILEINFO *pFixedVersionInfo;
  110. UINT len;
  111. if (VerQueryValueA(data, backslash, (LPVOID *)&pFixedVersionInfo, &len)) {
  112. sprintf(version, "%d.%d.%d.%d",
  113. pFixedVersionInfo->dwFileVersionMS >> 16,
  114. pFixedVersionInfo->dwFileVersionMS & 0xffff,
  115. pFixedVersionInfo->dwFileVersionLS >> 16,
  116. pFixedVersionInfo->dwFileVersionLS & 0xffff);
  117. } else
  118. sprintf(version, "version not found");
  119. } else
  120. sprintf(version, "version error %u", GetLastError());
  121. heap_free(data);
  122. } else
  123. sprintf(version, "version error %u", ERROR_OUTOFMEMORY);
  124. } else if (GetLastError() == ERROR_FILE_NOT_FOUND)
  125. sprintf(version, "dll is missing");
  126. else
  127. sprintf(version, "version not present %u", GetLastError());
  128. return version;
  129. }
  130. static BOOL running_under_wine (void)
  131. {
  132. HMODULE module = GetModuleHandleA("ntdll.dll");
  133. if (!module) return FALSE;
  134. return (GetProcAddress(module, "wine_server_call") != NULL);
  135. }
  136. static BOOL check_mount_mgr(void)
  137. {
  138. HANDLE handle = CreateFileA( "\\\\.\\MountPointManager", GENERIC_READ,
  139. FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
  140. if (handle == INVALID_HANDLE_VALUE) return FALSE;
  141. CloseHandle( handle );
  142. return TRUE;
  143. }
  144. static BOOL check_wow64_registry(void)
  145. {
  146. char buffer[MAX_PATH];
  147. DWORD type, size = MAX_PATH;
  148. HKEY hkey;
  149. BOOL ret;
  150. if (!is_wow64) return TRUE;
  151. if (RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey ))
  152. return FALSE;
  153. ret = !RegQueryValueExA( hkey, "ProgramFilesDir (x86)", NULL, &type, (BYTE *)buffer, &size );
  154. RegCloseKey( hkey );
  155. return ret;
  156. }
  157. static BOOL check_display_driver(void)
  158. {
  159. HWND hwnd = CreateWindowA( "STATIC", "", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
  160. 0, 0, GetModuleHandleA(0), 0 );
  161. if (!hwnd) return FALSE;
  162. DestroyWindow( hwnd );
  163. return TRUE;
  164. }
  165. static BOOL running_on_visible_desktop (void)
  166. {
  167. HWND desktop;
  168. HMODULE huser32 = GetModuleHandleA("user32.dll");
  169. HWINSTA (WINAPI *pGetProcessWindowStation)(void);
  170. BOOL (WINAPI *pGetUserObjectInformationA)(HANDLE,INT,LPVOID,DWORD,LPDWORD);
  171. pGetProcessWindowStation = (void *)GetProcAddress(huser32, "GetProcessWindowStation");
  172. pGetUserObjectInformationA = (void *)GetProcAddress(huser32, "GetUserObjectInformationA");
  173. desktop = GetDesktopWindow();
  174. if (!GetWindowLongPtrW(desktop, GWLP_WNDPROC)) /* Win9x */
  175. return IsWindowVisible(desktop);
  176. if (pGetProcessWindowStation && pGetUserObjectInformationA)
  177. {
  178. DWORD len;
  179. HWINSTA wstation;
  180. USEROBJECTFLAGS uoflags;
  181. wstation = pGetProcessWindowStation();
  182. assert(pGetUserObjectInformationA(wstation, UOI_FLAGS, &uoflags, sizeof(uoflags), &len));
  183. return (uoflags.dwFlags & WSF_VISIBLE) != 0;
  184. }
  185. return IsWindowVisible(desktop);
  186. }
  187. static int running_as_admin (void)
  188. {
  189. PSID administrators = NULL;
  190. SID_IDENTIFIER_AUTHORITY nt_authority = { SECURITY_NT_AUTHORITY };
  191. HANDLE token;
  192. DWORD groups_size;
  193. PTOKEN_GROUPS groups;
  194. DWORD group_index;
  195. /* Create a well-known SID for the Administrators group. */
  196. if (! AllocateAndInitializeSid(&nt_authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
  197. DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
  198. &administrators))
  199. return -1;
  200. /* Get the process token */
  201. if (! OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
  202. {
  203. FreeSid(administrators);
  204. return -1;
  205. }
  206. /* Get the group info from the token */
  207. groups_size = 0;
  208. GetTokenInformation(token, TokenGroups, NULL, 0, &groups_size);
  209. groups = heap_alloc(groups_size);
  210. if (groups == NULL)
  211. {
  212. CloseHandle(token);
  213. FreeSid(administrators);
  214. return -1;
  215. }
  216. if (! GetTokenInformation(token, TokenGroups, groups, groups_size, &groups_size))
  217. {
  218. heap_free(groups);
  219. CloseHandle(token);
  220. FreeSid(administrators);
  221. return -1;
  222. }
  223. CloseHandle(token);
  224. /* Now check if the token groups include the Administrators group */
  225. for (group_index = 0; group_index < groups->GroupCount; group_index++)
  226. {
  227. if (EqualSid(groups->Groups[group_index].Sid, administrators))
  228. {
  229. heap_free(groups);
  230. FreeSid(administrators);
  231. return 1;
  232. }
  233. }
  234. /* If we end up here we didn't find the Administrators group */
  235. heap_free(groups);
  236. FreeSid(administrators);
  237. return 0;
  238. }
  239. static int running_elevated (void)
  240. {
  241. HANDLE token;
  242. TOKEN_ELEVATION elevation_info;
  243. DWORD size;
  244. /* Get the process token */
  245. if (! OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
  246. return -1;
  247. /* Get the elevation info from the token */
  248. if (! GetTokenInformation(token, TokenElevation, &elevation_info,
  249. sizeof(TOKEN_ELEVATION), &size))
  250. {
  251. CloseHandle(token);
  252. return -1;
  253. }
  254. CloseHandle(token);
  255. return elevation_info.TokenIsElevated;
  256. }
  257. /* check for native dll when running under wine */
  258. static BOOL is_native_dll( HMODULE module )
  259. {
  260. static const char builtin_signature[] = "Wine builtin DLL";
  261. static const char fakedll_signature[] = "Wine placeholder DLL";
  262. const IMAGE_DOS_HEADER *dos;
  263. if (!running_under_wine()) return FALSE;
  264. if (!((ULONG_PTR)module & 1)) return FALSE; /* not loaded as datafile */
  265. /* builtin dlls can't be loaded as datafile, so we must have native or fake dll */
  266. dos = (const IMAGE_DOS_HEADER *)((const char *)module - 1);
  267. if (dos->e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
  268. if (dos->e_lfanew >= sizeof(*dos) + 32)
  269. {
  270. if (!memcmp( dos + 1, builtin_signature, sizeof(builtin_signature) )) return FALSE;
  271. if (!memcmp( dos + 1, fakedll_signature, sizeof(fakedll_signature) )) return FALSE;
  272. }
  273. return TRUE;
  274. }
  275. /*
  276. * Windows 8 has a concept of stub DLLs. When DLLMain is called the user is prompted
  277. * to install that component. To bypass this check we need to look at the version resource.
  278. */
  279. static BOOL is_stub_dll(const char *filename)
  280. {
  281. DWORD size, ver;
  282. BOOL isstub = FALSE;
  283. char *p, *data;
  284. size = GetFileVersionInfoSizeA(filename, &ver);
  285. if (!size) return FALSE;
  286. data = HeapAlloc(GetProcessHeap(), 0, size);
  287. if (!data) return FALSE;
  288. if (GetFileVersionInfoA(filename, ver, size, data))
  289. {
  290. char buf[256];
  291. sprintf(buf, "\\StringFileInfo\\%04x%04x\\OriginalFilename", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 1200);
  292. if (VerQueryValueA(data, buf, (void**)&p, &size))
  293. isstub = !lstrcmpiA("wcodstub.dll", p);
  294. }
  295. HeapFree(GetProcessHeap(), 0, data);
  296. return isstub;
  297. }
  298. static void print_version (void)
  299. {
  300. #ifdef __i386__
  301. static const char platform[] = "i386";
  302. #elif defined(__x86_64__)
  303. static const char platform[] = "x86_64";
  304. #elif defined(__arm__)
  305. static const char platform[] = "arm";
  306. #elif defined(__aarch64__)
  307. static const char platform[] = "arm64";
  308. #else
  309. # error CPU unknown
  310. #endif
  311. OSVERSIONINFOEXA ver;
  312. RTL_OSVERSIONINFOEXW rtlver;
  313. BOOL ext;
  314. int is_win2k3_r2, is_admin, is_elevated;
  315. const char *(CDECL *wine_get_build_id)(void);
  316. HMODULE hntdll = GetModuleHandleA("ntdll.dll");
  317. void (CDECL *wine_get_host_version)( const char **sysname, const char **release );
  318. BOOL (WINAPI *pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *);
  319. NTSTATUS (WINAPI *pRtlGetVersion)(RTL_OSVERSIONINFOEXW *);
  320. ver.dwOSVersionInfoSize = sizeof(ver);
  321. if (!(ext = GetVersionExA ((OSVERSIONINFOA *) &ver)))
  322. {
  323. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  324. if (!GetVersionExA ((OSVERSIONINFOA *) &ver))
  325. report (R_FATAL, "Can't get OS version.");
  326. }
  327. /* try to get non-faked values */
  328. if (ver.dwMajorVersion == 6 && ver.dwMinorVersion == 2)
  329. {
  330. rtlver.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
  331. pRtlGetVersion = (void *)GetProcAddress(hntdll, "RtlGetVersion");
  332. pRtlGetVersion(&rtlver);
  333. ver.dwMajorVersion = rtlver.dwMajorVersion;
  334. ver.dwMinorVersion = rtlver.dwMinorVersion;
  335. ver.dwBuildNumber = rtlver.dwBuildNumber;
  336. ver.dwPlatformId = rtlver.dwPlatformId;
  337. ver.wServicePackMajor = rtlver.wServicePackMajor;
  338. ver.wServicePackMinor = rtlver.wServicePackMinor;
  339. ver.wSuiteMask = rtlver.wSuiteMask;
  340. ver.wProductType = rtlver.wProductType;
  341. WideCharToMultiByte(CP_ACP, 0, rtlver.szCSDVersion, -1, ver.szCSDVersion, sizeof(ver.szCSDVersion), NULL, NULL);
  342. }
  343. xprintf (" Platform=%s%s\n", platform, is_wow64 ? " (WOW64)" : "");
  344. xprintf (" bRunningUnderWine=%d\n", running_under_wine ());
  345. xprintf (" bRunningOnVisibleDesktop=%d\n", running_on_visible_desktop ());
  346. is_admin = running_as_admin ();
  347. if (0 <= is_admin)
  348. {
  349. xprintf (" Account=%s", is_admin ? "admin" : "non-admin");
  350. is_elevated = running_elevated ();
  351. if (0 <= is_elevated)
  352. xprintf(", %s", is_elevated ? "elevated" : "not elevated");
  353. xprintf ("\n");
  354. }
  355. xprintf (" Submitter=%s\n", email );
  356. if (description)
  357. xprintf (" Description=%s\n", description );
  358. if (url)
  359. xprintf (" URL=%s\n", url );
  360. xprintf (" dwMajorVersion=%u\n dwMinorVersion=%u\n"
  361. " dwBuildNumber=%u\n PlatformId=%u\n szCSDVersion=%s\n",
  362. ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
  363. ver.dwPlatformId, ver.szCSDVersion);
  364. wine_get_build_id = (void *)GetProcAddress(hntdll, "wine_get_build_id");
  365. wine_get_host_version = (void *)GetProcAddress(hntdll, "wine_get_host_version");
  366. if (wine_get_build_id) xprintf( " WineBuild=%s\n", wine_get_build_id() );
  367. if (wine_get_host_version)
  368. {
  369. const char *sysname, *release;
  370. wine_get_host_version( &sysname, &release );
  371. xprintf( " Host system=%s\n Host version=%s\n", sysname, release );
  372. }
  373. is_win2k3_r2 = GetSystemMetrics(SM_SERVERR2);
  374. if(is_win2k3_r2)
  375. xprintf(" R2 build number=%d\n", is_win2k3_r2);
  376. if (!ext) return;
  377. xprintf (" wServicePackMajor=%d\n wServicePackMinor=%d\n"
  378. " wSuiteMask=%d\n wProductType=%d\n wReserved=%d\n",
  379. ver.wServicePackMajor, ver.wServicePackMinor, ver.wSuiteMask,
  380. ver.wProductType, ver.wReserved);
  381. pGetProductInfo = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"),"GetProductInfo");
  382. if (pGetProductInfo && !running_under_wine())
  383. {
  384. DWORD prodtype = 0;
  385. pGetProductInfo(ver.dwMajorVersion, ver.dwMinorVersion, ver.wServicePackMajor, ver.wServicePackMinor, &prodtype);
  386. xprintf(" dwProductInfo=%u\n", prodtype);
  387. }
  388. }
  389. static void print_language(void)
  390. {
  391. HMODULE hkernel32;
  392. BOOL (WINAPI *pGetSystemPreferredUILanguages)(DWORD, PULONG, PZZWSTR, PULONG);
  393. LANGID (WINAPI *pGetUserDefaultUILanguage)(void);
  394. LANGID (WINAPI *pGetThreadUILanguage)(void);
  395. xprintf (" SystemDefaultLCID=%04x\n", GetSystemDefaultLCID());
  396. xprintf (" UserDefaultLCID=%04x\n", GetUserDefaultLCID());
  397. xprintf (" ThreadLocale=%04x\n", GetThreadLocale());
  398. hkernel32 = GetModuleHandleA("kernel32.dll");
  399. pGetSystemPreferredUILanguages = (void*)GetProcAddress(hkernel32, "GetSystemPreferredUILanguages");
  400. pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
  401. pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
  402. if (pGetSystemPreferredUILanguages && !running_under_wine())
  403. {
  404. WCHAR langW[32];
  405. ULONG num, size = ARRAY_SIZE(langW);
  406. if (pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID, &num, langW, &size))
  407. {
  408. char lang[32], *p = lang;
  409. WideCharToMultiByte(CP_ACP, 0, langW, size, lang, sizeof(lang), NULL, NULL);
  410. for (p += strlen(p) + 1; *p != '\0'; p += strlen(p) + 1) *(p - 1) = ',';
  411. xprintf (" SystemPreferredUILanguages=%s\n", lang);
  412. }
  413. }
  414. if (pGetUserDefaultUILanguage)
  415. xprintf (" UserDefaultUILanguage=%04x\n", pGetUserDefaultUILanguage());
  416. if (pGetThreadUILanguage)
  417. xprintf (" ThreadUILanguage=%04x\n", pGetThreadUILanguage());
  418. }
  419. static inline BOOL is_dot_dir(const char* x)
  420. {
  421. return ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))));
  422. }
  423. static void remove_dir (const char *dir)
  424. {
  425. HANDLE hFind;
  426. WIN32_FIND_DATAA wfd;
  427. char path[MAX_PATH];
  428. size_t dirlen = strlen (dir);
  429. /* Make sure the directory exists before going further */
  430. memcpy (path, dir, dirlen);
  431. strcpy (path + dirlen++, "\\*");
  432. hFind = FindFirstFileA (path, &wfd);
  433. if (hFind == INVALID_HANDLE_VALUE) return;
  434. do {
  435. char *lp = wfd.cFileName;
  436. if (!lp[0]) lp = wfd.cAlternateFileName; /* ? FIXME not (!lp) ? */
  437. if (is_dot_dir (lp)) continue;
  438. strcpy (path + dirlen, lp);
  439. if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
  440. remove_dir(path);
  441. else if (!DeleteFileA(path))
  442. report (R_WARNING, "Can't delete file %s: error %d",
  443. path, GetLastError ());
  444. } while (FindNextFileA(hFind, &wfd));
  445. FindClose (hFind);
  446. if (!RemoveDirectoryA(dir))
  447. report (R_WARNING, "Can't remove directory %s: error %d",
  448. dir, GetLastError ());
  449. }
  450. static const char* get_test_source_file(const char* test, const char* subtest)
  451. {
  452. static char buffer[MAX_PATH];
  453. int len = strlen(test);
  454. if (len > 4 && !strcmp( test + len - 4, ".exe" ) &&
  455. strcmp( test, "ntoskrnl.exe" )) /* the one exception! */
  456. {
  457. len = sprintf(buffer, "programs/%s", test) - 4;
  458. buffer[len] = 0;
  459. }
  460. else len = sprintf(buffer, "dlls/%s", test);
  461. sprintf(buffer + len, "/tests/%s.c", subtest);
  462. return buffer;
  463. }
  464. static void* extract_rcdata (LPCSTR name, LPCSTR type, DWORD* size)
  465. {
  466. HRSRC rsrc;
  467. HGLOBAL hdl;
  468. LPVOID addr;
  469. if (!(rsrc = FindResourceA(NULL, name, type)) ||
  470. !(*size = SizeofResource (0, rsrc)) ||
  471. !(hdl = LoadResource (0, rsrc)) ||
  472. !(addr = LockResource (hdl)))
  473. return NULL;
  474. return addr;
  475. }
  476. /* Fills in the name and exename fields */
  477. static void
  478. extract_test (struct wine_test *test, const char *dir, LPSTR res_name)
  479. {
  480. BYTE* code;
  481. DWORD size;
  482. char *exepos;
  483. HANDLE hfile;
  484. DWORD written;
  485. code = extract_rcdata (res_name, "TESTRES", &size);
  486. if (!code) report (R_FATAL, "Can't find test resource %s: %d",
  487. res_name, GetLastError ());
  488. test->name = heap_strdup( res_name );
  489. test->exename = strmake (NULL, "%s\\%s", dir, test->name);
  490. exepos = strstr (test->name, testexe);
  491. if (!exepos) report (R_FATAL, "Not an .exe file: %s", test->name);
  492. *exepos = 0;
  493. test->name = heap_realloc (test->name, exepos - test->name + 1);
  494. report (R_STEP, "Extracting: %s", test->name);
  495. hfile = CreateFileA(test->exename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  496. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  497. if (hfile == INVALID_HANDLE_VALUE)
  498. report (R_FATAL, "Failed to open file %s.", test->exename);
  499. if (!WriteFile(hfile, code, size, &written, NULL))
  500. report (R_FATAL, "Failed to write file %s.", test->exename);
  501. CloseHandle(hfile);
  502. }
  503. static DWORD wait_process( HANDLE process, DWORD timeout )
  504. {
  505. DWORD wait, diff = 0, start = GetTickCount();
  506. MSG msg;
  507. while (diff < timeout)
  508. {
  509. wait = MsgWaitForMultipleObjects( 1, &process, FALSE, timeout - diff, QS_ALLINPUT );
  510. if (wait != WAIT_OBJECT_0 + 1) return wait;
  511. while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
  512. diff = GetTickCount() - start;
  513. }
  514. return WAIT_TIMEOUT;
  515. }
  516. static void append_path( const char *path)
  517. {
  518. char *newpath;
  519. newpath = heap_alloc(strlen(curpath) + 1 + strlen(path) + 1);
  520. strcpy(newpath, curpath);
  521. strcat(newpath, ";");
  522. strcat(newpath, path);
  523. SetEnvironmentVariableA("PATH", newpath);
  524. heap_free(newpath);
  525. }
  526. /* Run a command for MS milliseconds. If OUT != NULL, also redirect
  527. stdout to there.
  528. Return the exit status, -2 if can't create process or the return
  529. value of WaitForSingleObject.
  530. */
  531. static int
  532. run_ex (char *cmd, HANDLE out_file, const char *tempdir, DWORD ms, BOOL nocritical, DWORD* pid)
  533. {
  534. STARTUPINFOA si;
  535. PROCESS_INFORMATION pi;
  536. DWORD wait, status, flags;
  537. UINT old_errmode;
  538. /* Flush to disk so we know which test caused Windows to crash if it does */
  539. if (out_file)
  540. FlushFileBuffers(out_file);
  541. GetStartupInfoA (&si);
  542. si.dwFlags = STARTF_USESTDHANDLES;
  543. si.hStdInput = GetStdHandle( STD_INPUT_HANDLE );
  544. si.hStdOutput = out_file ? out_file : GetStdHandle( STD_OUTPUT_HANDLE );
  545. si.hStdError = out_file ? out_file : GetStdHandle( STD_ERROR_HANDLE );
  546. if (nocritical)
  547. {
  548. old_errmode = SetErrorMode(0);
  549. SetErrorMode(old_errmode | SEM_FAILCRITICALERRORS);
  550. flags = 0;
  551. }
  552. else
  553. flags = CREATE_DEFAULT_ERROR_MODE;
  554. if (!CreateProcessA (NULL, cmd, NULL, NULL, TRUE, flags,
  555. NULL, tempdir, &si, &pi))
  556. {
  557. if (nocritical) SetErrorMode(old_errmode);
  558. if (pid) *pid = 0;
  559. return -2;
  560. }
  561. if (nocritical) SetErrorMode(old_errmode);
  562. CloseHandle (pi.hThread);
  563. if (pid) *pid = pi.dwProcessId;
  564. status = wait_process( pi.hProcess, ms );
  565. switch (status)
  566. {
  567. case WAIT_OBJECT_0:
  568. GetExitCodeProcess (pi.hProcess, &status);
  569. CloseHandle (pi.hProcess);
  570. return status;
  571. case WAIT_FAILED:
  572. report (R_ERROR, "Wait for '%s' failed: %d", cmd, GetLastError ());
  573. break;
  574. case WAIT_TIMEOUT:
  575. break;
  576. default:
  577. report (R_ERROR, "Wait returned %d", status);
  578. break;
  579. }
  580. if (!TerminateProcess (pi.hProcess, 257))
  581. report (R_ERROR, "TerminateProcess failed: %d", GetLastError ());
  582. wait = wait_process( pi.hProcess, 5000 );
  583. switch (wait)
  584. {
  585. case WAIT_OBJECT_0:
  586. break;
  587. case WAIT_FAILED:
  588. report (R_ERROR, "Wait for termination of '%s' failed: %d", cmd, GetLastError ());
  589. break;
  590. case WAIT_TIMEOUT:
  591. report (R_ERROR, "Can't kill process '%s'", cmd);
  592. break;
  593. default:
  594. report (R_ERROR, "Waiting for termination: %d", wait);
  595. break;
  596. }
  597. CloseHandle (pi.hProcess);
  598. return status;
  599. }
  600. static DWORD
  601. get_subtests (const char *tempdir, struct wine_test *test, LPSTR res_name)
  602. {
  603. char *cmd;
  604. HANDLE subfile;
  605. DWORD err, total;
  606. char buffer[8192], *index;
  607. static const char header[] = "Valid test names:";
  608. int status, allocated;
  609. char tmpdir[MAX_PATH], subname[MAX_PATH];
  610. SECURITY_ATTRIBUTES sa;
  611. test->subtest_count = 0;
  612. if (!GetTempPathA( MAX_PATH, tmpdir ) ||
  613. !GetTempFileNameA( tmpdir, "sub", 0, subname ))
  614. report (R_FATAL, "Can't name subtests file.");
  615. /* make handle inheritable */
  616. sa.nLength = sizeof(sa);
  617. sa.lpSecurityDescriptor = NULL;
  618. sa.bInheritHandle = TRUE;
  619. subfile = CreateFileA( subname, GENERIC_READ|GENERIC_WRITE,
  620. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  621. &sa, CREATE_ALWAYS, 0, NULL );
  622. if ((subfile == INVALID_HANDLE_VALUE) &&
  623. (GetLastError() == ERROR_INVALID_PARAMETER)) {
  624. /* FILE_SHARE_DELETE not supported on win9x */
  625. subfile = CreateFileA( subname, GENERIC_READ|GENERIC_WRITE,
  626. FILE_SHARE_READ | FILE_SHARE_WRITE,
  627. &sa, CREATE_ALWAYS, 0, NULL );
  628. }
  629. if (subfile == INVALID_HANDLE_VALUE) {
  630. err = GetLastError();
  631. report (R_ERROR, "Can't open subtests output of %s: %u",
  632. test->name, GetLastError());
  633. goto quit;
  634. }
  635. cmd = strmake (NULL, "%s --list", test->exename);
  636. if (test->maindllpath) {
  637. /* We need to add the path (to the main dll) to PATH */
  638. append_path(test->maindllpath);
  639. }
  640. status = run_ex (cmd, subfile, tempdir, 5000, TRUE, NULL);
  641. err = GetLastError();
  642. if (test->maindllpath) {
  643. /* Restore PATH again */
  644. SetEnvironmentVariableA("PATH", curpath);
  645. }
  646. heap_free (cmd);
  647. if (status)
  648. {
  649. if (status == -2)
  650. report (R_ERROR, "Cannot run %s error %u", test->exename, err);
  651. else
  652. err = status;
  653. CloseHandle( subfile );
  654. goto quit;
  655. }
  656. SetFilePointer( subfile, 0, NULL, FILE_BEGIN );
  657. ReadFile( subfile, buffer, sizeof(buffer), &total, NULL );
  658. CloseHandle( subfile );
  659. if (sizeof buffer == total) {
  660. report (R_ERROR, "Subtest list of %s too big.",
  661. test->name, sizeof buffer);
  662. err = ERROR_OUTOFMEMORY;
  663. goto quit;
  664. }
  665. buffer[total] = 0;
  666. index = strstr (buffer, header);
  667. if (!index) {
  668. report (R_ERROR, "Can't parse subtests output of %s",
  669. test->name);
  670. err = ERROR_INTERNAL_ERROR;
  671. goto quit;
  672. }
  673. index += sizeof header;
  674. allocated = 10;
  675. test->subtests = heap_alloc (allocated * sizeof(char*));
  676. index = strtok (index, whitespace);
  677. while (index) {
  678. if (test->subtest_count == allocated) {
  679. allocated *= 2;
  680. test->subtests = heap_realloc (test->subtests,
  681. allocated * sizeof(char*));
  682. }
  683. test->subtests[test->subtest_count++] = heap_strdup(index);
  684. index = strtok (NULL, whitespace);
  685. }
  686. test->subtests = heap_realloc (test->subtests,
  687. test->subtest_count * sizeof(char*));
  688. err = 0;
  689. quit:
  690. if (!DeleteFileA (subname))
  691. report (R_WARNING, "Can't delete file '%s': %u", subname, GetLastError());
  692. return err;
  693. }
  694. static void
  695. run_test (struct wine_test* test, const char* subtest, HANDLE out_file, const char *tempdir)
  696. {
  697. /* Build the source filename so analysis tools can link to it */
  698. const char* file = get_test_source_file(test->name, subtest);
  699. if (test_filtered_out( test->name, subtest ))
  700. {
  701. report (R_STEP, "Skipping: %s:%s", test->name, subtest);
  702. xprintf ("%s:%s skipped %s\n", test->name, subtest, file);
  703. nr_of_skips++;
  704. }
  705. else
  706. {
  707. int status;
  708. DWORD pid, start = GetTickCount();
  709. char *cmd = strmake (NULL, "%s %s", test->exename, subtest);
  710. report (R_STEP, "Running: %s:%s", test->name, subtest);
  711. xprintf ("%s:%s start %s\n", test->name, subtest, file);
  712. status = run_ex (cmd, out_file, tempdir, 120000, FALSE, &pid);
  713. if (status == -2) status = -GetLastError();
  714. heap_free (cmd);
  715. xprintf ("%s:%s:%04x done (%d) in %ds\n", test->name, subtest, pid, status, (GetTickCount()-start)/1000);
  716. if (status) failures++;
  717. }
  718. if (failures) report (R_STATUS, "Running tests - %u failures", failures);
  719. }
  720. static BOOL CALLBACK
  721. EnumTestFileProc (HMODULE hModule, LPCSTR lpszType,
  722. LPSTR lpszName, LONG_PTR lParam)
  723. {
  724. if (!test_filtered_out( lpszName, NULL )) (*(int*)lParam)++;
  725. return TRUE;
  726. }
  727. static const struct clsid_mapping
  728. {
  729. const char *name;
  730. CLSID clsid;
  731. } clsid_list[] =
  732. {
  733. {"oledb32", {0xc8b522d1, 0x5cf3, 0x11ce, {0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d}}},
  734. {NULL, {0, 0, 0, {0,0,0,0,0,0,0,0}}}
  735. };
  736. static BOOL get_main_clsid(const char *name, CLSID *clsid)
  737. {
  738. const struct clsid_mapping *mapping;
  739. for(mapping = clsid_list; mapping->name; mapping++)
  740. {
  741. if(!strcasecmp(name, mapping->name))
  742. {
  743. *clsid = mapping->clsid;
  744. return TRUE;
  745. }
  746. }
  747. return FALSE;
  748. }
  749. static HMODULE load_com_dll(const char *name, char **path, char *filename)
  750. {
  751. HMODULE dll = NULL;
  752. HKEY hkey;
  753. char keyname[100];
  754. char dllname[MAX_PATH];
  755. char *p;
  756. CLSID clsid;
  757. if(!get_main_clsid(name, &clsid)) return NULL;
  758. sprintf(keyname, "CLSID\\{%08x-%04x-%04x-%02x%2x-%02x%2x%02x%2x%02x%2x}\\InprocServer32",
  759. clsid.Data1, clsid.Data2, clsid.Data3, clsid.Data4[0], clsid.Data4[1],
  760. clsid.Data4[2], clsid.Data4[3], clsid.Data4[4], clsid.Data4[5],
  761. clsid.Data4[6], clsid.Data4[7]);
  762. if(RegOpenKeyA(HKEY_CLASSES_ROOT, keyname, &hkey) == ERROR_SUCCESS)
  763. {
  764. LONG size = sizeof(dllname);
  765. if(RegQueryValueA(hkey, NULL, dllname, &size) == ERROR_SUCCESS)
  766. {
  767. if ((dll = LoadLibraryExA(dllname, NULL, LOAD_LIBRARY_AS_DATAFILE)))
  768. {
  769. strcpy( filename, dllname );
  770. p = strrchr(dllname, '\\');
  771. if (p) *p = 0;
  772. *path = heap_strdup( dllname );
  773. }
  774. }
  775. RegCloseKey(hkey);
  776. }
  777. return dll;
  778. }
  779. static void get_dll_path(HMODULE dll, char **path, char *filename)
  780. {
  781. char dllpath[MAX_PATH];
  782. GetModuleFileNameA(dll, dllpath, MAX_PATH);
  783. strcpy(filename, dllpath);
  784. *strrchr(dllpath, '\\') = '\0';
  785. *path = heap_strdup( dllpath );
  786. }
  787. static BOOL CALLBACK
  788. extract_test_proc (HMODULE hModule, LPCSTR lpszType, LPSTR lpszName, LONG_PTR lParam)
  789. {
  790. const char *tempdir = (const char *)lParam;
  791. char dllname[MAX_PATH];
  792. char filename[MAX_PATH];
  793. WCHAR dllnameW[MAX_PATH];
  794. HMODULE dll;
  795. DWORD err;
  796. HANDLE actctx;
  797. ULONG_PTR cookie;
  798. BOOL run;
  799. if (aborting) return TRUE;
  800. /* Check if the main dll is present on this system */
  801. CharLowerA(lpszName);
  802. strcpy(dllname, lpszName);
  803. *strstr(dllname, testexe) = 0;
  804. if (test_filtered_out( lpszName, NULL ))
  805. {
  806. nr_of_skips++;
  807. if (exclude_tests) xprintf (" %s=skipped\n", dllname);
  808. return TRUE;
  809. }
  810. extract_test (&wine_tests[nr_of_files], tempdir, lpszName);
  811. if (pCreateActCtxA != NULL && pActivateActCtx != NULL &&
  812. pDeactivateActCtx != NULL && pReleaseActCtx != NULL)
  813. {
  814. ACTCTXA actctxinfo;
  815. memset(&actctxinfo, 0, sizeof(ACTCTXA));
  816. actctxinfo.cbSize = sizeof(ACTCTXA);
  817. actctxinfo.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
  818. actctxinfo.lpSource = wine_tests[nr_of_files].exename;
  819. actctxinfo.lpResourceName = (LPSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
  820. actctx = pCreateActCtxA(&actctxinfo);
  821. if (actctx != INVALID_HANDLE_VALUE &&
  822. ! pActivateActCtx(actctx, &cookie))
  823. {
  824. pReleaseActCtx(actctx);
  825. actctx = INVALID_HANDLE_VALUE;
  826. }
  827. } else actctx = INVALID_HANDLE_VALUE;
  828. wine_tests[nr_of_files].maindllpath = NULL;
  829. strcpy(filename, dllname);
  830. dll = LoadLibraryExA(dllname, NULL, LOAD_LIBRARY_AS_DATAFILE);
  831. if (!dll) dll = load_com_dll(dllname, &wine_tests[nr_of_files].maindllpath, filename);
  832. if (!dll && pLoadLibraryShim)
  833. {
  834. MultiByteToWideChar(CP_ACP, 0, dllname, -1, dllnameW, MAX_PATH);
  835. if (SUCCEEDED( pLoadLibraryShim(dllnameW, NULL, NULL, &dll) ) && dll)
  836. {
  837. get_dll_path(dll, &wine_tests[nr_of_files].maindllpath, filename);
  838. FreeLibrary(dll);
  839. dll = LoadLibraryExA(filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
  840. }
  841. else dll = 0;
  842. }
  843. run = TRUE;
  844. if (dll)
  845. {
  846. if (is_stub_dll(dllname))
  847. {
  848. xprintf (" %s=dll is a stub\n", dllname);
  849. run = FALSE;
  850. }
  851. else if (is_native_dll(dll))
  852. {
  853. xprintf (" %s=dll is native\n", dllname);
  854. nr_native_dlls++;
  855. run = FALSE;
  856. }
  857. FreeLibrary(dll);
  858. }
  859. if (run)
  860. {
  861. err = get_subtests( tempdir, &wine_tests[nr_of_files], lpszName );
  862. switch (err)
  863. {
  864. case 0:
  865. xprintf (" %s=%s\n", dllname, get_file_version(filename));
  866. nr_of_tests += wine_tests[nr_of_files].subtest_count;
  867. nr_of_files++;
  868. break;
  869. case STATUS_DLL_NOT_FOUND:
  870. xprintf (" %s=dll is missing\n", dllname);
  871. /* or it is a side-by-side dll but the test has no manifest */
  872. break;
  873. case STATUS_ORDINAL_NOT_FOUND:
  874. xprintf (" %s=dll is missing an ordinal (%s)\n", dllname, get_file_version(filename));
  875. break;
  876. case STATUS_ENTRYPOINT_NOT_FOUND:
  877. xprintf (" %s=dll is missing an entrypoint (%s)\n", dllname, get_file_version(filename));
  878. break;
  879. case ERROR_SXS_CANT_GEN_ACTCTX:
  880. xprintf (" %s=dll is missing the requested side-by-side version\n", dllname);
  881. break;
  882. default:
  883. xprintf (" %s=load error %u\n", dllname, err);
  884. break;
  885. }
  886. }
  887. if (actctx != INVALID_HANDLE_VALUE)
  888. {
  889. pDeactivateActCtx(0, cookie);
  890. pReleaseActCtx(actctx);
  891. }
  892. return TRUE;
  893. }
  894. static char *
  895. run_tests (char *logname, char *outdir)
  896. {
  897. int i;
  898. char *strres, *eol, *nextline;
  899. DWORD strsize;
  900. SECURITY_ATTRIBUTES sa;
  901. char tmppath[MAX_PATH], tempdir[MAX_PATH+4];
  902. BOOL newdir;
  903. DWORD needed;
  904. HMODULE kernel32;
  905. /* Get the current PATH only once */
  906. needed = GetEnvironmentVariableA("PATH", NULL, 0);
  907. curpath = heap_alloc(needed);
  908. GetEnvironmentVariableA("PATH", curpath, needed);
  909. SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
  910. if (!GetTempPathA( MAX_PATH, tmppath ))
  911. report (R_FATAL, "Can't name temporary dir (check %%TEMP%%).");
  912. if (!logname) {
  913. static char tmpname[MAX_PATH];
  914. if (!GetTempFileNameA( tmppath, "res", 0, tmpname ))
  915. report (R_FATAL, "Can't name logfile.");
  916. logname = tmpname;
  917. }
  918. report (R_OUT, logname);
  919. /* make handle inheritable */
  920. sa.nLength = sizeof(sa);
  921. sa.lpSecurityDescriptor = NULL;
  922. sa.bInheritHandle = TRUE;
  923. logfile = strcmp(logname, "-") == 0 ? GetStdHandle( STD_OUTPUT_HANDLE ) :
  924. CreateFileA( logname, GENERIC_READ|GENERIC_WRITE,
  925. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  926. &sa, CREATE_ALWAYS, 0, NULL );
  927. if ((logfile == INVALID_HANDLE_VALUE) &&
  928. (GetLastError() == ERROR_INVALID_PARAMETER)) {
  929. /* FILE_SHARE_DELETE not supported on win9x */
  930. logfile = CreateFileA( logname, GENERIC_READ|GENERIC_WRITE,
  931. FILE_SHARE_READ | FILE_SHARE_WRITE,
  932. &sa, CREATE_ALWAYS, 0, NULL );
  933. }
  934. if (logfile == INVALID_HANDLE_VALUE)
  935. report (R_FATAL, "Could not open logfile: %u", GetLastError());
  936. if (outdir)
  937. {
  938. /* Get a full path so it is still valid after a chdir */
  939. GetFullPathNameA( outdir, ARRAY_SIZE(tempdir), tempdir, NULL );
  940. }
  941. else
  942. {
  943. strcpy( tempdir, tmppath );
  944. strcat( tempdir, "wct" ); /* try stable path for ZoneAlarm */
  945. }
  946. newdir = CreateDirectoryA( tempdir, NULL );
  947. if (!newdir && !outdir)
  948. {
  949. if (!GetTempFileNameA( tmppath, "wct", 0, tempdir ))
  950. report (R_FATAL, "Can't name temporary dir (check %%TEMP%%).");
  951. DeleteFileA( tempdir );
  952. newdir = CreateDirectoryA( tempdir, NULL );
  953. }
  954. if (!newdir && (!outdir || GetLastError() != ERROR_ALREADY_EXISTS))
  955. report (R_FATAL, "Could not create directory %s (%d)", tempdir, GetLastError());
  956. report (R_DIR, tempdir);
  957. xprintf ("Version 4\n");
  958. xprintf ("Tests from build %s\n", build_id[0] ? build_id : "-" );
  959. xprintf ("Archive: -\n"); /* no longer used */
  960. xprintf ("Tag: %s\n", tag);
  961. xprintf ("Build info:\n");
  962. strres = extract_rcdata ("BUILD_INFO", "STRINGRES", &strsize);
  963. while (strres) {
  964. eol = memchr (strres, '\n', strsize);
  965. if (!eol) {
  966. nextline = NULL;
  967. eol = strres + strsize;
  968. } else {
  969. strsize -= eol - strres + 1;
  970. nextline = strsize?eol+1:NULL;
  971. if (eol > strres && *(eol-1) == '\r') eol--;
  972. }
  973. xprintf (" %.*s\n", eol-strres, strres);
  974. strres = nextline;
  975. }
  976. xprintf ("Operating system version:\n");
  977. print_version ();
  978. print_language ();
  979. xprintf ("Dll info:\n" );
  980. report (R_STATUS, "Counting tests");
  981. if (!EnumResourceNamesA (NULL, "TESTRES", EnumTestFileProc, (LPARAM)&nr_of_files))
  982. report (R_FATAL, "Can't enumerate test files: %d",
  983. GetLastError ());
  984. wine_tests = heap_alloc (nr_of_files * sizeof wine_tests[0]);
  985. /* Do this only once during extraction (and version checking) */
  986. hmscoree = LoadLibraryA("mscoree.dll");
  987. pLoadLibraryShim = NULL;
  988. if (hmscoree)
  989. pLoadLibraryShim = (void *)GetProcAddress(hmscoree, "LoadLibraryShim");
  990. kernel32 = GetModuleHandleA("kernel32.dll");
  991. pCreateActCtxA = (void *)GetProcAddress(kernel32, "CreateActCtxA");
  992. pActivateActCtx = (void *)GetProcAddress(kernel32, "ActivateActCtx");
  993. pDeactivateActCtx = (void *)GetProcAddress(kernel32, "DeactivateActCtx");
  994. pReleaseActCtx = (void *)GetProcAddress(kernel32, "ReleaseActCtx");
  995. report (R_STATUS, "Extracting tests");
  996. report (R_PROGRESS, 0, nr_of_files);
  997. nr_of_files = 0;
  998. nr_of_tests = 0;
  999. nr_of_skips = 0;
  1000. if (!EnumResourceNamesA (NULL, "TESTRES", extract_test_proc, (LPARAM)tempdir))
  1001. report (R_FATAL, "Can't enumerate test files: %d",
  1002. GetLastError ());
  1003. FreeLibrary(hmscoree);
  1004. if (aborting) return logname;
  1005. xprintf ("Test output:\n" );
  1006. report (R_DELTA, 0, "Extracting: Done");
  1007. if (nr_native_dlls)
  1008. report( R_WARNING, "Some dlls are configured as native, you won't be able to submit results." );
  1009. report (R_STATUS, "Running tests");
  1010. report (R_PROGRESS, 1, nr_of_tests);
  1011. for (i = 0; i < nr_of_files; i++) {
  1012. struct wine_test *test = wine_tests + i;
  1013. int j;
  1014. if (aborting) break;
  1015. if (test->maindllpath) {
  1016. /* We need to add the path (to the main dll) to PATH */
  1017. append_path(test->maindllpath);
  1018. }
  1019. for (j = 0; j < test->subtest_count; j++) {
  1020. if (aborting) break;
  1021. run_test (test, test->subtests[j], logfile, tempdir);
  1022. }
  1023. if (test->maindllpath) {
  1024. /* Restore PATH again */
  1025. SetEnvironmentVariableA("PATH", curpath);
  1026. }
  1027. }
  1028. report (R_DELTA, 0, "Running: Done");
  1029. report (R_STATUS, "Cleaning up - %u failures", failures);
  1030. if (strcmp(logname, "-") != 0) CloseHandle( logfile );
  1031. logfile = 0;
  1032. if (newdir)
  1033. remove_dir (tempdir);
  1034. heap_free(wine_tests);
  1035. heap_free(curpath);
  1036. return logname;
  1037. }
  1038. static BOOL WINAPI ctrl_handler(DWORD ctrl_type)
  1039. {
  1040. if (ctrl_type == CTRL_C_EVENT) {
  1041. printf("Ignoring Ctrl-C, use Ctrl-Break if you really want to terminate\n");
  1042. return TRUE;
  1043. }
  1044. return FALSE;
  1045. }
  1046. static BOOL CALLBACK
  1047. extract_only_proc (HMODULE hModule, LPCSTR lpszType, LPSTR lpszName, LONG_PTR lParam)
  1048. {
  1049. const char *target_dir = (const char *)lParam;
  1050. char filename[MAX_PATH];
  1051. if (test_filtered_out( lpszName, NULL )) return TRUE;
  1052. strcpy(filename, lpszName);
  1053. CharLowerA(filename);
  1054. extract_test( &wine_tests[nr_of_files], target_dir, filename );
  1055. nr_of_files++;
  1056. return TRUE;
  1057. }
  1058. static void extract_only (const char *target_dir)
  1059. {
  1060. BOOL res;
  1061. report (R_DIR, target_dir);
  1062. res = CreateDirectoryA( target_dir, NULL );
  1063. if (!res && GetLastError() != ERROR_ALREADY_EXISTS)
  1064. report (R_FATAL, "Could not create directory: %s (%d)", target_dir, GetLastError ());
  1065. nr_of_files = 0;
  1066. report (R_STATUS, "Counting tests");
  1067. if (!EnumResourceNamesA(NULL, "TESTRES", EnumTestFileProc, (LPARAM)&nr_of_files))
  1068. report (R_FATAL, "Can't enumerate test files: %d", GetLastError ());
  1069. wine_tests = heap_alloc (nr_of_files * sizeof wine_tests[0] );
  1070. report (R_STATUS, "Extracting tests");
  1071. report (R_PROGRESS, 0, nr_of_files);
  1072. nr_of_files = 0;
  1073. if (!EnumResourceNamesA(NULL, "TESTRES", extract_only_proc, (LPARAM)target_dir))
  1074. report (R_FATAL, "Can't enumerate test files: %d", GetLastError ());
  1075. report (R_DELTA, 0, "Extracting: Done");
  1076. }
  1077. static void
  1078. usage (void)
  1079. {
  1080. fprintf (stderr,
  1081. "Usage: winetest [OPTION]... [TESTS]\n\n"
  1082. " --help print this message and exit\n"
  1083. " --version print the build version and exit\n"
  1084. " -c console mode, no GUI\n"
  1085. " -d DIR Use DIR as temp directory (default: %%TEMP%%\\wct)\n"
  1086. " -e preserve the environment\n"
  1087. " -h print this message and exit\n"
  1088. " -i INFO an optional description of the test platform\n"
  1089. " -m MAIL an email address to enable developers to contact you\n"
  1090. " -n exclude the specified tests\n"
  1091. " -p shutdown when the tests are done\n"
  1092. " -q quiet mode, no output at all\n"
  1093. " -o FILE put report into FILE, do not submit\n"
  1094. " -s FILE submit FILE, do not run tests\n"
  1095. " -S URL URL to submit the results to\n"
  1096. " -t TAG include TAG of characters [-.0-9a-zA-Z] in the report\n"
  1097. " -u URL include TestBot URL in the report\n"
  1098. " -x DIR Extract tests to DIR (default: .\\wct) and exit\n");
  1099. }
  1100. int __cdecl main( int argc, char *argv[] )
  1101. {
  1102. BOOL (WINAPI *pIsWow64Process)(HANDLE hProcess, PBOOL Wow64Process);
  1103. char *logname = NULL, *outdir = NULL;
  1104. const char *extract = NULL;
  1105. const char *cp, *submit = NULL, *submiturl = NULL;
  1106. int reset_env = 1;
  1107. int poweroff = 0;
  1108. int interactive = 1;
  1109. int i;
  1110. InitCommonControls();
  1111. if (!LoadStringA( 0, IDS_BUILD_ID, build_id, sizeof(build_id) )) build_id[0] = 0;
  1112. pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"),"IsWow64Process");
  1113. if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
  1114. for (i = 1; i < argc && argv[i]; i++)
  1115. {
  1116. if (!strcmp(argv[i], "--help")) {
  1117. usage ();
  1118. exit (0);
  1119. }
  1120. else if (!strcmp(argv[i], "--version")) {
  1121. printf("%-12.12s\n", build_id[0] ? build_id : "unknown");
  1122. exit (0);
  1123. }
  1124. else if ((argv[i][0] != '-' && argv[i][0] != '/') || argv[i][2]) {
  1125. if (nb_filters == ARRAY_SIZE(filters))
  1126. {
  1127. report (R_ERROR, "Too many test filters specified");
  1128. exit (2);
  1129. }
  1130. filters[nb_filters++] = argv[i];
  1131. }
  1132. else switch (argv[i][1]) {
  1133. case 'c':
  1134. report (R_TEXTMODE);
  1135. interactive = 0;
  1136. break;
  1137. case 'e':
  1138. reset_env = 0;
  1139. break;
  1140. case 'h':
  1141. case '?':
  1142. usage ();
  1143. exit (0);
  1144. case 'i':
  1145. if (!(description = argv[++i]))
  1146. {
  1147. usage();
  1148. exit( 2 );
  1149. }
  1150. break;
  1151. case 'm':
  1152. if (!(email = argv[++i]))
  1153. {
  1154. usage();
  1155. exit( 2 );
  1156. }
  1157. break;
  1158. case 'n':
  1159. exclude_tests = TRUE;
  1160. break;
  1161. case 'p':
  1162. poweroff = 1;
  1163. break;
  1164. case 'q':
  1165. report (R_QUIET);
  1166. interactive = 0;
  1167. break;
  1168. case 's':
  1169. if (!(submit = argv[++i]))
  1170. {
  1171. usage();
  1172. exit( 2 );
  1173. }
  1174. break;
  1175. case 'S':
  1176. if (!(submiturl = argv[++i]))
  1177. {
  1178. usage();
  1179. exit( 2 );
  1180. }
  1181. break;
  1182. case 'o':
  1183. if (!(logname = argv[++i]))
  1184. {
  1185. usage();
  1186. exit( 2 );
  1187. }
  1188. break;
  1189. case 't':
  1190. if (!(tag = argv[++i]))
  1191. {
  1192. usage();
  1193. exit( 2 );
  1194. }
  1195. if (strlen (tag) > MAXTAGLEN)
  1196. report (R_FATAL, "tag is too long (maximum %d characters)",
  1197. MAXTAGLEN);
  1198. cp = findbadtagchar (tag);
  1199. if (cp) {
  1200. report (R_ERROR, "invalid char in tag: %c", *cp);
  1201. usage ();
  1202. exit (2);
  1203. }
  1204. break;
  1205. case 'u':
  1206. if (!(url = argv[++i]))
  1207. {
  1208. usage();
  1209. exit( 2 );
  1210. }
  1211. break;
  1212. case 'x':
  1213. report (R_TEXTMODE);
  1214. if (!(extract = argv[++i]))
  1215. extract = ".\\wct";
  1216. extract_only (extract);
  1217. break;
  1218. case 'd':
  1219. outdir = argv[++i];
  1220. break;
  1221. default:
  1222. report (R_ERROR, "invalid option: -%c", argv[i][1]);
  1223. usage ();
  1224. exit (2);
  1225. }
  1226. }
  1227. if (submit) {
  1228. if (tag)
  1229. report (R_WARNING, "ignoring tag for submission");
  1230. send_file (submiturl, submit);
  1231. } else if (!extract) {
  1232. int is_win9x = (GetVersion() & 0x80000000) != 0;
  1233. report (R_STATUS, "Starting up");
  1234. if (is_win9x)
  1235. report (R_WARNING, "Running on win9x is not supported. You won't be able to submit results.");
  1236. if (!running_on_visible_desktop ())
  1237. report (R_FATAL, "Tests must be run on a visible desktop");
  1238. if (running_under_wine())
  1239. {
  1240. if (!check_mount_mgr())
  1241. report (R_FATAL, "Mount manager not running, most likely your WINEPREFIX wasn't created correctly.");
  1242. if (!check_wow64_registry())
  1243. report (R_FATAL, "WoW64 keys missing, most likely your WINEPREFIX wasn't created correctly.");
  1244. if (!check_display_driver())
  1245. report (R_FATAL, "Unable to create a window, the display driver is not working.");
  1246. }
  1247. SetConsoleCtrlHandler(ctrl_handler, TRUE);
  1248. if (reset_env)
  1249. {
  1250. SetEnvironmentVariableA( "WINETEST_PLATFORM", running_under_wine () ? "wine" : "windows" );
  1251. SetEnvironmentVariableA( "WINETEST_DEBUG", "1" );
  1252. SetEnvironmentVariableA( "WINETEST_INTERACTIVE", "0" );
  1253. SetEnvironmentVariableA( "WINETEST_REPORT_SUCCESS", "0" );
  1254. }
  1255. if (nb_filters && !exclude_tests)
  1256. {
  1257. run_tests( logname, outdir );
  1258. exit(0);
  1259. }
  1260. while (!tag) {
  1261. if (!interactive)
  1262. report (R_FATAL, "Please specify a tag (-t option) if "
  1263. "running noninteractive!");
  1264. if (guiAskTag () == IDABORT) exit (1);
  1265. }
  1266. report (R_TAG);
  1267. while (!email) {
  1268. if (!interactive)
  1269. report (R_FATAL, "Please specify an email address (-m option) to enable developers\n"
  1270. " to contact you about your report if necessary.");
  1271. if (guiAskEmail () == IDABORT) exit (1);
  1272. }
  1273. if (!build_id[0])
  1274. report( R_WARNING, "You won't be able to submit results without a valid build id.\n"
  1275. "To submit results, winetest needs to be built from a git checkout." );
  1276. if (!logname) {
  1277. logname = run_tests (NULL, outdir);
  1278. if (aborting) {
  1279. DeleteFileA(logname);
  1280. exit (0);
  1281. }
  1282. if (failures > FAILURES_LIMIT)
  1283. report( R_WARNING,
  1284. "%d tests failed. There is probably something broken with your setup.\n"
  1285. "You need to address this before submitting results.", failures );
  1286. if (build_id[0] && nr_of_skips <= SKIP_LIMIT && failures <= FAILURES_LIMIT &&
  1287. !nr_native_dlls && !is_win9x &&
  1288. report (R_ASK, MB_YESNO, "Do you want to submit the test results?") == IDYES)
  1289. if (!send_file (submiturl, logname) && !DeleteFileA(logname))
  1290. report (R_WARNING, "Can't remove logfile: %u", GetLastError());
  1291. } else run_tests (logname, outdir);
  1292. report (R_STATUS, "Finished - %u failures", failures);
  1293. }
  1294. if (poweroff)
  1295. {
  1296. HANDLE hToken;
  1297. TOKEN_PRIVILEGES npr;
  1298. /* enable the shutdown privilege for the current process */
  1299. if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
  1300. {
  1301. LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid);
  1302. npr.PrivilegeCount = 1;
  1303. npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  1304. AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0);
  1305. CloseHandle(hToken);
  1306. }
  1307. ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF | EWX_FORCEIFHUNG, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER);
  1308. }
  1309. exit (0);
  1310. }