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 #ifdef _M_AMD64 62 static ULONG64 randULONG64(void) 63 { 64 return (ULONG64)randULONG() << 32 | randULONG(); 65 } 66 #endif 67 68 void check(CONTEXT * pContext) 69 { 70 #ifdef _M_IX86 71 ok(pContext->ContextFlags == CONTEXT_FULL, 72 "ContextFlags=0x%lx\n", pContext->ContextFlags); 73 74 /* Random data segments */ 75 ok((pContext->SegGs & NTC_SEGMENT_BITS) == 76 (continueContext.SegGs & NTC_SEGMENT_BITS), 77 "SegGs=0x%lx / 0x%lx\n", pContext->SegGs, continueContext.SegGs); 78 79 ok((pContext->SegFs & NTC_SEGMENT_BITS) == 80 (continueContext.SegFs & NTC_SEGMENT_BITS), 81 "SegFs=0x%lx / 0x%lx\n", pContext->SegFs, continueContext.SegFs); 82 83 ok((pContext->SegEs & NTC_SEGMENT_BITS) == 84 (continueContext.SegEs & NTC_SEGMENT_BITS), 85 "SegEs=0x%lx / 0x%lx\n", pContext->SegEs, continueContext.SegEs); 86 87 ok((pContext->SegDs & NTC_SEGMENT_BITS) == 88 (continueContext.SegDs & NTC_SEGMENT_BITS), 89 "SegDs=0x%lx / 0x%lx\n", pContext->SegDs, continueContext.SegDs); 90 91 /* Integer registers */ 92 ok(pContext->Edi == continueContext.Edi, 93 "Edi: 0x%lx != 0x%lx\n", pContext->Edi, continueContext.Edi); 94 ok(pContext->Esi == continueContext.Esi, 95 "Esi: 0x%lx != 0x%lx\n", pContext->Esi, continueContext.Esi); 96 ok(pContext->Ebx == continueContext.Ebx, 97 "Ebx: 0x%lx != 0x%lx\n", pContext->Ebx, continueContext.Ebx); 98 ok(pContext->Edx == continueContext.Edx, 99 "Edx: 0x%lx != 0x%lx\n", pContext->Edx, continueContext.Edx); 100 ok(pContext->Ecx == continueContext.Ecx, 101 "Ecx: 0x%lx != 0x%lx\n", pContext->Ecx, continueContext.Ecx); 102 ok(pContext->Eax == continueContext.Eax, 103 "Eax: 0x%lx != 0x%lx\n", pContext->Eax, continueContext.Eax); 104 105 /* Control registers and segments */ 106 ok(pContext->Ebp == continueContext.Ebp, 107 "Ebp: 0x%lx != 0x%lx\n", pContext->Ebp, continueContext.Ebp); 108 ok(pContext->Eip == continueContext.Eip, 109 "Eip: 0x%lx != 0x%lx\n", pContext->Eip, continueContext.Eip); 110 ok(pContext->Esp == continueContext.Esp, 111 "Esp: 0x%lx != 0x%lx\n", pContext->Esp, continueContext.Esp); 112 113 ok((pContext->SegCs & NTC_SEGMENT_BITS) == 114 (continueContext.SegCs & NTC_SEGMENT_BITS), 115 "SegCs: 0x%lx != 0x%lx\n", pContext->SegCs, continueContext.SegCs); 116 117 ok((pContext->EFlags & NTC_EFLAGS_BITS) == 118 (continueContext.EFlags & NTC_EFLAGS_BITS), 119 "EFlags: 0x%lx != 0x%lx\n", pContext->EFlags, continueContext.EFlags); 120 121 ok((pContext->SegSs & NTC_SEGMENT_BITS) == 122 (continueContext.SegSs & NTC_SEGMENT_BITS), 123 "SegSs: 0x%lx != 0x%lx\n", pContext->SegSs, continueContext.SegSs); 124 #endif 125 126 /* Return where we came from */ 127 longjmp(jmpbuf, 1); 128 } 129 130 START_TEST(NtContinue) 131 { 132 #ifdef __RUNTIME_CHECKS__ 133 skip("This test breaks MSVC runtime checks!\n"); 134 return; 135 #endif /* __RUNTIME_CHECKS__ */ 136 initrand(); 137 138 /* First time */ 139 if(setjmp(jmpbuf) == 0) 140 { 141 CONTEXT bogus; 142 143 continueContext.ContextFlags = CONTEXT_FULL; 144 GetThreadContext(GetCurrentThread(), &continueContext); 145 146 #ifdef _M_IX86 147 continueContext.ContextFlags = CONTEXT_FULL; 148 149 /* Fill the integer registers with random values */ 150 continueContext.Edi = randULONG(); 151 continueContext.Esi = randULONG(); 152 continueContext.Ebx = randULONG(); 153 continueContext.Edx = randULONG(); 154 continueContext.Ecx = randULONG(); 155 continueContext.Eax = randULONG(); 156 continueContext.Ebp = randULONG(); 157 158 /* Randomize all the allowed flags (determined experimentally with WinDbg) */ 159 continueContext.EFlags = randULONG() & 0x3C0CD5; 160 161 /* Randomize the stack pointer as much as possible */ 162 continueContext.Esp = (ULONG)(((ULONG_PTR)&bogus) & 0xFFFFFFFF) + 163 sizeof(bogus) - (randULONG() & 0xF) * 4; 164 165 /* continuePoint() is implemented in assembler */ 166 continueContext.Eip = (ULONG)((ULONG_PTR)continuePoint & 0xFFFFFFF); 167 168 /* Can't do a lot about segments */ 169 #elif defined(_M_AMD64) 170 continueContext.ContextFlags = CONTEXT_FULL; 171 172 /* Fill the integer registers with random values */ 173 continueContext.Rdi = randULONG64(); 174 continueContext.Rsi = randULONG64(); 175 continueContext.Rbx = randULONG64(); 176 continueContext.Rdx = randULONG64(); 177 continueContext.Rcx = randULONG64(); 178 continueContext.Rax = randULONG64(); 179 continueContext.Rbp = randULONG64(); 180 181 /* Randomize all the allowed flags (determined experimentally with WinDbg) */ 182 continueContext.EFlags = randULONG64() & 0x3C0CD5; 183 184 /* Randomize the stack pointer as much as possible */ 185 continueContext.Rsp = (((ULONG_PTR)&bogus)) + 186 sizeof(bogus) - (randULONG() & 0xF) * 4; 187 188 /* continuePoint() is implemented in assembler */ 189 //continueContext.Rip = ((ULONG_PTR)continuePoint); 190 skip("NtContinue test does not yet work on x64."); 191 return; 192 #endif 193 194 NtContinue(&continueContext, FALSE); 195 ok(0, "should never get here\n"); 196 } 197 198 /* Second time */ 199 return; 200 } 201