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