1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPL - See COPYING in the top level directory 4 * PURPOSE: Test for NtContinue 5 * PROGRAMMER: 6 */ 7 8 #include "precomp.h" 9 10 #include <setjmp.h> 11 #include <time.h> 12 13 #ifdef _M_IX86 14 #define NTC_SEGMENT_BITS (0xFFFF) 15 #define NTC_EFLAGS_BITS (0x3C0CD5) 16 #endif 17 18 void continuePoint(void); 19 20 static jmp_buf jmpbuf; 21 static CONTEXT continueContext; 22 static unsigned int nRandBytes; 23 24 static int initrand(void) 25 { 26 unsigned int nRandMax; 27 unsigned int nRandMaxBits; 28 time_t tLoc; 29 30 nRandMax = RAND_MAX; 31 for(nRandMaxBits = 0; nRandMax != 0; nRandMax >>= 1, ++ nRandMaxBits); 32 nRandBytes = nRandMaxBits / CHAR_BIT; 33 //assert(nRandBytes != 0); 34 srand((unsigned)(time(&tLoc) & UINT_MAX)); 35 return 1; 36 } 37 38 static void randbytes(void * p, size_t n) 39 { 40 unsigned char * b; 41 size_t i; 42 int r = rand(); 43 44 b = (unsigned char *)p; 45 for(i = 0; i < n; ++ i) 46 { 47 if(i % nRandBytes == 0) 48 r = rand(); 49 b[i] = (unsigned char)(r & UCHAR_MAX); 50 r >>= CHAR_BIT; 51 } 52 } 53 54 static ULONG randULONG(void) 55 { 56 ULONG n; 57 randbytes(&n, sizeof(n)); 58 return n; 59 } 60 61 void check(CONTEXT * pContext) 62 { 63 #ifdef _M_IX86 64 ok(pContext->ContextFlags == CONTEXT_FULL, 65 "ContextFlags=0x%lx\n", pContext->ContextFlags); 66 67 /* Random data segments */ 68 ok((pContext->SegGs & NTC_SEGMENT_BITS) == 69 (continueContext.SegGs & NTC_SEGMENT_BITS), 70 "SegGs=0x%lx / 0x%lx\n", pContext->SegGs, continueContext.SegGs); 71 72 ok((pContext->SegFs & NTC_SEGMENT_BITS) == 73 (continueContext.SegFs & NTC_SEGMENT_BITS), 74 "SegFs=0x%lx / 0x%lx\n", pContext->SegFs, continueContext.SegFs); 75 76 ok((pContext->SegEs & NTC_SEGMENT_BITS) == 77 (continueContext.SegEs & NTC_SEGMENT_BITS), 78 "SegEs=0x%lx / 0x%lx\n", pContext->SegEs, continueContext.SegEs); 79 80 ok((pContext->SegDs & NTC_SEGMENT_BITS) == 81 (continueContext.SegDs & NTC_SEGMENT_BITS), 82 "SegDs=0x%lx / 0x%lx\n", pContext->SegDs, continueContext.SegDs); 83 84 /* Integer registers */ 85 ok(pContext->Edi == continueContext.Edi, 86 "Edi: 0x%lx != 0x%lx\n", pContext->Edi, continueContext.Edi); 87 ok(pContext->Esi == continueContext.Esi, 88 "Esi: 0x%lx != 0x%lx\n", pContext->Esi, continueContext.Esi); 89 ok(pContext->Ebx == continueContext.Ebx, 90 "Ebx: 0x%lx != 0x%lx\n", pContext->Ebx, continueContext.Ebx); 91 ok(pContext->Edx == continueContext.Edx, 92 "Edx: 0x%lx != 0x%lx\n", pContext->Edx, continueContext.Edx); 93 ok(pContext->Ecx == continueContext.Ecx, 94 "Ecx: 0x%lx != 0x%lx\n", pContext->Ecx, continueContext.Ecx); 95 ok(pContext->Eax == continueContext.Eax, 96 "Eax: 0x%lx != 0x%lx\n", pContext->Eax, continueContext.Eax); 97 98 /* Control registers and segments */ 99 ok(pContext->Ebp == continueContext.Ebp, 100 "Ebp: 0x%lx != 0x%lx\n", pContext->Ebp, continueContext.Ebp); 101 ok(pContext->Eip == continueContext.Eip, 102 "Eip: 0x%lx != 0x%lx\n", pContext->Eip, continueContext.Eip); 103 ok(pContext->Esp == continueContext.Esp, 104 "Esp: 0x%lx != 0x%lx\n", pContext->Esp, continueContext.Esp); 105 106 ok((pContext->SegCs & NTC_SEGMENT_BITS) == 107 (continueContext.SegCs & NTC_SEGMENT_BITS), 108 "SegCs: 0x%lx != 0x%lx\n", pContext->SegCs, continueContext.SegCs); 109 110 ok((pContext->EFlags & NTC_EFLAGS_BITS) == 111 (continueContext.EFlags & NTC_EFLAGS_BITS), 112 "EFlags: 0x%lx != 0x%lx\n", pContext->EFlags, continueContext.EFlags); 113 114 ok((pContext->SegSs & NTC_SEGMENT_BITS) == 115 (continueContext.SegSs & NTC_SEGMENT_BITS), 116 "SegSs: 0x%lx != 0x%lx\n", pContext->SegSs, continueContext.SegSs); 117 #endif 118 119 /* Return where we came from */ 120 longjmp(jmpbuf, 1); 121 } 122 123 START_TEST(NtContinue) 124 { 125 #ifdef __RUNTIME_CHECKS__ 126 skip("This test breaks MSVC runtime checks!\n"); 127 return; 128 #endif /* __RUNTIME_CHECKS__ */ 129 initrand(); 130 131 /* First time */ 132 if(setjmp(jmpbuf) == 0) 133 { 134 CONTEXT bogus; 135 136 continueContext.ContextFlags = CONTEXT_FULL; 137 GetThreadContext(GetCurrentThread(), &continueContext); 138 139 #ifdef _M_IX86 140 continueContext.ContextFlags = CONTEXT_FULL; 141 142 /* Fill the integer registers with random values */ 143 continueContext.Edi = randULONG(); 144 continueContext.Esi = randULONG(); 145 continueContext.Ebx = randULONG(); 146 continueContext.Edx = randULONG(); 147 continueContext.Ecx = randULONG(); 148 continueContext.Eax = randULONG(); 149 continueContext.Ebp = randULONG(); 150 151 /* Randomize all the allowed flags (determined experimentally with WinDbg) */ 152 continueContext.EFlags = randULONG() & 0x3C0CD5; 153 154 /* Randomize the stack pointer as much as possible */ 155 continueContext.Esp = (ULONG)(((ULONG_PTR)&bogus) & 0xFFFFFFFF) + 156 sizeof(bogus) - (randULONG() & 0xF) * 4; 157 158 /* continuePoint() is implemented in assembler */ 159 continueContext.Eip = (ULONG)((ULONG_PTR)continuePoint & 0xFFFFFFF); 160 161 /* Can't do a lot about segments */ 162 #endif 163 164 NtContinue(&continueContext, FALSE); 165 ok(0, "should never get here\n"); 166 } 167 168 /* Second time */ 169 return; 170 } 171