Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1684 lines
44 KiB

  1. // define COBJMACROS so the IUnknown_Release() gets defined
  2. #define COBJMACROS
  3. // disable ddraw COM declarations. Otherwise ddrawint.h defineds _NO_COM
  4. // and includes ddraw.h. That causes ddraw.h to define IUnknown as 'void *'
  5. // which obliterates the struct IUnknown in objbase.h. This all happens
  6. // inside winddi.h
  7. #define _NO_DDRAWINT_NO_COM
  8. #include <nt.h>
  9. #include <ntrtl.h>
  10. #include <nturtl.h>
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <time.h>
  15. #include <objbase.h>
  16. #include <mshtml.h>
  17. #include <winddi.h>
  18. #include <io.h>
  19. #define PAGE_4K 0x1000
  20. // Assume an error happened. This variable controls whether a pass or fail
  21. // is logged in the test results.
  22. BOOL g_bError = TRUE;
  23. // Time the test started (only valid in the main process)
  24. time_t TestStartTime;
  25. FILE *fpLogFile;
  26. void __cdecl PrintToLog(char *format, ...)
  27. {
  28. va_list pArg;
  29. char buffer[4096];
  30. va_start(pArg, format);
  31. _vsnprintf(buffer, sizeof(buffer), format, pArg);
  32. buffer[sizeof(buffer)-1] = '\0';
  33. printf("%s", buffer);
  34. if (fpLogFile) {
  35. fprintf(fpLogFile, "%s", buffer);
  36. }
  37. }
  38. //////////// All this code runs in a worker thread in a child process //////
  39. //// Prefix any output by "WOW64BVT1" so it can be identified as coming from
  40. //// the child process.
  41. // This routine is invoked when "childprocess" is passed on the command-line.
  42. // The child runs synchronously with the parent to maximize the test coverage.
  43. int BeAChildProcess(void)
  44. {
  45. HRESULT hr;
  46. IUnknown *pUnk;
  47. CLSID clsid;
  48. HWND hwnd;
  49. PrintToLog("WOW64BVT1: Child process running\n");
  50. // Do some COM stuff here
  51. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED|COINIT_DISABLE_OLE1DDE);
  52. if (FAILED(hr)) {
  53. PrintToLog("ERROR: WOW64BVT1: CoInitializeEx failed %x\n", hr);
  54. return 3;
  55. }
  56. // Load and call 32-bit mshtml inproc
  57. hr = CLSIDFromProgID(L"Shell.Explorer", &clsid);
  58. if (FAILED(hr)) {
  59. PrintToLog("ERROR: WOW64BVT1: CLSIDFromProgID for Shell.Explorer failed %x\n", hr);
  60. return 3;
  61. }
  62. #if 0 // The cocreate fails on IA64 with 8007000e (E_OUTOFMEMORY)
  63. hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (PVOID *)&pUnk);
  64. if (FAILED(hr)) {
  65. PrintToLog("ERROR: WOW64BVT1: CoCreateInstance for Shell.Explorer failed %x\n", hr);
  66. return 3;
  67. }
  68. Sleep(1000);
  69. IUnknown_Release(pUnk);
  70. pUnk = NULL;
  71. #endif
  72. // Load and call mplay32.exe out-of-proc
  73. #if 0 // The clsidfromprogid fails on IA64 with 800401f3 (CO_E_CLASSSTRING)
  74. hr = CLSIDFromProgID(L"MediaPlayer.MediaPlayer.1", &clsid);
  75. if (FAILED(hr)) {
  76. PrintToLog("ERROR: WOW64BVT1: CLSIDFromProgID for MediaPlayer.MediaPlayer failed %x\n", hr);
  77. return 3;
  78. }
  79. hr = CoCreateInstance(&clsid, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (PVOID *)&pUnk);
  80. if (FAILED(hr)) {
  81. PrintToLog("ERROR: WOW64BVT1: CoCreateInstance for MediaPlayer.MediaPlayer failed %x\n", hr);
  82. return 3;
  83. }
  84. Sleep(5000);
  85. IUnknown_Release(pUnk);
  86. pUnk = NULL;
  87. #endif
  88. // Unfortunately, mplay32 has a refcounting problem and doesn't close
  89. // when we release it. Post a quit message to make it close.
  90. hwnd = FindWindowW(NULL, L"Windows Media Player");
  91. if (hwnd) {
  92. PostMessage(hwnd, WM_QUIT, 0, 0);
  93. }
  94. // Wrap up COM now
  95. CoUninitialize();
  96. PrintToLog("WOW64BVT1: Child process done OK.\n");
  97. return 0;
  98. }
  99. //////////// All this code runs in a worker thread in the main process //////
  100. //// Prefix any output by "WOW64BVT" so it can be identified as coming from
  101. //// the parent process.
  102. DWORD BeAThread(LPVOID lpParam)
  103. {
  104. NTSTATUS st;
  105. LPWSTR lp;
  106. PrintToLog("WOW64BVT: Worker thread running\n");
  107. // Call an API close to the end of whnt32.c's dispatch table
  108. st = NtYieldExecution();
  109. if (FAILED(st)) {
  110. PrintToLog("ERROR: WOW64BVT: NtYieldExecution failed %x\n", st);
  111. exit(1);
  112. }
  113. // Call an API close to the end of whwin32.c's dispatch table. Pass NULL,
  114. // so it is expected to fail.
  115. lp = EngGetPrinterDataFileName(NULL); // calls NtGdiGetDhpdev()
  116. if (lp) {
  117. // It succeeded.... it shouldn't have since
  118. PrintToLog("ERROR: WOW64BVT: EngGetPrinterDataFileName succeeeded when it should not have.\n");
  119. exit(1);
  120. }
  121. PrintToLog("WOW64BVT: Worker thread done OK.\n");
  122. return 0;
  123. }
  124. HANDLE CreateTheThread(void)
  125. {
  126. HANDLE h;
  127. DWORD dwThreadId;
  128. PrintToLog("WOW64BVT: Creating child thread\n");
  129. h = CreateThread(NULL, 0, BeAThread, NULL, 0, &dwThreadId);
  130. if (h == INVALID_HANDLE_VALUE) {
  131. PrintToLog("ERROR: WOW64BVT: Error %d creating worker thread.\n", GetLastError());
  132. exit(2);
  133. }
  134. // Sleep a bit here, to try and let the child thread run a bit
  135. Sleep(10);
  136. return h;
  137. }
  138. BOOL AllocateStackAndTouch(
  139. INT Count)
  140. {
  141. char temp[4096];
  142. memset(temp, 0, sizeof(temp));
  143. if (--Count) {
  144. AllocateStackAndTouch(Count);
  145. }
  146. return TRUE;
  147. }
  148. DWORD WINAPI TestGuardPagesThreadProc(
  149. PVOID lpParam)
  150. {
  151. try {
  152. AllocateStackAndTouch(PtrToUlong(lpParam));
  153. } except(EXCEPTION_EXECUTE_HANDLER) {
  154. PrintToLog("ERROR: WOW64BVT: Error allocating stack. Exception Code = %lx\n",
  155. GetExceptionCode());
  156. exit(1);
  157. }
  158. return 0;
  159. }
  160. int TestGuardPages(
  161. VOID)
  162. {
  163. HANDLE h;
  164. DWORD dwExitCode, dwThreadId;
  165. BOOL b;
  166. ULONG NestedStackCount = 100;
  167. DWORD StackSize = 4096;
  168. PrintToLog("WOW64BVT: Creating worker threads to test guard pages\n");
  169. while (StackSize < (32768+1))
  170. {
  171. h = CreateThread(NULL,
  172. StackSize,
  173. TestGuardPagesThreadProc,
  174. UlongToPtr(NestedStackCount),
  175. 0,
  176. &dwThreadId);
  177. if (h == INVALID_HANDLE_VALUE) {
  178. PrintToLog("ERROR: WOW64BVT: Error %d creating worker thread for guard page tests.\n", GetLastError());
  179. exit(2);
  180. }
  181. StackSize += 4096;
  182. WaitForSingleObject(h, INFINITE);
  183. b = GetExitCodeThread(h, &dwExitCode);
  184. if (b) {
  185. if (dwExitCode) {
  186. return (int)dwExitCode;
  187. }
  188. } else {
  189. PrintToLog("ERROR: GetExitCodeThread failed with LastError = %d\n", GetLastError());
  190. return 1;
  191. }
  192. }
  193. PrintToLog("WOW64BVT: Test guard pages done OK.\n");
  194. return 0;
  195. }
  196. int TestMemoryMappedFiles(
  197. VOID)
  198. {
  199. HANDLE Handle;
  200. PWCHAR pwc;
  201. MEMORY_BASIC_INFORMATION mbi;
  202. BOOL ExceptionHappened = FALSE;
  203. PrintToLog("WOW64BVT: Testing memory mapped files\n");
  204. Handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
  205. NULL,
  206. SEC_RESERVE | PAGE_READWRITE,
  207. 0,
  208. 32 * 1024,
  209. L"HelloWorld");
  210. if (Handle == INVALID_HANDLE_VALUE) {
  211. PrintToLog("ERROR: WOW64BVT : Error %d creating file mapping\n", GetLastError());
  212. return 1;
  213. }
  214. pwc = (PWCHAR)MapViewOfFile(Handle,
  215. FILE_MAP_WRITE,
  216. 0,
  217. 0,
  218. 0);
  219. if (!pwc) {
  220. PrintToLog("ERROR: WOW64BVT : Error %d mapping section object\n", GetLastError());
  221. return 1;
  222. }
  223. if (!VirtualQuery(pwc,
  224. &mbi,
  225. sizeof(mbi))) {
  226. PrintToLog("ERROR: WOW64BVT : Virtual query failed with last error = %d\n", GetLastError());
  227. return 1;
  228. }
  229. if (mbi.State != MEM_RESERVE) {
  230. PrintToLog("ERROR: WOW64BVT : Memory attributes have changed since mapped %lx\n", mbi.State);
  231. return 1;
  232. }
  233. try {
  234. *pwc = *(pwc+1);
  235. } except(EXCEPTION_EXECUTE_HANDLER) {
  236. ExceptionHappened = TRUE;
  237. }
  238. if (ExceptionHappened == FALSE) {
  239. PrintToLog("ERROR: WOW64BVT : Memory has been committed while it should have ONLY been reserved.\n");
  240. return 1;
  241. }
  242. if (!VirtualQuery(pwc,
  243. &mbi,
  244. sizeof(mbi))) {
  245. PrintToLog("ERROR: WOW64BVT : Virtual query failed with last error = %d\n", GetLastError());
  246. return 1;
  247. }
  248. if (mbi.State != MEM_RESERVE) {
  249. PrintToLog("ERROR: WOW64BVT : Memory attributes have changed since mapped %lx\n", mbi.State);
  250. return 1;
  251. }
  252. UnmapViewOfFile(pwc);
  253. CloseHandle(Handle);
  254. PrintToLog("WOW64BVT: Testing memory mapped files done OK.\n");
  255. return 0;
  256. }
  257. BOOL ReleasePages(PVOID Address,
  258. DWORD DeAllocationType,
  259. SIZE_T ReleasedPages)
  260. {
  261. PVOID p = Address;
  262. SIZE_T nPages = ReleasedPages;
  263. NTSTATUS NtStatus;
  264. NtStatus = NtFreeVirtualMemory(NtCurrentProcess(),
  265. &p,
  266. &nPages,
  267. DeAllocationType);
  268. return NT_SUCCESS(NtStatus);
  269. }
  270. BOOL VerifyPages(PVOID Address,
  271. DWORD DeAllocationType,
  272. SIZE_T ReleasedPages)
  273. {
  274. DWORD PagesState;
  275. BOOL b;
  276. MEMORY_BASIC_INFORMATION mbi;
  277. if (DeAllocationType == MEM_DECOMMIT)
  278. {
  279. PagesState = MEM_RESERVE;
  280. }
  281. else if (DeAllocationType == MEM_RELEASE)
  282. {
  283. PagesState = MEM_FREE;
  284. }
  285. else
  286. {
  287. PagesState = DeAllocationType;
  288. }
  289. b = VirtualQuery(Address,
  290. &mbi,
  291. sizeof(mbi));
  292. if (b)
  293. {
  294. if (mbi.State != PagesState)
  295. {
  296. PrintToLog("ERROR: WOW64BVT: Incorrect page protection set at address %p. State = %lx - %lx, RegionSize = %lx - %lx\n",
  297. Address, mbi.State, PagesState, mbi.RegionSize, ReleasedPages);
  298. b = FALSE;
  299. }
  300. }
  301. else
  302. {
  303. PrintToLog("ERROR: WOW64BVT: Failed to query virtual memory at address %p - %lx\n",
  304. Address, GetLastError());
  305. }
  306. return b;
  307. }
  308. BOOL ReleaseVerifyPages(PVOID BaseAllocation,
  309. PVOID *Address,
  310. SIZE_T *AllocationSize,
  311. DWORD AllocationType,
  312. DWORD DeAllocationType,
  313. DWORD ReleasedPages)
  314. {
  315. BOOL b;
  316. if (ReleasedPages > *AllocationSize)
  317. {
  318. ReleasedPages = *AllocationSize;
  319. }
  320. b = ReleasePages(*Address, DeAllocationType, ReleasedPages);
  321. if (b == FALSE)
  322. {
  323. PrintToLog("ERROR: WOW64BVT: Failed to release a page - %lx\n", GetLastError());
  324. return b;
  325. }
  326. b = VerifyPages(*Address,
  327. DeAllocationType,
  328. ReleasedPages);
  329. *AllocationSize -= ReleasedPages;
  330. *Address = (PVOID)((ULONG_PTR)*Address + ReleasedPages);
  331. if (b == FALSE)
  332. {
  333. PrintToLog("ERROR: WOW64BVT: Failed to verify pages at address %lx - %lx\n",
  334. ((ULONG_PTR)Address + ReleasedPages), GetLastError());
  335. }
  336. return b;
  337. }
  338. BOOL TestVadSplitOnFreeHelper(DWORD AllocationType,
  339. DWORD DeAllocationType,
  340. SIZE_T TotalAllocation)
  341. {
  342. BOOL b;
  343. PVOID Address;
  344. PVOID BaseAllocation;
  345. SIZE_T BaseAllocationSize;
  346. INT n;
  347. Address = VirtualAlloc(NULL,
  348. TotalAllocation,
  349. AllocationType,
  350. PAGE_READWRITE);
  351. if (Address == NULL)
  352. {
  353. PrintToLog("ERROR: WOW64BVT: Failed to allocate memory - %lx\n", GetLastError());
  354. }
  355. n = 1;
  356. BaseAllocation = Address;
  357. BaseAllocationSize = TotalAllocation;
  358. while (TotalAllocation != 0)
  359. {
  360. b = ReleaseVerifyPages(BaseAllocation,
  361. &Address,
  362. &TotalAllocation,
  363. AllocationType,
  364. DeAllocationType,
  365. PAGE_4K * n);
  366. if (b == FALSE)
  367. {
  368. PrintToLog("ERROR: WOW64BVT: ReleaseVerifyPages failed - %lx. %lx-%lx-%lx",
  369. GetLastError(), BaseAllocation, Address, TotalAllocation);
  370. break;
  371. }
  372. b = VerifyPages(BaseAllocation,
  373. DeAllocationType,
  374. n * PAGE_4K);
  375. if (b == FALSE)
  376. {
  377. PrintToLog("ERROR: WOW64BVT: Verify released pages from address %p with length = %lx failed\n", BaseAllocation, (n * PAGE_4K));
  378. break;
  379. }
  380. if (TotalAllocation > 0)
  381. {
  382. b = VerifyPages(Address,
  383. AllocationType,
  384. TotalAllocation);
  385. if (b == FALSE)
  386. {
  387. PrintToLog("ERROR: WOW64BVT: Verify pages from address %p with length = %lx failed\n", BaseAllocation, TotalAllocation);
  388. break;
  389. }
  390. }
  391. n += 2;
  392. }
  393. return b;
  394. }
  395. int TestVadSplitOnFree()
  396. {
  397. BOOL b;
  398. SIZE_T AllocationSize = (PAGE_4K * 10);
  399. PrintToLog("WOW64BVT: Testing VAD splitting...\n");
  400. b = TestVadSplitOnFreeHelper(MEM_COMMIT,
  401. MEM_DECOMMIT,
  402. AllocationSize);
  403. if (b)
  404. {
  405. b = TestVadSplitOnFreeHelper(MEM_COMMIT,
  406. MEM_RELEASE,
  407. AllocationSize);
  408. }
  409. if (b)
  410. {
  411. b = TestVadSplitOnFreeHelper(MEM_RESERVE,
  412. MEM_RELEASE,
  413. AllocationSize);
  414. }
  415. if (b != FALSE)
  416. {
  417. PrintToLog("WOW64BVT: Testing VAD splitting...OK\n");
  418. }
  419. else
  420. {
  421. PrintToLog("ERROR: WOW64BVT: Testing VAD splitting\n");
  422. }
  423. return (b == FALSE);
  424. }
  425. PVOID GetReadOnlyBuffer()
  426. {
  427. PVOID pReadOnlyBuffer = NULL;
  428. if (!pReadOnlyBuffer)
  429. {
  430. SYSTEM_INFO SystemInfo;
  431. // Get system info so that we know the page size
  432. GetSystemInfo(&SystemInfo);
  433. // Allocate a whole page. This is optimal.
  434. pReadOnlyBuffer = VirtualAlloc(NULL, SystemInfo.dwPageSize, MEM_COMMIT, PAGE_READWRITE);
  435. if (pReadOnlyBuffer)
  436. {
  437. // Fill it with know patern
  438. FillMemory(pReadOnlyBuffer, SystemInfo.dwPageSize, 0xA5);
  439. // Mark the page readonly
  440. pReadOnlyBuffer = VirtualAlloc(pReadOnlyBuffer, SystemInfo.dwPageSize, MEM_COMMIT, PAGE_READONLY);
  441. }
  442. }
  443. return pReadOnlyBuffer;
  444. }
  445. PVOID GetReadOnlyBuffer2()
  446. {
  447. PVOID pReadOnlyBuffer = NULL;
  448. DWORD OldP;
  449. SYSTEM_INFO SystemInfo;
  450. // Get system info so that we know the page size
  451. GetSystemInfo(&SystemInfo);
  452. // Allocate a whole page. This is optimal.
  453. pReadOnlyBuffer = VirtualAlloc(NULL, SystemInfo.dwPageSize, MEM_COMMIT, PAGE_READWRITE);
  454. if (pReadOnlyBuffer)
  455. {
  456. FillMemory(pReadOnlyBuffer, SystemInfo.dwPageSize, 0xA5);
  457. lstrcpy((PTSTR)pReadOnlyBuffer, TEXT("xxxxxxxxxxxxxxxxxxxx"));
  458. if (!VirtualProtect(pReadOnlyBuffer, SystemInfo.dwPageSize, PAGE_READONLY, &OldP))
  459. {
  460. PrintToLog("ERROR: WOW64BVT: VirtualProtect() failed inside GetReadOnlyBuffer2()\n");
  461. VirtualFree(pReadOnlyBuffer, 0, MEM_RELEASE);
  462. pReadOnlyBuffer = NULL;
  463. }
  464. }
  465. return pReadOnlyBuffer;
  466. }
  467. BOOL TestMmPageProtection()
  468. {
  469. PTSTR String;
  470. BOOL AV = FALSE;
  471. PrintToLog("WOW64BVT: Testing MM Page Protection...\n");
  472. String = (PTSTR) GetReadOnlyBuffer();
  473. if (!String) {
  474. PrintToLog("ERROR: WOW64BVT: GetReadOnlyBuffer() failed\n");
  475. return TRUE;
  476. }
  477. try {
  478. *String = TEXT('S');
  479. } except(EXCEPTION_EXECUTE_HANDLER) {
  480. AV = TRUE;
  481. }
  482. VirtualFree(String, 0, MEM_RELEASE);
  483. if (AV == TRUE) {
  484. AV = FALSE;
  485. String = (PTSTR) GetReadOnlyBuffer2();
  486. if (!String) {
  487. PrintToLog("ERROR: WOW64BVT: GetReadOnlyBuffer2() failed\n");
  488. return TRUE;
  489. }
  490. try {
  491. *String = TEXT('A');
  492. } except(EXCEPTION_EXECUTE_HANDLER) {
  493. AV = TRUE;
  494. }
  495. VirtualFree(String, 0, MEM_RELEASE);
  496. } else {
  497. PrintToLog("ERROR: WOW64BVT: GetReadOnlyBuffer() failed to make 4K pages read only\n");
  498. }
  499. if (AV == TRUE) {
  500. PrintToLog("WOW64BVT: Testing MM Page Protection...OK\n");
  501. } else {
  502. PrintToLog("ERROR: WOW64BVT: Testing MM Page Protection\n");
  503. }
  504. return (AV == FALSE);
  505. }
  506. #define STACK_BUFFER 0x300
  507. BOOL TestX86MisalignedLock()
  508. {
  509. BOOL bError = FALSE;
  510. PrintToLog("WOW64BVT: Testing X86 Lock on misaligned addresses...\n");
  511. __try
  512. {
  513. __asm
  514. {
  515. pushad;
  516. pushfd;
  517. sub esp, STACK_BUFFER;
  518. ;;
  519. ;; make eax unaliged with respect to an 8-byte cache line
  520. ;;
  521. mov eax, esp;
  522. add eax, 10h;
  523. mov ecx, 0xfffffff0;
  524. and eax, ecx;
  525. add eax, 7;
  526. mov ebx, eax;
  527. ;;
  528. ;; add
  529. ;;
  530. mov DWORD PTR [eax], 0x0300;
  531. lock add WORD PTR [eax], 0x0004;
  532. cmp DWORD PTR [eax], 0x0304;
  533. jnz $endwitherrornow;
  534. mov DWORD PTR [eax], 0x0300;
  535. lock add DWORD PTR [eax], 0x10000;
  536. cmp DWORD PTR [eax], 0x10300;
  537. jnz $endwitherrornow;
  538. mov ecx, DWORD PTR [eax+8];
  539. add ecx, 0x10;
  540. lock add DWORD PTR [eax+8], 0x10;
  541. cmp DWORD PTR [eax+8], ecx;
  542. jnz $endwitherrornow;
  543. mov ecx, DWORD PTR fs:[5];
  544. mov esi, 0x30000;
  545. lock add DWORD PTR fs:[5], esi;
  546. add esi, ecx;
  547. cmp DWORD PTR fs:[5], esi;
  548. mov DWORD PTR fs:[5], ecx;
  549. jnz $endwitherrornow;
  550. mov edi, 5;
  551. mov ecx, DWORD PTR fs:[edi];
  552. mov esi, 0x30000;
  553. lock add DWORD PTR fs:[edi], esi;
  554. add esi, ecx;
  555. cmp DWORD PTR fs:[edi], esi;
  556. mov DWORD PTR fs:[edi], ecx;
  557. jnz $endwitherrornow;
  558. mov esi, 0x40;
  559. mov WORD PTR [eax], 0x3000;
  560. lock add WORD PTR [eax], si;
  561. cmp WORD PTR [eax], 0x3040;
  562. jnz $endwitherrornow;
  563. mov edi, 0x40;
  564. mov DWORD PTR [eax], 0x3000;
  565. lock add DWORD PTR [eax], edi;
  566. cmp DWORD PTR [eax], 0x3040;
  567. jnz $endwitherrornow;
  568. ;;
  569. ;; adc
  570. ;;
  571. pushfd;
  572. pop ecx;
  573. or ecx, 1;
  574. push ecx;
  575. popfd;
  576. mov DWORD PTR [eax], 0x030000;
  577. lock adc DWORD PTR [eax], 0x40000;
  578. cmp DWORD PTR [eax], 0x70001;
  579. jnz $endwitherrornow;
  580. pushfd;
  581. pop ecx;
  582. and ecx, 0xfffffffe;
  583. push ecx;
  584. popfd;
  585. mov dx, 0x4000;
  586. mov WORD PTR [eax], 0x03000;
  587. lock adc WORD PTR [eax], dx;
  588. cmp WORD PTR [eax], 0x7000;
  589. jnz $endwitherrornow;
  590. pushfd;
  591. pop ecx;
  592. or ecx, 0x01;
  593. push ecx;
  594. popfd;
  595. mov WORD PTR [eax], 0x03000;
  596. lock adc WORD PTR [eax], 0x04000;
  597. cmp WORD PTR [eax], 0x7001;
  598. jnz $endwitherrornow;
  599. ;;
  600. ;; and
  601. ;;
  602. mov DWORD PTR [eax], 0xffffffff;
  603. lock and DWORD PTR [eax], 0xffff;
  604. cmp DWORD PTR [eax], 0xffff;
  605. jnz $endwitherrornow;
  606. mov DWORD PTR [eax], 0xffffffff;
  607. lock and DWORD PTR [eax], 0xff00ff00;
  608. cmp DWORD PTR [eax], 0xff00ff00;
  609. jnz $endwitherrornow;
  610. mov DWORD PTR [eax], 0xffffffff;
  611. mov esi, 0x00ff00ff
  612. lock and DWORD PTR [eax], esi;
  613. cmp DWORD PTR [eax], esi;
  614. jnz $endwitherrornow;
  615. mov ecx, 4;
  616. mov DWORD PTR [eax+ecx*2], 0xffffffff;
  617. mov esi, 0xffff00ff
  618. lock and DWORD PTR [eax+ecx*2], esi;
  619. cmp DWORD PTR [eax+ecx*2], 0xffff00ff;
  620. jnz $endwitherrornow;
  621. mov WORD PTR [eax], 0xffff;
  622. mov si, 0xff
  623. lock and WORD PTR [eax], si;
  624. cmp WORD PTR [eax], si;
  625. jnz $endwitherrornow;
  626. mov edi, DWORD PTR fs:[5];
  627. mov DWORD PTR fs:[5], 0xffffffff;
  628. mov ebx, 5;
  629. lock and DWORD PTR fs:[ebx], 0xff00ff00;
  630. cmp DWORD PTR fs:[ebx], 0xff00ff00;
  631. mov DWORD PTR fs:[ebx], edi;
  632. jnz $endwitherrornow;
  633. ;;
  634. ;; or
  635. ;;
  636. mov DWORD PTR [eax], 0x00;
  637. lock or DWORD PTR [eax], 0xffff;
  638. cmp DWORD PTR [eax], 0xffff;
  639. jnz $endwitherrornow;
  640. mov DWORD PTR [eax], 0xff00ff00;
  641. lock or DWORD PTR [eax], 0xff00ff;
  642. cmp DWORD PTR [eax], 0xffffffff;
  643. jnz $endwitherrornow;
  644. mov DWORD PTR [eax], 0xff000000;
  645. mov esi, 0x00ff00ff
  646. lock or DWORD PTR [eax], esi;
  647. cmp DWORD PTR [eax], 0xffff00ff;
  648. jnz $endwitherrornow;
  649. mov ecx, 4;
  650. mov DWORD PTR [eax+ecx*2], 0xff000000;
  651. mov esi, 0x00ff00ff
  652. lock or DWORD PTR [eax+ecx*2], esi;
  653. cmp DWORD PTR [eax+ecx*2], 0xffff00ff;
  654. jnz $endwitherrornow;
  655. mov WORD PTR [eax], 0xf000;
  656. mov si, 0xff
  657. lock or WORD PTR [eax], si;
  658. cmp WORD PTR [eax], 0xf0ff;
  659. jnz $endwitherrornow;
  660. mov edi, DWORD PTR fs:[5];
  661. mov DWORD PTR fs:[5], 0x00;
  662. mov ebx, 5;
  663. lock or DWORD PTR fs:[ebx], 0xff00ff00;
  664. cmp DWORD PTR fs:[ebx], 0xff00ff00;
  665. mov DWORD PTR fs:[ebx], edi;
  666. jnz $endwitherrornow;
  667. ;;
  668. ;; xor
  669. ;;
  670. mov DWORD PTR [eax], 0x00ffffff;
  671. lock xor DWORD PTR [eax], 0xffff;
  672. cmp DWORD PTR [eax], 0x00ff0000;
  673. jnz $endwitherrornow;
  674. mov DWORD PTR [eax], 0xff00ff00;
  675. lock xor DWORD PTR [eax], 0xff00ff;
  676. cmp DWORD PTR [eax], 0xffffffff;
  677. jnz $endwitherrornow;
  678. mov DWORD PTR [eax], 0xff0000ff;
  679. mov esi, 0x00ff00ff
  680. lock xor DWORD PTR [eax], esi;
  681. cmp DWORD PTR [eax], 0xffff0000;
  682. jnz $endwitherrornow;
  683. mov ecx, 4;
  684. mov DWORD PTR [eax+ecx*2], 0xff000000;
  685. mov esi, 0xffff00ff
  686. lock xor DWORD PTR [eax+ecx*2], esi;
  687. cmp DWORD PTR [eax+ecx*2], 0x00ff00ff;
  688. jnz $endwitherrornow;
  689. mov WORD PTR [eax], 0xf000;
  690. mov si, 0xf0ff
  691. lock xor WORD PTR [eax], si;
  692. cmp WORD PTR [eax], 0x00ff;
  693. jnz $endwitherrornow;
  694. mov edi, DWORD PTR fs:[5];
  695. mov DWORD PTR fs:[5], 0x0f;
  696. mov ebx, 5;
  697. lock xor DWORD PTR fs:[ebx], 0xff00000f;
  698. cmp DWORD PTR fs:[ebx], 0xff000000;
  699. mov DWORD PTR fs:[ebx], edi;
  700. jnz $endwitherrornow;
  701. ;;
  702. ;; inc & dec
  703. ;;
  704. mov DWORD PTR [eax], 0xffff;
  705. lock inc DWORD PTR [eax];
  706. cmp DWORD PTR [eax], 0x10000;
  707. jnz $endwitherrornow;
  708. lock inc WORD PTR [eax];
  709. cmp WORD PTR [eax], 0x0001;
  710. lock dec WORD PTR [eax];
  711. jnz $endwitherrornow;
  712. cmp WORD PTR [eax], 0x00;
  713. jnz $endwitherrornow;
  714. mov DWORD PTR [eax], 0;
  715. lock dec DWORD PTR [eax];
  716. cmp DWORD PTR [eax], 0xffffffff;
  717. jnz $endwitherrornow;
  718. ;;
  719. ;; not
  720. ;;
  721. mov DWORD PTR [eax], 0x10101010;
  722. lock not DWORD PTR [eax];
  723. cmp DWORD PTR [eax], 0xefefefef;
  724. jnz $endwitherrornow;
  725. mov DWORD PTR [eax+8], 0xffff0000;
  726. lock not DWORD PTR [eax+8];
  727. cmp DWORD PTR [eax+8], 0x0000ffff;
  728. jnz $endwitherrornow;
  729. mov ecx, 2;
  730. mov DWORD PTR [eax+ecx*4], 0xffffffff;
  731. lock not DWORD PTR [eax+ecx*4];
  732. cmp DWORD PTR [eax+ecx*4], 0x00000000;
  733. jnz $endwitherrornow;
  734. ;;
  735. ;; neg
  736. ;;
  737. mov DWORD PTR [eax], 0;
  738. lock neg DWORD PTR [eax];
  739. jc $endwitherrornow;
  740. cmp DWORD PTR [eax], 0;
  741. jnz $endwitherrornow;
  742. mov DWORD PTR [eax], 0xffffffff;
  743. lock neg DWORD PTR [eax];
  744. jnc $endwitherrornow;
  745. cmp DWORD PTR [eax], 0x01;
  746. jnz $endwitherrornow;
  747. mov WORD PTR [eax], 0xff;
  748. lock neg WORD PTR [eax];
  749. jnc $endwitherrornow;
  750. cmp WORD PTR [eax], 0xff01;
  751. jnz $endwitherrornow;
  752. ;;
  753. ;; bts
  754. ;;
  755. mov DWORD PTR [eax], 0x7ffffffe;
  756. lock bts DWORD PTR [eax], 0;
  757. jc $endwitherrornow;
  758. cmp DWORD PTR [eax], 0x7fffffff;
  759. jnz $endwitherrornow;
  760. mov ecx, eax;
  761. sub ecx, 4;
  762. mov edx, 63;
  763. lock bts DWORD PTR [ecx], edx;
  764. jc $endwitherrornow;
  765. cmp DWORD PTR [eax], 0xffffffff
  766. jnz $endwitherrornow;
  767. ;;
  768. ;; xchg
  769. ;;
  770. mov DWORD PTR [eax], 0xf0f0f0f0;
  771. mov edx, 0x11112222;
  772. lock xchg DWORD PTR [eax], edx;
  773. cmp DWORD PTR [eax], 0x11112222;
  774. jnz $endwitherrornow;
  775. cmp edx, 0xf0f0f0f0;
  776. jnz $endwitherrornow;
  777. xchg WORD PTR [eax], dx;
  778. cmp WORD PTR [eax], 0xf0f0;
  779. jnz $endwitherrornow;
  780. cmp dx, 0x2222;
  781. jnz $endwitherrornow;
  782. ;;
  783. ;; cmpxchg
  784. ;;
  785. mov ebx, eax;
  786. mov DWORD PTR [ebx], 0xf0f0f0f0;
  787. mov eax, 0x10101010;
  788. mov edx, 0x22332233;
  789. lock cmpxchg DWORD PTR [ebx], edx;
  790. jz $endwitherrornow;
  791. cmp eax, 0xf0f0f0f0;
  792. jnz $endwitherrornow;
  793. mov DWORD PTR [ebx], 0xf0f0f0f0;
  794. mov eax, 0xf0f0f0f0;
  795. mov edx, 0x12341234;
  796. lock cmpxchg DWORD PTR [ebx], edx;
  797. jnz $endwitherrornow;
  798. cmp DWORD PTR [ebx], 0x12341234;
  799. jnz $endwitherrornow;
  800. ;;
  801. ;; cmpxchg8b
  802. ;;
  803. mov DWORD PTR [ebx], 0x11223344;
  804. mov DWORD PTR [ebx+4], 0x55667788;
  805. mov edx, 0x12341234;
  806. mov eax, 0xff00ff00;
  807. lock cmpxchg8b [ebx];
  808. jz $endwitherrornow;
  809. cmp edx, 0x55667788;
  810. jnz $endwitherrornow;
  811. cmp eax, 0x11223344;
  812. jnz $endwitherrornow;
  813. mov esi, ebx;
  814. mov DWORD PTR [esi], 0x11223344;
  815. mov DWORD PTR [esi+4], 0x55667788;
  816. mov edx, 0x55667788;
  817. mov eax, 0x11223344;
  818. mov ecx, 0x10101010;
  819. mov ebx, 0x20202020;
  820. lock cmpxchg8b [esi];
  821. jnz $endwitherrornow;
  822. cmp DWORD PTR [esi], 0x20202020;
  823. jnz $endwitherrornow;
  824. cmp DWORD PTR [esi+4], 0x10101010;
  825. jnz $endwitherrornow;
  826. mov eax, esi;
  827. mov ebx, eax;
  828. ;;
  829. ;; sub
  830. ;;
  831. mov DWORD PTR [eax], 0x0300;
  832. lock sub WORD PTR [eax], 0x0004;
  833. cmp DWORD PTR [eax], 0x2fc;
  834. jnz $endwitherrornow;
  835. mov DWORD PTR [eax], 0x10000;
  836. lock sub DWORD PTR [eax], 0x0300;
  837. cmp DWORD PTR [eax], 0xfd00;
  838. jnz $endwitherrornow;
  839. mov ecx, DWORD PTR [eax+8];
  840. sub ecx, 0x10;
  841. lock sub DWORD PTR [eax+8], 0x10;
  842. cmp DWORD PTR [eax+8], ecx;
  843. jnz $endwitherrornow;
  844. mov ecx, DWORD PTR fs:[5];
  845. mov esi, 0x3000;
  846. lock sub DWORD PTR fs:[5], esi;
  847. mov edi, ecx;
  848. sub ecx, esi;
  849. cmp DWORD PTR fs:[5], ecx;
  850. mov DWORD PTR fs:[5], edi;
  851. jnz $endwitherrornow;
  852. mov edi, 5;
  853. mov ecx, DWORD PTR fs:[edi];
  854. mov esi, 0x30000;
  855. lock sub DWORD PTR fs:[edi], esi;
  856. mov edx, ecx;
  857. sub ecx, esi;
  858. cmp DWORD PTR fs:[edi], ecx;
  859. mov DWORD PTR fs:[edi], edx;
  860. jnz $endwitherrornow;
  861. mov si, 0x40;
  862. mov WORD PTR [eax], 0x3000;
  863. lock sub WORD PTR [eax], si;
  864. cmp WORD PTR [eax], 0x2fc0;
  865. jnz $endwitherrornow;
  866. mov edi, 0x40;
  867. mov DWORD PTR [eax], 0x3000;
  868. lock sub DWORD PTR [eax], edi;
  869. cmp DWORD PTR [eax], 0x2fc0;
  870. jnz $endwitherrornow;
  871. ;;
  872. ;; sbb
  873. ;;
  874. pushfd;
  875. pop ecx;
  876. or ecx, 1;
  877. push ecx;
  878. popfd;
  879. mov DWORD PTR [eax], 0x030000;
  880. lock sbb DWORD PTR [eax], 0x40000;
  881. cmp DWORD PTR [eax], 0xfffeffff;
  882. jnz $endwitherrornow;
  883. pushfd;
  884. pop ecx;
  885. and ecx, 0xfffffffe;
  886. push ecx;
  887. popfd;
  888. mov dx, 0x4000;
  889. mov WORD PTR [eax], 0x03000;
  890. lock sbb WORD PTR [eax], dx;
  891. cmp WORD PTR [eax], 0xf000;
  892. jnz $endwitherrornow;
  893. pushfd;
  894. pop ecx;
  895. or ecx, 0x01;
  896. push ecx;
  897. popfd;
  898. mov WORD PTR [eax], 0x03000;
  899. lock sbb WORD PTR [eax], 0x04000;
  900. cmp WORD PTR [eax], 0xefff;
  901. jnz $endwitherrornow;
  902. ;;
  903. ;; xadd
  904. ;;
  905. mov DWORD PTR [eax], 0x12345678;
  906. mov ecx, 0x1234;
  907. lock xadd DWORD PTR [eax], ecx;
  908. cmp ecx, 0x12345678;
  909. jnz $endwitherrornow;
  910. mov edx, 0x1234;
  911. add edx, 0x12345678;
  912. cmp DWORD PTR [eax], edx;
  913. jnz $endwitherrornow;
  914. mov WORD PTR [eax], 0x5678;
  915. mov cx, 0x1234;
  916. lock xadd WORD PTR [eax], cx;
  917. cmp cx, 0x5678;
  918. jnz $endwitherrornow;
  919. mov dx, 0x5678;
  920. add dx, 0x1234;
  921. cmp WORD PTR [eax], dx;
  922. jnz $endwitherrornow;
  923. ;;
  924. ;; Update caller with status
  925. ;;
  926. mov bError, 0
  927. jmp $endnow;
  928. $endwitherrornow:
  929. mov bError, 1
  930. $endnow:
  931. add esp, STACK_BUFFER;
  932. popfd;
  933. popad;
  934. }
  935. }
  936. __except (EXCEPTION_EXECUTE_HANDLER)
  937. {
  938. bError = TRUE;
  939. printf("ERROR: WOW64BVT: Exception %lx\n", GetExceptionCode());
  940. }
  941. if (bError == FALSE) {
  942. PrintToLog("WOW64BVT: Testing X86 Lock on misaligned addresses...OK\n");
  943. } else {
  944. PrintToLog("ERROR: WOW64BVT: Testing X86 Lock on misaligned addresses\n");
  945. }
  946. return bError;
  947. }
  948. //////////// All this code runs in the main test driver thread //////
  949. HANDLE CreateTheChildProcess(char *ProcessName, char *LogFileName)
  950. {
  951. char Buffer[512];
  952. HANDLE h;
  953. STARTUPINFOA si;
  954. PROCESS_INFORMATION pi;
  955. BOOL b;
  956. PrintToLog("WOW64BVT: Creating child process\n");
  957. strcpy(Buffer, ProcessName);
  958. strcat(Buffer, " childprocess");
  959. memset(&si, 0, sizeof(si));
  960. si.cb = sizeof(si);
  961. if (fpLogFile) {
  962. // If we're logging, then change the child process' stdout/stderr
  963. // to be the log file handle, so their output is captured to the file.
  964. HANDLE hLog = (HANDLE)_get_osfhandle(_fileno(fpLogFile));
  965. si.dwFlags = STARTF_USESTDHANDLES;
  966. si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
  967. si.hStdOutput = hLog;
  968. si.hStdError = hLog;
  969. }
  970. b = CreateProcessA(NULL, Buffer, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
  971. if (!b) {
  972. PrintToLog("ERROR: WOW64BVT: Error %d creating child process.\n", GetLastError());
  973. exit(1);
  974. }
  975. CloseHandle(pi.hThread);
  976. return pi.hProcess;
  977. }
  978. // This is called from within exit() in the main test driver process
  979. void __cdecl AtExitHandler(void)
  980. {
  981. time_t EndTime;
  982. struct tm *newtime;
  983. OSVERSIONINFOW vi;
  984. BOOL b;
  985. int year, hour;
  986. memset(&vi, 0, sizeof(vi));
  987. vi.dwOSVersionInfoSize = sizeof(vi);
  988. b = GetVersionExW(&vi);
  989. if (!b) {
  990. PrintToLog("\tWARNING: GetVersionExW failed, LastError = %d\n", GetLastError());
  991. vi.dwBuildNumber = 0;
  992. }
  993. // Close the logging bucket.
  994. PrintToLog(("[/TEST LOGGING OUTPUT]\n"));
  995. // Print the required data:
  996. PrintToLog("\tTEST: wow64bvt\n");
  997. PrintToLog("\tBUILD: %d\n", vi.dwBuildNumber);
  998. PrintToLog("\tMACHINE: \\\\%s\n", getenv("COMPUTERNAME"));
  999. PrintToLog("\tRESULT: %s\n", (g_bError) ? "FAIL" : "PASS");
  1000. PrintToLog("\tCONTACT: samera\n");
  1001. PrintToLog("\tMGR CONTACT: samera\n");
  1002. PrintToLog("\tDEV PRIME: samera\n");
  1003. PrintToLog("\tDEV ALT: askhalid\n");
  1004. PrintToLog("\tTEST PRIME: terryla\n");
  1005. PrintToLog("\tTEST ALT: terryla\n");
  1006. newtime = localtime(&TestStartTime);
  1007. year = (newtime->tm_year >= 100) ? newtime->tm_year-100 : newtime->tm_year;
  1008. if (newtime->tm_hour == 0) {
  1009. hour = 12;
  1010. } else if (newtime->tm_hour > 12) {
  1011. hour = newtime->tm_hour-12;
  1012. } else {
  1013. hour = newtime->tm_hour;
  1014. }
  1015. PrintToLog("\tSTART TIME: %d/%d/%2.2d %d:%2.2d:%2.2d %s\n", newtime->tm_mon+1,
  1016. newtime->tm_mday,
  1017. year,
  1018. hour,
  1019. newtime->tm_min,
  1020. newtime->tm_sec,
  1021. (newtime->tm_hour < 12) ? "AM" : "PM");
  1022. time(&EndTime);
  1023. newtime = localtime(&EndTime);
  1024. year = (newtime->tm_year >= 100) ? newtime->tm_year-100 : newtime->tm_year;
  1025. if (newtime->tm_hour == 0) {
  1026. hour = 12;
  1027. } else if (newtime->tm_hour > 12) {
  1028. hour = newtime->tm_hour-12;
  1029. } else {
  1030. hour = newtime->tm_hour;
  1031. }
  1032. PrintToLog("\tEND TIME: %d/%d/%2.2d %d:%2.2d:%2.2d %s\n", newtime->tm_mon+1,
  1033. newtime->tm_mday,
  1034. year,
  1035. hour,
  1036. newtime->tm_min,
  1037. newtime->tm_sec,
  1038. (newtime->tm_hour < 12) ? "AM" : "PM");
  1039. PrintToLog("[/TESTRESULT]\n");
  1040. }
  1041. //
  1042. // This is just used to print out failing exception cases
  1043. //
  1044. void __cdecl ExceptionWoops(HRESULT want, HRESULT got)
  1045. {
  1046. if (got == 0) {
  1047. PrintToLog("==> Exception Skipped. Wanted: 0x%08x, Got: 0x%08x\n", want, got);
  1048. }
  1049. else {
  1050. PrintToLog("==> Unexpected Exception. Wanted: 0x%08x, Got: 0x%08x\n", want, got);
  1051. }
  1052. }
  1053. #define EXCEPTION_LOOP 10000
  1054. // Among other things, this does some divife by zero's (as a test)
  1055. // so don't have the compiler stop things just because we're causing an error
  1056. #pragma warning(disable:4756)
  1057. #pragma warning(disable:4723)
  1058. //
  1059. // Do some exception checks
  1060. //
  1061. int __cdecl ExceptionCheck(void)
  1062. {
  1063. int failThis;
  1064. int sawException;
  1065. int i;
  1066. char *p = NULL;
  1067. HRESULT code;
  1068. PrintToLog("WOW64BVT: Testing Exception Handling\n");
  1069. // Assume success
  1070. failThis = FALSE;
  1071. // Test a privileged instruction
  1072. sawException = FALSE;
  1073. __try {
  1074. __asm {
  1075. hlt
  1076. }
  1077. code = 0;
  1078. }
  1079. __except((code = GetExceptionCode()), 1 ) {
  1080. if (code == STATUS_PRIVILEGED_INSTRUCTION) {
  1081. // PrintToLog("Saw privileged instruction\n");
  1082. }
  1083. else {
  1084. PrintToLog("ERROR: Cause a privileged instruction fault\n");
  1085. ExceptionWoops(STATUS_PRIVILEGED_INSTRUCTION, code);
  1086. failThis = TRUE;
  1087. }
  1088. sawException = TRUE;
  1089. }
  1090. if (!sawException) {
  1091. PrintToLog("ERROR: Cause a privileged instruction fault\n");
  1092. ExceptionWoops(STATUS_PRIVILEGED_INSTRUCTION, code);
  1093. failThis = TRUE;
  1094. }
  1095. // Test an illegal instruction
  1096. sawException = FALSE;
  1097. __try {
  1098. __asm {
  1099. __asm _emit 0xff
  1100. __asm _emit 0xff
  1101. __asm _emit 0xff
  1102. __asm _emit 0xff
  1103. }
  1104. code = 0;
  1105. }
  1106. __except((code = GetExceptionCode()), 1 ) {
  1107. if (code == STATUS_ILLEGAL_INSTRUCTION) {
  1108. // PrintToLog("Saw illegal instruction\n");
  1109. }
  1110. else {
  1111. PrintToLog("ERROR: Cause an illegal instruction fault\n");
  1112. ExceptionWoops(STATUS_ILLEGAL_INSTRUCTION, code);
  1113. failThis = TRUE;
  1114. }
  1115. sawException = TRUE;
  1116. }
  1117. if (!sawException) {
  1118. PrintToLog("ERROR: Cause an illegal instruction fault\n");
  1119. ExceptionWoops(STATUS_ILLEGAL_INSTRUCTION, code);
  1120. failThis = TRUE;
  1121. }
  1122. //
  1123. // Testing for an int 3 can be a problem for systems that
  1124. // are running checked builds. So, don't bother with this
  1125. // test. Perhaps in the future, the code can test for a checked
  1126. // build and do appropriate.
  1127. //
  1128. #if 0
  1129. // Test the result of an int 3
  1130. sawException = FALSE;
  1131. __try {
  1132. _asm {
  1133. int 3
  1134. }
  1135. code = 0;
  1136. }
  1137. __except((code = GetExceptionCode()), 1 ) {
  1138. if (code == STATUS_BREAKPOINT) {
  1139. // PrintToLog("Saw debugger breakpoint\n");
  1140. }
  1141. else {
  1142. PrintToLog("ERROR: Cause an int 3 debugger breakpoint\n");
  1143. ExceptionWoops(STATUS_BREAKPOINT, code);
  1144. failThis = TRUE;
  1145. }
  1146. sawException = TRUE;
  1147. }
  1148. if (!sawException) {
  1149. PrintToLog("ERROR: Cause an int 3 debugger breakpoint\n");
  1150. ExceptionWoops(STATUS_BREAKPOINT, code);
  1151. failThis = TRUE;
  1152. }
  1153. #endif
  1154. // Test the result of an illegal int XX instruction
  1155. sawException = FALSE;
  1156. __try {
  1157. _asm {
  1158. int 66
  1159. }
  1160. code = 0;
  1161. }
  1162. __except((code = GetExceptionCode()), 1 ) {
  1163. if (code == STATUS_ACCESS_VIOLATION) {
  1164. // PrintToLog("Saw access violation\n");
  1165. }
  1166. else {
  1167. PrintToLog("ERROR: Cause an int 66 unknown interrupt (Access violation)\n");
  1168. ExceptionWoops(STATUS_ACCESS_VIOLATION, code);
  1169. failThis = TRUE;
  1170. }
  1171. sawException = TRUE;
  1172. }
  1173. if (!sawException) {
  1174. PrintToLog("ERROR: Cause an int 66 unknown interrupt (Access violation)\n");
  1175. ExceptionWoops(STATUS_ACCESS_VIOLATION, code);
  1176. failThis = TRUE;
  1177. }
  1178. // Test the result of an int divide by zero
  1179. sawException = FALSE;
  1180. __try {
  1181. int i, j, k;
  1182. i = 0;
  1183. j = 4;
  1184. k = j / i;
  1185. code = 0;
  1186. }
  1187. __except((code = GetExceptionCode()), 1 ) {
  1188. if (code == STATUS_INTEGER_DIVIDE_BY_ZERO) {
  1189. // PrintToLog("Saw int divide by zero\n");
  1190. }
  1191. else {
  1192. PrintToLog("ERROR: Cause an integer divide by zero\n");
  1193. ExceptionWoops(STATUS_INTEGER_DIVIDE_BY_ZERO, code);
  1194. failThis = TRUE;
  1195. }
  1196. sawException = TRUE;
  1197. }
  1198. if (!sawException) {
  1199. PrintToLog("ERROR: Cause an integer divide by zero\n");
  1200. ExceptionWoops(STATUS_INTEGER_DIVIDE_BY_ZERO, code);
  1201. failThis = TRUE;
  1202. }
  1203. // Test the result of an fp divide by zero
  1204. // PrintToLog("Before div0: Control is 0x%0.4x, Status is 0x%0.4x\n", _control87(0,0), _status87());
  1205. sawException = FALSE;
  1206. __try {
  1207. double x, y;
  1208. y = 0.0;
  1209. x = 1.0 / y ;
  1210. // PrintToLog("x is %lf\n", x);
  1211. code = 0;
  1212. }
  1213. __except((code = GetExceptionCode()), 1 ) {
  1214. // Don't actually get a divide by zero error, get
  1215. // so we should never hit this exception!
  1216. PrintToLog("Try a floating divide by zero\n");
  1217. PrintToLog("Woops! Saw an exception when we shouldn't have!\n");
  1218. sawException = TRUE;
  1219. failThis = TRUE;
  1220. }
  1221. // So you would think you'd get a float divide by zero error... Nope,
  1222. // you get X set to infinity...
  1223. if (code != 0) {
  1224. PrintToLog("ERROR: Try a floating divide by zero\n");
  1225. ExceptionWoops(0, code);
  1226. failThis = TRUE;
  1227. }
  1228. // PrintToLog("After div0: Control is 0x%0.4x, Status is 0x%0.4x\n", _control87(0,0), _status87());
  1229. // Test an int overflow (which actually does not cause an exception)
  1230. sawException = FALSE;
  1231. __try {
  1232. __asm {
  1233. into
  1234. }
  1235. // PrintToLog("into doesn't fault\n");
  1236. code = 0;
  1237. }
  1238. __except((code = GetExceptionCode()), 1 ) {
  1239. if (code == STATUS_INTEGER_OVERFLOW) {
  1240. // PrintToLog("Saw integer overflow\n");
  1241. }
  1242. else {
  1243. PrintToLog("ERROR: Try an into overflow fault\n");
  1244. ExceptionWoops(STATUS_INTEGER_OVERFLOW, code);
  1245. failThis = TRUE;
  1246. }
  1247. sawException = TRUE;
  1248. }
  1249. // Looks like integer overflow is ok... Is this a CRT thing?
  1250. if (code != 0) {
  1251. PrintToLog("ERROR: Try an into overflow fault\n");
  1252. ExceptionWoops(0, code);
  1253. failThis = TRUE;
  1254. }
  1255. // Test an illegal access
  1256. sawException = FALSE;
  1257. __try {
  1258. *p = 1;
  1259. code = 0;
  1260. }
  1261. __except((code = GetExceptionCode()), 1 ) {
  1262. if (code == STATUS_ACCESS_VIOLATION) {
  1263. // PrintToLog("Saw access violation\n");
  1264. }
  1265. else {
  1266. PrintToLog("ERROR: Cause an access violation\n");
  1267. ExceptionWoops(STATUS_ACCESS_VIOLATION, code);
  1268. failThis = TRUE;
  1269. }
  1270. sawException = TRUE;
  1271. }
  1272. if (!sawException) {
  1273. PrintToLog("ERROR: Cause an access violation\n");
  1274. ExceptionWoops(STATUS_ACCESS_VIOLATION, code);
  1275. failThis = TRUE;
  1276. }
  1277. //
  1278. // Finally, try a lot of exceptions (a loop) and verify we don't overflow
  1279. // the stack
  1280. //
  1281. for (i = 0; i < EXCEPTION_LOOP; i++) {
  1282. // Test an illegal access
  1283. sawException = FALSE;
  1284. __try {
  1285. *p = 1;
  1286. code = 0;
  1287. }
  1288. __except((code = GetExceptionCode()), 1 ) {
  1289. if (code == STATUS_ACCESS_VIOLATION) {
  1290. // PrintToLog("Saw access violation\n");
  1291. }
  1292. else {
  1293. PrintToLog("ERROR: Cause an access violation\n");
  1294. ExceptionWoops(STATUS_ACCESS_VIOLATION, code);
  1295. failThis = TRUE;
  1296. break;
  1297. }
  1298. sawException = TRUE;
  1299. }
  1300. if (!sawException) {
  1301. PrintToLog("ERROR: Cause an access violation\n");
  1302. ExceptionWoops(STATUS_ACCESS_VIOLATION, code);
  1303. failThis = TRUE;
  1304. break;
  1305. }
  1306. }
  1307. return failThis;
  1308. }
  1309. // Ok, go back to normal warnings...
  1310. #pragma warning(default:4756)
  1311. #pragma warning(default:4723)
  1312. #if defined(__BUILDMACHINE__)
  1313. #if defined(__BUILDDATE__)
  1314. #define B2(x, y) "" #x "." #y
  1315. #define B1(x, y) B2(x, y)
  1316. #define BUILD_MACHINE_TAG B1(__BUILDMACHINE__, __BUILDDATE__)
  1317. #else
  1318. #define B2(x) "" #x
  1319. #define B1(x) B2(x)
  1320. #define BUILD_MACHINE_TAG B1(__BUILDMACHINE__)
  1321. #endif
  1322. #else
  1323. #define BUILD_MACHINE_TAG ""
  1324. #endif
  1325. int __cdecl main(int argc, char *argv[])
  1326. {
  1327. NTSTATUS st;
  1328. HANDLE HandleList[2];
  1329. BOOL b;
  1330. DWORD dwExitCode;
  1331. // Disable buffering of the standard output handle
  1332. setvbuf(stdout, NULL, _IONBF, 0);
  1333. // Do some minimal command-line checking
  1334. if (argc < 2 || argc > 3) {
  1335. PrintToLog("Usage: wow64bvt log_file_name\n\n");
  1336. return 1;
  1337. } else if (strcmp(argv[1], "childprocess") == 0) {
  1338. return BeAChildProcess();
  1339. }
  1340. // We're the main exe
  1341. // Record the start time
  1342. time(&TestStartTime);
  1343. // Open the log file
  1344. fpLogFile = fopen(argv[1], "w");
  1345. if (!fpLogFile) {
  1346. PrintToLog("wow64bvt: Error: unable to create the log file '%s'\n", argv[1]);
  1347. return 1;
  1348. }
  1349. // Disable buffering of the log file handle
  1350. setvbuf(fpLogFile, NULL, _IONBF, 0);
  1351. // Print the initial banner
  1352. PrintToLog("[TESTRESULT]\n");
  1353. PrintToLog("[TEST LOGGING OUTPUT]\n");
  1354. PrintToLog("%s built on %s at %s by %s\n", argv[0], __DATE__, __TIME__, BUILD_MACHINE_TAG);
  1355. // Register the atexit handler - it closes the logging output section
  1356. // and prints the success/fail information as the BVT test exits.
  1357. atexit(AtExitHandler);
  1358. ///////////////////////////// Test starts here //////////////////////////
  1359. // 32-bit child process creation from 32-bit parent. The parent instance
  1360. // (running now) tested 32-bit child from 64-bit parent
  1361. HandleList[0] = CreateTheChildProcess(argv[0], argv[1]);
  1362. // Create a thread do so some more work
  1363. HandleList[1] = CreateTheThread();
  1364. // Wait for everything to finish
  1365. WaitForMultipleObjects(sizeof(HandleList)/sizeof(HandleList[0]), HandleList, TRUE, INFINITE);
  1366. // Get the return code from the child process
  1367. b=GetExitCodeProcess(HandleList[0], &dwExitCode);
  1368. if (b) {
  1369. if (dwExitCode) {
  1370. // The child failed. We should fail too.
  1371. return (int)dwExitCode;
  1372. }
  1373. } else {
  1374. PrintToLog("ERROR: GetExitCodeProcess failed with LastError = %d\n", GetLastError());
  1375. return 1;
  1376. }
  1377. // Get the return code from the thread
  1378. b=GetExitCodeThread(HandleList[1], &dwExitCode);
  1379. if (b) {
  1380. if (dwExitCode) {
  1381. // The child failed. We should fail too.
  1382. return (int)dwExitCode;
  1383. }
  1384. } else {
  1385. PrintToLog("ERROR: GetExitCodeThread failed with LastError = %d\n", GetLastError());
  1386. return 1;
  1387. }
  1388. b = ExceptionCheck();
  1389. if (b) {
  1390. PrintToLog("ERROR: Exception Handling test.\n");
  1391. return 1;
  1392. }
  1393. b = TestGuardPages();
  1394. if (b) {
  1395. PrintToLog("ERROR: TestGuardPages().\n");
  1396. return 1;
  1397. }
  1398. b = TestMemoryMappedFiles();
  1399. if (b) {
  1400. PrintToLog("ERROR: TestMemoryMappedFiles().\n");
  1401. return 1;
  1402. }
  1403. b = TestVadSplitOnFree();
  1404. if (b) {
  1405. PrintToLog("ERROR: TestVadSplitOnFree()\n");
  1406. return 1;
  1407. }
  1408. b = TestMmPageProtection();
  1409. if (b) {
  1410. PrintToLog("ERROR: TestMmPageProtection()\n");
  1411. return 1;
  1412. }
  1413. b = TestX86MisalignedLock();
  1414. if (b) {
  1415. PrintToLog("ERROR: TestX86MisalignedLock()\n");
  1416. return 1;
  1417. }
  1418. // Everything finished OK. Clear the error flag and exit. The atexit
  1419. // callback function will finish filling out the log if this is the
  1420. // main thread.
  1421. g_bError = FALSE;
  1422. return 0;
  1423. }