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 _MSC_VER 14 #pragma runtime_checks("s", off) 15 #endif 16 17 #define ok_eq_print(value, expected, spec) ok((value) == (expected), #value " = " spec ", expected " spec "\n", value, expected) 18 #define ok_eq_hex(value, expected) ok_eq_print(value, expected, "%lx") 19 #define ok_eq_hex64(value, expected) ok_eq_print(value, expected, "%I64x") 20 #define ok_eq_xmm(value, expected) ok((value).Low == (expected).Low, #value " = %I64x'%08I64x, expected %I64x'%08I64x\n", (value).Low, (value).High, (expected).Low, (expected).High) 21 22 #ifdef _M_IX86 23 #define NTC_SEGMENT_BITS (0xFFFF) 24 #define NTC_EFLAGS_BITS (0x3C0CD5) 25 #endif 26 27 void continuePoint(void); 28 29 static jmp_buf jmpbuf; 30 static CONTEXT continueContext; 31 static unsigned int nRandBytes; 32 33 static int initrand(void) 34 { 35 unsigned int nRandMax; 36 unsigned int nRandMaxBits; 37 time_t tLoc; 38 39 nRandMax = RAND_MAX; 40 for(nRandMaxBits = 0; nRandMax != 0; nRandMax >>= 1, ++ nRandMaxBits); 41 nRandBytes = nRandMaxBits / CHAR_BIT; 42 //assert(nRandBytes != 0); 43 srand((unsigned)(time(&tLoc) & UINT_MAX)); 44 return 1; 45 } 46 47 static void randbytes(void * p, size_t n) 48 { 49 unsigned char * b; 50 size_t i; 51 int r = rand(); 52 53 b = (unsigned char *)p; 54 for(i = 0; i < n; ++ i) 55 { 56 if(i % nRandBytes == 0) 57 r = rand(); 58 b[i] = (unsigned char)(r & UCHAR_MAX); 59 r >>= CHAR_BIT; 60 } 61 } 62 63 static ULONG randULONG(void) 64 { 65 ULONG n; 66 randbytes(&n, sizeof(n)); 67 return n; 68 } 69 70 #ifdef _M_AMD64 71 static ULONG64 randULONG64(void) 72 { 73 return (ULONG64)randULONG() << 32 | randULONG(); 74 } 75 #endif 76 77 void check(CONTEXT * pContext) 78 { 79 #ifdef _M_IX86 80 ok(pContext->ContextFlags == CONTEXT_FULL, 81 "ContextFlags=0x%lx\n", pContext->ContextFlags); 82 83 /* Random data segments */ 84 ok((pContext->SegGs & NTC_SEGMENT_BITS) == 85 (continueContext.SegGs & NTC_SEGMENT_BITS), 86 "SegGs=0x%lx / 0x%lx\n", pContext->SegGs, continueContext.SegGs); 87 88 ok((pContext->SegFs & NTC_SEGMENT_BITS) == 89 (continueContext.SegFs & NTC_SEGMENT_BITS), 90 "SegFs=0x%lx / 0x%lx\n", pContext->SegFs, continueContext.SegFs); 91 92 ok((pContext->SegEs & NTC_SEGMENT_BITS) == 93 (continueContext.SegEs & NTC_SEGMENT_BITS), 94 "SegEs=0x%lx / 0x%lx\n", pContext->SegEs, continueContext.SegEs); 95 96 ok((pContext->SegDs & NTC_SEGMENT_BITS) == 97 (continueContext.SegDs & NTC_SEGMENT_BITS), 98 "SegDs=0x%lx / 0x%lx\n", pContext->SegDs, continueContext.SegDs); 99 100 /* Integer registers */ 101 ok(pContext->Edi == continueContext.Edi, 102 "Edi: 0x%lx != 0x%lx\n", pContext->Edi, continueContext.Edi); 103 ok(pContext->Esi == continueContext.Esi, 104 "Esi: 0x%lx != 0x%lx\n", pContext->Esi, continueContext.Esi); 105 ok(pContext->Ebx == continueContext.Ebx, 106 "Ebx: 0x%lx != 0x%lx\n", pContext->Ebx, continueContext.Ebx); 107 ok(pContext->Edx == continueContext.Edx, 108 "Edx: 0x%lx != 0x%lx\n", pContext->Edx, continueContext.Edx); 109 ok(pContext->Ecx == continueContext.Ecx, 110 "Ecx: 0x%lx != 0x%lx\n", pContext->Ecx, continueContext.Ecx); 111 ok(pContext->Eax == continueContext.Eax, 112 "Eax: 0x%lx != 0x%lx\n", pContext->Eax, continueContext.Eax); 113 114 /* Control registers and segments */ 115 ok(pContext->Ebp == continueContext.Ebp, 116 "Ebp: 0x%lx != 0x%lx\n", pContext->Ebp, continueContext.Ebp); 117 ok(pContext->Eip == continueContext.Eip, 118 "Eip: 0x%lx != 0x%lx\n", pContext->Eip, continueContext.Eip); 119 ok(pContext->Esp == continueContext.Esp, 120 "Esp: 0x%lx != 0x%lx\n", pContext->Esp, continueContext.Esp); 121 122 ok((pContext->SegCs & NTC_SEGMENT_BITS) == 123 (continueContext.SegCs & NTC_SEGMENT_BITS), 124 "SegCs: 0x%lx != 0x%lx\n", pContext->SegCs, continueContext.SegCs); 125 126 ok((pContext->EFlags & NTC_EFLAGS_BITS) == 127 (continueContext.EFlags & NTC_EFLAGS_BITS), 128 "EFlags: 0x%lx != 0x%lx\n", pContext->EFlags, continueContext.EFlags); 129 130 ok((pContext->SegSs & NTC_SEGMENT_BITS) == 131 (continueContext.SegSs & NTC_SEGMENT_BITS), 132 "SegSs: 0x%lx != 0x%lx\n", pContext->SegSs, continueContext.SegSs); 133 #else 134 ok_eq_hex64(pContext->ContextFlags, CONTEXT_FULL | CONTEXT_SEGMENTS); 135 ok_eq_hex(pContext->MxCsr, continueContext.MxCsr); 136 ok_eq_hex(pContext->SegCs, continueContext.SegCs); 137 ok_eq_hex(pContext->SegDs, 0x2B); 138 ok_eq_hex(pContext->SegEs, 0x2B); 139 ok_eq_hex(pContext->SegFs, 0x53); 140 ok_eq_hex(pContext->SegGs, 0x2B); 141 ok_eq_hex(pContext->SegSs, continueContext.SegSs); 142 ok_eq_hex(pContext->EFlags, (continueContext.EFlags & ~0x1C0000) | 0x202); 143 144 ok_eq_hex64(pContext->Rax, continueContext.Rax); 145 ok_eq_hex64(pContext->Rdx, continueContext.Rdx); 146 ok_eq_hex64(pContext->Rbx, continueContext.Rbx); 147 ok_eq_hex64(pContext->Rsp, continueContext.Rsp); 148 ok_eq_hex64(pContext->Rbp, continueContext.Rbp); 149 ok_eq_hex64(pContext->Rsi, continueContext.Rsi); 150 ok_eq_hex64(pContext->Rdi, continueContext.Rdi); 151 ok_eq_hex64(pContext->R8, continueContext.R8); 152 ok_eq_hex64(pContext->R9, continueContext.R9); 153 ok_eq_hex64(pContext->R10, continueContext.R10); 154 ok_eq_hex64(pContext->R11, continueContext.R11); 155 ok_eq_hex64(pContext->R12, continueContext.R12); 156 ok_eq_hex64(pContext->R13, continueContext.R13); 157 ok_eq_hex64(pContext->R14, continueContext.R14); 158 ok_eq_hex64(pContext->R15, continueContext.R15); 159 ok_eq_xmm(pContext->Xmm0, continueContext.Xmm0); 160 ok_eq_xmm(pContext->Xmm1, continueContext.Xmm1); 161 ok_eq_xmm(pContext->Xmm2, continueContext.Xmm2); 162 ok_eq_xmm(pContext->Xmm3, continueContext.Xmm3); 163 ok_eq_xmm(pContext->Xmm4, continueContext.Xmm4); 164 ok_eq_xmm(pContext->Xmm5, continueContext.Xmm5); 165 ok_eq_xmm(pContext->Xmm6, continueContext.Xmm6); 166 ok_eq_xmm(pContext->Xmm7, continueContext.Xmm7); 167 ok_eq_xmm(pContext->Xmm8, continueContext.Xmm8); 168 ok_eq_xmm(pContext->Xmm9, continueContext.Xmm9); 169 ok_eq_xmm(pContext->Xmm10, continueContext.Xmm10); 170 ok_eq_xmm(pContext->Xmm11, continueContext.Xmm11); 171 ok_eq_xmm(pContext->Xmm12, continueContext.Xmm12); 172 ok_eq_xmm(pContext->Xmm13, continueContext.Xmm13); 173 ok_eq_xmm(pContext->Xmm14, continueContext.Xmm14); 174 ok_eq_xmm(pContext->Xmm15, continueContext.Xmm15); 175 176 // Clear the frame register to prevent unwinding, which is broken 177 ((_JUMP_BUFFER*)&jmpbuf)->Frame = 0; 178 #endif 179 180 /* Return where we came from */ 181 longjmp(jmpbuf, 1); 182 } 183 184 START_TEST(NtContinue) 185 { 186 initrand(); 187 188 RtlFillMemory(&continueContext, sizeof(continueContext), 0xBBBBBBBB); 189 190 /* First time */ 191 if(setjmp(jmpbuf) == 0) 192 { 193 CONTEXT bogus[2]; 194 195 RtlFillMemory(&bogus, sizeof(bogus), 0xCCCCCCCC); 196 197 continueContext.ContextFlags = CONTEXT_FULL; 198 GetThreadContext(GetCurrentThread(), &continueContext); 199 200 #ifdef _M_IX86 201 continueContext.ContextFlags = CONTEXT_FULL; 202 203 /* Fill the integer registers with random values */ 204 continueContext.Edi = randULONG(); 205 continueContext.Esi = randULONG(); 206 continueContext.Ebx = randULONG(); 207 continueContext.Edx = randULONG(); 208 continueContext.Ecx = randULONG(); 209 continueContext.Eax = randULONG(); 210 continueContext.Ebp = randULONG(); 211 212 /* Randomize all the allowed flags (determined experimentally with WinDbg) */ 213 continueContext.EFlags = randULONG() & 0x3C0CD5; 214 215 /* Randomize the stack pointer as much as possible */ 216 continueContext.Esp = (ULONG)(((ULONG_PTR)&bogus) & 0xFFFFFFFF) + 217 sizeof(bogus) - (randULONG() & 0xF) * 4; 218 219 /* continuePoint() is implemented in assembler */ 220 continueContext.Eip = (ULONG)((ULONG_PTR)continuePoint & 0xFFFFFFF); 221 222 /* Can't do a lot about segments */ 223 #elif defined(_M_AMD64) 224 continueContext.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; 225 226 /* Fill the integer registers with random values */ 227 PULONG64 Registers = &continueContext.Rax; 228 for (ULONG i = 0; i < 16; i++) 229 { 230 Registers[i] = randULONG64(); 231 } 232 233 /* Fill the XMM registers with random values */ 234 Registers = (PULONG64)&continueContext.Xmm0; 235 for (ULONG i = 0; i < 32; i++) 236 { 237 Registers[i] = randULONG64(); 238 } 239 240 continueContext.Dr0 = randULONG64() & 0xFFFF; 241 continueContext.Dr1 = randULONG64() & 0xFFFF; 242 continueContext.Dr2 = randULONG64() & 0xFFFF; 243 continueContext.Dr3 = randULONG64() & 0xFFFF; 244 continueContext.Dr6 = randULONG64() & 0xFFFF; 245 continueContext.Dr7 = randULONG64() & 0xFFFF; 246 247 /* Randomize all the allowed flags (determined experimentally with WinDbg) */ 248 continueContext.EFlags = randULONG64() & 0x3C0CD5; 249 250 /* Randomize the stack pointer as much as possible */ 251 continueContext.Rsp = (((ULONG_PTR)&bogus)) + (randULONG() & 0xF) * 16; 252 continueContext.Rsp = ALIGN_DOWN_BY(continueContext.Rsp, 16); 253 254 /* continuePoint() is implemented in assembler */ 255 continueContext.Rip = ((ULONG_PTR)continuePoint); 256 #endif 257 258 NtContinue(&continueContext, FALSE); 259 ok(0, "should never get here\n"); 260 } 261 262 /* Second time */ 263 return; 264 } 265