Leaked source code of windows server 2003
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.

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